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