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