Алгоритм з'ясування точок перегину для полілінії


22

Я намагаюся з'ясувати точки перегину, тобто точки, де криві в лінії починаються і закінчуються. Якщо ви подивитесь на зображення, зеленою лінією може бути дорога або потік, а чорні точки - це точки, де криві починаються і закінчуються. введіть тут опис зображення

Якими були б кроки на високому рівні для автоматизації генерації цих точок? У мене ArcGIS настільний і я дуже зручний з ArcObjects.


Вихідні дані - це полілінія, яка складається з лінійних сегментів, і ви хочете їх визначити кривими, або вони вже мають сегменти дуги?
U2ros

В даний час вона складається з лінійних сегментів.
Devdatta Tengshe

1
Ілюстрація в цьому питанні виглядає надзвичайно схожою на опубліковану на сайті esri.com/news/arcuser/0110/turning.html .
whuber

@whuber: Дуже проникливі спостереження. Саме це було джерело даних, яке я використав для створення зображення.
Devdatta Tengshe

Відповіді:


15

Коли крива складається з відрізків ліній, то всі внутрішні точки цих сегментів є точками перегину, що не цікаво. Натомість криву слід вважати апроксимованою вершинами цих відрізків. Прокручуючи кусочно двічі диференційовану криву через ці сегменти, ми можемо потім обчислити кривизну. Точка перегину, строго кажучи, - це місце, де кривизна дорівнює нулю.

У прикладі є довгі розтяжки, де кривизна майже дорівнює нулю. Це говорить про те, що зазначені точки повинні наближатись до кінців таких ділянок з низькою кривизною.

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

Ось робочий Rкод для ілюстрації цих ідей. Почнемо з рядкового рядка, вираженого як послідовність координат:

xy <- matrix(c(5,20, 3,18, 2,19, 1.5,16, 5.5,9, 4.5,8, 3.5,12, 2.5,11, 3.5,3, 
               2,3, 2,6, 0,6, 2.5,-4, 4,-5, 6.5,-2, 7.5,-2.5, 7.7,-3.5, 6.5,-8), ncol=2, byrow=TRUE)

Розкладіть координати x і y окремо для досягнення параметризації кривої. (Параметр буде викликаний time.)

n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")

Інтерполюйте сплайни для побудови та обчислення:

time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))

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

curvature <- function(t, fx, fy) {
  # t is an argument to spline functions fx and fy.
  xp <- fx(t,1); yp <- fy(t,1)            # First derivatives
  xpp <- fx(t,2); ypp <- fy(t,2)          # Second derivatives
  v <- sqrt(xp^2 + yp^2)                  # Speed
  (xp*ypp - yp*xpp) / v^3                 # (Signed) curvature
  # (Left turns have positive curvature; right turns, negative.)
}

kappa <- abs(curvature(time, fx, fy))     # Absolute curvature of the data

Я пропоную оцінити поріг нульової кривизни з точки зору міри кривої. Принаймні, це хороший вихідний пункт; його слід регулювати відповідно до обертовості кривої (тобто збільшувати для довших кривих). Пізніше це буде використано для фарбування ділянок відповідно до кривизни.

curvature.zero <- 2*pi / max(range(xy[,1]), range(xy[,2])) # A small threshold
i.col <- 1 + floor(127 * curvature.zero/(curvature.zero + kappa)) 
palette(terrain.colors(max(i.col)))                        # Colors

Тепер, коли вершини були сплайновані та обчислена кривизна, залишається лише знайти точки перегину . Щоб показати їх, ми можемо побудувати вершини, побудувати сплайн та позначити на ньому точки перегину.

plot(xy, asp=1, xlab="x",ylab="y", type="n")
tmp <- sapply(2:length(kappa), function(i) lines(rbind(uv[,i-1],uv[,i]), lwd=2, col=i.col[i]))
points(t(sapply(time[diff(kappa < curvature.zero/2) != 0], 
       function(t) c(fx(t), fy(t)))), pch=19, col="Black")
points(xy)

Сюжет

Відкриті точки - це оригінальні вершини, xyа чорні точки - точки перегину, автоматично ідентифіковані за допомогою цього алгоритму. Оскільки кривину неможливо надійно обчислити в кінцевих точках кривої, ці точки не позначені спеціально.


