375 lines
12 KiB
C++
375 lines
12 KiB
C++
/**********************************************************************
|
||
*
|
||
* GEOS - Geometry Engine Open Source
|
||
* http://geos.osgeo.org
|
||
*
|
||
* Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
|
||
* Copyright (C) 2006 Refractions Research Inc.
|
||
*
|
||
* This is free software; you can redistribute and/or modify it under
|
||
* the terms of the GNU Lesser General Public Licence as published
|
||
* by the Free Software Foundation.
|
||
* See the COPYING file for more information.
|
||
*
|
||
**********************************************************************
|
||
*
|
||
* Last port: geom/PrecisionModel.java r378 (JTS-1.12)
|
||
*
|
||
**********************************************************************/
|
||
|
||
#pragma once
|
||
|
||
#include <geos/geom/Coordinate.h>
|
||
#include <geos/export.h>
|
||
|
||
#include <cassert>
|
||
#include <string>
|
||
|
||
// Forward declarations
|
||
namespace geos {
|
||
namespace io {
|
||
class Unload;
|
||
}
|
||
namespace geom {
|
||
class Coordinate;
|
||
}
|
||
}
|
||
|
||
namespace geos {
|
||
namespace geom { // geos::geom
|
||
|
||
/**
|
||
* \class PrecisionModel geom.h geos.h
|
||
*
|
||
* \brief Specifies the precision model of the Coordinate in a Geometry.
|
||
*
|
||
* In other words, specifies the grid of allowable points for a <code>Geometry</code>.
|
||
* A precision model may be <b>floating</b> (PrecisionModel::Type::FLOATING or
|
||
* PrecisionModel::Type::FLOATING_SINGLE), in which case normal floating-point value semantics apply.
|
||
*
|
||
* For a PrecisionModel::Type::FIXED precision model the
|
||
* makePrecise(geom::Coordinate) method allows rounding a coordinate to
|
||
* a "precise" value; that is, one whose precision is known exactly.
|
||
*
|
||
* Coordinates are assumed to be precise in geometries.
|
||
* That is, the coordinates are assumed to be rounded to the
|
||
* precision model given for the geometry.
|
||
* All internal operations
|
||
* assume that coordinates are rounded to the precision model.
|
||
* Constructive methods (such as boolean operations) always round computed
|
||
* coordinates to the appropriate precision model.
|
||
*
|
||
* Three types of precision model are supported:
|
||
* - FLOATING - represents full double precision floating point.
|
||
* This is the default precision model used in JTS
|
||
* - FLOATING_SINGLE - represents single precision floating point.
|
||
* - FIXED - represents a model with a fixed number of decimal places.
|
||
* A Fixed Precision Model is specified by a scale factor.
|
||
* The scale factor specifies the grid which numbers are rounded to.
|
||
* Input coordinates are mapped to fixed coordinates according to the
|
||
* following equations:
|
||
* - jtsPt.x = round( inputPt.x * scale ) / scale
|
||
* - jtsPt.y = round( inputPt.y * scale ) / scale
|
||
*
|
||
* For example, to specify 3 decimal places of precision, use a scale factor
|
||
* of 1000. To specify -3 decimal places of precision (i.e. rounding to
|
||
* the nearest 1000), use a scale factor of 0.001.
|
||
*
|
||
* It is also supported to specify a precise grid size
|
||
* by providing it as a negative scale factor.
|
||
* For example, to specify rounding to the nearest 1000 use a scale factor of -1000.
|
||
*
|
||
* Coordinates are represented internally as Java double-precision values.
|
||
* Java uses the IEEE-394 floating point standard, which
|
||
* provides 53 bits of precision. (Thus the maximum precisely representable
|
||
* integer is 9,007,199,254,740,992).
|
||
*
|
||
*/
|
||
class GEOS_DLL PrecisionModel {
|
||
friend class io::Unload;
|
||
|
||
public:
|
||
|
||
/// The types of Precision Model which GEOS supports.
|
||
typedef enum {
|
||
|
||
/**
|
||
* Fixed Precision indicates that coordinates have a fixed
|
||
* number of decimal places.
|
||
* The number of decimal places is determined by the log10
|
||
* of the scale factor.
|
||
*/
|
||
FIXED,
|
||
|
||
/**
|
||
* Floating precision corresponds to the standard Java
|
||
* double-precision floating-point representation, which is
|
||
* based on the IEEE-754 standard
|
||
*/
|
||
FLOATING,
|
||
|
||
/**
|
||
* Floating single precision corresponds to the standard Java
|
||
* single-precision floating-point representation, which is
|
||
* based on the IEEE-754 standard
|
||
*/
|
||
FLOATING_SINGLE
|
||
|
||
} Type;
|
||
|
||
/// Creates a PrecisionModel with a default precision of FLOATING.
|
||
PrecisionModel(void);
|
||
|
||
/// Creates a PrecisionModel specifying an explicit precision model type.
|
||
///
|
||
/// If the model type is FIXED the scale factor will default to 1.
|
||
///
|
||
/// @param nModelType the type of the precision model
|
||
///
|
||
PrecisionModel(Type nModelType);
|
||
|
||
/** \brief
|
||
* Creates a <code>PrecisionModel</code> with Fixed precision.
|
||
*
|
||
* Fixed-precision coordinates are represented as precise internal
|
||
* coordinates, which are rounded to the grid defined by the
|
||
* scale factor.
|
||
*
|
||
* @param newScale amount by which to multiply a coordinate after
|
||
* subtracting the offset, to obtain a precise coordinate
|
||
* @param newOffsetX not used.
|
||
* @param newOffsetY not used.
|
||
*
|
||
* @deprecated offsets are no longer supported, since internal
|
||
* representation is rounded floating point
|
||
*/
|
||
PrecisionModel(double newScale, double newOffsetX, double newOffsetY);
|
||
|
||
/**
|
||
* \brief
|
||
* Creates a PrecisionModel with Fixed precision.
|
||
*
|
||
* Fixed-precision coordinates are represented as precise
|
||
* internal coordinates which are rounded to the grid defined
|
||
* by the scale factor.
|
||
* The provided scale may be negative, to specify an exact grid size.
|
||
* The scale is then computed as the reciprocal.
|
||
*
|
||
* @param newScale amount by which to multiply a coordinate
|
||
* after subtracting the offset, to obtain a precise coordinate. Must be non-zero.
|
||
*/
|
||
PrecisionModel(double newScale);
|
||
|
||
/// The maximum precise value representable in a double.
|
||
///
|
||
/// Since IEE754 double-precision numbers allow 53 bits of mantissa,
|
||
/// the value is equal to 2^53 - 1.
|
||
/// This provides <i>almost</i> 16 decimal digits of precision.
|
||
////
|
||
static const double maximumPreciseValue;
|
||
|
||
/** \brief
|
||
* Rounds a numeric value to the PrecisionModel grid.
|
||
*
|
||
* Asymmetric Arithmetic Rounding is used, to provide
|
||
* uniform rounding behaviour no matter where the number is
|
||
* on the number line.
|
||
*
|
||
* <b>Note:</b> Java's <code>Math#rint</code> uses the "Banker's Rounding" algorithm,
|
||
* which is not suitable for precision operations elsewhere in JTS.
|
||
*/
|
||
double makePrecise(double val) const;
|
||
|
||
/// Rounds the given Coordinate to the PrecisionModel grid.
|
||
void makePrecise(CoordinateXY& coord) const
|
||
{
|
||
// optimization for full precision
|
||
if(modelType == FLOATING) {
|
||
return;
|
||
}
|
||
|
||
coord.x = makePrecise(coord.x);
|
||
coord.y = makePrecise(coord.y);
|
||
};
|
||
|
||
void makePrecise(CoordinateXY* coord) const
|
||
{
|
||
assert(coord);
|
||
return makePrecise(*coord);
|
||
};
|
||
|
||
/// Tests whether the precision model supports floating point
|
||
///
|
||
/// @return <code>true</code> if the precision model supports
|
||
/// floating point
|
||
///
|
||
bool isFloating() const;
|
||
|
||
/// \brief
|
||
/// Returns the maximum number of significant digits provided by
|
||
/// this precision model.
|
||
///
|
||
/// Intended for use by routines which need to print out precise
|
||
/// values.
|
||
///
|
||
/// @return the maximum number of decimal places provided by this
|
||
/// precision model
|
||
///
|
||
int getMaximumSignificantDigits() const;
|
||
|
||
/// Gets the type of this PrecisionModel
|
||
///
|
||
/// @return the type of this PrecisionModel
|
||
///
|
||
Type getType() const
|
||
{
|
||
return modelType;
|
||
};
|
||
|
||
/// Returns the multiplying factor used to obtain a precise coordinate.
|
||
double getScale() const
|
||
{
|
||
assert(!(scale < 0));
|
||
return scale;
|
||
};
|
||
|
||
/**
|
||
* Computes the grid size for a fixed precision model.
|
||
* This is equal to the reciprocal of the scale factor.
|
||
* If the grid size has been set explicitly (via a negative scale factor)
|
||
* it will be returned.
|
||
*
|
||
* @return the grid size at a fixed precision scale.
|
||
*/
|
||
double getGridSize() const
|
||
{
|
||
if (isFloating())
|
||
return DoubleNotANumber;
|
||
|
||
if (gridSize != 0)
|
||
return gridSize;
|
||
|
||
return 1.0 / scale;
|
||
};
|
||
|
||
/// Returns the x-offset used to obtain a precise coordinate.
|
||
///
|
||
/// @return the amount by which to subtract the x-coordinate before
|
||
/// multiplying by the scale
|
||
/// @deprecated Offsets are no longer used
|
||
///
|
||
double getOffsetX() const;
|
||
|
||
/// Returns the y-offset used to obtain a precise coordinate.
|
||
///
|
||
/// @return the amount by which to subtract the y-coordinate before
|
||
/// multiplying by the scale
|
||
/// @deprecated Offsets are no longer used
|
||
///
|
||
double getOffsetY() const;
|
||
|
||
/*
|
||
* Sets ´internal` to the precise representation of `external`.
|
||
*
|
||
* @param external the original coordinate
|
||
* @param internal the coordinate whose values will be changed to the
|
||
* precise representation of <code>external</code>
|
||
* @deprecated use makePrecise instead
|
||
*/
|
||
//void toInternal(const Coordinate& external, Coordinate* internal) const;
|
||
|
||
/*
|
||
* Returns the precise representation of <code>external</code>.
|
||
*
|
||
*@param external the original coordinate
|
||
*@return
|
||
* the coordinate whose values will be changed to the precise
|
||
* representation of <code>external</code>
|
||
* @deprecated use makePrecise instead
|
||
*/
|
||
//Coordinate* toInternal(const Coordinate& external) const;
|
||
|
||
/*
|
||
* Returns the external representation of <code>internal</code>.
|
||
*
|
||
*@param internal the original coordinate
|
||
*@return the coordinate whose values will be changed to the
|
||
* external representation of <code>internal</code>
|
||
* @deprecated no longer needed, since internal representation is same as external representation
|
||
*/
|
||
//Coordinate* toExternal(const Coordinate& internal) const;
|
||
|
||
/*
|
||
* Sets <code>external</code> to the external representation of
|
||
* <code>internal</code>.
|
||
*
|
||
* @param internal the original coordinate
|
||
* @param external
|
||
* the coordinate whose values will be changed to the
|
||
* external representation of <code>internal</code>
|
||
* @deprecated no longer needed, since internal representation is same as external representation
|
||
*/
|
||
//void toExternal(const Coordinate& internal, Coordinate* external) const;
|
||
|
||
std::string toString() const;
|
||
|
||
/// \brief
|
||
/// Compares this PrecisionModel object with the specified object
|
||
/// for order.
|
||
///
|
||
/// A PrecisionModel is greater than another if it provides greater
|
||
/// precision.
|
||
/// The comparison is based on the value returned by the
|
||
/// getMaximumSignificantDigits method.
|
||
/// This comparison is not strictly accurate when comparing floating
|
||
/// precision models to fixed models;
|
||
/// however, it is correct when both models are either floating or
|
||
/// fixed.
|
||
///
|
||
/// @param other the PrecisionModel with which this PrecisionModel
|
||
/// is being compared
|
||
/// @return a negative integer, zero, or a positive integer as this
|
||
/// PrecisionModel is less than, equal to, or greater than the
|
||
/// specified PrecisionModel.
|
||
///
|
||
int compareTo(const PrecisionModel* other) const;
|
||
|
||
private:
|
||
|
||
/** \brief
|
||
* Sets the multiplying factor used to obtain a precise coordinate.
|
||
*
|
||
* This method is private because PrecisionModel is intended to
|
||
* be an immutable (value) type.
|
||
*
|
||
*/
|
||
void setScale(double newScale);
|
||
// throw IllegalArgumentException
|
||
|
||
/** \brief
|
||
* Snaps a value to nearest integer, if within tolerance.
|
||
*/
|
||
static double snapToInt(double val, double tolerance);
|
||
|
||
Type modelType;
|
||
|
||
/**
|
||
* The scale factor which determines the number of decimal places in fixed precision.
|
||
*/
|
||
double scale;
|
||
|
||
/**
|
||
* If non-zero, the precise grid size specified.
|
||
* In this case, the scale is also valid and is computed from the grid size.
|
||
* If zero, the scale is used to compute the grid size where needed.
|
||
*/
|
||
double gridSize = 0.0;
|
||
|
||
};
|
||
|
||
// Equality operator for PrecisionModel, deprecate it ?
|
||
//inline bool operator==(const PrecisionModel& a, const PrecisionModel& b);
|
||
|
||
} // namespace geos::geom
|
||
} // namespace geos
|