使用ArcGIS Desktop查找多边形的最小边到边距离?


9

我在ArcGIS 10中有一幅约3000个多边形的地图。我正在寻找它们之间的距离。我知道如何使用质心的经度和纬度坐标来实现,但是我正在寻找从一个多边形的最近边缘到另一个多边形的最近边缘的最短直线距离。有任何想法吗?

Answers:


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 2010年

1
抱歉,您在很多方面都错了。PostGIS具有本机距离计算。GOES不参与其中。其次,它绝对给出了边缘之间的最接近的距离,不仅是几何距离和地理类型球体距离计算中的顶点。保罗写的。
NicklasAvén2010年

要直观地看到几何图形,可以使用st_shortestline返回返回距离的线。
NicklasAvén2010年

1
Nik是正确的,在几何和地理上,距离函数都返回边缘之间的距离。例如,选择st_distance('LINESTRING(0 0,0 100)','LINESTRING(50 1,51 1)')
Paul Ramsey 2010年

2
哇,空间数据库真是太棒了!我正在计算一组〜8200个多边形与另一组〜8400个多边形中的最近邻居之间的距离。在arcgis 10中,搜索半径为10000 m的“生成近表”工具花费了1小时15分钟(在3.4 GHz四核i7台式机上)。在PostGIS中,相同的查询只花了3.5分钟,而那是在速度较慢的计算机上(2.7 GHz双核i7 macbook pro)。
pistachionut 2012年

8

从A到B的距离与从B到A的距离相同,并且从A到A的距离为零,因此半矩阵将为您节省一些工作。

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,最终自己写了一些类似的东西(显然速度较慢)
George Silva 2010年


2

我认为近桌工具可以满足您的需求:

确定在搜索范围内从输入要素中的每个要素到附近要素中的一个或多个附近要素的距离。结果记录在输出表中。

只需将搜索半径留空即可。


这是我首先尝试的解决方案,但它需要ArcInfo许可级别才能解锁“生成近表(分析)”工具。
PolyGeo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.