PostGIS: присвоить ID точки в слое A ближайшей точке в слое B

15

Это должно было быть очевидным предшественником (который я не задавал) к моему другому вопросу: Как создать диаграммы паука (линии центра) в PostGIS?

Если я не знаю взаимосвязи между точкой на уровне A (магазины) и точкой на уровне B (клиенты), я бы хотел сказать, что «Клиент 1 обслуживается ближайшим магазином». Хотя я понимаю, что этот факт не может быть правдой, это может быть достойной заменой.

Используя PostGIS, каков наиболее эффективный способ присвоения идентификатора ближайшей точки в слое A (магазины) каждой точке в слое B (клиенты). Вывод, который я ищу, выглядит примерно так.

Customer | Store
    1    |   A
    2    |   A
    3    |   B
    4    |   C
RyanKDalton
источник

Ответы:

6

также:

выберите A.ID в качестве CUST_ID, (выберите B.ID из B-порядка на st_distance (A.geom, B.geom) limit 1) в качестве STORE_ID из A

eprand
источник
Это был лучший способ выполнить задачу. Смотрите мою заметку ниже для реального кода, который я использовал.
RyanKDalton
8

Похоже, что если у вас гораздо больше покупателей, чем в магазинах, то может быть более эффективно создать слой многоугольников вороной для магазинов, а затем создать пространственное объединение покупателей с магазинами полигонов.

Кирк Куйкендалл
источник
1
Мне нравится этот подход!
Подземье
Какой подход будет проще всего создать вороной полис? Есть ли другие варианты, которые отмечены здесь: bostongis.com/… bostongis.com/…
RyanKDalton
Я думаю, что пакет Delaunay Triangulation and Dirichlet во втором уроке будет уместным, хотя я не уверен, что он самый простой.
Кирк Кайкендалл
5

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

Если вам нужно получить ближайшего соседа для всех записей в таблице, но вам нужен только первый ближайший сосед для каждой, тогда вы можете использовать особый синтаксис DISTINCT ON в PostgreSQL. Который будет выглядеть примерно так:

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) 

Это позволит найти минимальные расстояния до 300 единиц. Итак, вы должны сначала проверить свои данные и выяснить, насколько велики будут ваши минимальные расстояния.

Подземье
источник
3

Вы должны найти самую короткую пару в окне поиска, и если в коробке ничего нет, разверните ее. Это не красиво, но это работает. Здесь приведен пример кода PL / PgSQL http://trac.osgeo.org/postgis/wiki/UsersWikiNearest

Пол Рэмси
источник
3

Спасибо за вклад каждого. В конечном итоге я согласился с сочетанием предложений Эпранда и Подземья. Последний код, который я использовал, был:

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;

Затем я создал диаграмму Вороного в слое магазинов, чтобы убедиться, что результаты работают правильно, что, конечно, они и сделали. Спасибо всем за отличную работу!

RyanKDalton
источник