From 5476d99b56f348d2312c680f363ad431dad074c8 Mon Sep 17 00:00:00 2001 From: Ben Marchant <13385275+bmarchant@users.noreply.github.com> Date: Mon, 19 Jun 2023 08:23:39 -0500 Subject: [PATCH] Create a multipolygon for all polygons so they can be in one layer together. (#5674) --- .../main/cpp/hoot/core/io/FlatGeobufWriter.h | 2 +- .../cpp/hoot/core/io/OgrMultifileWriter.cpp | 30 ++++++++++++------- .../cpp/hoot/core/io/OgrMultifileWriter.h | 3 +- .../main/cpp/hoot/core/io/ShapefileWriter.h | 2 +- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/hoot-core/src/main/cpp/hoot/core/io/FlatGeobufWriter.h b/hoot-core/src/main/cpp/hoot/core/io/FlatGeobufWriter.h index 84dd917862..8512bc06d9 100644 --- a/hoot-core/src/main/cpp/hoot/core/io/FlatGeobufWriter.h +++ b/hoot-core/src/main/cpp/hoot/core/io/FlatGeobufWriter.h @@ -56,7 +56,7 @@ class FlatGeobufWriter : public OgrMultifileWriter const char* _getDriverName() const override { return "FlatGeobuf"; }; QString _getFileExtension() const override { return ".fgb"; } OgrOptions _getOptions() const override; - OGRwkbGeometryType _getPolygonGeometryType() const override { return OGRwkbGeometryType::wkbPolygon; } + bool _convertPolygons() const override { return true; } }; diff --git a/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.cpp b/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.cpp index fca4729582..7ba60280fe 100644 --- a/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.cpp +++ b/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.cpp @@ -31,6 +31,7 @@ #include // GEOS +#include #include #include @@ -298,7 +299,7 @@ void OgrMultifileWriter::writePoints(const ConstOsmMapPtr& map, const QString& p void OgrMultifileWriter::writePolygons(const ConstOsmMapPtr& map, const QString& path) { - _setupDataset(map, path, _getPolygonGeometryType(), ElementType::Unknown); + _setupDataset(map, path, wkbMultiPolygon, ElementType::Unknown); const WayMap& ways = map->getWays(); for (auto it = ways.begin(); it != ways.end(); ++it) @@ -309,15 +310,6 @@ void OgrMultifileWriter::writePolygons(const ConstOsmMapPtr& map, const QString& _writeWayPolygon(map, way); } - // For polygon only file types a multipolygon file needs to be written - if (_getPolygonGeometryType() == OGRwkbGeometryType::wkbPolygon) - { - _cleanupDataset(); - QString multipolyPath = path; - multipolyPath.replace("Polygons" + _getFileExtension(), "MultiPolygons" + _getFileExtension()); - _setupDataset(map, multipolyPath, OGRwkbGeometryType::wkbMultiPolygon, ElementType::Unknown); - } - const RelationMap& relations = map->getRelations(); for (auto it = relations.begin(); it != relations.end(); ++it) { @@ -344,6 +336,9 @@ void OgrMultifileWriter::_writeRelationPolygon(const ConstOsmMapPtr& map, const return; } + // Convert the polygon to a multipolygon if needed (FlagGeobuf cannot combine polygons and multipolygons in the same layer) + geometry = _polyToMultipoly(geometry); + std::string wkt = geometry->toString(); const char* t = wkt.data(); OGRGeometry* geom; @@ -383,6 +378,9 @@ void OgrMultifileWriter::_writeWayPolygon(const ConstOsmMapPtr& map, const WayPt return; } + // Convert the polygon to a multipolygon if needed (FlagGeobuf cannot combine polygons and multipolygons in the same layer) + p = _polyToMultipoly(p); + std::string wkt = p->toString(); const char* t = wkt.data(); OGRGeometry* geom; @@ -408,4 +406,16 @@ void OgrMultifileWriter::_writeWayPolygon(const ConstOsmMapPtr& map, const WayPt OGRFeature::DestroyFeature(poFeature); } +std::shared_ptr OgrMultifileWriter::_polyToMultipoly(const std::shared_ptr& geometry) const +{ + std::shared_ptr multi = geometry; + if (_convertPolygons() && geometry->getGeometryTypeId() == GeometryTypeId::GEOS_POLYGON) + { + // Convert the single polygon to a multipolygon + std::vector* single = new std::vector({ geometry->clone().release() }); + multi.reset(geos::geom::GeometryFactory::getDefaultInstance()->createMultiPolygon(single)); + } + return multi; +} + } diff --git a/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.h b/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.h index 84317add02..0b387c253c 100644 --- a/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.h +++ b/hoot-core/src/main/cpp/hoot/core/io/OgrMultifileWriter.h @@ -87,7 +87,7 @@ class OgrMultifileWriter : public OsmMapWriter, public Configurable virtual const char* _getDriverName() const = 0; virtual QString _getFileExtension() const = 0; virtual OgrOptions _getOptions() const = 0; - virtual OGRwkbGeometryType _getPolygonGeometryType() const = 0; + virtual bool _convertPolygons() const = 0; void _writeRelationPolygon(const ConstOsmMapPtr& map, const RelationPtr& relation) const; void _writeWayPolygon(const ConstOsmMapPtr& map, const WayPtr& way) const; @@ -95,6 +95,7 @@ class OgrMultifileWriter : public OsmMapWriter, public Configurable void _setupDataset(const ConstOsmMapPtr& map, const QString& path, OGRwkbGeometryType geometry_type, ElementType element_type); OGRFeature* _createFeature(const Tags& tags, double circular_error) const; void _cleanupDataset(); + std::shared_ptr _polyToMultipoly(const std::shared_ptr& geometry) const; }; } diff --git a/hoot-core/src/main/cpp/hoot/core/io/ShapefileWriter.h b/hoot-core/src/main/cpp/hoot/core/io/ShapefileWriter.h index 79622df8c7..a856ceee36 100644 --- a/hoot-core/src/main/cpp/hoot/core/io/ShapefileWriter.h +++ b/hoot-core/src/main/cpp/hoot/core/io/ShapefileWriter.h @@ -56,7 +56,7 @@ class ShapefileWriter : public OgrMultifileWriter const char* _getDriverName() const override { return "ESRI Shapefile"; }; QString _getFileExtension() const override { return ".shp"; } OgrOptions _getOptions() const override; - OGRwkbGeometryType _getPolygonGeometryType() const override { return OGRwkbGeometryType::wkbMultiPolygon; } + bool _convertPolygons() const override { return false; } };