Tengo una tabla PostGIS polygon_b
con algunas características de polígono. También hay una tabla polygon_a
que contiene los mismos polígonos polygon_b
pero con cambios menores. Ahora quiero crear líneas para visualizar las diferencias entre las características del polígono.
Supongo que ST_ExteriorRing
y ST_Difference
a hacer el trabajo, pero la cláusula WHERE parece ser bastante complicado.
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;
¿Alguien puede ayudarme?
EDITAR 1
Según lo publicado por 'tilt', lo he intentado ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)
pero el resultado no es el esperado.
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;
EDITAR 2
workupload.com/file/J0WBvRBb (conjunto de datos de ejemplo)
Intenté convertir los polígonos en multilíneas antes de usar ST_Difference, pero los resultados aún son extraños.
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;
fuente
Respuestas:
Aquí hay algunos trucos nuevos, usando:
EXCEPT
para eliminar geometrías de cualquier tabla que sean iguales, de modo que podamos centrarnos solo en geometrías que sean exclusivas de cada tabla (A_only
yB_only
).ST_Snap
para obtener un nudo exacto para los operadores de superposición.ST_SymDifference
operador de superposición para encontrar la diferencia simétrica entre los dos conjuntos de geometría para mostrar las diferencias. Actualización :ST_Difference
muestra el mismo resultado para este ejemplo. Puede probar cualquiera de las funciones para ver qué obtienen.Esto debería obtener lo que espera:
Para desempaquetar esta respuesta un poco más, el primer paso con
ST_Boundary
obtiene el límite de cada polígono, en lugar de solo el exterior. Por ejemplo, si hubiera agujeros, estos serían trazados por el límite.La
EXCEPT
cláusula se usa para eliminar las geometrías de A que son parte de B y las filas de B que son parte de A. Esto reduce el número de filas que son parte de A solamente y parte de B solamente. Por ejemplo, para obtener A_only:Aquí están las 6 filas de A_only y 3 filas de B_only:
A continuación,
ST_Union(DISTINCT A_only.geom)
se usa para combinar el trabajo de línea en una sola geometría, generalmente una MultiLineString.ST_Snap se usa para ajustar nodos de una geometría a otra. Por ejemplo
ST_Snap(A, B, tol)
, tomará la geometría A y agregará más nodos de la geometría B, o los moverá a la geometría B, si están dentro de latol
distancia. Probablemente hay varias formas de usar estas funciones, pero la idea es obtener coordenadas de cada geometría que sean exactas entre sí. Entonces las dos geometrías después del ajuste se ven así:Y para mostrar las diferencias, puede elegir usar
ST_SymDifference
oST_Difference
. Ambos muestran el mismo resultado para este ejemplo.fuente
Creo que es un poco complicado, debido a los diferentes conjuntos de nodos de sus dos polígonos (polígono verde A, segmentos rojos diferentes del polón B). Al comparar los segmentos de ambos polígonos se obtiene una pista sobre qué segmentos del polígono B se modificarán.
Nodos polígono A
Nodos de los segmentos "diferentes" polígono B
Desafortunadamente, esto muestra solo la diferencia en la estructura del segmento, pero espero que sea un punto de partida y funcione así:
Después de un proceso de descarga y descompresión, importé el conjunto de datos usando PostgrSQL 9.46, PostGIS 2.1 en Debian Linux Jessie con los comandos.
Suponiendo que los segmentos del polígono A no están en B y viceversa, trato de construir la diferencia entre los segmentos de ambos conjuntos de polígonos, descuidando la pertenencia del segmento a los polígonos en cada grupo (A o B). Por razones didácticas, formulo el material SQL en varias vistas.
En correspondencia con esta publicación GIS-SE , descompongo los dos polígonos en tablas de segmentos
segments_a
ysegments_b
La tabla de segmentos del polígono A:
El mismo procedimiento se aplicó al polígono B.
La tabla de segmentos polígono B
Puedo construir una vista de tabla de diferencias llamada
segments_diff_{a,b}
. La diferencia está dada por la no ocurrencia de puntos de inicio o fin ordenados en el conjunto de segmentos A y B.Y las cosas complementarias:
Conclusión: Para obtener un resultado adecuado para los pequeños segmentos pequeños que marcó con la flecha roja, ambos polígonos deben tener la misma estructura de nodo y un paso de intersección a nivel de nodo (se requiere insertar vértices del polígono A en B). La intersección podría hacerse por:
Pero con resultados extraños ...
fuente
Mirando el ejemplo, el cambio implica que las características de la nueva tabla que se han modificado siempre se superpondrán con las características de la tabla anterior. Por lo tanto, terminarías con
La negación de los toques se debe a que las características también se superponen si solo sus bordes comparten las mismas ubicaciones de vértices.
fuente