ArcGIS Desktop을 사용하여 다각형의 최소 가장자리 거리를 찾으십니까?


9

ArcGIS 10에는 약 3000 개의 다각형으로 구성된지도가 있습니다. 각 다각형 사이의 거리를 찾고 싶습니다. 중심의 위도 및 경도 좌표를 사용하는 방법을 알고 있지만 한 다각형의 가장 가까운 가장자리에서 다른 다각형의 가장 가까운 가장자리까지의 최단 직선 거리를 찾고 있습니다. 어떤 아이디어?

답변:


11

그것은 좋은 코드 조각이지만 (거의 지리적으로 캐스트를 제거하지 않는 경우 테이블이 지리적 좌표에 있다고 가정)만큼 좋지는 않습니다.

CREATE TABLE mytable_distances AS
SELECT a.id, b.id, ST_Distance(a.geom::geography, b.geom::geography) as distance
FROM mytable a, mytable b;

공간 데이터베이스가 흔들리는 것을 언급 했습니까? 그들이하다. 아, 그래


이것은 가장 가까운 정점 사이의 거리를 찾을 수 있지만 가장자리 자체는 아닙니다. GEOS가 더 정확한 답을 노출시키지 않는 것 같습니다. 아직도, 매우 편리합니다!
scw

1
죄송합니다 scw, 당신은 여러면에서 잘못되었습니다. PostGIS에는 기본 거리 계산이 있습니다. GOES는 관련이 없습니다. 둘째, 지오메트리 거리와 지리 형 스페 로이드 거리 계산에서 꼭짓점뿐만 아니라 가장자리 사이에 가장 가까운 거리를 제공합니다. 바울이 썼습니다.
Nicklas Avén

형상을 시각적으로 보려면 st_shortestline을 사용하여 거리를 제공하는 선을 반환 할 수 있습니다.
Nicklas Avén

1
Nik이 옳습니다. 지오메트리와 지리 모두에서 거리 함수는 가장자리 사이의 거리를 반환합니다. 예를 들어 st_distance ( 'LINESTRING (0 0, 0 100)', 'LINESTRING (50 1, 51 1)')
Paul Ramsey를 선택하십시오.

2
와우, 공간 데이터베이스가 흔들린다! ~ 8200 다각형 세트와 ~ 8400 다각형 세트에서 가장 가까운 이웃 사이의 거리를 계산하고 있습니다. arcgis 10에서 검색 반경이 10000m 인 '근접 테이블 생성'도구는 1 시간 15 분이 걸렸습니다 (3.4GHz 쿼드 코어 i7 데스크탑). PostGIS의 동일한 쿼리는 3.5 분 밖에 걸리지 않았으며 속도가 느린 컴퓨터 (2.7GHz 듀얼 코어 i7 맥북 프로)에서 발생했습니다.
피스타치오 넛

8

A에서 B까지의 거리는 B에서 A와 동일하고 A에서 A까지의 거리는 0이므로 반 행렬은 작업을 절약합니다.

IProximityOperator는 가장자리에서 거리를 반환합니다. 아래 코드는 각 다각형의 중심을 중심으로 한 방위각 투영을 사용합니다 (선과 함께 작동해야 함). 다각형이 너무 복잡하지 않거나 메모리가 많은 경우 모든 도형을 메모리에로드하면 투영 속도가 빨라집니다. (이것은 철저히 테스트되지 않았습니다).

public class Pair
{
    public int Oid1;
    public int Oid2;
    public double Dist;
    public static void TestGetDistances()
    {
        IWorkspaceFactory wsf = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();

        string path = @"C:\Program Files\ArcGIS\DeveloperKit10.0\Samples\data\Usa\USA.gdb";
        var fws = wsf.OpenFromFile(path, 0) as IFeatureWorkspace;
        IFeatureClass fc = fws.OpenFeatureClass("states");
        var halfMatrix = Pair.GetPairs(fc);

    }
    /// <summary>
    /// key is oid of each feature, value is pairs for features with smaller oids.
    /// </summary>
    /// <param name="fc"></param>
    /// <returns></returns>
    public static SortedList<int, List<Pair>> GetPairs(IFeatureClass fc)
    {
        ISpatialReferenceFactory3 srf = new SpatialReferenceEnvironmentClass();
        IProjectedCoordinateSystem pcs = 
        srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_WGS1984N_PoleAziEqui);

        var outList = new SortedList<int, List<Pair>>();
        IFeatureCursor fCur = fc.Search(null, true);
        IFeature f;
        while ((f = fCur.NextFeature()) != null)
        {
            var pairs = GetDistances(f, pcs);
            Debug.Print("{0} has {1} pairs", f.OID, pairs.Count);
            outList.Add(f.OID, pairs);
        }
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
        return outList;
    }

    private static IPoint GetGCSCentroid(IGeometry geom)
    {
        if (geom.SpatialReference is IProjectedCoordinateSystem)
        {
            geom.Project(((IProjectedCoordinateSystem)geom.SpatialReference).GeographicCoordinateSystem);
        }
        IArea a = geom is IArea ? geom as IArea : geom.Envelope as IArea;
        return a.Centroid;
    }

    /// <summary>
    /// return a list of all other features whose OID is lesser than f1
    /// </summary>
    /// <param name="f1"></param>
    /// <param name="pcs"></param>
    /// <returns></returns>
    private static List<Pair> GetDistances(IFeature f1, IProjectedCoordinateSystem pcs)
    {
        IPoint centroid = GetGCSCentroid(f1.ShapeCopy);

        pcs.set_CentralMeridian(true, centroid.X);
        ((IProjectedCoordinateSystem2)pcs).LatitudeOfOrigin = centroid.Y;
        var g1 = f1.ShapeCopy;
        g1.Project(pcs);

        var outList = new List<Pair>();
        var fc = f1.Class as IFeatureClass;
        var proxOp = g1 as IProximityOperator;
        IFeatureCursor fCur = fc.Search(null, true);
        IFeature f2 = null;
        while ((f2 = fCur.NextFeature()) != null)
        {
            if (f2.OID < f1.OID)
            {
                var g2 = f2.ShapeCopy;
                g2.Project(pcs);
                outList.Add(new Pair()
                {
                    Oid1 = f1.OID,
                    Oid2 = f2.OID,
                    Dist = proxOp.ReturnDistance(g2)
                });
            }
        }
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
        return outList;
    }
}

이것은 좋은 코드입니다. 나는 IproximityOperator에 대해 알고,이 같은 다소 뭔가를 코딩 자신을 종료되지 않았다 (분명히이 느리다)
조지 실바


2

니어 테이블 도구 는 원하는대로 작동 한다고 생각합니다 .

검색 반경 내에서 입력 형상의 각 형상에서 근거리 형상의 하나 이상의 주변 형상까지의 거리를 결정합니다. 결과는 출력 테이블에 기록됩니다.

검색 반경을 비워 두십시오.


이것이 내가 먼저 시도하는 솔루션이지만, Near Table 생성 (Analysis) 도구의 잠금을 해제하려면 ArcInfo 라이센스 수준이 필요합니다.
PolyGeo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.