GPS 위치와 가까운 지점을 어떻게 그룹화합니까?


10

저는 IT 담당자이므로 프로젝션에 대해 너무 많이 알지 못하므로 도와주세요.

GPS 위치를 수집하는 Android 용 응용 프로그램을 만들었으므로 주어진 시간에 위도와 경도가 있습니다. I는 이러한 요소를 함께 저장할 근처 같은 phisical 크기의 지형 영역의 그룹으로, 서로를; 문제는 사전에 요점을 모른다는 것이며 세계 어느 곳에서나 올 수 있다는 것입니다 .

나의 첫 번째 아이디어 (문제를 조금 더 설명하기 위해)는 그룹화에 위도와 경도의 소수점을 사용하는 것이 었습니다. 예를 들어 한 그룹은 위도가 35.123에서 35.124 사이이고 경도가 60.101과 60.102 사이의 위치가됩니다. lat = 35.1235647 및 lon = 60.1012254598과 같은 위치를 얻으면이 지점이 해당 그룹으로 이동합니다.

이 솔루션은 직교 2D 표현에 적합합니다. 너비가 0.001 단위이고 넓이가 높기 때문입니다. 그러나 경도 1 도의 크기가 위도마다 다르기 때문에이 방법을 사용할 수 없습니다.

어떤 생각?


위치를 그대로 저장 한 다음 나중에 처리를 수행 할 수없는 이유는 무엇입니까? 또한 적도에서 1 경도는 약 111km이므로 0.001 도는 1Km보다 약간 큽니다. 당신은 정말로 당신의 쓰레기통을 너무 크게 원하십니까?
Devdatta Tengshe 1

0.001 도는 내 생각의 예일뿐입니다. 물론 요구 사항에 맞게 조정해야합니다. 나는 실시간 응용 프로그램이 될 계획이기 때문에 포스트 프로세싱을 할 수 없으며, 내 포인트를 그룹화해야하기 때문에 내일까지 기다려야한다고 말할 수는 없습니다 . 어쨌든 아이디어에 감사드립니다;)
Kuu

답변:


6

하나의 빠르고 더러운 방법은 재귀 구형 세분을 사용합니다 . 지구 표면의 삼각 측량으로 시작하여 각 삼각형을 정점에서 가장 긴 변의 중간으로 재귀 적으로 나눕니다. (사실 삼각형을 두 개의 동일한 직경 부분 또는 같은 면적의 부분으로 나눕니다.하지만 약간의 계산이 필요하기 때문에 측면을 정확히 반으로 나눕니다. 이로 인해 다양한 삼각형의 크기가 약간 달라 지지만 이 응용 프로그램에는 중요하지 않은 것 같습니다.)

물론이 세분화를 임의의 점이있는 삼각형을 빠르게 식별 할 수있는 데이터 구조로 유지합니다. 재귀 호출을 기반으로하는 이진 트리는 훌륭하게 작동합니다. 삼각형이 분할 될 때마다 트리는 해당 삼각형의 노드에서 분할됩니다. 분할 평면과 관련된 데이터가 유지되므로 임의의 점이있는 평면의 어느 쪽을 신속하게 결정할 수 있습니다. 트리를 왼쪽 또는 오른쪽으로 이동할지 여부가 결정됩니다.

(평면 분할을 말했습니까? 그렇습니다. 지구 표면을 구체로 모델링하고 지구 중심 (x, y, z) 좌표를 사용하는 경우 대부분의 계산은 3 차원으로 이루어지며 삼각형의 변이 원점을 통해 평면 과 구의 교차점을 계산하면 빠르고 쉽게 계산할 수 있습니다.)


나는 구체의 한 옥탄트에 대한 절차를 보여줌으로써 설명 할 것이다. 다른 7 개의 옥타 트도 같은 방식으로 처리됩니다. 그러한 낙타는 90-90-90 삼각형입니다. 내 그래픽에서는 같은 모서리에 걸쳐 유클리드 삼각형을 그릴 것입니다. 작아 질 때까지 잘 보이지 않지만 쉽고 빠르게 그릴 수 있습니다. 다음은 유족에 해당하는 유클리드 삼각형입니다. 그것은 절차의 시작입니다.

