回答:
「最速」の量が含まれている場合、あなたの費やされた時間を、解決策は、あなたが慣れているものをソフトウェアに依存し、迅速に使用することができます。したがって、以下の発言では、可能な限り高速な計算時間を実現するためのアイデアに焦点を当てます。
定型プログラムを使用する場合、ほぼ確実にできる最善の方法は、ポリゴンを前処理して、KDツリーやクワッドツリーなどのパフォーマンスが通常O(log(V )*(N + V))ここで、Vはポリゴン内の頂点の総数、Nはポイントの数です。データ構造は作成に少なくともO(log(V)* V)の労力を要し、その後になります。ポイントごとのコストO(log(V))で各ポイントについてプローブする必要があります。
最初にポリゴンをグリッド化して、重複しないという仮定を活用することで、大幅に改善できます。各グリッドセルは完全にポリゴン内部(「ユニバーサルポリゴン」の内部を含む)にあります。この場合、セルにポリゴンのIDのラベルを付けるか、1つ以上のポリゴンエッジを含みます。このラスタライズのコストは、すべてのエッジのラスタライズ中に参照されるグリッドセルの数に等しく、O(V / c)です。cはセルのサイズですが、big-O表記の暗黙の定数は小さくなります。
(このアプローチの利点の1つは、標準のグラフィックルーチンを活用できることです。たとえば、(b)各ポリゴンに異なる色を使用して、(c)を使用して仮想画面にポリゴンを描画するシステムがある場合対処したい任意のピクセルの色を読み取ることができます。
このグリッドを配置した状態で、各ポイントを含むセルを計算することにより、ポイントを事前にスクリーニングします(数クロックしか必要としないO(1)操作)。ポイントがポリゴン境界の周りにクラスター化されていない限り、通常、結果があいまいなO(c)ポイントのみが残ります。したがって、グリッドの構築と事前スクリーニングの総コストはO(V / c + 1 / c ^ 2)+ O(N)です。O(log(V)* N * c)のコストで、残りのポイント(つまり、ポリゴンの境界に近いポイント)を処理するには、他の方法(これまでに推奨された方法など)を使用する必要があります。
cが小さくなると、エッジを持つ同じグリッドセル内のポイントが少なくなり、そのため、後続のO(log(V))処理が必要になるポイントが少なくなります。これに対処するために、O(1 / c ^ 2)グリッドセルを保存し、O(V / c + 1 / c ^ 2)時間をかけてポリゴンをラスタライズする必要があります。したがって、最適なグリッドサイズcがあります。それを使用して、総計算コストはO(ログ(V)* N)であるが、暗黙の定数は、典型的には方法、事前スクリーニングのO(N)の速度に起因缶詰の手順を使用してより小さい。
20年前、私はこのアプローチをテストし(イングランドおよびオフショア全体で等間隔のポイントを使用し、当時のビデオバッファーが提供する約400Kセルの比較的粗いグリッドを利用しました)、最高の公開アルゴリズムと比較して2桁のスピードアップを達成しました見つける。ポリゴンが小さくて単純な場合(三角形など)でも、桁違いのスピードアップが実質的に保証されます。
私の経験では、計算は非常に高速であったため、操作全体がCPUではなくデータI / O速度によって制限されていました。I / Oがボトルネックになる可能性があるため、データの読み取り時間を最小限に抑えるために、できるだけ圧縮された形式でポイントを保存することで、非常に高速な結果を達成できます。また、ディスクへの書き込みを制限できるように、結果の保存方法についてもいくつか考えてください。
私の場合は、おそらくCSVデータをshpファイルに読み込んでから、shapefileとshapelyを使用してPythonスクリプトを記述し、含まれるポリゴンIDを取得してフィールド値を更新します。
geotoolsとJTSがshapefile / shapelyより速いかどうかはわかりません...テストする時間はありません!
編集:ところで、値を簡単にフォーマットしてポリゴンシェープファイルの空間オブジェクトでテストできるため、シェープファイル形式へのcsv変換はおそらく必要ありません。
GUIをダウンロードします。シェープファイルとCSVの両方を仮想テーブルとして開くことができます。つまり、実際にデータベースにインポートするのではなく、テーブルとして表示されるため、好きな方法ですばやく結合してクエリを実行できます。
C / C ++ / PythonでOGRを使用すると、かなり迅速に実行できます(Pythonは3つの中で最も遅いはずです)。すべてのポリゴンをループして、ポイントにフィルターを設定し、フィルターを適用したポイントをループすると、ループする各ポイントが現在のポリゴンに属することがわかります。OGRを使用したPythonのサンプルコードは、ポリゴンをループし、それに応じてポイントをフィルターします。C / C ++コードはこれに非常によく似ており、Pythonに対して大幅な速度の向上が得られると思います。CSVを更新するには、数行のコードを追加する必要があります。
from osgeo import ogr
from osgeo.gdalconst import *
inPolyDS = ogr.Open("winnipeg.shp", GA_ReadOnly)
inPolyLayer = inPolyDS.GetLayer(0)
inPointDS = ogr.Open("busstops.vrt", GA_ReadOnly)
inPointLayer = inPointDS.GetLayerByName("busstops")
inPolyFeat = inPolyLayer.GetNextFeature()
while inPolyFeat is not None:
inPtFeat = inPointLayer.GetNextFeature()
while inPtFeat is not None:
ptGeom = inPtFeat.GetGeometryRef()
# Do work here...
inPtFeat = inPointLayer.GetNextFeature()
inPolyFeat = inPolyLayer.GetNextFeature()
VRTファイル(busstops.vrt):
<OGRVRTDataSource>
<OGRVRTLayer name="busstops">
<SrcDataSource>busstops.csv</SrcDataSource>
<GeometryType>wkbPoint</GeometryType>
<LayerSRS>WGS84</LayerSRS>
<GeometryField encoding="PointFromColumns" x="X" y="Y" reportSrcColumn="FALSE" />
</OGRVRTLayer>
</OGRVRTDataSource>
CSVファイル(busstops.csv):
FID,X,Y,stop_name
1,-97.1394781371062,49.8712241633646,Southbound Osborne at Mulvey
CSVTファイル(busstops.csvt、OGRは列タイプを識別するために必要です。そうでない場合、空間フィルターは実行されません):
Integer,Real,Real,String