Skip to content

Commit

Permalink
VFK: FIX invalid parcel "banana" geometries (fixes #3376) (#11688)
Browse files Browse the repository at this point in the history
Fixes #3376

Co-authored-by: Petr Zima <zima@matfyz.cz>
  • Loading branch information
seidlmic and petr-zima authored Jan 19, 2025
1 parent ba185c4 commit 607bec8
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 230 deletions.
1 change: 1 addition & 0 deletions autotest/ogr/ogr_vfk.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def test_ogr_vfk_1(vfk_ds):
# Read the first feature from layer 'PAR', check envelope


@pytest.mark.require_geos
def test_ogr_vfk_2(vfk_ds):

vfk_layer_par = vfk_ds.GetLayer(0)
Expand Down
1 change: 1 addition & 0 deletions ogr/ogr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ OGRGeometryH CPL_DLL OGR_G_SetPrecision(OGRGeometryH, double dfGridSize,
int nFlags) CPL_WARN_UNUSED_RESULT;

OGRGeometryH CPL_DLL OGR_G_Polygonize(OGRGeometryH) CPL_WARN_UNUSED_RESULT;
OGRGeometryH CPL_DLL OGR_G_BuildArea(OGRGeometryH) CPL_WARN_UNUSED_RESULT;

/*! @cond Doxygen_Suppress */
/* backward compatibility (non-standard methods) */
Expand Down
1 change: 1 addition & 0 deletions ogr/ogr_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ class CPL_DLL OGRGeometry
int bOnlyEdges) const CPL_WARN_UNUSED_RESULT;

virtual OGRGeometry *Polygonize() const CPL_WARN_UNUSED_RESULT;
virtual OGRGeometry *BuildArea() const CPL_WARN_UNUSED_RESULT;

virtual double Distance3D(const OGRGeometry *poOtherGeom) const;

Expand Down
94 changes: 94 additions & 0 deletions ogr/ogrgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6885,6 +6885,100 @@ OGRGeometryH OGR_G_Polygonize(OGRGeometryH hTarget)
OGRGeometry::FromHandle(hTarget)->Polygonize());
}

/************************************************************************/
/* BuildArea() */
/************************************************************************/

/**
* \brief Polygonize a linework assuming inner polygons are holes.
*
* This method is the same as the C function OGR_G_BuildArea().
*
* Polygonization is performed similarly to OGRGeometry::Polygonize().
* Additionally, holes are dropped and the result is unified producing
* a single Polygon or a MultiPolygon.
*
* A new geometry object is created and returned: NULL on failure,
* empty GeometryCollection if the input geometry cannot be polygonized,
* Polygon or MultiPolygon on success.
*
* This method is built on the GEOSBuildArea_r() function of the GEOS
* library, check it for the definition of the geometry operation.
* If OGR is built without the GEOS library, this method will always fail,
* issuing a CPLE_NotSupported error.
*
* @return a newly allocated geometry now owned by the caller,
* or NULL on failure.
*
* @since OGR 3.11
*/

OGRGeometry *OGRGeometry::BuildArea() const

{
#ifndef HAVE_GEOS

CPLError(CE_Failure, CPLE_NotSupported, "GEOS support not enabled.");
return nullptr;

#else

OGRGeometry *poPolygsOGRGeom = nullptr;

GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
GEOSGeom hThisGeosGeom = exportToGEOS(hGEOSCtxt);
if (hThisGeosGeom != nullptr)
{
GEOSGeom hGeosPolygs = GEOSBuildArea_r(hGEOSCtxt, hThisGeosGeom);
poPolygsOGRGeom =
BuildGeometryFromGEOS(hGEOSCtxt, hGeosPolygs, this, nullptr);
GEOSGeom_destroy_r(hGEOSCtxt, hThisGeosGeom);
}
freeGEOSContext(hGEOSCtxt);

return poPolygsOGRGeom;

#endif // HAVE_GEOS
}

/************************************************************************/
/* OGR_G_BuildArea() */
/************************************************************************/

/**
* \brief Polygonize a linework assuming inner polygons are holes.
*
* This function is the same as the C++ method OGRGeometry::BuildArea().
*
* Polygonization is performed similarly to OGR_G_Polygonize().
* Additionally, holes are dropped and the result is unified producing
* a single Polygon or a MultiPolygon.
*
* A new geometry object is created and returned: NULL on failure,
* empty GeometryCollection if the input geometry cannot be polygonized,
* Polygon or MultiPolygon on success.
*
* This function is built on the GEOSBuildArea_r() function of the GEOS
* library, check it for the definition of the geometry operation.
* If OGR is built without the GEOS library, this function will always fail,
* issuing a CPLE_NotSupported error.
*
* @param hGeom handle on the geometry to polygonize.
*
* @return a handle on newly allocated geometry now owned by the caller,
* or NULL on failure.
*
* @since OGR 3.11
*/

OGRGeometryH OGR_G_BuildArea(OGRGeometryH hGeom)

{
VALIDATE_POINTER1(hGeom, "OGR_G_BuildArea", nullptr);

return OGRGeometry::ToHandle(OGRGeometry::FromHandle(hGeom)->BuildArea());
}

/************************************************************************/
/* swapXY() */
/************************************************************************/
Expand Down
4 changes: 4 additions & 0 deletions ogr/ogrsf_frmts/vfk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ if (GDAL_USE_SQLITE3)
gdal_target_link_libraries(ogr_VFK PRIVATE SQLite::SQLite3)
target_compile_definitions(ogr_VFK PRIVATE -DHAVE_SQLITE)
endif ()
if (GDAL_USE_GEOS)
target_compile_definitions(ogr_VFK PRIVATE -DHAVE_GEOS=1)
gdal_target_link_libraries(ogr_VFK PRIVATE ${GEOS_TARGET})
endif ()
Loading

0 comments on commit 607bec8

Please sign in to comment.