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