¿Cómo transformar isolinas en isopolígonos con postgis?

9

Tengo una tabla de postgis de isolinas que se define así:

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

Visualmente, estos objetos de cadena lineal se ven así:

ingrese la descripción de la imagen aquí

Sé la extensión espacial de mis datos, por lo que puedo agregar un Bbox, para que LineStrings se pueda cerrar.

ingrese la descripción de la imagen aquí

Quiero crear una tabla de isopolígonos a myisopolygonspartir de una myisolinestabla, con polígonos, que no se superpongan, sino que creen una superficie continua y tengan una columna valcon las valisolinas más bajas , a partir de las cuales se formó el polígono. Entiendo que se puede formar a partir de isolina (isla) cerrada automáticamente, o isolina cerrada con bbox, en ese caso se valdebe tomar de esa isolina en particular. Visualmente debería verse así:

ingrese la descripción de la imagen aquí

Pensé que podía crear una topología de alguna manera y luego transformar caras en polígonos, pero no entiendo cómo hacerlo correctamente. ¿Cómo se puede hacer esto?

Otra opción sería usar recursivamente una función de diferencia entre bbox y cada polígono creado, pero supongo que esa no es la forma correcta de hacerlo, y definitivamente no es rápido en absoluto.

mofoyoda
fuente
ST_Split o ST_BuildArea son buenos candidatos para su problema
nickves

Respuestas:

3

Aquí hay una solución usando ST_Polygonize. Genera un polígono para cada límite y proporciona la elevación mínima y máxima cubierta por el polígono. El algoritmo no puede distinguir entre un pico y una depresión y devolverá la misma elevación tanto para el mínimo como para el máximo en estos casos.

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;

La WITHcláusula de la consulta "cierra" los contornos abiertos al unirlos con la extensión ligeramente contraída de los contornos existentes. (Se contrata la extensión para eliminar cualquier error de redondeo resultante del uso de ST_Extent, que produce una caja de precisión única, con ST_Polygonize, que requiere entradas perfectamente cerradas y nodadas en precisión doulbe). Si sus contornos ya están cerrados (es decir, está trabajando con una isla), entonces este paso puede omitirse.

dbaston
fuente
0

No tengo mucha experiencia, pero probaría la función geometría ST_MakePolygon (geometry outsidelinestring, geometry [] interiorlinestrings);

Simona
fuente
Eso realmente no responde la pregunta por completo.
John Powell
0

Usando su bbox e iterando sobre cada línea de contorno, puede usar ST_ConcaveHullpara convertir cada región en un polígono.

Travis Webb
fuente