Окремі багатокутники засновані на перетині за допомогою PostGIS


36

У мене є таблиця полігонів PostGIS, де деякі перетинаються між собою. Це те, що я намагаюся зробити:

  • Для даного багатокутника, вибраного ідентифікатором, дайте мені всі багатокутники, які перетинаються. В основному,select the_geom from the_table where ST_Intersects(the_geom, (select the_geom from the_table where source_id = '123'))
  • З цих багатокутників мені потрібно створити нові багатокутники такі, що перетин стає новим багатокутником. Отже, якщо багатокутник A перетинається з багатокутником B, я отримаю 3 нові багатокутники: A мінус AB, AB і B мінус AB.

Якісь ідеї?


1
Гммм, я думаю, бачте, до чого ви потрапляєте, але проста графіка може творити чудеса, щоб допомогти мені (та іншим) побачити саме те, що ви хочете.
Джейсон

Додав декілька у мою відповідь.
Адам Матан

Відповіді:


29

Оскільки ви сказали, що ви отримуєте групу пересічних багатокутників для кожного цікавить вас багатокутника, ви можете створити те, що називається "перекриття полігону".

Це не зовсім те, що робить рішення Адама. Щоб побачити різницю, подивіться на цю картину перетину ABC:

Перетин ABC

Я вважаю, що рішення Адама створить багатокутник "AB", який охоплює і область "AB! C" і "ABC", а також полігон "AC", який охоплює "AC! B" і "ABC", і " BC "багатокутник, що є" BC! A "і" ABC ". Таким чином, вихідні багатокутники "AB", "AC" і "BC" все би перекривали область "ABC".

Перекриття багатокутника створює багатосхилі багатокутники, тому AB! C був би одним многокутником, а ABC - одним многокутником.

Створення багатокутного накладання в PostGIS насправді досить просто.

В основному три кроки.

Крок 1 - витяг лінійної роботи [Зверніть увагу, що я використовую зовнішнє кільце багатокутника, воно стає трохи складніше, якщо ви хочете правильно обробити отвори]:

SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines

Крок 2 - це "вузол" лінії (створити вузол на кожному перетині). У деяких бібліотеках, таких як JTS, є класи "Noder", які ви можете використовувати для цього, але в PostGIS функція ST_Union робить це за вас:

SELECT ST_Union(the_geom) AS the_geom FROM (...your lines...) AS noded_lines

Крок 3 - створити всі можливі неперекриваються багатокутники, які можуть надходити з усіх цих ліній, виконаних функцією ST_Polygonize :

SELECT ST_Polygonize(the_geom) AS the_geom FROM (...your noded lines...)

Ви можете зберегти висновок кожного з цих кроків у темп-таблиці, або можете об'єднати їх у один оператор:

