precisionmodel.cpp
来自「一个很好的vc底层代码」· C++ 代码 · 共 406 行
CPP
406 行
/********************************************************************** * $Id: PrecisionModel.cpp,v 1.28.2.1 2005/05/23 18:41:51 strk Exp $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2001-2002 Vivid Solutions 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. * ********************************************************************** * $Log: PrecisionModel.cpp,v $ * Revision 1.28.2.1 2005/05/23 18:41:51 strk * Replaced sprintf uses with ostringstream * * Revision 1.28 2004/07/21 09:55:24 strk * CoordinateSequence::atLeastNCoordinatesOrNothing definition fix. * Documentation fixes. * * Revision 1.27 2004/07/12 15:42:03 strk * Fixed maximumPreciseValue scope * * Revision 1.26 2004/07/05 14:23:03 strk * More documentation cleanups. * * Revision 1.25 2004/07/03 12:51:37 strk * Documentation cleanups for DoxyGen. * * Revision 1.24 2004/07/02 13:28:26 strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.23 2004/05/28 18:16:01 ybychkov * Changed rounding method to make compilable with VC++ * * Revision 1.22 2004/05/21 13:39:31 strk * ::makePrecise make use of nearbyint() now, to be compatible with JTS * * Revision 1.21 2004/05/19 19:39:05 ybychkov * Changed rounding method to make compilable with VC++ * * Revision 1.20 2004/05/17 10:45:58 strk * Fixed bogus FIXED coordinate rounding * * Revision 1.19 2004/04/16 07:42:06 strk * PrecisionModel::Type made an enum instead of a Type. * * Revision 1.18 2004/04/14 09:38:10 strk * PrecisionModel(double newScale) missed to set the scale * * Revision 1.17 2004/03/31 07:50:37 ybychkov * "geom" partially upgraded to JTS 1.4 * * Revision 1.16 2003/11/12 17:15:05 strk * made sure PrecisionModel scale is never 0 * * Revision 1.15 2003/11/07 01:23:42 pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * Revision 1.14 2003/10/11 01:56:08 strk * * Code base padded with 'const' keywords ;) * * Revision 1.13 2003/10/09 10:10:05 strk * Throw an exception if scale is 0. Added Log entry. * **********************************************************************/#include <sstream>#include <geos/geom.h>#include <geos/util.h>namespace geos {const double PrecisionModel::maximumPreciseValue=9007199254740992.0;/* * \brief Implementation of rint() for Visual C++ */static doublerint_vc(double val){ double n; double f=fabs(modf(val,&n)); if (val>=0) { if (f<0.5) { return floor(val); } else if (f>0.5) { return ceil(val); } else { return(floor(n/2)==n/2)?n:n+1.0; } } else { if (f<0.5) { return ceil(val); } else if (f>0.5) { return floor(val); } else { return(floor(n/2)==n/2)?n:n-1.0; } }}/*** Rounds an numeric value to the PrecisionModel grid.*/double PrecisionModel::makePrecise(double val) const { if (modelType==FLOATING_SINGLE) { float floatSingleVal = (float) val; return (double) floatSingleVal; } if (modelType == FIXED) { //double d=val*scale; //double me=((d >= 0.0) ? floor(d+0.5)/scale : - floor(-d+0.5)/scale);// double ret = nearbyint(val*scale)/scale; double ret = rint_vc(val*scale)/scale; return ret; } // modelType == FLOATING - no rounding necessary return val;}/*** Rounds given Coordinate to the PrecisionModel grid.*/void PrecisionModel::makePrecise(Coordinate *coord) const { // optimization for full precision if (modelType==FLOATING) return; coord->x=makePrecise(coord->x); coord->y=makePrecise(coord->y);}/*** Creates a <code>PrecisionModel</code> with a default precision* of FLOATING.*/PrecisionModel::PrecisionModel(){ modelType=FLOATING; scale=1.0;}/*** Creates a <code>PrecisionModel</code> that specifies* an explicit precision model type.* If the model type is FIXED the scale factor will default to 1.** @param modelType the type of the precision model*/PrecisionModel::PrecisionModel(Type nModelType){ modelType=nModelType; if (modelType==FIXED){ setScale(1.0); }}/* * Creates a <code>PrecisionModel</code> that specifies Fixed precision. * Fixed-precision coordinates are represented as precise internal coordinates, * which are rounded to the grid defined by the scale factor. * * @param scale amount by which to multiply a coordinate after subtracting * the offset, to obtain a precise coordinate * @param offsetX not used. * @param offsetY not used. * * @deprecated offsets are no longer supported, * since internal representation is rounded floating point */PrecisionModel::PrecisionModel(double newScale, double newOffsetX, double newOffsetY) //throw(IllegalArgumentException *){ modelType = FIXED; setScale(newScale);}/* * Creates a <code>PrecisionModel</code> that specifies Fixed precision. * Fixed-precision coordinates are represented as precise internal coordinates, * which are rounded to the grid defined by the scale factor. * *@param scale amount by which to multiply a coordinate after subtracting * the offset, to obtain a precise coordinate */PrecisionModel::PrecisionModel(double newScale) //throw (IllegalArgumentException *){ modelType=FIXED; setScale(newScale);}PrecisionModel::PrecisionModel(const PrecisionModel &pm){ modelType = pm.modelType; scale = pm.scale;}/*** Tests whether the precision model supports floating point* @return <code>true</code> if the precision model supports floating point*/bool PrecisionModel::isFloating() const { return (modelType == FLOATING || modelType == FLOATING_SINGLE);}/*** 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 PrecisionModel::getMaximumSignificantDigits() const { int maxSigDigits = 16; if (modelType == FLOATING) { maxSigDigits = 16; }
else if (modelType == FLOATING_SINGLE) { maxSigDigits = 6; }
else if (modelType == FIXED) { maxSigDigits = 1 + (int)ceil((double)log(getScale())/(double)log(10.0)); } return maxSigDigits;}/*** Gets the type of this PrecisionModel* @return the type of this PrecisionModel*/PrecisionModel::Type PrecisionModel::getType() const { return modelType;}/*** Returns the multiplying factor used to obtain a precise coordinate.* This method is private because PrecisionModel is intended to* be an immutable (value) type.**@return the amount by which to multiply a coordinate after subtracting* the offset*/double PrecisionModel::getScale() const { return scale;}/*** 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 PrecisionModel::setScale(double newScale) { if ( newScale == 0 )
throw new IllegalArgumentException("PrecisionModel scale cannot be 0"); scale=fabs(newScale);}/* * 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 PrecisionModel::getOffsetX() const { return 0;}/* * 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 PrecisionModel::getOffsetY() const { return 0;}/* * Sets <code>internal</code> to the precise representation of <code>external</code>. * * @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 PrecisionModel::toInternal (const Coordinate& external, Coordinate* internal) const { if (isFloating()) { internal->x = external.x; internal->y = external.y; }
else { internal->x=makePrecise(external.x); internal->y=makePrecise(external.y); } internal->z = external.z;}/* * 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* PrecisionModel::toInternal(const Coordinate& external) const { Coordinate* internal=new Coordinate(external); makePrecise(internal); return internal;}/* * 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* PrecisionModel::toExternal(const Coordinate& internal) const { Coordinate* external=new Coordinate(internal); return external;}/* * 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 PrecisionModel::toExternal(const Coordinate& internal, Coordinate* external) const { external->x = internal.x; external->y = internal.y;} string PrecisionModel::toString() const { ostringstream s; if (modelType == FLOATING) { s<<"Floating"; } else if (modelType == FLOATING_SINGLE) { s<<"Floating-Single"; } else if (modelType == FIXED) { s<<"Fixed (Scale="<<getScale()<<")"; }
else { s<<"UNKNOWN"; } return s.str();}PrecisionModel::~PrecisionModel(){}bool operator==(const PrecisionModel a, const PrecisionModel b) { return a.isFloating() == b.isFloating() && a.getScale() == b.getScale();}/*** Compares this {@link 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* {@link 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 o the <code>PrecisionModel</code> with which this <code>PrecisionModel</code>* is being compared*@return a negative integer, zero, or a positive integer as this <code>PrecisionModel</code>* is less than, equal to, or greater than the specified <code>PrecisionModel</code>*/int PrecisionModel::compareTo(const PrecisionModel *other) const { int sigDigits=getMaximumSignificantDigits(); int otherSigDigits=other->getMaximumSignificantDigits(); return sigDigits<otherSigDigits? -1: (sigDigits==otherSigDigits? 0:1); //if (modelType==FLOATING && other->modelType==FLOATING) return 0; //if (modelType==FLOATING && other->modelType!=FLOATING) return 1; //if (modelType!=FLOATING && other->modelType==FLOATING) return -1; //if (modelType==FIXED && other->modelType==FIXED) { // if (scale>other->scale) // return 1; // else if (scale<other->scale) // return -1; // else // return 0; //} //Assert::shouldNeverReachHere("Unknown Precision Model type encountered"); //return 0;}}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?