[PostGIS] #6128: ST_intersects Gives false Positives related to meridian / antimeridian
PostGIS
trac at osgeo.org
Wed Sep 9 11:07:59 PDT 2026
#6128: ST_intersects Gives false Positives related to meridian / antimeridian
----------------------------------------------+---------------------------
Reporter: BoulderPika | Owner: pramsey
Type: defect | Status: new
Priority: medium | Milestone: PostGIS 3.6.5
Component: postgis | Version: 3.6.x
Keywords: geospatial false positive lookup |
----------------------------------------------+---------------------------
I am seeing some squirrely behavior with ST_intersects when determining if
a point intersects a polygon when a polygon touches (but does not span)
the antimeridian and the lookup point lies on the meridian. This is easily
reproducible in the latest docker image of postgis I could find.
**Versions:**\\
SELECT version();
{{{
version
--------------------------------------------------------------------------------------------------------------------
PostgreSQL 18.6 (Debian 18.6-1.pgdg13+2) on x86_64-pc-linux-gnu, compiled
by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
(1 row)
}}}
SELECT postgis_full_version();
{{{
postgis_full_version
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POSTGIS="3.6.4 94d984b" [EXTENSION] PGSQL="180" GEOS="3.14.1-CAPI-1.20.5"
(compiled against GEOS 3.13.1) PROJ="9.8.1 NETWORK_ENABLED=OFF
URL_ENDPOINT=https://cdn.proj.org
USER_WRITABLE_DIRECTORY=/var/lib/postgresql/.local/share/proj
DATABASE_PATH=/usr/share/proj/proj.db" (compiled against PROJ 9.6.0)
LIBXML="2.9.14" LIBJSON="0.18" LIBPROTOBUF="1.5.1" WAGYU="0.5.0
(Internal)" TOPOLOGY
(1 row)
}}}
**Below are the steps to setup the geography:**\\
docker pull postgis/postgis:18-3.6\\
docker run --name postgis-container -e POSTGRES_PASSWORD=password -d
postgis/postgis:18-3.6\\
docker exec -it postgis-container psql -U postgres\\
-- (1) Initialize\\
{{{
CREATE EXTENSION IF NOT EXISTS postgis;
}}}
-- (2) Versions before 3.12 had a bug:
https://trac.osgeo.org/postgis/ticket/5838\\
{{{
SELECT PostGIS_GEOS_Version();
}}}
-- (3) Make a table with (id, name, geography)\\
{{{
CREATE TABLE geojson_features ( id SERIAL PRIMARY KEY, name TEXT, geom
geography(POLYGON, 4326) NOT NULL );
}}}
-- (4) Add an index\\
{{{
CREATE INDEX idx_geojson_features_geom ON geojson_features USING GIST
(geom);
}}}
-- (5) Add a polygon in the northern hemisphere, which contains the point
(lon, lat) = (0, 25)\\
{{{
INSERT INTO geojson_features (name, geom) VALUES('poly1',
ST_GeomFromGeojson(' { "type": "Polygon", "coordinates": [ [ [ -10, 10 ],
[ -5, 10 ], [ 5, 20 ], [ 5, 30 ], [ -5, 40 ], [ -10, 40 ], [ -10, 10 ] ] ]
} ' )::geography);
}}}
-- (6) The below southern hemisphere polygon is the western portion of
"poly1" when translated to span the antemeridian and then sliced there\\
{{{
INSERT INTO geojson_features (name, geom) VALUES('poly2_west',
ST_GeomFromGeojson(' { "type": "Polygon", "coordinates": [ [ [ -180,
-35.4101725284 ], [ -175, -30 ], [ -175, -20 ], [ -180, -15.1725999559 ],
[ -180, -35.4101725284 ] ] ] } ' )::geography);
}}}
-- (7) The below southern hemisphere polygon is the eastern portion of
"poly1" when translated to span the antemeridian and then sliced there\\
{{{
INSERT INTO geojson_features (name, geom) VALUES('poly2_east',
ST_GeomFromGeojson(' { "type": "Polygon", "coordinates": [ [ [ 180,
-15.1725999559 ], [ 175, -10 ], [ 170, -10 ], [ 170, -40 ], [ 175, -40 ],
[ 180, -35.4101725284 ], [ 180, -15.1725999559 ] ] ] } ' )::geography);
}}}
=====================================================
At this point, we have three polygons setup. I now wish to perform some
point intersections. The below two execute as expected with a point very
close to zero lon:
{{{
SELECT name, ST_intersects(geom, ST_makepoint(-0.00001, 25)::geography)
FROM geojson_features;
}}}
name | st_intersects\\
-------+---------------\\
poly1 | t\\
poly2 | f\\
poly3 | f\\
(3 rows)\\
{{{
SELECT name, ST_intersects(geom, ST_makepoint(0.00001, 25)::geography)
FROM geojson_features;
}}}
name | st_intersects\\
-------+---------------\\
poly1 | t\\
poly2 | f\\
poly3 | f\\
(3 rows)\\
But on the next query, I get false positive results:
{{{
SELECT name, ST_intersects(geom, ST_makepoint(0, 25)::geography) FROM
geojson_features;
}}}
name | st_intersects\\
-------+---------------\\
poly1 | t\\
poly2 | t\\
poly3 | t\\
(3 rows)\\
Now the polygons in the southern hemisphere are included when the
longitude is exactly 0. But they were excluded when close to zero.
**Additional Details:**
If I were to setup the two southern hemisphere polygons such that they
were very close to the antimeridian (e.g. edges at 179.9999 instead of 180
and -179.9999 instead of -180) then the intersections behave as expected.
This also appears to be a symptom of not using the index. When I have 5000
more polygons in the table, then I confirmed the index is being used in
the optimizer and I get the results I expect. With just the three
polygons, a sequetial scan is performed and I get the false positives.
--
Ticket URL: <https://trac.osgeo.org/postgis/ticket/6128>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.
More information about the postgis-tickets
mailing list