/src/geos/include/geos/geom/PrecisionModel.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2011 Sandro Santilli <strk@kbt.io> |
7 | | * Copyright (C) 2006 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: geom/PrecisionModel.java r378 (JTS-1.12) |
17 | | * |
18 | | **********************************************************************/ |
19 | | |
20 | | #pragma once |
21 | | |
22 | | #include <geos/geom/Coordinate.h> |
23 | | #include <geos/export.h> |
24 | | |
25 | | #include <cassert> |
26 | | #include <string> |
27 | | |
28 | | // Forward declarations |
29 | | namespace geos { |
30 | | namespace io { |
31 | | } |
32 | | namespace geom { |
33 | | class Coordinate; |
34 | | } |
35 | | } |
36 | | |
37 | | namespace geos { |
38 | | namespace geom { // geos::geom |
39 | | |
40 | | /** |
41 | | * \class PrecisionModel geom.h geos.h |
42 | | * |
43 | | * \brief Specifies the precision model of the Coordinate in a Geometry. |
44 | | * |
45 | | * In other words, specifies the grid of allowable points for a <code>Geometry</code>. |
46 | | * A precision model may be <b>floating</b> (PrecisionModel::Type::FLOATING or |
47 | | * PrecisionModel::Type::FLOATING_SINGLE), in which case normal floating-point value semantics apply. |
48 | | * |
49 | | * For a PrecisionModel::Type::FIXED precision model the |
50 | | * makePrecise(geom::Coordinate) method allows rounding a coordinate to |
51 | | * a "precise" value; that is, one whose precision is known exactly. |
52 | | * |
53 | | * Coordinates are assumed to be precise in geometries. |
54 | | * That is, the coordinates are assumed to be rounded to the |
55 | | * precision model given for the geometry. |
56 | | * All internal operations |
57 | | * assume that coordinates are rounded to the precision model. |
58 | | * Constructive methods (such as boolean operations) always round computed |
59 | | * coordinates to the appropriate precision model. |
60 | | * |
61 | | * Three types of precision model are supported: |
62 | | * - FLOATING - represents full double precision floating point. |
63 | | * This is the default precision model used in JTS |
64 | | * - FLOATING_SINGLE - represents single precision floating point. |
65 | | * - FIXED - represents a model with a fixed number of decimal places. |
66 | | * A Fixed Precision Model is specified by a scale factor. |
67 | | * The scale factor specifies the grid which numbers are rounded to. |
68 | | * Input coordinates are mapped to fixed coordinates according to the |
69 | | * following equations: |
70 | | * - jtsPt.x = round( inputPt.x * scale ) / scale |
71 | | * - jtsPt.y = round( inputPt.y * scale ) / scale |
72 | | * |
73 | | * For example, to specify 3 decimal places of precision, use a scale factor |
74 | | * of 1000. To specify -3 decimal places of precision (i.e. rounding to |
75 | | * the nearest 1000), use a scale factor of 0.001. |
76 | | * |
77 | | * It is also supported to specify a precise grid size |
78 | | * by providing it as a negative scale factor. |
79 | | * For example, to specify rounding to the nearest 1000 use a scale factor of -1000. |
80 | | * |
81 | | * Coordinates are represented internally as Java double-precision values. |
82 | | * Java uses the IEEE-394 floating point standard, which |
83 | | * provides 53 bits of precision. (Thus the maximum precisely representable |
84 | | * integer is 9,007,199,254,740,992). |
85 | | * |
86 | | */ |
87 | | class GEOS_DLL PrecisionModel { |
88 | | |
89 | | public: |
90 | | |
91 | | /// The types of Precision Model which GEOS supports. |
92 | | typedef enum { |
93 | | |
94 | | /** |
95 | | * Fixed Precision indicates that coordinates have a fixed |
96 | | * number of decimal places. |
97 | | * The number of decimal places is determined by the log10 |
98 | | * of the scale factor. |
99 | | */ |
100 | | FIXED, |
101 | | |
102 | | /** |
103 | | * Floating precision corresponds to the standard Java |
104 | | * double-precision floating-point representation, which is |
105 | | * based on the IEEE-754 standard |
106 | | */ |
107 | | FLOATING, |
108 | | |
109 | | /** |
110 | | * Floating single precision corresponds to the standard Java |
111 | | * single-precision floating-point representation, which is |
112 | | * based on the IEEE-754 standard |
113 | | */ |
114 | | FLOATING_SINGLE |
115 | | |
116 | | } Type; |
117 | | |
118 | | /// Creates a PrecisionModel with a default precision of FLOATING. |
119 | | PrecisionModel(void); |
120 | | |
121 | | /// Creates a PrecisionModel specifying an explicit precision model type. |
122 | | /// |
123 | | /// If the model type is FIXED the scale factor will default to 1. |
124 | | /// |
125 | | /// @param nModelType the type of the precision model |
126 | | /// |
127 | | PrecisionModel(Type nModelType); |
128 | | |
129 | | /** \brief |
130 | | * Creates a <code>PrecisionModel</code> with Fixed precision. |
131 | | * |
132 | | * Fixed-precision coordinates are represented as precise internal |
133 | | * coordinates, which are rounded to the grid defined by the |
134 | | * scale factor. |
135 | | * |
136 | | * @param newScale amount by which to multiply a coordinate after |
137 | | * subtracting the offset, to obtain a precise coordinate |
138 | | * @param newOffsetX not used. |
139 | | * @param newOffsetY not used. |
140 | | * |
141 | | * @deprecated offsets are no longer supported, since internal |
142 | | * representation is rounded floating point |
143 | | */ |
144 | | PrecisionModel(double newScale, double newOffsetX, double newOffsetY); |
145 | | |
146 | | /** |
147 | | * \brief |
148 | | * Creates a PrecisionModel with Fixed precision. |
149 | | * |
150 | | * Fixed-precision coordinates are represented as precise |
151 | | * internal coordinates which are rounded to the grid defined |
152 | | * by the scale factor. |
153 | | * The provided scale may be negative, to specify an exact grid size. |
154 | | * The scale is then computed as the reciprocal. |
155 | | * |
156 | | * @param newScale amount by which to multiply a coordinate |
157 | | * after subtracting the offset, to obtain a precise coordinate. Must be non-zero. |
158 | | */ |
159 | | PrecisionModel(double newScale); |
160 | | |
161 | | /// The maximum precise value representable in a double. |
162 | | /// |
163 | | /// Since IEE754 double-precision numbers allow 53 bits of mantissa, |
164 | | /// the value is equal to 2^53 - 1. |
165 | | /// This provides <i>almost</i> 16 decimal digits of precision. |
166 | | //// |
167 | | static const double maximumPreciseValue; |
168 | | |
169 | | /** \brief |
170 | | * Rounds a numeric value to the PrecisionModel grid. |
171 | | * |
172 | | * Asymmetric Arithmetic Rounding is used, to provide |
173 | | * uniform rounding behaviour no matter where the number is |
174 | | * on the number line. |
175 | | * |
176 | | * <b>Note:</b> Java's <code>Math#rint</code> uses the "Banker's Rounding" algorithm, |
177 | | * which is not suitable for precision operations elsewhere in JTS. |
178 | | */ |
179 | | double makePrecise(double val) const; |
180 | | |
181 | | /// Rounds the given Coordinate to the PrecisionModel grid. |
182 | | void makePrecise(CoordinateXY& coord) const |
183 | 50.3M | { |
184 | | // optimization for full precision |
185 | 50.3M | if(modelType == FLOATING) { |
186 | 37.2M | return; |
187 | 37.2M | } |
188 | | |
189 | 13.0M | coord.x = makePrecise(coord.x); |
190 | 13.0M | coord.y = makePrecise(coord.y); |
191 | 13.0M | }; |
192 | | |
193 | | void makePrecise(CoordinateXY* coord) const |
194 | 0 | { |
195 | 0 | assert(coord); |
196 | 0 | return makePrecise(*coord); |
197 | 0 | }; |
198 | | |
199 | | /// Tests whether the precision model supports floating point |
200 | | /// |
201 | | /// @return <code>true</code> if the precision model supports |
202 | | /// floating point |
203 | | /// |
204 | | bool isFloating() const; |
205 | | |
206 | | /// \brief |
207 | | /// Returns the maximum number of significant digits provided by |
208 | | /// this precision model. |
209 | | /// |
210 | | /// Intended for use by routines which need to print out precise |
211 | | /// values. |
212 | | /// |
213 | | /// @return the maximum number of decimal places provided by this |
214 | | /// precision model |
215 | | /// |
216 | | int getMaximumSignificantDigits() const; |
217 | | |
218 | | /// Gets the type of this PrecisionModel |
219 | | /// |
220 | | /// @return the type of this PrecisionModel |
221 | | /// |
222 | | Type getType() const |
223 | 0 | { |
224 | 0 | return modelType; |
225 | 0 | }; |
226 | | |
227 | | /// Returns the multiplying factor used to obtain a precise coordinate. |
228 | | double getScale() const |
229 | 18.3k | { |
230 | 18.3k | assert(!(scale < 0)); |
231 | 18.3k | return scale; |
232 | 18.3k | }; |
233 | | |
234 | | /** |
235 | | * Computes the grid size for a fixed precision model. |
236 | | * This is equal to the reciprocal of the scale factor. |
237 | | * If the grid size has been set explicitly (via a negative scale factor) |
238 | | * it will be returned. |
239 | | * |
240 | | * @return the grid size at a fixed precision scale. |
241 | | */ |
242 | | double getGridSize() const |
243 | 0 | { |
244 | 0 | if (isFloating()) |
245 | 0 | return DoubleNotANumber; |
246 | 0 |
|
247 | 0 | if (gridSize != 0) |
248 | 0 | return gridSize; |
249 | 0 |
|
250 | 0 | return 1.0 / scale; |
251 | 0 | }; |
252 | | |
253 | | /// Returns the x-offset used to obtain a precise coordinate. |
254 | | /// |
255 | | /// @return the amount by which to subtract the x-coordinate before |
256 | | /// multiplying by the scale |
257 | | /// @deprecated Offsets are no longer used |
258 | | /// |
259 | | double getOffsetX() const; |
260 | | |
261 | | /// Returns the y-offset used to obtain a precise coordinate. |
262 | | /// |
263 | | /// @return the amount by which to subtract the y-coordinate before |
264 | | /// multiplying by the scale |
265 | | /// @deprecated Offsets are no longer used |
266 | | /// |
267 | | double getOffsetY() const; |
268 | | |
269 | | /* |
270 | | * Sets ´internal` to the precise representation of `external`. |
271 | | * |
272 | | * @param external the original coordinate |
273 | | * @param internal the coordinate whose values will be changed to the |
274 | | * precise representation of <code>external</code> |
275 | | * @deprecated use makePrecise instead |
276 | | */ |
277 | | //void toInternal(const Coordinate& external, Coordinate* internal) const; |
278 | | |
279 | | /* |
280 | | * Returns the precise representation of <code>external</code>. |
281 | | * |
282 | | *@param external the original coordinate |
283 | | *@return |
284 | | * the coordinate whose values will be changed to the precise |
285 | | * representation of <code>external</code> |
286 | | * @deprecated use makePrecise instead |
287 | | */ |
288 | | //Coordinate* toInternal(const Coordinate& external) const; |
289 | | |
290 | | /* |
291 | | * Returns the external representation of <code>internal</code>. |
292 | | * |
293 | | *@param internal the original coordinate |
294 | | *@return the coordinate whose values will be changed to the |
295 | | * external representation of <code>internal</code> |
296 | | * @deprecated no longer needed, since internal representation is same as external representation |
297 | | */ |
298 | | //Coordinate* toExternal(const Coordinate& internal) const; |
299 | | |
300 | | /* |
301 | | * Sets <code>external</code> to the external representation of |
302 | | * <code>internal</code>. |
303 | | * |
304 | | * @param internal the original coordinate |
305 | | * @param external |
306 | | * the coordinate whose values will be changed to the |
307 | | * external representation of <code>internal</code> |
308 | | * @deprecated no longer needed, since internal representation is same as external representation |
309 | | */ |
310 | | //void toExternal(const Coordinate& internal, Coordinate* external) const; |
311 | | |
312 | | std::string toString() const; |
313 | | |
314 | | /// \brief |
315 | | /// Compares this PrecisionModel object with the specified object |
316 | | /// for order. |
317 | | /// |
318 | | /// A PrecisionModel is greater than another if it provides greater |
319 | | /// precision. |
320 | | /// The comparison is based on the value returned by the |
321 | | /// getMaximumSignificantDigits method. |
322 | | /// This comparison is not strictly accurate when comparing floating |
323 | | /// precision models to fixed models; |
324 | | /// however, it is correct when both models are either floating or |
325 | | /// fixed. |
326 | | /// |
327 | | /// @param other the PrecisionModel with which this PrecisionModel |
328 | | /// is being compared |
329 | | /// @return a negative integer, zero, or a positive integer as this |
330 | | /// PrecisionModel is less than, equal to, or greater than the |
331 | | /// specified PrecisionModel. |
332 | | /// |
333 | | int compareTo(const PrecisionModel* other) const; |
334 | | |
335 | | private: |
336 | | |
337 | | /** \brief |
338 | | * Sets the multiplying factor used to obtain a precise coordinate. |
339 | | * |
340 | | * This method is private because PrecisionModel is intended to |
341 | | * be an immutable (value) type. |
342 | | * |
343 | | */ |
344 | | void setScale(double newScale); |
345 | | // throw IllegalArgumentException |
346 | | |
347 | | /** \brief |
348 | | * Snaps a value to nearest integer, if within tolerance. |
349 | | */ |
350 | | static double snapToInt(double val, double tolerance); |
351 | | |
352 | | Type modelType; |
353 | | |
354 | | /** |
355 | | * The scale factor which determines the number of decimal places in fixed precision. |
356 | | */ |
357 | | double scale; |
358 | | |
359 | | /** |
360 | | * If non-zero, the precise grid size specified. |
361 | | * In this case, the scale is also valid and is computed from the grid size. |
362 | | * If zero, the scale is used to compute the grid size where needed. |
363 | | */ |
364 | | double gridSize = 0.0; |
365 | | |
366 | | }; |
367 | | |
368 | | // Equality operator for PrecisionModel, deprecate it ? |
369 | | //inline bool operator==(const PrecisionModel& a, const PrecisionModel& b); |
370 | | |
371 | | } // namespace geos::geom |
372 | | } // namespace geos |