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