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