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