Как объединить смежные полигоны в 1 полигон и сохранить минимальные/максимальные данные?

У меня есть следующие полигоны в PostGIS

введите здесь описание изображения

У каждого полигона есть поле со значением «Данные». Я хотел бы автоматически объединить полигоны, которые соприкасаются друг с другом: 1-2 и 3-4-5-6-7

Кроме того, если возможно, я хотел бы, чтобы значения Min/Max из столбцов каждого многоугольника сохранялись в новом многоугольнике.

Id  Data    Geom
1   8.45098 MULTIPOLYGON(((178253.411393551 665205.232423685,178248.411393552 665205.232423685,178248.411393552 665210.232423684,178253.411393551 665210.232423684,178253.411393551 665205.232423685)))
2   10.7918 MULTIPOLYGON(((178258.411393551 665205.232423685,178253.411393551 665205.232423685,178253.411393551 665210.232423684,178258.411393551 665210.232423684,178258.411393551 665205.232423685)))
3   10.7918 MULTIPOLYGON(((178263.411393552 665185.232423682,178258.411393551 665185.232423682,178258.411393551 665190.232423685,178263.411393552 665190.232423685,178263.411393552 665185.232423682)))
4   10.4139 MULTIPOLYGON(((178268.411393553 665185.232423682,178263.411393552 665185.232423682,178263.411393552 665190.232423685,178268.411393553 665190.232423685,178268.411393553 665185.232423682)))
5   7.448   MULTIPOLYGON(((178263.411393552 665180.232423684,178258.411393551 665180.232423684,178258.411393551 665185.232423682,178263.411393552 665185.232423682,178263.411393552 665180.232423684)))
6   10.2318 MULTIPOLYGON(((178268.411393553 665180.232423684,178263.411393552 665180.232423684,178263.411393552 665185.232423682,178268.411393553 665185.232423682,178268.411393553 665180.232423684)))
7   10.998  MULTIPOLYGON(((178263.411393552 665175.232423685,178253.411393551 665175.232423685,178253.411393551 665180.232423684,178258.411393551 665180.232423684,178263.411393552 665180.232423684,178263.411393552 665175.232423685)))
8   10.7548 MULTIPOLYGON(((178263.411393552 665175.232423685,178253.411393551 665175.232423685,178253.411393551 665180.232423684,178258.411393551 665180.232423684,178263.411393552 665180.232423684,178263.411393552 665175.232423685)))

Как это будет сделать проще всего (у меня мало знаний в QGIS/ArcMap и лучше в PostGIS)?


person Alophind    schedule 22.11.2014    source источник
comment
Я обновил свой первоначальный неправильный ответ. Написал не проверив, так как не перед компом, извините.   -  person John Powell    schedule 25.11.2014
comment
Спасибо, что уделили время, чтобы ответить на этот вопрос, я новичок в postgres, и синтаксис такой странный (взято из mssql), я рассмотрю его позже. Спасибо !!!!   -  person Alophind    schedule 26.11.2014
comment
:-) Я также пришел из MySQL, поэтому я понимаю, откуда вы пришли с синтаксисом, это странный комментарий. Для пространственных (и многих других вещей) Postgres/Postgis выбивает MySQL из воды, как только вы к нему привыкнете. Что бы это ни стоило, такие вещи, как CTE (WITH-запросы), поддерживаются также в Oracle и SQL Server, так что это действительно MySQL, который является странным.   -  person John Powell    schedule 26.11.2014
comment
Я пишу функции (например, хранимые процедуры в MSSQL) и все еще изучаю все пространственные функции ... Не по теме - Какую программу вы используете для запросов PostGIS? пгадмин ? Навикат? ... Как вы визуализируете данные? :)   -  person Alophind    schedule 26.11.2014
comment
Я пишу практически все свои запросы в psql в командной строке Linux (старая школа, я знаю). Для визуализации я либо использую OpenLayers с WKT или GeoJSON, либо, если геометрия действительно сложная, я использую инструмент pgsql2shp для создания файлов shp и открываю их в удивительно хорошем и бесплатном (как в пиве и речи) QGIS. Если вы начинаете работать с ГИС, QGIS — действительно замечательный продукт. Итак, да, довольно много материала с открытым исходным кодом — и мое знакомство с ИТ заключалось в написании макросов Excel vba для Windows. Забавный старый мир.   -  person John Powell    schedule 26.11.2014
comment
Я неправильно прочитал ваш предыдущий комментарий, вы сказали, что Msql не mysql. На самом деле, сейчас SQL-сервер имеет очень хорошую пространственную поддержку, но это несколько обратный способ работы функций, вы делаете geom.STBuffer(1), а не ST_Buffer(geom, 1), потому что они на самом деле являются функциями CLR.   -  person John Powell    schedule 26.11.2014
comment
У меня QGIS 2.4, но там перестал работать плагин OSM... и мне нужен растр OGM/BING/Google для фона полигонов. Можно попробовать более новую или старую версию QGIS.   -  person Alophind    schedule 26.11.2014


