Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "reproject" step of "vector pipeline" 5 : * Author: Even Rouault <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "gdalalg_vector_reproject.h" 14 : 15 : #include "gdal_priv.h" 16 : #include "ogr_spatialref.h" 17 : #include "ogrsf_frmts.h" 18 : #include "ogrwarpedlayer.h" 19 : 20 : //! @cond Doxygen_Suppress 21 : 22 : #ifndef _ 23 : #define _(x) (x) 24 : #endif 25 : 26 : /************************************************************************/ 27 : /* GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm() */ 28 : /************************************************************************/ 29 : 30 101 : GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm(bool standaloneStep) 31 : : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 32 101 : standaloneStep) 33 : { 34 101 : AddActiveLayerArg(&m_activeLayer); 35 202 : AddArg(GDAL_ARG_NAME_INPUT_CRS, 's', _("Input CRS"), &m_srcCrs) 36 202 : .SetIsCRSArg() 37 202 : .AddHiddenAlias("src-crs") 38 101 : .AddHiddenAlias("s_srs"); 39 202 : AddArg(GDAL_ARG_NAME_OUTPUT_CRS, 'd', _("Output CRS"), &m_dstCrs) 40 202 : .SetIsCRSArg() 41 101 : .SetRequired() 42 202 : .AddHiddenAlias("dst-crs") 43 101 : .AddHiddenAlias("t_srs"); 44 101 : } 45 : 46 : /************************************************************************/ 47 : /* GDALVectorReprojectAlgorithm::RunStep() */ 48 : /************************************************************************/ 49 : 50 12 : bool GDALVectorReprojectAlgorithm::RunStep(GDALPipelineStepRunContext &) 51 : { 52 12 : auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 53 12 : CPLAssert(poSrcDS); 54 : 55 12 : CPLAssert(m_outputDataset.GetName().empty()); 56 12 : CPLAssert(!m_outputDataset.GetDatasetRef()); 57 : 58 12 : std::unique_ptr<OGRSpatialReference> poSrcCRS; 59 12 : if (!m_srcCrs.empty()) 60 : { 61 3 : poSrcCRS = std::make_unique<OGRSpatialReference>(); 62 3 : poSrcCRS->SetFromUserInput(m_srcCrs.c_str()); 63 3 : poSrcCRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 64 : } 65 : 66 24 : OGRSpatialReference oDstCRS; 67 12 : oDstCRS.SetFromUserInput(m_dstCrs.c_str()); 68 12 : oDstCRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 69 : 70 : auto reprojectedDataset = 71 24 : std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS); 72 : 73 12 : const int nLayerCount = poSrcDS->GetLayerCount(); 74 12 : bool ret = true; 75 40 : for (int i = 0; ret && i < nLayerCount; ++i) 76 : { 77 29 : auto poSrcLayer = poSrcDS->GetLayer(i); 78 29 : ret = (poSrcLayer != nullptr); 79 29 : if (ret) 80 : { 81 29 : if ((m_activeLayer.empty() && 82 47 : poSrcLayer->GetGeomType() != wkbNone) || 83 18 : m_activeLayer == poSrcLayer->GetDescription()) 84 : { 85 : const OGRSpatialReference *poSrcLayerCRS; 86 12 : if (poSrcCRS) 87 3 : poSrcLayerCRS = poSrcCRS.get(); 88 : else 89 9 : poSrcLayerCRS = poSrcLayer->GetSpatialRef(); 90 12 : if (!poSrcLayerCRS) 91 : { 92 1 : ReportError(CE_Failure, CPLE_AppDefined, 93 : "Layer '%s' has no spatial reference system", 94 1 : poSrcLayer->GetName()); 95 1 : return false; 96 : } 97 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>( 98 22 : OGRCreateCoordinateTransformation(poSrcLayerCRS, &oDstCRS)); 99 : auto poReversedCT = 100 : std::unique_ptr<OGRCoordinateTransformation>( 101 : OGRCreateCoordinateTransformation(&oDstCRS, 102 22 : poSrcLayerCRS)); 103 11 : ret = (poCT != nullptr) && (poReversedCT != nullptr); 104 11 : if (ret) 105 : { 106 22 : reprojectedDataset->AddLayer( 107 : *poSrcLayer, 108 11 : std::make_unique<OGRWarpedLayer>( 109 0 : poSrcLayer, /* iGeomField = */ 0, 110 22 : /*bTakeOwnership = */ false, std::move(poCT), 111 11 : std::move(poReversedCT))); 112 : } 113 : } 114 : else 115 : { 116 34 : reprojectedDataset->AddLayer( 117 : *poSrcLayer, 118 34 : std::make_unique<GDALVectorPipelinePassthroughLayer>( 119 : *poSrcLayer)); 120 : } 121 : } 122 : } 123 : 124 11 : if (ret) 125 11 : m_outputDataset.Set(std::move(reprojectedDataset)); 126 : 127 11 : return ret; 128 : } 129 : 130 : GDALVectorReprojectAlgorithmStandalone:: 131 : ~GDALVectorReprojectAlgorithmStandalone() = default; 132 : 133 : //! @endcond