Skip to content

Commit d65b1fc

Browse files
committed
PostGIS: use full geometry intersection for SetSpatialFilter(), and not only bounding box
1 parent 81c7c68 commit d65b1fc

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

autotest/ogr/ogr_pg.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6376,3 +6376,37 @@ def test_ogr_pg_field_truncation(pg_ds):
63766376
lyr.ResetReading()
63776377
f = lyr.GetNextFeature()
63786378
assert f["field"] == b"abcd\xc3\xa9".decode("UTF-8")
6379+
6380+
6381+
###############################################################################
6382+
# Test real geometry intersection in spatial filter
6383+
6384+
6385+
@gdaltest.enable_exceptions()
6386+
@pytest.mark.parametrize("GEOM_TYPE", ["geometry", "geography"])
6387+
def test_ogr_pg_geometry_intersection_spatial_filter(pg_ds, use_postgis, GEOM_TYPE):
6388+
6389+
if use_postgis:
6390+
srs = osr.SpatialReference(epsg=4326)
6391+
lyr = pg_ds.CreateLayer("test", srs, options=["GEOM_TYPE=" + GEOM_TYPE])
6392+
else:
6393+
lyr = pg_ds.CreateLayer("test")
6394+
f = ogr.Feature(lyr.GetLayerDefn())
6395+
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT (0.5 0.5)"))
6396+
lyr.CreateFeature(f)
6397+
f = ogr.Feature(lyr.GetLayerDefn())
6398+
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT (0.9 0.5)"))
6399+
lyr.CreateFeature(f)
6400+
6401+
lyr.ResetReading()
6402+
6403+
# Pacman style polygon: almost a square except it doesn't include 0.9, 0.5
6404+
lyr.SetSpatialFilter(
6405+
ogr.CreateGeometryFromWkt(
6406+
"POLYGON ((0 0,0 1,1 1,1 0.6,0.8 0.6,0.8 0.4,1 0.4,1 0,0 0))"
6407+
)
6408+
)
6409+
f = lyr.GetNextFeature()
6410+
assert f.GetGeometryRef().ExportToWkt() == "POINT (0.5 0.5)"
6411+
f = lyr.GetNextFeature()
6412+
assert f is None

ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,10 +1077,24 @@ void OGRPGTableLayer::BuildWhere()
10771077
sEnvelope.MinY);
10781078
CPLsnprintf(szBox3D_2, sizeof(szBox3D_2), "%.17g %.17g", sEnvelope.MaxX,
10791079
sEnvelope.MaxY);
1080-
osWHERE.Printf(
1081-
"WHERE %s && ST_SetSRID('BOX3D(%s, %s)'::box3d,%d) ",
1082-
OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
1083-
szBox3D_1, szBox3D_2, poGeomFieldDefn->nSRSId);
1080+
if (poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY)
1081+
{
1082+
OGRWktOptions sOptions;
1083+
sOptions.variant = wkbVariantIso;
1084+
const std::string osWKT = m_poFilterGeom->exportToWkt(sOptions);
1085+
osWHERE.Printf(
1086+
"WHERE ST_Intersects(%s, ST_SetSRID(ST_GeomFromText('%s'), "
1087+
"%d)) ",
1088+
OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
1089+
osWKT.c_str(), poGeomFieldDefn->nSRSId);
1090+
}
1091+
else
1092+
{
1093+
osWHERE.Printf(
1094+
"WHERE %s && ST_SetSRID('BOX3D(%s, %s)'::box3d,%d) ",
1095+
OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
1096+
szBox3D_1, szBox3D_2, poGeomFieldDefn->nSRSId);
1097+
}
10841098
}
10851099

10861100
if (!osQuery.empty())
@@ -1174,7 +1188,6 @@ OGRFeature *OGRPGTableLayer::GetNextFeature()
11741188
* request */
11751189
if (m_poFilterGeom == nullptr || poGeomFieldDefn == nullptr ||
11761190
poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
1177-
poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ||
11781191
FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter)))
11791192
{
11801193
if (iFIDAsRegularColumnIndex >= 0)

0 commit comments

Comments
 (0)