CREATE TABLE my_poly_overlay AS
SELECT geom FROM ST_Dump((
    SELECT ST_Polygonize(the_geom) AS the_geom FROM (
        SELECT ST_Union(the_geom) AS the_geom FROM (
            SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines
        ) AS noded_lines
    )
)

Я використовую ST_Dump, оскільки вихід ST_Polygonize - це колекція геометрії, і, як правило, зручніше мати таблицю, де кожен рядок є одним з многокутників, що складається з накладання багатокутника.


Зверніть увагу, що ST_ExteriorRingвипадає будь-які отвори ST_Boundaryзбереже внутрішні кільця, але також створить багатокутник всередині них.
jpmc26

Об’єднання зовнішніх кілець руйнується, коли занадто багато багатокутників. На жаль, це "прямо" рішення працює лише для невеликих покриттів.
П’єр Расін

13

Якщо я правильно розумію, ви хочете взяти (A - ліва геометрія, B - права):

Зображення A∪B http://img838.imageshack.us/img838/3996/intersectab1.png

І витяг:

A ∖ AB

Зображення A ∖ AB http://img830.imageshack.us/img830/273/intersectab2.png

AB

Зображення AB http://img828.imageshack.us/img828/7413/intersectab3.png

і B ∖ AB

Зображення B ∖ AB http://img839.imageshack.us/img839/5458/intersectab4.png

Тобто - три різні геометрії для кожної пари, що перетинається.

Спочатку давайте створимо уявлення про всі пересічні геометрії. Припустимо, що назва вашої таблиці є polygons_table, ми будемо використовувати:

CREATE OR REPLACE VIEW p_intersections AS    -- Create a view with the 
SELECT t1.the_geom as t1_geom,               -- intersecting geoms. Each pair
       t2.the_geom as t2_geom                -- appears once (t2.id<t2.id)
    FROM polygons_table t1, polygons_table t2  
         WHERE t1.id<t2.id AND t1.the_geom && t2.the_geom 
                           AND intersects t1.the_geom, t2.the_geom;

Тепер у нас є перегляд (практично таблиця, доступна лише для читання), яка зберігає пари пересічних геомів, де кожна пара з’являється лише один раз через t1.id<t2.idумову.

Тепер давайте збирати ваші перехресть - A∖AB, ABі B∖AB, використовуючи SQL для UNIONвсіх трьох запитів:

--AB:
SELECT ST_intersection(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION 

--AAB:
SELECT ST_Difference(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION

--BAB:
SELECT ST_Difference(t2.the_geom, t1.the_geom) 
    AS geom 
    FROM p_intersections;

Примітки:

  1. &&Оператор використовується в якості фільтра перед intersectsоператором, щоб поліпшити продуктивність.
  2. Я вирішив створити VIEWзамість одного гігантського запиту; Це лише для зручності.
  3. Якщо ви мали на увазі ABоб'єднання, а не перетин, Aі B- Використовуйте ST_Union замість st_intersection у UNIONзапиті у відповідних місцях.
  4. Знак є юнікода знак різниці Set; видаліть його з коду, якщо він плутає вашу базу даних.
  5. Зображення люб'язно надано категорії «Теорія наборів» Wikimedia Commons .

Мій квиток на помилку на мета: meta.gis.stackexchange.com/questions/79/…
Адам Матан

Приємне пояснення! Результати такі ж, як у scw розчині, але його шлях повинен бути швидшим (не обчислює / чи зберігає / додаткові перехрестя A і B)
stachu

Спасибі! Я думаю, що я не зберігаю зайвої інформації, оскільки я створюю лише SQL VIEW, а не таблиці.
Адам Матан

Так, це правда, але ви обчислюєте додатковий перетин A і B, який не
потрібен

5
Зображення у цій відповіді більше не працюють.
Fezter

8

Ви описуєте те, як працює оператор Союзу в ArcGIS, але він дещо інший, ніж будь-який Союз або Перетин у світі GEOS. Посібник Shapely містить приклади того, як працюють набори в GEOS . Однак у вікі PostGIS є хороший приклад використання лінійної роботи, яка повинна зробити трюк для вас.

Можна також обчислити три речі:

  1. ST_Intersection (geom_a, geom_b)
  2. ST_Difference (geom_a, geom_b)
  3. ST_Difference (geom_b, geom_a)

Це повинні бути три багатокутники, про які ви згадали у своїй другій точці кулі.


2
Приклад вікі PostGIS хороший
відмітка

Чи не повернуться ST_Intersects булевими, якщо вони перетинаються чи ні? Я думаю, що ST_Intersection спрацює.
Джейсон

Так, друкарня з мого боку - зафіксовано в оригіналі зараз, дякую Джейсону!
scw

-2

Щось на зразок:

ВСТАВЛЯЙТЬСЯ в нові_таблиці ((виберіть id, the_geom від old_table, де st_intersects (the_geom, (виберіть the_geom від old_table, де id = '123')) = true

EDIT: потрібне фактичне перетин багатокутника.

ВСТАВЛЯЙТЕСЬ у нові_таблиці ((виберіть ідентифікатор, ST_Intersection (the_geom, (виберіть the_geom зі старого, де id = 123))

подивіться, чи це виходить.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.