xref: /trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx (revision c2aa6762603290a3bb12637f1cdccb182d5b89fb)
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