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_POINT_B3DHOMPOINT_HXX
25 #define _BGFX_POINT_B3DHOMPOINT_HXX
26 
27 #include <basegfx/point/b3dpoint.hxx>
28 #include <basegfx/basegfxdllapi.h>
29 
30 namespace basegfx
31 {
32 	/** Basic homogen Point class with three double values and one homogen factor
33 
34 		This class provides access to homogen coordinates in 3D.
35 		For this purpose all the operators which need to do specific
36 		action due to their homogenity are implemented here.
37 		The only caveat are member methods which are declared as const
38 		but do change the content. These are documented for that reason.
39 		The class is designed to provide homogenous coordinates without
40 		direct access to the homogen part (mfW). This is also the reason
41 		for leaving out the [] operators which return references to members.
42 
43 		@see B3DTuple
44 	*/
45 	class BASEGFX_DLLPUBLIC B3DHomPoint
46 	{
47 	protected:
48 		/// This member contains the coordinate part of the point
49 		::basegfx::B3DTuple					maTuple;
50 
51 		/// This Member holds the homogenous part of the point
52 		double										mfW;
53 
54 		/**	Test if this homogen point does have a homogenous part
55 
56 			@return Returns true if this point has no homogenous part
57 		*/
implIsHomogenized() const58 		bool implIsHomogenized() const
59 		{
60 			const double fOne(1.0);
61 			return ::basegfx::fTools::equal(mfW, fOne);
62 		}
63 
64 		/**	Remove homogenous part of this Point
65 
66 			This method does necessary calculations to remove
67 			the evtl. homogenous part of this Point. This may
68 			change all members.
69 		*/
70 		void implHomogenize();
71 
72 		/**	Test and on demand remove homogenous part
73 
74 			This method tests if this Point does have a homogenous part
75 			and then evtl. takes actions to remove that part.
76 
77 			@attention Even when this method is const it may change all
78 			members of this instance. This is due to the fact that changing
79 			the homogenous part of a homogenous point does from a mathematical
80 			point of view not change the point at all.
81 		*/
implTestAndHomogenize() const82 		void implTestAndHomogenize() const
83 		{
84 			if(!implIsHomogenized())
85 				((B3DHomPoint*)this)->implHomogenize();
86 		}
87 
88 	public:
89 		/**	Create a homogen point
90 
91         	The point is initialized to (0.0, 0.0, 0.0)
92 		*/
B3DHomPoint()93 		B3DHomPoint()
94 		:	maTuple(),
95 			mfW(1.0)
96 		{}
97 
98 		/**	Create a homogen point
99 
100 			@param fX
101 			This parameter is used to initialize the X-coordinate
102 			of the Point. The homogenous part is initialized to 1.0.
103 
104 			@param fY
105 			This parameter is used to initialize the Y-coordinate
106 			of the Point. The homogenous part is initialized to 1.0.
107 
108 			@param fZ
109 			This parameter is used to initialize the Z-coordinate
110 			of the Point. The homogenous part is initialized to 1.0.
111 		*/
B3DHomPoint(double fX,double fY,double fZ)112 		B3DHomPoint(double fX, double fY, double fZ)
113 		:	maTuple(fX, fY, fZ),
114 			mfW(1.0)
115 		{}
116 
117 		/**	Create a copy of a 3D Point
118 
119 			@param rVec
120 			The 3D point which will be copied. The homogenous part
121 			is initialized to 1.0.
122 		*/
B3DHomPoint(const B3DPoint & rVec)123 		B3DHomPoint(const B3DPoint& rVec)
124 		:	maTuple(rVec),
125 			mfW(1.0)
126 		{}
127 
128 		/**	Create a copy of a homogen point
129 
130 			@param rVec
131 			The homogen point which will be copied. The homogenous part
132 			is copied, too.
133 		*/
B3DHomPoint(const B3DHomPoint & rVec)134 		B3DHomPoint(const B3DHomPoint& rVec)
135 		:	maTuple(rVec.maTuple.getX(), rVec.maTuple.getY(), rVec.maTuple.getZ()),
136 			mfW(rVec.mfW)
137 		{}
138 
~B3DHomPoint()139 		~B3DHomPoint()
140 		{}
141 
142 		/**	get a 3D point from this homogenous point
143 
144 			This method normalizes this homogen point if necessary and
145 			returns the corresponding 3D point for this homogen point.
146 
147 			@attention Even when this method is const it may change all
148 			members of this instance.
149 		*/
getB3DPoint() const150 		B3DPoint getB3DPoint() const
151 		{
152 			implTestAndHomogenize();
153 			return B3DPoint(maTuple.getX(), maTuple.getY(), maTuple.getZ());
154 		}
155 
156 		/**	get X-coordinate
157 
158 			This method normalizes this homogen point if necessary and
159 			returns the corresponding X-coordinate for this homogen point.
160 
161 			@attention Even when this method is const it may change all
162 			members of this instance.
163 		*/
getX() const164 		double getX() const
165 		{
166 			implTestAndHomogenize();
167 			return maTuple.getX();
168 		}
169 
170 		/**	get Y-coordinate
171 
172 			This method normalizes this homogen point if necessary and
173 			returns the corresponding Y-coordinate for this homogen point.
174 
175 			@attention Even when this method is const it may change all
176 			members of this instance.
177 		*/
getY() const178 		double getY() const
179 		{
180 			implTestAndHomogenize();
181 			return maTuple.getY();
182 		}
183 
184 		/**	get Z-coordinate
185 
186 			This method normalizes this homogen point if necessary and
187 			returns the corresponding Z-coordinate for this homogen point.
188 
189 			@attention Even when this method is const it may change all
190 			members of this instance.
191 		*/
getZ() const192 		double getZ() const
193 		{
194 			implTestAndHomogenize();
195 			return maTuple.getY();
196 		}
197 
198 		/**	Set X-coordinate of the homogen point.
199 
200 			This method sets the X-coordinate of the homogen point. If
201 			the point does have a homogenous part this is taken into account.
202 
203 			@param fX
204 			The to-be-set X-coordinate without homogenous part.
205 		*/
setX(double fX)206 		void setX(double fX)
207 		{
208 			maTuple.setX(implIsHomogenized() ? fX : fX * mfW );
209 		}
210 
211 		/**	Set Y-coordinate of the homogen point.
212 
213 			This method sets the Y-coordinate of the homogen point. If
214 			the point does have a homogenous part this is taken into account.
215 
216 			@param fY
217 			The to-be-set Y-coordinate without homogenous part.
218 		*/
setY(double fY)219 		void setY(double fY)
220 		{
221 			maTuple.setY(implIsHomogenized() ? fY : fY * mfW );
222 		}
223 
224 		/**	Set Z-coordinate of the homogen point.
225 
226 			This method sets the Z-coordinate of the homogen point. If
227 			the point does have a homogenous part this is taken into account.
228 
229 			@param fZ
230 			The to-be-set Z-coordinate without homogenous part.
231 		*/
setZ(double fZ)232 		void setZ(double fZ)
233 		{
234 			maTuple.setZ(implIsHomogenized() ? fZ : fZ * mfW );
235 		}
236 
237 		// operators
238 		//////////////////////////////////////////////////////////////////////
239 
operator +=(const B3DHomPoint & rPnt)240 		B3DHomPoint& operator+=( const B3DHomPoint& rPnt )
241 		{
242 			maTuple.setX(getX() * rPnt.mfW + rPnt.getX() * mfW);
243 			maTuple.setY(getY() * rPnt.mfW + rPnt.getY() * mfW);
244 			maTuple.setZ(getZ() * rPnt.mfW + rPnt.getZ() * mfW);
245 			mfW = mfW * rPnt.mfW;
246 
247 			return *this;
248 		}
249 
operator -=(const B3DHomPoint & rPnt)250 		B3DHomPoint& operator-=( const B3DHomPoint& rPnt )
251 		{
252 			maTuple.setX(getX() * rPnt.mfW - rPnt.getX() * mfW);
253 			maTuple.setY(getY() * rPnt.mfW - rPnt.getY() * mfW);
254 			maTuple.setZ(getZ() * rPnt.mfW - rPnt.getZ() * mfW);
255 			mfW = mfW * rPnt.mfW;
256 
257 			return *this;
258 		}
259 
operator *=(double t)260 		B3DHomPoint& operator*=(double t)
261 		{
262 			if(!::basegfx::fTools::equalZero(t))
263 			{
264 				mfW /= t;
265 			}
266 
267 			return *this;
268 		}
269 
operator /=(double t)270 		B3DHomPoint& operator/=(double t)
271 		{
272 			mfW *= t;
273 			return *this;
274 		}
275 
operator -(void)276 		B3DHomPoint& operator-(void)
277 		{
278 			mfW = -mfW;
279 			return *this;
280 		}
281 
operator ==(const B3DHomPoint & rPnt) const282 		bool operator==( const B3DHomPoint& rPnt ) const
283 		{
284 			implTestAndHomogenize();
285 			return (maTuple == rPnt.maTuple);
286 		}
287 
operator !=(const B3DHomPoint & rPnt) const288 		bool operator!=( const B3DHomPoint& rPnt ) const
289 		{
290 			implTestAndHomogenize();
291 			return (maTuple != rPnt.maTuple);
292 		}
293 
operator =(const B3DHomPoint & rPnt)294 		B3DHomPoint& operator=( const B3DHomPoint& rPnt )
295 		{
296 			maTuple = rPnt.maTuple;
297 			mfW = rPnt.mfW;
298 			return *this;
299 		}
300 	};
301 
302 	// external operators
303 	//////////////////////////////////////////////////////////////////////////
304 
minimum(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)305 	inline B3DHomPoint minimum(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB)
306 	{
307         return B3DHomPoint( // getX()/getY()/getZ() homogenizes already
308             std::min(rVecB.getX(), rVecA.getX()),
309             std::min(rVecB.getY(), rVecA.getY()),
310             std::min(rVecB.getZ(), rVecA.getZ()));
311 	}
312 
maximum(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)313 	inline B3DHomPoint maximum(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB)
314 	{
315         return B3DHomPoint(// getX()/getY()/getZ() homogenizes already
316             std::max(rVecB.getX(), rVecA.getX()),
317             std::max(rVecB.getY(), rVecA.getY()),
318             std::max(rVecB.getZ(), rVecA.getZ()));
319 	}
320 
absolute(const B3DHomPoint & rVec)321 	inline B3DHomPoint absolute(const B3DHomPoint& rVec)
322 	{
323         return B3DHomPoint(// getX()/getY()/getZ() homogenizes already
324             fabs(rVec.getX()),
325             fabs(rVec.getY()),
326             fabs(rVec.getZ()));
327 	}
328 
interpolate(B3DHomPoint & rOld1,B3DHomPoint & rOld2,double t)329 	inline B3DHomPoint interpolate(B3DHomPoint& rOld1, B3DHomPoint& rOld2, double t)
330 	{
331         if(0.0 >= t)
332         {
333             return rOld1;
334         }
335         else if(1.0 <= t)
336         {
337             return rOld2;
338         }
339         else if(rOld1 == rOld2) // this call homogenizes already
340         {
341             return rOld1;
342         }
343         else
344         {
345             return B3DHomPoint(
346                 ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(),
347                 ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(),
348                 ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ());
349         }
350 	}
351 
average(B3DHomPoint & rOld1,B3DHomPoint & rOld2)352 	inline B3DHomPoint average(B3DHomPoint& rOld1, B3DHomPoint& rOld2)
353 	{
354         return B3DHomPoint( // getX()/getY()/getZ() homogenizes already
355             rOld1.getX() == rOld2.getX() ? rOld1.getX() : (rOld1.getX() + rOld2.getX()) * 0.5,
356             rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5,
357             rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5);
358 	}
359 
average(B3DHomPoint & rOld1,B3DHomPoint & rOld2,B3DHomPoint & rOld3)360 	inline B3DHomPoint average(B3DHomPoint& rOld1, B3DHomPoint& rOld2, B3DHomPoint& rOld3)
361 	{
362         return B3DHomPoint( // getX()/getY()/getZ() homogenizes already
363             (rOld1.getX() == rOld2.getX() && rOld2.getX() == rOld3.getX()) ? rOld1.getX() : (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0),
364             (rOld1.getY() == rOld2.getY() && rOld2.getY() == rOld3.getY()) ? rOld1.getY() : (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0),
365             (rOld1.getZ() == rOld2.getZ() && rOld2.getZ() == rOld3.getZ()) ? rOld1.getZ() : (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0));
366 	}
367 
operator +(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)368 	inline B3DHomPoint operator+(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB)
369 	{
370 		B3DHomPoint aSum(rVecA);
371 		aSum += rVecB;
372 		return aSum;
373 	}
374 
operator -(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)375 	inline B3DHomPoint operator-(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB)
376 	{
377 		B3DHomPoint aSub(rVecA);
378 		aSub -= rVecB;
379 		return aSub;
380 	}
381 
operator *(const B3DHomPoint & rVec,double t)382 	inline B3DHomPoint operator*(const B3DHomPoint& rVec, double t)
383 	{
384 		B3DHomPoint aNew(rVec);
385 		aNew *= t;
386 		return aNew;
387 	}
388 
operator *(double t,const B3DHomPoint & rVec)389 	inline B3DHomPoint operator*(double t, const B3DHomPoint& rVec)
390 	{
391 		B3DHomPoint aNew(rVec);
392 		aNew *= t;
393 		return aNew;
394 	}
395 
operator /(const B3DHomPoint & rVec,double t)396 	inline B3DHomPoint operator/(const B3DHomPoint& rVec, double t)
397 	{
398 		B3DHomPoint aNew(rVec);
399 		aNew /= t;
400 		return aNew;
401 	}
402 
operator /(double t,const B3DHomPoint & rVec)403 	inline B3DHomPoint operator/(double t, const B3DHomPoint& rVec)
404 	{
405 		B3DHomPoint aNew(rVec);
406 		aNew /= t;
407 		return aNew;
408 	}
409 } // end of namespace basegfx
410 
411 #endif /* _BGFX_POINT_B3DHOMPOINT_HXX */
412