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