Coverage Report

Created: 2026-06-13 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/include/geos/operation/buffer/OffsetCurveBuilder.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2009-2011  Sandro Santilli <strk@kbt.io>
7
 * Copyright (C) 2006-2007 Refractions Research Inc.
8
 *
9
 * This is free software; you can redistribute and/or modify it under
10
 * the terms of the GNU Lesser General Public Licence as published
11
 * by the Free Software Foundation.
12
 * See the COPYING file for more information.
13
 *
14
 **********************************************************************
15
 *
16
 * Last port: operation/buffer/OffsetCurveBuilder.java r378 (JTS-1.12)
17
 *
18
 **********************************************************************/
19
20
#pragma once
21
22
#include <geos/export.h>
23
24
#include <geos/operation/buffer/BufferParameters.h> // for composition
25
#include <geos/operation/buffer/OffsetSegmentGenerator.h>
26
27
#include <vector>
28
#include <memory> // for unique_ptr
29
30
#ifdef _MSC_VER
31
#pragma warning(push)
32
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
33
#endif
34
35
// Forward declarations
36
namespace geos {
37
namespace geom {
38
class CoordinateSequence;
39
class PrecisionModel;
40
}
41
}
42
43
namespace geos {
44
namespace operation { // geos.operation
45
namespace buffer { // geos.operation.buffer
46
47
/**
48
 * \class OffsetCurveBuilder
49
 *
50
 * \brief
51
 * Computes the raw offset curve for a
52
 * single Geometry component (ring, line or point).
53
 *
54
 * A raw offset curve line is not noded -
55
 * it may contain self-intersections (and usually will).
56
 * The final buffer polygon is computed by forming a topological graph
57
 * of all the noded raw curves and tracing outside contours.
58
 * The points in the raw curve are rounded to a given PrecisionModel.
59
 *
60
 * Note: this may not produce correct results if the input
61
 * contains repeated or invalid points.
62
 * Repeated points should be removed before calling.
63
 * See removeRepeatedAndInvalidPoints.
64
 */
65
class GEOS_DLL OffsetCurveBuilder {
66
    using CoordinateSequence = geos::geom::CoordinateSequence;
67
    using PrecisionModel = geos::geom::PrecisionModel;
68
69
public:
70
71
    /*
72
     * @param nBufParams buffer parameters, this object will
73
     *                   keep a reference to the passed parameters
74
     *                   so caller must make sure the object is
75
     *                   kept alive for the whole lifetime of
76
     *                   the buffer builder.
77
     */
78
    OffsetCurveBuilder(
79
        const PrecisionModel* newPrecisionModel,
80
        const BufferParameters& nBufParams)
81
0
        : distance(0.0)
82
0
        , precisionModel(newPrecisionModel)
83
0
        , bufParams(nBufParams)
84
0
        {}
85
86
    /** \brief
87
     * Gets the buffer parameters being used to generate the curve.
88
     *
89
     * @return the buffer parameters being used
90
     */
91
    const BufferParameters&
92
    getBufferParameters() const
93
0
    {
94
0
        return bufParams;
95
0
    }
96
97
    /**
98
     * Tests whether the offset curve for line or point geometries
99
     * at the given offset distance is empty (does not exist).
100
     * This is the case if:
101
     *
102
     *  * the distance is zero,
103
     *  * the distance is negative, except for the case of singled-sided buffers
104
     *
105
     * @param distance the offset curve distance
106
     * @return true if the offset curve is empty
107
     */
108
    bool isLineOffsetEmpty(double distance);
109
110
    /** \brief
111
     * This method handles single points as well as lines.
112
     *
113
     * Lines are assumed to **not** be closed (the function will not
114
     * fail for closed lines, but will generate superfluous line caps).
115
     *
116
     * @param inputPts input points
117
     * @param distance offset distance
118
     * @param lineList the std::vector to which the newly created
119
     *                 CoordinateSequences will be pushed_back.
120
     */
121
    void getLineCurve(const CoordinateSequence* inputPts,
122
        double distance,
123
        std::vector<std::unique_ptr<CoordinateSequence>>& lineList);
124
125
    /**
126
    * This method handles single points as well as LineStrings.
127
    * LineStrings are assumed <b>not</b> to be closed (the function will not
128
    * fail for closed lines, but will generate superfluous line caps).
129
    *
130
    * @param inputPts the vertices of the line to offset
131
    * @param pDistance the offset distance
132
    *
133
    * @return a Coordinate array representing the curve
134
    * or null if the curve is empty
135
    */
136
    std::unique_ptr<CoordinateSequence> getLineCurve(
137
        const CoordinateSequence* inputPts, double pDistance);
138
139
    /** \brief
140
     * This method handles single points as well as lines.
141
     *
142
     * Lines are assumed to **not** be closed (the function will not
143
     * fail for closed lines, but will generate superfluous line caps).
144
     *
145
     * @param inputPts input points
146
     * @param distance offset distance
147
     * @param lineList the std::vector to which newly created
148
     *                 CoordinateSequences will be pushed_back.
149
     *                 Caller will be responsible to delete them.
150
     * @param leftSide indicates that the left side buffer will be
151
     *                 obtained/skipped
152
     * @param rightSide indicates that the right side buffer will
153
     *                  be obtained/skipped
154
     *
155
     * @note This is a GEOS extension.
156
     */
157
    void getSingleSidedLineCurve(const CoordinateSequence* inputPts,
158
                                 double distance, std::vector<std::unique_ptr<CoordinateSequence>>& lineList,
159
                                 bool leftSide, bool rightSide) ;
160
161
    /** \brief
162
     * This method handles the degenerate cases of single points and lines,
163
     * as well as rings.
164
     *
165
     * @param inputPts input points
166
     * @param side a [Position](@ref geom::Position)
167
     * @param distance offset distance
168
     * @param lineList the std::vector to which CoordinateSequences will
169
     *                 be pushed_back
170
     */
171
    void getRingCurve(const CoordinateSequence* inputPts, int side,
172
                      double distance,
173
                      std::vector<std::unique_ptr<CoordinateSequence>>& lineList);
174
175
    /**
176
    * This method handles the degenerate cases of single points and lines,
177
    * as well as valid rings.
178
    *
179
    * @param inputPts the coordinates of the ring (must not contain repeated points)
180
    * @param side side the side Position of the ring on which to construct the buffer line
181
    * @param pDistance the positive distance at which to create the offset
182
    * @return a Coordinate array representing the curve,
183
    * or null if the curve is empty
184
    */
185
    std::unique_ptr<CoordinateSequence> getRingCurve(
186
        const CoordinateSequence* inputPts,
187
        int side, double pDistance);
188
189
    void getOffsetCurve(const CoordinateSequence* inputPts,
190
                        double p_distance,
191
                        std::vector<std::unique_ptr<CoordinateSequence>>& lineList);
192
193
    std::unique_ptr<CoordinateSequence> getOffsetCurve(
194
        const CoordinateSequence* inputPts,
195
        double pDistance);
196
197
198
private:
199
200
    double distance;
201
202
    const PrecisionModel* precisionModel;
203
204
    const BufferParameters& bufParams;
205
206
    /** \brief
207
     * Use a value which results in a potential distance error which is
208
     * significantly less than the error due to the quadrant segment discretization.
209
     *
210
     * For QS = 8 a value of 100 is reasonable.
211
     * This should produce a maximum of 1% distance error.
212
     */
213
    static const double SIMPLIFY_FACTOR; // 100.0;
214
215
    /** \brief
216
     * Computes the distance tolerance to use during input
217
     * line simplification.
218
     *
219
     * @param bufDistance the buffer distance
220
     * @return the simplification tolerance
221
     */
222
    double simplifyTolerance(double bufDistance);
223
224
    void computeLineBufferCurve(const CoordinateSequence& inputPts,
225
                                OffsetSegmentGenerator& segGen);
226
227
    void computeSingleSidedBufferCurve(const CoordinateSequence& inputPts,
228
                                       bool isRightSide,
229
                                       OffsetSegmentGenerator& segGen);
230
231
    void computeRingBufferCurve(const CoordinateSequence& inputPts,
232
                                int side, OffsetSegmentGenerator& segGen);
233
234
    void computePointCurve(const geom::Coordinate& pt,
235
                           OffsetSegmentGenerator& segGen);
236
237
    void computeOffsetCurve(
238
        const CoordinateSequence* inputPts,
239
        bool isRightSide,
240
        OffsetSegmentGenerator& segGen);
241
242
243
244
    // Declare type as noncopyable
245
    OffsetCurveBuilder(const OffsetCurveBuilder& other) = delete;
246
    OffsetCurveBuilder& operator=(const OffsetCurveBuilder& rhs) = delete;
247
};
248
249
} // namespace geos::operation::buffer
250
} // namespace geos::operation
251
} // namespace geos
252
253
#ifdef _MSC_VER
254
#pragma warning(pop)
255
#endif
256