これはArcGIS固有です。
2つのポイントシェープファイルがA
ありB
、最初の(A
)は緯度経度を含む単一のポイント、2番目(B
)は緯度と経度をそれぞれ含む多数のポイント(12k以上)です。私がやろうとしていることは、シェープファイルB
からの距離に基づいてシェープファイルのポイントの75%の選択を自動化することですA
。言い換えると、シェープファイルB
ポイントの75%に最も近く、シェープファイルA
の1ポイントを選択します。
これはArcGIS固有です。
2つのポイントシェープファイルがA
ありB
、最初の(A
)は緯度経度を含む単一のポイント、2番目(B
)は緯度と経度をそれぞれ含む多数のポイント(12k以上)です。私がやろうとしていることは、シェープファイルB
からの距離に基づいてシェープファイルのポイントの75%の選択を自動化することですA
。言い換えると、シェープファイルB
ポイントの75%に最も近く、シェープファイルA
の1ポイントを選択します。
回答:
シェープファイルAで複数リングバッファーを作成してから、バッファーをシェープファイルBに空間結合することができます。ポリゴンとポイントの空間結合を実行すると、属性内の各ポリゴンのポイント数がカウントされます結合のテーブル。次に、バッファー内のポイントの総数を調べることにより、シェープファイルBのポイントの75%以内を取得できます。
少し異なるアプローチは、これをPythonでスクリプト化し、ループ内で75%をチェックすることですが、1回限りの計算の場合は、それが必要ない場合があります。
1200ポイント(または最大で12Mポイント?)の場合は、それらをジェネリックコレクション(この場合はリストのSortedList)としてメモリに格納します。これは、原点から同じ距離にある複数のポイントがある状況に遭遇したときに、ポイントをスキップするだけで簡略化できます。また、パフォーマンスのために、SortedListの代わりにハッシュテーブルを使用し、すべての距離を挿入した後に1回ソートすることを検討してください。ただし、コードを数行追加する必要があります(?)。
これをテストする時間はありませんでしたが、このc#で始められるかもしれません。
private void SelectNTile(string layer1, string layer2, double nTile)
{
var fLayer1 = FindLayer(ArcMap.Document.FocusMap, "LayerWithLotsofPoints");
var fLayer2 = FindLayer(ArcMap.Document.FocusMap, "LayerWithOneSelectedPoint");
IFeature feat = GetSingleFeature(fLayer2);
var distList = MakeDistList(fLayer1.FeatureClass,(IPoint)feat.ShapeCopy);
// assume not many points exactly same distance
var nRecs = (int)(distList.Count * nTile); // nTile would be 0.75 for 75%
var Oids = new List<int>();
foreach (KeyValuePair<double, List<int>> kvp in distList)
{
Oids.AddRange(kvp.Value);
if (Oids.Count > nRecs)
break;
}
var fSel = fLayer1 as IFeatureSelection;
var OidArray = Oids.ToArray();
fSel.SelectionSet.AddList(Oids.Count, ref OidArray[0]);
}
private SortedList<double, List<int>> MakeDistList(IFeatureClass fc, IPoint pnt)
{
var outList = new SortedList<double, List<int>>();
var proxOp = pnt as IProximityOperator;
IFeatureCursor fCur = null;
try
{
fCur = fc.Search(null, true); // recycling is faster, we just need OIDs
IFeature feat;
while ((feat = fCur.NextFeature()) != null)
{
double dist = proxOp.ReturnDistance(feat.Shape);
if (!outList.ContainsKey(dist))
outList.Add(dist, new List<int> { feat.OID });
else
outList[dist].Add(feat.OID); // this should rarely happen
}
}
catch
{
throw;
}
finally
{
if (fCur != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
}
return outList;
}
private IFeature GetSingleFeature(IFeatureLayer fLayer)
{
var fSel = fLayer as IFeatureSelection;
if (fSel.SelectionSet.Count != 1)
throw new Exception("select one feature in " + fLayer.Name + " first");
var enumIDs = fSel.SelectionSet.IDs;
enumIDs.Reset();
IFeature feat = fLayer.FeatureClass.GetFeature(enumIDs.Next());
return feat;
}
private IFeatureLayer FindLayer(IMap map, string name)
{
throw new NotImplementedException();
}
この問題は数年前にありました。データを「フラットデータ」として保持し、すべてのデータをループ処理して距離を手動で計算し、上位75%(実際には上位10%を保持)を使用する方が簡単であることがわかりました。その後、距離計算を使用してArcIMSでも同じことを行いましたが、はるかに長くかかりました。
バッファリングは莫大なオーバーヘッドですが、数学の計算は「得意先の強み」です。12kポイントをバッファリングすると、パフォーマンスの問題が発生すると思います。