Coverage Report

Created: 2026-02-14 06:52

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