가장 가까운 점을 찾기위한 알고리즘


18

위도 / 경도가있는 수백 개의 도시 목록이 있습니다. 다른 위치 (위도 / 경도)가 주어지면 가장 가까운 도시를 찾아야합니다.

내가 GIS를 사용하지 않기 때문에, 이제 명백한 알고리즘은 모든 도시에 대해 루프를 만들어 점 사이의 거리를 계산하는 것입니다.

루프를 만드는 것은 실용적이지만 더 효율적으로 알고리즘을 구현하는 것이 있습니까? 아니면 그것을 해결하는 데 도움이되는 가벼운 Java 라이브러리가 있습니까?

참고 사항 : 완전한 GIS 솔루션이나 무겁고 복잡한 라이브러리가 필요하지 않습니다. 나는 그것이 해결해야 할 유일한 것이므로 덜 좋지만 가장 쉽고 가벼운 솔루션을 선호합니다.


거리가 정확하지 않더라도 상관 없습니다. 그리고 한 도시를 다른 도시보다 더 크게 만들 수있는 도로 (대 각형 대 사각형)를 고려하고 싶지 않습니까?
브래드 네섬

예, 도로는 나에게 중요하지 않습니다. 날씨 예측을 위해 선형 거리에서 가장 가까운 도시가 필요합니다.
lujop

1
일기 예보? 수퍼 컴퓨터와 숙련 된 기상학자가 여러분의 처분에 따라 주시기 바랍니다.
Michael Todd

예측은 마이클에서 이루어집니다. 가장 가까운 것을 취해야합니다. :)
lujop

답변:


24

데스크탑 GIS를 설계 할 때 20 년 전에이 질문을 정확히 조사했습니다. 지점 간 거리를 대화식으로 찾아야했습니다. 우리의 목표는 수천 포인트에 대해 1/2 초 이내에 계산을 수행하는 것이 었습니다. 테스트 (25 MHz 486 PC에서!)는 우리가 설명 한대로 (간단한 명백한 알고리즘으로) 모든 거리를 계산할 수 있었으므로 쿼드 트리 구조와 같은보다 정교한 솔루션을 만드는 것은 의미가 없었습니다. .

단일 "프로브"포인트까지의 거리를 계산하려면 옵션에 (a) 프로브 포인트를 중심으로하는 등거리 투영을 사용하여 모든 포인트를 투영하거나 (b) 구형 지구 모델을 채택하고 Haversine 공식을 사용합니다 . 첫 번째는 타원체 모델의 정확도가 필요한 경우에 적합합니다. 두 경우 모두 계산 속도가 합리적으로 빠르며 아마도 1000 틱 미만이 걸릴 수도 있습니다. 단일 프로세서로 초당 약 백만 점을 쿼리 할 수 ​​있습니다.

당신을 위해 충분히 빨리? 그렇지 않은 경우 무차별 강제 방법은 쉽게 병렬화되고 프로세서 수에 따라 직접 확장됩니다. 프로세서간에 점을 나누고 각 프로세서에서 찾은 가장 가까운 점을 최종 비교합니다.

더 빠르게 진행해야하는 경우 다양한 근사값을 사용하여 화면 포인트를 표시 할 수 있습니다. 예를 들어, 위도가 -88도에서 +88도 사이이고 지금까지 가장 가까운 지점이 200km 떨어진 경우 위도가 프로브 포인트의 위도와 2도 이상 다른 지점은 더 가까이있을 수 없습니다 ( 지구의 위도는 약 110km를 초과합니다). 대부분의 경우 이러한 종류의 사전 심사를 통해 초당 수억 개의 포인트를 처리 할 수 ​​있습니다.


1
haversine 공식에 대한 설명
whuber를

4

나는 간단한 루프가 "수백 도시"에 효과적이어야한다는 것에 동의합니다.

응용 프로그램이 주어지면 타원체 거리를 다루는 것이 아마도 과도한 일이 될 것입니다. 아마도 몇 미터 정도의 지역이 거의없는 일기 예보를 다루고있을 것입니다. 구형 형상은 루프에서 쉽게 수행 할 수있을 정도로 단순합니다.

더 간단 할 수 있습니다 (예 : delta lat을 y로 사용하고 delta lon * cos (lat)을 x로 사용하고 최소 x ^ 2 + y ^ 2를 찾으십시오). 대상 위도의 코사인을 사용하고 있으며 한 번만 계산합니다. 이것은 먼 도시들에게는 점점 부정확 할 것이지만, 어쨌든 거부 될 것이기 때문에 중요하지 않습니다. 가장 가까운 도시가 일반적으로 수백 킬로미터 내에 있다고 가정하면이 결과를 사용하는 것과 다른 정확한 결과를 사용하는 다른 결과 (가장 가까운 도시)의 가능성은 매우 작으며 차이가 충분히 작아서 "예측이 더 많을 때"만 발생합니다 정확한 "는 어쨌든 다른 요소들에 의존 할 것입니다 (예 : 잡음 손실).

임베디드 시스템이나 느린 통역사를 사용하지 않는 한 다른 사람들이 제안한 구형 형식을 사용할 수 있습니다.


1

이것은 이미 말한 것 외에도 적절한 데이터 구조를 선택하는 것이 중요하다고 생각했습니다. .NET에서 K-Function에 대한 자체 코드를 작성했으며 효율적인 컬렉션을 사용하면 실제로 속도가 빨라졌습니다. 정확한 속도에 대한 O 표기법을 모르겠습니다. 포인트 ID를 키로 사용하여 x 및 y 좌표에 대해 두 개의 사전을 사용했습니다. 나는 Java를 모른다. 그래서 아무것도 제안 할 수 없었다.

건배, 데이비드

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.