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 100 : GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm(bool standaloneStep) 31 : : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 32 100 : standaloneStep) 33 : { 34 100 : AddActiveLayerArg(&m_activeLayer); 35 200 : AddArg(GDAL_ARG_NAME_INPUT_CRS, 's', _("Input CRS"), &m_srcCrs) 36 200 : .SetIsCRSArg() 37 200 : .AddHiddenAlias("src-crs") 38 100 : .AddHiddenAlias("s_srs"); 39 200 : AddArg(GDAL_ARG_NAME_OUTPUT_CRS, 'd', _("Output CRS"), &m_dstCrs) 40 200 : .SetIsCRSArg() 41 100 : .SetRequired() 42 200 : .AddHiddenAlias("dst-crs") 43 100 : .AddHiddenAlias("t_srs"); 44 100 : } 45 : 46 : /************************************************************************/ 47 : /* GDALVectorReprojectAlgorithm::RunStep() */ 48 : /************************************************************************/ 49 : 50 11 : bool GDALVectorReprojectAlgorithm::RunStep(GDALPipelineStepRunContext &) 51 : { 52 11 : auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 53 11 : CPLAssert(poSrcDS); 54 : 55 11 : CPLAssert(m_outputDataset.GetName().empty()); 56 11 : CPLAssert(!m_outputDataset.GetDatasetRef()); 57 : 58 11 : std::unique_ptr<OGRSpatialReference> poSrcCRS; 59 11 : 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 22 : OGRSpatialReference oDstCRS; 67 11 : oDstCRS.SetFromUserInput(m_dstCrs.c_str()); 68 11 : oDstCRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 69 : 70 : auto reprojectedDataset = 71 22 : std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS); 72 : 73 11 : const int nLayerCount = poSrcDS->GetLayerCount(); 74 11 : bool ret = true; 75 38 : for (int i = 0; ret && i < nLayerCount; ++i) 76 : { 77 28 : auto poSrcLayer = poSrcDS->GetLayer(i); 78 28 : ret = (poSrcLayer != nullptr); 79 28 : if (ret) 80 : { 81 45 : if (m_activeLayer.empty() || 82 17 : m_activeLayer == poSrcLayer->GetDescription()) 83 : { 84 : const OGRSpatialReference *poSrcLayerCRS; 85 12 : if (poSrcCRS) 86 3 : poSrcLayerCRS = poSrcCRS.get(); 87 : else 88 9 : poSrcLayerCRS = poSrcLayer->GetSpatialRef(); 89 12 : if (!poSrcLayerCRS) 90 : { 91 1 : ReportError(CE_Failure, CPLE_AppDefined, 92 : "Layer '%s' has no spatial reference system", 93 1 : poSrcLayer->GetName()); 94 1 : return false; 95 : } 96 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>( 97 22 : OGRCreateCoordinateTransformation(poSrcLayerCRS, &oDstCRS)); 98 : auto poReversedCT = 99 : std::unique_ptr<OGRCoordinateTransformation>( 100 : OGRCreateCoordinateTransformation(&oDstCRS, 101 22 : poSrcLayerCRS)); 102 11 : ret = (poCT != nullptr) && (poReversedCT != nullptr); 103 11 : if (ret) 104 : { 105 22 : reprojectedDataset->AddLayer( 106 : *poSrcLayer, 107 11 : std::make_unique<OGRWarpedLayer>( 108 0 : poSrcLayer, /* iGeomField = */ 0, 109 22 : /*bTakeOwnership = */ false, std::move(poCT), 110 11 : std::move(poReversedCT))); 111 : } 112 : } 113 : else 114 : { 115 32 : reprojectedDataset->AddLayer( 116 : *poSrcLayer, 117 32 : std::make_unique<GDALVectorPipelinePassthroughLayer>( 118 : *poSrcLayer)); 119 : } 120 : } 121 : } 122 : 123 10 : if (ret) 124 10 : m_outputDataset.Set(std::move(reprojectedDataset)); 125 : 126 10 : return ret; 127 : } 128 : 129 : GDALVectorReprojectAlgorithmStandalone:: 130 : ~GDALVectorReprojectAlgorithmStandalone() = default; 131 : 132 : //! @endcond