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