GteGVector.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
11 #include <cmath>
12 #include <initializer_list>
13 #include <vector>
14 
15 // Uncomment this to test for size mismatches that are wrapped by
16 // GVector::ValidateSize. If the test is not enabled, the compiler should
17 // not generate any code for ValidateSize in a release build.
18 //#define GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH
19 
20 namespace gte
21 {
22 
23 template <typename Real>
24 class GVector
25 {
26 public:
27  // The tuple is length zero (uninitialized).
28  GVector();
29 
30  // The tuple is length 'size' and the elements are uninitialized.
31  GVector(int size);
32 
33  // For 0 <= d <= size, element d is 1 and all others are zero. If d is
34  // invalid, the zero vector is created. This is a convenience for
35  // creating the standard Euclidean basis vectors; see also
36  // MakeUnit(int,int) and Unit(int,int).
37  GVector(int size, int d);
38 
39  // The copy constructor, destructor, and assignment operator are generated
40  // by the compiler.
41 
42  // Member access. SetSize(int) does not initialize the tuple. The first
43  // operator[] returns a const reference rather than a Real value. This
44  // supports writing via standard file operations that require a const
45  // pointer to data.
46  void SetSize(int size);
47  inline int GetSize() const;
48  inline Real const& operator[](int i) const;
49  inline Real& operator[](int i);
50 
51  // Comparison (for use by STL containers).
52  inline bool operator==(GVector const& vec) const;
53  inline bool operator!=(GVector const& vec) const;
54  inline bool operator< (GVector const& vec) const;
55  inline bool operator<=(GVector const& vec) const;
56  inline bool operator> (GVector const& vec) const;
57  inline bool operator>=(GVector const& vec) const;
58 
59  // Special vectors.
60  void MakeZero(); // All components are 0.
61  void MakeUnit(int d); // Component d is 1, all others are zero.
62  static GVector Zero(int size);
63  static GVector Unit(int size, int d);
64 
65 protected:
66  // This data structure takes advantage of the built-in operator[],
67  // range checking, and visualizers in MSVS.
68  std::vector<Real> mTuple;
69 };
70 
71 // Unary operations.
72 template <typename Real>
74 
75 template <typename Real>
77 
78 // Linear-algebraic operations.
79 template <typename Real>
81 
82 template <typename Real>
84 
85 template <typename Real>
86 GVector<Real> operator*(GVector<Real> const& v, Real scalar);
87 
88 template <typename Real>
89 GVector<Real> operator*(Real scalar, GVector<Real> const& v);
90 
91 template <typename Real>
92 GVector<Real> operator/(GVector<Real> const& v, Real scalar);
93 
94 template <typename Real>
96 
97 template <typename Real>
99 
100 template <typename Real>
101 GVector<Real>& operator*=(GVector<Real>& v, Real scalar);
102 
103 template <typename Real>
104 GVector<Real>& operator/=(GVector<Real>& v, Real scalar);
105 
106 // Geometric operations. The functions with 'robust' set to 'false' use the
107 // standard algorithm for normalizing a vector by computing the length as a
108 // square root of the squared length and dividing by it. The results can be
109 // infinite (or NaN) if the length is zero. When 'robust' is set to 'true',
110 // the algorithm is designed to avoid floating-point overflow and sets the
111 // normalized vector to zero when the length is zero.
112 template <typename Real>
113 Real Dot(GVector<Real> const& v0, GVector<Real> const& v1);
114 
115 template <typename Real>
116 Real Length(GVector<Real> const& v, bool robust = false);
117 
118 template <typename Real>
119 Real Normalize(GVector<Real>& v, bool robust = false);
120 
121 // Gram-Schmidt orthonormalization to generate orthonormal vectors from the
122 // linearly independent inputs. The function returns the smallest length of
123 // the unnormalized vectors computed during the process. If this value is
124 // nearly zero, it is possible that the inputs are linearly dependent (within
125 // numerical round-off errors). On input, 1 <= numElements <= N and v[0]
126 // through v[numElements-1] must be initialized. On output, the vectors
127 // v[0] through v[numElements-1] form an orthonormal set.
128 template <typename Real>
129 Real Orthonormalize(int numElements, GVector<Real>* v, bool robust = false);
130 
131 // Compute the axis-aligned bounding box of the vectors. The return value is
132 // 'true' iff the inputs are valid, in which case vmin and vmax have valid
133 // values.
134 template <typename Real>
135 bool ComputeExtremes(int numVectors, GVector<Real> const* v,
136  GVector<Real>& vmin, GVector<Real>& vmax);
137 
138 // Lift n-tuple v to homogeneous (n+1)-tuple (v,last).
139 template <typename Real>
140 GVector<Real> HLift(GVector<Real> const& v, Real last);
141 
142 // Project homogeneous n-tuple v = (u,v[n-1]) to (n-1)-tuple u.
143 template <typename Real>
145 
146 // Lift n-tuple v = (w0,w1) to (n+1)-tuple u = (w0,u[inject],w1). By
147 // inference, w0 is a (inject)-tuple [nonexistent when inject=0] and w1 is a
148 // (n-inject)-tuple [nonexistent when inject=n].
149 template <typename Real>
150 GVector<Real> Lift(GVector<Real> const& v, int inject, Real value);
151 
152 // Project n-tuple v = (w0,v[reject],w1) to (n-1)-tuple u = (w0,w1). By
153 // inference, w0 is a (reject)-tuple [nonexistent when reject=0] and w1 is a
154 // (n-1-reject)-tuple [nonexistent when reject=n-1].
155 template <typename Real>
156 GVector<Real> Project(GVector<Real> const& v, int reject);
157 
158 
159 template <typename Real>
161 {
162  // Uninitialized.
163 }
164 
165 template <typename Real>
167 {
168  SetSize(size);
169 }
170 
171 template <typename Real>
173 {
174  SetSize(size);
175  MakeUnit(d);
176 }
177 
178 template <typename Real>
180 {
181 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
182  LogAssert(size >= 0, "Mismatched size.");
183 #endif
184  if (size > 0)
185  {
186  mTuple.resize(size);
187  }
188 }
189 
190 template <typename Real> inline
192 {
193  return static_cast<int>(mTuple.size());
194 }
195 
196 template <typename Real> inline
197 Real const& GVector<Real>::operator[](int i) const
198 {
199  return mTuple[i];
200 }
201 
202 template <typename Real> inline
204 {
205  return mTuple[i];
206 }
207 
208 template <typename Real> inline
209 bool GVector<Real>::operator==(GVector const& vec) const
210 {
211  return mTuple == vec.mTuple;
212 }
213 
214 template <typename Real> inline
215 bool GVector<Real>::operator!=(GVector const& vec) const
216 {
217  return mTuple != vec.mTuple;
218 }
219 
220 template <typename Real> inline
221 bool GVector<Real>::operator<(const GVector& vec) const
222 {
223  return mTuple < vec.mTuple;
224 }
225 
226 template <typename Real> inline
227 bool GVector<Real>::operator<=(const GVector& vec) const
228 {
229  return mTuple <= vec.mTuple;
230 }
231 
232 template <typename Real> inline
233 bool GVector<Real>::operator>(const GVector& vec) const
234 {
235  return mTuple > vec.mTuple;
236 }
237 
238 template <typename Real> inline
239 bool GVector<Real>::operator>=(const GVector& vec) const
240 {
241  return mTuple >= vec.mTuple;
242 }
243 
244 template <typename Real>
246 {
247  std::fill(mTuple.begin(), mTuple.end(), (Real)0);
248 }
249 
250 template <typename Real>
252 {
253  std::fill(mTuple.begin(), mTuple.end(), (Real)0);
254  if (0 <= d && d < (int)mTuple.size())
255  {
256  mTuple[d] = (Real)1;
257  }
258 }
259 
260 template <typename Real>
262 {
263  GVector<Real> v(size);
264  v.MakeZero();
265  return v;
266 }
267 
268 template <typename Real>
270 {
271  GVector<Real> v(size);
272  v.MakeUnit(d);
273  return v;
274 }
275 
276 
277 
278 template <typename Real>
280 {
281  return v;
282 }
283 
284 template <typename Real>
286 {
288  for (int i = 0; i < v.GetSize(); ++i)
289  {
290  result[i] = -v[i];
291  }
292  return result;
293 }
294 
295 template <typename Real>
297 {
299  return result += v1;
300 }
301 
302 template <typename Real>
304 {
306  return result -= v1;
307 }
308 
309 template <typename Real>
311 {
313  return result *= scalar;
314 }
315 
316 template <typename Real>
318 {
320  return result *= scalar;
321 }
322 
323 template <typename Real>
325 {
327  return result /= scalar;
328 }
329 
330 template <typename Real>
332 {
333  if (v0.GetSize() == v1.GetSize())
334  {
335  for (int i = 0; i < v0.GetSize(); ++i)
336  {
337  v0[i] += v1[i];
338  }
339  }
340  else
341  {
342 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
343  LogError("Mismatched size.");
344 #endif
345  }
346  return v0;
347 }
348 
349 template <typename Real>
351 {
352  if (v0.GetSize() == v1.GetSize())
353  {
354  for (int i = 0; i < v0.GetSize(); ++i)
355  {
356  v0[i] -= v1[i];
357  }
358  }
359  else
360  {
361 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
362  LogError("Mismatched size.");
363 #endif
364  }
365  return v0;
366 }
367 
368 template <typename Real>
370 {
371  for (int i = 0; i < v.GetSize(); ++i)
372  {
373  v[i] *= scalar;
374  }
375  return v;
376 }
377 
378 template <typename Real>
380 {
381  if (scalar != (Real)0)
382  {
383  Real invScalar = ((Real)1) / scalar;
384  for (int i = 0; i < v.GetSize(); ++i)
385  {
386  v[i] *= invScalar;
387  }
388  }
389  else
390  {
391  for (int i = 0; i < v.GetSize(); ++i)
392  {
393  v[i] = (Real)0;
394  }
395  }
396  return v;
397 }
398 
399 template <typename Real>
400 Real Dot(GVector<Real> const& v0, GVector<Real> const& v1)
401 {
402  if (v0.GetSize() == v1.GetSize())
403  {
404  Real dot = v0[0] * v1[0];
405  for (int i = 1; i < v0.GetSize(); ++i)
406  {
407  dot += v0[i] * v1[i];
408  }
409  return dot;
410  }
411  else
412  {
413 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
414  LogError("Mismatched size.");
415 #endif
416  return (Real)0;
417  }
418 }
419 
420 template <typename Real>
421 Real Length(GVector<Real> const& v, bool robust)
422 {
423  if (robust)
424  {
425  Real maxAbsComp = fabs(v[0]);
426  for (int i = 1; i < v.GetSize(); ++i)
427  {
428  Real absComp = fabs(v[i]);
429  if (absComp > maxAbsComp)
430  {
431  maxAbsComp = absComp;
432  }
433  }
434 
435  Real length;
436  if (maxAbsComp > (Real)0)
437  {
438  GVector<Real> scaled = v / maxAbsComp;
439  length = maxAbsComp * sqrt(Dot(scaled, scaled));
440  }
441  else
442  {
443  length = (Real)0;
444  }
445  return length;
446  }
447  else
448  {
449  return sqrt(Dot(v, v));
450  }
451 }
452 
453 template <typename Real>
454 Real Normalize(GVector<Real>& v, bool robust)
455 {
456  if (robust)
457  {
458  Real maxAbsComp = fabs(v[0]);
459  for (int i = 1; i < v.GetSize(); ++i)
460  {
461  Real absComp = fabs(v[i]);
462  if (absComp > maxAbsComp)
463  {
464  maxAbsComp = absComp;
465  }
466  }
467 
468  Real length;
469  if (maxAbsComp > (Real)0)
470  {
471  v /= maxAbsComp;
472  length = sqrt(Dot(v, v));
473  v /= length;
474  length *= maxAbsComp;
475  }
476  else
477  {
478  length = (Real)0;
479  for (int i = 0; i < v.GetSize(); ++i)
480  {
481  v[i] = (Real)0;
482  }
483  }
484  return length;
485  }
486  else
487  {
488  Real length = sqrt(Dot(v, v));
489  if (length > (Real)0)
490  {
491  v /= length;
492  }
493  else
494  {
495  for (int i = 0; i < v.GetSize(); ++i)
496  {
497  v[i] = (Real)0;
498  }
499  }
500  return length;
501  }
502 }
503 
504 template <typename Real>
505 Real Orthonormalize(int numInputs, GVector<Real>* v, bool robust)
506 {
507  if (v && 1 <= numInputs && numInputs <= v[0].GetSize())
508  {
509 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
510  for (int i = 1; i < numInputs; ++i)
511  {
512  LogAssert(v[0].GetSize() == v[i].GetSize(), "Mismatched size.");
513  }
514 #endif
515  Real minLength = Normalize(v[0], robust);
516  for (int i = 1; i < numInputs; ++i)
517  {
518  for (int j = 0; j < i; ++j)
519  {
520  Real dot = Dot(v[i], v[j]);
521  v[i] -= v[j] * dot;
522  }
523  Real length = Normalize(v[i], robust);
524  if (length < minLength)
525  {
526  minLength = length;
527  }
528  }
529  return minLength;
530  }
531 
532  LogError("Invalid input.");
533  return (Real)0;
534 }
535 
536 template <typename Real>
537 bool ComputeExtremes(int numVectors, GVector<Real> const* v,
538  GVector<Real>& vmin, GVector<Real>& vmax)
539 {
540  if (v && numVectors > 0)
541  {
542 #if defined(GTE_ASSERT_ON_GVECTOR_SIZE_MISMATCH)
543  for (int i = 1; i < numVectors; ++i)
544  {
545  LogAssert(v[0].GetSize() == v[i].GetSize(), "Mismatched size.");
546  }
547 #endif
548  int const size = v[0].GetSize();
549  vmin = v[0];
550  vmax = vmin;
551  for (int j = 1; j < numVectors; ++j)
552  {
553  GVector<Real> const& vec = v[j];
554  for (int i = 0; i < size; ++i)
555  {
556  if (vec[i] < vmin[i])
557  {
558  vmin[i] = vec[i];
559  }
560  else if (vec[i] > vmax[i])
561  {
562  vmax[i] = vec[i];
563  }
564  }
565  }
566  return true;
567  }
568 
569  LogError("Invalid input.");
570  return false;
571 }
572 
573 template <typename Real>
574 GVector<Real> HLift(GVector<Real> const& v, Real last)
575 {
576  int const size = v.GetSize();
577  GVector<Real> result(size + 1);
578  for (int i = 0; i < size; ++i)
579  {
580  result[i] = v[i];
581  }
582  result[size] = last;
583  return result;
584 }
585 
586 template <typename Real>
588 {
589  int const size = v.GetSize();
590  if (size > 1)
591  {
592  GVector<Real> result(size - 1);
593  for (int i = 0; i < size - 1; ++i)
594  {
595  result[i] = v[i];
596  }
597  return result;
598  }
599  else
600  {
601  return GVector<Real>();
602  }
603 }
604 
605 template <typename Real>
606 GVector<Real> Lift(GVector<Real> const& v, int inject, Real value)
607 {
608  int const size = v.GetSize();
609  GVector<Real> result(size + 1);
610  int i;
611  for (i = 0; i < inject; ++i)
612  {
613  result[i] = v[i];
614  }
615  result[i] = value;
616  int j = i;
617  for (++j; i < size; ++i, ++j)
618  {
619  result[j] = v[i];
620  }
621  return result;
622 }
623 
624 template <typename Real>
626 {
627  int const size = v.GetSize();
628  if (size > 1)
629  {
630  GVector<Real> result(size - 1);
631  for (int i = 0, j = 0; i < size - 1; ++i, ++j)
632  {
633  if (j == reject)
634  {
635  ++j;
636  }
637  result[i] = v[j];
638  }
639  return result;
640  }
641  else
642  {
643  return GVector<Real>();
644  }
645 }
646 
647 }
void MakeUnit(int d)
Definition: GteGVector.h:251
GVector< Real > Project(GVector< Real > const &v, int reject)
Definition: GteGVector.h:625
#define LogAssert(condition, message)
Definition: GteLogger.h:86
DualQuaternion< Real > & operator*=(DualQuaternion< Real > &d, Real scalar)
GLfloat GLfloat v1
Definition: glcorearb.h:812
bool operator<=(GVector const &vec) const
Definition: GteGVector.h:227
GLsizei const GLfloat * value
Definition: glcorearb.h:819
void SetSize(int size)
Definition: GteGVector.h:179
bool operator==(GVector const &vec) const
Definition: GteGVector.h:209
GLsizeiptr size
Definition: glcorearb.h:659
bool operator<(GVector const &vec) const
Definition: GteGVector.h:221
GVector< Real > HLift(GVector< Real > const &v, Real last)
Definition: GteGVector.h:574
std::vector< Real > mTuple
Definition: GteGVector.h:68
DualQuaternion< Real > operator+(DualQuaternion< Real > const &d)
GVector< Real > HProject(GVector< Real > const &v)
Definition: GteGVector.h:587
Real const & operator[](int i) const
Definition: GteGVector.h:197
bool operator>=(GVector const &vec) const
Definition: GteGVector.h:239
static GVector Unit(int size, int d)
Definition: GteGVector.h:269
#define LogError(message)
Definition: GteLogger.h:92
DualQuaternion< Real > & operator-=(DualQuaternion< Real > &d0, DualQuaternion< Real > const &d1)
void MakeZero()
Definition: GteGVector.h:245
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real Orthonormalize(int numElements, GVector< Real > *v, bool robust=false)
Definition: GteGVector.h:505
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
GLfloat v0
Definition: glcorearb.h:811
GVector< Real > Lift(GVector< Real > const &v, int inject, Real value)
Definition: GteGVector.h:606
bool operator>(GVector const &vec) const
Definition: GteGVector.h:233
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:790
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
const GLdouble * v
Definition: glcorearb.h:832
DualQuaternion< Real > operator-(DualQuaternion< Real > const &d)
DualQuaternion< Real > & operator+=(DualQuaternion< Real > &d0, DualQuaternion< Real > const &d1)
bool operator!=(GVector const &vec) const
Definition: GteGVector.h:215
DualQuaternion< Real > & operator/=(DualQuaternion< Real > &d, Real scalar)
bool ComputeExtremes(int numVectors, GVector< Real > const *v, GVector< Real > &vmin, GVector< Real > &vmax)
Definition: GteGVector.h:537
Vector4< float > operator*(Transform const &M, Vector4< float > const &V)
GLuint64EXT * result
Definition: glext.h:10003
static GVector Zero(int size)
Definition: GteGVector.h:261
DualQuaternion< Real > operator/(DualQuaternion< Real > const &d, Real scalar)
int GetSize() const
Definition: GteGVector.h:191


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00