PostGIS: Aproximando um número de casa do intervalo de endereços

8

Estou desenvolvendo um geocoder reverso para o Canadá. Até agora, com base em um lat / lng, posso encontrar a rua mais próxima (segmento de linha), que inclui a direção do segmento de linha e os intervalos de endereços dos dois lados da rua. Agora estou tentando descobrir a melhor maneira de aproximar programaticamente o número da casa mais próximo ao ponto de lat / lng especificado.

Aqui está um exemplo de uma linha que contém os dados da rua:

-[ RECORD 1 ]-
[...]
l_adddirfg | Same Direction
l_hnumf    | 3219
l_hnuml    | 3235
l_stname_c | Breen Road North-west
r_adddirfg | Same Direction
r_hnumf    | 3224
r_hnuml    | 3236
r_stname_c | Breen Road North-west
the_geom   | 0105000020E610000001000000010200000002000000B0F6990E78885CC088DF2B5F3C8C49400875B39A89885CC0A0BCA6AC4B8C4940

Assim, dada uma coordenada lat / lng que fica próxima ao segmento de linha "the_geom", uma pessoa pode dizer visualmente em que lado da rua o ponto está (lado esquerdo ou direito) e a que distância está o segmento - desse modo aproximando um número da casa. Por exemplo, se o ponto estiver do lado direito, três quartos abaixo da rua, eu usaria os campos r_hnumf (lado direito, primeiro número) e r_hnuml (lado direito, último número) ... O endereço provavelmente está próximo para:

3232 Breen Road North-west

O que eu estou procurando é uma prática recomendada em calcular / aproximar isso no PostGIS (do qual eu sou novo) ou na camada de aplicativo assim que a linha for buscada.

Obrigado!

René Fournier
fonte

Respostas:

11

A solução pode ser construída inteiramente no PostGIS.

Dado um ponto (localização da casa, eu o modelei como um PONTO) e um segmento de rua (segmento de rua mais próximo a este ponto, modelado como LINESTRING), você pergunta:

  • Como saber se o ponto está à esquerda de um segmento de rua

Uma solução possível é determinar o ponto no segmento de rua mais próximo da casa e, em seguida, determinar se esse ponto fica à esquerda ou à direita da casa (o operador &<retorna true se o primeiro argumento de geometria se sobrepuser ou estiver à esquerda de o segundo argumento da geometria). &<realmente funciona com caixas delimitadoras, mas como estamos trabalhando com pontos, isso não deve importar.

osm=# select 'POINT(4 1)'::geometry &< st_closestpoint('LINESTRING(1 1,2 3,6 6)'::geometry, 'POINT(4 1)'::geometry) as houseIsOnLeft;
 houseisonleft 
---------------
 f
(1 row)
  • A que distância fica a casa no segmento da rua

Novamente, isso se traduz em quanto tempo (um valor entre 0 e 1) no segmento da rua é o ponto na rua mais próximo da casa. Existe uma função interna para isso, chamada st_line_locate_point :

osm=# select st_line_locate_point('LINESTRING(1 1,2 3,6 6)'::geometry, 'POINT(2 1)'::geometry);
 st_line_locate_point 
----------------------
   0.0618033988749895
(1 row)

osm=# select st_line_locate_point('LINESTRING(1 1,2 3,6 6)'::geometry, 'POINT(5 6)'::geometry);
 st_line_locate_point 
----------------------
    0.889442719099992
(1 row)

Diagrama de cadeia de linhas e ponto usado acima

diciu
fonte