Соответствующие сегменты разной длины

13

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

Вот типичный пример данных, которые у меня есть:

сегменты

Здесь я должен был бы соответствовать сегменту 652 к 198969, в то время как 711 и 707 не соответствуют ничему.

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

Хаусдорф на самом деле правильный метод для решения этой проблемы? Есть ли другие подходы? Я думал просто о создании набора проверок для параметров, которые я упомянул (расстояние, азимут и т. Д.), Но я боюсь, что мне нужно будет добавить целый ряд условий для обработки краевых случаев или таких вещей, как пороговое значение, на сколько они обращенных друг к другу.

Обновление: я нашел метод, который кажется приемлемым компромиссом:

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

Там может быть какая-то тонкая настройка, но пока она кажется приемлемой. Все еще ищу какие-либо другие методы или дополнительные проверки для запуска, если я пропустил некоторые крайние случаи.

Jukurrpa
источник
1
Почему бы просто не использовать конечные точки (синих) сегментов для определения потенциальных совпадений среди целевых (черных) сегментов? Совпадение сегмента, которое вы ищете, происходит, когда обе конечные точки находятся близко к общей цели, которая является простым запросом для выполнения. Этот метод обрабатывает несоответствия, которые возникают из-за ошибок в расположении конечных точек сегмента, с которыми в противном случае может возникнуть проблема: обратите внимание, что очень короткий (синий) сегмент имеет гораздо менее точную опору, чем более длинный сегмент.
whuber
1
Да, я на самом деле пробую что-то в этом духе, я уточню вопрос с деталями.
Jukurrpa
1
Не уверен, правильно ли я вас понимаю, но пытались ли вы создать центроиды для синих линий, а затем проверить расстояния от них до ближайших линий, оставив в результате самое короткое расстояние?
Кирилл М
1
Привет, Кирилл, я больше не работаю над этой проблемой, но проблема заключалась также в том, чтобы сопоставить синие сегменты в зависимости от их ориентации и того, насколько они "обращены" к черным сегментам. Что означает в этом случае, что 711 не должен совпадать ни с чем, хотя он довольно близко к черным сегментам
Jukurrpa

Ответы:

1

Вот пара функций, которые я написал, которые должны позволить вам делать то, что вам нужно. Проверьте и посмотрите, является ли линия полилинией или сегментом, если ломаная линия взорвет линию, затем сравните азимут и инверсию первой точки и последней точки на линиях, установите приемлемые критерии для кода, который будет принимать решение за вас. Это дугообразные методы, но они могут быть изменены.

вернуть азимут из отрезка линии 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.

Гари Лестер
источник