Skip to content

Commit

Permalink
ogr2ogr: run OGRGeometry::SetPrecision() when specifying -xyRes
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Mar 5, 2024
1 parent 4fb28f3 commit 50b08cc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
19 changes: 17 additions & 2 deletions apps/ogr2ogr_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3893,6 +3893,7 @@ bool SetupTargetLayer::CanUseWriteArrowBatch(
!m_bUnsetFieldWidth && !m_bExplodeCollections && !m_pszZField &&
m_bExactFieldNameMatch && !m_bForceNullable && !m_bResolveDomains &&
!m_bUnsetDefault && psOptions->nFIDToFetch == OGRNullFID &&
psOptions->dfXYRes == OGRGeomCoordinatePrecision::UNKNOWN &&
!psOptions->bMakeValid)
{
struct ArrowArrayStream streamSrc;
Expand Down Expand Up @@ -4328,11 +4329,13 @@ SetupTargetLayer::Setup(OGRLayer *poSrcLayer, const char *pszNewLayerName,
if (psOptions->dfXYRes != OGRGeomCoordinatePrecision::UNKNOWN)
{
if (m_poDstDS->GetDriver()->GetMetadataItem(
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION) == nullptr)
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION) == nullptr &&
!OGRGeometryFactory::haveGEOS())
{
CPLError(CE_Warning, CPLE_AppDefined,
"-xyRes specified, but driver does not expose the "
"DCAP_HONOR_GEOM_COORDINATE_PRECISION capability");
"DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, "
"and this build has no GEOS support");
}

oCoordPrec.dfXYResolution = psOptions->dfXYRes;
Expand Down Expand Up @@ -6378,6 +6381,18 @@ bool LayerTranslator::Translate(
poDstGeometry = poClipped.release();
}

if (psOptions->dfXYRes !=
OGRGeomCoordinatePrecision::UNKNOWN &&
OGRGeometryFactory::haveGEOS())
{
OGRGeometry *poRoundedGeom =
poDstGeometry->SetPrecision(psOptions->dfXYRes, 0);
delete poDstGeometry;
poDstGeometry = poRoundedGeom;
if (poDstGeometry == nullptr)
goto end_loop;
}

if (m_bMakeValid)
{
const bool bIsGeomCollection =
Expand Down
20 changes: 20 additions & 0 deletions autotest/utilities/test_ogr2ogr_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2619,3 +2619,23 @@ def test_ogr2ogr_lib_coordinate_precision(tmp_vsimem):
assert prec.GetZResolution() == 0
assert prec.GetMResolution() == 0
ds.Close()


###############################################################################


def test_ogr2ogr_lib_coordinate_precision_with_geom():

src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
src_lyr = src_ds.CreateLayer("test")
f = ogr.Feature(src_lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt("LINESTRING (1 1,9 9)"))
src_lyr.CreateFeature(f)

out_ds = gdal.VectorTranslate("", src_ds, format="Memory", xyRes=10)
out_lyr = out_ds.GetLayer(0)
f = out_lyr.GetNextFeature()
if ogr.GetGEOSVersionMajor() > 0:
assert f.GetGeometryRef().ExportToWkt() == "LINESTRING (0 0,10 10)"
else:
assert f.GetGeometryRef().ExportToWkt() == "LINESTRING (1 1,9 9)"
5 changes: 5 additions & 0 deletions doc/source/programs/ogr2ogr.rst
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ output coordinate system or even reprojecting the features during translation.
is specified, it is assumed to be expressed in the units of the target SRS.
The m, mm or deg suffixes can be specified to indicate that the value must be
interpreted as being in metre, millimeter or degree.

When specifying this option, the :cpp:func:``OGRGeometry::SetPrecision``
method is run on geometries before passing them to the output driver, to
avoid generating invalid geometries due to the potentially reduced precision.

If neither this option nor :option:`-unsetCoordPrecision` are specified, the
coordinate resolution of the source layer, if available, is used.

Expand Down

0 comments on commit 50b08cc

Please sign in to comment.