xref: /AOO41X/main/basegfx/inc/basegfx/range/basicrange.hxx (revision ce9c7ef7bd056b6da7d6eeebb749fbf2160d647b)
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_RANGE_BASICRANGE_HXX
25 #define _BGFX_RANGE_BASICRANGE_HXX
26 
27 #include <sal/types.h>
28 #include <float.h>
29 #include <basegfx/numeric/ftools.hxx>
30 
31 
32 namespace basegfx
33 {
34     template< typename T, typename Traits > class BasicRange
35     {
36     protected:
37         T       mnMinimum;
38         T       mnMaximum;
39 
40     public:
41         typedef T       ValueType;
42         typedef Traits  TraitsType;
43 
BasicRange()44         BasicRange() :
45             mnMinimum(Traits::maxVal()),
46             mnMaximum(Traits::minVal())
47         {
48         }
49 
BasicRange(T nValue)50         BasicRange( T nValue ) :
51             mnMinimum(nValue),
52             mnMaximum(nValue)
53         {
54         }
55 
BasicRange(const BasicRange & rRange)56         BasicRange(const BasicRange& rRange) :
57             mnMinimum(rRange.mnMinimum),
58             mnMaximum(rRange.mnMaximum)
59         {
60         }
61 
reset()62         void reset()
63         {
64             mnMinimum = Traits::maxVal();
65             mnMaximum = Traits::minVal();
66         }
67 
isEmpty() const68         bool isEmpty() const
69         {
70             return Traits::maxVal() == mnMinimum;
71         }
72 
getMinimum() const73         T getMinimum() const { return mnMinimum; }
getMaximum() const74         T getMaximum() const { return mnMaximum; }
75 
getCenter() const76         double getCenter() const
77         {
78             if(isEmpty())
79             {
80                 return 0.0;
81             }
82             else
83             {
84                 return ((mnMaximum + mnMinimum) / 2.0);
85             }
86         }
87 
isInside(T nValue) const88         bool isInside(T nValue) const
89         {
90             if(isEmpty())
91             {
92                 return false;
93             }
94             else
95             {
96                 return (nValue >= mnMinimum) && (nValue <= mnMaximum);
97             }
98         }
99 
isInside(const BasicRange & rRange) const100         bool isInside(const BasicRange& rRange) const
101         {
102             if(isEmpty())
103             {
104                 return false;
105             }
106             else
107             {
108                 if(rRange.isEmpty())
109                 {
110                     return false;
111                 }
112                 else
113                 {
114                     return (rRange.mnMinimum >= mnMinimum) && (rRange.mnMaximum <= mnMaximum);
115                 }
116             }
117         }
118 
overlaps(const BasicRange & rRange) const119         bool overlaps(const BasicRange& rRange) const
120         {
121             if(isEmpty())
122             {
123                 return false;
124             }
125             else
126             {
127                 if(rRange.isEmpty())
128                 {
129                     return false;
130                 }
131                 else
132                 {
133                     return !((rRange.mnMaximum < mnMinimum) || (rRange.mnMinimum > mnMaximum));
134                 }
135             }
136         }
137 
overlapsMore(const BasicRange & rRange) const138         bool overlapsMore(const BasicRange& rRange) const
139         {
140             if(isEmpty() || rRange.isEmpty())
141                 return false;
142             // returns true if the overlap is more than just a touching at the limits
143             return ((rRange.mnMaximum > mnMinimum) && (rRange.mnMinimum < mnMaximum));
144         }
145 
operator ==(const BasicRange & rRange) const146         bool operator==( const BasicRange& rRange ) const
147         {
148             return (mnMinimum == rRange.mnMinimum && mnMaximum == rRange.mnMaximum);
149         }
150 
operator !=(const BasicRange & rRange) const151         bool operator!=( const BasicRange& rRange ) const
152         {
153             return (mnMinimum != rRange.mnMinimum || mnMaximum != rRange.mnMaximum);
154         }
155 
operator =(const BasicRange & rRange)156         BasicRange& operator=(const BasicRange& rRange)
157         {
158             mnMinimum = rRange.mnMinimum;
159             mnMaximum = rRange.mnMaximum;
160             return *this;
161         }
162 
equal(const BasicRange & rRange) const163         bool equal(const BasicRange& rRange) const
164         {
165             return (
166                 fTools::equal(mnMinimum, rRange.mnMinimum) &&
167                 fTools::equal(mnMaximum, rRange.mnMaximum));
168         }
169 
expand(T nValue)170         void expand(T nValue)
171         {
172             if(isEmpty())
173             {
174                 mnMinimum = mnMaximum = nValue;
175             }
176             else
177             {
178                 if(nValue < mnMinimum)
179                 {
180                     mnMinimum = nValue;
181                 }
182 
183                 if(nValue > mnMaximum)
184                 {
185                     mnMaximum = nValue;
186                 }
187             }
188         }
189 
expand(const BasicRange & rRange)190         void expand(const BasicRange& rRange)
191         {
192             if(isEmpty())
193             {
194                 mnMinimum = rRange.mnMinimum;
195                 mnMaximum = rRange.mnMaximum;
196             }
197             else
198             {
199                 if(!rRange.isEmpty())
200                 {
201                     if(rRange.mnMinimum < mnMinimum)
202                     {
203                         mnMinimum = rRange.mnMinimum;
204                     }
205 
206                     if(rRange.mnMaximum > mnMaximum)
207                     {
208                         mnMaximum = rRange.mnMaximum;
209                     }
210                 }
211             }
212         }
213 
intersect(const BasicRange & rRange)214         void intersect(const BasicRange& rRange)
215         {
216             // here, overlaps also tests all isEmpty() conditions already.
217             if( !overlaps( rRange ) )
218             {
219                 reset();
220             }
221             else
222             {
223                 if(rRange.mnMinimum > mnMinimum)
224                 {
225                     mnMinimum = rRange.mnMinimum;
226                 }
227 
228                 if(rRange.mnMaximum < mnMaximum)
229                 {
230                     mnMaximum = rRange.mnMaximum;
231                 }
232             }
233         }
234 
grow(T nValue)235         void grow(T nValue)
236         {
237             if(!isEmpty())
238             {
239                 bool bLessThanZero(nValue < 0);
240 
241                 if(nValue > 0 || bLessThanZero)
242                 {
243                     mnMinimum -= nValue;
244                     mnMaximum += nValue;
245 
246                     if(bLessThanZero)
247                     {
248                         // test if range did collapse
249                         if(mnMinimum > mnMaximum)
250                         {
251                             // if yes, collapse to center
252                             mnMinimum = mnMaximum = (mnMinimum + mnMaximum) / 2;
253                         }
254                     }
255                 }
256             }
257         }
258 
getRange() const259         typename Traits::DifferenceType getRange() const
260         {
261             if(isEmpty())
262             {
263                 return Traits::neutral();
264             }
265             else
266             {
267                 return (mnMaximum - mnMinimum);
268             }
269         }
270     };
271 
272     // some pre-fabricated traits
273     struct DoubleTraits
274     {
minValbasegfx::DoubleTraits275         static double minVal() { return DBL_MIN; };
maxValbasegfx::DoubleTraits276         static double maxVal() { return DBL_MAX; };
neutralbasegfx::DoubleTraits277         static double neutral() { return 0.0; };
278 
279         typedef double DifferenceType;
280     };
281 
282     struct Int32Traits
283     {
minValbasegfx::Int32Traits284         static sal_Int32 minVal() { return SAL_MIN_INT32; };
maxValbasegfx::Int32Traits285         static sal_Int32 maxVal() { return SAL_MAX_INT32; };
neutralbasegfx::Int32Traits286         static sal_Int32 neutral() { return 0L; };
287 
288         typedef sal_Int64 DifferenceType;
289     };
290 
291 } // end of namespace basegfx
292 
293 #endif /* _BGFX_RANGE_BASICRANGE_HXX */
294