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