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) 2005-2007 Refractions Research Inc.
8  * Copyright (C) 2001-2002 Vivid Solutions 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/BufferOp.java r378 (JTS-1.12)
18  *
19  **********************************************************************/
20 
21 #ifndef GEOS_OP_BUFFER_BUFFEROP_H
22 #define GEOS_OP_BUFFER_BUFFEROP_H
23 
24 #include <geos/export.h>
25 #include <geos/operation/buffer/BufferParameters.h> // for enum values
26 
27 #include <geos/util/TopologyException.h> // for composition
28 
29 #ifdef _MSC_VER
30 #pragma warning(push)
31 #pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
32 #endif
33 
34 // Forward declarations
35 namespace geos {
36 namespace geom {
37 class PrecisionModel;
38 class Geometry;
39 }
40 }
41 
42 namespace geos {
43 namespace operation { // geos.operation
44 namespace buffer { // geos.operation.buffer
45 
46 /**
47  * \class BufferOp
48  *
49  * \brief
50  * Computes the buffer of a geometry, for both positive and negative
51  * buffer distances.
52  *
53  * In GIS, the positive (or negative) buffer of a geometry is defined as
54  * the Minkowski sum (or difference) of the geometry
55  * with a circle with radius equal to the absolute value of the buffer
56  * distance.
57  * In the CAD/CAM world buffers are known as *offset curves*.
58  * In morphological analysis the operation of positive and negative buffering
59  * is referred to as *erosion* and *dilation*.
60  *
61  * The buffer operation always returns a polygonal result.
62  * The negative or zero-distance buffer of lines and points is always
63  * an empty Polygon.
64  *
65  * Since true buffer curves may contain circular arcs,
66  * computed buffer polygons can only be approximations to the true geometry.
67  * The user can control the accuracy of the curve approximation by specifying
68  * the number of linear segments with which to approximate a curve.
69  *
70  * The end cap style of a linear buffer may be specified.
71  * The following end cap styles are supported:
72  * - CAP_ROUND - the usual round end caps
73  * - CAP_BUTT - end caps are truncated flat at the line ends
74  * - CAP_SQUARE - end caps are squared off at the buffer distance
75  *   beyond the line ends
76  *
77  */
78 class GEOS_DLL BufferOp {
79 
80 
81 private:
82 
83     /** \brief
84      *  A number of digits of precision which leaves some computational "headroom"
85      *  for floating point operations.
86      *
87      *  This value should be less than the decimal precision of double-precision values (16).
88      */
89     static const int MAX_PRECISION_DIGITS = 12;
90 
91     /**
92      * Compute a reasonable scale factor to limit the precision of
93      * a given combination of Geometry and buffer distance.
94      * The scale factor is based on a heuristic.
95      *
96      * @param g the Geometry being buffered
97      *
98      * @param distance the buffer distance
99      *
100      * @param maxPrecisionDigits the mzx # of digits that should be
101      *        allowed by the precision determined by the
102      *        computed scale factor
103      *
104      * @return a scale factor that allows a reasonable amount of
105      *         precision for the buffer computation
106      */
107     static double precisionScaleFactor(const geom::Geometry* g,
108                                        double distance, int maxPrecisionDigits);
109 
110     const geom::Geometry* argGeom;
111 
112     util::TopologyException saveException;
113 
114     double distance;
115 
116     //int quadrantSegments;
117     //int endCapStyle;
118     BufferParameters bufParams;
119 
120     geom::Geometry* resultGeometry;
121 
122     void computeGeometry();
123 
124     void bufferOriginalPrecision();
125 
126     void bufferReducedPrecision(int precisionDigits);
127 
128     void bufferReducedPrecision();
129 
130     void bufferFixedPrecision(const geom::PrecisionModel& fixedPM);
131 
132 public:
133 
134     enum {
135         /// Specifies a round line buffer end cap style.
136         /// @deprecated use BufferParameters
137         CAP_ROUND = BufferParameters::CAP_ROUND,
138 
139         /// Specifies a butt (or flat) line buffer end cap style.
140         /// @deprecated use BufferParameters
141         CAP_BUTT = BufferParameters::CAP_FLAT,
142 
143         /// Specifies a square line buffer end cap style.
144         /// @deprecated use BufferParameters
145         CAP_SQUARE = BufferParameters::CAP_SQUARE
146     };
147 
148     /** \brief
149      * Computes the buffer for a geometry for a given buffer distance
150      * and accuracy of approximation.
151      *
152      * @param g the geometry to buffer
153      * @param distance the buffer distance
154      * @param quadrantSegments the number of segments used to
155      *        approximate a quarter circle
156      * @param endCapStyle line buffer end cap style (default: BufferParameters::CAP_ROUND)
157      * @return the buffer of the input geometry
158      *
159      */
160     static geom::Geometry* bufferOp(const geom::Geometry* g,
161                                     double distance,
162                                     int quadrantSegments =
163                                         BufferParameters::DEFAULT_QUADRANT_SEGMENTS,
164                                     int endCapStyle = BufferParameters::CAP_ROUND);
165 
166     /** \brief
167      * Initializes a buffer computation for the given geometry.
168      *
169      * @param g the geometry to buffer
170      */
BufferOp(const geom::Geometry * g)171     BufferOp(const geom::Geometry* g)
172         :
173         argGeom(g),
174         bufParams(),
175         resultGeometry(nullptr)
176     {
177     }
178 
179     /** \brief
180      * Initializes a buffer computation for the given geometry
181      * with the given set of parameters.
182      *
183      * @param g the geometry to buffer
184      * @param params the buffer parameters to use. This class will
185      *               copy it to private memory.
186      */
BufferOp(const geom::Geometry * g,const BufferParameters & params)187     BufferOp(const geom::Geometry* g, const BufferParameters& params)
188         :
189         argGeom(g),
190         bufParams(params),
191         resultGeometry(nullptr)
192     {
193     }
194 
195     /** \brief
196      * Specifies the end cap style of the generated buffer.
197      *
198      * The styles supported are CAP_ROUND, CAP_BUTT, and CAP_SQUARE.
199      * The default is CAP_ROUND.
200      *
201      * @param nEndCapStyle the end cap style to specify
202      */
203     inline void setEndCapStyle(int nEndCapStyle);
204 
205     /** \brief
206      * Sets the number of segments used to approximate a angle fillet
207      *
208      * @param nQuadrantSegments the number of segments in a fillet for a quadrant
209      */
210     inline void setQuadrantSegments(int nQuadrantSegments);
211 
212     /** \brief
213      * Sets whether the computed buffer should be single-sided.
214      *
215      * A single-sided buffer is constructed on only one side
216      * of each input line.
217      *
218      * The side used is determined by the sign of the buffer distance:
219      * - a positive distance indicates the left-hand side
220      * - a negative distance indicates the right-hand side
221      *
222      * The single-sided buffer of point geometries is
223      * the same as the regular buffer.
224      *
225      * The End Cap Style for single-sided buffers is
226      * always ignored,
227      * and forced to the equivalent of `CAP_FLAT`.
228      *
229      * @param isSingleSided `true` if a single-sided buffer
230      *                      should be constructed
231      */
232     inline void setSingleSided(bool isSingleSided);
233 
234     /** \brief
235      * Returns the buffer computed for a geometry for a given buffer
236      * distance.
237      *
238      * @param nDistance the buffer distance
239      * @return the buffer of the input geometry
240      */
241     geom::Geometry* getResultGeometry(double nDistance);
242 
243 };
244 
245 // BufferOp inlines
246 void
setQuadrantSegments(int q)247 BufferOp::setQuadrantSegments(int q)
248 {
249     bufParams.setQuadrantSegments(q);
250 }
251 
252 void
setEndCapStyle(int s)253 BufferOp::setEndCapStyle(int s)
254 {
255     bufParams.setEndCapStyle((BufferParameters::EndCapStyle)s);
256 }
257 
258 void
setSingleSided(bool isSingleSided)259 BufferOp::setSingleSided(bool isSingleSided)
260 {
261     bufParams.setSingleSided(isSingleSided);
262 }
263 
264 } // namespace geos::operation::buffer
265 } // namespace geos::operation
266 } // namespace geos
267 
268 #ifdef _MSC_VER
269 #pragma warning(pop)
270 #endif
271 
272 #endif // ndef GEOS_OP_BUFFER_BUFFEROP_H
273 
274