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_B2DHOMPOINT_HXX
25 #define _BGFX_POINT_B2DHOMPOINT_HXX
26 
27 #include <basegfx/point/b2dpoint.hxx>
28 #include <basegfx/basegfxdllapi.h>
29 
30 namespace basegfx
31 {
32 	/** Basic homogen Point class with two double values and one homogen factor
33 
34 		This class provides access to homogen coordinates in 2D.
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 B2DTuple
44 	*/
45 	class BASEGFX_DLLPUBLIC B2DHomPoint
46 	{
47 	protected:
48 		/// This member contains the coordinate part of the point
49 		::basegfx::B2DTuple					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 		inline bool implIsHomogenized() const
59 	    {
60 		    const double fOne(1.0);
61 		    return ::basegfx::fTools::equal(fOne, mfW);
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 		inline void implTestAndHomogenize() const
83 	    {
84 		    if(!implIsHomogenized())
85 			    ((B2DHomPoint*)this)->implHomogenize();
86 	    }
87 
88 	public:
89 		/**	Create a homogen point
90 
91         	The point is initialized to (0.0, 0.0)
92 		*/
B2DHomPoint()93 		B2DHomPoint()
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 		*/
B2DHomPoint(double fX,double fY)108 		B2DHomPoint(double fX, double fY)
109 		:	maTuple(fX, fY),
110 			mfW(1.0)
111 		{}
112 
113 		/**	Create a copy of a 2D Point
114 
115 			@param rVec
116 			The 2D point which will be copied. The homogenous part
117 			is initialized to 1.0.
118 		*/
B2DHomPoint(const B2DPoint & rVec)119 		B2DHomPoint(const B2DPoint& rVec)
120 		:	maTuple(rVec),
121 			mfW(1.0)
122 		{}
123 
124 		/**	Create a copy of a homogen point
125 
126 			@param rVec
127 			The homogen point which will be copied. The homogenous part
128 			is copied, too.
129 		*/
B2DHomPoint(const B2DHomPoint & rVec)130 		B2DHomPoint(const B2DHomPoint& rVec)
131 		:	maTuple(rVec.maTuple.getX(), rVec.maTuple.getY()),
132 			mfW(rVec.mfW)
133 		{}
134 
~B2DHomPoint()135 		~B2DHomPoint()
136 		{}
137 
138 		/**	Get a 2D point from this homogenous point
139 
140 			This method normalizes this homogen point if necessary and
141 			returns the corresponding 2D point for this homogen point.
142 
143 			@attention Even when this method is const it may change all
144 			members of this instance.
145 		*/
getB2DPoint() const146 		inline B2DPoint getB2DPoint() const
147 	    {
148 		    implTestAndHomogenize();
149 		    return B2DPoint(maTuple.getX(), maTuple.getY());
150 	    }
151 
152 		/**	Get X-coordinate
153 
154 			This method normalizes this homogen point if necessary and
155 			returns the corresponding X-coordinate for this homogen point.
156 
157 			@attention Even when this method is const it may change all
158 			members of this instance.
159 		*/
getX() const160 		inline double getX() const
161 	    {
162 		    implTestAndHomogenize();
163 		    return maTuple.getX();
164 	    }
165 
166 		/**	Get Y-coordinate
167 
168 			This method normalizes this homogen point if necessary and
169 			returns the corresponding Y-coordinate for this homogen point.
170 
171 			@attention Even when this method is const it may change all
172 			members of this instance.
173 		*/
getY() const174 		inline double getY() const
175 	    {
176 		    implTestAndHomogenize();
177 		    return maTuple.getY();
178 	    }
179 
180 		/**	Set X-coordinate of the homogen point.
181 
182 			This method sets the X-coordinate of the homogen point. If
183 			the point does have a homogenous part this is taken into account.
184 
185 			@param fX
186 			The to-be-set X-coordinate without homogenous part.
187 		*/
setX(double fX)188 		inline void setX(double fX)
189 	    {
190 		    maTuple.setX(implIsHomogenized() ? fX : fX * mfW );
191 	    }
192 
193 		/**	Set Y-coordinate of the homogen point.
194 
195 			This method sets the Y-coordinate of the homogen point. If
196 			the point does have a homogenous part this is taken into account.
197 
198 			@param fY
199 			The to-be-set Y-coordinate without homogenous part.
200 		*/
setY(double fY)201 		inline void setY(double fY)
202 	    {
203 		    maTuple.setY(implIsHomogenized() ? fY : fY * mfW );
204 	    }
205 
206 		// operators
207 		//////////////////////////////////////////////////////////////////////
208 
operator +=(const B2DHomPoint & rPnt)209 		inline B2DHomPoint& operator+=( const B2DHomPoint& rPnt )
210 	    {
211 		    maTuple.setX(getX() * rPnt.mfW + rPnt.getX() * mfW);
212 		    maTuple.setY(getY() * rPnt.mfW + rPnt.getY() * mfW);
213 		    mfW = mfW * rPnt.mfW;
214 
215 		    return *this;
216 	    }
217 
operator -=(const B2DHomPoint & rPnt)218 		inline B2DHomPoint& operator-=( const B2DHomPoint& rPnt )
219 	    {
220 		    maTuple.setX(getX() * rPnt.mfW - rPnt.getX() * mfW);
221 		    maTuple.setY(getY() * rPnt.mfW - rPnt.getY() * mfW);
222 		    mfW = mfW * rPnt.mfW;
223 
224 		    return *this;
225 	    }
226 
operator *=(double t)227 		inline B2DHomPoint& operator*=(double t)
228 	    {
229 		    if(!::basegfx::fTools::equalZero(t))
230 		    {
231 			    mfW /= t;
232 		    }
233 
234 		    return *this;
235 	    }
236 
237 		B2DHomPoint& operator*=( const B2DHomMatrix& rMat );
238 
operator /=(double t)239 		inline B2DHomPoint& operator/=(double t)
240 	    {
241 		    mfW *= t;
242 		    return *this;
243 	    }
244 
operator -(void)245 		inline B2DHomPoint& operator-(void)
246 	    {
247 		    mfW = -mfW;
248 		    return *this;
249 	    }
250 
operator ==(const B2DHomPoint & rPnt) const251 		inline bool operator==( const B2DHomPoint& rPnt ) const
252 	    {
253 		    implTestAndHomogenize();
254 		    return (maTuple == rPnt.maTuple);
255 	    }
256 
operator !=(const B2DHomPoint & rPnt) const257 		inline bool operator!=( const B2DHomPoint& rPnt ) const
258 	    {
259 		    implTestAndHomogenize();
260 		    return (maTuple != rPnt.maTuple);
261 	    }
262 
operator =(const B2DHomPoint & rPnt)263 		inline B2DHomPoint& operator=( const B2DHomPoint& rPnt )
264 	    {
265 		    maTuple = rPnt.maTuple;
266 		    mfW = rPnt.mfW;
267 		    return *this;
268 	    }
269 	};
270 
271 	// external operators
272 	//////////////////////////////////////////////////////////////////////////
273 
minimum(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)274 	inline B2DHomPoint minimum(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB)
275 	{
276         return B2DHomPoint( // getX()/getY() homogenizes already
277             std::min(rVecB.getX(), rVecA.getX()),
278             std::min(rVecB.getY(), rVecA.getY()));
279 	}
280 
maximum(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)281 	inline B2DHomPoint maximum(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB)
282 	{
283         return B2DHomPoint( // getX()/getY() homogenizes already
284             std::max(rVecB.getX(), rVecA.getX()),
285             std::max(rVecB.getY(), rVecA.getY()));
286 	}
287 
absolute(const B2DHomPoint & rVec)288 	inline B2DHomPoint absolute(const B2DHomPoint& rVec)
289 	{
290         return B2DHomPoint( // getX()/getY() homogenizes already
291             fabs(rVec.getX()),
292             fabs(rVec.getY()));
293 	}
294 
interpolate(B2DHomPoint & rOld1,B2DHomPoint & rOld2,double t)295 	inline B2DHomPoint interpolate(B2DHomPoint& rOld1, B2DHomPoint& rOld2, double t)
296 	{
297         if(0.0 >= t)
298         {
299             return rOld1;
300         }
301         else if(1.0 <= t)
302         {
303             return rOld2;
304         }
305         else if(rOld1 == rOld2) // this call homogenizes already
306         {
307             return rOld1;
308         }
309         else
310         {
311 		    return B2DHomPoint(
312 			    ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(),
313 			    ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY());
314         }
315 	}
316 
average(B2DHomPoint & rOld1,B2DHomPoint & rOld2)317 	inline B2DHomPoint average(B2DHomPoint& rOld1, B2DHomPoint& rOld2)
318 	{
319         return B2DHomPoint( // getX()/ getY() homogenizes already
320             rOld1.getX() == rOld2.getX() ? rOld1.getX() : (rOld1.getX() + rOld2.getX()) * 0.5,
321             rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5);
322 	}
323 
average(B2DHomPoint & rOld1,B2DHomPoint & rOld2,B2DHomPoint & rOld3)324 	inline B2DHomPoint average(B2DHomPoint& rOld1, B2DHomPoint& rOld2, B2DHomPoint& rOld3)
325 	{
326         return B2DHomPoint( // getX()/ getY() homogenizes already
327             (rOld1.getX() == rOld2.getX() && rOld2.getX() == rOld3.getX()) ? rOld1.getX() : (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0),
328             (rOld1.getY() == rOld2.getY() && rOld2.getY() == rOld3.getY()) ? rOld1.getY() : (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0));
329 	}
330 
operator +(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)331 	inline B2DHomPoint operator+(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB)
332 	{
333 		B2DHomPoint aSum(rVecA);
334 		aSum += rVecB;
335 		return aSum;
336 	}
337 
operator -(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)338 	inline B2DHomPoint operator-(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB)
339 	{
340 		B2DHomPoint aSub(rVecA);
341 		aSub -= rVecB;
342 		return aSub;
343 	}
344 
operator *(const B2DHomPoint & rVec,double t)345 	inline B2DHomPoint operator*(const B2DHomPoint& rVec, double t)
346 	{
347 		B2DHomPoint aNew(rVec);
348 		aNew *= t;
349 		return aNew;
350 	}
351 
operator *(double t,const B2DHomPoint & rVec)352 	inline B2DHomPoint operator*(double t, const B2DHomPoint& rVec)
353 	{
354 		B2DHomPoint aNew(rVec);
355 		aNew *= t;
356 		return aNew;
357 	}
358 
operator *(const B2DHomMatrix & rMat,const B2DHomPoint & rPoint)359 	inline B2DHomPoint operator*( const B2DHomMatrix& rMat, const B2DHomPoint& rPoint )
360 	{
361 		B2DHomPoint aNew(rPoint);
362 		return aNew*=rMat;
363 	}
364 
operator /(const B2DHomPoint & rVec,double t)365 	inline B2DHomPoint operator/(const B2DHomPoint& rVec, double t)
366 	{
367 		B2DHomPoint aNew(rVec);
368 		aNew /= t;
369 		return aNew;
370 	}
371 
operator /(double t,const B2DHomPoint & rVec)372 	inline B2DHomPoint operator/(double t, const B2DHomPoint& rVec)
373 	{
374 		B2DHomPoint aNew(rVec);
375 		aNew /= t;
376 		return aNew;
377 	}
378 } // end of namespace basegfx
379 
380 #endif /* _BGFX_POINT_B2DHOMPOINT_HXX */
381