Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "gdal vector simplify-coverage" subcommand 5 : * Author: Daniel Baston 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2025, ISciences LLC 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "gdalalg_vector_simplify_coverage.h" 14 : 15 : #include "cpl_error.h" 16 : #include "gdal_priv.h" 17 : #include "gdalalg_vector_geom.h" 18 : #include "ogr_geometry.h" 19 : #include "ogr_geos.h" 20 : #include "ogrsf_frmts.h" 21 : 22 : #include <cinttypes> 23 : 24 : #ifndef _ 25 : #define _(x) (x) 26 : #endif 27 : 28 : //! @cond Doxygen_Suppress 29 : 30 54 : GDALVectorSimplifyCoverageAlgorithm::GDALVectorSimplifyCoverageAlgorithm( 31 54 : bool standaloneStep) 32 : : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 33 54 : standaloneStep) 34 : { 35 54 : AddActiveLayerArg(&m_activeLayer); 36 : AddArg("tolerance", 0, _("Distance tolerance for simplification."), 37 108 : &m_opts.tolerance) 38 54 : .SetRequired() 39 54 : .SetMinValueIncluded(0); 40 : AddArg("preserve-boundary", 0, 41 : _("Whether the exterior boundary should be preserved."), 42 54 : &m_opts.preserveBoundary); 43 54 : } 44 : 45 : #if defined HAVE_GEOS && \ 46 : (GEOS_VERSION_MAJOR > 3 || \ 47 : (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 12)) 48 : 49 16 : class GDALVectorSimplifyCoverageOutputDataset final 50 : : public GDALGeosNonStreamingAlgorithmDataset 51 : { 52 : public: 53 8 : GDALVectorSimplifyCoverageOutputDataset( 54 : const GDALVectorSimplifyCoverageAlgorithm::Options &opts) 55 8 : : m_opts(opts) 56 : { 57 8 : } 58 : 59 : ~GDALVectorSimplifyCoverageOutputDataset() override; 60 : 61 43 : bool PolygonsOnly() const override 62 : { 63 43 : return true; 64 : } 65 : 66 40 : bool SkipEmpty() const override 67 : { 68 40 : return false; 69 : } 70 : 71 4 : bool ProcessGeos() override 72 : { 73 : // Perform coverage simplification 74 4 : GEOSGeometry *coll = GEOSGeom_createCollection_r( 75 : m_poGeosContext, GEOS_GEOMETRYCOLLECTION, m_apoGeosInputs.data(), 76 4 : static_cast<unsigned int>(m_apoGeosInputs.size())); 77 : 78 4 : if (coll == nullptr) 79 : { 80 0 : return false; 81 : } 82 : 83 4 : m_apoGeosInputs.clear(); 84 : 85 8 : m_poGeosResultAsCollection = GEOSCoverageSimplifyVW_r( 86 4 : m_poGeosContext, coll, m_opts.tolerance, m_opts.preserveBoundary); 87 4 : GEOSGeom_destroy_r(m_poGeosContext, coll); 88 : 89 4 : return m_poGeosResultAsCollection != nullptr; 90 : } 91 : 92 : private: 93 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorSimplifyCoverageOutputDataset) 94 : 95 : const GDALVectorSimplifyCoverageAlgorithm::Options &m_opts; 96 : }; 97 : 98 : GDALVectorSimplifyCoverageOutputDataset:: 99 : ~GDALVectorSimplifyCoverageOutputDataset() = default; 100 : 101 8 : bool GDALVectorSimplifyCoverageAlgorithm::RunStep(GDALPipelineStepRunContext &) 102 : { 103 8 : auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 104 : auto poDstDS = 105 16 : std::make_unique<GDALVectorSimplifyCoverageOutputDataset>(m_opts); 106 : 107 8 : bool bFoundActiveLayer = false; 108 : 109 15 : for (auto &&poSrcLayer : poSrcDS->GetLayers()) 110 : { 111 14 : if (m_activeLayer.empty() || 112 4 : m_activeLayer == poSrcLayer->GetDescription()) 113 : { 114 7 : if (!poDstDS->AddProcessedLayer(*poSrcLayer)) 115 : { 116 3 : return false; 117 : } 118 4 : bFoundActiveLayer = true; 119 : } 120 : else 121 : { 122 3 : poDstDS->AddPassThroughLayer(*poSrcLayer); 123 : } 124 : } 125 : 126 5 : if (!bFoundActiveLayer) 127 : { 128 1 : ReportError(CE_Failure, CPLE_AppDefined, 129 : "Specified layer '%s' was not found", 130 : m_activeLayer.c_str()); 131 1 : return false; 132 : } 133 : 134 4 : m_outputDataset.Set(std::move(poDstDS)); 135 : 136 4 : return true; 137 : } 138 : 139 : #else 140 : 141 : bool GDALVectorSimplifyCoverageAlgorithm::RunStep(GDALPipelineStepRunContext &) 142 : { 143 : ReportError(CE_Failure, CPLE_AppDefined, 144 : "%s requires GDAL to be built against version 3.12 or later of " 145 : "the GEOS library.", 146 : NAME); 147 : return false; 148 : } 149 : #endif // HAVE_GEOS 150 : 151 : GDALVectorSimplifyCoverageAlgorithmStandalone:: 152 : ~GDALVectorSimplifyCoverageAlgorithmStandalone() = default; 153 : 154 : //! @endcond