返回,离当前用户定位最近的点位坐标(数据库存储点位经纬度)

文章介绍了如何使用Java实现一个方法,根据用户提供的经纬度,从数据库获取的配送中心列表中找到距离最近的配送中心ID。计算距离的部分采用了经纬度转换和Haversine公式。
@Override
public Integer getDistributionCenter(LongitudeAndLatitudeRequest request) {
	double userLatitude = Double.parseDouble(request.getLat());
	double userLongitude  = Double.parseDouble(request.getLng());

	// 配送中心Id;配送中心经纬度
	HashMap<Integer, CoordinateUtil.Coordinate> hashMap = new HashMap<>();

	//配送中心筛选条件待优化
	R<List<DistributionCenter>> dcList = remoteDistributionCenterService.getDcList();
	List<DistributionCenter> data = dcList.getData();

	for (DistributionCenter datum : data) {
		Integer dcId = datum.getId();
		String lat = datum.getLat();
		String lng = datum.getLng();
		hashMap.put(dcId,new CoordinateUtil.Coordinate(Double.parseDouble(lng),Double.parseDouble(lat)));
	}
	Iterator<Map.Entry<Integer, CoordinateUtil.Coordinate>> iterator = hashMap.entrySet().iterator();

	double minDistance = Double.MAX_VALUE;
	int minIndex = -1;
	while (iterator.hasNext()){
		Map.Entry<Integer, CoordinateUtil.Coordinate> entry = iterator.next();
		double distance = calculateDistance(userLatitude, userLongitude, entry.getValue().getLat(), entry.getValue().getLng());
		if (distance < minDistance) {
			minDistance = distance;
			minIndex = entry.getKey();
		}
	}
	return minIndex;
}

//计算2个经纬度之前的距离
public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
	double radLat1 = Math.toRadians(lat1);
	double radLat2 = Math.toRadians(lat2);
	double radLon1 = Math.toRadians(lon1);
	double radLon2 = Math.toRadians(lon2);

	double latDiff = radLat1 - radLat2;
	double lonDiff = radLon1 - radLon2;

	double a = Math.pow(Math.sin(latDiff / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(lonDiff / 2), 2);
	double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

	return 6371 * c; // 地球平均半径,单位:公里
}
使用经纬度点位坐标生成缓冲区是地理空间分析中常见的操作,通常用于创建围绕某个点的一定半径范围的区域(如500米、1公里等)。在 Python 中,可以使用 `geopy` 和 `shapely` 两个库配合完成这一任务: - `geopy`:用于地理距离计算,支持 `geodesic.destination()` 方法,可以从一个点沿某个方向移动一定距离得到新点。 - `shapely`:用于构建几何对象,如多边形。 --- ## ✅ 示例:使用经纬度点生成圆形缓冲区 ### 📦 所需依赖库: ```bash pip install geopy shapely ``` --- ### ✅ 示例代码: ```python from geopy.distance import geodesic from shapely.geometry import Polygon def create_geographic_buffer(lat, lon, radius_meters, num_points=36): """ 根据经纬度坐标点生成一个指定半径的圆形缓冲区。 :param lat: 纬度 :param lon: 经度 :param radius_meters: 缓冲区半径(单:米) :param num_points: 用于近似圆的点数,默认为36 :return: Shapely 的 Polygon 对象 """ points = [] for i in range(num_points): bearing = 360 * i / num_points # 方角,从0到360度 distance = geodesic(meters=radius_meters) dest = distance.destination(point=(lat, lon), bearing=bearing) points.append((dest.longitude, dest.latitude)) # 注意:shapely 使用 lon, lat # 创建多边形 polygon = Polygon(points) return polygon ``` --- ### ✅ 示例调用: ```python # 北京市的经纬度 lat, lon = 39.9042, 116.4074 radius_meters = 1000 # 半径1000米 buffer_polygon = create_geographic_buffer(lat, lon, radius_meters) print("缓冲区多边形 WKT 表示:") print(buffer_polygon.wkt) ``` --- ## 📌 说明: - `geodesic(meters=radius_meters)`:创建一个表示指定距离的地理距离对象。 - `destination(point, bearing)`:从给定点出发,按指定方向走指定距离,得到新的点。 - `shapely.geometry.Polygon(points)`:将一圈点连成多边形,表示缓冲区。 - `wkt`:是 Well-Known Text 格式,用于表示几何对象。 --- ## ✅ 保存为 GeoJSON 或 Shapefile(可选) 你可以使用 `geopandas` 将 `shapely` 的几何对象保存为 GeoJSON 或 Shapefile: ```python import geopandas as gpd from shapely.geometry import mapping # 创建 GeoDataFrame gdf = gpd.GeoDataFrame([{'geometry': buffer_polygon}], crs="EPSG:4326") # 保存为 GeoJSON gdf.to_file("buffer.geojson", driver="GeoJSON") # 保存为 Shapefile gdf.to_file("buffer.shp") ``` --- ## ⚠️ 注意事项: 1. **坐标顺序**:Python 中 `shapely` 使用 `(lon, lat)`,而 `geopy` 返回 `(lat, lon)`,要注意顺序转换。 2. **投影问题**:上述方法生成的是地理坐标系(WGS84),若要精确面积计算或缓冲区,建议使用投影坐标系(如 UTM)。 3. **缓冲区精度**:`num_points` 越大,缓冲区越接近圆形,但计算量也越大。 --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值