Підключення особливостей лінії та визначення довжини найдовшої лінії


12

У мене є функція лінії (див. Зображення), що представляє річку, яку я створив за допомогою інструменту Stream_to_Feature. Таблиця атрибутів містить кілька записів, що представляють різні рядки - проблема полягає в тому, що найдовший рядок (легко розрізнений візуально) не представлений як один рядок у таблиці, він фактично складається з багатьох менших рядків. Лінії здаються дотиковими, хоча вони не перетинаються одна з одною.

Як я можу об'єднати ці рядки, а потім визначити довжину найдовшої лінії за допомогою ArcObjects або вручну, які я можу перетворити на ArcObjects? Ще краще рішення передбачало б позбутися всіх приток і залишити мене лише річковим руслом як лінії.

Особливість лінії - річка


1
Вони взагалі підключаються? Ви сказали, що вони не перетинаються, але це означає, що вони не діляться вершиною?
Натанус

1
Вибачте - я мав би бути більш чітким. Вони поділяють вершини, але повністю не перетинаються одна з одною.
Радар

Чи знаєте ви, де знаходиться гирло річки? Чи річка завжди дерево (одна унікальна стежка від кожної верхівки води до гирла)?
Кірк Куйкендалл

3
Власне, вам не потрібно довжини "найдовшого рядка". Це може бути маршрут від одного охоплення вгору за течією до іншого віддаленого досяжного потоку. Це станеться, коли біля її гирла з’єднаються дві основні гілки потоку. Натомість вам потрібно найдовший маршрут між гирлом та будь-якою іншою кінцевою точкою на потоці. (Ця характеристика навіть не вимагає, щоб потік був представлений як дерево: він може
заплести

@whuber - ваша оцінка правильна - будь-яка ідея, як я можу досягти цього за допомогою маршрутів?
Радар

Відповіді:


18

По-перше, невелике тло, яке вказує на те, чому це не важка проблема. Потік через річку гарантує, що її ділянки, якщо правильно оцифровані, завжди можуть бути орієнтовані на формування спрямованого ациклічного графіка (DAG). У свою чергу, графік можна лінійно упорядкувати тоді і лише тоді, коли це DAG, використовуючи техніку, відому як топологічний сорт . Топологічне сортування швидко: його вимоги до часу та простору - це O (| E | + | V |) (E = кількість ребер, V = кількість вершин), що є настільки ж хорошим, скільки отримується. Створення такого лінійного упорядкування дозволить легко знайти основний русло потоку.

Ось, тоді, ескіз алгоритму . Устя струмка лежить уздовж основного русла. Перемістіть вгору за течією кожної гілки, прикріпленої до гирла (їх може бути більше, якщо рот є впаданням) і рекурсивно знайдіть основне русло, що веде до цієї гілки. Виберіть гілку, для якої загальна довжина найбільша: це ваша "зворотна лінія" уздовж основного ложа.

Щоб зробити це зрозумілішим, я пропоную кілька (неперевірених) псевдокодів . Вхід - це набір відрізків ліній (або дуг) S (що включає оцифрований потік), кожен з яких має дві чіткі кінцеві точки початку (S) і кінця (S) та додатну довжину, довжину (S); і гирло річки p , що є точкою. Вихід - це послідовність сегментів, що об'єднують рот з найбільш віддаленою точкою вгору за течією.

Нам знадобиться працювати з "позначеними сегментами" (S, p). Вони складаються з одного з відрізків S разом з однією з двох його кінцевих точок, с . Нам потрібно буде знайти всі сегменти S, які ділять кінцеву точку з точкою зонда q , позначити ці сегменти іншими їх кінцевими точками та повернути набір:

Procedure Extract(q: point, A: set of segments): Set of marked segments.

Коли такого сегмента не знайти, Extract повинен повернути порожній набір. В якості побічного ефекту, екстракт необхідно видалити всі сегменти вона повертається з безлічі А, тим самим змінюючи А сам.

Я не даю реалізувати Витяг: ваш ГІС надасть можливість вибору сегментів S, що ділиться кінцевою точкою з q . Позначення їх є просто питанням порівняння і початкового (S), і кінця (S) з q, і повернення того, що з двох кінцевих точок не відповідає.

Тепер ми готові вирішити проблему.

Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
    A0 = A                        // Optional: preserves A
    C = Extract(p, A0)            // Removes found segments from the set A0!
    L = 0; B = empty array
    For each (S,q) in C:          // Loop over the segments meeting point p
        (B0, M) = LongestUpstreamReach(q, A0)
        If (length(S) + M > L) then
            B = append(S, B0)
            L = length(S) + M
        End if
    End for
    Return (B, L)
End LongestUpstreamReach

Процедура "append (S, B0)" приклеює сегмент S в кінці масиву B0 і повертає новий масив.

(Якщо потік насправді є деревом: немає островів, озер, тасьм тощо), тоді ви можете відмовитися від кроку копіювання A в A0 .)

