xref: /AOO41X/main/basegfx/inc/basegfx/range/basicrange.hxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _BGFX_RANGE_BASICRANGE_HXX
29 #define _BGFX_RANGE_BASICRANGE_HXX
30 
31 #include <sal/types.h>
32 #include <float.h>
33 #include <basegfx/numeric/ftools.hxx>
34 
35 
36 namespace basegfx
37 {
38 	template< typename T, typename Traits > class BasicRange
39 	{
40 	protected:
41 		T		mnMinimum;
42 		T		mnMaximum;
43 
44 	public:
45         typedef T 		ValueType;
46         typedef Traits	TraitsType;
47 
48         BasicRange() :
49             mnMinimum(Traits::maxVal()),
50 			mnMaximum(Traits::minVal())
51 		{
52 		}
53 
54         BasicRange( T nValue ) :
55             mnMinimum(nValue),
56 			mnMaximum(nValue)
57 		{
58 		}
59 
60 		BasicRange(const BasicRange& rRange) :
61             mnMinimum(rRange.mnMinimum),
62 			mnMaximum(rRange.mnMaximum)
63 		{
64 		}
65 
66 		void reset()
67 		{
68 			mnMinimum = Traits::maxVal();
69 			mnMaximum = Traits::minVal();
70 		}
71 
72 		bool isEmpty() const
73 		{
74 			return Traits::maxVal() == mnMinimum;
75 		}
76 
77         T getMinimum() const { return mnMinimum; }
78         T getMaximum() const { return mnMaximum; }
79 
80 		double getCenter() const
81 		{
82 			if(isEmpty())
83 			{
84 				return 0.0;
85 			}
86 			else
87 			{
88 				return ((mnMaximum + mnMinimum) / 2.0);
89 			}
90 		}
91 
92 		bool isInside(T nValue) const
93 		{
94 			if(isEmpty())
95 			{
96 				return false;
97 			}
98 			else
99 			{
100 				return (nValue >= mnMinimum) && (nValue <= mnMaximum);
101 			}
102 		}
103 
104 		bool isInside(const BasicRange& rRange) const
105 		{
106 			if(isEmpty())
107 			{
108 				return false;
109 			}
110 			else
111 			{
112 				if(rRange.isEmpty())
113 				{
114 					return false;
115 				}
116 				else
117 				{
118 					return (rRange.mnMinimum >= mnMinimum) && (rRange.mnMaximum <= mnMaximum);
119 				}
120 			}
121 		}
122 
123 		bool overlaps(const BasicRange& rRange) const
124 		{
125 			if(isEmpty())
126 			{
127 				return false;
128 			}
129 			else
130 			{
131 				if(rRange.isEmpty())
132 				{
133 					return false;
134 				}
135 				else
136 				{
137 					return !((rRange.mnMaximum < mnMinimum) || (rRange.mnMinimum > mnMaximum));
138 				}
139 			}
140 		}
141 
142 		bool overlapsMore(const BasicRange& rRange) const
143 		{
144 			if(isEmpty() || rRange.isEmpty())
145 				return false;
146 			// returns true if the overlap is more than just a touching at the limits
147 			return ((rRange.mnMaximum > mnMinimum) && (rRange.mnMinimum < mnMaximum));
148 		}
149 
150 		bool operator==( const BasicRange& rRange ) const
151 		{
152 			return (mnMinimum == rRange.mnMinimum && mnMaximum == rRange.mnMaximum);
153 		}
154 
155 		bool operator!=( const BasicRange& rRange ) const
156 		{
157 			return (mnMinimum != rRange.mnMinimum || mnMaximum != rRange.mnMaximum);
158 		}
159 
160 		BasicRange& operator=(const BasicRange& rRange)
161 		{
162 			mnMinimum = rRange.mnMinimum;
163 			mnMaximum = rRange.mnMaximum;
164 			return *this;
165 		}
166 
167 		bool equal(const BasicRange& rRange) const
168         {
169             return (
170                 fTools::equal(mnMinimum, rRange.mnMinimum) &&
171                 fTools::equal(mnMaximum, rRange.mnMaximum));
172         }
173 
174 		void expand(T nValue)
175 		{
176 			if(isEmpty())
177 			{
178 				mnMinimum = mnMaximum = nValue;
179 			}
180 			else
181 			{
182 				if(nValue < mnMinimum)
183 				{
184 					mnMinimum = nValue;
185 				}
186 
187 				if(nValue > mnMaximum)
188 				{
189 					mnMaximum = nValue;
190 				}
191 			}
192 		}
193 
194 		void expand(const BasicRange& rRange)
195 		{
196 			if(isEmpty())
197 			{
198 				mnMinimum = rRange.mnMinimum;
199 				mnMaximum = rRange.mnMaximum;
200 			}
201 			else
202 			{
203 				if(!rRange.isEmpty())
204 				{
205 					if(rRange.mnMinimum < mnMinimum)
206 					{
207 						mnMinimum = rRange.mnMinimum;
208 					}
209 
210 					if(rRange.mnMaximum > mnMaximum)
211 					{
212 						mnMaximum = rRange.mnMaximum;
213 					}
214 				}
215 			}
216 		}
217 
218         void intersect(const BasicRange& rRange)
219         {
220 			// here, overlaps also tests all isEmpty() conditions already.
221             if( !overlaps( rRange ) )
222             {
223                 reset();
224             }
225             else
226             {
227 				if(rRange.mnMinimum > mnMinimum)
228 				{
229 					mnMinimum = rRange.mnMinimum;
230 				}
231 
232 				if(rRange.mnMaximum < mnMaximum)
233 				{
234 					mnMaximum = rRange.mnMaximum;
235 				}
236             }
237         }
238 
239 		void grow(T nValue)
240 		{
241 			if(!isEmpty())
242 			{
243 				bool bLessThanZero(nValue < 0);
244 
245 				if(nValue > 0 || bLessThanZero)
246 				{
247 					mnMinimum -= nValue;
248 					mnMaximum += nValue;
249 
250 					if(bLessThanZero)
251 					{
252 						// test if range did collapse
253 						if(mnMinimum > mnMaximum)
254 						{
255 							// if yes, collapse to center
256 							mnMinimum = mnMaximum = (mnMinimum + mnMaximum) / 2;
257 						}
258 					}
259 				}
260 			}
261 		}
262 
263 		typename Traits::DifferenceType getRange() const
264 		{
265 			if(isEmpty())
266 			{
267 				return Traits::neutral();
268 			}
269 			else
270 			{
271 				return (mnMaximum - mnMinimum);
272 			}
273 		}
274 	};
275 
276     // some pre-fabricated traits
277     struct DoubleTraits
278     {
279         static double minVal() { return DBL_MIN; };
280         static double maxVal() { return DBL_MAX; };
281         static double neutral() { return 0.0; };
282 
283         typedef double DifferenceType;
284     };
285 
286     struct Int32Traits
287     {
288         static sal_Int32 minVal() { return SAL_MIN_INT32; };
289         static sal_Int32 maxVal() { return SAL_MAX_INT32; };
290         static sal_Int32 neutral() { return 0L; };
291 
292         typedef sal_Int64 DifferenceType;
293     };
294 
295 } // end of namespace basegfx
296 
297 #endif /* _BGFX_RANGE_BASICRANGE_HXX */
298