高速2次元検索には、どのようなアルゴリズム/データレイアウトを使用すればよいですか?

現在位置(緯度、経度)を取得し、リスト内の最も近い数点に関するカスタムシリアルデータを出力する組み込みデバイスを構築したいと思います。

  • 現在地とカスタムデータを保持する点は緯度と経度で表されますが、前処理で別の座標系に投影することもできます。

  • 最も近いものは正確すぎる必要はありません。ポイントはかなりまばらで、一般的には数十マイル離れていますが、2つのポイントが近くにある場合は、どちらの順番で表示されていてもあまり問題になりません。 p>

  • 定期的に更新されますが、このリストは静的であることを意図しています。動的な変更はありません。

私は現在GPS/SDカードシールド付きのArduinoを使用することを考えていますが、徹底的な検索を必要としないデータを保存するための賢明な方法を考え出すのに苦労しています。メモリ)。

これを行うための共通のパターンはありますか?明らかにpostgisなどがこの種のことをしますが、Arduinoを実行するにはあまりにも膨大であり、同様のテクニックは同じ問題を抱えます。

私はツリー検索などをするためにある種の前処理を行う必要があると思っていますが、これが複数の次元でどのように機能するかはわかりません。

1]

6
追加された 著者 sgwill,
追加された 著者 sgwill,
@ Martinの質問に答えがありそうな場合、その答えはR-TreeまたはQuad Treeです。
追加された 著者 user19639,
これはより多くの情報を必要とします:ポイントはどのように表されますか?二次元座標?ユークリッド距離は「最も近い」かポイントを保持している構造を変更する必要がありますか(動的)、それとも静的ですか? 「最近点」の数は可変である必要がありますか、それとも常に10ですか。
追加された 著者 Martin Sugioarto,
Martinのコメントに従って質問が更新されました
追加された 著者 Mat,

6 答え

現在の位置を一連の既知のポイントと照合していると仮定すると、ポイントを QuadTree に保存するとカットされるはずです。検索時間をO(log n)まで下げます。

細分化が巧妙で、5〜10個のアイテムを葉に格納することで、メモリスペースの点でも効率的になります。

9
追加された

Zオーダー曲線は、低メモリ、低パフォーマンスの状況での4分木の便利な表現です。

基本的に、それはあなたのポイントの一次元の順序を計算します、そしてそれは局所性を保存します。どこから始めればよいかがわかったら、メモリ内を直線的に検索し、検索範囲内にないエントリをスキップします。 Wikipediaにその方法の説明があります

これはあなたに四分木を維持するフックをつかむかもしれません。

3
追加された

k -dツリーが適しているようですこの問題のために。特に、最近傍検索は比較的簡単です。

The nearest neighbour search (NN) algorithm aims to find the point in the tree that is nearest to a given input point. This search can be done efficiently by using the tree properties to quickly eliminate large portions of the search space.

Searching for a nearest neighbour in a k-d tree proceeds as follows:

  1. Starting with the root node, the algorithm moves down the tree recursively, in the same way that it would if the search point were being inserted (i.e. it goes left or right depending on whether the point is lesser than or greater than the current node in the split dimension).

  2. Once the algorithm reaches a leaf node, it saves that node point as the "current best"

  3. The algorithm unwinds the recursion of the tree, performing the following steps at each node:

    1. If the current node is closer than the current best, then it becomes the current best.

    2. The algorithm checks whether there could be any points on the other side of the splitting plane that are closer to the search point than the current best. In concept, this is done by intersecting the splitting hyperplane with a hypersphere around the search point that has a radius equal to the current nearest distance. Since the hyperplanes are all axis-aligned this is implemented as a simple comparison to see whether the distance between the splitting coordinate of the search point and current node is lesser than the distance (overall coordinates) from the search point to the current best.

      1. If the hypersphere crosses the plane, there could be nearer points on the other side of the plane, so the algorithm must move down the other branch of the tree from the current node looking for closer points, following the same recursive process as the entire search.

      2. If the hypersphere doesn't intersect the splitting plane, then the algorithm continues walking up the tree, and the entire branch on the other side of that node is eliminated.

  4. When the algorithm finishes this process for the root node, then the search is complete.

上記の k -dツリーを格納するために適切に検索可能なフラットファイルフォーマットを作成することは読者のための課題として残されています。

3
追加された

私は特別な地理的索引付け機能なしで共通のデータベースに対してこの種の検索を実装しました。トリックは可能な領域を絶えず増加するズームレベルでタイルに分割することです。たとえば、ズームレベル0では、タイル0が表示されます。ズームレベル1では、タイル1、2、3、4が表示されます。ズームレベル2では、タイル5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20があります。したがって、ズームレベルNの各タイルは、ズームレベルN + 1の4つの小さいタイルに分割されます。

次に、各行には、tile0、tile1、tile2、tile3、...、tile19という列があります(合計20のズームレベルを想定)。あるいは実際には、tile0は常に0なので省略することもできます。これらのtileN列のそれぞれは、標準のBツリー索引によって索引付けされています。

次に、ズームレベルNで任意の(x、y)座標に対応するタイルがどれであるかをすばやく判断するためのアルゴリズムが必要です。このアルゴリズムの実装方法は今思い出しませんが、ややトリッキーだったことを思い出します非常に速いです。

(x、y)座標がタイルの端に近い場合、隣接するタイルは現在のタイルにおける最良の解よりも良い解を含むことができる。したがって、一般に、ズームレベルNで検索に4つのタイルを含める必要があります。これら4つのタイルを計算する関数を実装する必要があります。

ズームレベルが0、1、2、...、19の場合は、ズームレベル19で適切な4つのタイルを検索し、次に18、次に17、...で十分な結果セットが得られるまで検索します。

1
追加された

ジオハッシュは、ここでは良い解決策です。あなたはあなたが必要とする精度に従って長さを作ることができます、そしてあなたのSDカードでgeohashをファイル名にします。それはあなたが特定の近接範囲内のすべてのポイントを取得するためにあなたがそれからあなたにフィルターをかける/分類するためにあなたにいくつかのファイルを読むことを可能にするでしょう。

0
追加された

この目的のために R-Trees を使用して、いくつかのプロジェクトをうまく実装しました。

1つの実装はこちらで、これは部分的に移植されたバージョンのJavaライブラリです( jsi )。

0
追加された