Skip to content

Commit

Permalink
GeoPackage: Fix handling of invalid SRS ID (#3286)
Browse files Browse the repository at this point in the history
GeoPackage 1.2.1
 1.1.1.1.1. File Format
  Requirement 11
   The record with an srs_id of -1 SHALL be used for undefined
   Cartesian coordinate reference systems.
   The record with an srs_id of 0 SHALL be used for undefined
   geographic coordinate reference systems.
  • Loading branch information
mloskot authored Dec 15, 2020
1 parent 7766e11 commit 3c2a318
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
6 changes: 4 additions & 2 deletions autotest/gdrivers/gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,8 @@ def test_gpkg_15():

# Repeated SetProjection()
out_ds = gdal.Open('/vsimem/tmp.gpkg', gdal.GA_Update)
assert out_ds.GetProjectionRef() == ''
assert out_ds.GetSpatialRef().IsLocal()
assert out_ds.GetProjectionRef().find('Undefined cartesian SRS') >= 0
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
ret = out_ds.SetProjection(srs.ExportToWkt())
Expand All @@ -1220,7 +1221,8 @@ def test_gpkg_15():
out_ds = None

out_ds = gdal.Open('/vsimem/tmp.gpkg')
assert out_ds.GetProjectionRef() == ''
assert out_ds.GetSpatialRef().IsLocal()
assert out_ds.GetProjectionRef().find('Undefined cartesian SRS') >= 0
# Test setting on read-only dataset
gdal.PushErrorHandler()
ret = out_ds.SetProjection('')
Expand Down
20 changes: 14 additions & 6 deletions autotest/ogr/ogr_gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,20 +898,28 @@ def test_ogr_gpkg_15():
pytest.fail()
gpkg_ds.ReleaseResultSet(sql_lyr)

# Invalid target SRID
# Invalid target SRID=0
# GeoPackage: The record with an srs_id of 0 SHALL be used for undefined geographic coordinate reference systems.
with gdaltest.error_handler():
sql_lyr = gpkg_ds.ExecuteSQL("SELECT ST_Transform(geom, 0) FROM tbl_linestring_renamed")
sql_lyr = gpkg_ds.ExecuteSQL("SELECT ST_Transform(geom, 0), ST_SRID(ST_Transform(geom, 0)) FROM tbl_linestring_renamed")
assert sql_lyr.GetSpatialRef().ExportToWkt().find('Undefined geographic SRS') >= 0
feat = sql_lyr.GetNextFeature()
if feat.GetGeometryRef() is not None:
if feat.GetGeometryRef() is None or feat.GetField(0) != 0:
feat.DumpReadable()
pytest.fail()
gpkg_ds.ReleaseResultSet(sql_lyr)

# Invalid source SRID
# Invalid source SRID=0
# GeoPackage: The record with an srs_id of 0 SHALL be used for undefined geographic coordinate reference systems.
# The source is undefined geographic coordinate reference systems (based on WGS84) and the target is WGS84,
# and the result is an identity transformation that leaves geometry unchanged.
src_lyr = gpkg_ds.GetLayerByName("point-with-spi-and-dashes")
assert src_lyr.GetSpatialRef().ExportToWkt().find('Undefined geographic SRS') >= 0
with gdaltest.error_handler():
sql_lyr = gpkg_ds.ExecuteSQL("SELECT ST_Transform(geom, 4326) FROM \"point-with-spi-and-dashes\"")
sql_lyr = gpkg_ds.ExecuteSQL("SELECT ST_Transform(geom, 4326), ST_SRID(ST_Transform(geom, 4326)) FROM \"point-with-spi-and-dashes\"")
assert sql_lyr.GetSpatialRef().ExportToWkt().find('WGS_1984') >= 0
feat = sql_lyr.GetNextFeature()
if feat.GetGeometryRef() is not None:
if feat.GetGeometryRef() is None or feat.GetField(0) != 4326:
feat.DumpReadable()
pytest.fail()
gpkg_ds.ReleaseResultSet(sql_lyr)
Expand Down
30 changes: 24 additions & 6 deletions gdal/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,6 @@ static OGRErr GDALGPKGImportFromEPSG(OGRSpatialReference *poSpatialRef,
OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId,
bool bFallbackToEPSG)
{
/* Should we do something special with undefined SRS ? */
if( iSrsId == 0 || iSrsId == -1 )
{
return nullptr;
}

std::map<int, OGRSpatialReference*>::const_iterator oIter =
m_oMapSrsIdToSrs.find(iSrsId);
if( oIter != m_oMapSrsIdToSrs.end() )
Expand All @@ -352,6 +346,30 @@ OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId,
return oIter->second;
}

if( iSrsId == 0 || iSrsId == -1 )
{
OGRSpatialReference *poSpatialRef = new OGRSpatialReference();
poSpatialRef->SetAxisMappingStrategy( OAMS_TRADITIONAL_GIS_ORDER );

if( iSrsId == 0)
{
poSpatialRef->SetGeogCS("Undefined geographic SRS",
"unknown",
"unknown",
SRS_WGS84_SEMIMAJOR,
SRS_WGS84_INVFLATTENING);
}
else if( iSrsId == -1)
{
poSpatialRef->SetLocalCS("Undefined cartesian SRS");
poSpatialRef->SetLinearUnits( SRS_UL_METER, 1.0 );
}

m_oMapSrsIdToSrs[iSrsId] = poSpatialRef;
poSpatialRef->Reference();
return poSpatialRef;
}

CPLString oSQL;
oSQL.Printf( "SELECT definition, organization, organization_coordsys_id%s "
"FROM gpkg_spatial_ref_sys WHERE definition IS NOT NULL AND "
Expand Down

0 comments on commit 3c2a318

Please sign in to comment.