PostGIS: Asigne la ID del punto en la capa A al punto más cercano en la Capa B

15

Esto debería haber sido un precursor obvio (que no pregunté) a mi otra pregunta: ¿Cómo crear diagramas de araña (líneas de cubo) en PostGIS?

Si no conozco la relación entre un punto en la capa A (tiendas) y un punto en la capa B (clientes), en general me gustaría decir "La tienda más cercana atiende al Cliente 1". Si bien me doy cuenta de que este hecho puede no ser cierto, puede ser un sustituto decente.

Usando PostGIS, cuál es la forma más eficiente de asignar la ID del punto más cercano en la capa A (tiendas) a cada punto en la capa B (clientes). El resultado que estoy buscando es algo como a continuación.

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

Respuestas:

6

igualmente:

seleccione A.ID como CUST_ID, (seleccione B.ID del orden B por st_distance (A.geom, B.geom) límite 1) como STORE_ID de A

eprand
fuente
Esta fue la mejor manera de lograr la tarea. Vea mi nota a continuación para ver el código real que utilicé.
RyanKDalton
8

Parece que si tiene muchos más clientes que tiendas, entonces podría ser más eficiente crear una capa de polígonos voronoi para las tiendas, luego hacer una unión espacial de clientes contra los polígonos de la tienda.

Kirk Kuykendall
fuente
1
Me gusta este enfoque!
oscuro
¿Qué enfoque sería más fácil de crear voronoi polys? ¿Hay otras opciones que se señalan aquí: bostongis.com/… bostongis.com/…
RyanKDalton
Creo que el paquete de triangulación y Dirichlet de Delaunay en el segundo tutorial sería apropiado, aunque no estoy seguro de si es el más fácil.
Kirk Kuykendall el
5

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

Si necesita obtener el vecino más cercano para todos los registros en una tabla, pero solo necesita el primer vecino más cercano para cada uno, puede usar la sintaxis DISTINCT ON distintiva de PostgreSQL. Lo que se vería así:

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) 

Esto encontrará distancias mínimas de hasta 300 unidades. Por lo tanto, primero debe verificar sus datos y averiguar qué tan grandes serán sus distancias mínimas.

bajo oscuro
fuente
3

Gracias por el aporte de todos. Finalmente fui con una combinación de las sugerencias de Eprand y Underdark. El código final que utilicé fue:

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;

Luego creé un diagrama de voronoi en la capa de tiendas para confirmar que los resultados funcionaron correctamente, lo que por supuesto lo hicieron. Gracias por el gran trabajo de todos!

RyanKDalton
fuente