Ответы (2)


Единственный способ, которым я мог понять, как это сделать, состоял в том, чтобы создать таблицу объединенных геометрий в CTE, использовать ST_Dump для создания отдельных полигонов (т.е. 1-2 и 3-4-5-6 в вашем вопросе), а затем выберите максимальные и минимальные значения атрибутов данных из исходной таблицы (которые я назвал полигонами, поскольку вы не указали имя), которые пересекаются с новыми объединенными геометриями, и сгруппируйте по одним и тем же новым объединенным геометриям.

WITH geoms (geom) as 
   (SELECT (ST_Dump(ST_Union(geom))).geom from polygons) 
SELECT max(data), min(data), g.geom
   FROM polygons p, geoms g 
   WHERE St_Intersects(s.geom, g.geom)
   GROUP BY g.geom;

Если вы хотите сохранить это в новую таблицу, добавьте CREATE TABLE new_table AS перед WITH. Возможно, есть более эффективный способ, но этот работает. В вашем вопросе ваши входные полигоны являются MutliPolygons, поэтому, если вы хотите, чтобы это было и на выходе, добавьте ST_Multi перед новой объединенной геометрией. Собрав все вместе, вы получите что-то вроде:

CREATE TABLE Unioned_geometries AS
  WITH geoms (geom) as 
    (SELECT (ST_Dump(ST_Union(geom))).geom from polygons) 
  SELECT max(data), min(data), ST_Multi(g.geom)
    FROM polygons p, geoms g 
    WHERE St_Intersects(s.geom, g.geom)
    GROUP BY g.geom;
person John Powell    schedule 23.11.2014

Вы можете использовать ST_Dump и ST_Union, но у вас будут проблемы с большими данными, если вы ОБЪЕДИНИТЕ миллионы полигонов, ваша геометрия будет очень-очень сложной, а PostGIS не предназначен для работы с большими, сложными геометриями. Вы можете использовать топологию или что-то вроде этого

CREATE TABLE block_buildings AS                                                 
SELECT                                                                          
block_id                                                                        
, ST_MemUnion(geometry)                                                         

FROM houses building                                                            
, LATERAL (                                                                     
   with recursive building_block AS (                                           
      SELECT building.id                                                        
      UNION                                                                     
      SELECT building2.id FROM building_block                                   
      JOIN houses build_geom USING(id)                                          
      JOIN houses building2                                                     
      ON st_dwithin(build_geom.geometry, building2.geometry, 0.5)               
   )                                                                            
   SELECT md5(string_agg(id::text, ',' order by id)) block_id FROM building_block JOIN houses USING(id)
) block                                                                         
GROUP BY block_id                                                               
; 

LATERAL работает как цикл for, подзапрос выполняется для каждой строки. WITH recursive — обычное табличное выражение, оно работает рекурсивно, как снежный ком. ST_DWithin используется из-за оптимизации, вы можете использовать дамп исходящих геометрий, если хотите объединить только полигоны с общей границей или перекрытия. Он медленный, но потребляет не так много памяти (из-за латераля), его можно оптимизировать (например, с помощью plpgsql), потому что каждая группа вычисляется для всех своих полигонов. Но вы можете использовать в агрегатном запросе некоторые агрегаты для atrs. Если вы будете создавать только геометрию, вы можете агрегировать атрибуты с помощью ST_With и ST_PointOnSurface, это довольно быстро, если хорошо проиндексировано.

-------- edit В актуальном PostGIS есть функции для кластеризации

это или это или это

Это функции

person Jelen    schedule 22.04.2018
comment
Этот запрос блестящий. Попробовал принятый ответ и сдался после одного дня работы, этот запрос занял 7 минут для той же задачи. - person Vesanto; 30.10.2019