Library of Assembled Shared Sources
vector_3d.inl
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2024 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43
44
45#ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_VECTOR_3D_INL
46#define LASS_GUARDIAN_OF_INCLUSION_PRIM_VECTOR_3D_INL
47
48
49
50
51#include "vector_3d.h"
52#include "../num/basic_ops.h"
53#include "../num/distribution.h"
54#include <random>
55
56namespace lass
57{
58
59namespace prim
60{
61
62
63template<typename T> inline
64Vector3D<T>::Vector3D():
65 x(TNumTraits::zero),
66 y(TNumTraits::zero),
67 z(TNumTraits::zero)
68{
69}
70
71
72
73template<typename T> inline
74Vector3D<T>::Vector3D(TParam x, TParam y, TParam z):
75 x(x),
76 y(y),
77 z(z)
78{
79}
80
81
82
83template <typename T>
84template <typename U> inline
85Vector3D<T>::Vector3D(const Vector3D<U>& other):
86 x(static_cast<TValue>(other.x)),
87 y(static_cast<TValue>(other.y)),
88 z(static_cast<TValue>(other.z))
89{
90}
91
92
93
94template <typename T>
95template <typename U> inline
96Vector3D<T>::Vector3D(const U& x, const U& y, const U& z):
97 x(static_cast<TValue>(x)),
98 y(static_cast<TValue>(y)),
99 z(static_cast<TValue>(z))
100{
101}
102
103
104
105template<typename T>
106typename Vector3D<T>::TConstReference Vector3D<T>::operator[](size_t index) const
108 LASS_ASSERT(index < dimension);
109 return *(&x + index);
110}
114template<typename T>
115typename Vector3D<T>::TReference Vector3D<T>::operator[](size_t index)
117 LASS_ASSERT(index < dimension);
118 return *(&x + index);
119}
123/** Wrap index around range.
124 */
125template<typename T>
126typename Vector3D<T>::TConstReference Vector3D<T>::at(signed index) const
128 return *(&x + num::mod(index, dimension));
129}
131
133/** Wrap index around range.
134 */
135template<typename T>
136typename Vector3D<T>::TReference Vector3D<T>::at(signed index)
137{
138 return *(&x + num::mod(index, dimension));
139}
140
141
142
143/** A weird way to get back the same object
144 */
145template<typename T>
146const Vector3D<T>& Vector3D<T>::operator+() const
147{
148 return *this;
149}
150
151
152
153template<typename T>
154const Vector3D<T> Vector3D<T>::operator-() const
155{
156 return Vector3D(-x, -y, -z);
157}
158
159
160
161/** componentwise addition
162 */
163template<typename T> inline
164Vector3D<T>& Vector3D<T>::operator+=(const Vector3D<T>& other)
165{
166 x += other.x;
167 y += other.y;
168 z += other.z;
169 return *this;
170}
171
172
173
174/** componentwise subtraction
175 */
176template<typename T>
177Vector3D<T>& Vector3D<T>::operator-=(const Vector3D<T>& other)
178{
179 x -= other.x;
180 y -= other.y;
181 z -= other.z;
182 return *this;
183}
184
185
186
187/** Componentwise multiplication.
188 */
189template<typename T> inline
190Vector3D<T>& Vector3D<T>::operator*=(const Vector3D<T>& other)
191{
192 x *= other.x;
193 y *= other.y;
194 z *= other.z;
195 return *this;
196}
197
198
199
200/** Componentwise division.
201 */
202template<typename T> inline
203Vector3D<T>& Vector3D<T>::operator/=(const Vector3D<T>& other)
204{
205 x /= other.x;
206 y /= other.y;
207 z /= other.z;
208 return *this;
209}
210
211
212
213/** add other to each component of this.
214 */
215template<typename T> inline
216Vector3D<T>& Vector3D<T>::operator+=(TParam other)
217{
218 x += other;
219 y += other;
220 z += other;
221 return *this;
222}
223
224
225
226/** subtract other of each component of this.
227 */
228template<typename T> inline
229Vector3D<T>& Vector3D<T>::operator-=(TParam other)
230{
231 x -= other;
232 y -= other;
233 z -= other;
234 return *this;
235}
236
237
238
239/** multiply each component of this with other.
240 */
241template<typename T> inline
242Vector3D<T>& Vector3D<T>::operator*=(TParam other)
243{
244 x *= other;
245 y *= other;
246 z *= other;
247 return *this;
248}
249
250
251
252/** divide each component of this by other.
253 */
254template<typename T> inline
255Vector3D<T>& Vector3D<T>::operator/=(TParam other)
256{
257 x /= other;
258 y /= other;
259 z /= other;
260 return *this;
261}
262
263
264
265/** Return true if all the components are (exactly!) zero
266 */
267template<typename T> inline
269{
270 return x == TNumTraits::zero && y == TNumTraits::zero && z == TNumTraits::zero;
271}
272
273
274
275/** Return true if at least one of the components is NaN
276 */
277template<typename T> inline
279{
280 return num::isNaN(x) || num::isNaN(y) || num::isNaN(z);
281}
282
283
284
285/** Return squared norm of vector.
286 */
287template<typename T> inline
288const typename Vector3D<T>::TValue Vector3D<T>::squaredNorm() const
289{
290 return dot(*this, *this);
291}
292
293
294
295/** Return norm of vector.
296 */
297template<typename T> inline
298const typename Vector3D<T>::TValue Vector3D<T>::norm() const
299{
300 return num::sqrt(squaredNorm());
301}
302
303
304
305/** Return axis with the greatest absolute value
306 */
307template<typename T>
309{
310 const TValue absX = num::abs(x);
311 const TValue absY = num::abs(y);
312 const TValue absZ = num::abs(z);
313 if (absX > absY && absX > absZ)
314 {
315 return XYZ(0);
316 }
317 else if (absY > absZ)
318 {
319 return XYZ(1);
320 }
321 else
322 {
323 return XYZ(2);
324 }
325}
326
327
328/** return a unit vector with same direction/sense as this vector.
329 *
330 * <i>The normalized vector of <b>X</b> is a vector in the same direction but with norm (length) 1.
331 * It is denoted <b>X^</b> and given by <b>X^</b> = <b>X</b> / |<b>X</b>|</i>,
332 * http://mathworld.wolfram.com/NormalizedVector.html.
333 */
334template<typename T>
335const Vector3D<T> Vector3D<T>::normal() const
336{
337 Vector3D<T> result(*this);
338 result.normalize();
339 return result;
340}
341
342
343
344/** return the reciprocal version of this vector
345 */
346template<typename T>
347const Vector3D<T> Vector3D<T>::reciprocal() const
348{
349 Vector3D<T> result(TNumTraits::one, TNumTraits::one, TNumTraits::one);
350 result /= *this;
351 return result;
352}
353
354
355
356/** Project vector on this one
357 */
358template <typename T>
359const Vector3D<T> Vector3D<T>::project(const Vector3D<T>& other) const
360{
361 Vector3D<T> result(*this);
362 result *= dot(other, *this);
363 result /= squaredNorm();
364 return result;
365}
366
367
368
369/** Reject vector from this one
370 */
371template<typename T> inline
372const Vector3D<T> Vector3D<T>::reject(const Vector3D<T>& other) const
373{
374 return other - project(other);
375}
376
377
378
379template<typename T> inline
380const Vector3D<T> Vector3D<T>::reflect(const Vector3D<T>& other) const
381{
382 return 2 * project(other) - other;
383}
384
385
386
387/** apply a function to every component
388 */
389template <typename T>
390const Vector3D<T> Vector3D<T>::transform(T (*op)(T)) const
391{
392 return Vector3D<T>(op(x), op(y), op(z));
393}
394
395
396
397/** Normalize vector.
398 */
399template<typename T> inline
401{
402 *this /= norm();
403}
404
405
406
407/** Random unit vector
408 */
409template <typename T>
410template <class RandomGenerator>
411Vector3D<T> Vector3D<T>::random(RandomGenerator& generator)
412{
413 std::uniform_real_distribution<T> zDistribution(-TNumTraits::one, std::nextafter(TNumTraits::one, TNumTraits::max));
414 const TValue z = zDistribution(generator);
415 const TValue r = num::sqrt(1 - num::sqr(z));
416
417 std::uniform_real_distribution<T> thetaDistribution(TNumTraits::zero, 2 * TNumTraits::pi);
418 const TValue theta = thetaDistribution(generator);
419
420 return Vector3D<T>(r * num::cos(theta), r * num::sin(theta), z);
421}
422
423
424
425/** dot product.
426 * @relates lass::prim::Vector3D
427 */
428template<typename T> inline
429typename Vector3D<T>::TValue dot(const Vector3D<T>& a, const Vector3D<T>& b)
430{
431 return a.x * b.x + a.y * b.y + a.z * b.z;
432}
433
434
435
436/** cross product
437 * @relates lass::prim::Vector3D
438 */
439template<typename T> inline
440Vector3D<T> cross(const Vector3D<T>& a, const Vector3D<T>& b)
441{
442 return Vector3D<T>(a.y * b.z - a.z * b.y,
443 a.z * b.x - a.x * b.z,
444 a.x * b.y - a.y * b.x);
445}
446
447
448
449/** @relates lass::prim::Vector3D
450 */
451template<typename T> inline
452bool operator==(const Vector3D<T>& a, const Vector3D<T>& b)
453{
454 return a.x == b.x && a.y == b.y && a.z == b.z;
455}
456
457
458
459/** @relates lass::prim::Vector3D
460 */
461template<typename T> inline
462bool operator!=(const Vector3D<T>& a, const Vector3D<T>& b)
463{
464 return !(a == b);
465}
466
467
468
469/** componentwise addition
470 * @relates lass::prim::Vector3D
471 */
472template<typename T> inline
473Vector3D<T> operator+(const Vector3D<T>& a, const Vector3D<T>& b)
474{
475 Vector3D<T> result(a);
476 result += b;
477 return result;
478}
479
480
481
482/** componentwise subtraction
483 * @relates lass::prim::Vector3D
484 */
485template<typename T> inline
486Vector3D<T> operator-(const Vector3D<T>& a, const Vector3D<T>& b)
487{
488 Vector3D<T> result(a);
489 result -= b;
490 return result;
491}
492
493
494
495/** Componentwise multiplication
496 * @relates lass::prim::Vector3D
497 */
498template<typename T> inline
499Vector3D<T> operator*(const Vector3D<T>& a, const Vector3D<T>& b)
500{
501 Vector3D<T> result(a);
502 result *= b;
503 return result;
504}
505
506
507
508/** Componentwise division
509 * @relates lass::prim::Vector3D
510 */
511template<typename T> inline
512Vector3D<T> operator/(const Vector3D<T>& a, const Vector3D<T>& b)
513{
514 Vector3D<T> result(a);
515 result /= b;
516 return result;
517}
518
519
520
521/** add b to all components of a.
522 * @relates lass::prim::Vector3D
523 */
524template<typename T> inline
525Vector3D<T> operator+(const Vector3D<T>& a, typename Vector3D<T>::TParam b)
526{
527 Vector3D<T> result(a);
528 result += b;
529 return result;
530}
531
532
533
534/** subtract b of all components of a.
535 * @relates lass::prim::Vector3D
536 */
537template<typename T> inline
538Vector3D<T> operator-(const Vector3D<T>& a, typename Vector3D<T>::TParam b)
539{
540 Vector3D<T> result(a);
541 result -= b;
542 return result;
543}
544
545
546
547/** muliply all components of a by b
548 * @relates lass::prim::Vector3D
549 */
550template<typename T> inline
551Vector3D<T> operator*(const Vector3D<T>& a, typename Vector3D<T>::TParam b)
552{
553 Vector3D<T> result(a);
554 result *= b;
555 return result;
556}
557
558
559
560/** divide all components of a by b
561 * @relates lass::prim::Vector3D
562 */
563template<typename T> inline
564Vector3D<T> operator/(const Vector3D<T>& a, typename Vector3D<T>::TParam b)
565{
566 Vector3D<T> result(a);
567 result /= b;
568 return result;
569}
570
571
572
573/** add a to all components of b
574 * @relates lass::prim::Vector3D
575 */
576template<typename T> inline
577Vector3D<T> operator+(typename Vector3D<T>::TParam a, const Vector3D<T>& b)
578{
579 Vector3D<T> result(b);
580 result += a;
581 return result;
582}
583
584
585
586/** subtract a of all components of b
587 * @relates lass::prim::Vector3D
588 */
589template<typename T> inline
590Vector3D<T> operator-(typename Vector3D<T>::TParam a, const Vector3D<T>& b)
591{
592 Vector3D<T> result(-b);
593 result += a;
594 return result;
595}
596
597
598
599/** multiply all components of b with a
600 * @relates lass::prim::Vector3D
601 */
602template<typename T> inline
603Vector3D<T> operator*(typename Vector3D<T>::TParam a, const Vector3D<T>& b)
604{
605 Vector3D<T> result(b);
606 result *= a;
607 return result;
608}
609
610
611
612/** return a vector with, for each coordinate, the minimum value of @a a and @a b
613 * @relates lass::prim::Vector3D
614 */
615template<typename T>
616inline Vector3D<T> pointwiseMin(const Vector3D<T>& a, const Vector3D<T>& b)
617{
618 return Vector3D<T>(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
619}
620
621
622
623/** return a vector with, for each coordinate, the maximum value of @a a and @a b
624 * @relates lass::prim::Vector3D
625 */
626template<typename T>
627inline Vector3D<T> pointwiseMax(const Vector3D<T>& a, const Vector3D<T>& b)
628{
629 return Vector3D<T>(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
630}
631
632
633
634/** interpolate linearly between two vectors: a + t * (b - a)
635 * @relates lass::prim::Vector3D
636 */
637template<typename T>
638inline Vector3D<T> lerp(const Vector3D<T>& a, const Vector3D<T>& b, typename Vector3D<T>::TParam t)
639{
640 Vector3D<T> result = b;
641 result -= a;
642 result *= t;
643 result += a;
644 return result;
645}
646
647
648
649/** @relates lass::prim::Vector3D
650 */
651template<typename T, typename Char, typename Traits>
652std::basic_ostream<Char, Traits>& operator<<(
653 std::basic_ostream<Char, Traits>& stream, const Vector3D<T>& b)
654{
655 LASS_ENFORCE_STREAM(stream) << "(" << b.x << ", " << b.y << ", " << b.z << ")";
656 return stream;
657}
658
659
660
661/** @relates lass::prim::Vector3D
662 */
663template<typename T, typename Char, typename Traits>
664std::basic_istream<Char, Traits>& operator>>(
665 std::basic_istream<Char, Traits>& stream, Vector3D<T>& b)
666{
667 Vector3D<T> result;
668
669 char c = 0;
670 stream >> c;
671 if (c != '(')
672 {
673 stream.clear(std::ios::failbit);
674 return stream;
675 }
676
677 c = 0;
678 stream >> result.x >> c;
679 if (c != ',')
680 {
681 stream.clear(std::ios::failbit);
682 return stream;
683 }
684
685 c = 0;
686 stream >> result.y >> c;
687 if (c != ',')
688 {
689 stream.clear(std::ios::failbit);
690 return stream;
691 }
692
693 c = 0;
694 stream >> result.z >> c;
695 if (c != ')')
696 {
697 stream.clear(std::ios::failbit);
698 return stream;
699 }
700
701 b = result;
702 return stream;
703}
704
705
706
707/** @relates lass::prim::Vector3D
708 */
709template<typename T>
710io::XmlOStream& operator<<(io::XmlOStream& stream, const Vector3D<T>& b)
711{
712 LASS_ENFORCE_STREAM(stream)
713 << "<Vector3D>" << b.x << " " << b.y << " " << b.z << "</Vector3D>\n";
714 return stream;
715}
716
717
718
719}
720
721}
722
723#endif
LineSegment3D< T, PP > project(const Plane3D< T, EP, NP > &plane, const LineSegment3D< T, PP > &lineSegment)
project a linesegment on a plane.
cyclic iterator over xyz indices
Definition xyz.h:62
T sqr(const T &x)
return x * x
Definition basic_ops.h:162
T norm(const T &x)
return norm of x as if x is real part of complex number: sqr(x)
T abs(const T &x)
if x < 0 return -x, else return x.
Definition basic_ops.h:145
set of geometrical primitives
Definition aabb_2d.h:81
Library for Assembled Shared Sources.
Definition config.h:53
const Vector3D< T > project(const Vector3D< T > &other) const
Project vector on this one.
Vector3D< T > operator*(const Vector3D< T > &a, typename Vector3D< T >::TParam b)
muliply all components of a by b
Vector3D::TConstReference at(signed index) const
Wrap index around range.
Vector3D< T > operator+(typename Vector3D< T >::TParam a, const Vector3D< T > &b)
add a to all components of b
const TValue squaredNorm() const
Return squared norm of vector.
void normalize()
Normalize vector.
Vector3D< T > pointwiseMax(const Vector3D< T > &a, const Vector3D< T > &b)
return a vector with, for each coordinate, the maximum value of a and b
const Vector3D< T > reject(const Vector3D< T > &other) const
Reject vector from this one.
const Vector3D< T > transform(T(*op)(T)) const
apply a function to every component
Vector3D< T > operator-(const Vector3D< T > &a, const Vector3D< T > &b)
componentwise subtraction
Vector3D< T > operator+(const Vector3D< T > &a, const Vector3D< T > &b)
componentwise addition
Vector3D< T > operator*(typename Vector3D< T >::TParam a, const Vector3D< T > &b)
multiply all components of b with a
Vector3D< T > operator*(const Vector3D< T > &a, const Vector3D< T > &b)
Componentwise multiplication.
Vector3D< T > operator-(const Vector3D< T > &a, typename Vector3D< T >::TParam b)
subtract b of all components of a.
XYZ majorAxis() const
Return axis with the greatest absolute value.
const TValue norm() const
Return norm of vector.
Vector3D< T > & operator/=(const Vector3D< T > &other)
Componentwise division.
Vector3D< T > operator/(const Vector3D< T > &a, typename Vector3D< T >::TParam b)
divide all components of a by b
Vector3D< T > & operator-=(const Vector3D< T > &other)
componentwise subtraction
Vector3D< T >::TValue dot(const Vector3D< T > &a, const Vector3D< T > &b)
dot product.
static Vector3D< T > random(RandomGenerator &generator)
Random unit vector.
bool isNaN() const
Return true if at least one of the components is NaN.
Vector3D< T > pointwiseMin(const Vector3D< T > &a, const Vector3D< T > &b)
return a vector with, for each coordinate, the minimum value of a and b
Vector3D< T > & operator+=(const Vector3D< T > &other)
componentwise addition
bool isZero() const
Return true if all the components are (exactly!) zero.
Vector3D< T > operator-(typename Vector3D< T >::TParam a, const Vector3D< T > &b)
subtract a of all components of b
const Vector3D< T > & operator+() const
A weird way to get back the same object.
Vector3D< T > operator/(const Vector3D< T > &a, const Vector3D< T > &b)
Componentwise division.
Vector3D< T > cross(const Vector3D< T > &a, const Vector3D< T > &b)
cross product
const Vector3D< T > normal() const
return a unit vector with same direction/sense as this vector.
Vector3D< T > lerp(const Vector3D< T > &a, const Vector3D< T > &b, typename Vector3D< T >::TParam t)
interpolate linearly between two vectors: a + t * (b - a)
const Vector3D< T > reciprocal() const
return the reciprocal version of this vector
Vector3D< T > operator+(const Vector3D< T > &a, typename Vector3D< T >::TParam b)
add b to all components of a.
Vector3D< T > & operator*=(const Vector3D< T > &other)
Componentwise multiplication.