Easy3D 2.5.3
vec.h
1/********************************************************************
2 * Copyright (C) 2015-2021 by Liangliang Nan <liangliang.nan@gmail.com>
3 * Copyright (C) 2000-2005 INRIA - Project ALICE
4 *
5 * The code in this file is partly from OGF/Graphite (2.0 alpha-4) with
6 * modifications and enhancement:
7 * https://gforge.inria.fr/forum/forum.php?forum_id=11459
8 * The original code was distributed under the GNU GPL license.
9 ********************************************************************/
10
11#ifndef EASY3D_CORE_VEC_H
12#define EASY3D_CORE_VEC_H
13
14#include <cassert>
15#include <iostream>
16#include <cmath>
17#include <cfloat>
18#include <cstring>
19#include <limits>
20
21
22namespace easy3d {
23
24#if 1
25
33 template <size_t N, class T>
34 class Vec {
35 public:
36 typedef Vec<N, T> thisclass;
37 typedef T FT;
38
40 Vec() { for (size_t i = 0; i < N; i++) { data_[i] = T(0); } }
41
43 explicit Vec(const T& s) { for (size_t i = 0; i < N; i++) { data_[i] = s; } }
44
46 // This one should never be called : a template constructor cannot be a copy constructor
47 template<class T2> explicit Vec(const Vec<N, T2>& rhs) {
48 for (size_t i = 0; i < N; i++) {
49 data_[i] = T(rhs[i]);
50 }
51 }
52
54 // to avoid compilation problems
55 template<class T2, size_t M> explicit Vec(const Vec<M, T2>& rhs) {
56 assert(M == N);
57 for (size_t i = 0; i < N; i++) {
58 data_[i] = T(rhs[i]);
59 }
60 }
61
63 template<class T2> explicit Vec(const T2* rhs) {
64 for (size_t i = 0; i < N; i++) {
65 data_[i] = T(rhs[i]);
66 }
67 }
68
71 memcpy(data_, rhs.data(), N*sizeof(T));
72 return *this;
73 }
74
76 size_t dimension() const { return (size_t)N; }
78 size_t size() const { return dimension(); }
79
81 T* data() { return data_; }
83 const T* data() const { return data_; }
84
87 operator const T*() const { return data_; }
90 operator T*() { return data_; }
91
92 // Liangliang: The compiler can't decide whether to use your overloaded
93 // operator[] or the built-in operator[] on the const T*.
94 // See https://stackoverflow.com/questions/1726740/c-error-operator-2-overloads-have-similar-conversions
95 //inline T& operator[](size_t idx) {
96 // assert(idx < N);
97 // return data()[idx];
98 //}
99 //
100 //inline const T& operator[](size_t idx) const {
101 // assert(idx < N);
102 // return data()[idx];
103 //}
104
106 inline T length2() const {
107 T result = T(0);
108 for (size_t i = 0; i < N; i++) {
109 result += data_[i] * data_[i];
110 }
111 return result;
112 }
113
115 inline T length() const {
116 return std::sqrt(length2());
117 }
118
120 inline T norm() const {
121 return length();
122 }
123
125 inline T distance2(const thisclass &rhs) const {
126 T result = T(0);
127 for (size_t i = 0; i < N; i++) {
128 T val = rhs.data_[i] - data_[i];
129 result += val*val;
130 }
131 return result;
132 }
133
136 T s = length();
137 s = (s > std::numeric_limits<T>::min()) ? T(1.0) / s : T(0.0);
138 *this *= s;
139 return *this;
140 }
141
143 inline thisclass& operator+=(const thisclass& v) {
144 for (size_t i = 0; i < N; i++) {
145 data_[i] += v.data_[i];
146 }
147 return *this;
148 }
149
151 inline thisclass& operator-=(const thisclass& v) {
152 for (size_t i = 0; i < N; i++) {
153 data_[i] -= v.data_[i];
154 }
155 return *this;
156 }
157
159 inline thisclass& operator*=(const thisclass& v) {
160 for (size_t i = 0; i < N; i++) {
161 data_[i] *= v.data_[i];
162 }
163 return *this;
164 }
165
167 inline thisclass& operator/=(const thisclass& v) {
168 for (size_t i = 0; i < N; i++) {
169 data_[i] /= v.data_[i];
170 }
171 return *this;
172 }
173
175 template <class T2> inline thisclass& operator*=(T2 s) {
176 for (size_t i = 0; i < N; i++) {
177 data_[i] *= T(s);
178 }
179 return *this;
180 }
181
183 template <class T2> inline thisclass& operator/=(T2 s) {
184 for (size_t i = 0; i < N; i++) {
185 data_[i] /= T(s);
186 }
187 return *this;
188 }
189
191 inline thisclass operator+ (const thisclass& v) const {
192 thisclass result(*this);
193 for (size_t i = 0; i < N; i++) {
194 result.data_[i] += v.data_[i];
195 }
196 return result;
197 }
198
200 inline thisclass operator- (const thisclass& v) const {
201 thisclass result(*this);
202 for (size_t i = 0; i < N; i++) {
203 result.data_[i] -= v.data_[i];
204 }
205 return result;
206 }
207
209 template <class T2> inline thisclass operator* (T2 s) const {
210 thisclass result(*this);
211 for (size_t i = 0; i < N; i++) {
212 result.data_[i] *= T(s);
213 }
214 return result;
215 }
216
218 template <class T2> inline thisclass operator/ (T2 s) const {
219 thisclass result(*this);
220 for (size_t i = 0; i < N; i++) {
221 result.data_[i] /= T(s);
222 }
223 return result;
224 }
225
227 inline thisclass operator- () const {
228 thisclass result;
229 for (size_t i = 0; i < N; i++) {
230 result.data_[i] = -data_[i];
231 }
232 return result;
233 }
234
235
236 private:
237 T data_[N];
238 };
239
240
242 template <size_t N, class T> inline T dot(const Vec<N, T>& v1, const Vec<N, T>& v2) {
243 T result = 0;
244 for (size_t i = 0; i < N; i++) {
245 result += v1[i] * v2[i];
246 }
247 return result;
248 }
249
251 template <size_t N, class T> inline Vec<N, T> operator-(const Vec<N, T>& v1) {
252 Vec<N, T> result;
253 for (size_t i = 0; i < N; i++) {
254 result[i] = -v1[i];
255 }
256 return result;
257 }
258
260 template <class T2, size_t N, class T> inline Vec<N, T> operator*(T2 s, const Vec<N, T>& v) {
261 Vec<N, T> result;
262 for (size_t i = 0; i < N; i++) {
263 result[i] = T(s)*v[i];
264 }
265 return result;
266 }
267
269 template <size_t N, class T> inline Vec<N, T> operator+(const Vec<N, T>& v1, const Vec<N, T>& v2) {
270 Vec<N, T> result;
271 for (size_t i = 0; i < N; i++) {
272 result[i] = v1[i] + v2[i];
273 }
274 return result;
275 }
276
278 template <size_t N, class T> inline Vec<N, T> operator-(const Vec<N, T>& v1, const Vec<N, T>& v2) {
279 Vec<N, T> result;
280 for (size_t i = 0; i < N; i++) {
281 result[i] = v1[i] - v2[i];
282 }
283 return result;
284 }
285
286 // Global functions for vectors (compatible with GLSL)
287
289 template <size_t N, class T> inline T length(const Vec<N, T>& v) { return v.length(); }
291 template <size_t N, class T> inline T norm(const Vec<N, T>& v) { return v.length(); }
293 template <size_t N, class T> inline T length2(const Vec<N, T>& v) { return v.length2(); }
295 template <size_t N, class T> inline T distance(const Vec<N, T>& v1, const Vec<N, T>& v2) { return length(v2 - v1); }
297 template <size_t N, class T> inline T distance2(const Vec<N, T>& v1, const Vec<N, T>& v2) { return v2.distance2(v1); }
299 template <size_t N, class T> inline Vec<N, T> normalize(const Vec<N, T>& v) {
300 T s = v.length();
301 s = (s > std::numeric_limits<T>::min()) ? T(1.0) / s : T(0.0);
302 return v * s;
303 }
304
307 template <size_t N, class T> inline Vec<N, T> mix(const Vec<N, T>& v1, const Vec<N, T>& v2, T w) {
308 return (T(1) - w) * v1 + w * v2;
309 }
310
311 //-------------------- vec2 -------------------------------------------------------------------
312
319 template <class T>
320 class Vec<2, T> {
321 public:
322 typedef Vec<2, T> thisclass;
323 typedef T FT;
324
325 Vec() : x(0), y(0) { }
326 Vec(T x_in, T y_in) : x(x_in), y(y_in) { }
327 explicit Vec(const Vec<3, T>& v) : x(v.x), y(v.y) { } // very useful for inverse promoting from homogeneous coordinates
328
329 explicit Vec(const T& s) : x(s), y(s) { }
330
331 template<class T2> explicit Vec(const Vec<2, T2> & v)
332 : x(v.x), y(v.y) {}
333
334 template<class T2> explicit Vec(const T2* v)
335 : x(T(v[0])), y(T(v[1])) {}
336
337
338 inline T length2() const { return x*x + y*y; }
339 inline T length() const { return std::sqrt(x*x + y*y); }
340 inline T norm() const { return length(); }
341 inline T distance2(const thisclass& rhs) const {
342 T dx = rhs.x - x;
343 T dy = rhs.y - y;
344 return dx*dx + dy*dy;
345 }
346
347 inline thisclass& normalize() {
348 T s = length();
349 s = (s > std::numeric_limits<T>::min()) ? T(1.0) / s : T(0.0);
350 *this *= s;
351 return *this;
352 }
353
354 // operators
355 inline thisclass& operator+=(const thisclass& v) { x += v.x; y += v.y; return *this; }
356 inline thisclass& operator-=(const thisclass& v) { x -= v.x; y -= v.y; return *this; }
357 inline thisclass& operator*=(const thisclass& v) { x *= v.x; y *= v.y; return *this; }
358 inline thisclass& operator/=(const thisclass& v) { x /= v.x; y /= v.y; return *this; }
359 template <class T2> inline thisclass& operator*=(T2 s) { x *= T(s); y *= T(s); return *this; }
360 template <class T2> inline thisclass& operator/=(T2 s) { x /= T(s); y /= T(s); return *this; }
361
362 inline thisclass operator+ (const thisclass& v) const { return thisclass(x + v.x, y + v.y); }
363 inline thisclass operator- (const thisclass& v) const { return thisclass(x - v.x, y - v.y); }
364 template <class T2> inline thisclass operator* (T2 s) const { return thisclass(x*T(s), y*T(s)); }
365 template <class T2> inline thisclass operator/ (T2 s) const { return thisclass(x / T(s), y / T(s)); }
366 inline thisclass operator- () const { return thisclass(-x, -y); }
367
368 size_t dimension() const { return (size_t)2; }
369 size_t size() const { return dimension(); }
370
371 T* data() { return _array; }
372 const T* data() const { return _array; }
373
374 // Conversion operator returning the memory address of the data.
375 // Very convenient to pass the data pointer as a parameter to functions.
376 // e.g., glVertex2fv(pos);
377 operator const T*() const { return _array; }
378 operator T*() { return _array; }
379
380 // Liangliang: The compiler can't decide whether to use your overloaded
381 // operator[] or the built-in operator[] on the const T*.
382 // See https://stackoverflow.com/questions/1726740/c-error-operator-2-overloads-have-similar-conversions
383 //inline T& operator[](size_t idx) {
384 // assert(idx < 2);
385 // return _array[idx];
386 //}
387 //
388 //inline const T& operator[](size_t idx) const {
389 // assert(idx < 2);
390 // return _array[idx];
391 //}
392
393 //data intentionally left public to allow vec.x
394 union {
395 T _array[2]; // array access
396 struct { T x, y; }; // standard names for components
397 struct { T u, v; }; // standard names for components
398 };
399 };
400
402 template <class T> inline T dot(const Vec<2, T>& v1, const Vec<2, T>& v2) { return v1.x*v2.x + v1.y*v2.y; }
403
405 template <class T> inline T det(const Vec<2, T>& v1, const Vec<2, T>& v2) {
406 return v1.x*v2.y - v1.y*v2.x;
407 }
408
410 template <class T> inline Vec<2, T> operator-(const Vec<2, T>& v1) {
411 return Vec<2, T>(-v1.x, -v1.y);
412 }
413
415 template <class T2, class T> inline Vec<2, T> operator*(T2 s, const Vec<2, T>& v) {
416 return Vec<2, T>(T(s)*v.x, T(s)*v.y);
417 }
418
420 template <class T> inline Vec<2, T> operator+(const Vec<2, T>& v1, const Vec<2, T>& v2) {
421 return Vec<2, T>(v1.x + v2.x, v1.y + v2.y);
422 }
423
425 template <class T> inline Vec<2, T> operator-(const Vec<2, T>& v1, const Vec<2, T>& v2) {
426 return Vec<2, T>(v1.x - v2.x, v1.y - v2.y);
427 }
428
429
430 //---------------- vec3 ------------------------------------------------------------------------
431
438 template <class T>
439 class Vec<3, T> {
440 public:
441 typedef Vec<3, T> thisclass;
442 typedef T FT;
443
444 Vec() : x(0), y(0), z(0) {}
445 explicit Vec(const Vec<2, T>& v, const T& s = 1) : x(v.x), y(v.y), z(s) {} // very useful for promoting to homogeneous coordinates
446 explicit Vec(const Vec<4, T>& v) : x(v.x), y(v.y), z(v.z) {} // very useful for inverse promoting from homogeneous coordinates
447
448 Vec(T x_in, T y_in, T z_in) : x(x_in), y(y_in), z(z_in) {}
449
450 explicit Vec(const T& s) : x(s), y(s), z(s) { }
451
452 template<class T2> explicit Vec(const Vec<3, T2> & v) : x(v.x), y(v.y), z(v.z) {}
453 template<class T2> explicit Vec(const T2* v)
454 : x(T(v[0])), y(T(v[1])), z(T(v[2])) {}
455
456 inline T length2() const { return x*x + y*y + z*z; }
457 inline T length() const { return std::sqrt(x*x + y*y + z*z); }
458 inline T norm() const { return length(); }
459 inline T distance2(const thisclass& rhs) const {
460 T dx = rhs.x - x;
461 T dy = rhs.y - y;
462 T dz = rhs.z - z;
463 return dx*dx + dy*dy + dz*dz;
464 }
465
466 inline thisclass& normalize() {
467 T s = length();
468 s = (s > std::numeric_limits<T>::min()) ? T(1.0) / s : T(0.0);
469 *this *= s;
470 return *this;
471 }
472
473 // operators
474 inline thisclass& operator+=(const thisclass& v) { x += v.x; y += v.y; z += v.z; return *this; }
475 inline thisclass& operator-=(const thisclass& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
476 inline thisclass& operator*=(const thisclass& v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
477 inline thisclass& operator/=(const thisclass& v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
478 template <class T2> inline thisclass& operator*=(T2 s) { x *= T(s); y *= T(s); z *= T(s); return *this; }
479 template <class T2> inline thisclass& operator/=(T2 s) { x /= T(s); y /= T(s); z /= T(s); return *this; }
480
481 inline thisclass operator+ (const thisclass& v) const { return thisclass(x + v.x, y + v.y, z + v.z); }
482 inline thisclass operator- (const thisclass& v) const { return thisclass(x - v.x, y - v.y, z - v.z); }
483 template <class T2> inline thisclass operator* (T2 s) const { return thisclass(x*T(s), y*T(s), z*T(s)); }
484 template <class T2> inline thisclass operator/ (T2 s) const { return thisclass(x / T(s), y / T(s), z / T(s)); }
485
486 inline thisclass operator- () const { return thisclass(-x, -y, -z); }
487
488 size_t dimension() const { return (size_t)3; }
489 size_t size() const { return dimension(); }
490
491 T* data() { return _array; }
492 const T* data() const { return _array; }
493
494 // the (x, y) components
495 Vec<2, T> xy() const { return Vec<2, T>(x, y); }
496
497 // Conversion operator returning the memory address of the data.
498 // Very convenient to pass the data pointer as a parameter to functions.
499 // ------------
500 // vec3 pos, normal;
501 // glNormal3fv(normal);
502 // glVertex3fv(pos);
503 // ------------
504 operator const T*() const { return _array; }
505 operator T*() { return _array; }
506
507 // Liangliang: The compiler can't decide whether to use your overloaded
508 // operator[] or the built-in operator[] on the const T*.
509 // See https://stackoverflow.com/questions/1726740/c-error-operator-2-overloads-have-similar-conversions
510 //inline T& operator[](size_t idx) {
511 // assert(idx < 3);
512 // return _array[idx];
513 //}
514 //
515 //inline const T& operator[](size_t idx) const {
516 // assert(idx < 3);
517 // return _array[idx];
518 //}
519
520 //data intentionally left public to allow vec.x
521 union {
522 T _array[3]; // array access
523 struct { T x, y, z; }; // standard names for components
524 struct { T r, g, b; }; // standard names for components
525 };
526 };
527
529 template <class T> inline T dot(const Vec<3, T>& v1, const Vec<3, T>& v2) {
530 return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
531 }
532
534 template <class T> inline Vec<3, T> cross(const Vec<3, T>& v1, const Vec<3, T>& v2) {
535 return Vec<3, T>(
536 v1.y*v2.z - v1.z*v2.y,
537 v1.z*v2.x - v1.x*v2.z,
538 v1.x*v2.y - v1.y*v2.x
539 );
540 }
541
543 template <class T> inline Vec<3, T> operator-(const Vec<3, T>& v1) { return Vec<3, T>(-v1.x, -v1.y, -v1.z); }
544
546 template <class T2, class T> inline Vec<3, T> operator*(T2 s, const Vec<3, T>& v) {
547 return Vec<3, T>(T(s)*v.x, T(s)*v.y, T(s)*v.z);
548 }
549
551 template <class T> inline Vec<3, T> operator+(const Vec<3, T>& v1, const Vec<3, T>& v2) {
552 return Vec<3, T>(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
553 }
554
556 template <class T> inline Vec<3, T> operator-(const Vec<3, T>& v1, const Vec<3, T>& v2) {
557 return Vec<3, T>(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
558 }
559
561 template <class T> inline Vec<3, T> orthogonal(const Vec<3, T>& v) {
562 T absx = std::fabs(v.x);
563 T absy = std::fabs(v.y);
564 T absz = std::fabs(v.z);
565 // Find smallest component. Keep equal case for null values.
566 if ((absy >= absx) && (absz >= absx))
567 return Vec<3, T>(0.0f, -v.z, v.y);
568 else
569 if ((absx >= absy) && (absz >= absy))
570 return Vec<3, T>(-v.z, 0.0f, v.x);
571 else
572 return Vec<3, T>(-v.y, v.x, 0.0f);
573 }
574
575 // ----------------- vec4 ----------------------------------------------------------------------------------
576
583 template <class T>
584 class Vec<4, T> {
585 public:
586 typedef Vec<4, T> thisclass;
587 typedef T FT;
588
589 Vec() : x(0), y(0), z(0), w(0) {}
590 explicit Vec(const Vec<3, T>& v, const T& s = 1) : x(v.x), y(v.y), z(v.z), w(s) {} // very useful for promoting to homogeneous coordinates
591 Vec(T x_in, T y_in, T z_in, T w_in) : x(x_in), y(y_in), z(z_in), w(w_in) {}
592
593 explicit Vec(const T& s) : x(s), y(s), z(s), w(s) { }
594
595 template<class T2> explicit Vec(const Vec<4, T2> & v)
596 : x(v.x), y(v.y), z(v.z), w(v.w) {}
597 template<class T2> explicit Vec(const T2* v)
598 : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
599
600 inline T length2() const { return x*x + y*y + z*z + w*w; }
601 inline T length() const { return std::sqrt(x*x + y*y + z*z + w*w); }
602 inline T norm() const { return length(); }
603 inline T distance2(const thisclass& rhs) const {
604 T dx = rhs.x - x;
605 T dy = rhs.y - y;
606 T dz = rhs.z - z;
607 T dw = rhs.w - w;
608 return dx*dx + dy*dy + dz*dz + dw*dw;
609 }
610
611 inline thisclass& normalize() {
612 T s = length();
613 s = (s > std::numeric_limits<T>::min()) ? T(1.0) / s : T(0.0);
614 *this *= s;
615 return *this;
616 }
617
618 size_t dimension() const { return (size_t)4; }
619 size_t size() const { return dimension(); }
620
621 // operators
622 inline thisclass& operator+=(const thisclass& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
623 inline thisclass& operator-=(const thisclass& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
624 inline thisclass& operator*=(const thisclass& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
625 inline thisclass& operator/=(const thisclass& v) { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; }
626 template <class T2> inline thisclass& operator*=(T2 s) {
627 x *= T(s); y *= T(s); z *= T(s); w *= T(s); return *this;
628 }
629 template <class T2> inline thisclass& operator/=(T2 s) {
630 x /= T(s); y /= T(s); z /= T(s); w /= T(s); return *this;
631 }
632 inline thisclass operator+ (const thisclass& v) const { return thisclass(x + v.x, y + v.y, z + v.z, w + v.w); }
633 inline thisclass operator- (const thisclass& v) const { return thisclass(x - v.x, y - v.y, z - v.z, w - v.w); }
634 template <class T2> inline thisclass operator* (T2 s) const { return thisclass(x*T(s), y*T(s), z*T(s), w*T(s)); }
635 template <class T2> inline thisclass operator/ (T2 s) const { return thisclass(x / T(s), y / T(s), z / T(s), w / T(s)); }
636 inline thisclass operator- () const { return thisclass(-x, -y, -z, -w); }
637
638 T* data() { return _array; }
639 const T* data() const { return _array; }
640
641 // the (x, y, z) components
642 Vec<3, T> xyz() const { return Vec<3, T>(x, y, z); }
643
644 // Conversion operator returning the memory address of the data.
645 // Very convenient to pass the data pointer as a parameter to functions.
646 // e.g., glColor4fv(c);
647 operator const T*() const { return _array; }
648 operator T*() { return _array; }
649
650 // Liangliang: The compiler can't decide whether to use your overloaded
651 // operator[] or the built-in operator[] on the const T*.
652 // See https://stackoverflow.com/questions/1726740/c-error-operator-2-overloads-have-similar-conversions
653 //inline T& operator[](size_t idx) {
654 // assert(idx < 4);
655 // return _array[idx];
656 //}
657 //
658 //inline const T& operator[](size_t idx) const {
659 // assert(idx < 4);
660 // return _array[idx];
661 //}
662
663 //data intentionally left public to allow vec.x
664 union {
665 T _array[4]; // array access
666 struct { T x, y, z, w; }; // standard names for components
667 struct { T r, g, b, a; }; // standard names for components
668 };
669 };
670
672 template <class T> inline T dot(const Vec<4, T>& v1, const Vec<4, T>& v2) {
673 return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w;
674 }
675
677 template <class T> inline Vec<4, T> operator-(const Vec<4, T>& v1) { return Vec<4, T>(-v1.x, -v1.y, -v1.z, -v1.w); }
678
680 template <class T2, class T> inline Vec<4, T> operator*(T2 s, const Vec<4, T>& v) {
681 return Vec<4, T>(T(s)*v.x, T(s)*v.y, T(s)*v.z, T(s)*v.w);
682 }
683
685 template <class T> inline Vec<4, T> operator+(const Vec<4, T>& v1, const Vec<4, T>& v2) {
686 return Vec<4, T>(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
687 }
688
690 template <class T> inline Vec<4, T> operator-(const Vec<4, T>& v1, const Vec<4, T>& v2) {
691 return Vec<4, T>(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
692 }
693
694
695
696 //------------------------------- IO (input/output) ----------------------------
697
699 template <size_t N, class T> inline std::ostream& operator<<(std::ostream& out, const Vec<N, T>& v) {
700 for (size_t i = 0; i < N; i++) {
701 out << v[i] << " ";
702 }
703 return out;
704 }
705
707 template <size_t N, class T> inline std::istream& operator>>(std::istream& in, Vec<N, T>& v) {
708 for (size_t i = 0; i < N; i++) {
709 in >> v[i];
710 }
711 return in;
712 }
713
715 template <class T> inline std::ostream& operator<<(std::ostream& out, const Vec<2, T>& v) {
716 return out << v.x << " " << v.y;
717 }
718
720 template <class T> inline std::istream& operator>>(std::istream& in, Vec<2, T>& v) {
721 return in >> v.x >> v.y;
722 }
723
725 template <class T> inline std::ostream& operator<<(std::ostream& out, const Vec<3, T>& v) {
726 return out << v.x << " " << v.y << " " << v.z;
727 }
728
730 template <class T> inline std::istream& operator>>(std::istream& in, Vec<3, T>& v) {
731 return in >> v.x >> v.y >> v.z;
732 }
733
735 template <class T> inline std::ostream& operator<<(std::ostream& out, const Vec<4, T>& v) {
736 return out << v.x << " " << v.y << " " << v.z << " " << v.w;
737 }
738
740 template <class T> inline std::istream& operator>>(std::istream& in, Vec<4, T>& v) {
741 return in >> v.x >> v.y >> v.z >> v.w;
742 }
743
744 //----------------------------------------------------------------------
745
747 template <size_t N, class T>
748 inline bool has_nan(const Vec<N, T> &v) {
749 for (std::size_t i = 0; i < N; ++i) {
750 if (std::isnan(v[i]) || std::isinf(v[i]))
751 return true;
752 }
753 return false;
754 }
755
757 template <size_t N, class T>
758 inline bool operator==(const Vec<N,T> &a, const Vec<N,T> &b) {
759 bool t = (a[0] == b[0]);
760 unsigned int i=1;
761 while(i<N && t) {
762 t = t && (a[i]==b[i]);
763 ++i;
764 }
765 return t;
766 }
767
769 template <size_t N, class T>
770 inline bool operator!=(const Vec<N,T> &a, const Vec<N,T> &b) {
771 bool t = (a[0] != b[0]);
772 unsigned int i=1;
773 while(i<N && !t) {
774 t = t || (a[i]!=b[i]);
775 ++i;
776 }
777 return t;
778 }
779
781 template <size_t N, class T>
782 inline bool operator<(const Vec<N,T> &a, const Vec<N,T> &b) {
783 for(unsigned int i=0; i<N; ++i){
784 if(a[i]<b[i]) return true;
785 if(a[i]>b[i]) return false;
786 }
787 return false;
788 }
789
791 template <size_t N, class T>
792 inline Vec<N, T> comp_product(const Vec<N, T> &v1, const Vec<N, T> &v2) {
793 Vec<N, T> result;
794 for (int i = 0; i < N; ++i)
795 result[i] = v1[i] * v2[i];
796 return result;
797 }
798
800 template <size_t N, class T>
801 inline Vec<N, T> comp_min(const Vec<N, T> &v1, const Vec<N, T> &v2) {
802 Vec<N, T> result;
803 for (int i = 0; i < N; ++i)
804 result[i] = std::min(v1[i], v2[i]);
805 return result;
806 }
807
809 template <size_t N, class T>
810 inline Vec<N, T> comp_max(const Vec<N, T> &v1, const Vec<N, T> &v2) {
811 Vec<N, T> result;
812 for (int i = 0; i < N; ++i)
813 result[i] = std::max(v1[i], v2[i]);
814 return result;
815 }
816
818 template<size_t N, class T>
819 inline T min_coord(const Vec<N, T> &a) {
820 T result = a[0];
821 for (unsigned int i = 1; i < N; ++i) if (a[i] < result) result = a[i];
822 return result;
823 }
824
826 template<size_t N, class T>
827 inline T max_coord(const Vec<N, T> &a) {
828 T result = a[0];
829 for (unsigned int i = 1; i < N; ++i) if (a[i] > result) result = a[i];
830 return result;
831 }
832
834 template<size_t N, class T>
835 inline Vec<N, T> clamp(const Vec<N, T> &a, const Vec<N, T> &lower, const Vec<N, T> &upper) {
836 Vec<N, T> result;
837 for (unsigned int i = 0; i < N; ++i) result[i] = std::min(upper[i], std::max(a[i], lower[i]));
838 return result;
839 }
840
841#else
842
843
844 template <size_t DIM, typename T> struct Vec {
845 Vec() { for (size_t i=DIM; i--; data_[i] = T()); }
846 T& operator[](const size_t i) { assert(i<DIM); return data_[i]; }
847 const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; }
848 private:
849 T data_[DIM];
850 };
851
852 typedef Vec<2, float> vec2;
853 typedef Vec<3, float> vec3;
854 typedef Vec<3, int > vec3i;
855 typedef Vec<4, float> vec4;
856
857 template <typename T> struct Vec<2,T> {
858 Vec() : x(T()), y(T()) {}
859 Vec(T X, T Y) : x(X), y(Y) {}
860 template <class U> Vec<2,T>(const Vec<2,U> &v);
861 T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; }
862 const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; }
863 T x,y;
864 };
865
866 template <typename T> struct Vec<3,T> {
867 Vec() : x(T()), y(T()), z(T()) {}
868 Vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
869 T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
870 const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
871 float norm() { return std::sqrt(x*x+y*y+z*z); }
872 Vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; }
873 T x,y,z;
874 };
875
876 template <typename T> struct Vec<4,T> {
877 Vec() : x(T()), y(T()), z(T()), w(T()) {}
878 Vec(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {}
879 T& operator[](const size_t i) { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); }
880 const T& operator[](const size_t i) const { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); }
881 T x,y,z,w;
882 };
883
884 template<size_t DIM,typename T> T operator*(const Vec<DIM,T>& lhs, const Vec<DIM,T>& rhs) {
885 T ret = T();
886 for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]);
887 return ret;
888 }
889
890 template<size_t DIM,typename T>Vec<DIM,T> operator+(Vec<DIM,T> lhs, const Vec<DIM,T>& rhs) {
891 for (size_t i=DIM; i--; lhs[i]+=rhs[i]);
892 return lhs;
893 }
894
895 template<size_t DIM,typename T>Vec<DIM,T> operator-(Vec<DIM,T> lhs, const Vec<DIM,T>& rhs) {
896 for (size_t i=DIM; i--; lhs[i]-=rhs[i]);
897 return lhs;
898 }
899
900 template<size_t DIM,typename T,typename U> Vec<DIM,T> operator*(const Vec<DIM,T> &lhs, const U& rhs) {
901 Vec<DIM,T> ret;
902 for (size_t i=DIM; i--; ret[i]=lhs[i]*rhs);
903 return ret;
904 }
905
906 template<size_t DIM,typename T> Vec<DIM,T> operator-(const Vec<DIM,T> &lhs) {
907 return lhs*T(-1);
908 }
909
910
911 template<size_t DIM,typename T> T dot(const Vec<DIM,T>& lhs, const Vec<DIM,T>& rhs) {
912 T ret = T();
913 for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]);
914 return ret;
915 }
916
917 template <typename T> Vec<3,T> cross(Vec<3,T> v1, Vec<3,T> v2) {
918 return Vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
919 }
920
921 template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, const Vec<DIM,T>& v) {
922 for(unsigned int i=0; i<DIM; i++) out << v[i] << " " ;
923 return out ;
924 }
925
926#endif
927
928}
929
930#endif // EASY3D_CORE_VEC_H
931
A 2D vector (used for representing 2D points or vectors).
Definition: vec.h:320
A 3D vector (used for representing 3D points or vectors).
Definition: vec.h:439
A 4D vector (used for representing 3D points or vectors in homogeneous coordinates).
Definition: vec.h:584
Base class for vector types. It provides generic functionality for N dimensional vectors.
Definition: vec.h:34
thisclass & operator*=(T2 s)
Compound vector-scalar multiplication.
Definition: vec.h:175
size_t size() const
Returns the dimension/size of this vector.
Definition: vec.h:78
thisclass & operator/=(T2 s)
Compound vector-scalar division.
Definition: vec.h:183
thisclass & operator+=(const thisclass &v)
Compound addition with another vector.
Definition: vec.h:143
T length() const
Returns the length of this vector.
Definition: vec.h:115
thisclass operator/(T2 s) const
Vector-scalar division.
Definition: vec.h:218
thisclass & operator*=(const thisclass &v)
Compound component-wise multiplication with another vector.
Definition: vec.h:159
const T * data() const
Returns the constant memory address of the vector.
Definition: vec.h:83
thisclass operator*(T2 s) const
Vector-scalar multiplication.
Definition: vec.h:209
thisclass & operator/=(const thisclass &v)
Compound component-wise division with another vector.
Definition: vec.h:167
Vec(const T &s)
Constructs a vector from a scalar number s. All elements will be initialized to this value.
Definition: vec.h:43
size_t dimension() const
Returns the dimension/size of this vector.
Definition: vec.h:76
Vec()
Default constructor. All elements will be initialized to zero.
Definition: vec.h:40
thisclass & operator-=(const thisclass &v)
Compound subtraction with another vector.
Definition: vec.h:151
thisclass operator-() const
Negates this vector (i.e., adds a minus sign).
Definition: vec.h:227
thisclass operator+(const thisclass &v) const
Addition with another vector.
Definition: vec.h:191
Vec(const Vec< N, T2 > &rhs)
Constructs a vector from another vector of the same dimension/size.
Definition: vec.h:47
Vec(const Vec< M, T2 > &rhs)
Constructs a vector from another vector of the same dimension/size.
Definition: vec.h:55
T distance2(const thisclass &rhs) const
Returns the squared Euclidean distance to another vector.
Definition: vec.h:125
thisclass & normalize()
Normalizes this vector.
Definition: vec.h:135
T norm() const
Returns the norm (i.e., length/magnitude0 of this vector.
Definition: vec.h:120
thisclass & operator=(const thisclass &rhs)
Assignment operator. It assigns the value of this vector from another vector.
Definition: vec.h:70
T * data()
Returns the memory address of the vector.
Definition: vec.h:81
Vec(const T2 *rhs)
Constructs a vector from an array of values.
Definition: vec.h:63
T length2() const
Returns the squared length of this vector.
Definition: vec.h:106
Definition: collider.cpp:182
Matrix< FT > operator+(const Matrix< FT > &, const FT &)
Definition: matrix.h:990
Matrix< FT > operator-(const Matrix< FT > &)
arithmetic operators
Definition: matrix.h:975
bool operator<(const Vec< N, T > &a, const Vec< N, T > &b)
Lexicographic comparison of two vectors.
Definition: vec.h:782
Vec< 3, float > vec3
A 3D point/vector of float type.
Definition: types.h:45
Vec< N, T > comp_product(const Vec< N, T > &v1, const Vec< N, T > &v2)
Component-wise product of two vectors.
Definition: vec.h:792
T distance(const Vec< N, T > &v1, const Vec< N, T > &v2)
Computes the distance between two vectors/points.
Definition: vec.h:295
bool has_nan(const GenericBox< DIM, FT > &box)
Definition: box.h:284
T max_coord(const Vec< N, T > &a)
The maximum coordinate of elements in a vector.
Definition: vec.h:827
T min_coord(const Vec< N, T > &a)
The minimum coordinate of elements in a vector.
Definition: vec.h:819
T clamp(T x, T lower, T upper)
Clamps a num to be within a given range.
Definition: types.h:130
Vec< N, T > mix(const Vec< N, T > &v1, const Vec< N, T > &v2, T w)
Definition: vec.h:307
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Definition: line.h:133
T length(const Vec< N, T > &v)
Computes the length/magnitude of a vector.
Definition: vec.h:289
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Definition: graph.h:920
Vec< 3, T > orthogonal(const Vec< 3, T > &v)
Compute a vector that is orthogonal to the given vector.
Definition: vec.h:561
T det(const Vec< 2, T > &v1, const Vec< 2, T > &v2)
Compute the determinant of the 2x2 matrix formed by the two 2D vectors as the two rows.
Definition: vec.h:405
Vec< 4, float > vec4
A 4D point/vector of float type.
Definition: types.h:47
bool operator==(const Vec< N, T > &a, const Vec< N, T > &b)
Test if two vectors are strictly identical.
Definition: vec.h:758
Vec< 2, float > vec2
A 2D point/vector of float type.
Definition: types.h:43
Vec< N, T > comp_min(const Vec< N, T > &v1, const Vec< N, T > &v2)
Component-wise minimum vector.
Definition: vec.h:801
Vec< 3, T > cross(const Vec< 3, T > &v1, const Vec< 3, T > &v2)
Compute the cross product of two 3D vectors.
Definition: vec.h:534
Vec< N, T > comp_max(const Vec< N, T > &v1, const Vec< N, T > &v2)
Component-wise maximum vector.
Definition: vec.h:810
T distance2(const Vec< N, T > &v1, const Vec< N, T > &v2)
Computes the squared distance between two vectors/points.
Definition: vec.h:297
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition: matrix.h:1803
bool operator!=(const Vec< N, T > &a, const Vec< N, T > &b)
Test if two vectors are strictly not identical.
Definition: vec.h:770
FT norm(const Matrix< FT > &)
utilities
Definition: matrix.h:1424
Vec< N, T > normalize(const Vec< N, T > &v)
Computes and returns the normalized vector (Note: the input vector is not modified).
Definition: vec.h:299
Mat< N, M, T > operator*(T lhs, const Mat< N, M, T > &rhs)
Component-wise scalar-matrix multiplication.
Definition: mat.h:787
T length2(const Vec< N, T > &v)
Computes the squared length/magnitude of a vector.
Definition: vec.h:293