(转)根据经纬度计算方位距离
(原文地址:http://www.cnblogs.com/leejuan/p/5552460.html)
1.根据两点经纬度计算其间距离,发现有3种公式,结果区别不是很大。
2.根据一点的经纬度与到另外一点的距离、方位角,计算另一点的经纬度,误差不是很大。
1 /** 2 * 3 * 计算经纬度、距离、方位角 4 * 5 * */ 6 public class CalculationLogLatDistance { 7 /** 8 * 地球赤道半径(km) 9 * */ 10 public final static double EARTH_RADIUS = 6378.137; 11 /** 12 * 地球每度的弧长(km) 13 * */ 14 public final static double EARTH_ARC = 111.199; 15 16 /** 17 * 转化为弧度(rad) 18 * */ 19 public static double rad(double d) { 20 return d * Math.PI / 180.0; 21 } 22 23 /** 24 * 求两经纬度距离 25 * 26 * @param lon1 27 * 第一点的经度 28 * @param lat1 29 * 第一点的纬度 30 * @param lon2 31 * 第二点的经度 32 * @param lat2 33 * 第二点的纬度 34 * @return 两点距离,单位km 35 * */ 36 public static double GetDistanceOne(double lon1, double lat1, double lon2, 37 double lat2) { 38 double r1 = rad(lat1); 39 double r2 = rad(lon1); 40 double a = rad(lat2); 41 double b = rad(lon2); 42 double s = Math.acos(Math.cos(r1) * Math.cos(a) * Math.cos(r2 - b) 43 + Math.sin(r1) * Math.sin(a)) 44 * EARTH_RADIUS; 45 return s; 46 } 47 48 /** 49 * 求两经纬度距离(google maps源码中) 50 * 51 * @param lon1 52 * 第一点的经度 53 * @param lat1 54 * 第一点的纬度 55 * @param lon2 56 * 第二点的经度 57 * @param lat2 58 * 第二点的纬度 59 * @return 两点距离,单位km 60 * */ 61 public static double GetDistanceTwo(double lon1, double lat1, double lon2, 62 double lat2) { 63 double radLat1 = rad(lat1); 64 double radLat2 = rad(lat2); 65 double a = radLat1 - radLat2; 66 double b = rad(lon1) - rad(lon2); 67 double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) 68 + Math.cos(radLat1) * Math.cos(radLat2) 69 * Math.pow(Math.sin(b / 2), 2))); 70 s = s * EARTH_RADIUS; 71 return s; 72 } 73 74 /** 75 * 求两经纬度距离 76 * 77 * @param lon1 78 * 第一点的经度 79 * @param lat1 80 * 第一点的纬度 81 * @param lon2 82 * 第二点的经度 83 * @param lat2 84 * 第二点的纬度 85 * @return 两点距离,单位km 86 * */ 87 public static double GetDistanceThree(double lon1, double lat1, 88 double lon2, double lat2) { 89 double radLat1 = rad(lat1); 90 double radLat2 = rad(lat2); 91 double radLon1 = rad(lon1); 92 double radLon2 = rad(lon2); 93 if (radLat1 < 0) 94 radLat1 = Math.PI / 2 + Math.abs(radLat1);// south 95 if (radLat1 > 0) 96 radLat1 = Math.PI / 2 - Math.abs(radLat1);// north 97 if (radLon1 < 0) 98 radLon1 = Math.PI * 2 - Math.abs(radLon1);// west 99 if (radLat2 < 0) 100 radLat2 = Math.PI / 2 + Math.abs(radLat2);// south 101 if (radLat2 > 0) 102 radLat2 = Math.PI / 2 - Math.abs(radLat2);// north 103 if (radLon2 < 0) 104 radLon2 = Math.PI * 2 - Math.abs(radLon2);// west 105 double x1 = Math.cos(radLon1) * Math.sin(radLat1); 106 double y1 = Math.sin(radLon1) * Math.sin(radLat1); 107 double z1 = Math.cos(radLat1); 108 109 double x2 = Math.cos(radLon2) * Math.sin(radLat2); 110 double y2 = Math.sin(radLon2) * Math.sin(radLat2); 111 double z2 = Math.cos(radLat2); 112 113 double d = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2) 114 + Math.pow((z1 - z2), 2); 115 // // 余弦定理求夹角 116 // double theta = Math.acos((2 - d) / 2); 117 118 d = Math.pow(EARTH_RADIUS, 2) * d; 119 // //余弦定理求夹角 120 double theta = Math.acos((2 * Math.pow(EARTH_RADIUS, 2) - d) 121 / (2 * Math.pow(EARTH_RADIUS, 2))); 122 123 double dist = theta * EARTH_RADIUS; 124 return dist; 125 } 126 127 /** 128 * 求两经纬度方向角 129 * 130 * @param lon1 131 * 第一点的经度 132 * @param lat1 133 * 第一点的纬度 134 * @param lon2 135 * 第二点的经度 136 * @param lat2 137 * 第二点的纬度 138 * @return 方位角,角度(单位:°) 139 * */ 140 public static double GetAzimuth(double lon1, double lat1, double lon2, 141 double lat2) { 142 lat1 = rad(lat1); 143 lat2 = rad(lat2); 144 lon1 = rad(lon1); 145 lon2 = rad(lon2); 146 double azimuth = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) 147 * Math.cos(lat2) * Math.cos(lon2 - lon1); 148 azimuth = Math.sqrt(1 - azimuth * azimuth); 149 azimuth = Math.cos(lat2) * Math.sin(lon2 - lon1) / azimuth; 150 azimuth = Math.asin(azimuth) * 180 / Math.PI; 151 if (Double.isNaN(azimuth)) { 152 if (lon1 < lon2) { 153 azimuth = 90.0; 154 } else { 155 azimuth = 270.0; 156 } 157 } 158 return azimuth; 159 } 160 161 /** 162 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度(计算结果有误) 163 * 164 * @param lon1 165 * A的经度 166 * @param lat1 167 * A的纬度 168 * @param distance 169 * AB距离(单位:米) 170 * @param azimuth 171 * AB方位角 172 * @return B的经纬度 173 * */ 174 public static String GetOtherPoint(double lon1, double lat1, 175 double distance, double azimuth) { 176 azimuth = rad(azimuth); 177 double ab = distance / EARTH_ARC;// AB间弧线长 178 ab = rad(ab); 179 double Lat = Math.asin(Math.sin(lat1) * Math.cos(ab) + Math.cos(lat1) 180 * Math.sin(ab) * Math.cos(azimuth)); 181 double Lon = lon1 182 + Math.asin(Math.sin(azimuth) * Math.sin(ab) / Math.cos(Lat)); 183 System.out.println(Lon + ”,” + Lat); 184 185 double a = Math.acos(Math.cos(90 - lon1) * Math.cos(ab) 186 + Math.sin(90 - lon1) * Math.sin(ab) * Math.cos(azimuth)); 187 double C = Math.asin(Math.sin(ab) * Math.sin(azimuth) / Math.sin(a)); 188 System.out.println(”c=” + C); 189 double lon2 = lon1 + C; 190 double lat2 = 90 - a; 191 return lon2 + “,” + lat2; 192 } 193 194 /** 195 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度 196 * 197 * @param lon1 198 * A的经度 199 * @param lat1 200 * A的纬度 201 * @param distance 202 * AB距离(单位:米) 203 * @param azimuth 204 * AB方位角 205 * @return B的经纬度 206 * */ 207 public static String ConvertDistanceToLogLat(double lng1, double lat1, 208 double distance, double azimuth) { 209 azimuth = rad(azimuth); 210 // 将距离转换成经度的计算公式 211 double lon = lng1 + (distance * Math.sin(azimuth)) 212 / (EARTH_ARC * Math.cos(rad(lat1))); 213 // 将距离转换成纬度的计算公式 214 double lat = lat1 + (distance * Math.cos(azimuth)) / EARTH_ARC; 215 return lon + “,” + lat; 216 } 217 218 public static void main(String[] args) { 219 double lon1 = 121.469156; 220 double lat1 = 31.232307; 221 double lon2 = 121.469156; 222 double lat2 = 31.233205; 223 double distance = GetDistanceTwo(lon1, lat1, lon2, lat2); 224 double azimuth = GetAzimuth(lon1, lat1, lon2, lat2); 225 System.out.println(”经纬度为(“ + lon1 + “,” + lat1 + “)的点与经纬度为(“ + lon2 226 + ”,” + lat2 + “)相距:” + distance + “千米,” + “方位角:” + azimuth 227 + ”°”); 228 System.out.println(”距经纬度为(“ + lon1 + “,” + lat1 + “)的点” + distance 229 + ”千米,方位角为” + azimuth + “°的另一点经纬度为(“ 230 + ConvertDistanceToLogLat(lon1, lat1, distance, azimuth) + ”)”); 231 } 232 } 233 [java] view plain copy 234 235 236 /** 237 * 238 * 计算经纬度、距离、方位角 239 * 240 * */ 241 public class CalculationLogLatDistance { 242 /** 243 * 地球赤道半径(km) 244 * */ 245 public final static double EARTH_RADIUS = 6378.137; 246 /** 247 * 地球每度的弧长(km) 248 * */ 249 public final static double EARTH_ARC = 111.199; 250 251 /** 252 * 转化为弧度(rad) 253 * */ 254 public static double rad(double d) { 255 return d * Math.PI / 180.0; 256 } 257 258 /** 259 * 求两经纬度距离 260 * 261 * @param lon1 262 * 第一点的经度 263 * @param lat1 264 * 第一点的纬度 265 * @param lon2 266 * 第二点的经度 267 * @param lat2 268 * 第二点的纬度 269 * @return 两点距离,单位km 270 * */ 271 public static double GetDistanceOne(double lon1, double lat1, double lon2, 272 double lat2) { 273 double r1 = rad(lat1); 274 double r2 = rad(lon1); 275 double a = rad(lat2); 276 double b = rad(lon2); 277 double s = Math.acos(Math.cos(r1) * Math.cos(a) * Math.cos(r2 - b) 278 + Math.sin(r1) * Math.sin(a)) 279 * EARTH_RADIUS; 280 return s; 281 } 282 283 /** 284 * 求两经纬度距离(google maps源码中) 285 * 286 * @param lon1 287 * 第一点的经度 288 * @param lat1 289 * 第一点的纬度 290 * @param lon2 291 * 第二点的经度 292 * @param lat2 293 * 第二点的纬度 294 * @return 两点距离,单位km 295 * */ 296 public static double GetDistanceTwo(double lon1, double lat1, double lon2, 297 double lat2) { 298 double radLat1 = rad(lat1); 299 double radLat2 = rad(lat2); 300 double a = radLat1 - radLat2; 301 double b = rad(lon1) - rad(lon2); 302 double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) 303 + Math.cos(radLat1) * Math.cos(radLat2) 304 * Math.pow(Math.sin(b / 2), 2))); 305 s = s * EARTH_RADIUS; 306 return s; 307 } 308 309 /** 310 * 求两经纬度距离 311 * 312 * @param lon1 313 * 第一点的经度 314 * @param lat1 315 * 第一点的纬度 316 * @param lon2 317 * 第二点的经度 318 * @param lat2 319 * 第二点的纬度 320 * @return 两点距离,单位km 321 * */ 322 public static double GetDistanceThree(double lon1, double lat1, 323 double lon2, double lat2) { 324 double radLat1 = rad(lat1); 325 double radLat2 = rad(lat2); 326 double radLon1 = rad(lon1); 327 double radLon2 = rad(lon2); 328 if (radLat1 < 0) 329 radLat1 = Math.PI / 2 + Math.abs(radLat1);// south 330 if (radLat1 > 0) 331 radLat1 = Math.PI / 2 - Math.abs(radLat1);// north 332 if (radLon1 < 0) 333 radLon1 = Math.PI * 2 - Math.abs(radLon1);// west 334 if (radLat2 < 0) 335 radLat2 = Math.PI / 2 + Math.abs(radLat2);// south 336 if (radLat2 > 0) 337 radLat2 = Math.PI / 2 - Math.abs(radLat2);// north 338 if (radLon2 < 0) 339 radLon2 = Math.PI * 2 - Math.abs(radLon2);// west 340 double x1 = Math.cos(radLon1) * Math.sin(radLat1); 341 double y1 = Math.sin(radLon1) * Math.sin(radLat1); 342 double z1 = Math.cos(radLat1); 343 344 double x2 = Math.cos(radLon2) * Math.sin(radLat2); 345 double y2 = Math.sin(radLon2) * Math.sin(radLat2); 346 double z2 = Math.cos(radLat2); 347 348 double d = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2) 349 + Math.pow((z1 - z2), 2); 350 // // 余弦定理求夹角 351 // double theta = Math.acos((2 - d) / 2); 352 353 d = Math.pow(EARTH_RADIUS, 2) * d; 354 // //余弦定理求夹角 355 double theta = Math.acos((2 * Math.pow(EARTH_RADIUS, 2) - d) 356 / (2 * Math.pow(EARTH_RADIUS, 2))); 357 358 double dist = theta * EARTH_RADIUS; 359 return dist; 360 } 361 362 /** 363 * 求两经纬度方向角 364 * 365 * @param lon1 366 * 第一点的经度 367 * @param lat1 368 * 第一点的纬度 369 * @param lon2 370 * 第二点的经度 371 * @param lat2 372 * 第二点的纬度 373 * @return 方位角,角度(单位:°) 374 * */ 375 public static double GetAzimuth(double lon1, double lat1, double lon2, 376 double lat2) { 377 lat1 = rad(lat1); 378 lat2 = rad(lat2); 379 lon1 = rad(lon1); 380 lon2 = rad(lon2); 381 double azimuth = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) 382 * Math.cos(lat2) * Math.cos(lon2 - lon1); 383 azimuth = Math.sqrt(1 - azimuth * azimuth); 384 azimuth = Math.cos(lat2) * Math.sin(lon2 - lon1) / azimuth; 385 azimuth = Math.asin(azimuth) * 180 / Math.PI; 386 if (Double.isNaN(azimuth)) { 387 if (lon1 < lon2) { 388 azimuth = 90.0; 389 } else { 390 azimuth = 270.0; 391 } 392 } 393 return azimuth; 394 } 395 396 /** 397 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度(计算结果有误) 398 * 399 * @param lon1 400 * A的经度 401 * @param lat1 402 * A的纬度 403 * @param distance 404 * AB距离(单位:米) 405 * @param azimuth 406 * AB方位角 407 * @return B的经纬度 408 * */ 409 public static String GetOtherPoint(double lon1, double lat1, 410 double distance, double azimuth) { 411 azimuth = rad(azimuth); 412 double ab = distance / EARTH_ARC;// AB间弧线长 413 ab = rad(ab); 414 double Lat = Math.asin(Math.sin(lat1) * Math.cos(ab) + Math.cos(lat1) 415 * Math.sin(ab) * Math.cos(azimuth)); 416 double Lon = lon1 417 + Math.asin(Math.sin(azimuth) * Math.sin(ab) / Math.cos(Lat)); 418 System.out.println(Lon + "," + Lat); 419 420 double a = Math.acos(Math.cos(90 - lon1) * Math.cos(ab) 421 + Math.sin(90 - lon1) * Math.sin(ab) * Math.cos(azimuth)); 422 double C = Math.asin(Math.sin(ab) * Math.sin(azimuth) / Math.sin(a)); 423 System.out.println("c=" + C); 424 double lon2 = lon1 + C; 425 double lat2 = 90 - a; 426 return lon2 + "," + lat2; 427 } 428 429 /** 430 * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度 431 * 432 * @param lon1 433 * A的经度 434 * @param lat1 435 * A的纬度 436 * @param distance 437 * AB距离(单位:米) 438 * @param azimuth 439 * AB方位角 440 * @return B的经纬度 441 * */ 442 public static String ConvertDistanceToLogLat(double lng1, double lat1, 443 double distance, double azimuth) { 444 azimuth = rad(azimuth); 445 // 将距离转换成经度的计算公式 446 double lon = lng1 + (distance * Math.sin(azimuth)) 447 / (EARTH_ARC * Math.cos(rad(lat1))); 448 // 将距离转换成纬度的计算公式 449 double lat = lat1 + (distance * Math.cos(azimuth)) / EARTH_ARC; 450 return lon + "," + lat; 451 } 452 453 public static void main(String[] args) { 454 double lon1 = 121.469156; 455 double lat1 = 31.232307; 456 double lon2 = 121.469156; 457 double lat2 = 31.233205; 458 double distance = GetDistanceTwo(lon1, lat1, lon2, lat2); 459 double azimuth = GetAzimuth(lon1, lat1, lon2, lat2); 460 System.out.println("经纬度为(" + lon1 + "," + lat1 + ")的点与经纬度为(" + lon2 461 + "," + lat2 + ")相距:" + distance + "千米," + "方位角:" + azimuth 462 + "°"); 463 System.out.println("距经纬度为(" + lon1 + "," + lat1 + ")的点" + distance 464 + "千米,方位角为" + azimuth + "°的另一点经纬度为(" 465 + ConvertDistanceToLogLat(lon1, lat1, distance, azimuth) + ")"); 466 } 467 }