xref: /AOO41X/main/basegfx/inc/basegfx/point/b2dhompoint.hxx (revision 7024eca93be2e0c3654aa8f286feedace76da6ff)
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