1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _BGFX_NUMERIC_FTOOLS_HXX 25 #define _BGFX_NUMERIC_FTOOLS_HXX 26 27 #include <rtl/math.hxx> 28 29 ////////////////////////////////////////////////////////////////////////////// 30 // standard PI defines from solar.h, but we do not want to link against tools 31 32 #ifndef F_PI 33 #define F_PI M_PI 34 #endif 35 #ifndef F_PI2 36 #define F_PI2 M_PI_2 37 #endif 38 #ifndef F_PI4 39 #define F_PI4 M_PI_4 40 #endif 41 #ifndef F_PI180 42 #define F_PI180 (M_PI/180.0) 43 #endif 44 #ifndef F_PI1800 45 #define F_PI1800 (M_PI/1800.0) 46 #endif 47 #ifndef F_PI18000 48 #define F_PI18000 (M_PI/18000.0) 49 #endif 50 #ifndef F_2PI 51 #define F_2PI (2.0*M_PI) 52 #endif 53 54 ////////////////////////////////////////////////////////////////////////////// 55 // fTools defines 56 57 namespace basegfx 58 { 59 /** Round double to nearest integer 60 61 @return the nearest integer 62 */ fround(double fVal)63 inline sal_Int32 fround( double fVal ) 64 { 65 return fVal > 0.0 ? static_cast<sal_Int32>( fVal + .5 ) : -static_cast<sal_Int32>( -fVal + .5 ); 66 } 67 68 /** Round double to nearest integer 69 70 @return the nearest 64 bit integer 71 */ fround64(double fVal)72 inline sal_Int64 fround64( double fVal ) 73 { 74 return fVal > 0.0 ? static_cast<sal_Int64>( fVal + .5 ) : -static_cast<sal_Int64>( -fVal + .5 ); 75 } 76 77 /** Prune a small epsilon range around zero. 78 79 Use this method e.g. for calculating scale values. There, it 80 is usually advisable not to set a scaling to 0.0, because that 81 yields singular transformation matrices. 82 83 @param fVal 84 An arbitrary, but finite and valid number 85 86 @return either fVal, or a small value slightly above (when 87 fVal>0) or below (when fVal<0) zero. 88 */ pruneScaleValue(double fVal)89 inline double pruneScaleValue( double fVal ) 90 { 91 // old version used ::std::min/max, but this collides if min is defined as preprocessor 92 // macro which is the case e.g with windows.h headers. The simplest way to avoid this is to 93 // just use the full comparison. I keep the original here, maybe there will be a better 94 // solution some day. 95 // 96 //return fVal < 0.0 ? 97 // (::std::min(fVal,-0.00001)) : 98 // (::std::max(fVal,0.00001)); 99 100 if(fVal < 0.0) 101 return (fVal < -0.00001 ? fVal : -0.00001); 102 else 103 return (fVal > 0.00001 ? fVal : 0.00001); 104 } 105 106 /** clamp given value against given minimum and maximum values 107 */ clamp(const T & value,const T & minimum,const T & maximum)108 template <class T> inline const T& clamp(const T& value, const T& minimum, const T& maximum) 109 { 110 if(value < minimum) 111 { 112 return minimum; 113 } 114 else if(value > maximum) 115 { 116 return maximum; 117 } 118 else 119 { 120 return value; 121 } 122 } 123 124 /** Convert value from degrees to radians 125 */ deg2rad(double v)126 inline double deg2rad( double v ) 127 { 128 // divide first, to get exact values for v being a multiple of 129 // 90 degrees 130 return v / 90.0 * M_PI_2; 131 } 132 133 /** Convert value radians to degrees 134 */ rad2deg(double v)135 inline double rad2deg( double v ) 136 { 137 // divide first, to get exact values for v being a multiple of 138 // pi/2 139 return v / M_PI_2 * 90.0; 140 } 141 142 /** Snap v to nearest multiple of fStep, from negative and 143 positive side. 144 145 Examples: 146 147 snapToNearestMultiple(-0.1, 0.5) = 0.0 148 snapToNearestMultiple(0.1, 0.5) = 0.0 149 snapToNearestMultiple(0.25, 0.5) = 0.0 150 snapToNearestMultiple(0.26, 0.5) = 0.5 151 */ 152 double snapToNearestMultiple(double v, const double fStep); 153 154 /** Snap v to the range [0.0 .. fWidth] using modulo 155 */ 156 double snapToZeroRange(double v, double fWidth); 157 158 /** Snap v to the range [fLow .. fHigh] using modulo 159 */ 160 double snapToRange(double v, double fLow, double fHigh); 161 162 /** return fValue with the sign of fSignCarrier, thus evtl. changed 163 */ copySign(double fValue,double fSignCarrier)164 inline double copySign(double fValue, double fSignCarrier) 165 { 166 #ifdef WNT 167 return _copysign(fValue, fSignCarrier); 168 #else 169 return copysign(fValue, fSignCarrier); 170 #endif 171 } 172 173 class fTools 174 { 175 /// Threshold value for equalZero() 176 static double mfSmallValue; 177 178 public: 179 /// Get threshold value for equalZero and friends getSmallValue()180 static double getSmallValue() { return mfSmallValue; } 181 /// Set threshold value for equalZero and friends setSmallValue(const double & rfNew)182 static void setSmallValue(const double& rfNew) { mfSmallValue = rfNew; } 183 184 /// Compare against small value equalZero(const double & rfVal)185 static bool equalZero(const double& rfVal) 186 { 187 return (fabs(rfVal) <= getSmallValue()); 188 } 189 190 /// Compare against given small value equalZero(const double & rfVal,const double & rfSmallValue)191 static bool equalZero(const double& rfVal, const double& rfSmallValue) 192 { 193 return (fabs(rfVal) <= rfSmallValue); 194 } 195 equal(const double & rfValA,const double & rfValB)196 static bool equal(const double& rfValA, const double& rfValB) 197 { 198 // changed to approxEqual usage for better numerical correctness 199 return rtl::math::approxEqual(rfValA, rfValB); 200 } 201 equal(const double & rfValA,const double & rfValB,const double & rfSmallValue)202 static bool equal(const double& rfValA, const double& rfValB, const double& rfSmallValue) 203 { 204 return (fabs(rfValA - rfValB) <= rfSmallValue); 205 } 206 less(const double & rfValA,const double & rfValB)207 static bool less(const double& rfValA, const double& rfValB) 208 { 209 return (rfValA < rfValB && !equal(rfValA, rfValB)); 210 } 211 lessOrEqual(const double & rfValA,const double & rfValB)212 static bool lessOrEqual(const double& rfValA, const double& rfValB) 213 { 214 return (rfValA < rfValB || equal(rfValA, rfValB)); 215 } 216 more(const double & rfValA,const double & rfValB)217 static bool more(const double& rfValA, const double& rfValB) 218 { 219 return (rfValA > rfValB && !equal(rfValA, rfValB)); 220 } 221 moreOrEqual(const double & rfValA,const double & rfValB)222 static bool moreOrEqual(const double& rfValA, const double& rfValB) 223 { 224 return (rfValA > rfValB || equal(rfValA, rfValB)); 225 } 226 }; 227 } // end of namespace basegfx 228 229 #endif /* _BGFX_NUMERIC_FTOOLS_HXX */ 230