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