그림 1

모든 변의 길이가 같으므로 한 변이 "가장 긴"것으로 임의로 선택되고 세분됩니다.

그림 2

새로운 삼각형 각각에 대해 이것을 반복하십시오.

그림 3

n 단계 후에 2 ^ n 삼각형이 생깁니다. 10 단계 후의 상황은 다음과 같습니다. 8 각이 1024 개 (구체적으로는 전체 8192 개)로 표시됩니다.

그림 4

더 설명하기 위해, 나는이 octant 내에서 임의의 점을 생성하고 삼각형의 가장 긴 변이 0.05 라디안 미만에 도달 할 때까지 세분화 트리를 여행했습니다. (카테 시안) 삼각형은 프로브 포인트가 빨간색으로 표시됩니다.

그림 5

덧붙여 말하면, 한 지점의 위도를 대략 1도까지 좁히려면 약 1/60 라디안이므로 (1/60) ^ 2 / (Pi / 2) = 1/6000 정도입니다. 총 표면. 각 세분은 삼각형 크기의 약 절반이므로, 옥탄트의 약 13 ~ 14 세분이 트릭을 수행합니다. 아래에서 볼 수 있듯이 많은 계산이 아니므로 트리를 전혀 저장하지 않고 하위 분류를 즉시 수행하는 것이 효율적입니다. 처음에는 점이 어느 옥탄트에 있는지, 즉 3 자리 이진수로 기록 될 수있는 세 좌표의 부호에 의해 결정되며 각 단계에서 점이 있는지 여부를 기억하려고합니다. 삼각형의 왼쪽 (0) 또는 오른쪽 (1)에 다른 14 자리 이진수를 제공합니다. 이 코드를 사용하여 임의의 점을 그룹화 할 수 있습니다.

(일반적으로 두 개의 코드가 실제 이진수로 가까우면 해당 점이 가까워 지지만 점이 여전히 가까울 수 있으며 현저하게 다른 코드가있을 수 있습니다. 예를 들어, 1 미터 간격으로 Equator와 분리 된 두 점을 고려하십시오. 이진수 앞에 다른 옥탄트가 있기 때문에 고정 된 공간 분할에서는 피할 수 없습니다.)


Mathematica 8 을 사용 하여 이것을 구현했습니다. 선호하는 프로그래밍 환경에서 구현하기 위해 그대로 또는 의사 코드로 사용할 수 있습니다.

평면 0-ab 점 p 의 어느 쪽이 위치하는지 확인 합니다.

side[p_, {a_, b_}] := If[Det[{p, a, b}] >=  0, left, right];

점 p를 기준으로 삼각형 abc를 세분화합니다.

refine[p_, {a_, b_, c_}] := Block[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  If[side[p, {x, m}] === right, {y, m, x}, {x, m, z}] 
  ]

마지막 그림은 octant를 표시하고 그 위에 다음 목록을 다각형 세트로 렌더링하여 그려졌습니다.

