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_VECTOR_B3DVECTOR_HXX
25 #define _BGFX_VECTOR_B3DVECTOR_HXX
26 
27 #include <basegfx/tuple/b3dtuple.hxx>
28 #include <basegfx/basegfxdllapi.h>
29 
30 //////////////////////////////////////////////////////////////////////////////
31 
32 namespace basegfx
33 {
34 	// predeclaration
35 	class B3DHomMatrix;
36 
37 	/** Base Point class with three double values
38 
39 		This class derives all operators and common handling for
40 		a 3D data class from B3DTuple. All necessary extensions
41 		which are special for 3D Vectors are added here.
42 
43 		@see B3DTuple
44 	*/
45 	class BASEGFX_DLLPUBLIC B3DVector : public ::basegfx::B3DTuple
46 	{
47 	public:
48 		/**	Create a 3D Vector
49 
50         	The vector is initialized to (0.0, 0.0, 0.0)
51 		*/
B3DVector()52 		B3DVector()
53 		:	B3DTuple()
54 		{}
55 
56 		/**	Create a 3D Vector
57 
58 			@param fX
59 			This parameter is used to initialize the X-coordinate
60 			of the 3D Vector.
61 
62 			@param fY
63 			This parameter is used to initialize the Y-coordinate
64 			of the 3D Vector.
65 
66 			@param fZ
67 			This parameter is used to initialize the Z-coordinate
68 			of the 3D Vector.
69 		*/
B3DVector(double fX,double fY,double fZ)70 		B3DVector(double fX, double fY, double fZ)
71 		:	B3DTuple(fX, fY, fZ)
72 		{}
73 
74 		/**	Create a copy of a 3D Vector
75 
76 			@param rVec
77 			The 3D Vector which will be copied.
78 		*/
B3DVector(const B3DVector & rVec)79 		B3DVector(const B3DVector& rVec)
80 		:	B3DTuple(rVec)
81 		{}
82 
83 		/** constructor with tuple to allow copy-constructing
84 			from B3DTuple-based classes
85 		*/
B3DVector(const::basegfx::B3DTuple & rTuple)86 		B3DVector(const ::basegfx::B3DTuple& rTuple)
87 		:	B3DTuple(rTuple)
88 		{}
89 
~B3DVector()90 		~B3DVector()
91 		{}
92 
93 		/** *=operator to allow usage from B3DVector, too
94 		*/
operator *=(const B3DVector & rPnt)95 		B3DVector& operator*=( const B3DVector& rPnt )
96 		{
97 			mfX *= rPnt.mfX;
98 			mfY *= rPnt.mfY;
99 			mfZ *= rPnt.mfZ;
100 			return *this;
101 		}
102 
103 		/** *=operator to allow usage from B3DVector, too
104 		*/
operator *=(double t)105 		B3DVector& operator*=(double t)
106 		{
107 			mfX *= t;
108 			mfY *= t;
109 			mfZ *= t;
110 			return *this;
111 		}
112 
113 		/** assignment operator to allow assigning the results
114 			of B3DTuple calculations
115 		*/
operator =(const::basegfx::B3DTuple & rVec)116 		B3DVector& operator=( const ::basegfx::B3DTuple& rVec )
117 		{
118 			mfX = rVec.getX();
119 			mfY = rVec.getY();
120 			mfZ = rVec.getZ();
121 			return *this;
122 		}
123 
124 		/** Calculate the length of this 3D Vector
125 
126 			@return The Length of the 3D Vector
127 		*/
getLength(void) const128 		double getLength(void) const
129 		{
130 			double fLen(scalar(*this));
131 			if((0.0 == fLen) || (1.0 == fLen))
132 				return fLen;
133 			return sqrt(fLen);
134 		}
135 
136 		/** Calculate the length in the XY-Plane for this 3D Vector
137 
138 			@return The XY-Plane Length of the 3D Vector
139 		*/
getXYLength(void) const140 		double getXYLength(void) const
141 		{
142 			double fLen((mfX * mfX) + (mfY * mfY));
143 			if((0.0 == fLen) || (1.0 == fLen))
144 				return fLen;
145 			return sqrt(fLen);
146 		}
147 
148 		/** Calculate the length in the XZ-Plane for this 3D Vector
149 
150 			@return The XZ-Plane Length of the 3D Vector
151 		*/
getXZLength(void) const152 		double getXZLength(void) const
153 		{
154 			double fLen((mfX * mfX) + (mfZ * mfZ)); // #i73040#
155 			if((0.0 == fLen) || (1.0 == fLen))
156 				return fLen;
157 			return sqrt(fLen);
158 		}
159 
160 		/** Calculate the length in the YZ-Plane for this 3D Vector
161 
162 			@return The YZ-Plane Length of the 3D Vector
163 		*/
getYZLength(void) const164 		double getYZLength(void) const
165 		{
166 			double fLen((mfY * mfY) + (mfZ * mfZ));
167 			if((0.0 == fLen) || (1.0 == fLen))
168 				return fLen;
169 			return sqrt(fLen);
170 		}
171 
172 		/** Set the length of this 3D Vector
173 
174 			@param fLen
175 			The to be achieved length of the 3D Vector
176 		*/
setLength(double fLen)177 		B3DVector& setLength(double fLen)
178 		{
179 			double fLenNow(scalar(*this));
180 
181 			if(!::basegfx::fTools::equalZero(fLenNow))
182 			{
183 				const double fOne(1.0);
184 
185 				if(!::basegfx::fTools::equal(fOne, fLenNow))
186 				{
187 					fLen /= sqrt(fLenNow);
188 				}
189 
190 				mfX *= fLen;
191 				mfY *= fLen;
192 				mfZ *= fLen;
193 			}
194 
195 			return *this;
196 		}
197 
198 		/** Normalize this 3D Vector
199 
200 			The length of the 3D Vector is set to 1.0
201 		*/
202 		B3DVector& normalize();
203 
204 		/** Test if this 3D Vector is normalized
205 
206 			@return
207 			true if lenth of vector is equal to 1.0
208 			false else
209 		*/
isNormalized() const210 		bool isNormalized() const
211 		{
212 			const double fOne(1.0);
213 			const double fScalar(scalar(*this));
214 
215 			return (::basegfx::fTools::equal(fOne, fScalar));
216 		}
217 
218 		/** get a 3D Vector which is perpendicular to this and a given 3D Vector
219 
220 			@attention This only works if this and the given 3D Vector are
221 			both normalized.
222 
223 			@param rNormalizedVec
224 			A normalized 3D Vector.
225 
226 			@return
227 			A 3D Vector perpendicular to this and the given one
228 		*/
229 		B3DVector getPerpendicular(const B3DVector& rNormalizedVec) const;
230 
231 		/** get the projection of this Vector on the given Plane
232 
233 			@attention This only works if the given 3D Vector defining
234 			the Plane is normalized.
235 
236 			@param rNormalizedPlane
237 			A normalized 3D Vector defining a Plane.
238 
239 			@return
240 			The projected 3D Vector
241 		*/
242 		B3DVector getProjectionOnPlane(const B3DVector& rNormalizedPlane) const;
243 
244 		/** Calculate the Scalar product
245 
246 			This method calculates the Scalar product between this
247 			and the given 3D Vector.
248 
249 			@param rVec
250 			A second 3D Vector.
251 
252 			@return
253 			The Scalar Product of two 3D Vectors
254 		*/
scalar(const B3DVector & rVec) const255 		double scalar(const B3DVector& rVec) const
256 		{
257 			return ((mfX * rVec.mfX) + (mfY * rVec.mfY) + (mfZ * rVec.mfZ));
258 		}
259 
260 		/** Transform vector by given transformation matrix.
261 
262         	Since this is a vector, translational components of the
263         	matrix are disregarded.
264 		*/
265 		B3DVector& operator*=( const B3DHomMatrix& rMat );
266 
getEmptyVector()267 		static const B3DVector& getEmptyVector()
268 		{
269 			return (const B3DVector&) ::basegfx::B3DTuple::getEmptyTuple();
270 		}
271 	};
272 
273 	// external operators
274 	//////////////////////////////////////////////////////////////////////////
275 
276 	/** get a 3D Vector which is in 2D (ignoring
277 		the Z-Coordinate) perpendicular to a given 3D Vector
278 
279 		@attention This only works if the given 3D Vector is normalized.
280 
281 		@param rNormalizedVec
282 		A normalized 3D Vector.
283 
284 		@return
285 		A 3D Vector perpendicular to the given one in X,Y (2D).
286 	*/
getPerpendicular2D(const B3DVector & rNormalizedVec)287 	inline B3DVector getPerpendicular2D( const B3DVector& rNormalizedVec )
288 	{
289 		B3DVector aPerpendicular(-rNormalizedVec.getY(), rNormalizedVec.getX(), rNormalizedVec.getZ());
290 		return aPerpendicular;
291 	}
292 
293 	/** Test two vectors which need not to be normalized for parallelism
294 
295 		@param rVecA
296 		The first 3D Vector
297 
298 		@param rVecB
299 		The second 3D Vector
300 
301 		@return
302 		bool if the two values are parallel. Also true if
303 		one of the vectors is empty.
304 	*/
305 	BASEGFX_DLLPUBLIC bool areParallel( const B3DVector& rVecA, const B3DVector& rVecB );
306 
307 	/** Transform vector by given transformation matrix.
308 
309 		Since this is a vector, translational components of the
310     	matrix are disregarded.
311 	*/
312 	BASEGFX_DLLPUBLIC B3DVector operator*( const B3DHomMatrix& rMat, const B3DVector& rVec );
313 
314 	/** Calculate the Cross Product of two 3D Vectors
315 
316 		@param rVecA
317 		A first 3D Vector.
318 
319 		@param rVecB
320 		A second 3D Vector.
321 
322 		@return
323 		The Cross Product of both 3D Vectors
324 	*/
cross(const B3DVector & rVecA,const B3DVector & rVecB)325 	inline B3DVector cross(const B3DVector& rVecA, const B3DVector& rVecB)
326 	{
327 		B3DVector aVec(
328 			rVecA.getY() * rVecB.getZ() - rVecA.getZ() * rVecB.getY(),
329 			rVecA.getZ() * rVecB.getX() - rVecA.getX() * rVecB.getZ(),
330 			rVecA.getX() * rVecB.getY() - rVecA.getY() * rVecB.getX());
331 		return aVec;
332 	}
333 } // end of namespace basegfx
334 
335 //////////////////////////////////////////////////////////////////////////////
336 
337 #endif /* _BGFX_VECTOR_B3DVECTOR_HXX */
338