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