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