1.根据两点经纬度计算其间距离,发现有3种公式,结果区别不是很大。
2.根据一点的经纬度与到另外一点的距离、方位角,计算另一点的经纬度,误差不是很大。
1 package com.zhs.util; 2 3 /** 4 * 5 * 计算经纬度、距离、方位角 6 * 7 * @author lillian.he 8 * @time 2016-06-02 9 * */ 10 public class CalculationLogLatDistance { 11 /** 12 * 地球赤道半径(km) 13 * */ 14 public final static double EARTH_RADIUS = 6378.137; 15 /** 16 * 地球每度的弧长(km) 17 * */ 18 public final static double EARTH_ARC = 111.199; 19 20 /** 21 * 转化为弧度(rad) 22 * */ 23 public static double rad(double d) { 24 return d * Math.PI / 180.0; 25 } 26 27 /** 28 * 求两经纬度距离 29 * 30 * @param lon1 31 * 第一点的经度 32 * @param lat1 33 * 第一点的纬度 34 * @param lon2 35 * 第二点的经度 36 * @param lat2 37 * 第二点的纬度 38 * @return 两点距离,单位km 39 * */ 40 public static double GetDistanceOne(double lon1, double lat1, double lon2, 41 double lat2) { 42 double r1 = rad(lat1); 43 double r2 = rad(lon1); 44 double a = rad(lat2); 45 double b = rad(lon2); 46 double s = Math.acos(Math.cos(r1) * Math.cos(a) * Math.cos(r2 - b) 47 + Math.sin(r1) * Math.sin(a)) 48 * EARTH_RADIUS; 49 return s; 50 } 51 52 /** 53 * 求两经纬度距离(google maps源码中) 54 * 55 * @param lon1 56 * 第一点的经度 57 * @param lat1 58 * 第一点的纬度 59 * @param lon2 60 * 第二点的经度 61 * @param lat2 62 * 第二点的纬度 63 * @return 两点距离,单位km 64 * */ 65 public static double GetDistanceTwo(double lon1, double lat1, double lon2, 66 double lat2) { 67 double radLat1 = rad(lat1); 68 double radLat2 = rad(lat2); 69 double a = radLat1 - radLat2; 70 double b = rad(lon1) - rad(lon2); 71 double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) 72 + Math.cos(radLat1) * Math.cos(radLat2) 73 * Math.pow(Math.sin(b / 2), 2))); 74 s = s * EARTH_RADIUS; 75 return s; 76 } 77 78 /** 79 * 求两经纬度距离 80 * 81 * @param lon1 82 * 第一点的经度 83 * @param lat1 84 * 第一点的纬度 85 * @param lon2 86 * 第二点的经度 87 * @param lat2 88 * 第二点的纬度 89 * @return 两点距离,单位km 90 * */ 91 public static double GetDistanceThree(double lon1, double lat1, 92 double lon2, double lat2) { 93 double radLat1 = rad(lat1); 94 double radLat2 = rad(lat2); 95 double radLon1 = rad(lon1); 96 double radLon2 = rad(lon2); 97 if (radLat1 < 0) 98 radLat1 = Math.PI / 2 + Math.abs(radLat1);// south 99 if (radLat1 > 0) 100 radLat1 = Math.PI / 2 - Math.abs(radLat1);// north 101 if (radLon1 < 0) 102 radLon1 = Math.PI * 2 - Math.abs(radLon1);// west 103 if (radLat2 < 0) 104 radLat2 = Math.PI / 2 + Math.abs(radLat2);// south 105 if (radLat2 > 0) 106 radLat2 = Math.PI / 2 - Math.abs(radLat2);// north 107 if (radLon2 < 0) 108 radLon2 = Math.PI * 2 - Math.abs(radLon2);// west 109 double x1 = Math.cos(radLon1) * Math.sin(radLat1); 110 double y1 = Math.sin(radLon1) * Math.sin(radLat1); 111 double z1 = Math.cos(radLat1); 112 113 double x2 = Math.cos(radLon2) * Math.sin(radLat2); 114 double y2 = Math.sin(radLon2) * Math.sin(radLat2); 115 double z2 = Math.cos(radLat2); 116 117 double d = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2) 118 + Math.pow((z1 - z2), 2); 119 // // 余弦定理求夹角 120 // double theta = Math.acos((2 - d) / 2); 121 122 d = Math.pow(EARTH_RADIUS, 2) * d; 123 // //余弦定理求夹角 124 double theta = Math.acos((2 * Math.pow(EARTH_RADIUS, 2) - d) 125 / (2 * Math.pow(EARTH_RADIUS, 2))); 126 127 double dist = theta * EARTH_RADIUS; 128 return dist; 129 } 130 131 /** 132 * 求两经纬度方向角 133 * 134 * @param lon1 135 * 第一点的经度 136 * @param lat1 137 * 第一点的纬度 138 * @param lon2 139 * 第二点的经度 140 * @param lat2 141 * 第二点的纬度 142 * @return 方位角,角度(单位:°) 143 * */ 144 public static double GetAzimuth(double lon1, double lat1, double lon2, 145 double lat2) { 146 lat1 = rad(lat1); 147 lat2 = rad(lat2); 148 lon1 = rad(lon1); 149 lon2 = rad(lon2); 150 double azimuth = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) 151 * Math.cos(lat2) * Math.cos(lon2 - lon1); 152 azimuth = Math.sqrt(1 - azimuth * azimuth); 153 azimuth = Math.cos(lat2) * Math.sin(lon2 - lon1) / azimuth; 154 azimuth = Math.asin(azimuth) * 180 / Math.PI; 155 if (Double.isNaN(azimuth)) { 156 if (lon1 < lon2) { 157 azimuth = 90.0; 158 } else { 159 azimuth = 270.0; 160 } 161 } 162 return azimuth; 163 } 164 165 /** 166 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度(计算结果有误) 167 * 168 * @param lon1 169 * A的经度 170 * @param lat1 171 * A的纬度 172 * @param distance 173 * AB距离(单位:米) 174 * @param azimuth 175 * AB方位角 176 * @return B的经纬度 177 * */ 178 public static String GetOtherPoint(double lon1, double lat1, 179 double distance, double azimuth) { 180 azimuth = rad(azimuth); 181 double ab = distance / EARTH_ARC;// AB间弧线长 182 ab = rad(ab); 183 double Lat = Math.asin(Math.sin(lat1) * Math.cos(ab) + Math.cos(lat1) 184 * Math.sin(ab) * Math.cos(azimuth)); 185 double Lon = lon1 186 + Math.asin(Math.sin(azimuth) * Math.sin(ab) / Math.cos(Lat)); 187 System.out.println(Lon + "," + Lat); 188 189 double a = Math.acos(Math.cos(90 - lon1) * Math.cos(ab) 190 + Math.sin(90 - lon1) * Math.sin(ab) * Math.cos(azimuth)); 191 double C = Math.asin(Math.sin(ab) * Math.sin(azimuth) / Math.sin(a)); 192 System.out.println("c=" + C); 193 double lon2 = lon1 + C; 194 double lat2 = 90 - a; 195 return lon2 + "," + lat2; 196 } 197 198 /** 199 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度 200 * 201 * @param lon1 202 * A的经度 203 * @param lat1 204 * A的纬度 205 * @param distance 206 * AB距离(单位:米) 207 * @param azimuth 208 * AB方位角 209 * @return B的经纬度 210 * */ 211 public static String ConvertDistanceToLogLat(double lng1, double lat1, 212 double distance, double azimuth) { 213 azimuth = rad(azimuth); 214 // 将距离转换成经度的计算公式 215 double lon = lng1 + (distance * Math.sin(azimuth)) 216 / (EARTH_ARC * Math.cos(rad(lat1))); 217 // 将距离转换成纬度的计算公式 218 double lat = lat1 + (distance * Math.cos(azimuth)) / EARTH_ARC; 219 return lon + "," + lat; 220 } 221 222 public static void main(String[] args) { 223 double lon1 = 121.469156; 224 double lat1 = 31.232307; 225 double lon2 = 121.469156; 226 double lat2 = 31.233205; 227 double distance = GetDistanceTwo(lon1, lat1, lon2, lat2); 228 double azimuth = GetAzimuth(lon1, lat1, lon2, lat2); 229 System.out.println("经纬度为(" + lon1 + "," + lat1 + ")的点与经纬度为(" + lon2 230 + "," + lat2 + ")相距:" + distance + "千米," + "方位角:" + azimuth 231 + "°"); 232 System.out.println("距经纬度为(" + lon1 + "," + lat1 + ")的点" + distance 233 + "千米,方位角为" + azimuth + "°的另一点经纬度为(" 234 + ConvertDistanceToLogLat(lon1, lat1, distance, azimuth) + ")"); 235 } 236 }
时间: 2024-09-29 18:52:02