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_TUPLE_B3DTUPLE_HXX
25 #define _BGFX_TUPLE_B3DTUPLE_HXX
26 
27 #include <sal/types.h>
28 #include <basegfx/numeric/ftools.hxx>
29 #undef min
30 #undef max
31 #include <algorithm>
32 
33 namespace basegfx
34 {
35 	// predeclarations
36 	class B3ITuple;
37 
38 	/** Base class for all Points/Vectors with three double values
39 
40 		This class provides all methods common to Point
41 		avd Vector classes which are derived from here.
42 
43 		@derive Use this class to implement Points or Vectors
44 		which are based on three double values
45 	*/
46 	class BASEGFX_DLLPUBLIC B3DTuple
47 	{
48 	protected:
49 		double										mfX;
50 		double										mfY;
51 		double										mfZ;
52 
53 	public:
54 		/**	Create a 3D Tuple
55 
56         	The tuple is initialized to (0.0, 0.0, 0.0)
57 		*/
B3DTuple()58 		B3DTuple()
59 		:	mfX(0.0),
60 			mfY(0.0),
61 			mfZ(0.0)
62 		{}
63 
64 		/**	Create a 3D Tuple
65 
66 			@param fX
67 			This parameter is used to initialize the X-coordinate
68 			of the 3D Tuple.
69 
70 			@param fY
71 			This parameter is used to initialize the Y-coordinate
72 			of the 3D Tuple.
73 
74 			@param fZ
75 			This parameter is used to initialize the Z-coordinate
76 			of the 3D Tuple.
77 		*/
B3DTuple(double fX,double fY,double fZ)78 		B3DTuple(double fX, double fY, double fZ)
79 		:	mfX(fX),
80 			mfY(fY),
81 			mfZ(fZ)
82 		{}
83 
84 		/**	Create a copy of a 3D Tuple
85 
86 			@param rTup
87 			The 3D Tuple which will be copied.
88 		*/
B3DTuple(const B3DTuple & rTup)89 		B3DTuple(const B3DTuple& rTup)
90 		:	mfX( rTup.mfX ),
91 			mfY( rTup.mfY ),
92 			mfZ( rTup.mfZ )
93 		{}
94 
95 		/**	Create a copy of a 3D integer Tuple
96 
97 			@param rTup
98 			The 3D Tuple which will be copied.
99 		*/
100 		explicit B3DTuple(const B3ITuple& rTup);
101 
~B3DTuple()102 		~B3DTuple()
103 		{}
104 
105 		/// get X-Coordinate of 3D Tuple
getX() const106 		double getX() const
107 		{
108 			return mfX;
109 		}
110 
111 		/// get Y-Coordinate of 3D Tuple
getY() const112 		double getY() const
113 		{
114 			return mfY;
115 		}
116 
117 		/// get Z-Coordinate of 3D Tuple
getZ() const118 		double getZ() const
119 		{
120 			return mfZ;
121 		}
122 
123 		/// set X-Coordinate of 3D Tuple
setX(double fX)124 		void setX(double fX)
125 		{
126 			mfX = fX;
127 		}
128 
129 		/// set Y-Coordinate of 3D Tuple
setY(double fY)130 		void setY(double fY)
131 		{
132 			mfY = fY;
133 		}
134 
135 		/// set Z-Coordinate of 3D Tuple
setZ(double fZ)136 		void setZ(double fZ)
137 		{
138 			mfZ = fZ;
139 		}
140 
141 		/// Array-access to 3D Tuple
operator [](int nPos) const142 		const double& operator[] (int nPos) const
143 		{
144 			// Here, normally two if(...)'s should be used. In the assumption that
145 			// both double members can be accessed as an array a shortcut is used here.
146 			// if(0 == nPos) return mfX; if(1 == nPos) return mfY; return mfZ;
147 			return *((&mfX) + nPos);
148 		}
149 
150 		/// Array-access to 3D Tuple
operator [](int nPos)151 		double& operator[] (int nPos)
152 		{
153 			// Here, normally two if(...)'s should be used. In the assumption that
154 			// both double members can be accessed as an array a shortcut is used here.
155 			// if(0 == nPos) return mfX; if(1 == nPos) return mfY; return mfZ;
156 			return *((&mfX) + nPos);
157 		}
158 
159 		// comparators with tolerance
160 		//////////////////////////////////////////////////////////////////////
161 
equalZero() const162 		bool equalZero() const
163 		{
164 			return (this == &getEmptyTuple() ||
165 				(::basegfx::fTools::equalZero(mfX)
166 				&& ::basegfx::fTools::equalZero(mfY)
167 				&& ::basegfx::fTools::equalZero(mfZ)));
168 		}
169 
equalZero(const double & rfSmallValue) const170 		bool equalZero(const double& rfSmallValue) const
171 		{
172 			return (this == &getEmptyTuple() ||
173 				(::basegfx::fTools::equalZero(mfX, rfSmallValue)
174 				&& ::basegfx::fTools::equalZero(mfY, rfSmallValue)
175 				&& ::basegfx::fTools::equalZero(mfZ, rfSmallValue)));
176 		}
177 
equal(const B3DTuple & rTup) const178 		bool equal(const B3DTuple& rTup) const
179 		{
180 			return (
181 				this == &rTup ||
182 				(::basegfx::fTools::equal(mfX, rTup.mfX) &&
183 				::basegfx::fTools::equal(mfY, rTup.mfY) &&
184 				::basegfx::fTools::equal(mfZ, rTup.mfZ)));
185 		}
186 
equal(const B3DTuple & rTup,const double & rfSmallValue) const187 		bool equal(const B3DTuple& rTup, const double& rfSmallValue) const
188 		{
189 			return (
190 				this == &rTup ||
191 				(::basegfx::fTools::equal(mfX, rTup.mfX, rfSmallValue) &&
192 				::basegfx::fTools::equal(mfY, rTup.mfY, rfSmallValue) &&
193 				::basegfx::fTools::equal(mfZ, rTup.mfZ, rfSmallValue)));
194 		}
195 
196 		// operators
197 		//////////////////////////////////////////////////////////////////////
198 
operator +=(const B3DTuple & rTup)199 		B3DTuple& operator+=( const B3DTuple& rTup )
200 		{
201 			mfX += rTup.mfX;
202 			mfY += rTup.mfY;
203 			mfZ += rTup.mfZ;
204 			return *this;
205 		}
206 
operator -=(const B3DTuple & rTup)207 		B3DTuple& operator-=( const B3DTuple& rTup )
208 		{
209 			mfX -= rTup.mfX;
210 			mfY -= rTup.mfY;
211 			mfZ -= rTup.mfZ;
212 			return *this;
213 		}
214 
operator /=(const B3DTuple & rTup)215 		B3DTuple& operator/=( const B3DTuple& rTup )
216 		{
217 			mfX /= rTup.mfX;
218 			mfY /= rTup.mfY;
219 			mfZ /= rTup.mfZ;
220 			return *this;
221 		}
222 
operator *=(const B3DTuple & rTup)223 		B3DTuple& operator*=( const B3DTuple& rTup )
224 		{
225 			mfX *= rTup.mfX;
226 			mfY *= rTup.mfY;
227 			mfZ *= rTup.mfZ;
228 			return *this;
229 		}
230 
operator *=(double t)231 		B3DTuple& operator*=(double t)
232 		{
233 			mfX *= t;
234 			mfY *= t;
235 			mfZ *= t;
236 			return *this;
237 		}
238 
operator /=(double t)239 		B3DTuple& operator/=(double t)
240 		{
241 			const double fVal(1.0 / t);
242 			mfX *= fVal;
243 			mfY *= fVal;
244 			mfZ *= fVal;
245 			return *this;
246 		}
247 
operator -(void) const248 		B3DTuple operator-(void) const
249 		{
250 			return B3DTuple(-mfX, -mfY, -mfZ);
251 		}
252 
operator ==(const B3DTuple & rTup) const253 		bool operator==( const B3DTuple& rTup ) const
254 		{
255 			return mfX == rTup.mfX && mfY == rTup.mfY && mfZ == rTup.mfZ;
256 		}
257 
operator !=(const B3DTuple & rTup) const258 		bool operator!=( const B3DTuple& rTup ) const
259 		{
260 			return mfX != rTup.mfX || mfY != rTup.mfY || mfZ != rTup.mfZ;
261 		}
262 
operator =(const B3DTuple & rTup)263 		B3DTuple& operator=( const B3DTuple& rTup )
264 		{
265 			mfX = rTup.mfX;
266 			mfY = rTup.mfY;
267 			mfZ = rTup.mfZ;
268 			return *this;
269 		}
270 
correctValues(const double fCompareValue=0.0)271 		void correctValues(const double fCompareValue = 0.0)
272 		{
273 			if(0.0 == fCompareValue)
274 			{
275 				if(::basegfx::fTools::equalZero(mfX))
276 				{
277 					mfX = 0.0;
278 				}
279 
280 				if(::basegfx::fTools::equalZero(mfY))
281 				{
282 					mfY = 0.0;
283 				}
284 
285 				if(::basegfx::fTools::equalZero(mfZ))
286 				{
287 					mfZ = 0.0;
288 				}
289 			}
290 			else
291 			{
292 				if(::basegfx::fTools::equal(mfX, fCompareValue))
293 				{
294 					mfX = fCompareValue;
295 				}
296 
297 				if(::basegfx::fTools::equal(mfY, fCompareValue))
298 				{
299 					mfY = fCompareValue;
300 				}
301 
302 				if(::basegfx::fTools::equal(mfZ, fCompareValue))
303 				{
304 					mfZ = fCompareValue;
305 				}
306 			}
307 		}
308 
309 		static const B3DTuple& getEmptyTuple();
310 	};
311 
312 	// external operators
313 	//////////////////////////////////////////////////////////////////////////
314 
minimum(const B3DTuple & rTupA,const B3DTuple & rTupB)315 	inline B3DTuple minimum(const B3DTuple& rTupA, const B3DTuple& rTupB)
316 	{
317         return B3DTuple(
318             std::min(rTupB.getX(), rTupA.getX()),
319             std::min(rTupB.getY(), rTupA.getY()),
320             std::min(rTupB.getZ(), rTupA.getZ()));
321 	}
322 
maximum(const B3DTuple & rTupA,const B3DTuple & rTupB)323 	inline B3DTuple maximum(const B3DTuple& rTupA, const B3DTuple& rTupB)
324 	{
325         return B3DTuple(
326             std::max(rTupB.getX(), rTupA.getX()),
327             std::max(rTupB.getY(), rTupA.getY()),
328             std::max(rTupB.getZ(), rTupA.getZ()));
329 	}
330 
absolute(const B3DTuple & rTup)331 	inline B3DTuple absolute(const B3DTuple& rTup)
332 	{
333 		B3DTuple aAbs(
334             fabs(rTup.getX()),
335             fabs(rTup.getY()),
336             fabs(rTup.getZ()));
337 		return aAbs;
338 	}
339 
interpolate(const B3DTuple & rOld1,const B3DTuple & rOld2,double t)340 	inline B3DTuple interpolate(const B3DTuple& rOld1, const B3DTuple& rOld2, double t)
341 	{
342         if(rOld1 == rOld2)
343         {
344             return rOld1;
345         }
346         else if(0.0 >= t)
347         {
348             return rOld1;
349         }
350         else if(1.0 <= t)
351         {
352             return rOld2;
353         }
354         else
355         {
356             return B3DTuple(
357 			    ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(),
358 			    ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(),
359 			    ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ());
360         }
361 	}
362 
average(const B3DTuple & rOld1,const B3DTuple & rOld2)363 	inline B3DTuple average(const B3DTuple& rOld1, const B3DTuple& rOld2)
364 	{
365         return B3DTuple(
366             rOld1.getX() == rOld2.getX() ? rOld1.getX() : (rOld1.getX() + rOld2.getX()) * 0.5,
367             rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5,
368             rOld1.getZ() == rOld2.getZ() ? rOld1.getZ() : (rOld1.getZ() + rOld2.getZ()) * 0.5);
369 	}
370 
average(const B3DTuple & rOld1,const B3DTuple & rOld2,const B3DTuple & rOld3)371 	inline B3DTuple average(const B3DTuple& rOld1, const B3DTuple& rOld2, const B3DTuple& rOld3)
372 	{
373         return B3DTuple(
374             (rOld1.getX() == rOld2.getX() && rOld2.getX() == rOld3.getX()) ? rOld1.getX() : (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0),
375             (rOld1.getY() == rOld2.getY() && rOld2.getY() == rOld3.getY()) ? rOld1.getY() : (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0),
376             (rOld1.getZ() == rOld2.getZ() && rOld2.getZ() == rOld3.getZ()) ? rOld1.getZ() : (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0));
377 	}
378 
operator +(const B3DTuple & rTupA,const B3DTuple & rTupB)379 	inline B3DTuple operator+(const B3DTuple& rTupA, const B3DTuple& rTupB)
380 	{
381 		B3DTuple aSum(rTupA);
382 		aSum += rTupB;
383 		return aSum;
384 	}
385 
operator -(const B3DTuple & rTupA,const B3DTuple & rTupB)386 	inline B3DTuple operator-(const B3DTuple& rTupA, const B3DTuple& rTupB)
387 	{
388 		B3DTuple aSub(rTupA);
389 		aSub -= rTupB;
390 		return aSub;
391 	}
392 
operator /(const B3DTuple & rTupA,const B3DTuple & rTupB)393 	inline B3DTuple operator/(const B3DTuple& rTupA, const B3DTuple& rTupB)
394 	{
395 		B3DTuple aDiv(rTupA);
396 		aDiv /= rTupB;
397 		return aDiv;
398 	}
399 
operator *(const B3DTuple & rTupA,const B3DTuple & rTupB)400 	inline B3DTuple operator*(const B3DTuple& rTupA, const B3DTuple& rTupB)
401 	{
402 		B3DTuple aMul(rTupA);
403 		aMul *= rTupB;
404 		return aMul;
405 	}
406 
operator *(const B3DTuple & rTup,double t)407 	inline B3DTuple operator*(const B3DTuple& rTup, double t)
408 	{
409 		B3DTuple aNew(rTup);
410 		aNew *= t;
411 		return aNew;
412 	}
413 
operator *(double t,const B3DTuple & rTup)414 	inline B3DTuple operator*(double t, const B3DTuple& rTup)
415 	{
416 		B3DTuple aNew(rTup);
417 		aNew *= t;
418 		return aNew;
419 	}
420 
operator /(const B3DTuple & rTup,double t)421 	inline B3DTuple operator/(const B3DTuple& rTup, double t)
422 	{
423 		B3DTuple aNew(rTup);
424 		aNew /= t;
425 		return aNew;
426 	}
427 
operator /(double t,const B3DTuple & rTup)428 	inline B3DTuple operator/(double t, const B3DTuple& rTup)
429 	{
430 		B3DTuple aNew(rTup);
431 		aNew /= t;
432 		return aNew;
433 	}
434 
435 	/** Round double to nearest integer for 3D tuple
436 
437 		@return the nearest integer for this tuple
438 	*/
439 	BASEGFX_DLLPUBLIC B3ITuple fround(const B3DTuple& rTup);
440 } // end of namespace basegfx
441 
442 #endif /* _BGFX_TUPLE_B3DTUPLE_HXX */
443