PostGIS: Atribuir ID do ponto na camada A ao ponto mais próximo da camada B

15

Isso deveria ter sido um precursor óbvio (que eu não perguntei) para minha outra pergunta: Como criar diagramas de aranha (linhas de cubo) no PostGIS?

Se eu não souber a relação entre um ponto na camada A (lojas) e um ponto na camada B (clientes), gostaria de dizer geralmente "O cliente 1 é atendido pela loja mais próxima". Embora eu saiba que esse fato pode não ser verdade, pode ser um substituto decente.

Usando o PostGIS, qual é a maneira mais eficiente de atribuir o ID do ponto mais próximo na camada A (lojas) a cada ponto na camada B (clientes). A saída que estou procurando é algo como abaixo.

Customer | Store
    1    |   A
    2    |   A
    3    |   B
    4    |   C
RyanKDalton
fonte

Respostas:

6

Da mesma forma:

selecione A.ID como CUST_ID, (selecione B.ID da ordem B por st_distance (A.geom, B.geom) limite 1) como STORE_ID de A

eprand
fonte
Essa foi a melhor maneira de realizar a tarefa. Veja minha nota abaixo para obter o código real que eu usei.
RyanKDalton
8

Parece que se você tem muito mais clientes do que as lojas, pode ser mais eficiente criar uma camada de polígonos voronoi para as lojas e fazer uma junção espacial de clientes contra os polígonos da loja.

Kirk Kuykendall
fonte
1
Eu gosto dessa abordagem!
Underdark
Qual abordagem seria mais fácil de criar polis voronoi? Existem outras opções além das mencionadas aqui: bostongis.com/… bostongis.com/…
RyanKDalton
Eu acho que o pacote de triangulação e dirichlet de Delaunay no segundo tutorial seria apropriado, mas não tenho certeza se é o mais fácil.
precisa saber é o seguinte
5

Em http://www.bostongis.com/?content_name=postgis_nearest_neighbor :

Se você precisou obter o vizinho mais próximo para todos os registros em uma tabela, mas precisa apenas do primeiro vizinho mais próximo para cada um, então você pode usar a sintaxe distintiva DISTINCT ON do PostgreSQL. O que seria algo parecido com isto:

SELECT DISTINCT ON(g1.gid)  g1.gid As gref_gid, 
       g1.description As gref_description, 
       g2.gid As gnn_gid, 
       g2.description As gnn_description  
FROM sometable As g1, sometable As g2   
WHERE g1.gid <> g2.gid 
      AND ST_DWithin(g1.the_geom, g2.the_geom, 300)   
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom) 

Isso encontrará distâncias mínimas de até 300 unidades. Portanto, você deve primeiro verificar seus dados e descobrir o tamanho das distâncias mínimas.

underdark
fonte
3

Obrigado pela contribuição de todos. Finalmente, fui com uma combinação de sugestões de eprand e underdark. O código final que usei foi:

CREATE TABLE closest_point as
SELECT DISTINCT ON (A.GID) A.GID AS CUST_ID, 
      (SELECT B.GID FROM "STORES" as B 
       ORDER BY ST_Distance(A.the_geom, B.the_geom) limit 1) as STORE_ID, 
       A.the_geom 
FROM "CUSTOMERS" as A, "STORES" as B;

Criei um diagrama de voronoi na camada de lojas para confirmar que os resultados funcionaram corretamente, o que é claro que eles fizeram. Obrigado pelo excelente trabalho de todos!

RyanKDalton
fonte