Coverage Report

Created: 2025-06-13 06:29

/src/gdal/alg/marching_squares/contour_generator.h
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  Marching squares
4
 * Purpose:  Classes for contour generation
5
 * Author:   Hugo Mercier, <hugo dot mercier at oslandia dot com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2018, Oslandia <infos at oslandia dot com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef MARCHING_SQUARES_CONTOUR_GENERATOR_H
14
#define MARCHING_SQUARES_CONTOUR_GENERATOR_H
15
16
#include <vector>
17
#include <algorithm>
18
19
#include "gdal.h"
20
21
#include "utility.h"
22
#include "point.h"
23
#include "square.h"
24
25
namespace marching_squares
26
{
27
28
template <typename ContourWriter, typename LevelGenerator>
29
class ContourGenerator
30
{
31
  public:
32
    ContourGenerator(size_t width, size_t height, bool hasNoData,
33
                     double noDataValue, ContourWriter &writer,
34
                     LevelGenerator &levelGenerator)
35
0
        : width_(width), height_(height), hasNoData_(hasNoData),
36
0
          noDataValue_(noDataValue), previousLine_(), writer_(writer),
37
0
          levelGenerator_(levelGenerator)
38
0
    {
39
0
        previousLine_.resize(width_);
40
0
        std::fill(previousLine_.begin(), previousLine_.end(), NaN);
41
0
    }
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>, marching_squares::IntervalLevelRangeIterator>::ContourGenerator(unsigned long, unsigned long, bool, double, marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>&, marching_squares::IntervalLevelRangeIterator&)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ContourGenerator(unsigned long, unsigned long, bool, double, marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>&, marching_squares::FixedLevelRangeIterator&)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ContourGenerator(unsigned long, unsigned long, bool, double, marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>&, marching_squares::FixedLevelRangeIterator&)
42
43
    CPLErr feedLine(const double *line)
44
0
    {
45
0
        if (lineIdx_ <= height_)
46
0
        {
47
0
            feedLine_(line);
48
0
            if (lineIdx_ == height_)
49
0
            {
50
                // last line
51
0
                feedLine_(nullptr);
52
0
            }
53
0
        }
54
0
        return CE_None;
55
0
    }
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::feedLine(double const*)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::feedLine(double const*)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>, marching_squares::IntervalLevelRangeIterator>::feedLine(double const*)
56
57
  private:
58
    size_t width_;
59
    size_t height_;
60
    bool hasNoData_;
61
    double noDataValue_;
62
63
    size_t lineIdx_ = 0;
64
65
    std::vector<double> previousLine_;
66
67
    ContourWriter &writer_;
68
    LevelGenerator &levelGenerator_;
69
70
    class ExtendedLine
71
    {
72
      public:
73
        ExtendedLine(const double *line, size_t size, bool hasNoData,
74
                     double noDataValue)
75
0
            : line_(line), size_(size), hasNoData_(hasNoData),
76
0
              noDataValue_(noDataValue)
77
0
        {
78
0
        }
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ExtendedLine::ExtendedLine(double const*, unsigned long, bool, double)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ExtendedLine::ExtendedLine(double const*, unsigned long, bool, double)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>, marching_squares::IntervalLevelRangeIterator>::ExtendedLine::ExtendedLine(double const*, unsigned long, bool, double)
79
80
        double value(int idx) const
81
0
        {
82
0
            if (line_ == nullptr)
83
0
                return NaN;
84
0
            if (idx < 0 || idx >= int(size_))
85
0
                return NaN;
86
0
            double v = line_[idx];
87
0
            if (hasNoData_ && v == noDataValue_)
88
0
                return NaN;
89
0
            return v;
90
0
        }
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ExtendedLine::value(int) const
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ExtendedLine::value(int) const
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>, marching_squares::IntervalLevelRangeIterator>::ExtendedLine::value(int) const
91
92
      private:
93
        const double *line_;
94
        size_t size_;
95
        bool hasNoData_;
96
        double noDataValue_;
97
    };
98
99
    void feedLine_(const double *line)
100
0
    {
101
0
        writer_.beginningOfLine();
102
103
0
        ExtendedLine previous(&previousLine_[0], width_, hasNoData_,
104
0
                              noDataValue_);
105
0
        ExtendedLine current(line, width_, hasNoData_, noDataValue_);
106
0
        for (int colIdx = -1; colIdx < int(width_); colIdx++)
107
0
        {
108
0
            const ValuedPoint upperLeft(colIdx + 1 - .5, lineIdx_ - .5,
109
0
                                        previous.value(colIdx));
110
0
            const ValuedPoint upperRight(colIdx + 1 + .5, lineIdx_ - .5,
111
0
                                         previous.value(colIdx + 1));
112
0
            const ValuedPoint lowerLeft(colIdx + 1 - .5, lineIdx_ + .5,
113
0
                                        current.value(colIdx));
114
0
            const ValuedPoint lowerRight(colIdx + 1 + .5, lineIdx_ + .5,
115
0
                                         current.value(colIdx + 1));
116
117
0
            Square(upperLeft, upperRight, lowerLeft, lowerRight)
118
0
                .process(levelGenerator_, writer_);
119
0
        }
120
0
        if (line != nullptr)
121
0
            std::copy(line, line + width_, previousLine_.begin());
122
0
        lineIdx_++;
123
124
0
        writer_.endOfLine();
125
0
    }
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::feedLine_(double const*)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::feedLine_(double const*)
Unexecuted instantiation: marching_squares::ContourGenerator<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::IntervalLevelRangeIterator>, marching_squares::IntervalLevelRangeIterator>::feedLine_(double const*)
126
};
127
128
template <typename ContourWriter, typename LevelGenerator>
129
inline ContourGenerator<ContourWriter, LevelGenerator> *
130
newContourGenerator(size_t width, size_t height, bool hasNoData,
131
                    double noDataValue, ContourWriter &writer,
132
                    LevelGenerator &levelGenerator)
133
{
134
    return new ContourGenerator<ContourWriter, LevelGenerator>(
135
        width, height, hasNoData, noDataValue, writer, levelGenerator);
136
}
137
138
template <typename ContourWriter, typename LevelGenerator>
139
class ContourGeneratorFromRaster
140
    : public ContourGenerator<ContourWriter, LevelGenerator>
141
{
142
  public:
143
    ContourGeneratorFromRaster(const GDALRasterBandH band, bool hasNoData,
144
                               double noDataValue, ContourWriter &writer,
145
                               LevelGenerator &levelGenerator)
146
0
        : ContourGenerator<ContourWriter, LevelGenerator>(
147
0
              GDALGetRasterBandXSize(band), GDALGetRasterBandYSize(band),
148
0
              hasNoData, noDataValue, writer, levelGenerator),
149
0
          band_(band)
150
0
    {
151
0
    }
Unexecuted instantiation: marching_squares::ContourGeneratorFromRaster<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ContourGeneratorFromRaster(void*, bool, double, marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>&, marching_squares::FixedLevelRangeIterator&)
Unexecuted instantiation: marching_squares::ContourGeneratorFromRaster<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::ContourGeneratorFromRaster(void*, bool, double, marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>&, marching_squares::FixedLevelRangeIterator&)
152
153
    bool process(GDALProgressFunc progressFunc = nullptr,
154
                 void *progressData = nullptr)
155
0
    {
156
0
        size_t width = GDALGetRasterBandXSize(band_);
157
0
        size_t height = GDALGetRasterBandYSize(band_);
158
0
        std::vector<double> line;
159
0
        line.resize(width);
160
161
0
        for (size_t lineIdx = 0; lineIdx < height; lineIdx++)
162
0
        {
163
0
            if (progressFunc &&
164
0
                progressFunc(double(lineIdx) / height, "Processing line",
165
0
                             progressData) == FALSE)
166
0
                return false;
167
168
0
            CPLErr error =
169
0
                GDALRasterIO(band_, GF_Read, 0, int(lineIdx), int(width), 1,
170
0
                             &line[0], int(width), 1, GDT_Float64, 0, 0);
171
0
            if (error != CE_None)
172
0
            {
173
0
                CPLDebug("CONTOUR", "failed fetch %d %d", int(lineIdx),
174
0
                         int(width));
175
0
                return false;
176
0
            }
177
0
            this->feedLine(&line[0]);
178
0
        }
179
0
        if (progressFunc)
180
0
            progressFunc(1.0, "", progressData);
181
0
        return true;
182
0
    }
Unexecuted instantiation: marching_squares::ContourGeneratorFromRaster<marching_squares::SegmentMerger<marching_squares::PolygonRingAppender<PolygonContourWriter>, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::process(int (*)(double, char const*, void*), void*)
Unexecuted instantiation: marching_squares::ContourGeneratorFromRaster<marching_squares::SegmentMerger<GDALRingAppender, marching_squares::FixedLevelRangeIterator>, marching_squares::FixedLevelRangeIterator>::process(int (*)(double, char const*, void*), void*)
183
184
  private:
185
    const GDALRasterBandH band_;
186
187
    ContourGeneratorFromRaster(const ContourGeneratorFromRaster &) = delete;
188
    ContourGeneratorFromRaster &
189
    operator=(const ContourGeneratorFromRaster &) = delete;
190
};
191
192
}  // namespace marching_squares
193
194
#endif