Como obter o ponto mais próximo de uma cadeia de linhas para um determinado ponto?

28

Estou usando o PostGIS há muito tempo, mas nunca tive que usar a LINESTRINGgeometria ...! :)

Aqui está o que eu gostaria de fazer: Eu tenho uma tabela de cadeias de linhas (representando ruas de uma determinada cidade, SRID 3395) e gostaria de encontrar as cadeias de linhas mais próximas de um determinado ponto (posição GPS, SRID 4326).

A solução que encontrei é selecionar todas as cadeias de linhas no meu ponto usando o expand()método e determinar a distância entre cada cadeia de linhas e meu ponto usando o ST_Distance()método.

Aqui está o SQL:

SELECT myLineId, myLineName, ST_Distance(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395),myLineGeom) AS myLineDistance
FROM myLines
WHERE myLineGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)
ORDER BY myLineDistance;

Os resultados parecem bons, mas sinto que algo está errado na minha implementação.

1) Vocês acham que expand()podem obter todas as cadeias de linhas em questão?

2) Vocês acham que ST_Distance()é o método certo para usar? Acho que estou fazendo errado, já que a distância que eu gostaria de obter é a menor distância entre o ponto e minha linha e não a distância entre o ponto e um dos pontos da cadeia de linhas.

Ilustração:

texto alternativo

Vivi
fonte

Respostas:

11

ad 1) Examinando a documentação para suas funções usadas, eu diria: "Sim, todas as cadeias de linhas envolvidas serão encontradas".

expandir (geometria, flutuar)

Esta função retorna uma caixa delimitadora expandida em todas as direções a partir da caixa delimitadora da geometria de entrada, por uma quantidade especificada no segundo argumento. Muito útil para consultas a distância (), para adicionar um filtro de índice à consulta.

A && B

O operador "&&" é o operador "sobreposições". Se a caixa delimitadora de A se sobrepuser à caixa delimitadora de B, o operador retornará verdadeiro.

anúncio 2) Você deve conseguir o que deseja via:

line_interpolate_point(linestring, line_locate_point(LineString, Point))

line_interpolate_point (cadeia de linhas, localização)

Interpola um ponto ao longo de uma linha. O primeiro argumento deve ser um LINESTRING. O segundo argumento é um float8 entre 0 e 1, representando a fração do comprimento total em 2d em que o ponto deve ser localizado.

line_locate_point (LineString, Point)

Retorna um ponto flutuante entre 0 e 1 representando a localização do ponto mais próximo em LineString ao ponto especificado, como uma fração do comprimento total da linha 2d. Você pode usar o local retornado para extrair um ponto (line_interpolate_point)

Fonte: http://main.merlin.com.ua/doc/postgis/docs/ch06.html

underdark
fonte
Para o ponto 2), eu estava pensando se ST_Distance entre uma geometria POINT e uma geometria LINESTRING oferece a menor distância possível entre teses (também conhecida como o comprimento da linha perpendicular entre o POINT e o LINGESTRING); Quero distância de cada geometria LINESTRING :)
Vivi
E acho que não é a distância que estou procurando, pois "a função line_locate_point fornece um valor entre 0 e 1, representando a localização do ponto mais próximo da LineString ao ponto especificado": /
Vivi
Receio que você tenha me perdido em seu último comentário. Agora não tenho mais certeza do que você deseja;)
underdark
1
Desculpe :) Gostaria do seguinte: fornecendo uma geometria LINESTRING (representando um caminho) e uma geometria POINT, quero ter a geometria POINT mais próxima que esteja no caminho (que pode não ser um ponto da definição de geometria LINESTRING). Está claro? Talvez eu deva atualizar meu post com um desenho: D
Vivi
Não consigo atualizar meu post então aqui está um link para um desenho do que eu gostaria de ter: i.imgur.com/UwPxo.jpg
Vivi
7

Hallo

Primeiro, a pergunta sobre o que ST_Distance retorna. ST_Distance retorna a menor distância entre a linha e o ponto (ou que tipos de geometria são inseridos) Isso significa que ST_Distance entre o ponto (1 3) e a cadeia de linhas (0 0,0 10) retornará 1. A distância não será medida entre o ponto e (0 0) ou o ponto e (0 10) mas do ponto (1 3) a (0 3).

Então, pelo que entendi, ST_Distance dá a resposta que você deseja.

Se você deseja encontrar o ponto (0 3) no exemplo acima, pode usar ST_Closestpoint se tiver o PostGIS 1.5. Para o meu exemplo, use-o assim: ST_Closestpoint ('LINESTRING (0 0,0 10)' :: geometry, ' POINT (1 3) ':: geometry), então você deve obter o ponto (0 3) em retorno, o ponto na linha que está mais próximo do seu ponto.

HTH Nicklas

Nicklas Avén
fonte
5

Eu encontrei :) (Bem, eu acho: P)

Usando o ST_Line_Locate_Point()e ST_Line_Interpolate_point()eu consegui obter um ponto que NÃO faz parte da definição LINESTRING, mas ESTÁ na linha mencionada :) Tudo o que tenho a fazer é obter a distância do meu ponto até esse ponto e pronto.

SELECT AsText(ST_Line_Interpolate_Point(myLineGeom,ST_Line_Locate_Point(myLineGeom,ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395))))
FROM myLines
WHERE myGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)

O ST_Line_Locate_Point()método encontra a localização do ponto mais próximo da linha ao ponto especificado, o ST_Line_Interpolate_Pointmétodo transforma essa localização em um ponto.

Vivi
fonte
1
St_distance entre o ponto e a linha lhe dará a mesma resposta. Por que você acha que precisa fazer dessa maneira?
Nicklas Avén
1
Eu acho que ST_Distance pode ser usado com qualquer tipo de geometria. postgis.refractions.net/docs/ST_Distance.html :ST_Distance(geometry g1, geometry g2)
Magno C
2

Este tópico do Postgis pode responder http://postgis.refractions.net/pipermail/postgis-users/2007-June/016045.html

ThomasG77
fonte
refractions.net não funciona para mim: "refractions.net expirou em 14/09/2010 e está pendente de renovação ou exclusão".
underdark
@underdark ele trabalha para mim
dassouki
@dassouki: isso é estranho: |
underdark
@underdark refractions.net trabalha novamente
ThomasG77