Привязка начального и конечного узлов линий к другим строкам в PostGIS
9
Существует множество примеров, показывающих, как привязывать линии к точкам, но я не смог найти (быстрого!) Способа привязать начальный и конечный узлы строк к узлам других линий.
По сути, я хочу «очистить» свой слой в postgis (2.0), переместив почти одинаковые точки вместе и сшив крошечные отверстия между строками строк.
Не имеет большого значения, добавлю ли я другой узел, переместлю первый / последний узел любой линии или переместлю обе точки в центр.
Я нашел два варианта, но я не уверен, как начать с любого из них:
Мне удалось решить эту проблему, не используя упомянутые инструменты GRASS или топологические функции.
По сути, я беру все начальные и конечные узлы, помещаю их в новую временную таблицу, помещаю вокруг них буфер, объединяю объекты буфера и перемещаю все найденные узлы в каждом буфере в центр тяжести буфера.
Когда это сделано, я перемещаю исходные точки начала и конца в новое место.
Проще, чем ожидалось, и все еще быстро, но я ожидал, что PostGIS будет иметь некоторую встроенную функцию для этого - это будет еще быстрее.
Изменить: в интересах возвращения к сообществу, это мой (довольно дерьмовый) код на данный момент.
droptableifexists nodes;droptableifexists nodes2;droptableifexists buffers;-- Get Start and End nodesselect ST_StartPoint(wkb_geometry) startnode, ST_EndPoint(wkb_geometry) endnode, ogc_fid into nodes from sourceTable;-- Combine all nodes into one table for easier queriesselect startnode node, ogc_fid into nodes2 from nodes;insertinto nodes2 select endnode node, ogc_fid from nodes;-- Some indexes to speed everything upCREATEINDEX nodesstart_idx ON nodes USING gist (startnode);CREATEINDEX nodesend_idx ON nodes USING gist (endnode);CREATEINDEX nodes2_idx ON nodes2 USING gist (node);CREATEINDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);-- Create buffers, combine them, split combined objects againselect(ST_Dump(ST_Union(ST_Buffer(node,1)))).geom geom into buffers from nodes2;CREATEINDEX buffers_idx ON buffers USING gist (geom);-- Update start/end nodes tableUPDATE nodes SET startnode = ST_Centroid((select geom from buffers WHERE geom && startnode));UPDATE nodes SET endnode = ST_Centroid((select geom from buffers WHERE geom && endnode));-- Update original pointsupdate sourceTable set wkb_geometry = ST_SetPoint(
ST_SetPoint(wkb_geometry,0,(select startnode from nodes where ogc_fid=sourceTable.ogc_fid)),
ST_NumPoints(wkb_geometry)-1,(select endnode from nodes where ogc_fid=sourceTable.ogc_fid));DROPTABLE nodes;DROPTABLE nodes2;DROPTABLE buffers;
Этот ответ очень похож на «нетопологическое» предположение из моего ответа. Было бы любезно, если бы вы дали ответ или выбрали ответ. Это то, что кормит сообщество здесь :)
katahdin
Вы правы. Я отклонил ваш ответ и отредактирую свой ответ, включив в него мой код.
Джелмер Баас
4
Вот три варианта. Надеюсь, один поможет.
v.clean
Используя инструменты GRASS в QGIS, вы можете очистить топологию пространственного объекта. Пользователь @RK дает хороший набор инструкций о том, как это сделать, отвечая на другой вопрос . Преимущество, которое дает GRASS, заключается в том, что он будет выводить топологию шейп-файла. Недостатком вашей ситуации является то, что ваши данные не находятся в шейп-файле. Конечно, вы можете экспортировать данные из Postgres в шейп-файл, используя инструмент «Добавить слой PostGIS», но это дополнительный шаг.
Нетопологические функции PostGIS
В PostGIS вы можете использовать функции ST_EndPoint и ST_StartPoint, чтобы получить конечную и начальную точку строки. Затем, используя комбинацию ST_DWithi n и ST_Distance , вы можете найти ближайшую начальную или конечную точку на ближайшей геометрии. Если у вас много точек, то ST_DWithin сильно ускорит запрос - при условии, что у вас есть индекс. Оттуда вам нужно будет установить правило, которое определяет, какие точки должны быть изменены, а какие зафиксированы.
Преимущество здесь в том, что вам не нужно отправлять свои данные в GRASS для очистки, но есть некоторые подводные камни, на которые стоит обратить внимание.
Топологические функции PostGIS
Вопрос касался топологических функций PostGIS. Они прекрасно работают, но, как описывает вики , вы должны явно определить ребра, узлы и грани. Очевидно, это будет проблемой для вашего набора данных, поскольку у вас есть известные проблемы с топологией.
Спасибо, я в курсе этих функций. ST_Snap привязывает ВСЕ узлы, я хочу только начальный и конечный узел. ST_SnapToGrid на самом деле не подходит, потому что он изменяет всю существующую геометрию и может перемещать узлы, которые находятся ближе друг к другу, потому что они едва попадают в другой сегмент.
Вот три варианта. Надеюсь, один поможет.
v.clean
Используя инструменты GRASS в QGIS, вы можете очистить топологию пространственного объекта. Пользователь @RK дает хороший набор инструкций о том, как это сделать, отвечая на другой вопрос . Преимущество, которое дает GRASS, заключается в том, что он будет выводить топологию шейп-файла. Недостатком вашей ситуации является то, что ваши данные не находятся в шейп-файле. Конечно, вы можете экспортировать данные из Postgres в шейп-файл, используя инструмент «Добавить слой PostGIS», но это дополнительный шаг.
Нетопологические функции PostGIS
В PostGIS вы можете использовать функции ST_EndPoint и ST_StartPoint, чтобы получить конечную и начальную точку строки. Затем, используя комбинацию ST_DWithi n и ST_Distance , вы можете найти ближайшую начальную или конечную точку на ближайшей геометрии. Если у вас много точек, то ST_DWithin сильно ускорит запрос - при условии, что у вас есть индекс. Оттуда вам нужно будет установить правило, которое определяет, какие точки должны быть изменены, а какие зафиксированы.
Преимущество здесь в том, что вам не нужно отправлять свои данные в GRASS для очистки, но есть некоторые подводные камни, на которые стоит обратить внимание.
Топологические функции PostGIS
Вопрос касался топологических функций PostGIS. Они прекрасно работают, но, как описывает вики , вы должны явно определить ребра, узлы и грани. Очевидно, это будет проблемой для вашего набора данных, поскольку у вас есть известные проблемы с топологией.
источник
У PostGIS есть функции привязки .. может быть, они помогут?
ST_Snap
: Привязка сегментов и вершин входной геометрии к вершинам эталонной геометрии.ST_SnapToGrid
: Привязать все точки входной геометрии к регулярной сетке.источник