Passende Segmente unterschiedlicher Länge

13

Ich versuche, kleine Segmente mit einem größeren Segment abzugleichen, mit dem sie am wahrscheinlichsten zu tun haben: relativ eng, ähnlich gelagert und einander zugewandt.

Hier ist ein typisches Beispiel für die Daten, die ich habe:

Segmente

Hier müsste ich das Segment 652 mit 198969 abgleichen, während 711 und 707 zu nichts passen.

Ich habe nach verschiedenen Methoden gesucht, insbesondere nach der Hausdorff-Distanz (basierend auf den Antworten hier ). Ich habe es mit PostGIS berechnet, aber ich erhalte merkwürdige Ergebnisse: Die kürzeste Entfernung, die ich erhalte, liegt zwischen 707 und 198985, und 652 hat eine größere Entfernung zu 198969 als zum Beispiel zu 198985 (ich kann die Abfrage und die Ergebnisse bei Bedarf hinzufügen).

Ist Hausdorff tatsächlich die richtige Methode, um dies zu lösen? Gibt es noch andere Ansätze? Ich habe überlegt, einfach eine Reihe von Überprüfungen der von mir genannten Parameter (Entfernung, Peilung usw.) durchzuführen, aber ich habe Angst, eine ganze Reihe von Bedingungen hinzufügen zu müssen, um Randfälle oder Dinge wie Schwellenwerte für deren Höhe zu behandeln Einander gegenüberstehen.

Update: Ich habe eine Methode gefunden, die als akzeptabler Kompromiss erscheint:

  • Ich finde zuerst die 10 nächsten schwarzen Segmente von dem blauen, das ich (mit dem PostGIS- <->Operator) abgleichen möchte und die weniger als 10 Meter entfernt sind.
  • Ich erstelle dann ein neues Segment, indem ich die nächsten Punkte zu den Enden des blauen Segments auf jedem der schwarzen finde (mit ST_ClosestPoint) und die Ergebnisse herausfiltere, deren Länge weniger als 90% des blauen ist (was bedeutet, dass die Segmente nicht sind) oder dass die Peilungsdifferenz mehr als ~ 20 ° beträgt)
  • Dann erhalte ich das erste Ergebnis sortiert nach Entfernung und Hausdorff-Entfernung, falls vorhanden.

Möglicherweise müssen einige Feinabstimmungen vorgenommen werden, aber es scheint vorerst eine akzeptable Arbeit zu leisten. Ich suche immer noch nach anderen Methoden oder zusätzlichen Überprüfungen, die ausgeführt werden sollen, wenn ich einige Randfälle verpasst habe.

Jukurrpa
quelle
1
Warum nicht einfach die Endpunkte der (blauen) Segmente verwenden, um mögliche Übereinstimmungen zwischen den Zielsegmenten (schwarz) zu identifizieren? Die gesuchten Segmentübereinstimmungen treten auf, wenn sich beide Endpunkte in der Nähe eines gemeinsamen Ziels befinden. Dies ist eine einfach auszuführende Abfrage. Diese Methode behandelt Abweichungen, die auf Fehler an den Positionen der Segmentendpunkte zurückzuführen sind, die ansonsten möglicherweise schwierig zu bewältigen sind: Beachten Sie, dass ein sehr kurzes (blaues) Segment eine wesentlich ungenauere Peilung aufweist als ein längeres Segment.
Whuber
1
Ja, ich versuche tatsächlich etwas in diese Richtung. Ich werde die Frage mit den Details aktualisieren.
Jukurrpa
1
Nicht sicher, ob ich Sie richtig verstehe, aber haben Sie versucht, Zentroide für blaue Linien zu erstellen und dann die Abstände zu den nächstgelegenen Linien zu überprüfen, sodass der kürzeste Abstand erhalten bleibt?
Cyril
1
Hallo Cyril, ich arbeite nicht mehr an diesem Problem, aber es ging auch darum, die blauen Segmente anhand ihrer Ausrichtung abzugleichen und wie weit sie den schwarzen Segmenten "zugewandt" sind. Was in diesem Fall bedeutet, dass 711 mit nichts übereinstimmen sollte, obwohl er ziemlich nahe an den schwarzen Segmenten ist
Jukurrpa

Antworten:

1

Hier sind ein paar Funktionen, die ich geschrieben habe, damit Sie tun können, was Sie tun müssen. Überprüfen Sie, ob es sich bei der Linie um eine Polylinie oder um ein Segment handelt, wenn die Linie durch eine Polylinie aufgelöst wird. Vergleichen Sie dann den Azimut und die Umkehrung des ersten Punkts und des letzten Punkts auf der Linie, und legen Sie die akzeptablen Kriterien für die Entscheidung des Codes fest. Dies sind arcpy-Methoden, die jedoch geändert werden können.

Rückgabe des Azimuts vom Liniensegment 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

Rückgabe invers von ESRI-Punkten

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

Polylinie in Liniensegment zerlegen

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

renn so durch deinen Tisch

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.....

diese eigenschaften sollten in postgis verfügbar sein - firstpoint, lastpoint, pointarray Ich nehme esri-eigenschaften an, da es das ist, was ich am besten kenne, aber die obigen können leicht geändert werden, um mit postgis zu arbeiten.

Gary Lester
quelle