| | |
| | | package com.xiaopeng.map.utils; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.fasterxml.jackson.databind.JsonNode; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.xiaopeng.api.dto.operation.LonLatDto; |
| | | import com.xiaopeng.api.vo.map.PointByIpVo; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.utils.HttpUtils; |
| | | import com.xiaopeng.map.constant.I18nKeyConstant; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.OkHttpClient; |
| | | import okhttp3.Request; |
| | | import okhttp3.Response; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.TimeUnit; |
| | |
| | | // 高德地图Web服务API配置 |
| | | private static final String AMAP_API_BASE_URL = "https://restapi.amap.com/v3/direction/walking"; |
| | | private static final String AMAP_GEOCODING_URL = "https://restapi.amap.com/v3/geocode/geo"; |
| | | // 高德API基础URL |
| | | private static final String IP_API_URL = "https://restapi.amap.com/v3/ip"; |
| | | private static final String GEOCODE_API_URL = "https://restapi.amap.com/v3/geocode/geo"; |
| | | |
| | | // 你的高德地图API Key(请替换成你自己的) |
| | | private final String apiKey; |
| | | |
| | | // HTTP客户端 |
| | | private final OkHttpClient httpClient; |
| | | private final ObjectMapper objectMapper; |
| | | |
| | | |
| | | // @Value("${map.apikey}") |
| | | private static String apiKey="66ae577f63898dae3016d599fda57221"; |
| | | |
| | | /** |
| | | * 构造函数 |
| | | * @param apiKey 高德地图API Key |
| | | * IP定位 |
| | | */ |
| | | public static PointByIpVo ipLocation(String ip) throws IOException { |
| | | PointByIpVo pointByIpVo = new PointByIpVo(); |
| | | StringBuilder urlBuilder = new StringBuilder(IP_API_URL) |
| | | .append("?key=").append(apiKey) |
| | | .append("&output=json"); |
| | | |
| | | if (ip != null && !ip.trim().isEmpty()) { |
| | | urlBuilder.append("&ip=").append(ip); |
| | | } |
| | | |
| | | String response = HttpUtils.sendGet(urlBuilder.toString()); |
| | | JSONObject jsonObject = JSONObject.parseObject(response); |
| | | |
| | | // 城市名称 |
| | | String city = jsonObject.getString("city"); |
| | | String province = jsonObject.getString("province"); |
| | | if(("局域网").equals(province)){ |
| | | pointByIpVo.setCity("成都市"); |
| | | LonLatDto lonLatDto = new LonLatDto(104.07, 30.660); |
| | | pointByIpVo.setPoint(lonLatDto); |
| | | pointByIpVo.setAdcode("510100"); |
| | | return pointByIpVo; |
| | | } |
| | | String adcode = jsonObject.getString("adcode"); |
| | | if (city == null || city.trim().isEmpty() || "[]".equals(city)) { |
| | | // 直辖市:adcode前两位是11,12,31,50 |
| | | if (adcode != null) { |
| | | String prefix = adcode.substring(0, 2); |
| | | if ("11".equals(prefix)) { |
| | | city = "北京市"; |
| | | } |
| | | if ("12".equals(prefix)) { |
| | | city = "天津市"; |
| | | } |
| | | if ("31".equals(prefix)) { |
| | | city = "上海市"; |
| | | } |
| | | if ("50".equals(prefix)) { |
| | | city = "重庆市"; |
| | | } |
| | | // 如果没有city但有province,使用省份 |
| | | city = province; |
| | | } |
| | | } |
| | | |
| | | LonLatDto lonLatDto = geocodeCity(city); |
| | | pointByIpVo.setCity(city); |
| | | pointByIpVo.setPoint(lonLatDto); |
| | | pointByIpVo.setAdcode(adcode); |
| | | return pointByIpVo; |
| | | |
| | | } |
| | | |
| | | private static LonLatDto geocodeCity(String cityName) throws IOException { |
| | | String url = GEOCODE_API_URL + "?key=" +apiKey + "&address=" + cityName + "&output=json&city=" + cityName; |
| | | String response = HttpUtils.sendGet(url); |
| | | System.out.println(response); |
| | | JSONObject jsonObject = JSONObject.parseObject(response); |
| | | // 获取geocodes数组 |
| | | JSONArray geocodes = jsonObject.getJSONArray("geocodes"); |
| | | if (geocodes == null || geocodes.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // 取第一个geocode |
| | | JSONObject firstGeocode = geocodes.getJSONObject(0); |
| | | |
| | | // 获取location字段 |
| | | String lonLat = firstGeocode.getString("location"); |
| | | String[] lonLatArray = lonLat.split(","); |
| | | double longitude = Double.parseDouble(lonLatArray[0]); |
| | | double latitude = Double.parseDouble(lonLatArray[1]); |
| | | return new LonLatDto(longitude, latitude); |
| | | |
| | | } |
| | | public static void main (String[]args) throws IOException { |
| | | geocodeCity("凉山彝族自治州"); |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 构造函数 |
| | | * @param apiKey 高德地图API Key |
| | | */ |
| | | public AmapWalkingRouteUtil(String apiKey) { |
| | | this.apiKey = apiKey; |
| | | this.httpClient = new OkHttpClient.Builder() |
| | | .connectTimeout(10, TimeUnit.SECONDS) |
| | | .readTimeout(10, TimeUnit.SECONDS) |
| | | .writeTimeout(10, TimeUnit.SECONDS) |
| | | .build(); |
| | | this.objectMapper = new ObjectMapper(); |
| | | } |
| | | |
| | | /** |
| | | * 位置坐标类 |
| | | */ |
| | | public static class Location { |
| | | private final double longitude; // 经度 |
| | | private final double latitude; // 纬度 |
| | | |
| | | public Location(double longitude, double latitude) { |
| | | this.longitude = longitude; |
| | | this.latitude = latitude; |
| | | } |
| | | |
| | | public double getLongitude() { |
| | | return longitude; |
| | | } |
| | | |
| | | public double getLatitude() { |
| | | return latitude; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return String.format("%.6f,%.6f", longitude, latitude); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 步行路线结果类 |
| | | */ |
| | | public static class WalkingRouteResult { |
| | | private int duration; // 步行时间(秒) |
| | | private int distance; // 步行距离(米) |
| | | private String origin; // 起点地址 |
| | | private String destination; // 终点地址 |
| | | private boolean success; // 是否成功 |
| | | private String message; // 返回信息 |
| | | |
| | | // getters and setters |
| | | public int getDuration() { |
| | | return duration; |
| | | } |
| | | |
| | | public void setDuration(int duration) { |
| | | this.duration = duration; |
| | | } |
| | | |
| | | public int getDistance() { |
| | | return distance; |
| | | } |
| | | |
| | | public void setDistance(int distance) { |
| | | this.distance = distance; |
| | | } |
| | | |
| | | public String getOrigin() { |
| | | return origin; |
| | | } |
| | | |
| | | public void setOrigin(String origin) { |
| | | this.origin = origin; |
| | | } |
| | | |
| | | public String getDestination() { |
| | | return destination; |
| | | } |
| | | |
| | | public void setDestination(String destination) { |
| | | this.destination = destination; |
| | | } |
| | | |
| | | public boolean isSuccess() { |
| | | return success; |
| | | } |
| | | |
| | | public void setSuccess(boolean success) { |
| | | this.success = success; |
| | | } |
| | | |
| | | public String getMessage() { |
| | | return message; |
| | | } |
| | | |
| | | public void setMessage(String message) { |
| | | this.message = message; |
| | | this.apiKey = apiKey; |
| | | this.httpClient = new OkHttpClient.Builder() |
| | | .connectTimeout(10, TimeUnit.SECONDS) |
| | | .readTimeout(10, TimeUnit.SECONDS) |
| | | .writeTimeout(10, TimeUnit.SECONDS) |
| | | .build(); |
| | | this.objectMapper = new ObjectMapper(); |
| | | } |
| | | |
| | | /** |
| | | * 获取格式化的步行时间 |
| | | * @return 格式化的时间字符串(如:15分钟30秒) |
| | | * 位置坐标类 |
| | | */ |
| | | public String getFormattedDuration() { |
| | | public static class Location { |
| | | private final double longitude; // 经度 |
| | | private final double latitude; // 纬度 |
| | | |
| | | int seconds = duration; |
| | | int minutes = seconds / 60; |
| | | seconds = seconds % 60; |
| | | return String.format("%d分%d秒", minutes, seconds); |
| | | public Location(double longitude, double latitude) { |
| | | this.longitude = longitude; |
| | | this.latitude = latitude; |
| | | } |
| | | |
| | | public double getLongitude() { |
| | | return longitude; |
| | | } |
| | | |
| | | public double getLatitude() { |
| | | return latitude; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return String.format("%.6f,%.6f", longitude, latitude); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取格式化的步行距离 |
| | | * @return 格式化的距离字符串(如:1.2公里) |
| | | * 步行路线结果类 |
| | | */ |
| | | public String getFormattedDistance() { |
| | | if (distance >= 1000) { |
| | | double km = distance / 1000.0; |
| | | return String.format("%.1f公里", km); |
| | | } else { |
| | | return String.format("%d米", distance); |
| | | } |
| | | } |
| | | } |
| | | public static class WalkingRouteResult { |
| | | private int duration; // 步行时间(秒) |
| | | private int distance; // 步行距离(米) |
| | | private String origin; // 起点地址 |
| | | private String destination; // 终点地址 |
| | | private boolean success; // 是否成功 |
| | | private String message; // 返回信息 |
| | | |
| | | /** |
| | | * 根据地址获取经纬度坐标 |
| | | * @param address 地址信息 |
| | | * @return 经纬度坐标 |
| | | */ |
| | | public Location getLocationByAddress(String address) throws IOException { |
| | | Map<String, String> params = new HashMap<>(); |
| | | params.put("key", apiKey); |
| | | params.put("address", address); |
| | | |
| | | String url = buildUrl(AMAP_GEOCODING_URL, params); |
| | | Request request = new Request.Builder().url(url).build(); |
| | | |
| | | try (Response response = httpClient.newCall(request).execute()) { |
| | | if (!response.isSuccessful()) { |
| | | throw new IOException("请求失败: " + response); |
| | | // getters and setters |
| | | public int getDuration() { |
| | | return duration; |
| | | } |
| | | |
| | | String responseBody = response.body().string(); |
| | | JsonNode rootNode = objectMapper.readTree(responseBody); |
| | | public void setDuration(int duration) { |
| | | this.duration = duration; |
| | | } |
| | | |
| | | if ("1".equals(rootNode.get("status").asText())) { |
| | | JsonNode geocodes = rootNode.get("geocodes"); |
| | | if (geocodes != null && geocodes.size() > 0) { |
| | | String locationStr = geocodes.get(0).get("location").asText(); |
| | | String[] locationArray = locationStr.split(","); |
| | | double longitude = Double.parseDouble(locationArray[0]); |
| | | double latitude = Double.parseDouble(locationArray[1]); |
| | | return new Location(longitude, latitude); |
| | | public int getDistance() { |
| | | return distance; |
| | | } |
| | | |
| | | public void setDistance(int distance) { |
| | | this.distance = distance; |
| | | } |
| | | |
| | | public String getOrigin() { |
| | | return origin; |
| | | } |
| | | |
| | | public void setOrigin(String origin) { |
| | | this.origin = origin; |
| | | } |
| | | |
| | | public String getDestination() { |
| | | return destination; |
| | | } |
| | | |
| | | public void setDestination(String destination) { |
| | | this.destination = destination; |
| | | } |
| | | |
| | | public boolean isSuccess() { |
| | | return success; |
| | | } |
| | | |
| | | public void setSuccess(boolean success) { |
| | | this.success = success; |
| | | } |
| | | |
| | | public String getMessage() { |
| | | return message; |
| | | } |
| | | |
| | | public void setMessage(String message) { |
| | | this.message = message; |
| | | } |
| | | |
| | | /** |
| | | * 获取格式化的步行时间 |
| | | * @return 格式化的时间字符串(如:15分钟30秒) |
| | | */ |
| | | public String getFormattedDuration() { |
| | | |
| | | int seconds = duration; |
| | | int minutes = seconds / 60; |
| | | seconds = seconds % 60; |
| | | return String.format("%d分%d秒", minutes, seconds); |
| | | } |
| | | |
| | | /** |
| | | * 获取格式化的步行距离 |
| | | * @return 格式化的距离字符串(如:1.2公里) |
| | | */ |
| | | public String getFormattedDistance() { |
| | | if (distance >= 1000) { |
| | | double km = distance / 1000.0; |
| | | return String.format("%.1f公里", km); |
| | | } else { |
| | | return String.format("%d米", distance); |
| | | } |
| | | } |
| | | |
| | | throw new IOException("地址解析失败: " + rootNode.get("info").asText()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取步行路线和时间 |
| | | * @param origin 起点坐标 |
| | | * @param destination 终点坐标 |
| | | * @return 步行路线结果 |
| | | */ |
| | | public WalkingRouteResult getWalkingRoute(Location origin, Location destination) { |
| | | WalkingRouteResult result = new WalkingRouteResult(); |
| | | |
| | | try { |
| | | /** |
| | | * 根据地址获取经纬度坐标 |
| | | * @param address 地址信息 |
| | | * @return 经纬度坐标 |
| | | */ |
| | | public Location getLocationByAddress (String address) throws IOException { |
| | | Map<String, String> params = new HashMap<>(); |
| | | params.put("key", apiKey); |
| | | params.put("origin", origin.toString()); |
| | | params.put("destination", destination.toString()); |
| | | params.put("address", address); |
| | | |
| | | String url = buildUrl(AMAP_API_BASE_URL, params); |
| | | String url = buildUrl(AMAP_GEOCODING_URL, params); |
| | | Request request = new Request.Builder().url(url).build(); |
| | | |
| | | try (Response response = httpClient.newCall(request).execute()) { |
| | | if (!response.isSuccessful()) { |
| | | result.setSuccess(false); |
| | | result.setMessage("HTTP请求失败: " + response.code()); |
| | | return result; |
| | | throw new IOException("请求失败: " + response); |
| | | } |
| | | |
| | | String responseBody = response.body().string(); |
| | | JsonNode rootNode = objectMapper.readTree(responseBody); |
| | | |
| | | String status = rootNode.get("status").asText(); |
| | | String info = rootNode.get("info").asText(); |
| | | |
| | | if ("1".equals(status)) { |
| | | JsonNode route = rootNode.get("route"); |
| | | JsonNode paths = route.get("paths"); |
| | | |
| | | if (paths != null && paths.size() > 0) { |
| | | JsonNode firstPath = paths.get(0); |
| | | int duration = firstPath.get("duration").asInt(); |
| | | int distance = firstPath.get("distance").asInt(); |
| | | |
| | | result.setDuration(duration); |
| | | result.setDistance(distance); |
| | | result.setSuccess(true); |
| | | result.setMessage("成功获取步行路线"); |
| | | |
| | | // 尝试获取地址信息 |
| | | result.setOrigin(getAddressByLocation(origin)); |
| | | result.setDestination(getAddressByLocation(destination)); |
| | | |
| | | } else { |
| | | result.setSuccess(false); |
| | | result.setMessage("未找到步行路线"); |
| | | log.info("未找到步行路线"); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | if ("1".equals(rootNode.get("status").asText())) { |
| | | JsonNode geocodes = rootNode.get("geocodes"); |
| | | if (geocodes != null && geocodes.size() > 0) { |
| | | String locationStr = geocodes.get(0).get("location").asText(); |
| | | String[] locationArray = locationStr.split(","); |
| | | double longitude = Double.parseDouble(locationArray[0]); |
| | | double latitude = Double.parseDouble(locationArray[1]); |
| | | return new Location(longitude, latitude); |
| | | } |
| | | } else { |
| | | result.setSuccess(false); |
| | | result.setMessage("API返回错误: " + info); |
| | | log.info("API返回错误" + info); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | } |
| | | |
| | | throw new IOException("地址解析失败: " + rootNode.get("info").asText()); |
| | | } |
| | | } catch (Exception e) { |
| | | result.setSuccess(false); |
| | | result.setMessage("获取步行路线失败: " + e.getMessage()); |
| | | log.info("获取步行路线失败" + e.getMessage()); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | /** |
| | | * 获取步行路线和时间 |
| | | * @param origin 起点坐标 |
| | | * @param destination 终点坐标 |
| | | * @return 步行路线结果 |
| | | */ |
| | | public WalkingRouteResult getWalkingRoute (Location origin, Location destination){ |
| | | WalkingRouteResult result = new WalkingRouteResult(); |
| | | |
| | | /** |
| | | * 根据经纬度获取地址(逆地理编码) |
| | | * @param location 经纬度坐标 |
| | | * @return 地址信息 |
| | | */ |
| | | private String getAddressByLocation(Location location) { |
| | | try { |
| | | Map<String, String> params = new HashMap<>(); |
| | | params.put("key", apiKey); |
| | | params.put("location", location.toString()); |
| | | try { |
| | | Map<String, String> params = new HashMap<>(); |
| | | params.put("key", apiKey); |
| | | params.put("origin", origin.toString()); |
| | | params.put("destination", destination.toString()); |
| | | |
| | | String url = buildUrl("https://restapi.amap.com/v3/geocode/regeo", params); |
| | | Request request = new Request.Builder().url(url).build(); |
| | | String url = buildUrl(AMAP_API_BASE_URL, params); |
| | | Request request = new Request.Builder().url(url).build(); |
| | | |
| | | try (Response response = httpClient.newCall(request).execute()) { |
| | | if (response.isSuccessful()) { |
| | | try (Response response = httpClient.newCall(request).execute()) { |
| | | if (!response.isSuccessful()) { |
| | | result.setSuccess(false); |
| | | result.setMessage("HTTP请求失败: " + response.code()); |
| | | return result; |
| | | } |
| | | |
| | | String responseBody = response.body().string(); |
| | | JsonNode rootNode = objectMapper.readTree(responseBody); |
| | | |
| | | if ("1".equals(rootNode.get("status").asText())) { |
| | | JsonNode regeocode = rootNode.get("regeocode"); |
| | | if (regeocode != null) { |
| | | return regeocode.get("formatted_address").asText(); |
| | | String status = rootNode.get("status").asText(); |
| | | String info = rootNode.get("info").asText(); |
| | | |
| | | if ("1".equals(status)) { |
| | | JsonNode route = rootNode.get("route"); |
| | | JsonNode paths = route.get("paths"); |
| | | |
| | | if (paths != null && paths.size() > 0) { |
| | | JsonNode firstPath = paths.get(0); |
| | | int duration = firstPath.get("duration").asInt(); |
| | | int distance = firstPath.get("distance").asInt(); |
| | | |
| | | result.setDuration(duration); |
| | | result.setDistance(distance); |
| | | result.setSuccess(true); |
| | | result.setMessage("成功获取步行路线"); |
| | | |
| | | // 尝试获取地址信息 |
| | | result.setOrigin(getAddressByLocation(origin)); |
| | | result.setDestination(getAddressByLocation(destination)); |
| | | |
| | | } else { |
| | | result.setSuccess(false); |
| | | result.setMessage("未找到步行路线"); |
| | | log.info("未找到步行路线"); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | } |
| | | } else { |
| | | result.setSuccess(false); |
| | | result.setMessage("API返回错误: " + info); |
| | | log.info("API返回错误" + info); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | result.setSuccess(false); |
| | | result.setMessage("获取步行路线失败: " + e.getMessage()); |
| | | log.info("获取步行路线失败" + e.getMessage()); |
| | | throw new ServiceException("未找到步行路线", I18nKeyConstant.NO_WALKING_ROUTE_FOUND); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 根据经纬度获取地址(逆地理编码) |
| | | * @param location 经纬度坐标 |
| | | * @return 地址信息 |
| | | */ |
| | | private String getAddressByLocation (Location location){ |
| | | try { |
| | | Map<String, String> params = new HashMap<>(); |
| | | params.put("key", apiKey); |
| | | params.put("location", location.toString()); |
| | | |
| | | String url = buildUrl("https://restapi.amap.com/v3/geocode/regeo", params); |
| | | Request request = new Request.Builder().url(url).build(); |
| | | |
| | | try (Response response = httpClient.newCall(request).execute()) { |
| | | if (response.isSuccessful()) { |
| | | String responseBody = response.body().string(); |
| | | JsonNode rootNode = objectMapper.readTree(responseBody); |
| | | |
| | | if ("1".equals(rootNode.get("status").asText())) { |
| | | JsonNode regeocode = rootNode.get("regeocode"); |
| | | if (regeocode != null) { |
| | | return regeocode.get("formatted_address").asText(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | // 地址解析失败时返回坐标 |
| | | } |
| | | } catch (Exception e) { |
| | | // 地址解析失败时返回坐标 |
| | | return location.toString(); |
| | | } |
| | | return location.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 构建带参数的URL |
| | | * @param baseUrl 基础URL |
| | | * @param params 参数Map |
| | | * @return 完整的URL |
| | | */ |
| | | private String buildUrl(String baseUrl, Map<String, String> params) { |
| | | StringBuilder urlBuilder = new StringBuilder(baseUrl).append("?"); |
| | | params.forEach((key, value) -> { |
| | | urlBuilder.append(key).append("=").append(value).append("&"); |
| | | }); |
| | | // 删除最后一个& |
| | | urlBuilder.deleteCharAt(urlBuilder.length() - 1); |
| | | return urlBuilder.toString(); |
| | | } |
| | | /** |
| | | * 构建带参数的URL |
| | | * @param baseUrl 基础URL |
| | | * @param params 参数Map |
| | | * @return 完整的URL |
| | | */ |
| | | private String buildUrl (String baseUrl, Map < String, String > params){ |
| | | StringBuilder urlBuilder = new StringBuilder(baseUrl).append("?"); |
| | | params.forEach((key, value) -> { |
| | | urlBuilder.append(key).append("=").append(value).append("&"); |
| | | }); |
| | | // 删除最后一个& |
| | | urlBuilder.deleteCharAt(urlBuilder.length() - 1); |
| | | return urlBuilder.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 计算两点间的直线距离(仅供参考,不是实际步行距离) |
| | | * @param loc1 坐标1 |
| | | * @param loc2 坐标2 |
| | | * @return 直线距离(米) |
| | | */ |
| | | public static double calculateStraightDistance(Location loc1, Location loc2) { |
| | | double earthRadius = 6371000; // 地球半径(米) |
| | | double lat1 = Math.toRadians(loc1.getLatitude()); |
| | | double lat2 = Math.toRadians(loc2.getLatitude()); |
| | | double deltaLat = Math.toRadians(loc2.getLatitude() - loc1.getLatitude()); |
| | | double deltaLon = Math.toRadians(loc2.getLongitude() - loc1.getLongitude()); |
| | | /** |
| | | * 计算两点间的直线距离(仅供参考,不是实际步行距离) |
| | | * @param loc1 坐标1 |
| | | * @param loc2 坐标2 |
| | | * @return 直线距离(米) |
| | | */ |
| | | public static double calculateStraightDistance (Location loc1, Location loc2){ |
| | | double earthRadius = 6371000; // 地球半径(米) |
| | | double lat1 = Math.toRadians(loc1.getLatitude()); |
| | | double lat2 = Math.toRadians(loc2.getLatitude()); |
| | | double deltaLat = Math.toRadians(loc2.getLatitude() - loc1.getLatitude()); |
| | | double deltaLon = Math.toRadians(loc2.getLongitude() - loc1.getLongitude()); |
| | | |
| | | double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + |
| | | Math.cos(lat1) * Math.cos(lat2) * |
| | | Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); |
| | | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| | | double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + |
| | | Math.cos(lat1) * Math.cos(lat2) * |
| | | Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); |
| | | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| | | |
| | | return earthRadius * c; |
| | | } |
| | | return earthRadius * c; |
| | | } |
| | | |
| | | |
| | | } |
| | | } |