데이터베이스 구조를 수정할 수있는 경우 위도와 경도를 저장하는 대신 (또는 추가하여) 위치 좌표를 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)