ArcGIS에서 하나의 개별 포인트로부터의 거리를 기준으로 포인트 그룹의 백분율 (75 %)을 선택합니까?


9

이것은 ArcGIS에만 해당됩니다.

2 점 모양 파일이 A있고 B첫 번째 점 ( A)은 위도 길이를 포함하는 단일 점이고 두 번째 점 ( B)은 위도 및 길이가 각각 포함 된 여러 점 (12k 이상)입니다. 내가하려는 것은 shapefile B로부터의 거리를 기준으로 shapefile 점 의 75 % 선택을 자동화하는 것 A입니다. 즉, shapefile B점 중 75 %의 가장 가까운 75 %를 shapefile A의 한 점 으로 선택하려고합니다 .


프로그래밍 솔루션이 허용됩니까?
Kirk Kuykendall

BTW, Esri가 Shapefield를 맞춤형 ITableSortCallback 에서 사용할 수 있도록 요청 했지만 이에 대한 타당성이 없다고 들었습니다. 이 사용 사례는 달리 보여줍니다.
Kirk Kuykendall

@Kirk Kuykendall 예, 1k 회 이상 반복해야하는 프로세스이기 때문에 프로그래밍 솔루션이 실제로 선호됩니다. 대략 1200 개의 개별 점이 있으며 각 점마다 평균 12k 점이있는 다른 모양 파일이 있습니다. 주변 지점의 가장 가까운 75 %를 쉽게 선택할 수있는 방법을 찾아야합니다. 수동으로하는 것은 의문의 여지가 없습니다.
Furlong

아마도이 의견은 적절한 의견 범위를 벗어 났지만 그러한 분석이 언제 그리고 왜 유용한가? 이것은 내 자신의 설명을위한 것입니다. 느려짐을 용서하십시오.
Nathanus

1
통계 소프트웨어 사용을 고려하십시오. 1200 개의 shapefile을 모두 병합하고 병합하는 동안 소스 ID 필드를 작성하는 경우 해당 중심점 좌표를 결합하여 1200 * 12k = 14.4M 거리를 모두 계산할 수 있습니다. 그러면 소스 ID 별 거리의 75 번째 백분위 수 목록이 필요합니다. Stata (상업용) 또는 R (오픈 소스)에서는 약 10 초가 걸립니다. (이를 위해 ArcGIS를 사용하는 경우 계산에 걸리는 시간을 알려주십시오. :-)
whuber

답변:


5

당신이 만들 수있는 다중 링 버퍼를 Shape 파일 A를 한 다음 당신이 다각형 포인트의 조인 공간적 할 때 B를 shape 파일에 버퍼의 조인 공간적 할, 당신은 속성의 각 다각형에 포인트의 수를 얻을 조인 테이블. 그런 다음 버퍼 내의 총 점 수를 검사하여 shapefile B에서 점의 75 % 이내를 얻을 수 있습니다.

약간 다른 접근법은 파이썬에서 이것을 스크립팅하고 루프에서 75 %를 확인하는 것이지만 일회성 계산이라면 필요하지 않을 수 있습니다.


4
A 대 B의 공간 결합을 수행하고 결과 [distance] 필드의 3 분위를 계산하고 해당 거리 미만의 모든 레코드를 선택하는 것이 더 간단하고 빠르며 정확합니다.
whuber

공간적으로 포인트를 결합하는 것이 가능하다는 것을 몰랐습니다! 나는 이것이 훨씬 더 나은 방법이라고 동의합니다.
djq

@Andy 반대로 조인은 가장 가까운 점 관계입니다. 전혀 도표화 된 속성을 기반으로하지 않습니다. 또한 Arc * 소프트웨어 (ArcView 2로 돌아 가기)에서 결합의 결과로 거리가 자동으로 계산됩니다.
whuber

1
@ whuber, 알아요! 따라서 철회 된 (삭제 된 문!) 속성 테이블 조인으로 거리를 계산할 수 있다고 가정하지만 컨텍스트를 고려할 때 불필요합니다. 반복하고 싶은 요점은 단순히 1 점 사이의 거리를 계산하는 것입니다. 루핑이나 버퍼 또는 반복 절차가 필요하지 않습니다.
Andy W

1
@Furlong Spatial Join의 예제를 읽으면 help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… 파이썬에서이를 실행하는 방법에 대한 아이디어를 얻을 수 있습니다. 그런 다음 속성 테이블을 살펴보고 기준과 일치하는 값을 선택해야합니다.
djq

4

1200 포인트 (심지어 또는 12M 포인트 대답?) 난 그냥 일반 컬렉션으로 메모리에 넣어 것 -이 경우 A의 SortedList목록 . 원점과 같은 거리에있는 여러 점이있는 상황에 처할 때 점을 건너 뛰면 간단히 단순화 할 수 있습니다. 또한 성능 을 위해 SortedList 대신 해시 테이블을 사용하고 모든 거리를 삽입 한 후 한 번 정렬하는 것이 좋습니다. 그래도 몇 줄의 코드가 더 필요합니다 (?).

나는 이것을 테스트 할 시간이 없었지만이 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();
}

4

파이썬 지오 프로세싱 스크립트는 확실한 선택입니다.

  1. 점 거리 도구를 사용하여 피쳐 클래스 B의 피쳐 (공구의 "입력 피쳐"매개 변수)에서 피쳐 클래스 A의 포인트 (도구의 "근처 피쳐"파라미터)까지의 거리를 계산합니다.
  2. 계산 된 거리별로 테이블을 정렬하십시오.
  3. 출력 테이블 ( "Input_FID"열)에서 오브젝트 ID의 처음 75 %를 선택하고이를 사용하여 피쳐 클래스 B의 원래 피쳐에서 선택하십시오.

2

몇 년 전에이 문제가있었습니다. 나는 데이터를 '플랫 데이터'로 유지하고 모든 데이터를 반복하고 거리를 수동으로 계산 한 다음 상위 75 % (실제로 상위 10 %를 유지)를 유지하는 것이 더 쉽다는 것을 알았습니다. 그런 다음 ArcIMS에서 거리 계산을 사용하여 동일한 작업을 수행했으며 시간이 훨씬 더 걸렸습니다.

버퍼링은 엄청난 오버 헤드이지만 수학 계산은 '퍼터 장점'입니다. 12k 포인트를 버퍼링하면 성능 문제가 발생한다고 생각합니다.


나는 [@Mapperz] 댓글을 삭제했습니다-mod 툴 가이드 라인이이 글에 무의미한
경고음
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.