GteVector3.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.1 (2016/07/08)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector.h>
11 
12 namespace gte
13 {
14 
15 // Template alias for convenience.
16 template <typename Real>
18 
19 // Cross, UnitCross, and DotCross have a template parameter N that should
20 // be 3 or 4. The latter case supports affine vectors in 4D (last component
21 // w = 0) when you want to use 4-tuples and 4x4 matrices for affine algebra.
22 
23 // Compute the cross product using the formal determinant:
24 // cross = det{{e0,e1,e2},{x0,x1,x2},{y0,y1,y2}}
25 // = (x1*y2-x2*y1, x2*y0-x0*y2, x0*y1-x1*y0)
26 // where e0 = (1,0,0), e1 = (0,1,0), e2 = (0,0,1), v0 = (x0,x1,x2), and
27 // v1 = (y0,y1,y2).
28 template <int N, typename Real>
30 
31 // Compute the normalized cross product.
32 template <int N, typename Real>
34  bool robust = false);
35 
36 // Compute Dot((x0,x1,x2),Cross((y0,y1,y2),(z0,z1,z2)), the triple scalar
37 // product of three vectors, where v0 = (x0,x1,x2), v1 = (y0,y1,y2), and
38 // v2 is (z0,z1,z2).
39 template <int N, typename Real>
40 Real DotCross(Vector<N,Real> const& v0, Vector<N,Real> const& v1,
41  Vector<N,Real> const& v2);
42 
43 // Compute a right-handed orthonormal basis for the orthogonal complement
44 // of the input vectors. The function returns the smallest length of the
45 // unnormalized vectors computed during the process. If this value is nearly
46 // zero, it is possible that the inputs are linearly dependent (within
47 // numerical round-off errors). On input, numInputs must be 1 or 2 and
48 // v[0] through v[numInputs-1] must be initialized. On output, the
49 // vectors v[0] through v[2] form an orthonormal set.
50 template <typename Real>
51 Real ComputeOrthogonalComplement(int numInputs, Vector3<Real>* v, bool robust = false);
52 
53 // Compute the barycentric coordinates of the point P with respect to the
54 // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where
55 // b0 + b1 + b2 + b3 = 1. The return value is 'true' iff {V0,V1,V2,V3} is
56 // a linearly independent set. Numerically, this is measured by
57 // |det[V0 V1 V2 V3]| <= epsilon. The values bary[] are valid only when the
58 // return value is 'true' but set to zero when the return value is 'false'.
59 template <typename Real>
61  Vector3<Real> const& v1, Vector3<Real> const& v2, Vector3<Real> const& v3,
62  Real bary[4], Real epsilon = (Real)0);
63 
64 // Get intrinsic information about the input array of vectors. The return
65 // value is 'true' iff the inputs are valid (numVectors > 0, v is not null,
66 // and epsilon >= 0), in which case the class members are valid.
67 template <typename Real>
69 {
70 public:
71  // The constructor sets the class members based on the input set.
72  IntrinsicsVector3(int numVectors, Vector3<Real> const* v, Real inEpsilon);
73 
74  // A nonnegative tolerance that is used to determine the intrinsic
75  // dimension of the set.
76  Real epsilon;
77 
78  // The intrinsic dimension of the input set, computed based on the
79  // nonnegative tolerance mEpsilon.
80  int dimension;
81 
82  // Axis-aligned bounding box of the input set. The maximum range is
83  // the larger of max[0]-min[0], max[1]-min[1], and max[2]-min[2].
84  Real min[3], max[3];
85  Real maxRange;
86 
87  // Coordinate system. The origin is valid for any dimension d. The
88  // unit-length direction vector is valid only for 0 <= i < d. The
89  // extreme index is relative to the array of input points, and is also
90  // valid only for 0 <= i < d. If d = 0, all points are effectively
91  // the same, but the use of an epsilon may lead to an extreme index
92  // that is not zero. If d = 1, all points effectively lie on a line
93  // segment. If d = 2, all points effectively line on a plane. If
94  // d = 3, the points are not coplanar.
97 
98  // The indices that define the maximum dimensional extents. The
99  // values extreme[0] and extreme[1] are the indices for the points
100  // that define the largest extent in one of the coordinate axis
101  // directions. If the dimension is 2, then extreme[2] is the index
102  // for the point that generates the largest extent in the direction
103  // perpendicular to the line through the points corresponding to
104  // extreme[0] and extreme[1]. Furthermore, if the dimension is 3,
105  // then extreme[3] is the index for the point that generates the
106  // largest extent in the direction perpendicular to the triangle
107  // defined by the other extreme points. The tetrahedron formed by the
108  // points V[extreme[0]], V[extreme[1]], V[extreme[2]], and
109  // V[extreme[3]] is clockwise or counterclockwise, the condition
110  // stored in extremeCCW.
111  int extreme[4];
113 };
114 
115 
116 template <int N, typename Real>
118 {
119  static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
120 
122  result.MakeZero();
123  result[0] = v0[1] * v1[2] - v0[2] * v1[1];
124  result[1] = v0[2] * v1[0] - v0[0] * v1[2];
125  result[2] = v0[0] * v1[1] - v0[1] * v1[0];
126  return result;
127 }
128 
129 template <int N, typename Real>
130 Vector<N, Real> UnitCross(Vector<N, Real> const& v0, Vector<N, Real> const& v1, bool robust)
131 {
132  static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
133 
134  Vector<N, Real> unitCross = Cross(v0, v1);
135  Normalize(unitCross, robust);
136  return unitCross;
137 }
138 
139 template <int N, typename Real>
140 Real DotCross(Vector<N, Real> const& v0, Vector<N, Real> const& v1,
141  Vector<N, Real> const& v2)
142 {
143  static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
144 
145  return Dot(v0, Cross(v1, v2));
146 }
147 
148 template <typename Real>
149 Real ComputeOrthogonalComplement(int numInputs, Vector3<Real>* v, bool robust)
150 {
151  if (numInputs == 1)
152  {
153  if (fabs(v[0][0]) > fabs(v[0][1]))
154  {
155  v[1] = { -v[0][2], (Real)0, +v[0][0] };
156  }
157  else
158  {
159  v[1] = { (Real)0, +v[0][2], -v[0][1] };
160  }
161  numInputs = 2;
162  }
163 
164  if (numInputs == 2)
165  {
166  v[2] = Cross(v[0], v[1]);
167  return Orthonormalize<3, Real>(3, v, robust);
168  }
169 
170  return (Real)0;
171 }
172 
173 template <typename Real>
175  Vector3<Real> const& v1, Vector3<Real> const& v2, Vector3<Real> const& v3,
176  Real bary[4], Real epsilon)
177 {
178  // Compute the vectors relative to V3 of the tetrahedron.
179  Vector3<Real> diff[4] = { v0 - v3, v1 - v3, v2 - v3, p - v3 };
180 
181  Real det = DotCross(diff[0], diff[1], diff[2]);
182  if (det < -epsilon || det > epsilon)
183  {
184  Real invDet = ((Real)1) / det;
185  bary[0] = DotCross(diff[3], diff[1], diff[2]) * invDet;
186  bary[1] = DotCross(diff[3], diff[2], diff[0]) * invDet;
187  bary[2] = DotCross(diff[3], diff[0], diff[1]) * invDet;
188  bary[3] = (Real)1 - bary[0] - bary[1] - bary[2];
189  return true;
190  }
191 
192  for (int i = 0; i < 4; ++i)
193  {
194  bary[i] = (Real)0;
195  }
196  return false;
197 }
198 
199 template <typename Real>
201  Vector3<Real> const* v, Real inEpsilon)
202  :
203  epsilon(inEpsilon),
204  dimension(0),
205  maxRange((Real)0),
206  origin({ (Real)0, (Real)0, (Real)0 }),
207  extremeCCW(false)
208 {
209  min[0] = (Real)0;
210  min[1] = (Real)0;
211  min[2] = (Real)0;
212  direction[0] = { (Real)0, (Real)0, (Real)0 };
213  direction[1] = { (Real)0, (Real)0, (Real)0 };
214  direction[2] = { (Real)0, (Real)0, (Real)0 };
215  extreme[0] = 0;
216  extreme[1] = 0;
217  extreme[2] = 0;
218  extreme[3] = 0;
219 
220  if (numVectors > 0 && v && epsilon >= (Real)0)
221  {
222  // Compute the axis-aligned bounding box for the input vectors. Keep
223  // track of the indices into 'vectors' for the current min and max.
224  int j, indexMin[3], indexMax[3];
225  for (j = 0; j < 3; ++j)
226  {
227  min[j] = v[0][j];
228  max[j] = min[j];
229  indexMin[j] = 0;
230  indexMax[j] = 0;
231  }
232 
233  int i;
234  for (i = 1; i < numVectors; ++i)
235  {
236  for (j = 0; j < 3; ++j)
237  {
238  if (v[i][j] < min[j])
239  {
240  min[j] = v[i][j];
241  indexMin[j] = i;
242  }
243  else if (v[i][j] > max[j])
244  {
245  max[j] = v[i][j];
246  indexMax[j] = i;
247  }
248  }
249  }
250 
251  // Determine the maximum range for the bounding box.
252  maxRange = max[0] - min[0];
253  extreme[0] = indexMin[0];
254  extreme[1] = indexMax[0];
255  Real range = max[1] - min[1];
256  if (range > maxRange)
257  {
258  maxRange = range;
259  extreme[0] = indexMin[1];
260  extreme[1] = indexMax[1];
261  }
262  range = max[2] - min[2];
263  if (range > maxRange)
264  {
265  maxRange = range;
266  extreme[0] = indexMin[2];
267  extreme[1] = indexMax[2];
268  }
269 
270  // The origin is either the vector of minimum x0-value, vector of
271  // minimum x1-value, or vector of minimum x2-value.
272  origin = v[extreme[0]];
273 
274  // Test whether the vector set is (nearly) a vector.
275  if (maxRange <= epsilon)
276  {
277  dimension = 0;
278  for (j = 0; j < 3; ++j)
279  {
280  extreme[j + 1] = extreme[0];
281  }
282  return;
283  }
284 
285  // Test whether the vector set is (nearly) a line segment. We need
286  // {direction[2],direction[3]} to span the orthogonal complement of
287  // direction[0].
288  direction[0] = v[extreme[1]] - origin;
289  Normalize(direction[0], false);
290  if (fabs(direction[0][0]) > fabs(direction[0][1]))
291  {
292  direction[1][0] = -direction[0][2];
293  direction[1][1] = (Real)0;
294  direction[1][2] = +direction[0][0];
295  }
296  else
297  {
298  direction[1][0] = (Real)0;
299  direction[1][1] = +direction[0][2];
300  direction[1][2] = -direction[0][1];
301  }
302  Normalize(direction[1], false);
303  direction[2] = Cross(direction[0], direction[1]);
304 
305  // Compute the maximum distance of the points from the line
306  // origin+t*direction[0].
307  Real maxDistance = (Real)0;
308  Real distance, dot;
309  extreme[2] = extreme[0];
310  for (i = 0; i < numVectors; ++i)
311  {
312  Vector3<Real> diff = v[i] - origin;
313  dot = Dot(direction[0], diff);
314  Vector3<Real> proj = diff - dot * direction[0];
315  distance = Length(proj, false);
316  if (distance > maxDistance)
317  {
318  maxDistance = distance;
319  extreme[2] = i;
320  }
321  }
322 
323  if (maxDistance <= epsilon*maxRange)
324  {
325  // The points are (nearly) on the line origin+t*direction[0].
326  dimension = 1;
327  extreme[2] = extreme[1];
328  extreme[3] = extreme[1];
329  return;
330  }
331 
332  // Test whether the vector set is (nearly) a planar polygon. The
333  // point v[extreme[2]] is farthest from the line: origin +
334  // t*direction[0]. The vector v[extreme[2]]-origin is not
335  // necessarily perpendicular to direction[0], so project out the
336  // direction[0] component so that the result is perpendicular to
337  // direction[0].
338  direction[1] = v[extreme[2]] - origin;
339  dot = Dot(direction[0], direction[1]);
340  direction[1] -= dot * direction[0];
341  Normalize(direction[1], false);
342 
343  // We need direction[2] to span the orthogonal complement of
344  // {direction[0],direction[1]}.
345  direction[2] = Cross(direction[0], direction[1]);
346 
347  // Compute the maximum distance of the points from the plane
348  // origin+t0*direction[0]+t1*direction[1].
349  maxDistance = (Real)0;
350  Real maxSign = (Real)0;
351  extreme[3] = extreme[0];
352  for (i = 0; i < numVectors; ++i)
353  {
354  Vector3<Real> diff = v[i] - origin;
355  distance = Dot(direction[2], diff);
356  Real sign = (distance >(Real)0 ? (Real)1 :
357  (distance < (Real)0 ? (Real)-1 : (Real)0));
358  distance = fabs(distance);
359  if (distance > maxDistance)
360  {
361  maxDistance = distance;
362  maxSign = sign;
363  extreme[3] = i;
364  }
365  }
366 
367  if (maxDistance <= epsilon * maxRange)
368  {
369  // The points are (nearly) on the plane origin+t0*direction[0]
370  // +t1*direction[1].
371  dimension = 2;
372  extreme[3] = extreme[2];
373  return;
374  }
375 
376  dimension = 3;
377  extremeCCW = (maxSign > (Real)0);
378  return;
379  }
380 }
381 
382 }
void MakeZero()
Definition: GteVector.h:279
GLfloat GLfloat v1
Definition: glcorearb.h:812
Vector< N, Real > UnitCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, bool robust=false)
Definition: GteVector3.h:130
GLsizei GLsizei GLfloat distance
Definition: glext.h:9704
IntrinsicsVector3(int numVectors, Vector3< Real > const *v, Real inEpsilon)
Definition: GteVector3.h:200
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLfloat GLfloat GLfloat GLfloat v3
Definition: glcorearb.h:814
Vector3< Real > direction[3]
Definition: GteVector3.h:96
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
GLfloat v0
Definition: glcorearb.h:811
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real DotCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, Vector< N, Real > const &v2)
Definition: GteVector3.h:140
bool ComputeBarycentrics(Vector2< Real > const &p, Vector2< Real > const &v0, Vector2< Real > const &v1, Vector2< Real > const &v2, Real bary[3], Real epsilon=(Real) 0)
Definition: GteVector2.h:135
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
const GLdouble * v
Definition: glcorearb.h:832
Vector3< Real > origin
Definition: GteVector3.h:95
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:813
GLenum GLint * range
Definition: glcorearb.h:1920
Real ComputeOrthogonalComplement(int numInputs, Vector2< Real > *v, bool robust=false)
Definition: GteVector2.h:123
GLfloat GLfloat p
Definition: glext.h:11668
GLuint64EXT * result
Definition: glext.h:10003


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