GPS位置を使用して近接ポイントをグループ化するにはどうすればよいですか?


10

私はIT担当者なので、予測などについてあまり詳しくありません。

Android向けにGPS位置を収集するアプリケーションを作成したので、ある時点での緯度と経度がわかります。同じ物理サイズのテレインエリアのグループで、互いに近い要素を一緒に保存したいと思います。問題は、私が事前にポイントを知らないことであり、それらは世界のどの位置からでも来ることができます

私の最初のアイデア(問題をもう少し説明する)は、グループ化に緯度と経度の小数を使用することでした。たとえば、1つのグループは、緯度が35.123〜35.124、経度が60.101〜60.102の位置になります。したがって、lat = 35.1235647およびlon = 60.1012254598のような位置を取得した場合、このポイントはそのグループに移動します。

この解決策は、幅が0.001単位で高さが大きい領域があるため、デカルト2D表現には問題ありません。ただし、緯度によって経度1度のサイズが異なるため、この方法は使用できません。

何か案が?


位置をそのまま保存して、後で処理できないのはなぜですか?赤道でも経度1度は約111kmなので、0.001度は1km強になります。あなたは本当にあなたのビンをとても大きくしたいですか?
Devdatta Tengshe 2013年

0.001度は私のアイデアのほんの一例でした。もちろん、私はそれを要件に適合させなければなりません。リアルタイムアプリケーションになる予定なので、後処理を行うことができず、ユーザーに「ポイントをグループ化する必要があるため、明日まで待ちますとは言えません。とにかくアイデアをありがとう;)
Kuu

回答:


6

迅速で汚れた方法の1つは、再帰的な球状サブディビジョンを使用します。地表の三角形分割から始めて、各三角形を頂点からその最長辺の中央まで再帰的に分割します。(理想的には、三角形を2つの等しい直径の部分または等しい面積の部分に分割しますが、それらは面倒な計算を伴うため、辺をちょうど半分に分割します。これにより、さまざまな三角形のサイズが最終的に少し異なりますが、これは、このアプリケーションにとって重要ではないと思われます。)

もちろん、このサブディビジョンをデータ構造で維持することで、任意の点が存在する三角形をすばやく識別できるようになります。バイナリツリー(再帰呼び出しに基づく)はうまく機能します。三角形が分割されるたびに、ツリーはその三角形のノードで分割されます。分割平面に関するデータが保持されるため、任意の点が平面のどちら側にあるかをすばやく判断できます。これにより、ツリーを左または右に移動するかどうかが決まります。

(「平面」を分割すると言いましたか?はい-地球の表面を球体としてモデル化し、地理中心(x、y、z)座標を使用する場合、ほとんどの計算は3次元で行われ、三角形の辺は球とその原点を通る平面の交差。これにより、計算が迅速かつ簡単になります。)


球の1つのオクタントでの手順を示して説明します。他の7つのオクタントは同じ方法で処理されます。そのような八分円は、90-90-90の三角形です。私のグラフィックスでは、同じコーナーにまたがるユークリッド三角形を描画します。それらは、小さくなるまで見栄えがよくありませんが、簡単かつ迅速に描画できます。八分円に対応するユークリッド三角形は次のとおりです。これが手順の始まりです。

図1

すべての辺の長さが等しいため、「最長」としてランダムに選択され、細分化されます。

図2

新しい三角形のそれぞれについて、これを繰り返します。

図3

nステップ後、2 ^ n個の三角形ができます。これは、10ステップ後の状況で、オクタントに1024個の三角形(および球全体に8192個)を示しています。

図4

もう1つの例として、このオクタント内にランダムなポイントを生成し、三角形の最も長い辺が0.05ラジアン未満になるまでサブディビジョンツリーを移動しました。(デカルト)三角形は、プローブポイントが赤で表示されます。

図5

ちなみに、ポイントの位置を1度の緯度(およそ)に狭めると、これは約1/60ラジアンであり、約(1/60)^ 2 /(Pi / 2)= 1/6000をカバーすることに注意してください。全表面。各サブディビジョンは三角形のサイズを約半分にするので、オクタントの約13〜14サブディビジョンでうまくいきます。以下で説明するように、これはあまり計算ではありません。ツリーをまったく保存せずに、その場でサブディビジョンを実行するのが効率的です。最初に、ポイントがどのオクタントにあるかを確認します。これは、3桁の2進数として記録できる3つの座標の符号によって決定されます。各ステップで、ポイントが存在するかどうかを覚えておきます。三角形の左側(0)または右側(1)。これにより、別の14桁の2進数が得られます。 これらのコードを使用して、任意のポイントをグループ化できます。

(一般的に、2つのコードが実際の2進数に近い場合、対応するポイントは近くなりますが、ポイントは依然として近く、コードが著しく異なる場合があります。たとえば、赤道から1メートル離れた2つのポイントを考えます。たとえば、コードは異なる必要がありますバイナリポイントの前。これらは異なるオクタントにあるため。この種のことは、スペースの固定パーティションで避けられません。)


私は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}] 
  ]

最後の図は、オクタントを表示することによって、さらにその上に、次のリストをポリゴンのセットとしてレンダリングすることによって描かれました。

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)、操作を繰り返し適用します()。

オクタントの完全な三角測量を表示するために、最初のオクタントから始めて、精製を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)のみを使用してすべての作業を行います。(RotateLeftおよびのようないくつかの単純なリスト操作コマンドとFlatten、各三角形の最も長い辺の検索があります。)


1

3D WGS84地理座標系からフラットな2D投影に移行すると、投影によって歪みが生じるため、これは難しいものです。グローバルな規模では、システムのどこかに歪みが生じることになります。

あなたの最善の策は、ユニバーサル横メルカトル図法に投影することだと思います。私が知る限り、これは最も歪みが少ないグローバル投影に到達できる最も近いものです。

グループを正確に同じサイズの領域で定義する必要があるという要件と、リアルタイム処理の要件を緩和できる場合は、DBSCANなどのクラスタリングアルゴリズムと、グループ化の生成に役立つ派生クラスのファミリーがあります。


1
UTMは「グローバル投影」ではありません。デモンストレーションは、(500000、5000000)などの有効な座標のほぼすべてのペアが、UTMシステム内の少なくとも120個の明確に離れたポイントに対応することを示しています。そして、残念ながら、クラスタリングアルゴリズムは、(他のポイントへの近接性ではなく)ロケーションのみに基づいてリアルタイムでポイントをグループ化できるというOPのニーズを満たしていません。
whuber

@whuber re: "グローバルプロジェクション"-そうです。だから、「世界の予測に最も近い」と言ったのです。より適切なより適切なプロジェクションシステムをご存知の場合は、コメント欄に残してください。回答を編集します。また、OPには最初の投稿でのリアルタイム要件はありませんでした。これを考慮に入れるように回答を編集します。
Sean Barbeau 2013年

Sean、(1)私のグローバルな投影問題の解決策は、使用しないことです。特異点のないグローバルな予測は存在しません。(2)確かに、リアルタイムの説明がコメントに表示されました。「私の最初のアイデア」に続くテキストは、この問題が、一連の場所をクラスター化するのではなく、地表を分割することの1つであることを強調して、うまく機能します。それが、私が(あまり効果的ではないが)先ほどのコメントで伝えようとしていた点です。
whuber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.