На вихідне запитання відповідає відповідь, утворюючи об'єднання сегментів, повернених LongestUpstreamReach.

Для ілюстрації розглянемо потік у вихідній карті. Припустимо, вона оцифрована як колекція із семи дуг. Дуга a йде від гирла в точці 0 (вгорі карти, праворуч на рисунку внизу, яка повертається) вгору за течією до першого впадіння в точці 1. Це довга дуга, скажімо, 8 одиниць. Дуга b відгалужується ліворуч (на карті) і коротка, довжиною близько 2 одиниць. Дуга c відгалужується праворуч і становить близько 4 одиниць і т.д. Дозволяючи "b", "d" і "f" позначають ліві гілки, коли ми рухаємося згори вниз на карті, і "a", "c", "e" та "g" інші гілки, і нумеруючи вершини від 0 до 7, ми можемо абстрактно представити графік як сукупність дуг

A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}

Я вважаю , що вони мають довжину 8, 2, 4, 1, 2, 2, 2 для через г , відповідно. Рот - вершина 0.

Малюнок

Перший приклад - заклик до Extract (5, {f, g}). Він повертає набір позначених сегментів {(f, 6), (g, 7)}. Зверніть увагу, що вершина 5 знаходиться в місці злиття дуг f і g (дві дуги внизу карти) і що (f, 6) і (g, 7) позначають кожну з цих дуг їх кінцевими точками вгору за течією .

Наступний приклад - виклик LongestUpstreamReach (0, A). Перша дія, яку він вживає, - це заклик до вилучення (0, A). Це повертає набір, що містить позначений сегмент (a, 1), і він вилучає сегмент a з множини A0 , який тепер дорівнює {b, c, d, e, f, g}. Є одна ітерація циклу, де (S, q) = (a, 1). Під час цієї ітерації здійснюється виклик LongestUpstreamReach (1, A0). Рекурсивно він повинен повертати або послідовність (g, e, c), або (f, e, c): обидва однаково дійсні. Довжина (M), яку він повертає, дорівнює 4 + 2 + 2 = 8. (Зверніть увагу, що LongestUpstreamReach не змінює A0 .) В кінці циклу сегментуйте aбуло додано до русла потоку, а довжина збільшена до 8 + 8 = 16. Отже, перше повернене значення складається або з послідовності (g, e, c, a), або (f, e, c, a), довжиною 16 в будь-якому випадку для другого повернутого значення. Це показує, як LongestUpstreamReach просто переміщується вгору за течією від гирла, вибираючи в кожному злитті гілку з найдовшою відстані, яку потрібно пройти, і відстежує сегменти, пройдені по її маршруту.

Більш ефективна реалізація можлива, коли існує багато косів та островів, але для більшості цілей буде витрачено мало зусиль, якщо LongestUpstreamReach буде виконано точно так, як показано, тому що при кожному злитті не відбувається перекриття серед пошукових запитів у різних галузях: обчислювальна техніка час (і глибина стека) буде прямо пропорційним загальній кількості сегментів.


+1 Тепер, коли б тільки вони знали це, перш ніж називати річку Міссурі.
Кірк Куйкендалл

1
@ Кірк Рекурсивне дослідження американського Заходу на початку 1800-х років було непростим :-).
whuber

це надзвичайно корисно! Я побачу, чи зможу я встановити цю установку всередині свого ГІС та поділитися корисним кодом, як тільки я зроблю його. Ура!
Радар

Приємна відповідь, що пролунає
Рагі Ясер Бурхум

2

Інструмент " Нерозпущена лінія" може бути корисним для того, що ви намагаєтеся зробити, хоча вам потрібно буде розробити якийсь метод, щоб диференціювати одну гілку потоку від іншої (для поля розчинення). Це передбачає, що у вас є ліцензія ArcInfo.

Якщо у вас немає такої ліцензії, ви можете розглянути підхід ArcObjects, який приймає XY кожної вершини, заповнює IPointCollectionїх, а потім створює IGeometryа PolyLineClass.


1

Ви можете використовувати RivEX, це інструмент ArcGIS 9.1 (який працюватиме в 9.3 та 10). Він має інструменти для виявлення топологічних проблем з річковими мережами та багато інструментів для обробки. Один такий інструмент знаходить головний стебло .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.