Je pense que c'est un peu délicat, en raison des différents ensembles de nœuds de vos deux polygones (polygone vert A, segments rouges différents du polyon B). La comparaison des segments des deux polygones donne un indice sur les segments du polygone B qui seront modifiés.
Nœuds polygone A
Noeuds du polygone de segments "différents" B
Malheureusement, cela ne montre que la différence dans la structure des segments, mais j'espère que c'est un point de départ et que cela fonctionne comme ceci:
Après un processus de téléchargement et de décompression, j'ai importé l'ensemble de données à l'aide de PostgrSQL 9.46, PostGIS 2.1 sous Debian Linux Jessie avec les commandes.
$ createdb gis-se
$ psql gis-se < /usr/share/postgis-2.1/postgis.sql
$ psql gis-se < /usr/share/postgis-2.1/spatial_ref_sys.sql
$ shp2pgsql -S polygon_a | psql gis-se
$ shp2pgsql -S polygon_b | psql gis-se
En supposant que les segments du polygone A ne sont pas en B et vice-versa, j'essaie de créer la différence entre les segments des deux ensembles de polygones, en négligeant l'appartenance des segments aux polygones de chaque groupe (A ou B). Pour des raisons didactiques, je formule le truc SQL dans plusieurs vues.
Correspondant à ce post GIS-SE , je décompose les deux polygones en tables de segments segments_a
etsegments_b
-- Segments of the polygon A
CREATE VIEW segments_a AS SELECT sp, ep
FROM
-- extract the endpoints for every 2-point line segment for each linestring
(SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM
-- extract the individual linestrings
(SELECT (ST_Dump(ST_Boundary(geom))).geom
FROM polygon_a
) AS linestrings
-- be sure that nothing is scrambled
ORDER BY sp, ep
) AS segments;
Le polygone de table de segments A:
SELECT
st_astext(sp) AS sp,
st_astext(ep) AS ep
FROM segments_a
LIMIT 3;
sp | ep
-------------------------------------------+--------------------------------------------
POINT(-292.268907321861 95.0342877387557) | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195) | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.03428773875
La même procédure a été appliquée au polygone B.
-- Segments of the polygon B
CREATE VIEW segments_b AS SELECT sp, ep
FROM
-- extract the endpoints for every 2-point line segment for each linestring
(SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM
-- extract the individual linestrings
(SELECT (ST_Dump(ST_Boundary(geom))).geom
FROM polygon_b
) AS linestrings
-- be sure that nothing is scrambled
ORDER BY sp, ep
) AS segments;
Le polygone de table de segments B
SELECT
st_astext(sp) AS sp,
st_astext(ep) AS ep
FROM segments_b
LIMIT 3;
sp | ep
-------------------------------------------+-------------------------------------------
POINT(-292.268907321861 95.0342877387557) | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195) | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.0342877387557)
...
Je peux créer une vue de table des différences nommée segments_diff_{a,b}
. La différence est donnée par la non-occurrence de points de début ou de fin triés dans l'ensemble de segments A et B.
CREATE VIEW segments_diff_a AS
SELECT st_makeline(b.sp, b.ep) as geom
FROM segments_b as b
LEFT JOIN segments_a as a ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon A
WHERE a.sp IS NULL;
Et les trucs complémentaires:
CREATE VIEW segments_diff_b AS
SELECT st_makeline(a.sp, a.ep) as geom
FROM segments_a as a
LEFT JOIN segments_b as b ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon B
WHERE b.sp IS NULL;
Conclusion: Pour obtenir un résultat correct pour les petits petits segments que vous avez marqués avec la flèche rouge, les deux polygones doivent avoir la même structure de nœud et une étape d'intersection au niveau du nœud (insertion de sommets du polygone A dans B) est requise. L'intersection pourrait se faire par:
CREATE VIEW segments_bi AS
SELECT distinct sp, ep
FROM (
SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM (
SELECT st_difference(b.seg, a.seg) as geom FROM
segments_diff_a as a, segments_diff_b as b
WHERE st_intersects(a.seg, b.seg)
) as cut
) as segments
WHERE sp IS NOT NULL AND ep IS NOT NULL
ORDER BY sp, ep;
Mais avec des résultats étranges ...