Знаходження мінімальної відстані полігонів від краю до краю за допомогою ArcGIS Desktop?


9

У мене є карта приблизно 3000 полігонів в ArcGIS 10. Я шукаю відстань між кожним з них. Я знаю, як це зробити за допомогою lat і довгих координат центроїда, але я шукаю найкоротшу відстань прямої лінії від найближчого краю одного многокутника до найближчого краю іншого багатокутника. Будь-які ідеї?

Відповіді:


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
Вибачте, скаже, ти помилився в багатьох аспектах. PostGIS має власний розрахунок відстані. GOES в цьому не бере участі. По-друге, він абсолютно дає найближчу відстань між ребрами, не тільки вершини як в геометричній відстані, так і в географічному типі обчислення відстані сфероїда. Пол написав це.
Nicklas Avén

Щоб візуально його бачити для геометрії, ви можете використовувати st_shortestline, який повертає лінію, яка дає відстань.
Nicklas Avén

1
Нік правий, і в геометрії, і в географії функція відстані повертає відстань між ребрами. Наприклад, виберіть st_distance ('LINESTRING (0 0, 0 100)', 'LINESTRING (50 1, 51 1)')
Paul Ramsey

2
Уау, просторові бази даних рок! Я обчислюю відстань між набором ~ 8200 багатокутників та найближчим сусідом в іншому наборі ~ 8400 багатокутників. в арггізі 10 інструмент «генерувати біля таблиці» радіусом пошуку 10000 м займав 1 годину та 15 хвилин (на чотирьохядерному i7 на робочому столі 3,4 ГГц). цей же запит у PostGIS займав лише 3,5 хвилини, і це було на повільнішому комп'ютері (двоядерний i7 macbook i7 macbook 2,7 ГГц).
фісташкувати

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, і в кінцевому підсумку кодував щось подібне сам (очевидно, що це повільніше)
Джордж Сільва


2

Я думаю, що інструмент поблизу таблиці буде працювати для того, що ви хочете:

Визначає відстані від кожної функції у вхідних функціях до однієї або кількох сусідніх функцій, розташованих поблизу, у радіусі пошуку. Результати записуються у вихідну таблицю.

Просто залиште радіус пошуку порожнім.


Це рішення, яке я спробую спершу, але для розблокування інструменту «Генерувати біля таблиці» (Аналіз) потрібен рівень ліцензії ArcInfo.
PolyGeo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.