1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #pragma once
21 
22 #include <basegfx/tuple/b3dtuple.hxx>
23 #include <basegfx/basegfxdllapi.h>
24 
25 namespace basegfx
26 {
27     class B3DHomMatrix;
28 
29     /** Base Point class with three double values
30 
31         This class derives all operators and common handling for
32         a 3D data class from B3DTuple. All necessary extensions
33         which are special for 3D Vectors are added here.
34 
35         @see B3DTuple
36     */
37     class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC B3DVector : public ::basegfx::B3DTuple
38     {
39     public:
40         /** Create a 3D Vector
41 
42             The vector is initialized to (0.0, 0.0, 0.0)
43         */
B3DVector()44         B3DVector()
45         :   B3DTuple()
46         {}
47 
48         /** Create a 3D Vector
49 
50             @param fX
51             This parameter is used to initialize the X-coordinate
52             of the 3D Vector.
53 
54             @param fY
55             This parameter is used to initialize the Y-coordinate
56             of the 3D Vector.
57 
58             @param fZ
59             This parameter is used to initialize the Z-coordinate
60             of the 3D Vector.
61         */
B3DVector(double fX,double fY,double fZ)62         B3DVector(double fX, double fY, double fZ)
63         :   B3DTuple(fX, fY, fZ)
64         {}
65 
66         /** constructor with tuple to allow copy-constructing
67             from B3DTuple-based classes
68         */
B3DVector(const::basegfx::B3DTuple & rTuple)69         B3DVector(const ::basegfx::B3DTuple& rTuple)
70         :   B3DTuple(rTuple)
71         {}
72 
73         /** *=operator to allow usage from B3DVector, too
74         */
operator *=(const B3DVector & rPnt)75         B3DVector& operator*=( const B3DVector& rPnt )
76         {
77             mfX *= rPnt.mfX;
78             mfY *= rPnt.mfY;
79             mfZ *= rPnt.mfZ;
80             return *this;
81         }
82 
83         /** *=operator to allow usage from B3DVector, too
84         */
operator *=(double t)85         B3DVector& operator*=(double t)
86         {
87             mfX *= t;
88             mfY *= t;
89             mfZ *= t;
90             return *this;
91         }
92 
93         /** assignment operator to allow assigning the results
94             of B3DTuple calculations
95         */
operator =(const::basegfx::B3DTuple & rVec)96         B3DVector& operator=( const ::basegfx::B3DTuple& rVec )
97         {
98             mfX = rVec.getX();
99             mfY = rVec.getY();
100             mfZ = rVec.getZ();
101             return *this;
102         }
103 
104         /** Calculate the length of this 3D Vector
105 
106             @return The Length of the 3D Vector
107         */
getLength() const108         double getLength() const
109         {
110             double fLen(scalar(*this));
111             if((0.0 == fLen) || (1.0 == fLen))
112                 return fLen;
113             return sqrt(fLen);
114         }
115 
116         /** Calculate the length in the XZ-Plane for this 3D Vector
117 
118             @return The XZ-Plane Length of the 3D Vector
119         */
getXZLength() const120         double getXZLength() const
121         {
122             double fLen((mfX * mfX) + (mfZ * mfZ)); // #i73040#
123             if((0.0 == fLen) || (1.0 == fLen))
124                 return fLen;
125             return sqrt(fLen);
126         }
127 
128         /** Calculate the length in the YZ-Plane for this 3D Vector
129 
130             @return The YZ-Plane Length of the 3D Vector
131         */
getYZLength() const132         double getYZLength() const
133         {
134             double fLen((mfY * mfY) + (mfZ * mfZ));
135             if((0.0 == fLen) || (1.0 == fLen))
136                 return fLen;
137             return sqrt(fLen);
138         }
139 
140         /** Set the length of this 3D Vector
141 
142             @param fLen
143             The to be achieved length of the 3D Vector
144         */
setLength(double fLen)145         B3DVector& setLength(double fLen)
146         {
147             double fLenNow(scalar(*this));
148 
149             if(!::basegfx::fTools::equalZero(fLenNow))
150             {
151                 const double fOne(1.0);
152 
153                 if(!::basegfx::fTools::equal(fOne, fLenNow))
154                 {
155                     fLen /= sqrt(fLenNow);
156                 }
157 
158                 mfX *= fLen;
159                 mfY *= fLen;
160                 mfZ *= fLen;
161             }
162 
163             return *this;
164         }
165 
166         /** Normalize this 3D Vector
167 
168             The length of the 3D Vector is set to 1.0
169         */
170         B3DVector& normalize();
171 
172         /** get a 3D Vector which is perpendicular to this and a given 3D Vector
173 
174             @attention This only works if this and the given 3D Vector are
175             both normalized.
176 
177             @param rNormalizedVec
178             A normalized 3D Vector.
179 
180             @return
181             A 3D Vector perpendicular to this and the given one
182         */
183         B3DVector getPerpendicular(const B3DVector& rNormalizedVec) const;
184 
185         /** Calculate the Scalar product
186 
187             This method calculates the Scalar product between this
188             and the given 3D Vector.
189 
190             @param rVec
191             A second 3D Vector.
192 
193             @return
194             The Scalar Product of two 3D Vectors
195         */
scalar(const B3DVector & rVec) const196         double scalar(const B3DVector& rVec) const
197         {
198             return ((mfX * rVec.mfX) + (mfY * rVec.mfY) + (mfZ * rVec.mfZ));
199         }
200 
201         /** Transform vector by given transformation matrix.
202 
203             Since this is a vector, translational components of the
204             matrix are disregarded.
205         */
206         B3DVector& operator*=( const B3DHomMatrix& rMat );
207 
getEmptyVector()208         static const B3DVector& getEmptyVector()
209         {
210             return static_cast<const B3DVector&>( ::basegfx::B3DTuple::getEmptyTuple() );
211         }
212     };
213 
214     // external operators
215 
216 
217     /** Test two vectors which need not to be normalized for parallelism
218 
219         @param rVecA
220         The first 3D Vector
221 
222         @param rVecB
223         The second 3D Vector
224 
225         @return
226         bool if the two values are parallel. Also true if
227         one of the vectors is empty.
228     */
229     BASEGFX_DLLPUBLIC bool areParallel( const B3DVector& rVecA, const B3DVector& rVecB );
230 
231     /** Transform vector by given transformation matrix.
232 
233         Since this is a vector, translational components of the
234         matrix are disregarded.
235     */
236     BASEGFX_DLLPUBLIC B3DVector operator*( const B3DHomMatrix& rMat, const B3DVector& rVec );
237 
238     /** Calculate the Cross Product of two 3D Vectors
239 
240         @param rVecA
241         A first 3D Vector.
242 
243         @param rVecB
244         A second 3D Vector.
245 
246         @return
247         The Cross Product of both 3D Vectors
248     */
cross(const B3DVector & rVecA,const B3DVector & rVecB)249     inline B3DVector cross(const B3DVector& rVecA, const B3DVector& rVecB)
250     {
251         B3DVector aVec(
252             rVecA.getY() * rVecB.getZ() - rVecA.getZ() * rVecB.getY(),
253             rVecA.getZ() * rVecB.getX() - rVecA.getX() * rVecB.getZ(),
254             rVecA.getX() * rVecB.getY() - rVecA.getY() * rVecB.getX());
255         return aVec;
256     }
257 } // end of namespace basegfx
258 
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
260