GtePrimalQuery2.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 <Mathematics/GteVector2.h>
11 
12 // Queries about the relation of a point to various geometric objects. The
13 // choices for N when using UIntegerFP32<N> for either BSNumber of BSRational
14 // are determined in GeometricTools/GTEngine/Tools/PrecisionCalculator. These
15 // N-values are worst case scenarios. Your specific input data might require
16 // much smaller N, in which case you can modify PrecisionCalculator to use the
17 // BSPrecision(int32_t,int32_t,int32_t,bool) constructors.
18 
19 namespace gte
20 {
21 
22 template <typename Real>
24 {
25 public:
26  // The caller is responsible for ensuring that the array is not empty
27  // before calling queries and that the indices passed to the queries are
28  // valid. The class does no range checking.
29  PrimalQuery2();
30  PrimalQuery2(int numVertices, Vector2<Real> const* vertices);
31 
32  // Member access.
33  inline void Set(int numVertices, Vector2<Real> const* vertices);
34  inline int GetNumVertices() const;
35  inline Vector2<Real> const* GetVertices() const;
36 
37  // In the following, point P refers to vertices[i] or 'test' and Vi refers
38  // to vertices[vi].
39 
40  // For a line with origin V0 and direction <V0,V1>, ToLine returns
41  // +1, P on right of line
42  // -1, P on left of line
43  // 0, P on the line
44  //
45  // Choice of N for UIntegerFP32<N>.
46  // input type | compute type | N
47  // -----------+--------------+-----
48  // float | BSNumber | 18
49  // double | BSNumber | 132
50  // float | BSRational | 214
51  // double | BSRational | 1587
52  int ToLine(int i, int v0, int v1) const;
53  int ToLine(Vector2<Real> const& test, int v0, int v1) const;
54 
55  // For a line with origin V0 and direction <V0,V1>, ToLine returns
56  // +1, P on right of line
57  // -1, P on left of line
58  // 0, P on the line
59  // The 'order' parameter is
60  // -3, points not collinear, P on left of line
61  // -2, P strictly left of V0 on the line
62  // -1, P = V0
63  // 0, P interior to line segment [V0,V1]
64  // +1, P = V1
65  // +2, P strictly right of V0 on the line
66  //
67  // Choice of N for UIntegerFP32<N>.
68  // input type | compute type | N
69  // -----------+--------------+-----
70  // float | BSNumber | 18
71  // double | BSNumber | 132
72  // float | BSRational | 214
73  // double | BSRational | 1587
74  // This is the same as the first-listed ToLine calls because the worst-case
75  // path has the same computational complexity.
76  int ToLine(int i, int v0, int v1, int& order) const;
77  int ToLine(Vector2<Real> const& test, int v0, int v1, int& order) const;
78 
79  // For a triangle with counterclockwise vertices V0, V1, and V2,
80  // ToTriangle returns
81  // +1, P outside triangle
82  // -1, P inside triangle
83  // 0, P on triangle
84  //
85  // Choice of N for UIntegerFP32<N>.
86  // input type | compute type | N
87  // -----------+--------------+-----
88  // float | BSNumber | 18
89  // double | BSNumber | 132
90  // float | BSRational | 214
91  // double | BSRational | 1587
92  // The query involves three calls to ToLine, so the numbers match those
93  // of ToLine.
94  int ToTriangle(int i, int v0, int v1, int v2) const;
95  int ToTriangle(Vector2<Real> const& test, int v0, int v1, int v2) const;
96 
97  // For a triangle with counterclockwise vertices V0, V1, and V2,
98  // ToCircumcircle returns
99  // +1, P outside circumcircle of triangle
100  // -1, P inside circumcircle of triangle
101  // 0, P on circumcircle of triangle
102  //
103  // Choice of N for UIntegerFP32<N>.
104  // input type | compute type | N
105  // -----------+--------------+------
106  // float | BSNumber | 35
107  // double | BSNumber | 263
108  // float | BSRational | 12302
109  // double | BSRational | 92827
110  // The query involves three calls of ToLine, so the numbers match those
111  // of ToLine.
112  int ToCircumcircle(int i, int v0, int v1, int v2) const;
113  int ToCircumcircle(Vector2<Real> const& test, int v0, int v1, int v2) const;
114 
115  // An extended classification of the relationship of a point to a line
116  // segment. For noncollinear points, the return value is
117  // ORDER_POSITIVE when <P,Q0,Q1> is a counterclockwise triangle
118  // ORDER_NEGATIVE when <P,Q0,Q1> is a clockwise triangle
119  // For collinear points, the line direction is Q1-Q0. The return value is
120  // ORDER_COLLINEAR_LEFT when the line ordering is <P,Q0,Q1>
121  // ORDER_COLLINEAR_RIGHT when the line ordering is <Q0,Q1,P>
122  // ORDER_COLLINEAR_CONTAIN when the line ordering is <Q0,P,Q1>
124  {
133  };
134 
135  // Choice of N for UIntegerFP32<N>.
136  // input type | compute type | N
137  // -----------+--------------+-----
138  // float | BSNumber | 18
139  // double | BSNumber | 132
140  // float | BSRational | 214
141  // double | BSRational | 1587
142  // This is the same as the first-listed ToLine calls because the worst-case
143  // path has the same computational complexity.
144  OrderType ToLineExtended(Vector2<Real> const& P, Vector2<Real> const& Q0, Vector2<Real> const& Q1) const;
145 
146 private:
149 };
150 
151 
152 template <typename Real>
154  :
155  mNumVertices(0),
156  mVertices(nullptr)
157 {
158 }
159 
160 template <typename Real>
162  Vector2<Real> const* vertices)
163  :
164  mNumVertices(numVertices),
165  mVertices(vertices)
166 {
167 }
168 
169 template <typename Real> inline
170 void PrimalQuery2<Real>::Set(int numVertices, Vector2<Real> const* vertices)
171 {
172  mNumVertices = numVertices;
173  mVertices = vertices;
174 }
175 
176 template <typename Real> inline
178 {
179  return mNumVertices;
180 }
181 
182 template <typename Real> inline
184 {
185  return mVertices;
186 }
187 
188 template <typename Real>
189 int PrimalQuery2<Real>::ToLine(int i, int v0, int v1) const
190 {
191  return ToLine(mVertices[i], v0, v1);
192 }
193 
194 template <typename Real>
195 int PrimalQuery2<Real>::ToLine(Vector2<Real> const& test, int v0, int v1) const
196 {
197  Vector2<Real> const& vec0 = mVertices[v0];
198  Vector2<Real> const& vec1 = mVertices[v1];
199 
200  Real x0 = test[0] - vec0[0];
201  Real y0 = test[1] - vec0[1];
202  Real x1 = vec1[0] - vec0[0];
203  Real y1 = vec1[1] - vec0[1];
204  Real x0y1 = x0*y1;
205  Real x1y0 = x1*y0;
206  Real det = x0y1 - x1y0;
207  Real const zero(0);
208 
209  return (det > zero ? +1 : (det < zero ? -1 : 0));
210 }
211 
212 template <typename Real>
213 int PrimalQuery2<Real>::ToLine(int i, int v0, int v1, int& order) const
214 {
215  return ToLine(mVertices[i], v0, v1, order);
216 }
217 
218 template <typename Real>
219 int PrimalQuery2<Real>::ToLine(Vector2<Real> const& test, int v0, int v1, int& order) const
220 {
221  Vector2<Real> const& vec0 = mVertices[v0];
222  Vector2<Real> const& vec1 = mVertices[v1];
223 
224  Real x0 = test[0] - vec0[0];
225  Real y0 = test[1] - vec0[1];
226  Real x1 = vec1[0] - vec0[0];
227  Real y1 = vec1[1] - vec0[1];
228  Real x0y1 = x0*y1;
229  Real x1y0 = x1*y0;
230  Real det = x0y1 - x1y0;
231  Real const zero(0);
232 
233  if (det > zero)
234  {
235  order = +3;
236  return +1;
237  }
238 
239  if (det < zero)
240  {
241  order = -3;
242  return -1;
243  }
244 
245  Real x0x1 = x0*x1;
246  Real y0y1 = y0*y1;
247  Real dot = x0x1 + y0y1;
248  if (dot == zero)
249  {
250  order = -1;
251  }
252  else if (dot < zero)
253  {
254  order = -2;
255  }
256  else
257  {
258  Real x0x0 = x0*x0;
259  Real y0y0 = y0*y0;
260  Real sqrLength = x0x0 + y0y0;
261  if (dot == sqrLength)
262  {
263  order = +1;
264  }
265  else if (dot > sqrLength)
266  {
267  order = +2;
268  }
269  else
270  {
271  order = 0;
272  }
273  }
274 
275  return 0;
276 }
277 
278 template <typename Real>
279 int PrimalQuery2<Real>::ToTriangle(int i, int v0, int v1, int v2) const
280 {
281  return ToTriangle(mVertices[i], v0, v1, v2);
282 }
283 
284 template <typename Real>
285 int PrimalQuery2<Real>::ToTriangle(Vector2<Real> const& test, int v0, int v1, int v2) const
286 {
287  int sign0 = ToLine(test, v1, v2);
288  if (sign0 > 0)
289  {
290  return +1;
291  }
292 
293  int sign1 = ToLine(test, v0, v2);
294  if (sign1 < 0)
295  {
296  return +1;
297  }
298 
299  int sign2 = ToLine(test, v0, v1);
300  if (sign2 > 0)
301  {
302  return +1;
303  }
304 
305  return ((sign0 && sign1 && sign2) ? -1 : 0);
306 }
307 
308 template <typename Real>
309 int PrimalQuery2<Real>::ToCircumcircle(int i, int v0, int v1, int v2) const
310 {
311  return ToCircumcircle(mVertices[i], v0, v1, v2);
312 }
313 
314 template <typename Real>
315 int PrimalQuery2<Real>::ToCircumcircle(Vector2<Real> const& test, int v0, int v1, int v2) const
316 {
317  Vector2<Real> const& vec0 = mVertices[v0];
318  Vector2<Real> const& vec1 = mVertices[v1];
319  Vector2<Real> const& vec2 = mVertices[v2];
320 
321  Real x0 = vec0[0] - test[0];
322  Real y0 = vec0[1] - test[1];
323  Real s00 = vec0[0] + test[0];
324  Real s01 = vec0[1] + test[1];
325  Real t00 = s00*x0;
326  Real t01 = s01*y0;
327  Real z0 = t00 + t01;
328 
329  Real x1 = vec1[0] - test[0];
330  Real y1 = vec1[1] - test[1];
331  Real s10 = vec1[0] + test[0];
332  Real s11 = vec1[1] + test[1];
333  Real t10 = s10*x1;
334  Real t11 = s11*y1;
335  Real z1 = t10 + t11;
336 
337  Real x2 = vec2[0] - test[0];
338  Real y2 = vec2[1] - test[1];
339  Real s20 = vec2[0] + test[0];
340  Real s21 = vec2[1] + test[1];
341  Real t20 = s20*x2;
342  Real t21 = s21*y2;
343  Real z2 = t20 + t21;
344 
345  Real y0z1 = y0*z1;
346  Real y0z2 = y0*z2;
347  Real y1z0 = y1*z0;
348  Real y1z2 = y1*z2;
349  Real y2z0 = y2*z0;
350  Real y2z1 = y2*z1;
351  Real c0 = y1z2 - y2z1;
352  Real c1 = y2z0 - y0z2;
353  Real c2 = y0z1 - y1z0;
354  Real x0c0 = x0*c0;
355  Real x1c1 = x1*c1;
356  Real x2c2 = x2*c2;
357  Real term = x0c0 + x1c1;
358  Real det = term + x2c2;
359  Real const zero(0);
360 
361  return (det < zero ? 1 : (det > zero ? -1 : 0));
362 }
363 
364 template <typename Real>
366  Vector2<Real> const& P, Vector2<Real> const& Q0, Vector2<Real> const& Q1) const
367 {
368  Real const zero(0);
369 
370  Real x0 = Q1[0] - Q0[0];
371  Real y0 = Q1[1] - Q0[1];
372  if (x0 == zero && y0 == zero)
373  {
374  return ORDER_Q0_EQUALS_Q1;
375  }
376 
377  Real x1 = P[0] - Q0[0];
378  Real y1 = P[1] - Q0[1];
379  if (x1 == zero && y1 == zero)
380  {
381  return ORDER_P_EQUALS_Q0;
382  }
383 
384  Real x2 = P[0] - Q1[0];
385  Real y2 = P[1] - Q1[1];
386  if (x2 == zero && y2 == zero)
387  {
388  return ORDER_P_EQUALS_Q1;
389  }
390 
391  // The theoretical classification relies on computing exactly the sign of
392  // the determinant. Numerical roundoff errors can cause misclassification.
393  Real x0y1 = x0 * y1;
394  Real x1y0 = x1 * y0;
395  Real det = x0y1 - x1y0;
396 
397  if (det != zero)
398  {
399  if (det > zero)
400  {
401  // The points form a counterclockwise triangle <P,Q0,Q1>.
402  return ORDER_POSITIVE;
403  }
404  else
405  {
406  // The points form a clockwise triangle <P,Q1,Q0>.
407  return ORDER_NEGATIVE;
408  }
409  }
410  else
411  {
412  // The points are collinear; P is on the line through Q0 and Q1.
413  Real x0x1 = x0 * x1;
414  Real y0y1 = y0 * y1;
415  Real dot = x0x1 + y0y1;
416  if (dot < zero)
417  {
418  // The line ordering is <P,Q0,Q1>.
419  return ORDER_COLLINEAR_LEFT;
420  }
421 
422  Real x0x0 = x0 * x0;
423  Real y0y0 = y0 * y0;
424  Real sqrLength = x0x0 + y0y0;
425  if (dot > sqrLength)
426  {
427  // The line ordering is <Q0,Q1,P>.
428  return ORDER_COLLINEAR_RIGHT;
429  }
430 
431  // The line ordering is <Q0,P,Q1> with P strictly between Q0 and Q1.
433  }
434 }
435 
436 
437 }
Vector2< Real > const * mVertices
int GetNumVertices() const
GLfixed GLfixed GLint GLint order
Definition: glext.h:4927
OrderType ToLineExtended(Vector2< Real > const &P, Vector2< Real > const &Q0, Vector2< Real > const &Q1) const
void Set(int numVertices, Vector2< Real > const *vertices)
GLfloat GLfloat v1
Definition: glcorearb.h:812
GLfixed GLfixed GLfixed y2
Definition: glext.h:4952
int ToLine(int i, int v0, int v1) const
GLfixed y1
Definition: glext.h:4952
Vector2< Real > const * GetVertices() const
GLuint GLfloat x0
Definition: glext.h:9013
GLfloat v0
Definition: glcorearb.h:811
int ToCircumcircle(int i, int v0, int v1, int v2) const
int ToTriangle(int i, int v0, int v1, int v2) const
GLuint GLfloat GLfloat GLfloat x1
Definition: glext.h:9013
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:813
GLfixed GLfixed x2
Definition: glext.h:4952
GLuint GLfloat GLfloat y0
Definition: glext.h:9013


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