Coverage Report

Created: 2025-07-17 06:34

/src/geos/include/geos/operation/buffer/BufferBuilder.h
Line
Count
Source (jump to first uncovered line)
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) 2008-2010 Safe Software Inc.
8
 * Copyright (C) 2006-2007 Refractions Research Inc.
9
 *
10
 * This is free software; you can redistribute and/or modify it under
11
 * the terms of the GNU Lesser General Public Licence as published
12
 * by the Free Software Foundation.
13
 * See the COPYING file for more information.
14
 *
15
 **********************************************************************
16
 *
17
 * Last port: operation/buffer/BufferBuilder.java 149b38907 (JTS-1.12)
18
 *
19
 **********************************************************************/
20
21
#pragma once
22
23
#include <geos/export.h>
24
25
#include <vector>
26
27
#include <geos/operation/buffer/BufferOp.h> // for inlines (BufferOp enums)
28
#include <geos/operation/buffer/OffsetCurveBuilder.h> // for inline (OffsetCurveBuilder enums)
29
#include <geos/geomgraph/EdgeList.h> // for composition
30
31
#ifdef _MSC_VER
32
#pragma warning(push)
33
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
34
#endif
35
36
// Forward declarations
37
namespace geos {
38
namespace geom {
39
class PrecisionModel;
40
class Geometry;
41
class GeometryFactory;
42
}
43
namespace algorithm {
44
class LineIntersector;
45
}
46
namespace noding {
47
class Noder;
48
class SegmentString;
49
class IntersectionAdder;
50
}
51
namespace geomgraph {
52
class Edge;
53
class Label;
54
class PlanarGraph;
55
}
56
namespace operation {
57
namespace buffer {
58
class BufferSubgraph;
59
class PolygonBuilder;
60
}
61
62
}
63
}
64
65
namespace geos {
66
namespace operation { // geos.operation
67
namespace buffer { // geos.operation.buffer
68
69
/**
70
 *
71
 * \brief
72
 * Builds the buffer geometry for a given input geometry and precision model.
73
 *
74
 * Allows setting the level of approximation for circular arcs,
75
 * and the precision model in which to carry out the computation.
76
 *
77
 * When computing buffers in floating point double-precision
78
 * it can happen that the process of iterated noding can fail to converge
79
 * (terminate).
80
 *
81
 * In this case a TopologyException will be thrown.
82
 * Retrying the computation in a fixed precision
83
 * can produce more robust results.
84
 *
85
 */
86
class GEOS_DLL BufferBuilder {
87
88
public:
89
    /**
90
     * Creates a new BufferBuilder
91
     *
92
     * @param nBufParams buffer parameters, this object will
93
     *                   keep a reference to the passed parameters
94
     *                   so caller must make sure the object is
95
     *                   kept alive for the whole lifetime of
96
     *                   the buffer builder.
97
     */
98
    BufferBuilder(const BufferParameters& nBufParams)
99
        :
100
0
        bufParams(nBufParams),
101
0
        workingPrecisionModel(nullptr),
102
0
        li(nullptr),
103
0
        intersectionAdder(nullptr),
104
0
        workingNoder(nullptr),
105
0
        geomFact(nullptr),
106
0
        edgeList(),
107
0
        isInvertOrientation(false)
108
0
    {}
109
110
    ~BufferBuilder();
111
112
113
    /**
114
     * Sets the precision model to use during the curve computation
115
     * and noding,
116
     * if it is different to the precision model of the Geometry.
117
     * If the precision model is less than the precision of the
118
     * Geometry precision model,
119
     * the Geometry must have previously been rounded to that precision.
120
     *
121
     * @param pm the precision model to use
122
     */
123
    void
124
    setWorkingPrecisionModel(const geom::PrecisionModel* pm)
125
0
    {
126
0
        workingPrecisionModel = pm;
127
0
    }
128
129
    /**
130
     * Sets the {@link noding::Noder} to use during noding.
131
     * This allows choosing fast but non-robust noding, or slower
132
     * but robust noding.
133
     *
134
     * @param newNoder the noder to use
135
     */
136
    void
137
    setNoder(noding::Noder* newNoder)
138
0
    {
139
0
        workingNoder = newNoder;
140
0
    }
141
142
    /**
143
    * Sets whether the offset curve is generated
144
    * using the inverted orientation of input rings.
145
    * This allows generating a buffer(0) polygon from the smaller lobes
146
    * of self-crossing rings.
147
    *
148
    * @param p_isInvertOrientation true if input ring orientation should be inverted
149
    */
150
    void
151
    setInvertOrientation(bool p_isInvertOrientation)
152
0
    {
153
0
        isInvertOrientation = p_isInvertOrientation;
154
0
    }
155
156
157
    std::unique_ptr<geom::Geometry> buffer(const geom::Geometry* g, double distance);
158
159
    /**
160
     * Generates offset curve for linear geometry.
161
     *
162
     * @param g non-areal geometry object
163
     * @param distance width of offset
164
     * @param leftSide controls on which side of the input geometry
165
     *        offset curve is generated.
166
     *
167
     * @note For left-side offset curve, the offset will be at the left side
168
     *       of the input line and retain the same direction.
169
     *       For right-side offset curve, it'll be at the right side
170
     *       and in the opposite direction.
171
     *
172
     * @note BufferParameters::setSingleSided parameter, which is specific to
173
     *       areal geometries only, is ignored by this routine.
174
     *
175
     * @note Not in JTS: this is a GEOS extension
176
     */
177
    std::unique_ptr<geom::Geometry> bufferLineSingleSided(
178
        const geom::Geometry* g,
179
        double distance, bool leftSide);
180
181
private:
182
183
    /**
184
     * Compute the change in depth as an edge is crossed from R to L
185
     */
186
    static int depthDelta(const geomgraph::Label& label);
187
188
    const BufferParameters& bufParams;
189
190
    const geom::PrecisionModel* workingPrecisionModel;
191
192
    algorithm::LineIntersector* li;
193
194
    noding::IntersectionAdder* intersectionAdder;
195
196
    noding::Noder* workingNoder;
197
198
    const geom::GeometryFactory* geomFact;
199
200
    geomgraph::EdgeList edgeList;
201
202
    std::vector<geomgraph::Label*> newLabels;
203
204
    bool isInvertOrientation;
205
206
    void computeNodedEdges(std::vector<noding::SegmentString*>& bufSegStr,
207
                           const geom::PrecisionModel* precisionModel);
208
    // throw(GEOSException);
209
210
    /**
211
     * Inserted edges are checked to see if an identical edge already
212
     * exists.
213
     * If so, the edge is not inserted, but its label is merged
214
     * with the existing edge.
215
     *
216
     * The function takes responsibility of releasing the Edge parameter
217
     * memory when appropriate.
218
     */
219
    void insertUniqueEdge(geomgraph::Edge* e);
220
221
    void createSubgraphs(geomgraph::PlanarGraph* graph,
222
                         std::vector<BufferSubgraph*>& list);
223
224
    /**
225
     * Completes the building of the input subgraphs by
226
     * depth-labelling them,
227
     * and adds them to the PolygonBuilder.
228
     * The subgraph list must be sorted in rightmost-coordinate order.
229
     *
230
     * @param subgraphList the subgraphs to build
231
     * @param polyBuilder the PolygonBuilder which will build
232
     *        the final polygons
233
     */
234
    void buildSubgraphs(const std::vector<BufferSubgraph*>& subgraphList,
235
                        PolygonBuilder& polyBuilder);
236
237
    /// \brief
238
    /// Return the externally-set noding::Noder OR a newly created
239
    /// one using the given precisionModel.
240
    ///
241
    /// NOTE: if an externally-set noding::Noder is available no
242
    /// check is performed to ensure it will use the
243
    /// given PrecisionModel
244
    ///
245
    noding::Noder* getNoder(const geom::PrecisionModel* precisionModel);
246
247
248
    /**
249
     * Gets the standard result for an empty buffer.
250
     * Since buffer always returns a polygonal result,
251
     * this is chosen to be an empty polygon.
252
     *
253
     * @return the empty result geometry, transferring ownership to caller.
254
     */
255
    std::unique_ptr<geom::Geometry> createEmptyResultGeometry() const;
256
257
    // Declare type as noncopyable
258
    BufferBuilder(const BufferBuilder& other) = delete;
259
    BufferBuilder& operator=(const BufferBuilder& rhs) = delete;
260
};
261
262
} // namespace geos::operation::buffer
263
} // namespace geos::operation
264
} // namespace geos
265
266
#ifdef _MSC_VER
267
#pragma warning(pop)
268
#endif
269