1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 #include <Inventor/SbVec4f.h>
34 
35 #include <limits>
36 #include <cassert>
37 
38 #include <Inventor/SbVec4d.h>
39 #include <Inventor/SbVec4b.h>
40 #include <Inventor/SbVec4s.h>
41 #include <Inventor/SbVec4i32.h>
42 #include <Inventor/SbVec3f.h>
43 #if COIN_DEBUG
44 #include <Inventor/errors/SoDebugError.h>
45 #endif // COIN_DEBUG
46 
47 #include "tidbitsp.h" // coin_debug_normalize()
48 
49 /*!
50   \class SbVec4f SbVec4f.h Inventor/SbVec4f.h
51   \brief The SbVec4f class is a 4 dimensional vector with floating point coordinates.
52 
53   \ingroup base
54 
55   This vector class is used by many other classes in
56   Coin. It provides storage for a 3 dimensional homogeneoues
57   vector (with the 4 components usually referred to as <x, y, z, w>)
58   as well as simple floating point arithmetic operations.
59 
60   \sa SbVec2s, SbVec2f, SbVec2d, SbVec3s, SbVec3f, SbVec3d, SbVec4d.
61 */
62 
63 /*!
64   \fn SbVec4f::SbVec4f(void)
65 
66   The default constructor does nothing. The vector coordinates will be
67   uninitialized until a call the setValue().
68 */
69 
70 /*!
71   \fn SbVec4f::SbVec4f(const float v[4])
72   Constructs an SbVec4f instance with initial values from \a v.
73 */
74 
75 /*!
76   \fn SbVec4f::SbVec4f(float x, float y, float z, float w)
77 
78   Constructs an SbVec4f instance with the initial homogeneous vector
79   set to \a <x,y,z,w>.
80 */
81 
82 /*!
83   \fn SbVec4f::SbVec4f(const SbVec4d & v)
84 
85   Constructs an SbVec4f instance from an SbVec4d instance.
86 */
87 
88 /*!
89   \fn SbVec4f::SbVec4f(const SbVec4b & v)
90 
91   Constructs an SbVec4f instance from an SbVec4b instance.
92 
93   \since Coin 2.5
94 */
95 
96 /*!
97   \fn SbVec4f::SbVec4f(const SbVec4s & v)
98 
99   Constructs an SbVec4f instance from an SbVec4s instance.
100 
101   \since Coin 2.5
102 */
103 
104 /*!
105   \fn SbVec4f::SbVec4f(const SbVec4i32 & v)
106 
107   Constructs an SbVec4f instance from an SbVec4i32 instance.
108 
109   \since Coin 2.5
110 */
111 
112 /*!
113   \fn float SbVec4f::dot(const SbVec4f & v) const
114 
115   Calculates and returns the result of taking the dot product of this
116   vector and \a v.
117 */
118 
119 /*!
120   Compares the vector with \a v and returns \c TRUE if the distance
121   between the vectors is smaller or equal to the square root of
122   \a tolerance.
123 
124   The comparison is done in 4D-space, i.e. the \a w component of the
125   vector is \e not used to make x, y and z into Cartesian coordinates
126   first.
127 */
128 SbBool
equals(const SbVec4f & v,float tolerance) const129 SbVec4f::equals(const SbVec4f& v, float tolerance) const
130 {
131 #if COIN_DEBUG
132   if(!(tolerance >= 0.0f))
133     SoDebugError::postWarning("SbVec4f::equals","Tolerance should be >= 0.0f");
134 #endif // COIN_DEBUG
135 
136   float xdist = this->vec[0] - v[0];
137   float ydist = this->vec[1] - v[1];
138   float zdist = this->vec[2] - v[2];
139   float wdist = this->vec[3] - v[3];
140 
141   if((xdist*xdist + ydist*ydist + zdist*zdist + wdist*wdist) <= tolerance)
142     return TRUE;
143   return FALSE;
144 }
145 
146 /*!
147   Returns the vector as a Cartesian 3D vector in \a v. This means that
148   the 3 first components x, y and z will be divided by the fourth, w.
149 */
150 void
getReal(SbVec3f & v) const151 SbVec4f::getReal(SbVec3f & v) const
152 {
153 #if COIN_DEBUG
154   if(!(this->vec[3] != 0.0f))
155     SoDebugError::postWarning("SbVec4f::getReal",
156                               "The 4th vector component is zero => "
157                               "division by zero");
158 #endif // COIN_DEBUG
159 
160   v.setValue(vec[0]/vec[3], vec[1]/vec[3], vec[2]/vec[3]);
161 }
162 
163 /*!
164   \fn const float * SbVec4f::getValue(void) const
165   Returns a pointer to an array of four floats containing the
166   x, y, z and w coordinates of the vector.
167 
168   \sa setValue().
169 */
170 
171 /*!
172   \fn void SbVec4f::getValue(float & x, float & y, float & z, float & w) const
173   Returns the x, y, z and w coordinates of the vector.
174 
175   \sa setValue().
176 */
177 
178 /*!
179   Return the length of the vector in 4D space.
180  */
181 float
length(void) const182 SbVec4f::length(void) const
183 {
184   return static_cast<float>(sqrt(this->sqrLength()));
185 }
186 
187 /*!
188   \fn float SbVec4f::sqrLength(void) const
189   Return the square of the length of the vector in 4D space.
190 */
191 
192 /*!
193   \fn void SbVec4f::negate(void)
194   Negate the vector.
195 */
196 
197 /*!
198   Normalize the vector to unit length. Return value is the original
199   length of the vector before normalization.
200 */
201 
202 float
normalize(void)203 SbVec4f::normalize(void)
204 {
205   float len = this->length();
206   //This number is found by doing some testing, but I suspect it to be a bit to high. BFG
207   static const float NORMALIZATION_TOLERANCE = 1.0/16777216;
208 
209   if (len > 0.0f) {
210     //We don't want to normalize if we are close enough, as we are
211     //probably just going to make things worse
212     if (SbAbs(len-1.0) > NORMALIZATION_TOLERANCE) {
213       operator/=(len);
214     }
215   }
216 #if COIN_DEBUG
217   else if (coin_debug_normalize()) {
218     SoDebugError::postWarning("SbVec4f::normalize",
219                               "The length of the vector should be > 0.0f "
220                               "to be able to normalize.");
221   }
222 #endif // COIN_DEBUG
223 
224   return len;
225 }
226 
227 /*!
228   \fn SbVec4f & SbVec4f::setValue(const float v[4])
229   Set new coordinates for the vector from \a v. Returns reference to
230   self.
231 
232   \sa getValue().
233 */
234 
235 /*!
236   \fn SbVec4f & SbVec4f::setValue(float x, float y, float z, float w)
237 
238   Set new coordinates for the vector. Returns reference to self.
239 
240   \sa getValue().
241 */
242 
243 /*!
244   Sets the value from an SbVec4d instance.
245 */
246 
247 SbVec4f &
setValue(const SbVec4d & v)248 SbVec4f::setValue(const SbVec4d & v)
249 {
250 #if COIN_DEBUG
251   if (v[0] > std::numeric_limits<float>::max() || v[0] < -std::numeric_limits<float>::max() ||
252       v[1] > std::numeric_limits<float>::max() || v[1] < -std::numeric_limits<float>::max() ||
253       v[2] > std::numeric_limits<float>::max() || v[2] < -std::numeric_limits<float>::max()) {
254     SoDebugError::post("SbVec4f::setValue", "SbVec4d argument out of range for SbVec4f storage");
255   }
256 #endif // COIN_DEBUG
257   vec[0] = static_cast<float>(v[0]);
258   vec[1] = static_cast<float>(v[1]);
259   vec[2] = static_cast<float>(v[2]);
260   vec[3] = static_cast<float>(v[3]);
261   return *this;
262 }
263 
264 /*!
265   \since Coin 2.5
266 */
267 
268 SbVec4f &
setValue(const SbVec4b & v)269 SbVec4f::setValue(const SbVec4b & v)
270 {
271   vec[0] = static_cast<float>(v[0]);
272   vec[1] = static_cast<float>(v[1]);
273   vec[2] = static_cast<float>(v[2]);
274   vec[3] = static_cast<float>(v[3]);
275   return *this;
276 }
277 
278 /*!
279   \since Coin 2.5
280 */
281 
282 SbVec4f &
setValue(const SbVec4s & v)283 SbVec4f::setValue(const SbVec4s & v)
284 {
285   vec[0] = static_cast<float>(v[0]);
286   vec[1] = static_cast<float>(v[1]);
287   vec[2] = static_cast<float>(v[2]);
288   vec[3] = static_cast<float>(v[3]);
289   return *this;
290 }
291 
292 /*!
293   \since Coin 2.5
294 */
295 
296 SbVec4f &
setValue(const SbVec4i32 & v)297 SbVec4f::setValue(const SbVec4i32 & v)
298 {
299   vec[0] = static_cast<float>(v[0]);
300   vec[1] = static_cast<float>(v[1]);
301   vec[2] = static_cast<float>(v[2]);
302   vec[3] = static_cast<float>(v[3]);
303   return *this;
304 }
305 
306 /*!
307   \fn float & SbVec4f::operator [] (int i)
308 
309   Index operator. Returns modifiable x, y, z or w component of vector.
310 
311   \sa getValue() and setValue().
312 */
313 
314 /*!
315   \fn const float & SbVec4f::operator [] (int i) const
316 
317   Index operator. Returns x, y, z or w component of vector.
318 
319   \sa getValue() and setValue().
320 */
321 
322 /*!
323   \fn SbVec4f & SbVec4f::operator *= (float d)
324 
325   Multiply components of vector with value \a d. Returns reference to self.
326 */
327 
328 /*!
329   \fn SbVec4f & SbVec4f::operator /= (float d)
330   Divides components of vector with value \a d. Returns reference to self.
331 */
332 
333 /*!
334   \fn SbVec4f & SbVec4f::operator += (const SbVec4f & v)
335 
336   Adds this vector and vector \a v. Returns reference to self.
337 */
338 
339 /*!
340   \fn SbVec4f & SbVec4f::operator -= (const SbVec4f & v)
341 
342   Subtracts vector \a v from this vector. Returns reference to self.
343 */
344 
345 /*!
346   \fn SbVec4f SbVec4f::operator - (void) const
347 
348   Non-destructive negation operator. Returns a new SbVec4f instance which
349   has all components negated.
350 
351   \sa negate().
352 */
353 
354 /*!
355   \fn SbVec4f operator * (const SbVec4f & v, float d)
356   \relates SbVec4f
357 
358   Returns an SbVec4f instance which is the components of vector \a v
359   multiplied with \a d.
360 */
361 
362 /*!
363   \fn SbVec4f operator * (float d, const SbVec4f & v)
364   \relates SbVec4f
365 
366   Returns an SbVec4f instance which is the components of vector \a v
367   multiplied with \a d.
368 */
369 
370 /*!
371   \fn SbVec4f operator / (const SbVec4f & v, float d)
372   \relates SbVec4f
373 
374   Returns an SbVec4f instance which is the components of vector \a v
375   divided on the scalar factor \a d.
376 */
377 
378 /*!
379   \fn SbVec4f operator + (const SbVec4f & v1, const SbVec4f & v2)
380   \relates SbVec4f
381 
382   Returns an SbVec4f instance which is the sum of vectors \a v1 and \a v2.
383 */
384 
385 /*!
386   \fn SbVec4f operator - (const SbVec4f & v1, const SbVec4f & v2)
387   \relates SbVec4f
388 
389   Returns an SbVec4f instance which is vector \a v2 subtracted from
390   vector \a v1.
391 */
392 
393 /*!
394   \fn int operator == (const SbVec4f & v1, const SbVec4f & v2)
395   \relates SbVec4f
396 
397   Returns \a 1 if \a v1 and \a v2 are equal, \a 0 otherwise.
398 
399   \sa equals().
400 */
401 
402 /*!
403   \fn int operator != (const SbVec4f & v1, const SbVec4f & v2)
404   \relates SbVec4f
405 
406   Returns \a 1 if \a v1 and \a v2 are not equal, \a 0 if they are equal.
407 
408   \sa equals().
409 */
410 
411 /*!
412   Dump the state of this object to the \a file stream. Only works in
413   debug version of library, method does nothing in an optimized compile.
414  */
415 void
print(FILE * fp) const416 SbVec4f::print(FILE * fp) const
417 {
418 #if COIN_DEBUG
419   fprintf( fp, "<%f, %f, %f, %f>", this->vec[0], this->vec[1], this->vec[2],
420     this->vec[3] );
421 #endif // COIN_DEBUG
422 }
423 
424 #ifdef COIN_TEST_SUITE
425 
BOOST_AUTO_TEST_CASE(noNormalizingNormalized)426 BOOST_AUTO_TEST_CASE(noNormalizingNormalized)
427 {
428   const float SQRT2 = sqrt(2.f)/2.f;
429   SbVec4f vec(0,-SQRT2,0,SQRT2);
430 
431   vec.normalize();
432   for (int i=0;i<4;++i) {
433     int premultiply = ((i&0x1)*((i&0x2)-1));
434     float testVal = premultiply*SQRT2;
435     BOOST_CHECK_MESSAGE(
436                         testVal==vec[i],
437                         std::string("Wrong value when trying to access value #")
438                         + boost::lexical_cast<std::string>(i)
439                         + ": "
440                         + boost::lexical_cast<std::string>(vec[i]) +
441                         " == "
442                         + boost::lexical_cast<std::string>(testVal)
443                         );
444   }
445 
446 }
447 
BOOST_AUTO_TEST_CASE(normalizingDeNormalized)448 BOOST_AUTO_TEST_CASE(normalizingDeNormalized)
449 {
450   const int FLOAT_SENSITIVITY = 1;
451   const float SQRT2 = sqrt(2.f)/2.f;
452   SbVec4f vec(0,-1,0,1);
453 
454   vec.normalize();
455   for (int i=0;i<4;++i) {
456     int premultiply = ((i&0x1)*((i&0x2)-1));
457     float testVal = premultiply*SQRT2;
458     BOOST_CHECK_MESSAGE(
459                         floatEquals(testVal,vec[i],FLOAT_SENSITIVITY),
460                         std::string("Wrong value when trying to access value #")
461                         + boost::lexical_cast<std::string>(i)
462                         + ": "
463                         + boost::lexical_cast<std::string>(vec[i]) +
464                         " == "
465                         + boost::lexical_cast<std::string>(testVal)
466                         );
467   }
468 
469 }
470 
471 #endif //COIN_TEST_SUITE
472