GPS를 이용한 두지점간 거리계산 방법입니다.
안드로이드에서 기본적으로 제공해주는 직선거리 구하는 방법
지구는 타원으로 되어있기에 가까운지역인 경우 오차가 없지만,
거리가 멀어지면 오차가 발생하는걸 알 수 있습니다.
방법1.
double distance;
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
방법2.
float[] results = new float[3]; Location location = new Location("start"); location.distanceBetween( startLatitude, startLongitude, endLatitude, endLongitude, results); Sring mes = Float.toString(results[0]); =============================================================================== The computed distance is stored in results[0].
If results has length 2 or greater, the initial bearing is stored in results[1].
If results has length 3 or greater, the final bearing is stored in results[2].
국토지리원에서 공개한 거리계산 함수 사용하기.
지구는 완전한 구라는 가정하에 지구를 GRS80타원체로 봤을경우
두지점간 거리와 방위각 구하는 소스
//거리 구하는 부분
public double distance(double P1_latitude, double P1_longitude,
double P2_latitude, double P2_longitude) {
if ((P1_latitude == P2_latitude) && (P1_longitude == P2_longitude)) {
return 0;
}
double e10 = P1_latitude * Math.PI / 180;
double e11 = P1_longitude * Math.PI / 180;
double e12 = P2_latitude * Math.PI / 180;
double e13 = P2_longitude * Math.PI / 180;
/* 타원체 GRS80 */
double c16 = 6356752.314140910;
double c15 = 6378137.000000000;
double c17 = 0.0033528107;
double f15 = c17 + c17 * c17;
double f16 = f15 / 2;
double f17 = c17 * c17 / 2;
double f18 = c17 * c17 / 8;
double f19 = c17 * c17 / 16;
double c18 = e13 - e11;
double c20 = (1 - c17) * Math.tan(e10);
double c21 = Math.atan(c20);
double c22 = Math.sin(c21);
double c23 = Math.cos(c21);
double c24 = (1 - c17) * Math.tan(e12);
double c25 = Math.atan(c24);
double c26 = Math.sin(c25);
double c27 = Math.cos(c25);
double c29 = c18;
double c31 = (c27 * Math.sin(c29) * c27 * Math.sin(c29))
+ (c23 * c26 - c22 * c27 * Math.cos(c29))
* (c23 * c26 - c22 * c27 * Math.cos(c29));
double c33 = (c22 * c26) + (c23 * c27 * Math.cos(c29));
double c35 = Math.sqrt(c31) / c33;
double c36 = Math.atan(c35);
double c38 = 0;
if (c31 == 0) {
c38 = 0;
} else {
c38 = c23 * c27 * Math.sin(c29) / Math.sqrt(c31);
}
double c40 = 0;
if ((Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38))) == 0) {
c40 = 0;
} else {
c40 = c33 - 2 * c22 * c26
/ (Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38)));
}
double c41 = Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38))
* (c15 * c15 - c16 * c16) / (c16 * c16);
double c43 = 1 + c41 / 16384
* (4096 + c41 * (-768 + c41 * (320 - 175 * c41)));
double c45 = c41 / 1024 * (256 + c41 * (-128 + c41 * (74 - 47 * c41)));
double c47 = c45
* Math.sqrt(c31)
* (c40 + c45
/ 4
* (c33 * (-1 + 2 * c40 * c40) - c45 / 6 * c40
* (-3 + 4 * c31) * (-3 + 4 * c40 * c40)));
double c50 = c17
/ 16
* Math.cos(Math.asin(c38))
* Math.cos(Math.asin(c38))
* (4 + c17
* (4 - 3 * Math.cos(Math.asin(c38))
* Math.cos(Math.asin(c38))));
double c52 = c18
+ (1 - c50)
* c17
* c38
* (Math.acos(c33) + c50 * Math.sin(Math.acos(c33))
* (c40 + c50 * c33 * (-1 + 2 * c40 * c40)));
double c54 = c16 * c43 * (Math.atan(c35) - c47);
// return distance in meter
return c54;
}
//방위각 구하는 부분
public short bearingP1toP2(double P1_latitude, double P1_longitude,
double P2_latitude, double P2_longitude) {
// 현재 위치 : 위도나 경도는 지구 중심을 기반으로 하는 각도이기 때문에
//라디안 각도로 변환한다.
double Cur_Lat_radian = P1_latitude * (3.141592 / 180);
double Cur_Lon_radian = P1_longitude * (3.141592 / 180);
// 목표 위치 : 위도나 경도는 지구 중심을 기반으로 하는 각도이기 때문에
// 라디안 각도로 변환한다.
double Dest_Lat_radian = P2_latitude * (3.141592 / 180);
double Dest_Lon_radian = P2_longitude * (3.141592 / 180);
// radian distance
double radian_distance = 0;
radian_distance = Math.acos(Math.sin(Cur_Lat_radian)
* Math.sin(Dest_Lat_radian) + Math.cos(Cur_Lat_radian)
* Math.cos(Dest_Lat_radian)
* Math.cos(Cur_Lon_radian - Dest_Lon_radian));
// 목적지 이동 방향을 구한다.(현재 좌표에서 다음 좌표로 이동하기 위해서는
//방향을 설정해야 한다. 라디안값이다.
double radian_bearing = Math.acos((Math.sin(Dest_Lat_radian) - Math
.sin(Cur_Lat_radian)
* Math.cos(radian_distance))
/ (Math.cos(Cur_Lat_radian) * Math.sin(radian_distance)));
// acos의 인수로 주어지는 x는 360분법의 각도가 아닌 radian(호도)값이다.
double true_bearing = 0;
if (Math.sin(Dest_Lon_radian - Cur_Lon_radian) < 0) {
true_bearing = radian_bearing * (180 / 3.141592);
true_bearing = 360 - true_bearing;
} else {
true_bearing = radian_bearing * (180 / 3.141592);
}
return (short) true_bearing;
}
이외 거리 구하는 참고자료는 첨부파일 참고해주세요~
출처 - http://sunmo.blogspot.kr/2010/12/android-gps-%EC%9C%84%EB%8F%84%EA%B2%BD%EB%8F%84%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%91%90%EC%A7%80%EC%A0%90-%EA%B1%B0%EB%A6%AC%EA%B3%84%EC%82%B0-%EC%B4%9D%EC%A7%91%ED%95%A9.html
public double distance(double P1_latitude, double P1_longitude, double P2_latitude, double P2_longitude) { if ((P1_latitude == P2_latitude) && (P1_longitude == P2_longitude)) { return 0; } double e10 = P1_latitude * Math.PI / 180; double e11 = P1_longitude * Math.PI / 180; double e12 = P2_latitude * Math.PI / 180; double e13 = P2_longitude * Math.PI / 180; /* 타원체 GRS80 */ double c16 = 6356752.314140910; double c15 = 6378137.000000000; double c17 = 0.0033528107; double f15 = c17 + c17 * c17; double f16 = f15 / 2; double f17 = c17 * c17 / 2; double f18 = c17 * c17 / 8; double f19 = c17 * c17 / 16; double c18 = e13 - e11; double c20 = (1 - c17) * Math.tan(e10); double c21 = Math.atan(c20); double c22 = Math.sin(c21); double c23 = Math.cos(c21); double c24 = (1 - c17) * Math.tan(e12); double c25 = Math.atan(c24); double c26 = Math.sin(c25); double c27 = Math.cos(c25); double c29 = c18; double c31 = (c27 * Math.sin(c29) * c27 * Math.sin(c29)) + (c23 * c26 - c22 * c27 * Math.cos(c29)) * (c23 * c26 - c22 * c27 * Math.cos(c29)); double c33 = (c22 * c26) + (c23 * c27 * Math.cos(c29)); double c35 = Math.sqrt(c31) / c33; double c36 = Math.atan(c35); double c38 = 0; if (c31 == 0) { c38 = 0; } else { c38 = c23 * c27 * Math.sin(c29) / Math.sqrt(c31); } double c40 = 0; if ((Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38))) == 0) { c40 = 0; } else { c40 = c33 - 2 * c22 * c26 / (Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38))); } double c41 = Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38)) * (c15 * c15 - c16 * c16) / (c16 * c16); double c43 = 1 + c41 / 16384 * (4096 + c41 * (-768 + c41 * (320 - 175 * c41))); double c45 = c41 / 1024 * (256 + c41 * (-128 + c41 * (74 - 47 * c41))); double c47 = c45 * Math.sqrt(c31) * (c40 + c45 / 4 * (c33 * (-1 + 2 * c40 * c40) - c45 / 6 * c40 * (-3 + 4 * c31) * (-3 + 4 * c40 * c40))); double c50 = c17 / 16 * Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38)) * (4 + c17 * (4 - 3 * Math.cos(Math.asin(c38)) * Math.cos(Math.asin(c38)))); double c52 = c18 + (1 - c50) * c17 * c38 * (Math.acos(c33) + c50 * Math.sin(Math.acos(c33)) * (c40 + c50 * c33 * (-1 + 2 * c40 * c40))); double c54 = c16 * c43 * (Math.atan(c35) - c47); // return distance in meter return c54; } public short bearingP1toP2(double P1_latitude, double P1_longitude, double P2_latitude, double P2_longitude) { // 현재 위치 : 위도나 경도는 지구 중심을 기반으로 하는 각도이기 때문에 라디안 각도로 변환한다. double Cur_Lat_radian = P1_latitude * (3.141592 / 180); double Cur_Lon_radian = P1_longitude * (3.141592 / 180); // 목표 위치 : 위도나 경도는 지구 중심을 기반으로 하는 각도이기 때문에 라디안 각도로 변환한다. double Dest_Lat_radian = P2_latitude * (3.141592 / 180); double Dest_Lon_radian = P2_longitude * (3.141592 / 180); // radian distance double radian_distance = 0; radian_distance = Math.acos(Math.sin(Cur_Lat_radian) * Math.sin(Dest_Lat_radian) + Math.cos(Cur_Lat_radian) * Math.cos(Dest_Lat_radian) * Math.cos(Cur_Lon_radian - Dest_Lon_radian)); // 목적지 이동 방향을 구한다.(현재 좌표에서 다음 좌표로 이동하기 위해서는 방향을 설정해야 한다. 라디안값이다. double radian_bearing = Math.acos((Math.sin(Dest_Lat_radian) - Math.sin(Cur_Lat_radian) * Math.cos(radian_distance)) / (Math.cos(Cur_Lat_radian) * Math.sin(radian_distance))); // acos의 인수로 주어지는 x는 360분법의 각도가 아닌 radian(호도)값이다. double true_bearing = 0; if (Math.sin(Dest_Lon_radian - Cur_Lon_radian) < 0) { true_bearing = radian_bearing * (180 / 3.141592); true_bearing = 360 - true_bearing; } else { true_bearing = radian_bearing * (180 / 3.141592); } return (short)true_bearing; }
출처 - http://blog.daum.net/haha25/5387990
'OpenSource > Map' 카테고리의 다른 글
map - WGS84와 GRS80의 차이 (0) | 2012.08.26 |
---|---|
map - 국토지리정보원, 최신 항공사진 분기별 공개 및 Open API 서비스 실시 (0) | 2012.08.26 |
map - 위도 경도로 거리계산 (0) | 2012.08.26 |
경도/위도 좌표 값으로 거리 계산 (0) | 2012.07.17 |
JAVASCRIPT - Daum Map API를 사용해서 좌표 -> 주소 변환하기 (0) | 2012.05.27 |