We've run into an odd query result with PostGIS. We have a large polygon and several smaller ones, and we're interested in checking whether or not the smaller ones are contained in the large polygon.
A visual inspection reveals they are indeed within the polygon (zoomed-out here so that the bottom boundary of the large polygon is visible; the smaller ones are in blue):
However, running ST_Within(boundaries, geometry)
results in False
for all these polygons. After some introspection, ST_Within(ST_Transform(boundaries, 4326), ST_Transform(geometry, 4326))
results in True
.
Both geometries are in local CRS (EPSG:3067
), and both tables' entries in geometry_columns
have srid=3067
, same geometry type (GEOMETRY
), same coord_dimension
(2), etc.
Since this is resolved by transforming the coordinates, I can only assume that postgis does some partial transformation behind the scenes, but I'm not sure how to resolve this without transforming all our geometries to 4326.
For reference, here's a EWKT excerpt with the geometries:
with bbox as (select st_geomfromewkt('SRID=3067;POLYGON((64562.78588868573 6649100.87912667,205761.97180753836 7794679.579243775,674306.9889334934 7782478.683824445,757812.7263923198 6632497.631782339,64562.78588868573 6649100.87912667))') geom),
polys as (select st_geomfromewkt('SRID=3067;POLYGON((284346.675638346 6640055.333759279,284346.46427643043 6640053.187765737,284345.83831320365 6640051.1242415225,284344.8218040813 6640049.222486716,284343.45381293906 6640047.555584686,284341.7869109092 6640046.187593544,284339.885156102 6640045.171084422,284337.82163188816 6640044.545121195,284335.675638346 6640044.333759279,284333.52964480384 6640044.545121195,284331.46612059 6640045.171084422,284329.5643657828 6640046.187593544,284327.89746375295 6640047.555584686,284326.5294726107 6640049.222486716,284325.51296348835 6640051.1242415225,284324.8870002616 6640053.187765737,284324.675638346 6640055.333759279,284324.8870002616 6640057.479752821,284325.51296348835 6640059.5432770355,284326.5294726107 6640061.445031842,284327.89746375295 6640063.111933872,284329.5643657828 6640064.479925014,284331.46612059 6640065.496434136,284333.52964480384 6640066.122397363,284335.675638346 6640066.333759279,284337.82163188816 6640066.122397363,284339.885156102 6640065.496434136,284341.7869109092 6640064.479925014,284343.45381293906 6640063.111933872,284344.8218040813 6640061.445031842,284345.83831320365 6640059.5432770355,284346.46427643043 6640057.479752821,284346.675638346 6640055.333759279))') geom)
select st_within(polys.geom, bbox.geom), st_within(st_transform(polys.geom, 4326), st_transform(bbox.geom, 4326))
from bbox, polys;
st_within|st_within|
---------+---------+
false |true |
@geozelot pointed out the distortion when projecting from a geography to a geometry - I did not anticipate it cause such a large discrepancy (~14km at the point of interest here). The obvious answer is to modify our original bounding box to be larger.
Below is a visual inspection as suggested; in red - the bounding box (large polygon) in WGS84, in purple - the projected bounding box in EPSG:3067
, and in pink dots - the polygons of interest (in EPSG:3067
).