I do have a similar problem as described in Stack Exchange article … the whole story is a bit complex: what I really want is to create polygon-skeleton with ST_ApproximateMedialAxis but this one returns "straight skeleton of Polygon with point touching rings is not implemented" – which indicates that I have invalid polygons in my data.
Looking for a way to identify these polygons I carried on with the following PostGIS statements:
------- create outer and inner rings ----------
--- outer rings
CREATE TABLE skeleton_tests.dump_outer_rings AS
SELECT
b.id,
b.path AS gid,
b.geom ::geometry(Polygon) as geom
FROM
(SELECT
id,
(ST_DumpRings(geom)).*
FROM skeleton_tests.dump_gehst_ta_klein) b
WHERE b.path[1] =0; -- OUTER rings ARE = 0
--- inner rings
CREATE TABLE skeleton_tests.dump_inner_rings AS
SELECT
b.id,
b.path AS gid,
b.geom ::geometry(Polygon) as geom
From
(SELECT
id,
(ST_DumpRings(geom)).*
FROM skeleton_tests.dump_gehst_ta_klein) b
WHERE b.path[1] > 0; -- >0 means inner ring
which identifies the ring-types and is just a preparatory step – to give you an idea of my input data for the next steps.
The following two versions of finding touching parts of inner rings raise my confusion …
This one does identify a couple of touching inner rings:
--- Inner Ring touches outer Ring / with cross join lateral "iteration"
SELECT
a.id,
c.id,
a.geom,
c.geom
FROM skeleton_tests.dump_outer_rings as a
CROSS JOIN LATERAL
(
SELECT
b.id,
b.geom
FROM skeleton_tests.dump_inner_rings AS b
where ST_TOUCHES(st_boundary(a.geom), b.geom)) AS c
ORDER BY a.id;
But this one – which would be much faster – doesn't find any touching parts when using ST_TOUCHES but it does find some when using ST_INTERSECTS:
SELECT a.id, b.id
FROM
skeleton_tests.dump_outer_rings AS a INNER JOIN skeleton_tests.dump_inner_rings AS b
ON ST_intersects(a.geom, b.geom)
WHERE a.id != b.id;
Depending on the data it could make a difference in finding intersecting vs. touching parts!
Any hint about that phenomenon?
Best Answer
In the first query you are testing:
whereas in the second query you are testing
In fact, those are both wrong!
First of all, since the
ST_DumpRings
return shells and holes as polygons (for some unknown reason),ST_Boundary
needs to be used to extract the boundary ring linework (otherwise, the test is compromised due to presence of polygon interior areas). These needs to be done on both inputs to the test.Second, you need to use
ST_Intersects
instead ofST_Touches
. The reason is that the definition ofST_Touches
is:This means that
ST_Touches
is not useful for checking whether rings touch, since any touch point is in the interior of the ring linework. For instance, in this example of touching rings the result isfalse
:Instead, using
ST_Intersects
is the correct way to test whether rings touch:So the test condition should be: