У меня есть таблица PostGIS polygon_b
с некоторыми функциями многоугольника. Также есть таблица, polygon_a
которая содержит те же полигоны, что и polygon_b
с небольшими изменениями. Теперь я хочу создать линии, чтобы визуализировать различия между полигонами.
Я предполагаю, что так ST_ExteriorRing
и ST_Difference
сделаю свою работу, но предложение WHERE кажется довольно сложным.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, yourSRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
-- ?
) AS g;
Может кто-нибудь мне помочь?
РЕДАКТИРОВАТЬ 1
Как и в «Tilt» я пытался, ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)
но результат не так, как ожидалось.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, your_SRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom))
AS g;
РЕДАКТИРОВАТЬ 2
workupload.com/file/J0WBvRBb (пример набора данных)
Я пытался превратить полигоны в мультилинии перед использованием ST_Difference, но результаты все еще странные.
CREATE VIEW multiline_a AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_a.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_a;
CREATE VIEW multiline_b AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_b.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_b;
CREATE VIEW line_difference AS SELECT
row_number() over() as gid,
g.geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(multiline_a.geom, multiline_b.geom)))).geom::geometry(linestring, 4326) AS geom
FROM
multiline_a, multiline_b)
As g;
источник
Ответы:
Вот несколько новых приемов, использующих:
EXCEPT
удалить из любой таблицы одинаковые геометрии, поэтому мы можем сосредоточиться только на геометриях, уникальных для каждой таблицы (A_only
иB_only
).ST_Snap
чтобы получить точное кодирование для операторов наложения.ST_SymDifference
оператор наложения, чтобы найти симметричное различие между двумя наборами геометрии, чтобы показать различия. Обновление :ST_Difference
показывает тот же результат для этого примера. Вы можете попробовать любую функцию, чтобы увидеть, что они получают.Это должно получить то, что вы ожидаете:
Чтобы распаковать этот ответ немного больше, первый шаг с
ST_Boundary
получает границу каждого многоугольника, а не только внешность. Например, если бы были дыры, они были бы прослежены границей.EXCEPT
Пункт используется для удаления геометрии из A , которые являются частью B и строки из B , которые являются частью A. Это уменьшает количество строк , которые являются частью только A и часть B только. Например, чтобы получить A_only:Вот 6 строк A_only и 3 строки B_only:
Далее,
ST_Union(DISTINCT A_only.geom)
используется для объединения линий в единую геометрию, обычно MultiLineString.ST_Snap используется для привязки узлов из одной геометрии в другую. Например
ST_Snap(A, B, tol)
, возьмем геометрию A и добавим больше узлов из геометрии B или переместим их в геометрию B, если они находятся наtol
расстоянии. Возможно, есть несколько способов использовать эти функции, но идея состоит в том, чтобы получить координаты от каждой геометрии, которые являются точными друг к другу. Таким образом, две геометрии после привязки выглядят так:И показать различия, вы можете использовать либо
ST_SymDifference
илиST_Difference
. Они оба показывают одинаковый результат для этого примера.источник
Я думаю, что это немного сложно, из-за разных наборов узлов обоих полигонов (зеленый многоугольник A, красный разные сегменты многоугольника B). Сравнение сегментов обоих полигонов дает представление о том, какие сегменты полигона B будут изменены.
Узлы полигона А
Узлы "разных" сегментов многоугольника B
К сожалению, это показывает только разницу в структуре сегмента, но я надеюсь, что это отправная точка, и она работает так:
После загрузки и распаковки я импортировал набор данных, используя PostgrSQL 9.46, PostGIS 2.1 под Debian Linux Jessie с командами.
Предполагая, что сегменты полигона A не находятся в B и наоборот, я пытаюсь построить разницу между сегментами обоих наборов полигонов, пренебрегая принадлежностью сегмента к полигонам в каждой группе (A или B). По дидактическим причинам я формулирую SQL в нескольких видах.
В соответствии с этим постом GIS-SE я разлагаю оба полигона на таблицы сегментов
segments_a
иsegments_b
Сегмент таблицы многоугольника А:
Та же самая процедура была применена к многоугольнику B.
Сегмент настольный многоугольник B
Я могу построить представление таблицы различий с именем
segments_diff_{a,b}
. Разница определяется отсутствием отсортированных начальных или конечных точек в сегментах A и B.И дополнительные вещи:
Вывод: Чтобы получить правильный результат для маленьких маленьких сегментов, которые вы пометили красной стрелкой, оба полигона должны иметь одинаковую структуру узла, и требуется шаг пересечения на уровне узла (вставка вершин многоугольника A в B). Пересечение может быть сделано:
Но со странными результатами ...
источник
Глядя на пример, изменение подразумевает, что объекты из новой таблицы, которые были изменены, всегда будут перекрывать объекты из старой таблицы. Поэтому вы бы сделали с
Отрицание касаний связано с тем, что элементы также перекрываются, если только их границы имеют одинаковые местоположения вершин.
источник