xref: /trunk/main/basegfx/inc/basegfx/point/b2dhompoint.hxx (revision 914d351e5f5b84e4342a86d6ab8d4aca7308b9bd)
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