LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_reproject.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 57 58 98.3 %
Date: 2025-01-18 12:42:00 Functions: 6 6 100.0 %

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

Generated by: LCOV version 1.14