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