Segmentos correspondentes de diferentes comprimentos

13

Estou tentando combinar pequenos segmentos com um segmento maior com o qual eles provavelmente estão mais relacionados: rolamentos relativamente próximos e similares, e de frente um para o outro.

Aqui está um exemplo típico dos dados que tenho:

segmentos

Aqui eu precisaria corresponder o segmento 652 a 198969, enquanto o 711 e o 707 não correspondiam a nada.

Procurei métodos diferentes, em particular a distância de Hausdorff (com base nas respostas aqui ). Eu o calculei usando o PostGIS, mas estou obtendo resultados ímpares: a menor distância que recebo é entre 707 e 198985, e 652 tem uma distância maior entre 198969 do que 198985, por exemplo (posso adicionar a consulta e os resultados, se necessário).

Hausdorff é realmente o método correto para resolver isso? Existem outras abordagens? Pensei em simplesmente criar um conjunto de verificações nos parâmetros que mencionei (distância, rumo, etc.), mas tenho medo de adicionar um monte de condições para lidar com casos extremos ou coisas como limitar o quanto eles são encarando um ao outro.

Atualização: Encontrei um método que parece ser um compromisso aceitável:

  • Encontro pela primeira vez os 10 segmentos pretos mais próximos do azul que estou tentando corresponder (usando o <->operador PostGIS ) a menos de 10 metros de distância.
  • Em seguida, crio um novo segmento localizando os pontos mais próximos às extremidades do segmento azul em cada um dos pretos (usando ST_ClosestPoint) e filtro os resultados cujo comprimento é menor que 90% do azul (o que significa que os segmentos não são virado, ou que a diferença de rolamento seja superior a ~ 20 °)
  • Então, recebo o primeiro resultado classificado por distância e distância de Hausdorff, se houver.

Pode haver algum ajuste fino a ser feito, mas parece fazer um trabalho aceitável por enquanto. Ainda estou procurando outros métodos ou verificações adicionais para executar, caso eu tenha perdido alguns casos extremos.

Jukurrpa
fonte
1
Por que não usar os pontos de extremidade dos segmentos (azuis) para identificar possíveis correspondências entre os segmentos de destino (pretos)? As correspondências do segmento que você procura ocorrem quando os dois pontos de extremidade estão próximos de um destino comum, que é uma consulta simples de executar. Esse método lida com discrepâncias causadas por erros nos locais dos pontos de extremidade do segmento, que de outro modo poderiam ser difíceis de lidar: observe que um segmento muito curto (azul) tem uma orientação muito menos precisa do que um segmento mais longo.
whuber
1
Sim, na verdade estou tentando algo nesse sentido, atualizarei a pergunta com os detalhes.
Jukurrpa
1
Não tenho certeza se o entendi corretamente, mas você tentou criar centróides para linhas azuis e depois verificar as distâncias delas até as linhas mais próximas, deixando a menor distância como resultado?
Cyril M
1
Olá Cyril, não estou mais trabalhando nesse problema, mas o problema também era combinar os segmentos azuis com base em sua orientação e quanto eles "enfrentavam" os segmentos pretos. Que meios, neste caso, que 711 não deve coincidir com qualquer coisa, mesmo que ele é muito próximo dos segmentos negros
Jukurrpa

Respostas:

1

Aqui estão algumas funções que escrevi que devem permitir que você faça o que precisa. Verifique e veja se a linha é polilinha ou segmento, se a polilinha explodir, então compare o azimute e o inverso do primeiro e do último ponto nas linhas, defina critérios aceitáveis ​​para o código tomar sua decisão. Estes são métodos arcpy, mas podem ser modificados.

retornar azimute do segmento de linha 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 dos pontos 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

explodir polilinha no segmento de linha

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

percorrer sua mesa como esta

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

essas propriedades devem estar disponíveis no postgis - firstpoint, lastpoint, pointarray Eu assumo as propriedades esri acima porque é o que eu sei melhor, mas o acima pode ser facilmente alterado para funcionar com o postgis.

Gary Lester
fonte