Можливо, термінологія, яку я використав, була неправильною. Те, що ви припускали, саме те, що я хотів. Ваша відповідь виглядає багатообіцяючою, і мені доведеться попрацювати з R, щоб обробити свій Shapefile.
Devdatta Tengshe

3

Можна скористатися інструментом ущільнення . У цьому випадку ви вирішите ущільнити за кутом, Далі виберіть максимальний кут, прийнятий у прямій. Потім застосуйте рядок результатів до рядка інструменту Розділити у вершинах . Нарешті, видаліть лінії, що мають shape_length меншу мінімальну довжину дороги.

введіть тут опис зображення

На цьому малюнку ми бачимо три кроки:

1- Ущільнюйте лінію за допомогою кута. Я використовував 10 градусів як параметр, і ми використовували роздільну лінію. На малюнку вигнута лінія знаходиться в початковій фазі.

arcpy.Densify_edit("line" , "ANGLE" , "","",10)
arcpy.SplitLine_management("line" , "line_split")

2- Виберіть сегменти, де довжина shape_length не є зайвою. Як ми бачимо в таблиці, я не обрав цих зайвих довжин. Потім я вибираю їх у новий клас функцій.

arcpy.Select_analysis("line_split" , "line_split_selected")

3- Ми витягли вершини, розташовані в краях ліній, які є точками перегину.

arcpy.FeatureVerticesToPoints_management("line_split_selected" , "line_split_pnt" , "DANGLE")

У мене є такі ж коментарі та запитання, що стосуються вашої іншої відповіді: це гарна ідея, але в той же час не ясно, що вона дасть бажаний результат, як і як слід обирати пороговий кут. Чи можете ви надати ілюстрацію результату, щоб читачі могли оцінити, що насправді робить ця пропозиція? Надання відпрацьованих прикладів особливо важливо при рекомендуванні програмного забезпечення ESRI як частини рішення, оскільки їх алгоритми, як правило, не задокументовані, що робить неможливим точно знати, що вони роблять.
whuber

щоб бути дуже впевненим, що це робоче рішення, мені потрібно перевірити його, але я не можу його перевірити, я пропускаю дані, тому я вважаю, що запропоновані інструменти ESRI працюватимуть як очікувалося, але для цього відповіді потрібно пройти тестування далі.
geogeek

ми могли б назвати їх ідеями, а не відповідями
geogeek

1
Чи хотіли б ви тоді перенести їх у коментарі? До речі, якщо ви хочете перевірити дані, ви можете - для початку використати координати, які я розмістив у своїй відповіді, оскільки вони близькі до ілюстрації у питанні. Але чому б просто не використати будь-які географічні дані, які вам зручні?
whuber

2
так, справді це рішення краще працює на витягуванні лише прямих ліній.
geogeek

1

Ви можете використовувати інструмент « Узагальнити », який має максимальний зсув від початкового рядка як параметр, так що ви можете вибрати зміщення, яке відповідає вашому випадку.

введіть тут опис зображення

Якщо ми назвемо початковий рядок "line_cur", а узагальнений "line_gen", тоді ми могли б відрізати "line_cur" за допомогою "line_gen". Результатом стане прямий відрізок "line_cur". Тоді ми могли б очистити дуже короткий відрізок, видаливши їх за допомогою sql-запиту, який вибирає довжину Shape_length більше мінімальної довжини дороги.


Це гарна ідея. Не ясно, наскільки добре це буде працювати на практиці, хоча. Не могли б ви показати приклад, який показує виявлені точки перегину?
whuber

я зробив редагування, щоб включити малюнок, на малюнку пояснено, як цей інструмент міг зробити лінію, що стикується з прямими відрізками, тому ми повинні зробити кліп на стару лінію, щоб витягти лише старі відрізки прямих ліній
geogeek

щось не зрозуміло, я готовий відповісти на ваші запитання?
geogeek

Я не бачу жодних точок перегину, визначених на ілюстрації. Де вони б точно були? І як слід обирати толерантність до узагальнення?
whuber

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