Узгодження сегментів різної довжини


13

Я намагаюся співставити невеликі сегменти з більшим сегментом, з яким вони, ймовірно, пов'язані: відносно близькі, схожі підшипники та звернені один до одного.

Ось типовий приклад даних, які я маю:

сегменти

Тут мені потрібно зіставити сегмент 652 з 198969, маючи 711 і 707, що нічого не відповідає.

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

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

Оновлення: я знайшов метод, який здається прийнятним компромісом:

  • Я спочатку знаходжу 10 найближчих чорних сегментів із блакитного, з яким я намагаюся зіставити (за допомогою <->оператора PostGIS ), які знаходяться на відстані менше 10 метрів.
  • Потім я створюю новий сегмент, знаходячи найближчі точки до кінців синього відрізка на кожному з чорних (використовуючи ST_ClosestPoint) та фільтрую результати, довжина яких менше 90% від синього (тобто сегменти не є облицювання або що різниця підшипників більше ~ 20 °)
  • Тоді я отримую перший результат, відсортований по відстані та відстані Хаусдорфа, якщо такі є.

Можливо, можна зробити якусь тонку настройку, але зараз, здається, це робиться прийнятною роботою. Досі шукаю будь-які інші методи або додаткові перевірки, щоб запустити, якщо я пропустив кілька кращих справ.


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

1
Так, я насправді щось намагаюся в цьому напрямку, і я оновлю питання з деталями.
Jukurrpa

1
Не впевнений, чи я вас правильно розумію, але ви намагалися створити центроїди для синіх ліній, а потім перевірити відстань від них до найближчих ліній, залишивши в результаті найкоротшу відстань?
Кирило Михальченко

1
Привіт, Кирило, я вже не працюю над цією проблемою, але проблема полягала також у тому, щоб відповідати синім сегментам залежно від їх орієнтації та наскільки вони "стикаються" з чорними сегментами. Що означає в цьому випадку, що 711 не повинен ні з чим збігатися, хоча він досить близький до чорних сегментів
Jukurrpa

Відповіді:


1

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

повернути азимут із сегмента лінії ESRI @shape

def returnAzimuth(shape):
    point1 = shape.firstPoint
    point2 = shape.lastPoint
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az
    return az

повернути зворотну від точок ESRI

def returnInverse(point1,point2):
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    dis = sqrt(dX**2+dY**2)
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az,dis
    return az,dis

вибухнути полілінією в сегмент лінії

def explodePolyline(shape):
    sr = "insert your spatial reference"
    lines=[]
    pnts = shape.getPart(0)
    for x in range(len(pnts)-1):
        array = arcpy.Array()
        point1 = arcpy.Point(pnts.getObject(x).X,pnts.getObject(x).Y,pnts.getObject(x).Z)
        point2 = arcpy.Point(pnts.getObject(x+1).X,pnts.getObject(x+1).Y,pnts.getObject(x+1).Z)
        array.add(point1)
        array.add(point2)
        line = arcpy.Polyline(array,sr,True,True)
        print(line)
        lines.append(line)
    return lines

пробіжись по таблиці так

for shape in Table:
    for shape2 in Table:
         check if shape is polyline:
            if yes, explode and compare returned line segments with shape2
                for seg in returnedlinesegments
                    if seg.firstpoint=shape2.lastpoint and shape.az=shape2.az
                        do stuff.....
            if no, compare shape and shape2
                if shape.firstpoint=shape2.lastpoint and shape.az=shape2.az
                   do stuff.....

ці властивості повинні бути доступні в postgis - firstpoint, lastpoint, pointarray Я припускаю, що властивості esri вище, тому що це те, що я найкраще знаю, але вищезгадане можна легко змінити для роботи з postgis.

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