Как преобразовать изолинии в изополигоны с постгисом?

9

У меня есть таблица postgis изолиний, которая определяется следующим образом:

CREATE TABLE myisolines
(
  gid serial NOT NULL,
  isotime timestamp without timezone,
  val numeric(10,4),
  geom geometry(LineString,4326)
);

Визуально эти линейные объекты выглядят так:

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

Я знаю пространственный экстент моих данных, поэтому я могу добавить Bbox, чтобы LineStrings можно было как бы замкнуть.

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

Я хочу создать таблицу изополигонов myisopolygonsиз myisolinesтаблицы с полигонами, которые не будут перекрываться, но создают непрерывную поверхность и имеют столбец valс наименьшим valиз изолиний, из которого был сформирован многоугольник. Я понимаю, что он может быть сформирован из самозакрытой изолинии (островка) или изолинии, закрытой bbox, в этом случае его valследует взять из этой конкретной изолинии. Визуально это должно выглядеть так:

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

Я думал, что могу как-то создать топологию, а затем преобразовать грани в полигоны, но я не понимаю, как это сделать правильно. Как это может быть сделано?

Другим вариантом будет рекурсивное использование разностной функции между bbox и каждым созданным многоугольником, но я думаю, что это неправильный способ, и определенно не быстрый.

mofoyoda
источник
ST_Split или ST_BuildArea - хорошие кандидаты для вашей проблемы
nickves

Ответы:

3

Вот решение с использованием ST_Polygonize. Он генерирует многоугольник для каждой границы и обеспечивает минимальное и максимальное превышение, охватываемое многоугольником. Алгоритм не может различить пик и депрессию и будет возвращать одинаковую высоту для минимума и максимума в этих случаях.

WITH closed_contours AS (
    SELECT 
      ST_Union(geom) AS geom 
    FROM 
      (SELECT geom FROM contours 
       UNION ALL 
       SELECT ST_SetSRID(ST_Boundary(ST_Expand(ST_Extent(geom), -1e-10)), 4326) 
       FROM contours) 
sq)

SELECT
  poly_id, 
  min(polys.geom) AS geom, 
  min(elevation)  AS min_elev, 
  max(elevation)  AS max_elev
FROM
  (SELECT row_number() OVER () AS poly_id, geom FROM
      (SELECT 
         (ST_Dump(ST_Polygonize(geom))).geom
       FROM closed_contours) dump
  ) polys
INNER JOIN contours ON ST_Intersects(polys.geom, contours.geom)
GROUP BY poly_id;

Предложение WITHзапроса «закрывает» любые открытые контуры, объединяя их со слегка сокращенным экстентом существующих контуров. (Степень сокращается для устранения любых ошибок округления, возникающих в результате использования, при ST_Extentкотором создается коробка одинарной точности, с ST_Polygonizeкоторой требуются идеально замкнутые и узловые входы в точности doulbe). Если ваши контуры уже закрыты (то есть вы работаете с островом), то этот шаг можно пропустить.

dbaston
источник
0

Я не очень опытный, но я бы попробовал геометрию функции ST_MakePolygon (геометрия externallinestring, geometry [] interiorlinestrings);

Simona
источник
Это не совсем отвечает на вопрос полностью.
Джон Пауэлл
0

Используя ваш bbox и итерируя по каждой линии контура, вы можете использовать ST_ConcaveHullдля преобразования каждого региона в многоугольник.

Трэвис Уэбб
источник