1

In PostGIS, how can it be determined if a polygon lies within another even if it shares an edge?

ST_Contains works well enough, except if there is a shared edge.


At the suggestion of @ziggy's comment, I tried to use a "small negative buffer", but to no avail -- either my code is wrong or the operation is inpracticaly slow:

SELECT z.id, z.name 
FROM z 
INNER JOIN d ON ST_Contains( 
    z.geom, 
    ST_Buffer( d.geom, -1)
)
WHERE d.id = '933';

The best I can come up with is to check just the centroid:

SELECT z.id, z.name 
FROM z 
INNER JOIN d ON ST_Contains( 
    z.geom, 
     ST_Centroid(d.geom)
)
WHERE d.id = '933';

But that doesn't work for polygons shaped like a letter C....

4
  • 1
    you can do a small negative buffer then use st_contains or st_within
    – ziggy
    Commented Sep 7, 2022 at 13:33
  • 2
    ST_Contains does work for nested polygons with shared edges. Can you post the data for the geometries which don't work?
    – dr_jts
    Commented Sep 7, 2022 at 15:02
  • 1
    Can you add a screenshot?
    – Bera
    Commented Sep 7, 2022 at 16:52
  • 1
    It's not too difficult to set up topology in postgis. This would clean up your edges that don't match up exactly, allowing you to run st_contains and get the expected result. Here's the docs postgis.net/docs/Topology.html. And this post has a function for loading topology 1 feature at a time to catch errors blog.mathieu-leplatre.info/…
    – jbalk
    Commented Sep 7, 2022 at 17:12

1 Answer 1

2

If area of intersection of two polygons A and B is equqal to area of polygon B, then B lies within A. However, I think it's not the fastest metod and it doesn't work for degenerate polygons.

SELECT z.id, z.name 
FROM z 
INNER JOIN d ON ST_Intersects(z.geom, d.geom) 
    and ST_Area(ST_Intersection(z.geom, d.geom)) = ST_Area(z.geom)
    and ST_Area(z.geom) > 0;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.