p = Normalize@RandomReal[NormalDistribution[0, 1], 3]        (* Random point *)
{a, b, c} = IdentityMatrix[3] . DiagonalMatrix[Sign[p]] // N (* First octant *)
NestWhileList[refine[p, #] &, {a, b, c}, Norm[#[[1]] - #[[2]]] >= 0.05 &, 1, 16]

NestWhileListrefine조건이 관련되어 있거나 (삼각형이 클 때) 또는 최대 작업 횟수에 도달 할 때까지 (16) 작업을 반복해서 적용합니다 .

8 인의 완전한 삼각 분할을 나타 내기 위해, 나는 첫 번째 8 인간부터 시작하여 10 번 정련을 반복했습니다. 이것은 약간의 수정으로 시작됩니다 refine.

split[{a_, b_, c_}] := Module[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  {{y, m, x}, {x, m, z}}
  ]

차이점은 주어진 점이있는 것이 아니라 입력 삼각형의 반쪽 을 split반환 한다는 것입니다. 전체 삼각 분할은 다음을 반복하여 얻습니다.

triangles = NestList[Flatten[split /@ #, 1] &, {IdentityMatrix[3] // N}, 10];

확인하기 위해 모든 삼각형의 크기를 측정하고 범위를 보았습니다. (이 "크기"는 각 삼각형과 구의 중심이 차지하는 피라미드 모양의 도형에 비례합니다. 이와 같은 작은 삼각형의 경우이 크기는 기본적으로 구형 영역에 비례합니다.)

Through[{Min, Max}[Map[Round[Det[#], 0.00001] &, triangles[[10]] // N, {1}]]]

{0.00523, 0.00739}

따라서 크기는 평균보다 약 25 % 증가 또는 감소합니다. 이는 점을 그룹화하는 대략 균일 한 방법을 달성하는 데 합리적입니다.

이 코드를 스캔 할 때 삼각법없다는 것을 알 수 있습니다. 구면 좌표와 직교 좌표 간을 앞뒤로 변환하는 데 필요한 유일한 곳입니다. 이 코드는 또한 지구 표면을지도에 투영하지 않으므로 수반 왜곡을 피할 수 있습니다. 그렇지 않으면 평균화 ( Mean), 피타고라스 정리 ( Norm) 및 3 x 3 결정자 ( Det) 만 사용하여 모든 작업을 수행합니다. ( RotateLeftFlatten삼각형과 같은 가장 긴면을 검색하는 것과 같은 간단한 목록 조작 명령 도 있습니다.)


1

투영은 3D WGS84 지리 좌표계에서 평평한 2D 투영으로 갈 때 왜곡이 발생하기 때문에 어려운 작업입니다. 전 세계적으로 시스템 어딘가에 왜곡이 발생합니다.

가장 좋은 방법은 Universal Transverse Mercator 투영법으로 투영하는 것 입니다. 내가 아는 한 가장 적은 왜곡으로 글로벌 프로젝션을 얻을 수있는 가장 가까운 거리입니다.

실시간 처리 요구 사항뿐만 아니라 정확히 동일한 크기의 영역에서 그룹을 정의해야하는 요구 사항을 완화 할 수있는 경우 DBSCAN 과 같은 클러스터링 알고리즘 및 파생 상품 그룹이있어 그룹화를 생성하는 데 도움이됩니다.


1
UTM은 "전역 투영"이 아닙니다. 데모는 (500000, 5000000)과 같은 거의 모든 유효한 좌표 쌍이 UTM 시스템에서 적어도 120 개의 서로 다른 분리 된 점에 해당한다는 것입니다. 불행히도 클러스터링 알고리즘은 위치에 따라 (그리고 다른 지점과의 근접성이 아닌) 실시간으로 포인트를 그룹화 할 수 있어야하는 OP의 요구를 충족시키지 못합니다.
whuber

@ whuber re : "전역 투영"-맞습니다. 그렇기 때문에 "글로벌 프로젝션에 가장 가까운 곳"이라고 말했습니다. 더 적합한 프로젝션 시스템을 알고 있다면 의견에 남겨 주시면 답변을 편집하겠습니다. 또한 OP는 초기 게시물에 실시간 요구 사항이 없었습니다. 이것을 고려하여 답변을 편집하겠습니다.
Sean Barbeau

Sean, (1) 글로벌 예측 문제에 대한 나의 해결책은 하나를 사용하지 않는 것입니다. 특이점 이 없는 세계적인 전망은 없습니다. (2) 사실, 실시간 설명이 의견에 나타났습니다. "나의 첫 번째 아이디어"뒤에 나오는 텍스트는이 문제가 일련의 위치를 모으기 보다는 지구 표면 을 분할 하는 것 중 하나라는 점을 강조하면서 훌륭하게 작동 합니다. 그것이 내가 당신에게 이전에 언급 한 의견을 통해 (매우 효과적이지 않은) 지적을했던 요점입니다.
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.