Coverage Report

Created: 2026-07-25 06:50

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(GDAL_ARG_NAME_INPUT_CRS, 's', _("Input CRS"), &m_srcCrs)
36
0
        .SetIsCRSArg()
37
0
        .AddHiddenAlias("src-crs")
38
0
        .AddHiddenAlias("s_srs");
39
0
    AddArg(GDAL_ARG_NAME_OUTPUT_CRS, 'd', _("Output CRS"), &m_dstCrs)
40
0
        .SetIsCRSArg()
41
0
        .AddHiddenAlias("dst-crs")
42
0
        .AddHiddenAlias("t_srs")
43
0
        .SetMutualExclusionGroup("output-crs");
44
0
    AddArg("like", 0, _("Dataset from which an output CRS should be extracted"),
45
0
           &m_likeDataset, GDAL_OF_RASTER | GDAL_OF_VECTOR)
46
0
        .SetMetaVar("DATASET")
47
0
        .SetMutualExclusionGroup("output-crs");
48
0
    AddArg("like-layer", 0, ("Name of the layer of the 'like' dataset"),
49
0
           &m_likeLayer)
50
0
        .SetMetaVar("LAYER-NAME");
51
0
}
52
53
/************************************************************************/
54
/*               GDALVectorReprojectAlgorithm::RunStep()                */
55
/************************************************************************/
56
57
bool GDALVectorReprojectAlgorithm::RunStep(GDALPipelineStepRunContext &)
58
0
{
59
0
    auto poSrcDS = m_inputDataset[0].GetDatasetRef();
60
0
    CPLAssert(poSrcDS);
61
62
0
    CPLAssert(m_outputDataset.GetName().empty());
63
0
    CPLAssert(!m_outputDataset.GetDatasetRef());
64
65
0
    std::unique_ptr<OGRSpatialReference> poSrcCRS;
66
0
    if (!m_srcCrs.empty())
67
0
    {
68
0
        poSrcCRS = std::make_unique<OGRSpatialReference>();
69
0
        poSrcCRS->SetFromUserInput(m_srcCrs.c_str());
70
0
        poSrcCRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
71
0
    }
72
73
0
    OGRSpatialReference oDstCRS;
74
0
    if (!m_dstCrs.empty())
75
0
    {
76
0
        oDstCRS.SetFromUserInput(m_dstCrs.c_str());
77
0
        oDstCRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
78
0
    }
79
0
    else if (auto *poLikeDS = m_likeDataset.GetDatasetRef())
80
0
    {
81
0
        if (!m_likeLayer.empty())
82
0
        {
83
0
            const auto *poLikeLayer =
84
0
                poLikeDS->GetLayerByName(m_likeLayer.c_str());
85
0
            if (!poLikeLayer)
86
0
            {
87
0
                ReportError(CE_Failure, CPLE_AppDefined,
88
0
                            "Specified layer '%s' not found.",
89
0
                            m_likeLayer.c_str());
90
0
                return false;
91
0
            }
92
0
            if (!poLikeLayer->GetSpatialRef())
93
0
            {
94
0
                ReportError(
95
0
                    CE_Failure, CPLE_AppDefined,
96
0
                    "Specified layer '%s' has no spatial reference system.",
97
0
                    m_likeLayer.c_str());
98
0
                return false;
99
0
            }
100
101
0
            oDstCRS = *poLikeLayer->GetSpatialRef();
102
0
        }
103
0
        else
104
0
        {
105
0
            const auto *poLikeCRS = poLikeDS->GetSpatialRef();
106
107
0
            if (!poLikeCRS)
108
0
            {
109
0
                ReportError(
110
0
                    CE_Failure, CPLE_AppDefined,
111
0
                    "Dataset specified by --like has no spatial reference "
112
0
                    "system, or has multiple layers with different spatial "
113
0
                    "reference systems. An individual layer can be specified "
114
0
                    "with --like-layer.");
115
0
                return false;
116
0
            }
117
0
            oDstCRS = *poLikeCRS;
118
0
        }
119
0
    }
120
0
    else
121
0
    {
122
0
        ReportError(CE_Failure, CPLE_AppDefined,
123
0
                    "Must specify --output-crs or --like");
124
0
        return false;
125
0
    }
126
127
0
    auto reprojectedDataset =
128
0
        std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
129
130
0
    const int nLayerCount = poSrcDS->GetLayerCount();
131
0
    bool ret = true;
132
0
    for (int i = 0; ret && i < nLayerCount; ++i)
133
0
    {
134
0
        auto poSrcLayer = poSrcDS->GetLayer(i);
135
0
        ret = (poSrcLayer != nullptr);
136
0
        if (ret)
137
0
        {
138
0
            if ((m_activeLayer.empty() &&
139
0
                 poSrcLayer->GetGeomType() != wkbNone) ||
140
0
                m_activeLayer == poSrcLayer->GetDescription())
141
0
            {
142
0
                const OGRSpatialReference *poSrcLayerCRS;
143
0
                if (poSrcCRS)
144
0
                    poSrcLayerCRS = poSrcCRS.get();
145
0
                else
146
0
                    poSrcLayerCRS = poSrcLayer->GetSpatialRef();
147
0
                if (!poSrcLayerCRS)
148
0
                {
149
0
                    ReportError(CE_Failure, CPLE_AppDefined,
150
0
                                "Layer '%s' has no spatial reference system",
151
0
                                poSrcLayer->GetName());
152
0
                    return false;
153
0
                }
154
0
                auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
155
0
                    OGRCreateCoordinateTransformation(poSrcLayerCRS, &oDstCRS));
156
0
                auto poReversedCT =
157
0
                    std::unique_ptr<OGRCoordinateTransformation>(
158
0
                        OGRCreateCoordinateTransformation(&oDstCRS,
159
0
                                                          poSrcLayerCRS));
160
0
                ret = (poCT != nullptr) && (poReversedCT != nullptr);
161
0
                if (ret)
162
0
                {
163
0
                    reprojectedDataset->AddLayer(
164
0
                        *poSrcLayer,
165
0
                        std::make_unique<OGRWarpedLayer>(
166
0
                            poSrcLayer, /* iGeomField = */ 0,
167
0
                            /*bTakeOwnership = */ false, std::move(poCT),
168
0
                            std::move(poReversedCT)));
169
0
                }
170
0
            }
171
0
            else
172
0
            {
173
0
                reprojectedDataset->AddLayer(
174
0
                    *poSrcLayer,
175
0
                    std::make_unique<GDALVectorPipelinePassthroughLayer>(
176
0
                        *poSrcLayer));
177
0
            }
178
0
        }
179
0
    }
180
181
0
    if (ret)
182
0
        m_outputDataset.Set(std::move(reprojectedDataset));
183
184
0
    return ret;
185
0
}
186
187
GDALVectorReprojectAlgorithmStandalone::
188
0
    ~GDALVectorReprojectAlgorithmStandalone() = default;
189
190
//! @endcond