高德地图获取经纬度
高德官方地址
/*** @author 周坤* @date Create in 10:51 2022/4/18* 高德地理位置信息* 地理/逆地理编码 :https://lbs.amap.com/api/webservice/guide/api/georegeo* 地理编码:将详细的结构化地址转换为高德经纬度坐标。且支持对地标性名胜景区、建筑物名称解析为高德经纬度坐标。* 逆地理编码:将经纬度转换为详细结构化的地址,且返回附近周边的POI、AOI信息。*/
@Slf4j
public class GeoLocation {// 高德秘钥private static final String APP_CODE_GAODE = "44aa4b2a7772504960b691cfb9802";/*** 地理编码* 根据地址获取经纬度,调用量上限:300000** @param address 填写结构化地址信息:省份+城市+区县+城镇+乡村+街道+门牌号码 例[北京市朝阳区阜通东大街6号]* @param city 市,可选 例如[北京]* @return java.lang.String*/public static String GetLocationByAddress(String address, String city) {log.info("地理编码:address=" + address + ",currentCity=" + city);try {HashMap<String, Object> parameters = new HashMap<>(3);parameters.put("address", address);parameters.put("city", city);parameters.put("key", APP_CODE_GAODE);// 高德获取地理信息String response = HttpUtil.get("https://restapi.amap.com/v3/geocode/geo", parameters);JSONObject responseJson = JSONUtil.parseObj(response);String status = responseJson.get("status").toString();if (!"1".equals(status)) {log.error("列表信息获取失败,关键字:" + address + "城市:" + city);return null;}JSONArray geocodes = responseJson.getJSONArray("geocodes");return JSONUtil.parseObj(geocodes.get(0)).get("location").toString();} catch (Exception ex) {log.error("调用接口失败!" + ex.getMessage());return null;}}/*** 逆地理编码* 根据经纬度获取地址,调用量上限:300000** @param location 经纬度:经度在前,纬度在后,经纬度间以“,”分割* @return java.lang.String*/public static String GetAddressByLocation(String location) {log.info("逆地理编码:location=" + location);try {HashMap<String, Object> parameters = new HashMap(16);parameters.put("location", location);parameters.put("key", APP_CODE_GAODE);// 高德获取地理信息String response = HttpUtil.get("https://restapi.amap.com/v3/geocode/regeo", parameters);JSONObject responseJson = JSONUtil.parseObj(response);String status = responseJson.get("status").toString();if (!"1".equals(status)) {log.error("列表信息获取失败,经纬度:" + location);return null;}JSONObject regeocode = responseJson.getJSONObject("regeocode");return regeocode.get("formatted_address").toString();} catch (Exception ex) {log.error("调用接口失败!" + ex.getMessage());return null;}}}
根据经纬度进行距离测算
/*** @author 周坤* @date Create in 11:44 2022/4/18*/
@Slf4j
public class DistanceUtils {/*** 地球半径,单位 km*/private static final double EARTH_RADIUS = 6378.137;/*** 基于余弦定理求两经纬度距离* Math.pow(x,y) //这个函数是求x的y次方* Math.toRadians //将一个角度测量的角度转换成以弧度表示的近似角度* Math.sin //正弦函数* Math.cos //余弦函数* Math.sqrt //求平方根函数* Math.asin //反正弦函数*/public static double getDistanceStr(String lng1, String lat1, String lng2, String lat2) {return getDistance(new Double(lng1), new Double(lat1), new Double(lng2), new Double(lat2));}/*** 根据经纬度计算两点间的距离* 基于余弦定理求两经纬度距离** @param longitude1 第一个点的经度* @param latitude1 第一个点的纬度* @param longitude2 第二个点的经度* @param latitude2 第二个点的纬度* @return 返回距离 单位千米*/public static double getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {log.info("经纬度距离:longitude1=" + longitude1 + ",latitude1=" + latitude1 + ",longitude2=" + longitude2 + ",latitude2=" + latitude2);// 纬度double lat1 = Math.toRadians(latitude1);double lat2 = Math.toRadians(latitude2);// 经度double lng1 = Math.toRadians(longitude1);double lng2 = Math.toRadians(longitude2);// 纬度之差double a = lat1 - lat2;// 经度之差double b = lng1 - lng2;// 计算两点距离的公式double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));// 弧长乘地球半径, 返回单位: 千米s = s * EARTH_RADIUS;return s;}/*** 根据经纬度,计算两点间的距离* 由于三角函数中特定的关联关系,Haversine公式的最终实现方式可以有多种,比如借助转角度的函数atan2:** @param longitude1 第一个点的经度* @param latitude1 第一个点的纬度* @param longitude2 第二个点的经度* @param latitude2 第二个点的纬度* @return double*/public static double getDistance2(double longitude1, double latitude1,double longitude2, double latitude2) {double latDistance = Math.toRadians(longitude1 - longitude2);double lngDistance = Math.toRadians(latitude1 - latitude2);double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)+ Math.cos(Math.toRadians(longitude1)) * Math.cos(Math.toRadians(longitude2))* Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));return c * EARTH_RADIUS;}
}
工具类
/*** @author 周坤* @date Create in 11:45 2022/4/18*/
@Slf4j
public class GeoDistance {/*** 根据位置计算距离** @param origin 出发点,市区与详细地址中间用逗号拼接,例如:南京市,仙林中心* @param destination 目的地,与出发点相同* @return double*/public static double getDistance(String origin, String destination) {if (StringUtils.isEmpty(origin) || StringUtils.isEmpty(destination)) {log.info("出发点或者目的地为空!");return 0;}String[] originList = origin.split(",");String[] destinationList = destination.split(",");// 获取经纬度String originLocation = GeoLocation.GetLocationByAddress(originList[1], originList[0]);String destinationLocation = GeoLocation.GetLocationByAddress(destinationList[1], destinationList[0]);// 根据经纬度计算距离double distance = DistanceUtils.getDistanceStr(originLocation.split(",")[0], originLocation.split(",")[1], destinationLocation.split(",")[0], destinationLocation.split(",")[1]);BigDecimal bg = BigDecimal.valueOf(distance);double f1 = bg.setScale(2, RoundingMode.HALF_UP).doubleValue();log.info("两地距离: " + f1 + "KM");return distance;}}
测试
@Testpublic void test1() {String s = GeoLocation.GetLocationByAddress("陕西省西安市雁塔区", "西安");String s1 = GeoLocation.GetLocationByAddress("广东省深圳市光明区", "深圳");assert s != null;String[] split = s.split(",");assert s1 != null;String[] split1 = s1.split(",");Console.log(s);Console.log(s1);double distance = GeoDistance.getDistance("西安,陕西省西安市雁塔区东八里村新村一巷", "深圳,广东省深圳市光明区");Console.log(distance);}