Segmentos coincidentes de diferentes longitudes

13

Estoy tratando de hacer coincidir segmentos pequeños con un segmento más grande con el que probablemente estén más relacionados: relativamente cerca, rumbo similar y uno frente al otro.

Aquí hay un ejemplo típico de los datos que tengo:

segmentos

Aquí tendría que hacer coincidir el segmento 652 con 198969, mientras que 711 y 707 no coinciden con nada.

He buscado diferentes métodos, en particular la distancia de Hausdorff (basada en las respuestas aquí ). Lo calculé usando PostGIS pero obtengo resultados extraños: la distancia más corta que obtengo es entre 707 y 198985, y 652 tiene una distancia mayor a 198969 que a 198985, por ejemplo (puedo agregar la consulta y los resultados si es necesario).

¿Es Hausdorff realmente el método correcto para resolver esto? ¿Hay otros enfoques? Pensé en simplemente crear un conjunto de comprobaciones en los parámetros que mencioné (distancia, rumbo, etc.), pero tengo miedo de tener que agregar un montón de condiciones para manejar casos extremos o cosas como el umbral de cuánto son uno frente al otro.

Actualización: encontré un método que parece un compromiso aceptable:

  • Primero encuentro los 10 segmentos negros más cercanos del azul que estoy tratando de igualar (usando el <->operador PostGIS ) que están a menos de 10 metros de distancia.
  • Luego creo un nuevo segmento al encontrar los puntos más cercanos a los extremos del segmento azul en cada uno de los negros (usando ST_ClosestPoint) y filtrar los resultados cuya longitud es inferior al 90% del azul (lo que significa que los segmentos no son frente, o que la diferencia de demora es más de ~ 20 °)
  • Luego obtengo el primer resultado ordenado por distancia y distancia de Hausdorff, si corresponde.

Puede haber algunos ajustes finos que hacer, pero parece hacer un trabajo aceptable por ahora. Todavía estoy buscando otros métodos o verificaciones adicionales para ejecutar si me perdí algunos casos extremos.

Jukurrpa
fuente
1
¿Por qué no usar los puntos finales de los segmentos (azules) para identificar posibles coincidencias entre los segmentos (negros) objetivo? Las coincidencias de segmento que busca se producen cuando ambos puntos finales están cerca de un objetivo común, que es una consulta simple de ejecutar. Este método maneja las discrepancias que se deben a errores en las ubicaciones de los puntos finales del segmento, que de lo contrario podrían ser difíciles de manejar: observe que un segmento muy corto (azul) tiene una demora mucho menos precisa que un segmento más largo.
whuber
1
Sí, en realidad estoy intentando algo en este sentido, actualizaré la pregunta con los detalles.
Jukurrpa
1
No estoy seguro si lo entiendo correctamente, pero ¿ha tratado de crear centroides para líneas azules y luego verifica las distancias desde ellos hasta las líneas más cercanas, dejando como resultado la distancia más corta?
Cyril M
1
Hola, Cyril, ya no estoy trabajando en este problema, pero el problema también era hacer coincidir los segmentos azules según su orientación y cuánto están "enfrentando" a los segmentos negros. Lo que significa que en este caso el 711 no debería coincidir con nada a pesar de que está bastante cerca de los segmentos negros
Jukurrpa

Respuestas:

1

Aquí hay un par de funciones que escribí que deberían permitirle hacer lo que necesita hacer. Verifique y vea si la línea es polilínea o segmento si la polilínea explota la línea, luego compare el acimut y el inverso del primer punto y el último punto en las líneas, establezca criterios aceptables para que el código tome una decisión por usted. Estos son métodos arcpy pero podrían modificarse.

devolver azimut desde el segmento de línea 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

retorno inverso desde puntos 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

explotar polilínea en segmento de línea

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

recorre tu mesa así

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

estas propiedades deberían estar disponibles en postgis: primer punto, último punto, pointarray. Supongo que las propiedades de esri anteriores son las que mejor conozco, pero lo anterior se puede cambiar fácilmente para que funcione con postgis.

Gary Lester
fuente