File: gdalalg_vector_simplify_coverage.cpp

package info (click to toggle)
gdal 3.12.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 92,292 kB
  • sloc: cpp: 1,223,498; ansic: 206,434; python: 26,278; java: 6,001; xml: 4,769; sh: 3,855; cs: 2,513; yacc: 1,306; makefile: 214
file content (155 lines) | stat: -rw-r--r-- 4,288 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/******************************************************************************
*
 * Project:  GDAL
 * Purpose:  "gdal vector simplify-coverage" subcommand
 * Author:   Daniel Baston
 *
 ******************************************************************************
 * Copyright (c) 2025, ISciences LLC
 *
 * SPDX-License-Identifier: MIT
 ****************************************************************************/

#include "gdalalg_vector_simplify_coverage.h"

#include "cpl_error.h"
#include "gdal_priv.h"
#include "gdalalg_vector_geom.h"
#include "ogr_geometry.h"
#include "ogr_geos.h"
#include "ogrsf_frmts.h"

#include <cinttypes>

#ifndef _
#define _(x) (x)
#endif

//! @cond Doxygen_Suppress

GDALVectorSimplifyCoverageAlgorithm::GDALVectorSimplifyCoverageAlgorithm(
    bool standaloneStep)
    : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
                                      standaloneStep)
{
    AddActiveLayerArg(&m_activeLayer);
    AddArg("tolerance", 0, _("Distance tolerance for simplification."),
           &m_opts.tolerance)
        .SetPositional()
        .SetRequired()
        .SetMinValueIncluded(0);
    AddArg("preserve-boundary", 0,
           _("Whether the exterior boundary should be preserved."),
           &m_opts.preserveBoundary);
}

#if defined HAVE_GEOS &&                                                       \
    (GEOS_VERSION_MAJOR > 3 ||                                                 \
     (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 12))

class GDALVectorSimplifyCoverageOutputDataset final
    : public GDALGeosNonStreamingAlgorithmDataset
{
  public:
    GDALVectorSimplifyCoverageOutputDataset(
        const GDALVectorSimplifyCoverageAlgorithm::Options &opts)
        : m_opts(opts)
    {
    }

    ~GDALVectorSimplifyCoverageOutputDataset() override;

    bool PolygonsOnly() const override
    {
        return true;
    }

    bool SkipEmpty() const override
    {
        return false;
    }

    bool ProcessGeos() override
    {
        // Perform coverage simplification
        GEOSGeometry *coll = GEOSGeom_createCollection_r(
            m_poGeosContext, GEOS_GEOMETRYCOLLECTION, m_apoGeosInputs.data(),
            static_cast<unsigned int>(m_apoGeosInputs.size()));

        if (coll == nullptr)
        {
            return false;
        }

        m_apoGeosInputs.clear();

        m_poGeosResultAsCollection = GEOSCoverageSimplifyVW_r(
            m_poGeosContext, coll, m_opts.tolerance, m_opts.preserveBoundary);
        GEOSGeom_destroy_r(m_poGeosContext, coll);

        return m_poGeosResultAsCollection != nullptr;
    }

  private:
    CPL_DISALLOW_COPY_ASSIGN(GDALVectorSimplifyCoverageOutputDataset)

    const GDALVectorSimplifyCoverageAlgorithm::Options &m_opts;
};

GDALVectorSimplifyCoverageOutputDataset::
    ~GDALVectorSimplifyCoverageOutputDataset() = default;

bool GDALVectorSimplifyCoverageAlgorithm::RunStep(GDALPipelineStepRunContext &)
{
    auto poSrcDS = m_inputDataset[0].GetDatasetRef();
    auto poDstDS =
        std::make_unique<GDALVectorSimplifyCoverageOutputDataset>(m_opts);

    bool bFoundActiveLayer = false;

    for (auto &&poSrcLayer : poSrcDS->GetLayers())
    {
        if (m_activeLayer.empty() ||
            m_activeLayer == poSrcLayer->GetDescription())
        {
            if (!poDstDS->AddProcessedLayer(*poSrcLayer))
            {
                return false;
            }
            bFoundActiveLayer = true;
        }
        else
        {
            poDstDS->AddPassThroughLayer(*poSrcLayer);
        }
    }

    if (!bFoundActiveLayer)
    {
        ReportError(CE_Failure, CPLE_AppDefined,
                    "Specified layer '%s' was not found",
                    m_activeLayer.c_str());
        return false;
    }

    m_outputDataset.Set(std::move(poDstDS));

    return true;
}

#else

bool GDALVectorSimplifyCoverageAlgorithm::RunStep(GDALPipelineStepRunContext &)
{
    ReportError(CE_Failure, CPLE_AppDefined,
                "%s requires GDAL to be built against version 3.12 or later of "
                "the GEOS library.",
                NAME);
    return false;
}
#endif  // HAVE_GEOS

GDALVectorSimplifyCoverageAlgorithmStandalone::
    ~GDALVectorSimplifyCoverageAlgorithmStandalone() = default;

//! @endcond