memilih persentase (75%) dari sekelompok titik berdasarkan jarak dari satu titik terpisah di ArcGIS?

9

Ini spesifik untuk ArcGIS.

Saya memiliki 2 titik shapefile Adan B, yang pertama ( A) adalah satu titik yang berisi panjang lat, yang kedua ( B) adalah banyak titik (lebih dari 12k) yang masing-masing berisi lat dan panjangnya. Apa yang saya coba lakukan adalah mengotomatiskan pemilihan 75% Btitik shapefile berdasarkan jarak dari shapefile A. Dengan kata lain saya ingin memilih 75% Btitik shapefile terdekat untuk Asatu titik shapefile .

Furlong
sumber
Apakah solusi terprogram diterima?
Kirk Kuykendall
BTW, saya meminta agar Esri mengizinkan Shapefield untuk digunakan dalam custom ITableSortCallback tetapi diberitahu tidak ada pembenaran untuk ini. Kasus penggunaan ini menunjukkan sebaliknya.
Kirk Kuykendall
@Kirk Kuykendall Ya solusi terprogram sebenarnya lebih disukai karena ini adalah proses yang harus saya ulangi lebih dari 1k kali. Saya memiliki sekitar 1.200 poin yang terpisah dan masing-masing poin tersebut memiliki bentuk lain dengan rata-rata 12k poin di sekitarnya. Saya perlu mencari cara untuk dengan mudah memilih 75% poin terdekat untuk semuanya. Melakukannya secara manual hanyalah sebuah pertanyaan.
Furlong
Mungkin komentar ini berada di luar cakupan komentar yang tepat, tetapi kapan dan mengapa analisis seperti itu bermanfaat? Ini untuk penjelasan saya sendiri; maafkan kelambatan saya.
Nathanus
1
Pertimbangkan untuk menggunakan perangkat lunak statistik. Jika Anda menggabungkan semua 1.200 shapefile, membuat bidang id sumber selama penggabungan, Anda bisa bergabung dengan koordinat titik pusat terkait untuk itu dan menghitung semua jarak 1200 * 12k = 14,4M. Yang Anda butuhkan adalah daftar persentil jarak ke-75 berdasarkan id sumber: yang akan memakan waktu sekitar sepuluh detik dengan Stata (komersial) atau R (open source). (Jika Anda menggunakan ArcGIS untuk ini, beri tahu kami berapa banyak waktu yang diperlukan untuk perhitungan. :-)
whuber

Jawaban:

5

Anda bisa membuat Multiple Ring Buffer pada shapefile A, dan kemudian melakukan join spasial dari Buffer ke shapefile B. Ketika Anda melakukan join spasial dari poligon dan titik, Anda mendapatkan hitungan jumlah titik di setiap poligon dalam atribut. tabel bergabung. Kemudian, dengan memeriksa jumlah total poin dalam buffer, Anda bisa mendapatkan 75% dari poin dalam shapefile B.

Pendekatan yang sedikit berbeda adalah dengan skrip ini di Python, dan periksa 75% dalam satu lingkaran, tetapi jika itu adalah perhitungan sekali mati Anda mungkin tidak memerlukan itu.

djq
sumber
4
Akan lebih mudah, lebih cepat, dan lebih akurat untuk melakukan gabungan spasial dari A ke B, menghitung kuartil ketiga dari bidang [jarak] yang dihasilkan, dan memilih semua rekaman kurang dari jarak itu.
whuber
Saya tidak tahu itu mungkin untuk secara spasial bergabung dengan poin! Saya setuju, ini akan menjadi cara yang lebih baik untuk melakukannya.
djq
@Andy Sebaliknya, bergabung adalah hubungan titik terdekat. Itu tidak didasarkan pada atribut tabulasi sama sekali. Juga, dalam perangkat lunak Arc * (kembali ke ArcView 2), jarak dihitung secara otomatis sebagai hasil penggabungan.
whuber
1
@whuber, aku tahu! Oleh karena itu ditarik (pernyataan dihapus!) Saya menganggap Anda bisa melakukannya dengan tabel atribut bergabung (dan menghitung jarak sendiri) tetapi itu tidak perlu diberikan konteksnya. Saya kira poin yang saya ingin ulangi adalah bahwa itu hanya menghitung jarak antara 1 titik, tidak ada perulangan atau buffer atau prosedur berulang diperlukan.
Andy W
1
@Furlong Jika Anda membaca contoh Spatial Join: help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… Anda bisa mendapatkan ide bagaimana menjalankan ini dengan python. Kemudian, ini adalah masalah menjalankan melalui tabel atribut dan memilih nilai yang sesuai dengan kriteria Anda
djq
4

Untuk 1.200 poin (atau bahkan hingga 12 juta poin?) Saya baru saja memasukkannya ke dalam memori sebagai Koleksi Generik - dalam hal ini adalah SortedList dari daftar . Ini bisa disederhanakan dengan hanya melewatkan titik ketika Anda mengalami situasi dengan beberapa titik yang jaraknya sama dari titik asal. Selain itu, untuk kinerja, pertimbangkan untuk menggunakan hashtable alih-alih SortedList, dan menyortir sekali setelah memasukkan semua jarak. Itu akan membutuhkan beberapa baris kode lagi (?).

Saya tidak punya waktu untuk menguji ini, tetapi c # ini dapat membantu Anda memulai:

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();
}
Kirk Kuykendall
sumber
4

Script geoprocessing Python adalah pilihan yang jelas:

  1. Gunakan alat Point Distance untuk menghitung jarak dari fitur Anda di kelas fitur B ("Fitur Input" parameter alat) ke titik di kelas fitur A ("Fitur Dekat" parameter alat).
  2. Sortir tabel berdasarkan jarak yang dihitung.
  3. Pilih 75% pertama objectid di tabel output (kolom "Input_FID") dan gunakan itu untuk memilih dari fitur asli di kelas fitur B.
Philip
sumber
2

Saya memiliki masalah ini beberapa tahun yang lalu. Saya merasa lebih mudah untuk menyimpan data sebagai 'data datar', mengulang semua data dan menghitung jarak secara manual, lalu mengambil 75% teratas (saya benar-benar mempertahankan 10% teratas). Saya kemudian melakukan hal yang sama di ArcIMS menggunakan perhitungan jarak mereka dan butuh waktu lebih lama.

Buffering adalah overhead yang besar, namun perhitungan matematika adalah keahlian 'puters'. Jika Anda buffer 12k poin, saya pikir Anda akan memiliki masalah kinerja.

Berbulu
sumber
Saya [@Mapperz] menghapus komentar - pedoman alat mod menandai pos ini karena terdegradasi menjadi pertengkaran sia-sia ...
Mapperz