Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "gdal vector convex-hull" 5 : * Author: Daniel Baston 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2026, ISciences LLC 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "gdalalg_vector_convex_hull.h" 14 : 15 : #include "gdal_priv.h" 16 : #include "ogrsf_frmts.h" 17 : 18 : #include <cinttypes> 19 : 20 : //! @cond Doxygen_Suppress 21 : 22 : #ifndef _ 23 : #define _(x) (x) 24 : #endif 25 : 26 80 : GDALVectorConvexHullAlgorithm::GDALVectorConvexHullAlgorithm( 27 80 : bool standaloneStep) 28 : : GDALVectorGeomAbstractAlgorithm(NAME, DESCRIPTION, HELP_URL, 29 80 : standaloneStep, m_opts) 30 : { 31 80 : } 32 : 33 : #ifdef HAVE_GEOS 34 : 35 : namespace 36 : { 37 : 38 : class GDALVectorConvexHullAlgorithmLayer final 39 : : public GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorConvexHullAlgorithm> 40 : { 41 : public: 42 3 : GDALVectorConvexHullAlgorithmLayer( 43 : OGRLayer &oSrcLayer, const GDALVectorConvexHullAlgorithm::Options &opts) 44 3 : : GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorConvexHullAlgorithm>( 45 : oSrcLayer, opts), 46 3 : m_poFeatureDefn(oSrcLayer.GetLayerDefn()->Clone()) 47 : { 48 3 : m_poFeatureDefn->Reference(); 49 : 50 : // Convex hull output type can be Point/LineString/Polygon depending on input. 51 : // To avoid schema/type conflicts, advertise unknown geometry type for 52 : // processed geometry fields. 53 6 : for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i) 54 : { 55 3 : if (IsSelectedGeomField(i)) 56 3 : m_poFeatureDefn->GetGeomFieldDefn(i)->SetType(wkbUnknown); 57 : } 58 3 : } 59 : 60 6 : ~GDALVectorConvexHullAlgorithmLayer() override 61 3 : { 62 3 : m_poFeatureDefn->Release(); 63 6 : } 64 : 65 6 : const OGRFeatureDefn *GetLayerDefn() const override 66 : { 67 6 : return m_poFeatureDefn; 68 : } 69 : 70 : protected: 71 : using GDALVectorGeomOneToOneAlgorithmLayer::TranslateFeature; 72 : 73 : std::unique_ptr<OGRFeature> 74 3 : TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const override 75 : { 76 3 : const int nGeomFieldCount = poSrcFeature->GetGeomFieldCount(); 77 6 : for (int i = 0; i < nGeomFieldCount; ++i) 78 : { 79 3 : if (!IsSelectedGeomField(i)) 80 0 : continue; 81 : 82 3 : if (const OGRGeometry *poGeom = poSrcFeature->GetGeomFieldRef(i)) 83 : { 84 3 : std::unique_ptr<OGRGeometry> poHull(poGeom->ConvexHull()); 85 3 : if (!poHull) 86 : { 87 0 : CPLError( 88 : CE_Failure, CPLE_AppDefined, 89 : "Failed to compute convex hull of feature %" PRId64, 90 0 : static_cast<int64_t>(poSrcFeature->GetFID())); 91 0 : return nullptr; 92 : } 93 : 94 3 : poHull->assignSpatialReference(poGeom->getSpatialReference()); 95 3 : poSrcFeature->SetGeomField(i, std::move(poHull)); 96 : } 97 : } 98 : 99 3 : poSrcFeature->SetFDefnUnsafe(m_poFeatureDefn); 100 3 : return poSrcFeature; 101 : } 102 : 103 : private: 104 : OGRFeatureDefn *const m_poFeatureDefn; 105 : 106 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorConvexHullAlgorithmLayer) 107 : }; 108 : 109 : } // namespace 110 : 111 : #endif // HAVE_GEOS 112 : 113 : std::unique_ptr<OGRLayerWithTranslateFeature> 114 3 : GDALVectorConvexHullAlgorithm::CreateAlgLayer( 115 : [[maybe_unused]] OGRLayer &srcLayer) 116 : { 117 : #ifdef HAVE_GEOS 118 3 : return std::make_unique<GDALVectorConvexHullAlgorithmLayer>(srcLayer, 119 3 : m_opts); 120 : #else 121 : CPLAssert(false); 122 : return nullptr; 123 : #endif 124 : } 125 : 126 3 : bool GDALVectorConvexHullAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt) 127 : { 128 : #ifdef HAVE_GEOS 129 3 : return GDALVectorGeomAbstractAlgorithm::RunStep(ctxt); 130 : #else 131 : (void)ctxt; 132 : ReportError(CE_Failure, CPLE_NotSupported, 133 : "This algorithm is only supported for builds against GEOS"); 134 : return false; 135 : #endif 136 : } 137 : 138 : GDALVectorConvexHullAlgorithmStandalone:: 139 : ~GDALVectorConvexHullAlgorithmStandalone() = default; 140 : 141 : //! @endcond