经纬度和距离之间的计算
不是我写的, 也看不太懂, 备忘
package com.iwhere.easy.travel.tool; import org.junit.Test; import org.springframework.util.Assert; /** */ public class GeoUtils { public final static float EARTH_RADIUS = 6378137; // 地球半径 @Test public void test2() { // GeoUtils.getBoxByCoordinate(120.0, 40.0, 2000.0); Double distance = GeoUtils.getDistance(new Point(119.9765412051408, 39.98202952055585), new Point(120.0234587948592, 40.01797047944415)); System.out.println(distance); } /** * 根据中心点获取box * * @return */ public static Double[] getBoxByCoordinate(Double longitude, Double latitude, Double raidusMile) { Assert.notNull(longitude); Assert.notNull(latitude); Double degree = (24901 * 1609) / 360.0; // 获取每度弧长 Double mpdLng = Double.parseDouble((degree * Math.cos(latitude * (Math.PI / 180)) + "").replace("-", "")); Double dpmLng = 1 / mpdLng; Double radiusLng = dpmLng * raidusMile; // 获取最小经度 Double minLat = longitude - radiusLng; // 获取最大经度 Double maxLat = longitude + radiusLng; Double dpmLat = 1 / degree; Double radiusLat = dpmLat * raidusMile; // 获取最小纬度 Double minLng = latitude - radiusLat; // 获取最大纬度 Double maxLng = latitude + radiusLat; System.out.println(minLat + ": " + maxLat + ": " + minLng + ": " + maxLng); return null; } /** * 获取距离 * * @param from * 开始点 * @param to * 结束点 * @return */ public static Double getDistance(Point from, Point to) { if (from == null || to == null || from.getLat() == null || from.getLng() == null || to.getLat() == null || to.getLng() == null) { return Double.NaN; } else { double lat1 = from.getLat() * Math.PI / 180.0; double lat2 = to.getLat() * Math.PI / 180.0; double a = lat1 - lat2; double b = (from.getLng() - to.getLng()) * Math.PI / 180.0; double sa2, sb2; sa2 = Math.sin(a / 2.0); sb2 = Math.sin(b / 2.0); return 2 * EARTH_RADIUS * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2)); } } /** * * --------------------------------------------------------------------------- * 点 * --------------------------------------------------------------------------- * <strong>copyright</strong>: ©版权所有 成都都在哪网讯科技有限公司<br> * ---------------------------------------------------------------------------- * * @author: hewei * @time:2016年10月28日 下午6:29:22 * --------------------------------------------------------------------------- */ public static class Point { public Double lat; // 纬度 public Double lng; // 经度 /** * */ public Point() { super(); } /** * @param lat * @param lng */ public Point(Double lat, Double lng) { super(); this.lat = lat; this.lng = lng; } /** * @return the lat */ public Double getLat() { return lat; } /** * @param lat * the lat to set */ public void setLat(Double lat) { this.lat = lat; } /** * @return the lng */ public Double getLng() { return lng; } /** * @param lng * the lng to set */ public void setLng(Double lng) { this.lng = lng; } } }
角度计算:
package com.iwhere.easy.travel.tool; import org.junit.Test; public class GeoTools { public static double getAngle(double lat1, double lng1, double lat2, double lng2) { double x1 = lng1; double y1 = lat1; double x2 = lng2; double y2 = lat2; double pi = Math.PI; double w1 = y1 / 180 * pi; double j1 = x1 / 180 * pi; double w2 = y2 / 180 * pi; double j2 = x2 / 180 * pi; double ret; if (j1 == j2) { if (w1 > w2) return 270; // 北半球的情况,南半球忽略 else if (w1 < w2) return 90; else return -1;// 位置完全相同 } ret = 4 * Math.pow(Math.sin((w1 - w2) / 2), 2) - Math.pow(Math.sin((j1 - j2) / 2) * (Math.cos(w1) - Math.cos(w2)), 2); ret = Math.sqrt(ret); double temp = (Math.sin(Math.abs(j1 - j2) / 2) * (Math.cos(w1) + Math.cos(w2))); ret = ret / temp; ret = Math.atan(ret) / pi * 180; if (j1 > j2) { // 1为参考点坐标 if (w1 > w2) ret += 180; else ret = 180 - ret; } else if (w1 > w2) ret = 360 - ret; return ret; } /** * @param lat1 * 纬度1,参考点 * @param lng1 * 经度1,参考点 * @param lat2 * 纬度2 * @param lng2 * 经度2 * @return 方向 */ public static String getDirection(double lat1, double lng1, double lat2, double lng2) { double jiaodu = getAngle(lat1, lng1, lat2, lng2); if ((jiaodu <= 10) || (jiaodu > 350)) return "正东方"; if ((jiaodu > 10) && (jiaodu <= 80)) return "东北方"; if ((jiaodu > 80) && (jiaodu <= 100)) return "正北方"; if ((jiaodu > 100) && (jiaodu <= 170)) return "西北方"; if ((jiaodu > 170) && (jiaodu <= 190)) return "正西方"; if ((jiaodu > 190) && (jiaodu <= 260)) return "西南方"; if ((jiaodu > 260) && (jiaodu <= 280)) return "正南方"; if ((jiaodu > 280) && (jiaodu <= 350)) return "东南方"; return ""; } /** * 获取方位角描述 * 前一个点 * 参照点 * 目标点 * @return */ public static String getAzimuth(double preLng, double preLat, double referLng, double referLat, double poiLng, double poiLat) { double jiaodu1 = getAngle(preLat, preLng, referLat, referLng); double jiaodu2 = getAngle(referLat, referLng, poiLat, poiLng); double jiaodu = jiaodu2 - jiaodu1; if (((jiaodu <=10 && jiaodu > 0) || jiaodu > 350) || ((jiaodu >= -10 && jiaodu < 0) || jiaodu < -350)) { return "正前方"; }else if ((jiaodu <= 80 && jiaodu > 10) || (jiaodu >= -350 && jiaodu < -280)) { return "左前方"; }else if ((jiaodu <= 100 && jiaodu > 80) || (jiaodu >= -280 && jiaodu < -260)) { return "左侧"; }else if ((jiaodu <= 170 && jiaodu > 100) || (jiaodu >= -260 && jiaodu < -190)) { return "左后方"; }else if ((jiaodu <= 190 && jiaodu > 170) || (jiaodu >= -190 && jiaodu < -170)) { return "后方"; }else if ((jiaodu <=260 && jiaodu > 190) || (jiaodu >= -170 && jiaodu < -100)) { return "右后方"; }else if ((jiaodu <=280 && jiaodu > 260) || (jiaodu >= -100 && jiaodu < -80)) { return "右侧"; }else if ((jiaodu <= 350 && jiaodu > 280) || (jiaodu >= -80 && jiaodu < -10)) { return "右前方"; } return ""; } @Test public void test() { String azimuth = GeoTools.getAzimuth(0d, 0d, -40d, 20d, 30d, 30d); System.out.println(azimuth); } public static void main(String[] args) { String str = getDirection(0, 0, -40, -34); System.out.println(str); } }
参考: http://blog.csdn.net/koryako/article/details/51864161