2016-08-25 5 views
0

사용자 지정 지점에서 가까운 위치 (300m)를 찾는 서비스가 있습니다.위도와 경도 제한 받기

나는 위치 https://en.wikipedia.org/wiki/Haversine_formula

내 문제는 지점 근처에 있는지 확인하는 하버 사인 공식을 사용하고는 내 DB의 모든 포인트에 대해 확인 이후가 느린 것입니다.

내가 원하는 것은 초기 쿼리를 제한하고 더 좁은 경계 영역에있는 포인트 목록에 haversine 수식을 적용하는 것입니다. 예 : 012ers

results = (SELECT * FROM location WHERE location.latitude BETWEEN 14.223 AND 14.5) 
AND location.longitude BETWEEN 121.5 AND 122 

haversine(results, user_point) 

주어진 지점에서 범위를 벗어나는 느슨한 방법이 있습니까? 또는 기본적으로 위도/경도가 미터로 더티 변환 되나요? 구형 지구의 근사

답변

1

데이터베이스 구조를 수정할 수있는 경우 위도와 경도를 저장하는 대신 (또는 추가하여) 위치 좌표를 3D 공간으로 변환하고 x, y, z는 미터 단위입니다. 그럼 그냥 할 수있어

이렇게하면 목록을 잘 다듬을 수 있으며 결과 세트에서 haversine 계산을 수행 할 수 있습니다.


위도와 경도 만있는 데이터베이스를 사용하는 경우 검색 범위를 좁힐 수 있습니다. 위도는 쉽습니다. 극지방에 가까워 질 때 발생하는 합병증을 무시하면 북쪽 또는 남쪽으로 1도 정도의 위도가 항상 111km에 해당합니다. 그것은 300m의 거리가 위도의 0.0027 ... 도인 것을 의미합니다. 물론 약간 보수적 일 수도 있고 0.003 또는 0.004를 사용할 수도 있습니다.

북쪽이나 남쪽에 따라 변환 요소가 달라지기 때문에 경도는 다소 까다 롭습니다.하지만 여전히 복잡하지는 않습니다. 위도의 코사인을 곱하면됩니다.

distance = cos(latitude) * 111.19... km/degree * delta_angle 

적도에서, 위도와 같습니다 : 적도의 경도에서 1도 변경은 111km입니다.북쪽 (또는 남쪽)의 80도에서 cos(80 degrees) = 0.17...의 계수를 곱하면 경도의 1도 변화는 19.3km에 불과합니다. 귀하의 목적을 위해 이것을 뒤집어서 경도의 범위를 찾아 300 m/cos(latitude)/(111.19... km/degree) = (0.0027... degrees)/cos(latitude)으로 선택할 수 있습니다. 그 계수는 첫 번째 단락과 같은 양입니다. 그것은 우연이 아닙니다.

극한 문제는 좌표계의 불연속 근처에서 발생합니다 (예 : 극에 가까워지는 경우).

0.0027... degrees/cos(89.9996 degrees) = 386... degrees 

글쎄, 어떻게 360도 전체적으로 원형 만있을 때 할 수있다 : 당신이 89.9996도 같은 위도에 연결 시작할 때 이유를 볼 수 있습니까? 이것은 300m 반경이 기둥 주위로 뻗어 있고 말하기의 방식으로 출발점을 포함하도록 되돌아 왔음을 나타냅니다. 이 시점에서 데이터베이스의 모든 지점을 기둥 가까이에서 검색하면됩니다. 물론, 89.999도 정도에서 시작해야합니다. 왜냐하면 여러분이 찾고있는 지역의 직경 600m 지름이 완전히 극을 감싸고 있기 때문입니다.

국제 날짜 표시 줄, 또는 더 정확하게는 "antimeridian"에 경도 -180도에서 +180도까지의 점프와 관련하여 또 다른 문제가 있습니다. 적도에있는 +179.9999도와 -179.9999 도의 지점은 지리적으로 단지 몇 미터 떨어져 있더라도 매우 다른 좌표를 갖습니다. 더 자세한 검색을위한 예비 필터로 이것을 수행하고 있기 때문에 아마도 antimeridian의 0.006도 (대략 300m 반경 원의 직경) 내의 모든 지점을 통과 한 다음 haversine을 통과하는 것이 가장 쉽습니다 계산에 따라 포인트가 실제로 닫혀 있는지 여부가 결정됩니다.

요약하면 위에서 언급 한 위도와 경도의 범위를 사용할 수 있으며 극점과 반 평균량의 특수한 경우를 추가하면됩니다. 의사 SQL/코드 하이브리드의 어떤 종류에서 :

IF abs(center.latitude) > 89.999 
    SELECT * FROM location WHERE abs(location.latitude - center.latitude) < 0.003 
ELSE 
    IF abs(center.longitude) > 179.997 
    SELECT * FROM location 
     WHERE abs(location.latitude - center.latitude) < 0.003 
     AND 180 - abs(location.longitude) < (0.006/cos(center.latitude)) 
    ELSE 
    SELECT * FROM location 
     WHERE abs(location.latitude - center.latitude) < 0.003 
     AND abs(location.longitude - center.longitude) < (0.003/cos(center.latitude)) 
    ENDIF 
ENDIF 

당신은 많은 점수, 당신은 경도의 절대 값을 비교할 수 있습니다 두 번 잠재적으로 테스트해야하는 비용에서 골수 문하려면 다음

SELECT * FROM location 
    WHERE abs(location.latitude - center.latitude) < 0.003 
    AND abs(abs(location.longitude) - abs(center.longitude)) <= min(0.003/cos(center.latitude), 180) 
0

개의 연속 위도 사이의 거리 r 지구의 반경

dPerLat = pi * r/180°, 

의해 계산 될 수있다. 이것은 대략 111 킬로미터 일 것이다. 당신의 기준점 (lat, long)하고 검색 반경 당신이

lat* \in [lat - d/dPerLat, lat + d/dPerLat] 

그런 범위에서 위도을 검색하려면 다음 d 경우

따라서, 주어진 위도를 들어, 연속 경도의 거리입니다

dPerLong = pi * r * cos(lat)/180° 

다시 경도 범위는 +- d/dPerLong입니다. 보수적 인 (최대) 범위, 즉 가장 높은 절대 값을 가진 lat 값을 제공하는 lat 값을 사용해야합니다.

극점에주의하십시오.