Ocean
Vector3.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_VECTOR3_H
9 #define META_OCEAN_MATH_VECTOR3_H
10 
11 #include "ocean/math/Math.h"
12 #include "ocean/math/Numeric.h"
13 #include "ocean/math/Vector2.h"
14 
15 #include <type_traits>
16 #include <vector>
17 
18 namespace Ocean
19 {
20 
21 // Forward declaration.
22 template <typename T> class VectorT3;
23 
24 /**
25  * Definition of a 3D vector.
26  * @see VectorT3
27  * @ingroup math
28  */
30 
31 /**
32  * Definition of a 3D vector with double values.
33  * @see VectorT3
34  * @ingroup math
35  */
37 
38 /**
39  * Definition of a 3D vector with float values.
40  * @see VectorT3
41  * @ingroup math
42  */
44 
45 /**
46  * Definition of a 3D vector with integer values.
47  * @see VectorT3
48  * @ingroup math
49  */
51 
52 /**
53  * Definition of a typename alias for vectors with VectorT3 objects.
54  * @see VectorT3
55  * @ingroup math
56  */
57 template <typename T>
58 using VectorsT3 = std::vector<VectorT3<T>>;
59 
60 /**
61  * Definition of a vector holding Vector3 objects.
62  * @see Vector3
63  * @ingroup math
64  */
65 typedef std::vector<Vector3> Vectors3;
66 
67 /**
68  * Definition of a vector holding VectorD3 objects.
69  * @see VectorD3
70  * @ingroup math
71  */
72 typedef std::vector<VectorD3> VectorsD3;
73 
74 /**
75  * Definition of a vector holding VectorF3 objects.
76  * @see VectorF3
77  * @ingroup math
78  */
79 typedef std::vector<VectorF3> VectorsF3;
80 
81 /**
82  * Definition of a vector holding VectorI3 objects.
83  * @see VectorI3
84  * @ingroup math
85  */
86 typedef std::vector<VectorI3> VectorsI3;
87 
88 /**
89  * This class implements a vector with three elements.
90  * The element order is: (x, y, z).
91  * @tparam T Data type of the vector elements.
92  * @see Vector3, VectorF3, VectorD3.
93  * @ingroup math
94  */
95 template <typename T>
96 class VectorT3
97 {
98  public:
99 
100  /**
101  * Definition of the used data type.
102  */
103  typedef T Type;
104 
105  public:
106 
107  /**
108  * Creates a new 3D vector with undefined elements.
109  * Beware: The elements are neither zero nor a specific value!
110  * This is useful in situations where VectorT3 objects are created (e.g, by a large array or vector)
111  * and their values are assigned in a function afterwards.
112  */
113  inline VectorT3() noexcept;
114 
115  /**
116  * Creates a new 3D vector.
117  * @param setToHomogeneous Determines whether a homogeneous vector (0, 0, 1) will be created, otherwise the vector is initialized with zeros
118  */
119  inline explicit VectorT3(const bool setToHomogeneous) noexcept;
120 
121  /**
122  * Creates a new 3D vector with three given elements.
123  * @param x X value
124  * @param y Y value
125  * @param z Z value
126  */
127  inline VectorT3(const T& x, const T& y, const T& z) noexcept;
128 
129  /**
130  * Creates a new 3D vector with a given array of elements.
131  * @param valueArray Array with at least three elements
132  */
133  inline explicit VectorT3(const T* valueArray) noexcept;
134 
135  /**
136  * Creates a new 3D vector with a given 2D vector defining the first two elements and a single value defining the third element.
137  * @param vector 2D vector defining the first two elements (X and Y value)
138  * @param z Z value defining the third element
139  */
140  inline explicit VectorT3(const VectorT2<T>& vector, const T& z = 0) noexcept;
141 
142  /**
143  * Copies a vector.
144  * @param vector 3D vector that is copied
145  */
146  inline VectorT3(const VectorT3<T>& vector) noexcept;
147 
148  /**
149  * Copies a vector with different element data type than T.
150  * @param vector The 3D vector to copy
151  * @tparam U The element data type of the second vector
152  */
153  template <typename U>
154  inline explicit VectorT3(const VectorT3<U>& vector) noexcept;
155 
156  /**
157  * Returns the cross product of two vectors.
158  * The cross product of two parallel vectors (or of at least one zero vector) results in a zero vector.
159  * @param vector The right vector
160  * @return The resulting cross product of both vectors
161  * @see isParallel().
162  */
163  inline VectorT3<T> cross(const VectorT3<T>& vector) const;
164 
165  /**
166  * Returns the normalized vector.
167  * Beware: This function does not throw an exception if this vector cannot be normalized.<br>
168  * Thus, ensure that this vector is not zero before calling this function.<br>
169  * Or even better, use different normalization functions like: normalizedOrZero(), normalizedOrValue(), or normalize().<br>
170  * In case, the vector cannot be normalized, an uninitialized vector will be returned (due to performance reasons).
171  * @return This vector as unit vector (vector with length 1)
172  * @see normalizedOrZero(), normalizedOrValue(), normalize().
173  */
174  inline VectorT3<T> normalized() const;
175 
176  /**
177  * Returns the normalized vector.
178  * If this vector cannot be normalized the zero vector is returned.
179  * @return Vector with length 1
180  */
181  inline VectorT3<T> normalizedOrZero() const;
182 
183  /**
184  * Returns the normalized vector.
185  * If this vector cannot be normalized the given vector is returned.
186  * @param value Vector that will be returned if the vector cannot be normalized
187  * @return Vector with length 1
188  */
189  inline VectorT3<T> normalizedOrValue(const VectorT3<T>& value) const;
190 
191  /**
192  * Normalizes this vector
193  * @return True, if the vector could be normalized
194  */
195  inline bool normalize();
196 
197  /**
198  * Returns the length of the vector.
199  * @return Vector length
200  */
201  inline T length() const;
202 
203  /**
204  * Returns the square of the vector length.
205  * @return Square of vector length
206  */
207  inline T sqr() const;
208 
209  /**
210  * Returns the distance between this 3D position and a second 3D position.
211  * @param right Second 3D position
212  * @return Distance between the two points
213  */
214  inline T distance(const VectorT3<T>& right) const;
215 
216  /**
217  * Returns the square distance between this 3D position and a second 3D position.
218  * @param right Second 3D position
219  * @return Square distance between the two points
220  */
221  inline T sqrDistance(const VectorT3<T>& right) const;
222 
223  /**
224  * Returns the angle between this vector and a second vectors.
225  * Beware: This vector must not be zero.<br>
226  * Beware: This function does not throw an exception if one or both vectors are zero.<br>
227  * In case, the angle cannot be determined -1 will be returned.
228  * @param right Second vector, must not be zero
229  * @return Angle between both vectors in radian, with range [0, PI], -1 in case of an error
230  */
231  T angle(const VectorT3<T>& right) const;
232 
233  /**
234  * Returns the reflected vector of this vector corresponding to a given normal vector.
235  * The dot product between this vector and the normal vector must be positive.<br>
236  * @param normal The normal vector used to determine the reflection vector for
237  * @return Resulting reflection vector
238  */
239  VectorT3<T> reflect(const VectorT3<T>& normal) const;
240 
241  /**
242  * Returns the refracted vector of this vector corresponding to a given normal vector.
243  * The dot product between this vector and the normal vector must be positive.<br>
244  * @param normal The normal vector used to determine the refracted vector for
245  * @param index Refraction index that is the ratio between the leaving and the entering refraction index, an index lower than 1 describes the transition from a thin into a thick medium, with range (0, infinity)
246  * @return Resulting refracted vector
247  */
248  VectorT3<T> refract(const VectorT3<T>& normal, const T index) const;
249 
250  /**
251  * Returns a vector that is perpendicular to this vector.
252  * If this vector is a zero vector, than the resulting vector will be arbitrary.
253  * @return Resulting perpendicular vector, a unity vector is not guaranteed
254  */
256 
257  /**
258  * Returns whether two vectors are parallel.
259  * A zero vector will not be parallel.
260  * @param right The right vector
261  * @return True, if so
262  * @see cross().
263  */
264  bool isParallel(const VectorT3<T>& right) const;
265 
266  /**
267  * Returns whether two vectors are orthogonal.
268  * A zero vector will not be orthogonal.
269  * @param right The right vector
270  * @return True, if so
271  */
272  inline bool isOrthogonal(const VectorT3<T>& right) const;
273 
274  /**
275  * Returns the x value.
276  * @return X value
277  */
278  inline const T& x() const noexcept;
279 
280  /**
281  * Returns the x value.
282  * @return X value
283  */
284  inline T& x() noexcept;
285 
286  /**
287  * Returns the y value.
288  * @return Y value
289  */
290  inline const T& y() const noexcept;
291 
292  /**
293  * Returns the y value.
294  * @return Y value
295  */
296  inline T& y() noexcept;
297 
298  /**
299  * Returns the z value.
300  * @return Z value
301  */
302  inline const T& z() const noexcept;
303 
304  /**
305  * Returns the z value.
306  * @return Z value
307  */
308  inline T& z() noexcept;
309 
310  /**
311  * Returns the x and y component of the vector as new 2D vector.
312  * @return New 2D vector
313  */
314  inline VectorT2<T> xy() const noexcept;
315 
316  /**
317  * Returns an pointer to the vector elements.
318  * @return Pointer to elements
319  */
320  inline const T* data() const noexcept;
321 
322  /**
323  * Returns an pointer to the vector elements.
324  * @return Pointer to elements
325  */
326  inline T* data() noexcept;
327 
328  /**
329  * Returns whether this vector is a null vector up to a small epsilon.
330  * @return True, if so
331  */
332  inline bool isNull() const;
333 
334  /**
335  * Returns whether this vector is a unit vector (whether the vector has the length 1).
336  * @param eps Epsilon to be used, with range [0, infinity)
337  * @return True, if so
338  */
339  inline bool isUnit(const T eps = NumericT<T>::eps()) const;
340 
341  /**
342  * Returns whether two vectors are equal up to a specified epsilon.
343  * @param vector Second vector
344  * @param eps Epsilon to be used
345  * @return True, if so
346  */
347  inline bool isEqual(const VectorT3<T>& vector, const T eps) const;
348 
349  /**
350  * Copy assigns a vector
351  * @param vector 3D vector that is copied
352  */
353  inline VectorT3& operator=(const VectorT3<T>& vector);
354 
355  /**
356  * Returns whether two vectors are identical up to a small epsilon.
357  * @param vector Right vector
358  * @return True, if so
359  */
360  inline bool operator==(const VectorT3<T>& vector) const;
361 
362  /**
363  * Returns whether two vectors are not identical up to a small epsilon.
364  * @param vector Right vector
365  * @return True, if so
366  */
367  inline bool operator!=(const VectorT3<T>& vector) const;
368 
369  /**
370  * Adds two vectors.
371  * @param vector Right vector
372  * @return Sum vector
373  */
374  inline VectorT3<T> operator+(const VectorT3<T>& vector) const;
375 
376  /**
377  * Adds and assigns two vectors.
378  * @param vector Right vector
379  * @return Reference to this vector
380  */
381  inline VectorT3<T>& operator+=(const VectorT3<T>& vector);
382 
383  /**
384  * Subtracts two vectors.
385  * @param vector Right vector
386  * @return Difference vector
387  */
388  inline VectorT3<T> operator-(const VectorT3<T>& vector) const;
389 
390  /**
391  * Subtracts and assigns two vectors.
392  * @param vector Right vector
393  * @return Reference to this vector
394  */
395  inline VectorT3<T>& operator-=(const VectorT3<T>& vector);
396 
397  /**
398  * Returns the negated vector.
399  * @return Negated vector
400  */
401  inline VectorT3<T> operator-() const;
402 
403  /**
404  * Returns the dot product of two vectors.
405  * @param vector Right vector
406  * @return Dot product
407  */
408  inline T operator*(const VectorT3<T>& vector) const;
409 
410  /**
411  * Multiplies this vector with a scalar.
412  * @param value Scalar value
413  * @return Resulting vector
414  */
415  inline VectorT3<T> operator*(const T& value) const;
416 
417  /**
418  * Multiplies and assigns this vector with a scalar.
419  * @param value Scalar value
420  * @return Reference to this vector
421  */
422  inline VectorT3<T>& operator*=(const T& value);
423 
424  /**
425  * Divides this vector by a scalar.
426  * Beware: This function does not throw an exception if the given value is zero.<br>
427  * Thus, ensure that given value is not zero before calling this function.<br>
428  * In case, the given value is zero, the result is undefined.
429  * @param value Scalar value to be used as denominator, must not be zero
430  * @return Resulting vector
431  */
432  inline VectorT3<T> operator/(const T& value) const;
433 
434  /**
435  * Divides and assigns this vector by a scalar.
436  * Beware: This function does not throw an exception if the given value is zero.<br>
437  * Thus, ensure that given value is not zero before calling this function.<br>
438  * In case, the given value is zero, the result is undefined.
439  * @param value Scalar value to be used as denominator, must not be zero
440  * @return Reference to this vector
441  */
442  inline VectorT3<T>& operator/=(const T& value);
443 
444  /**
445  * Compares two vector objects and returns whether the left vector represents a smaller value than the right vector.
446  * First the first component of both vectors are compared, if these values are equal then the next components are compares and so on.<br>
447  * @param vector The second vector to compare
448  * @return True, if so
449  */
450  inline bool operator<(const VectorT3<T>& vector) const;
451 
452  /**
453  * Element access operator.
454  * @param index The index of the element to access, with range [0, 2]
455  * @return Element of the vector
456  */
457  inline const T& operator[](const unsigned int index) const noexcept;
458 
459  /**
460  * Element access operator.
461  * @param index The index of the element to access, with range [0, 2]
462  * @return Element of the vector
463  */
464  inline T& operator[](const unsigned int index) noexcept;
465 
466  /**
467  * Element access operator.
468  * @param index The index of the element to access, with range [0, 2]
469  * @return Element of the vector
470  */
471  inline const T& operator()(const unsigned int index) const noexcept;
472 
473  /**
474  * Element access operator.
475  * @param index The index of the element to access, with range [0, 2]
476  * @return Element of the vector
477  */
478  inline T& operator()(const unsigned int index) noexcept;
479 
480  /**
481  * Access operator.
482  * @return Pointer to the elements
483  */
484  inline const T* operator()() const noexcept;
485 
486  /**
487  * Access operator.
488  * @return Pointer to the elements
489  */
490  inline T* operator()() noexcept;
491 
492  /**
493  * Hash function.
494  * @param vector The vector for which the hash value will be determined
495  * @return The resulting hash value
496  */
497  inline size_t operator()(const VectorT3<T>& vector) const;
498 
499  /**
500  * Converts vectors with specific data type to vectors with different data type.
501  * @param vectors The vectors to convert
502  * @return The converted vectors
503  * @tparam U The element data type of the vectors to convert
504  */
505  template <typename U>
506  static inline std::vector<VectorT3<T>> vectors2vectors(std::vector<VectorT3<U>>&& vectors);
507 
508  /**
509  * Converts vectors with specific data type to vectors with different data type.
510  * @param vectors The vectors to convert
511  * @return The converted vectors
512  * @tparam U The element data type of the vectors to convert
513  */
514  template <typename U>
515  static inline std::vector<VectorT3<T>> vectors2vectors(const std::vector<VectorT3<U>>& vectors);
516 
517  /**
518  * Converts vectors with specific data type to vectors with different data type.
519  * @param vectors The vectors to convert
520  * @param size The number of vector to convert
521  * @return The converted vectors
522  * @tparam U The element data type of the vectors to convert
523  */
524  template <typename U>
525  static inline std::vector<VectorT3<T>> vectors2vectors(const VectorT3<U>* vectors, const size_t size);
526 
527  protected:
528 
529  /// The three values of the vector, with element order x, y, z.
530  T values_[3];
531 };
532 
533 template <typename T>
534 inline VectorT3<T>::VectorT3() noexcept
535 {
536  static_assert(std::is_arithmetic<T>::value, "VectorT3 only supports arithmetic types");
537  // nothing to do here
538 }
539 
540 template <typename T>
541 inline VectorT3<T>::VectorT3(const bool setToHomogeneous) noexcept
542 {
543  if (setToHomogeneous)
544  {
545  values_[0] = T(0.0);
546  values_[1] = T(0.0);
547  values_[2] = T(1.0);
548  }
549  else
550  {
551  values_[0] = T(0.0);
552  values_[1] = T(0.0);
553  values_[2] = T(0.0);
554  }
555 }
556 
557 template <typename T>
558 inline VectorT3<T>::VectorT3(const T& x, const T& y, const T& z) noexcept
559 {
560  values_[0] = x;
561  values_[1] = y;
562  values_[2] = z;
563 }
564 
565 template <typename T>
566 inline VectorT3<T>::VectorT3(const T* valueArray) noexcept
567 {
568  memcpy(values_, valueArray, sizeof(T) * 3);
569 }
570 
571 template <typename T>
572 inline VectorT3<T>::VectorT3(const VectorT2<T>& vector, const T& z) noexcept
573 {
574  values_[0] = vector[0];
575  values_[1] = vector[1];
576  values_[2] = z;
577 }
578 
579 template <typename T>
580 inline VectorT3<T>::VectorT3(const VectorT3<T>& vector) noexcept
581 {
582  values_[0] = vector.values_[0];
583  values_[1] = vector.values_[1];
584  values_[2] = vector.values_[2];
585 }
586 
587 template <typename T>
588 template <typename U>
589 inline VectorT3<T>::VectorT3(const VectorT3<U>& vector) noexcept
590 {
591  values_[0] = T(vector[0]);
592  values_[1] = T(vector[1]);
593  values_[2] = T(vector[2]);
594 }
595 
596 template <typename T>
597 inline VectorT3<T> VectorT3<T>::cross(const VectorT3<T>& vector) const
598 {
599  return VectorT3<T>(values_[1] * vector.values_[2] - values_[2] * vector.values_[1],
600  values_[2] * vector.values_[0] - values_[0] * vector.values_[2],
601  values_[0] * vector.values_[1] - values_[1] * vector.values_[0]);
602 }
603 
604 template <typename T>
606 {
607  const T len = length();
608  if (NumericT<T>::isEqualEps(len))
609  {
610  ocean_assert(false && "Division by zero!");
611  return VectorT3<T>();
612  }
613 
614  const T factor = T(1) / len;
615  return VectorT3<T>(values_[0] * factor, values_[1] * factor, values_[2] * factor);
616 }
617 
618 template <typename T>
620 {
621  const T len = length();
622 
623  if (NumericT<T>::isEqualEps(len))
624  {
625  return *this;
626  }
627 
628  const T factor = T(1) / len;
629  return VectorT3<T>(values_[0] * factor, values_[1] * factor, values_[2] * factor);
630 }
631 
632 template <typename T>
634 {
635  const T len = length();
636 
637  if (NumericT<T>::isEqualEps(len))
638  {
639  return value;
640  }
641 
642  const T factor = T(1) / len;
643  return VectorT3<T>(values_[0] * factor, values_[1] * factor, values_[2] * factor);
644 }
645 
646 template <typename T>
648 {
649  const T len = length();
650  if (NumericT<T>::isEqualEps(len))
651  {
652  return false;
653  }
654 
655  const T factor = T(1) / len;
656  values_[0] *= factor;
657  values_[1] *= factor;
658  values_[2] *= factor;
659 
660  return true;
661 }
662 
663 template <typename T>
664 inline T VectorT3<T>::length() const
665 {
666  return NumericT<T>::sqrt(values_[0] * values_[0] + values_[1] * values_[1] + values_[2] * values_[2]);
667 }
668 
669 template <typename T>
670 inline T VectorT3<T>::sqr() const
671 {
672  return values_[0] * values_[0] + values_[1] * values_[1] + values_[2] * values_[2];
673 }
674 
675 template <typename T>
676 inline T VectorT3<T>::distance(const VectorT3<T>& right) const
677 {
678  return NumericT<T>::sqrt(NumericT<T>::sqr(values_[0] - right.values_[0]) + NumericT<T>::sqr(values_[1] - right.values_[1]) + NumericT<T>::sqr(values_[2] - right.values_[2]));
679 }
680 
681 template <typename T>
682 inline T VectorT3<T>::sqrDistance(const VectorT3<T>& right) const
683 {
684  return NumericT<T>::sqr(values_[0] - right.values_[0]) + NumericT<T>::sqr(values_[1] - right.values_[1]) + NumericT<T>::sqr(values_[2] - right.values_[2]);
685 }
686 
687 template <typename T>
688 T VectorT3<T>::angle(const VectorT3<T>& right) const
689 {
690  // a * b = cos * |a| * |b|
691  // cos = (a * b) / (|a| * |b|)
692  // we separate the sqrt determinations to receive a higher accuracy
693 
694  const T thisLength = length();
695  const T rightLength = right.length();
696 
697  if (NumericT<T>::isEqualEps(thisLength) || NumericT<T>::isEqualEps(rightLength))
698  {
699  ocean_assert(false && "Invalid vector!");
700  return T(-1);
701  }
702 
703  const T dot = values_[0] * right.values_[0] + values_[1] * right.values_[1] + values_[2] * right.values_[2];
704 
705  return NumericT<T>::acos((dot / thisLength) / rightLength);
706 }
707 
708 template <typename T>
710 {
711  ocean_assert(NumericT<T>::isNotEqualEps(normal.length()));
712  ocean_assert(*this * normal >= 0);
713 
714 #ifdef OCEAN_DEBUG
715  const VectorT3<T> result(normal * ((normal * *this) * 2) - *this);
716  ocean_assert(int(angle(normal) * 100) == int(result.angle(normal) * 100));
717  ocean_assert(result * normal >= 0);
718  ocean_assert(NumericT<T>::isWeakEqual(length(), result.length()));
719 #endif // OCEAN_DEBUG
720 
721  return normal * ((normal * *this) * 2) - *this;
722 }
723 
724 template <typename T>
725 VectorT3<T> VectorT3<T>::refract(const VectorT3<T>& normal, const T index) const
726 {
727  ocean_assert(NumericT<T>::isNotEqualEps(normal.length()));
728  ocean_assert(*this * normal >= 0);
729  ocean_assert(index > T(0));
730 
731  const T dot = normal * *this;
732 
733  const T sqrtValue = T(1) - (index * index) * (T(1) - dot * dot);
734 
735  // check whether a total internal reflection occurs
736  if (sqrtValue < T(0))
737  {
738  return reflect(normal);
739  }
740 
741 #ifdef OCEAN_DEBUG
742  const VectorT3<T> result(normal * (index * dot - NumericT<T>::sqrt(sqrtValue)) - *this * index);
743  const T angle0 = angle(normal);
744  const T angle1 = result.angle(-normal);
745  const T sin0 = NumericT<T>::sin(angle0);
746  const T sin1 = NumericT<T>::sin(angle1);
747  ocean_assert(NumericT<T>::isNotEqualEps(sin1));
748  ocean_assert(NumericT<T>::isWeakEqual(index, sin0 / sin1));
749  ocean_assert(NumericT<T>::isWeakEqual(length(), result.length()));
750 #endif // OCEAN_DEBUG
751 
752  return normal * (index * dot - NumericT<T>::sqrt(T(1) - (index * index) * (T(1) - dot * dot))) - *this * index;
753 }
754 
755 template <typename T>
757 {
759  {
760  return cross(VectorT3<T>(0, 1, 0));
761  }
762 
764  {
765  return cross(VectorT3<T>(1, 0, 0));
766  }
767 
768  ocean_assert(isNull());
769  return VectorT3<T>(1, 0, 0);
770 }
771 
772 template <typename T>
773 bool VectorT3<T>::isParallel(const VectorT3<T>& right) const
774 {
775 #ifdef OCEAN_DEBUG
776  if (std::is_same<double, Scalar>::value)
777  {
778  const VectorT3<T> normalizedThis(normalizedOrZero());
779  const VectorT3<T> normalizedRight(right.normalizedOrZero());
780 
781  const T dotProduct = normalizedThis * normalizedRight;
782 
783  const bool debugResult = NumericT<T>::isEqual(dotProduct, 1) || NumericT<T>::isEqual(dotProduct, -1);
784  const VectorT3<T> crossVector = cross(right);
785 
786  ocean_assert_accuracy(debugResult == (!isNull() && !right.isNull() && crossVector.isNull()));
787  }
788 #endif
789 
790  return !isNull() && !right.isNull() && cross(right).isNull();
791 }
792 
793 template <typename T>
794 inline bool VectorT3<T>::isOrthogonal(const VectorT3<T>& right) const
795 {
796  return NumericT<T>::isEqualEps(values_[0] * right.values_[0] + values_[1] * right.values_[1] + values_[2] * right.values_[2]);
797 }
798 
799 template <typename T>
800 inline const T& VectorT3<T>::x() const noexcept
801 {
802  return values_[0];
803 }
804 
805 template <typename T>
806 inline T& VectorT3<T>::x() noexcept
807 {
808  return values_[0];
809 }
810 
811 template <typename T>
812 inline const T& VectorT3<T>::y() const noexcept
813 {
814  return values_[1];
815 }
816 
817 template <typename T>
818 inline T& VectorT3<T>::y() noexcept
819 {
820  return values_[1];
821 }
822 
823 template <typename T>
824 inline const T& VectorT3<T>::z() const noexcept
825 {
826  return values_[2];
827 }
828 
829 template <typename T>
830 inline T& VectorT3<T>::z() noexcept
831 {
832  return values_[2];
833 }
834 
835 template <typename T>
836 inline VectorT2<T> VectorT3<T>::xy() const noexcept
837 {
838  return VectorT2<T>(values_[0], values_[1]);
839 }
840 
841 template <typename T>
842 inline const T* VectorT3<T>::data() const noexcept
843 {
844  return values_;
845 }
846 
847 template <typename T>
848 inline T* VectorT3<T>::data() noexcept
849 {
850  return values_;
851 }
852 
853 template <typename T>
854 inline bool VectorT3<T>::isNull() const
855 {
858 }
859 
860 template <typename T>
861 inline bool VectorT3<T>::isUnit(const T eps) const
862 {
863  return NumericT<T>::isEqual(length(), T(1), eps);
864 }
865 
866 template <typename T>
867 inline bool VectorT3<T>::isEqual(const VectorT3<T>& vector, const T eps) const
868 {
869  return NumericT<T>::isEqual(values_[0], vector.values_[0], eps)
870  && NumericT<T>::isEqual(values_[1], vector.values_[1], eps)
871  && NumericT<T>::isEqual(values_[2], vector.values_[2], eps);
872 }
873 
874 template <typename T>
876 {
877  if (this == &vector)
878  {
879  return *this;
880  }
881 
882  values_[0] = vector.values_[0];
883  values_[1] = vector.values_[1];
884  values_[2] = vector.values_[2];
885 
886  return *this;
887 }
888 
889 template <typename T>
890 inline bool VectorT3<T>::operator==(const VectorT3<T>& vector) const
891 {
892  return NumericT<T>::isEqual(values_[0], vector.values_[0])
893  && NumericT<T>::isEqual(values_[1], vector.values_[1])
894  && NumericT<T>::isEqual(values_[2], vector.values_[2]);
895 }
896 
897 template <typename T>
898 inline bool VectorT3<T>::operator!=(const VectorT3<T>& vector) const
899 {
900  return NumericT<T>::isNotEqual(values_[0], vector.values_[0])
901  || NumericT<T>::isNotEqual(values_[1], vector.values_[1])
902  || NumericT<T>::isNotEqual(values_[2], vector.values_[2]);
903 }
904 
905 template <typename T>
906 inline VectorT3<T> VectorT3<T>::operator+(const VectorT3<T>& vector) const
907 {
908  return VectorT3<T>(values_[0] + vector.values_[0], values_[1] + vector.values_[1], values_[2] + vector.values_[2]);
909 }
910 
911 template <typename T>
913 {
914  values_[0] += vector.values_[0];
915  values_[1] += vector.values_[1];
916  values_[2] += vector.values_[2];
917 
918  return *this;
919 }
920 
921 template <typename T>
922 inline VectorT3<T> VectorT3<T>::operator-(const VectorT3<T>& vector) const
923 {
924  return VectorT3<T>(values_[0] - vector.values_[0], values_[1] - vector.values_[1], values_[2] - vector.values_[2]);
925 }
926 
927 template <typename T>
929 {
930  values_[0] -= vector.values_[0];
931  values_[1] -= vector.values_[1];
932  values_[2] -= vector.values_[2];
933 
934  return *this;
935 }
936 
937 template <typename T>
939 {
940  return VectorT3<T>(-values_[0], -values_[1], -values_[2]);
941 }
942 
943 template <typename T>
944 inline T VectorT3<T>::operator*(const VectorT3<T>& vector) const
945 {
946  return values_[0] * vector.values_[0] + values_[1] * vector.values_[1] + values_[2] * vector.values_[2];
947 }
948 
949 template <typename T>
950 inline VectorT3<T> VectorT3<T>::operator*(const T& value) const
951 {
952  return VectorT3<T>(values_[0] * value, values_[1] * value, values_[2] * value);
953 }
954 
955 template <typename T>
956 inline VectorT3<T>& VectorT3<T>::operator*=(const T& value)
957 {
958  values_[0] *= value;
959  values_[1] *= value;
960  values_[2] *= value;
961 
962  return *this;
963 }
964 
965 template <typename T>
966 inline VectorT3<T> VectorT3<T>::operator/(const T& value) const
967 {
968  ocean_assert(NumericT<T>::isNotEqualEps(value));
969  T factor = T(1) / value;
970 
971  return VectorT3<T>(values_[0] * factor, values_[1] * factor, values_[2] * factor);
972 }
973 
974 template <typename T>
975 inline VectorT3<T>& VectorT3<T>::operator/=(const T& value)
976 {
977  ocean_assert(NumericT<T>::isNotEqualEps(value));
978 
979  T factor = T(1) / value;
980 
981  values_[0] *= factor;
982  values_[1] *= factor;
983  values_[2] *= factor;
984 
985  return *this;
986 }
987 
988 template <typename T>
989 inline bool VectorT3<T>::operator<(const VectorT3<T>& right) const
990 {
991  return values_[0] < right.values_[0]
992  || (values_[0] == right.values_[0] && (values_[1] < right.values_[1]
993  || (values_[1] == right.values_[1] && values_[2] < right.values_[2])));
994 }
995 
996 template <typename T>
997 inline const T& VectorT3<T>::operator[](const unsigned int index) const noexcept
998 {
999  ocean_assert(index < 3u);
1000  return values_[index];
1001 }
1002 
1003 template <typename T>
1004 inline T& VectorT3<T>::operator[](const unsigned int index) noexcept
1005 {
1006  ocean_assert(index < 3u);
1007  return values_[index];
1008 }
1009 
1010 template <typename T>
1011 inline const T& VectorT3<T>::operator()(const unsigned int index) const noexcept
1012 {
1013  ocean_assert(index < 3u);
1014  return values_[index];
1015 }
1016 
1017 template <typename T>
1018 inline T& VectorT3<T>::operator()(const unsigned int index) noexcept
1019 {
1020  ocean_assert(index < 3u);
1021  return values_[index];
1022 }
1023 
1024 template <typename T>
1025 inline const T* VectorT3<T>::operator()() const noexcept
1026 {
1027  return values_;
1028 }
1029 
1030 template <typename T>
1031 inline T* VectorT3<T>::operator()() noexcept
1032 {
1033  return values_;
1034 }
1035 
1036 template <typename T>
1037 inline size_t VectorT3<T>::operator()(const VectorT3<T>& vector) const
1038 {
1039  size_t seed = std::hash<T>{}(vector.x());
1040  seed ^= std::hash<T>{}(vector.y()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1041  seed ^= std::hash<T>{}(vector.z()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1042 
1043  return seed;
1044 }
1045 
1046 template <>
1047 template <>
1048 inline std::vector<VectorT3<float>> VectorT3<float>::vectors2vectors(std::vector<VectorT3<float>>&& vectors)
1049 {
1050  return std::move(vectors);
1051 }
1052 
1053 template <>
1054 template <>
1055 inline std::vector<VectorT3<double>> VectorT3<double>::vectors2vectors(std::vector<VectorT3<double>>&& vectors)
1056 {
1057  return std::move(vectors);
1058 }
1059 
1060 template <typename T>
1061 template <typename U>
1062 inline std::vector<VectorT3<T>> VectorT3<T>::vectors2vectors(std::vector<VectorT3<U>>&& vectors)
1063 {
1064  std::vector<VectorT3<T>> result;
1065  result.reserve(vectors.size());
1066 
1067  for (typename std::vector<VectorT3<U>>::const_iterator i = vectors.cbegin(); i != vectors.cend(); ++i)
1068  {
1069  result.emplace_back(*i);
1070  }
1071 
1072  return result;
1073 }
1074 
1075 template <>
1076 template <>
1077 inline std::vector<VectorT3<float>> VectorT3<float>::vectors2vectors(const std::vector<VectorT3<float>>& vectors)
1078 {
1079  return vectors;
1080 }
1081 
1082 template <>
1083 template <>
1084 inline std::vector<VectorT3<double>> VectorT3<double>::vectors2vectors(const std::vector<VectorT3<double>>& vectors)
1085 {
1086  return vectors;
1087 }
1088 
1089 template <typename T>
1090 template <typename U>
1091 inline std::vector<VectorT3<T>> VectorT3<T>::vectors2vectors(const std::vector<VectorT3<U>>& vectors)
1092 {
1093  std::vector<VectorT3<T>> result;
1094  result.reserve(vectors.size());
1095 
1096  for (typename std::vector<VectorT3<U>>::const_iterator i = vectors.cbegin(); i != vectors.cend(); ++i)
1097  {
1098  result.emplace_back(*i);
1099  }
1100 
1101  return result;
1102 }
1103 
1104 template <typename T>
1105 template <typename U>
1106 inline std::vector<VectorT3<T>> VectorT3<T>::vectors2vectors(const VectorT3<U>* vectors, const size_t size)
1107 {
1108  std::vector< VectorT3<T>> result;
1109  result.reserve(size);
1110 
1111  for (size_t n = 0; n < size; ++n)
1112  {
1113  result.emplace_back(vectors[n]);
1114  }
1115 
1116  return result;
1117 }
1118 
1119 template <typename T>
1120 std::ostream& operator<<(std::ostream& stream, const VectorT3<T>& vector)
1121 {
1122  stream << "[" << vector.x() << ", " << vector.y() << ", " << vector.z() << "]";
1123 
1124  return stream;
1125 }
1126 
1127 template <bool tActive, typename T>
1128 MessageObject<tActive>& operator<<(MessageObject<tActive>& messageObject, const VectorT3<T>& vector)
1129 {
1130  return messageObject << "[" << vector.x() << ", " << vector.y() << ", " << vector.z() << "]";
1131 }
1132 
1133 template <bool tActive, typename T>
1134 MessageObject<tActive>& operator<<(MessageObject<tActive>&& messageObject, const VectorT3<T>& vector)
1135 {
1136  return messageObject << "[" << vector.x() << ", " << vector.y() << ", " << vector.z() << "]";
1137 }
1138 
1139 }
1140 
1141 #endif // META_OCEAN_MATH_VECTOR3_H
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static T sin(const T value)
Returns the sine of a given value.
Definition: Numeric.h:1568
static T sqrt(const T value)
Returns the square root of a given value.
Definition: Numeric.h:1533
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition: Numeric.h:2386
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition: Numeric.h:2087
static T acos(const T value)
Returns the arccosine of a given value.
Definition: Numeric.h:2907
static bool isNotEqual(const T first, const T second)
Returns whether two values are not equal up to a small epsilon.
Definition: Numeric.h:2613
This class implements a vector with two elements.
Definition: Vector2.h:96
bool isUnit(const T eps=NumericT< T >::eps()) const
Returns whether this vector is a unit vector (whether the vector has the length 1).
Definition: Vector3.h:861
VectorT3< T > normalizedOrValue(const VectorT3< T > &value) const
Returns the normalized vector.
Definition: Vector3.h:633
const T * operator()() const noexcept
Access operator.
Definition: Vector3.h:1025
VectorT3< T > perpendicular() const
Returns a vector that is perpendicular to this vector.
Definition: Vector3.h:756
bool operator!=(const VectorT3< T > &vector) const
Returns whether two vectors are not identical up to a small epsilon.
Definition: Vector3.h:898
VectorT3< T > & operator*=(const T &value)
Multiplies and assigns this vector with a scalar.
Definition: Vector3.h:956
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
VectorT3< T > & operator-=(const VectorT3< T > &vector)
Subtracts and assigns two vectors.
Definition: Vector3.h:928
bool normalize()
Normalizes this vector.
Definition: Vector3.h:647
T operator*(const VectorT3< T > &vector) const
Returns the dot product of two vectors.
Definition: Vector3.h:944
VectorT3< T > cross(const VectorT3< T > &vector) const
Returns the cross product of two vectors.
Definition: Vector3.h:597
bool isOrthogonal(const VectorT3< T > &right) const
Returns whether two vectors are orthogonal.
Definition: Vector3.h:794
const T & operator[](const unsigned int index) const noexcept
Element access operator.
Definition: Vector3.h:997
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
static std::vector< VectorT3< T > > vectors2vectors(std::vector< VectorT3< U >> &&vectors)
Converts vectors with specific data type to vectors with different data type.
Definition: Vector3.h:1062
VectorT2< T > xy() const noexcept
Returns the x and y component of the vector as new 2D vector.
Definition: Vector3.h:836
VectorT3< T > normalizedOrZero() const
Returns the normalized vector.
Definition: Vector3.h:619
VectorT3< T > refract(const VectorT3< T > &normal, const T index) const
Returns the refracted vector of this vector corresponding to a given normal vector.
Definition: Vector3.h:725
VectorT3< T > normalized() const
Returns the normalized vector.
Definition: Vector3.h:605
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
VectorT3() noexcept
Creates a new 3D vector with undefined elements.
Definition: Vector3.h:534
bool isNull() const
Returns whether this vector is a null vector up to a small epsilon.
Definition: Vector3.h:854
bool isEqual(const VectorT3< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition: Vector3.h:867
T values_[3]
The three values of the vector, with element order x, y, z.
Definition: Vector3.h:530
const T * data() const noexcept
Returns an pointer to the vector elements.
Definition: Vector3.h:842
VectorT3< T > & operator/=(const T &value)
Divides and assigns this vector by a scalar.
Definition: Vector3.h:975
T distance(const VectorT3< T > &right) const
Returns the distance between this 3D position and a second 3D position.
Definition: Vector3.h:676
T sqrDistance(const VectorT3< T > &right) const
Returns the square distance between this 3D position and a second 3D position.
Definition: Vector3.h:682
VectorT3< T > operator/(const T &value) const
Divides this vector by a scalar.
Definition: Vector3.h:966
VectorT3< T > operator-() const
Returns the negated vector.
Definition: Vector3.h:938
T length() const
Returns the length of the vector.
Definition: Vector3.h:664
bool isParallel(const VectorT3< T > &right) const
Returns whether two vectors are parallel.
Definition: Vector3.h:773
VectorT3< T > operator+(const VectorT3< T > &vector) const
Adds two vectors.
Definition: Vector3.h:906
VectorT3< T > reflect(const VectorT3< T > &normal) const
Returns the reflected vector of this vector corresponding to a given normal vector.
Definition: Vector3.h:709
VectorT3< T > & operator+=(const VectorT3< T > &vector)
Adds and assigns two vectors.
Definition: Vector3.h:912
VectorT3 & operator=(const VectorT3< T > &vector)
Copy assigns a vector.
Definition: Vector3.h:875
T Type
Definition of the used data type.
Definition: Vector3.h:103
bool operator==(const VectorT3< T > &vector) const
Returns whether two vectors are identical up to a small epsilon.
Definition: Vector3.h:890
T sqr() const
Returns the square of the vector length.
Definition: Vector3.h:670
T angle(const VectorT3< T > &right) const
Returns the angle between this vector and a second vectors.
Definition: Vector3.h:688
bool operator<(const VectorT3< T > &vector) const
Compares two vector objects and returns whether the left vector represents a smaller value than the r...
Definition: Vector3.h:989
std::vector< VectorI3 > VectorsI3
Definition of a vector holding VectorI3 objects.
Definition: Vector3.h:86
VectorT3< int > VectorI3
Definition of a 3D vector with integer values.
Definition: Vector3.h:50
std::vector< VectorF3 > VectorsF3
Definition of a vector holding VectorF3 objects.
Definition: Vector3.h:79
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
std::vector< VectorD3 > VectorsD3
Definition of a vector holding VectorD3 objects.
Definition: Vector3.h:72
VectorT3< float > VectorF3
Definition of a 3D vector with float values.
Definition: Vector3.h:43
std::vector< VectorT3< T > > VectorsT3
Definition of a typename alias for vectors with VectorT3 objects.
Definition: Vector3.h:58
VectorT3< double > VectorD3
Definition of a 3D vector with double values.
Definition: Vector3.h:36
std::vector< Vector3 > Vectors3
Definition of a vector holding Vector3 objects.
Definition: Vector3.h:65
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15
std::ostream & operator<<(std::ostream &stream, const HighPerformanceStatistic &highPerformanceStatistic)
Definition: HighPerformanceTimer.h:963