gjk_libccd-inl.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H
39 #define FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H
40 
41 #include <array>
42 #include <iostream>
43 #include <sstream>
44 #include <string>
45 #include <unordered_map>
46 #include <unordered_set>
47 
48 #include "fcl/common/unused.h"
49 #include "fcl/common/warning.h"
52 
53 namespace fcl
54 {
55 
56 namespace detail
57 {
58 
59 //==============================================================================
60 extern template
61 class FCL_EXPORT GJKInitializer<double, Cylinder<double>>;
62 
63 //==============================================================================
64 extern template
65 class FCL_EXPORT GJKInitializer<double, Sphere<double>>;
66 
67 //==============================================================================
68 extern template
69 class FCL_EXPORT GJKInitializer<double, Ellipsoid<double>>;
70 
71 //==============================================================================
72 extern template
73 class FCL_EXPORT GJKInitializer<double, Box<double>>;
74 
75 //==============================================================================
76 extern template
77 class FCL_EXPORT GJKInitializer<double, Capsule<double>>;
78 
79 //==============================================================================
80 extern template
81 class FCL_EXPORT GJKInitializer<double, Cone<double>>;
82 
83 //==============================================================================
84 extern template
85 class FCL_EXPORT GJKInitializer<double, Convex<double>>;
86 
87 //==============================================================================
88 extern template
89 void* triCreateGJKObject(
90  const Vector3d& P1, const Vector3d& P2, const Vector3d& P3);
91 
92 //==============================================================================
93 extern template
94 void* triCreateGJKObject(
95  const Vector3d& P1,
96  const Vector3d& P2,
97  const Vector3d& P3,
98  const Transform3d& tf);
99 
100 //==============================================================================
101 extern template
102 bool GJKCollide(
103  void* obj1,
104  ccd_support_fn supp1,
105  ccd_center_fn cen1,
106  void* obj2,
107  ccd_support_fn supp2,
108  ccd_center_fn cen2,
109  unsigned int max_iterations,
110  double tolerance,
111  Vector3d* contact_points,
112  double* penetration_depth,
113  Vector3d* normal);
114 
115 //==============================================================================
116 extern template
117 bool GJKDistance(
118  void* obj1,
119  ccd_support_fn supp1,
120  void* obj2,
121  ccd_support_fn supp2,
122  unsigned int max_iterations,
123  double tolerance,
124  double* dist,
125  Vector3d* p1,
126  Vector3d* p2);
127 
128 extern template
129 bool GJKSignedDistance(
130  void* obj1,
131  ccd_support_fn supp1,
132  void* obj2,
133  ccd_support_fn supp2,
134  unsigned int max_iterations,
135  double tolerance,
136  double* dist,
137  Vector3d* p1,
138  Vector3d* p2);
139 
140 struct ccd_obj_t
141 {
142  ccd_vec3_t pos;
143  ccd_quat_t rot, rot_inv;
144 };
145 
146 struct ccd_box_t : public ccd_obj_t
147 {
148  ccd_real_t dim[3];
149 };
150 
151 struct ccd_cap_t : public ccd_obj_t
152 {
153  ccd_real_t radius, height;
154 };
155 
156 struct ccd_cyl_t : public ccd_obj_t
157 {
158  ccd_real_t radius, height;
159 };
160 
161 struct ccd_cone_t : public ccd_obj_t
162 {
163  ccd_real_t radius, height;
164 };
165 
166 struct ccd_sphere_t : public ccd_obj_t
167 {
168  ccd_real_t radius;
169 };
170 
171 struct ccd_ellipsoid_t : public ccd_obj_t
172 {
173  ccd_real_t radii[3];
174 };
175 
176 template <typename S>
177 struct ccd_convex_t : public ccd_obj_t
178 {
180 };
181 
182 struct ccd_triangle_t : public ccd_obj_t
183 {
184  ccd_vec3_t p[3];
185  ccd_vec3_t c;
186 };
187 
188 namespace libccd_extension
189 {
190 
191 // These two functions contain the only "valid" invocations of
192 // ccdVec3PointTriDist2(). Any other invocations should be considered a defect.
193 // We can remove these safety layers if/when the issue noted below gets
194 // resolved upstream.
195 
196 // The code in this file (and elsewhere if it comes up), should *not* ever call
197 // `ccdVec3PointTriDist2()` directly. It has some precision quirks. For those
198 // invocations that want the squared distance without a witness point, call
199 // *this* function.
200 static ccd_real_t ccdVec3PointTriDist2NoWitness(const ccd_vec3_t* P,
201  const ccd_vec3_t* a,
202  const ccd_vec3_t* b,
203  const ccd_vec3_t* c) {
204  // When called, ccdVec3PointTriDist2 can optionally compute the value of the
205  // "witness" point. When we don't need the witness point, we skip it. However,
206  // the libccd implementation takes two different code paths based on whether
207  // we request the witness point producing different answers due to numerical
208  // precision issues. So, when FCL doesn't want/need a witness point, we use
209  // this wrapper to force the witness point to get a more consistent and
210  // reliable answer. See
211  // https://github.com/danfis/libccd/issues/55 for an explanation.
212  //
213  // Any actual invocation of ccdVec3PointTriDist2() in the code should request
214  // a witness point *or* call this invocation.
215  ccd_vec3_t unused;
216  return ccdVec3PointTriDist2(P, a, b, c, &unused);
217 }
218 
219 // The code in this file (and elsewhere if it comes up), should *not* ever call
220 // `ccdVec3PointTriDist2()` directly. It has some precision quirks. For those
221 // invocations that want the squared distance *with* a witness point, call
222 // *this* function.
223 static ccd_real_t ccdVec3PointTriDist2WithWitness(const ccd_vec3_t* P,
224  const ccd_vec3_t* a,
225  const ccd_vec3_t* b,
226  const ccd_vec3_t* c,
227  ccd_vec3_t* w) {
228  return ccdVec3PointTriDist2(P, a, b, c, w);
229 }
230 
231 static ccd_real_t simplexReduceToTriangle(ccd_simplex_t *simplex,
232  ccd_real_t dist,
233  ccd_vec3_t *best_witness)
234 {
235  ccd_real_t newdist;
236  ccd_vec3_t witness;
237  int best = -1;
238  int i;
239 
240  // try the fourth point in all three positions
241  for (i = 0; i < 3; i++){
243  ccd_vec3_origin, &ccdSimplexPoint(simplex, (i == 0 ? 3 : 0))->v,
244  &ccdSimplexPoint(simplex, (i == 1 ? 3 : 1))->v,
245  &ccdSimplexPoint(simplex, (i == 2 ? 3 : 2))->v, &witness);
246  newdist = CCD_SQRT(newdist);
247 
248  // record the best triangle
249  if (newdist < dist){
250  dist = newdist;
251  best = i;
252  ccdVec3Copy(best_witness, &witness);
253  }
254  }
255 
256  if (best >= 0){
257  ccdSimplexSet(simplex, best, ccdSimplexPoint(simplex, 3));
258  }
259  ccdSimplexSetSize(simplex, 3);
260 
261  return dist;
262 }
263 
264 _ccd_inline void tripleCross(const ccd_vec3_t *a, const ccd_vec3_t *b,
265  const ccd_vec3_t *c, ccd_vec3_t *d)
266 {
267  ccd_vec3_t e;
268  ccdVec3Cross(&e, a, b);
269  ccdVec3Cross(d, &e, c);
270 }
271 
272 /* This is *not* an implementation of the general function: what's the nearest
273  point on the line segment AB to the origin O? It is not intended to be.
274  This is a limited, special case which exploits the known (or at least
275  expected) construction history of AB. The history is as follows:
276 
277  1. We originally started with the Minkowski support point B (p_OB), which
278  was *not* the origin.
279  2. We define a support direction as p_BO = -p_OB and use that to get the
280  Minkowski support point A.
281  3. We confirm that O is not strictly beyond A in the direction p_BO
282  (confirming separation).
283  4. Then, and only then, do we invoke this method.
284 
285  The method will do one of two things:
286 
287  - determine if the origin lies within the simplex (i.e. lies on the line
288  segment, confirming non-separation) and reports if this is the case,
289  - otherwise it computes a new support direction: a vector pointing to the
290  origin from the nearest point on the segment AB. The direction is
291  guaranteed; the only guarantee about the magnitude is that it is
292  numerically viable (i.e. greater than epsilon).
293 
294  The algorithm exploits the construction history as outlined below. Without
295  loss of generality, we place B some non-zero distance away from the origin
296  along the î direction (all other orientations can be rigidly transformed to
297  this canonical example). The diagram below shows the origin O and the point
298  B. It also shows three regions: 1, 2, and 3.
299 
300 
301  1 ⯅ 2 3
302  │░░░░░░░░░░┆▒▒▒▒▒
303  │░░░░░░░░░░┆▒▒▒▒▒
304  │░░░░░░░░░░┆▒▒▒▒▒
305  │░░░░░░░░░░┆▒▒▒▒▒
306  │░░░░░░░░░░┆▒▒▒▒▒
307  ───────────O──────────B────⯈ î
308  │░░░░░░░░░░┆▒▒▒▒▒
309  │░░░░░░░░░░┆▒▒▒▒▒
310  │░░░░░░░░░░┆▒▒▒▒▒
311  │░░░░░░░░░░┆▒▒▒▒▒
312  │░░░░░░░░░░┆▒▒▒▒▒
313 
314  The point A cannot lie in region 3.
315 
316  - B is a support point of the Minkowski difference. p_BO defines the
317  support vector that produces the support point A. Vertex A must lie at
318  least as far in the p_BO as B otherwise A is not actually a valid support
319  point for that direction. It could lie on the boundary of regions 2 & 3
320  and still be a valid support point.
321 
322  The point A cannot lie in region 2 (or on the boundary between 2 & 3).
323  - We confirm that O is not strictly beyond A in the direction p_BO. For all
324  A in region 2, O lies beyond A (when projected onto the p_BO vector).
325 
326  The point A _must_ lie in region 1 (including the boundary between regions 1 &
327  2) by process of elimination.
328 
329  The implication of this is that the O must project onto the _interior_ of the
330  line segment AB (with one notable exception). If A = O, then the projection of
331  O is at the end point and, is in fact, itself.
332 
333  Therefore, this function can only have two possible outcomes:
334 
335  1. In the case where p_BA = k⋅p_BO (i.e., they are co-linear), we know the
336  origin lies "in" the simplex. If A = O, it lies on the simplex's surface
337  and the objects are touching, otherwise, the objects are penetrating.
338  Either way, we can report that they are definitely *not* separated.
339  2. p_BA ≠ k⋅p_BO, we define the new support direction as perpendicular to the
340  line segment AB, pointing to O from the nearest point on the segment to O.
341 
342  Return value indicates concrete knowledge that the origin lies "in" the
343  2-simplex (encoded as a 1), or indication that computation should continue (0).
344 
345  @note: doSimplex2 should _only_ be called with the construction history
346  outlined above: promotion of a 1-simplex. doSimplex2() is only invoked by
347  doSimplex(). This follows the computation of A and the promotion of the
348  simplex. Therefore, the history is always valid. Even though doSimplex3() can
349  demote itself to a 2-simplex, that 2-simplex immediately gets promoted back to
350  a 3-simplex via the same construction process. Therefore, as long as
351  doSimplex2() is only called from doSimplex() its region 1 assumption _should_
352  remain valid.
353 */
354 static int doSimplex2(ccd_simplex_t *simplex, ccd_vec3_t *dir) {
355  // Used to define numerical thresholds near zero; typically scaled to the size
356  // of the quantities being tested.
357  constexpr ccd_real_t eps = constants<ccd_real_t>::eps();
358 
359  const Vector3<ccd_real_t> p_OA(simplex->ps[simplex->last].v.v);
360  const Vector3<ccd_real_t> p_OB(simplex->ps[0].v.v);
361 
362  // Confirm that A is in region 1. Given that A may be very near to the origin,
363  // we must avoid normalizing p_OA. So, we use this instead.
364  // let A' be the projection of A onto the line defined by O and B.
365  // |A'B| >= |OB| iff A is in region 1.
366  // Numerically, we can express it as follows (allowing for |A'B| to be ever
367  // so slightly *less* than |OB|):
368  // p_AB ⋅ phat_OB >= |p_OB| - |p_OB| * ε = |p_OB| * (1 - ε)
369  // p_AB ⋅ phat_OB ⋅ |p_OB| >= |p_OB|⋅|p_OB| * (1 - ε)
370  // p_AB ⋅ p_OB >= |p_OB|² * (1 - ε)
371  // (p_OB - p_OA) ⋅ p_OB >= |p_OB|² * (1 - ε)
372  // p_OB ⋅ p_OB - p_OA ⋅ p_OB >= |p_OB|² * (1 - ε)
373  // |p_OB|² - p_OA ⋅ p_OB >= |p_OB|² * (1 - ε)
374  // -p_OA ⋅ p_OB >= -|p_OB|²ε
375  // p_OA ⋅ p_OB <= |p_OB|²ε
376  assert(p_OA.dot(p_OB) <= p_OB.squaredNorm() * eps && "A is not in region 1");
377 
378  // Test for co-linearity. Given A is in region 1, co-linearity --> O is "in"
379  // the simplex.
380  // We'll use the angle between two vectors to determine co-linearity: p_AB
381  // and p_OB. If they are co-linear, then the angle between them (θ) is zero.
382  // Similarly, sin(θ) is zero. Ideally, it can be expressed as:
383  // |p_AB × p_OB| = |p_AB||p_OB||sin(θ)| = 0
384  // Numerically, we allow θ (and sin(θ)) to be slightly larger than zero
385  // leading to a numerical formulation as:
386  // |p_AB × p_OB| = |p_AB||p_OB||sin(θ)| < |p_AB||p_OB|ε
387  // Finally, to reduce the computational cost, we eliminate the square roots by
388  // evaluating the equivalently discriminating test:
389  // |p_AB × p_OB|² < |p_AB|²|p_OB|²ε²
390  //
391  // In addition to providing a measure of co-linearity, the cross product gives
392  // us the normal to the plane on which points A, B, and O lie (which we will
393  // use later to compute a new support direction, as necessary).
394  const Vector3<ccd_real_t> p_AB = p_OB - p_OA;
395  const Vector3<ccd_real_t> plane_normal = p_OB.cross(p_AB);
396  if (plane_normal.squaredNorm() <
397  p_AB.squaredNorm() * p_OB.squaredNorm() * eps * eps) {
398  return 1;
399  }
400 
401  // O is not co-linear with AB, so dist(O, AB) > ε. Define `dir` as the
402  // direction to O from the nearest point on AB.
403  // Note: We use the normalized `plane_normal` (n̂) because we've already
404  // concluded that the origin is farther from AB than ε. We want to make sure
405  // `dir` likewise has a magnitude larger than ε. With normalization, we know
406  // |dir| = |n̂ × AB| = |AB| > dist(O, AB) > ε.
407  // Without normalizing, if |OA| and |OB| were smaller than ³√ε but
408  // sufficiently larger than ε, dist(O, AB) > ε, but |dir| < ε.
409  const Vector3<ccd_real_t> new_dir = plane_normal.normalized().cross(p_AB);
410  ccdVec3Set(dir, new_dir(0), new_dir(1), new_dir(2));
411  return 0;
412 }
413 
414 // Compares the given `value` against a _squared epsilon_. This is particularly
415 // important when testing some quantity (e.g., distance) to see if it
416 // is _functionally_ zero but using its _squared_ value in the test. Comparing
417 // _squared distance_ directly against epsilon is equivalent to comparing
418 // distance to sqrt(epsilon) -- we classify the distance as zero or not using
419 // only half the available precision.
420 static bool isAbsValueLessThanEpsSquared(ccd_real_t val) {
421  return std::abs(val) < std::numeric_limits<ccd_real_t>::epsilon() *
423 }
424 
425 // TODO(SeanCurtis-TRI): Define the return value:
426 // 1: (like doSimplex2) --> origin is "in" the simplex.
427 // 0:
428 // -1: If the 3-simplex is degenerate. How is this intepreted?
429 static int doSimplex3(ccd_simplex_t *simplex, ccd_vec3_t *dir)
430 {
431  const ccd_support_t *A, *B, *C;
432  ccd_vec3_t AO, AB, AC, ABC, tmp;
433  ccd_real_t dot;
434 
435  // get last added as A
436  A = ccdSimplexLast(simplex);
437  // get the other points
438  B = ccdSimplexPoint(simplex, 1);
439  C = ccdSimplexPoint(simplex, 0);
440 
441  // check touching contact
442  const ccd_real_t dist_squared = ccdVec3PointTriDist2NoWitness(
443  ccd_vec3_origin, &A->v, &B->v, &C->v);
444  if (isAbsValueLessThanEpsSquared(dist_squared)) {
445  return 1;
446  }
447 
448  // check if triangle is really triangle (has area > 0)
449  // if not simplex can't be expanded and thus no intersection is found
450  // TODO(SeanCurtis-TRI): Coincident points is sufficient but not necessary
451  // for a zero-area triangle. What about co-linearity? Can we guarantee that
452  // co-linearity can't happen? See the `triangle_area_is_zero()` method in
453  // this same file.
454  if (ccdVec3Eq(&A->v, &B->v) || ccdVec3Eq(&A->v, &C->v)){
455  // TODO(SeanCurtis-TRI): Why do we simply quit if the simplex is degenerate?
456  return -1;
457  }
458 
459  // compute AO vector
460  ccdVec3Copy(&AO, &A->v);
461  ccdVec3Scale(&AO, -CCD_ONE);
462 
463  // compute AB and AC segments and ABC vector (perpendircular to triangle)
464  ccdVec3Sub2(&AB, &B->v, &A->v);
465  ccdVec3Sub2(&AC, &C->v, &A->v);
466  ccdVec3Cross(&ABC, &AB, &AC);
467 
468  ccdVec3Cross(&tmp, &ABC, &AC);
469  dot = ccdVec3Dot(&tmp, &AO);
470  if (ccdIsZero(dot) || dot > CCD_ZERO){
471  dot = ccdVec3Dot(&AC, &AO);
472  if (ccdIsZero(dot) || dot > CCD_ZERO){
473  // C is already in place
474  ccdSimplexSet(simplex, 1, A);
475  ccdSimplexSetSize(simplex, 2);
476  tripleCross(&AC, &AO, &AC, dir);
477  }else{
478  ccd_do_simplex3_45:
479  dot = ccdVec3Dot(&AB, &AO);
480  if (ccdIsZero(dot) || dot > CCD_ZERO){
481  ccdSimplexSet(simplex, 0, B);
482  ccdSimplexSet(simplex, 1, A);
483  ccdSimplexSetSize(simplex, 2);
484  tripleCross(&AB, &AO, &AB, dir);
485  }else{
486  ccdSimplexSet(simplex, 0, A);
487  ccdSimplexSetSize(simplex, 1);
488  ccdVec3Copy(dir, &AO);
489  }
490  }
491  }else{
492  ccdVec3Cross(&tmp, &AB, &ABC);
493  dot = ccdVec3Dot(&tmp, &AO);
494  if (ccdIsZero(dot) || dot > CCD_ZERO){
495  goto ccd_do_simplex3_45;
496  }else{
497  dot = ccdVec3Dot(&ABC, &AO);
498  if (ccdIsZero(dot) || dot > CCD_ZERO){
499  ccdVec3Copy(dir, &ABC);
500  }else{
501  ccd_support_t Ctmp;
502  ccdSupportCopy(&Ctmp, C);
503  ccdSimplexSet(simplex, 0, B);
504  ccdSimplexSet(simplex, 1, &Ctmp);
505 
506  ccdVec3Copy(dir, &ABC);
507  ccdVec3Scale(dir, -CCD_ONE);
508  }
509  }
510  }
511 
512  return 0;
513 }
514 
515 static int doSimplex4(ccd_simplex_t *simplex, ccd_vec3_t *dir)
516 {
517  const ccd_support_t *A, *B, *C, *D;
518  ccd_vec3_t AO, AB, AC, AD, ABC, ACD, ADB;
519  int B_on_ACD, C_on_ADB, D_on_ABC;
520  int AB_O, AC_O, AD_O;
521 
522  // get last added as A
523  A = ccdSimplexLast(simplex);
524  // get the other points
525  B = ccdSimplexPoint(simplex, 2);
526  C = ccdSimplexPoint(simplex, 1);
527  D = ccdSimplexPoint(simplex, 0);
528 
529  // check if tetrahedron is really tetrahedron (has volume > 0)
530  // if it is not simplex can't be expanded and thus no intersection is
531  // found.
532  ccd_real_t dist_squared = ccdVec3PointTriDist2NoWitness(
533  &A->v, &B->v, &C->v, &D->v);
534  if (isAbsValueLessThanEpsSquared(dist_squared)) {
535  return -1;
536  }
537 
538  // check if origin lies on some of tetrahedron's face - if so objects
539  // intersect
540  dist_squared =
541  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &A->v, &B->v, &C->v);
542  if (isAbsValueLessThanEpsSquared((dist_squared))) return 1;
543  dist_squared =
544  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &A->v, &C->v, &D->v);
545  if (isAbsValueLessThanEpsSquared((dist_squared))) return 1;
546  dist_squared =
547  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &A->v, &B->v, &D->v);
548  if (isAbsValueLessThanEpsSquared(dist_squared)) return 1;
549  dist_squared =
550  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &B->v, &C->v, &D->v);
551  if (isAbsValueLessThanEpsSquared(dist_squared)) return 1;
552 
553  // compute AO, AB, AC, AD segments and ABC, ACD, ADB normal vectors
554  ccdVec3Copy(&AO, &A->v);
555  ccdVec3Scale(&AO, -CCD_ONE);
556  ccdVec3Sub2(&AB, &B->v, &A->v);
557  ccdVec3Sub2(&AC, &C->v, &A->v);
558  ccdVec3Sub2(&AD, &D->v, &A->v);
559  ccdVec3Cross(&ABC, &AB, &AC);
560  ccdVec3Cross(&ACD, &AC, &AD);
561  ccdVec3Cross(&ADB, &AD, &AB);
562 
563  // side (positive or negative) of B, C, D relative to planes ACD, ADB
564  // and ABC respectively
565  B_on_ACD = ccdSign(ccdVec3Dot(&ACD, &AB));
566  C_on_ADB = ccdSign(ccdVec3Dot(&ADB, &AC));
567  D_on_ABC = ccdSign(ccdVec3Dot(&ABC, &AD));
568 
569  // whether origin is on same side of ACD, ADB, ABC as B, C, D
570  // respectively
571  AB_O = ccdSign(ccdVec3Dot(&ACD, &AO)) == B_on_ACD;
572  AC_O = ccdSign(ccdVec3Dot(&ADB, &AO)) == C_on_ADB;
573  AD_O = ccdSign(ccdVec3Dot(&ABC, &AO)) == D_on_ABC;
574 
575  if (AB_O && AC_O && AD_O){
576  // origin is in tetrahedron
577  return 1;
578 
579  // rearrange simplex to triangle and call doSimplex3()
580  }else if (!AB_O){
581  // B is farthest from the origin among all of the tetrahedron's
582  // points, so remove it from the list and go on with the triangle
583  // case
584 
585  // D and C are in place
586  ccdSimplexSet(simplex, 2, A);
587  ccdSimplexSetSize(simplex, 3);
588  }else if (!AC_O){
589  // C is farthest
590  ccdSimplexSet(simplex, 1, D);
591  ccdSimplexSet(simplex, 0, B);
592  ccdSimplexSet(simplex, 2, A);
593  ccdSimplexSetSize(simplex, 3);
594  }else{ // (!AD_O)
595  ccdSimplexSet(simplex, 0, C);
596  ccdSimplexSet(simplex, 1, B);
597  ccdSimplexSet(simplex, 2, A);
598  ccdSimplexSetSize(simplex, 3);
599  }
600 
601  return doSimplex3(simplex, dir);
602 }
603 
604 static int doSimplex(ccd_simplex_t *simplex, ccd_vec3_t *dir)
605 {
606  if (ccdSimplexSize(simplex) == 2){
607  // simplex contains segment only one segment
608  return doSimplex2(simplex, dir);
609  }else if (ccdSimplexSize(simplex) == 3){
610  // simplex contains triangle
611  return doSimplex3(simplex, dir);
612  }else{ // ccdSimplexSize(simplex) == 4
613  // tetrahedron - this is the only shape which can encapsule origin
614  // so doSimplex4() also contains test on it
615  return doSimplex4(simplex, dir);
616  }
617 }
618 
620 static int simplexToPolytope2(const void *obj1, const void *obj2,
621  const ccd_t *ccd,
622  const ccd_simplex_t *simplex,
623  ccd_pt_t *pt, ccd_pt_el_t **nearest)
624 {
625  const ccd_support_t *a, *b;
626  ccd_vec3_t ab, ac, dir;
627  ccd_support_t supp[4];
628  ccd_pt_vertex_t *v[6];
629  ccd_pt_edge_t *e[12];
630  size_t i;
631  int found;
632 
633  a = ccdSimplexPoint(simplex, 0);
634  b = ccdSimplexPoint(simplex, 1);
635 
636  // This situation is a bit tricky. If only one segment comes from
637  // previous run of GJK - it means that either this segment is on
638  // minkowski edge (and thus we have touch contact) or it it isn't and
639  // therefore segment is somewhere *inside* minkowski sum and it *must*
640  // be possible to fully enclose this segment with polyhedron formed by
641  // at least 8 triangle faces.
642 
643  // get first support point (any)
644  found = 0;
645  for (i = 0; i < ccd_points_on_sphere_len; i++){
646  __ccdSupport(obj1, obj2, &ccd_points_on_sphere[i], ccd, &supp[0]);
647  if (!ccdVec3Eq(&a->v, &supp[0].v) && !ccdVec3Eq(&b->v, &supp[0].v)){
648  found = 1;
649  break;
650  }
651  }
652  if (!found)
653  goto simplexToPolytope2_touching_contact;
654 
655  // get second support point in opposite direction than supp[0]
656  ccdVec3Copy(&dir, &supp[0].v);
657  ccdVec3Scale(&dir, -CCD_ONE);
658  __ccdSupport(obj1, obj2, &dir, ccd, &supp[1]);
659  if (ccdVec3Eq(&a->v, &supp[1].v) || ccdVec3Eq(&b->v, &supp[1].v))
660  goto simplexToPolytope2_touching_contact;
661 
662  // next will be in direction of normal of triangle a,supp[0],supp[1]
663  ccdVec3Sub2(&ab, &supp[0].v, &a->v);
664  ccdVec3Sub2(&ac, &supp[1].v, &a->v);
665  ccdVec3Cross(&dir, &ab, &ac);
666  __ccdSupport(obj1, obj2, &dir, ccd, &supp[2]);
667  if (ccdVec3Eq(&a->v, &supp[2].v) || ccdVec3Eq(&b->v, &supp[2].v))
668  goto simplexToPolytope2_touching_contact;
669 
670  // and last one will be in opposite direction
671  ccdVec3Scale(&dir, -CCD_ONE);
672  __ccdSupport(obj1, obj2, &dir, ccd, &supp[3]);
673  if (ccdVec3Eq(&a->v, &supp[3].v) || ccdVec3Eq(&b->v, &supp[3].v))
674  goto simplexToPolytope2_touching_contact;
675 
676  goto simplexToPolytope2_not_touching_contact;
677 simplexToPolytope2_touching_contact:
678  v[0] = ccdPtAddVertex(pt, a);
679  v[1] = ccdPtAddVertex(pt, b);
680  *nearest = (ccd_pt_el_t *)ccdPtAddEdge(pt, v[0], v[1]);
681  if (*nearest == NULL)
682  return -2;
683 
684  return -1;
685 
686 simplexToPolytope2_not_touching_contact:
687  // form polyhedron
688  v[0] = ccdPtAddVertex(pt, a);
689  v[1] = ccdPtAddVertex(pt, &supp[0]);
690  v[2] = ccdPtAddVertex(pt, b);
691  v[3] = ccdPtAddVertex(pt, &supp[1]);
692  v[4] = ccdPtAddVertex(pt, &supp[2]);
693  v[5] = ccdPtAddVertex(pt, &supp[3]);
694 
695  e[0] = ccdPtAddEdge(pt, v[0], v[1]);
696  e[1] = ccdPtAddEdge(pt, v[1], v[2]);
697  e[2] = ccdPtAddEdge(pt, v[2], v[3]);
698  e[3] = ccdPtAddEdge(pt, v[3], v[0]);
699 
700  e[4] = ccdPtAddEdge(pt, v[4], v[0]);
701  e[5] = ccdPtAddEdge(pt, v[4], v[1]);
702  e[6] = ccdPtAddEdge(pt, v[4], v[2]);
703  e[7] = ccdPtAddEdge(pt, v[4], v[3]);
704 
705  e[8] = ccdPtAddEdge(pt, v[5], v[0]);
706  e[9] = ccdPtAddEdge(pt, v[5], v[1]);
707  e[10] = ccdPtAddEdge(pt, v[5], v[2]);
708  e[11] = ccdPtAddEdge(pt, v[5], v[3]);
709 
710  if (ccdPtAddFace(pt, e[4], e[5], e[0]) == NULL
711  || ccdPtAddFace(pt, e[5], e[6], e[1]) == NULL
712  || ccdPtAddFace(pt, e[6], e[7], e[2]) == NULL
713  || ccdPtAddFace(pt, e[7], e[4], e[3]) == NULL
714 
715  || ccdPtAddFace(pt, e[8], e[9], e[0]) == NULL
716  || ccdPtAddFace(pt, e[9], e[10], e[1]) == NULL
717  || ccdPtAddFace(pt, e[10], e[11], e[2]) == NULL
718  || ccdPtAddFace(pt, e[11], e[8], e[3]) == NULL){
719  return -2;
720  }
721 
722  return 0;
723 }
724 
725 #ifndef NDEBUG
726 static bool isPolytopeEmpty(const ccd_pt_t& polytope) {
727  ccd_pt_vertex_t* v = nullptr;
728  ccdListForEachEntry(&polytope.vertices, v, ccd_pt_vertex_t, list) {
729  if (v) {
730  return false;
731  }
732  }
733  ccd_pt_edge_t* e = nullptr;
734  ccdListForEachEntry(&polytope.edges, e, ccd_pt_edge_t, list) {
735  if (e) {
736  return false;
737  }
738  }
739  ccd_pt_face_t* f = nullptr;
740  ccdListForEachEntry(&polytope.faces, f, ccd_pt_face_t, list) {
741  if (f) {
742  return false;
743  }
744  }
745  return true;
746 }
747 #endif
748 
766 static int convert2SimplexToTetrahedron(const void* obj1, const void* obj2,
767  const ccd_t* ccd, const ccd_simplex_t* simplex,
768  ccd_pt_t* polytope, ccd_pt_el_t** nearest) {
769  assert(nearest);
770  assert(isPolytopeEmpty(*polytope));
771  assert(simplex->last == 2); // a 2-simplex.
772  const ccd_support_t *a, *b, *c;
773  ccd_support_t d, d2;
774  ccd_vec3_t ab, ac, dir;
775  ccd_pt_vertex_t* v[4];
776  ccd_pt_edge_t* e[6];
777 
778  *nearest = NULL;
779 
780  a = ccdSimplexPoint(simplex, 0);
781  b = ccdSimplexPoint(simplex, 1);
782  c = ccdSimplexPoint(simplex, 2);
783 
784  // The 2-simplex is just a triangle containing the origin. We will expand this
785  // triangle to a tetrahedron, by adding the support point along the normal
786  // direction of the triangle.
787  ccdVec3Sub2(&ab, &b->v, &a->v);
788  ccdVec3Sub2(&ac, &c->v, &a->v);
789  ccdVec3Cross(&dir, &ab, &ac);
790  __ccdSupport(obj1, obj2, &dir, ccd, &d);
791  const ccd_real_t dist_squared =
792  ccdVec3PointTriDist2NoWitness(&d.v, &a->v, &b->v, &c->v);
793 
794  // and second one take in opposite direction
795  ccdVec3Scale(&dir, -CCD_ONE);
796  __ccdSupport(obj1, obj2, &dir, ccd, &d2);
797  const ccd_real_t dist_squared_opposite =
798  ccdVec3PointTriDist2NoWitness(&d2.v, &a->v, &b->v, &c->v);
799 
800  // check if face isn't already on edge of minkowski sum and thus we
801  // have touching contact
802  if (ccdIsZero(dist_squared) || ccdIsZero(dist_squared_opposite)) {
803  v[0] = ccdPtAddVertex(polytope, a);
804  v[1] = ccdPtAddVertex(polytope, b);
805  v[2] = ccdPtAddVertex(polytope, c);
806  e[0] = ccdPtAddEdge(polytope, v[0], v[1]);
807  e[1] = ccdPtAddEdge(polytope, v[1], v[2]);
808  e[2] = ccdPtAddEdge(polytope, v[2], v[0]);
809  *nearest = (ccd_pt_el_t*)ccdPtAddFace(polytope, e[0], e[1], e[2]);
810  if (*nearest == NULL) return -2;
811 
812  return -1;
813  }
814  // Form a tetrahedron with abc as one face, pick either d or d2, based
815  // on which one has larger distance to the face abc. We pick the larger
816  // distance because it gives a tetrahedron with larger volume, so potentially
817  // more "expanded" than the one with the smaller volume.
818  auto FormTetrahedron = [polytope, a, b, c, &v,
819  &e](const ccd_support_t& new_support) -> int {
820  v[0] = ccdPtAddVertex(polytope, a);
821  v[1] = ccdPtAddVertex(polytope, b);
822  v[2] = ccdPtAddVertex(polytope, c);
823  v[3] = ccdPtAddVertex(polytope, &new_support);
824 
825  e[0] = ccdPtAddEdge(polytope, v[0], v[1]);
826  e[1] = ccdPtAddEdge(polytope, v[1], v[2]);
827  e[2] = ccdPtAddEdge(polytope, v[2], v[0]);
828  e[3] = ccdPtAddEdge(polytope, v[0], v[3]);
829  e[4] = ccdPtAddEdge(polytope, v[1], v[3]);
830  e[5] = ccdPtAddEdge(polytope, v[2], v[3]);
831 
832  // ccdPtAdd*() functions return NULL either if the memory allocation
833  // failed of if any of the input pointers are NULL, so the bad
834  // allocation can be checked by the last calls of ccdPtAddFace()
835  // because the rest of the bad allocations eventually "bubble up" here
836  // Note, there is no requirement on the winding of the face, namely we do
837  // not guarantee if all f.e(0).cross(f.e(1)) points outward (or inward) for
838  // all the faces added below.
839  if (ccdPtAddFace(polytope, e[0], e[1], e[2]) == NULL ||
840  ccdPtAddFace(polytope, e[3], e[4], e[0]) == NULL ||
841  ccdPtAddFace(polytope, e[4], e[5], e[1]) == NULL ||
842  ccdPtAddFace(polytope, e[5], e[3], e[2]) == NULL) {
843  return -2;
844  }
845  return 0;
846  };
847 
848  if (std::abs(dist_squared) > std::abs(dist_squared_opposite)) {
849  return FormTetrahedron(d);
850  } else {
851  return FormTetrahedron(d2);
852  }
853 }
854 
857 static int simplexToPolytope4(const void* obj1, const void* obj2,
858  const ccd_t* ccd, ccd_simplex_t* simplex,
859  ccd_pt_t* pt, ccd_pt_el_t** nearest) {
860  const ccd_support_t *a, *b, *c, *d;
861  bool use_polytope3{false};
862  ccd_pt_vertex_t* v[4];
863  ccd_pt_edge_t* e[6];
864  size_t i;
865 
866  a = ccdSimplexPoint(simplex, 0);
867  b = ccdSimplexPoint(simplex, 1);
868  c = ccdSimplexPoint(simplex, 2);
869  d = ccdSimplexPoint(simplex, 3);
870 
871  // The origin can lie on any of the tetrahedra faces. In fact, for a
872  // degenerate tetrahedron, it could be considered to lie on multiple faces
873  // simultaneously. If it lies on any face, we can simply reduce the dimension
874  // of the simplex to that face and then attempt to construct the polytope from
875  // the resulting face. We simply take the first face which exhibited the
876  // trait.
877 
878  ccd_real_t dist_squared =
879  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &a->v, &b->v, &c->v);
880  if (isAbsValueLessThanEpsSquared(dist_squared)) {
881  use_polytope3 = true;
882  }
883  if (!use_polytope3) {
884  dist_squared =
885  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &a->v, &c->v, &d->v);
886  if (isAbsValueLessThanEpsSquared(dist_squared)) {
887  use_polytope3 = true;
888  ccdSimplexSet(simplex, 1, c);
889  ccdSimplexSet(simplex, 2, d);
890  }
891  }
892  if (!use_polytope3) {
893  dist_squared =
894  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &a->v, &b->v, &d->v);
895  if (isAbsValueLessThanEpsSquared(dist_squared)) {
896  use_polytope3 = true;
897  ccdSimplexSet(simplex, 2, d);
898  }
899  }
900  if (!use_polytope3) {
901  dist_squared =
902  ccdVec3PointTriDist2NoWitness(ccd_vec3_origin, &b->v, &c->v, &d->v);
903  if (isAbsValueLessThanEpsSquared(dist_squared)) {
904  use_polytope3 = true;
905  ccdSimplexSet(simplex, 0, b);
906  ccdSimplexSet(simplex, 1, c);
907  ccdSimplexSet(simplex, 2, d);
908  }
909  }
910 
911  if (use_polytope3) {
912  ccdSimplexSetSize(simplex, 3);
913  return convert2SimplexToTetrahedron(obj1, obj2, ccd, simplex, pt, nearest);
914  }
915 
916  // no touching contact - simply create tetrahedron
917  for (i = 0; i < 4; i++) {
918  v[i] = ccdPtAddVertex(pt, ccdSimplexPoint(simplex, i));
919  }
920 
921  e[0] = ccdPtAddEdge(pt, v[0], v[1]);
922  e[1] = ccdPtAddEdge(pt, v[1], v[2]);
923  e[2] = ccdPtAddEdge(pt, v[2], v[0]);
924  e[3] = ccdPtAddEdge(pt, v[3], v[0]);
925  e[4] = ccdPtAddEdge(pt, v[3], v[1]);
926  e[5] = ccdPtAddEdge(pt, v[3], v[2]);
927 
928  // ccdPtAdd*() functions return NULL either if the memory allocation
929  // failed of if any of the input pointers are NULL, so the bad
930  // allocation can be checked by the last calls of ccdPtAddFace()
931  // because the rest of the bad allocations eventually "bubble up" here
932  if (ccdPtAddFace(pt, e[0], e[1], e[2]) == NULL ||
933  ccdPtAddFace(pt, e[3], e[4], e[0]) == NULL ||
934  ccdPtAddFace(pt, e[4], e[5], e[1]) == NULL ||
935  ccdPtAddFace(pt, e[5], e[3], e[2]) == NULL) {
936  return -2;
937  }
938 
939  return 0;
940 }
941 
943 static bool are_coincident(const ccd_vec3_t& p, const ccd_vec3_t& q) {
944  // This uses a scale-dependent basis for determining coincidence. It examines
945  // each axis independently, and only, if all three axes are sufficiently
946  // close (relative to its own scale), are the two points considered
947  // coincident.
948  //
949  // For dimension i, two values are considered the same if:
950  // |pᵢ - qᵢ| <= ε·max(1, |pᵢ|, |qᵢ|)
951  // And the points are coincident if the previous condition holds for all
952  // `i ∈ {0, 1, 2}` (i.e. the x-, y-, *and* z-dimensions).
953  using std::abs;
954  using std::max;
955 
956  constexpr ccd_real_t eps = constants<ccd_real_t>::eps();
957  // NOTE: Wrapping "1.0" with ccd_real_t accounts for mac problems where ccd
958  // is actually float based.
959  for (int i = 0; i < 3; ++i) {
960  const ccd_real_t tolerance =
961  max({ccd_real_t{1}, abs(p.v[i]), abs(q.v[i])}) * eps;
962  const ccd_real_t delta = abs(p.v[i] - q.v[i]);
963  if (delta > tolerance) return false;
964  }
965  return true;
966 }
967 
974 static bool triangle_area_is_zero(const ccd_vec3_t& a, const ccd_vec3_t& b,
975  const ccd_vec3_t& c) {
976  // First coincidence condition. This doesn't *explicitly* test for b and c
977  // being coincident. That will be captured in the subsequent co-linearity
978  // test. If b and c *were* coincident, it would be cheaper to perform the
979  // coincidence test than the co-linearity test.
980  // However, the expectation is that typically the triangle will not have zero
981  // area. In that case, we want to minimize the number of tests performed on
982  // the average, so we prefer to eliminate one coincidence test.
983  if (are_coincident(a, b) || are_coincident(a, c)) return true;
984 
985  // We're going to compute the *sine* of the angle θ between edges (given that
986  // the vertices are *not* coincident). If the sin(θ) < ε, the edges are
987  // co-linear.
988  ccd_vec3_t AB, AC, n;
989  ccdVec3Sub2(&AB, &b, &a);
990  ccdVec3Sub2(&AC, &c, &a);
991  ccdVec3Normalize(&AB);
992  ccdVec3Normalize(&AC);
993  ccdVec3Cross(&n, &AB, &AC);
994  constexpr ccd_real_t eps = constants<ccd_real_t>::eps();
995  // Second co-linearity condition.
996  if (ccdVec3Len2(&n) < eps * eps) return true;
997  return false;
998 }
999 
1013 static ccd_vec3_t faceNormalPointingOutward(const ccd_pt_t* polytope,
1014  const ccd_pt_face_t* face) {
1015  // This doesn't necessarily define a triangle; I don't know that the third
1016  // vertex added here is unique from the other two.
1017 #ifndef NDEBUG
1018  // quick test for degeneracy
1019  const ccd_vec3_t& a = face->edge[0]->vertex[1]->v.v;
1020  const ccd_vec3_t& b = face->edge[0]->vertex[0]->v.v;
1021  const ccd_vec3_t& test_v = face->edge[1]->vertex[0]->v.v;
1022  const ccd_vec3_t& c = are_coincident(test_v, a) || are_coincident(test_v, b) ?
1023  face->edge[1]->vertex[1]->v.v : test_v;
1024  if (triangle_area_is_zero(a, b, c)) {
1026  "Cannot compute face normal for a degenerate (zero-area) triangle");
1027  }
1028 #endif
1029  // We find two edges of the triangle as e1 and e2, and the normal vector
1030  // of the face is e1.cross(e2).
1031  ccd_vec3_t e1, e2;
1032  ccdVec3Sub2(&e1, &(face->edge[0]->vertex[1]->v.v),
1033  &(face->edge[0]->vertex[0]->v.v));
1034  ccdVec3Sub2(&e2, &(face->edge[1]->vertex[1]->v.v),
1035  &(face->edge[1]->vertex[0]->v.v));
1036  ccd_vec3_t dir;
1037  // TODO(hongkai.dai): we ignore the degeneracy here, namely we assume e1 and
1038  // e2 are not colinear. We should check if e1 and e2 are colinear, and handle
1039  // this corner case.
1040  ccdVec3Cross(&dir, &e1, &e2);
1041  const ccd_real_t dir_norm = std::sqrt(ccdVec3Len2(&dir));
1042  ccd_vec3_t unit_dir = dir;
1043  ccdVec3Scale(&unit_dir, 1.0 / dir_norm);
1044  // The winding of the triangle is *not* guaranteed. The normal `n = e₁ × e₂`
1045  // may point inside or outside. We rely on the fact that the origin lies
1046  // within the polytope to resolve this ambiguity. A vector from the origin to
1047  // any point on the triangle must point in the "same" direction as the normal
1048  // (positive dot product).
1049 
1050  // However, the distance to the origin may be too small for the origin to
1051  // serve as a reliable witness of inside-ness. In that case, we examine the
1052  // polytope's *other* vertices; they should all lie on the "inside" of the
1053  // current triangle. If at least one is a reliable distance, then that is
1054  // considered to be the inside. If all vertices are "too close" (like the
1055  // origin), then "inside" is defined as the side of the triangle that had the
1056  // most distant vertex.
1057 
1058  // For these tests, we use the arbitrary distance of 0.01 unit length as a
1059  // "reliable" distance for both the origin and other vertices. Even if it
1060  // seems large, the fall through case of comparing the maximum distance will
1061  // always guarantee correctness.
1062  const ccd_real_t dist_tol = 0.01;
1063  // origin_distance_to_plane computes the signed distance from the origin to
1064  // the plane nᵀ * (x - v) = 0 coinciding with the triangle, where v is a
1065  // point on the triangle.
1066  const ccd_real_t origin_distance_to_plane =
1067  ccdVec3Dot(&unit_dir, &(face->edge[0]->vertex[0]->v.v));
1068  if (origin_distance_to_plane < -dist_tol) {
1069  // Origin is more than `dist_tol` away from the plane, but the negative
1070  // value implies that the normal vector is pointing in the wrong direction;
1071  // flip it.
1072  ccdVec3Scale(&dir, ccd_real_t(-1));
1073  } else if (-dist_tol <= origin_distance_to_plane &&
1074  origin_distance_to_plane <= dist_tol) {
1075  // The origin is close to the plane of the face. Pick another vertex to test
1076  // the normal direction.
1077  ccd_real_t max_distance_to_plane = -CCD_REAL_MAX;
1078  ccd_real_t min_distance_to_plane = CCD_REAL_MAX;
1079  ccd_pt_vertex_t* v;
1080  // If the magnitude of the distance_to_plane is larger than dist_tol,
1081  // then it means one of the vertices is at least `dist_tol` away from the
1082  // plane coinciding with the face.
1083  ccdListForEachEntry(&polytope->vertices, v, ccd_pt_vertex_t, list) {
1084  // distance_to_plane is the signed distance from the
1085  // vertex v->v.v to the face, i.e., distance_to_plane = nᵀ *
1086  // (v->v.v - face_point). Note that origin_distance_to_plane = nᵀ *
1087  // face_point.
1088  const ccd_real_t distance_to_plane =
1089  ccdVec3Dot(&unit_dir, &(v->v.v)) - origin_distance_to_plane;
1090  if (distance_to_plane > dist_tol) {
1091  // The vertex is at least dist_tol away from the face plane, on the same
1092  // direction of `dir`. So we flip dir to point it outward from the
1093  // polytope.
1094  ccdVec3Scale(&dir, ccd_real_t(-1));
1095  return dir;
1096  } else if (distance_to_plane < -dist_tol) {
1097  // The vertex is at least `dist_tol` away from the face plane, on the
1098  // opposite direction of `dir`. So `dir` points outward already.
1099  return dir;
1100  } else {
1101  max_distance_to_plane =
1102  std::max(max_distance_to_plane, distance_to_plane);
1103  min_distance_to_plane =
1104  std::min(min_distance_to_plane, distance_to_plane);
1105  }
1106  }
1107  // If max_distance_to_plane > |min_distance_to_plane|, it means that the
1108  // vertices that are on the positive side of the plane, has a larger maximal
1109  // distance than the vertices on the negative side of the plane. Thus we
1110  // regard that `dir` points into the polytope. Hence we flip `dir`.
1111  if (max_distance_to_plane > std::abs(min_distance_to_plane)) {
1112  ccdVec3Scale(&dir, ccd_real_t(-1));
1113  }
1114  }
1115  return dir;
1116 }
1117 
1118 // Return true if the point `pt` is on the outward side of the half-plane, on
1119 // which the triangle `f1 lives. Notice if the point `pt` is exactly on the
1120 // half-plane, the return is false.
1121 // @param f A triangle on a polytope.
1122 // @param pt A point.
1123 static bool isOutsidePolytopeFace(const ccd_pt_t* polytope,
1124  const ccd_pt_face_t* f, const ccd_vec3_t* pt) {
1125  ccd_vec3_t n = faceNormalPointingOutward(polytope, f);
1126  // r_VP is the vector from a vertex V on the face `f`, to the point P `pt`.
1127  ccd_vec3_t r_VP;
1128  ccdVec3Sub2(&r_VP, pt, &(f->edge[0]->vertex[0]->v.v));
1129  return ccdVec3Dot(&n, &r_VP) > 0;
1130 }
1131 
1132 #ifndef NDEBUG
1133 // The function ComputeVisiblePatchRecursiveSanityCheck() is only called in the
1134 // debug mode. In the release mode, this function is declared/defined but not
1135 // used. Without this NDEBUG macro, the function will cause a -Wunused-function
1136 // error on CI's release builds.
1147  const ccd_pt_t& polytope,
1148  const std::unordered_set<ccd_pt_edge_t*>& border_edges,
1149  const std::unordered_set<ccd_pt_face_t*>& visible_faces,
1150  const std::unordered_set<ccd_pt_edge_t*>& internal_edges) {
1151  ccd_pt_face_t* f;
1152  // TODO(SeanCurtis-TRI): Instead of returning false, have this throw the
1153  // exception itself so that it can provide additional information.
1154  ccdListForEachEntry(&polytope.faces, f, ccd_pt_face_t, list) {
1155  bool has_edge_internal = false;
1156  for (int i = 0; i < 3; ++i) {
1157  // Since internal_edges is a set, internal_edges.count(e) means that e
1158  // is contained in the set internal_edges.
1159  if (internal_edges.count(f->edge[i]) > 0) {
1160  has_edge_internal = true;
1161  break;
1162  }
1163  }
1164  if (has_edge_internal) {
1165  if (visible_faces.count(f) == 0) {
1166  return false;
1167  }
1168  }
1169  }
1170  ccd_pt_edge_t* e;
1171  ccdListForEachEntry(&polytope.edges, e, ccd_pt_edge_t, list) {
1172  if (visible_faces.count(e->faces[0]) > 0 &&
1173  visible_faces.count(e->faces[1]) > 0) {
1174  if (internal_edges.count(e) == 0) {
1175  return false;
1176  }
1177  } else if (visible_faces.count(e->faces[0]) +
1178  visible_faces.count(e->faces[1]) ==
1179  1) {
1180  if (border_edges.count(e) == 0) {
1181  return false;
1182  }
1183  }
1184  }
1185  for (const auto b : border_edges) {
1186  if (internal_edges.count(b) > 0) {
1187  return false;
1188  }
1189  }
1190  return true;
1191 }
1192 #endif
1193 
1202  std::unordered_set<ccd_pt_edge_t*>* border_edges,
1203  std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1204  border_edges->insert(edge);
1205  if (internal_edges->count(edge) > 0) {
1207  "An edge is being classified as border that has already been "
1208  "classifed as internal");
1209  }
1210 }
1211 
1220  std::unordered_set<ccd_pt_edge_t*>* border_edges,
1221  std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1222  internal_edges->insert(edge);
1223  if (border_edges->count(edge) > 0) {
1225  "An edge is being classified as internal that has already been "
1226  "classified as border");
1227  }
1228 }
1229 
1244  const ccd_pt_t& polytope, ccd_pt_face_t& f, int edge_index,
1245  const ccd_vec3_t& query_point,
1246  std::unordered_set<ccd_pt_edge_t*>* border_edges,
1247  std::unordered_set<ccd_pt_face_t*>* visible_faces,
1248  std::unordered_set<ccd_pt_face_t*>* hidden_faces,
1249  std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1250  ccd_pt_edge_t* edge = f.edge[edge_index];
1251 
1252  ccd_pt_face_t* g = edge->faces[0] == &f ? edge->faces[1] : edge->faces[0];
1253  assert(g != nullptr);
1254 
1255  bool is_visible = visible_faces->count(g) > 0;
1256  bool is_hidden = hidden_faces->count(g) > 0;
1257  assert(!(is_visible && is_hidden));
1258 
1259  // First check to see if face `g` has been classifed already.
1260  if (is_visible) {
1261  // Face f is visible (prerequisite), and g has been previously
1262  // marked visible (via a different path); their shared edge should be
1263  // marked internal.
1264  ClassifyInternalEdge(edge, border_edges, internal_edges);
1265  return;
1266  }
1267 
1268  if (is_hidden) {
1269  // Face *has* already been classified as hidden; we just need to classify
1270  // the edge.
1271  ClassifyBorderEdge(edge, border_edges, internal_edges);
1272  return;
1273  }
1274 
1275  // Face `g` has not been classified yet. Try to classify it as visible (i.e.,
1276  // the `query_point` lies outside of this face).
1277  is_visible = isOutsidePolytopeFace(&polytope, g, &query_point);
1278  if (!is_visible) {
1279  // Face `g` is *apparently* not visible from the query point. However, it
1280  // might _still_ be considered visible. The query point could be co-linear
1281  // with `edge` which, by definition means that `g` *is* visible and
1282  // numerical error led to considering it hidden. We can detect this case
1283  // if the triangle formed by edge and query point has zero area.
1284  //
1285  // It may be that the previous designation that `f` was visible was a
1286  // mistake and now face `g` is inheriting that visible status. This is a
1287  // conservative resolution that will prevent us from creating co-planar
1288  // faces (at the cost of a longer border).
1289  is_visible = triangle_area_is_zero(query_point, edge->vertex[0]->v.v,
1290  edge->vertex[1]->v.v);
1291  }
1292 
1293  if (is_visible) {
1294  visible_faces->insert(g);
1295  ClassifyInternalEdge(edge, border_edges, internal_edges);
1296  for (int i = 0; i < 3; ++i) {
1297  if (g->edge[i] != edge) {
1298  // One of the neighbouring face is `f`, so do not need to visit again.
1299  ComputeVisiblePatchRecursive(polytope, *g, i, query_point, border_edges,
1300  visible_faces, hidden_faces,
1301  internal_edges);
1302  }
1303  }
1304  } else {
1305  // No logic could classify the face as visible, so mark it hidden and
1306  // mark the edge as a border edge.
1307  ClassifyBorderEdge(edge, border_edges, internal_edges);
1308  hidden_faces->insert(g);
1309  }
1310 }
1311 
1347  const ccd_pt_t& polytope, ccd_pt_face_t& f,
1348  const ccd_vec3_t& query_point,
1349  std::unordered_set<ccd_pt_edge_t*>* border_edges,
1350  std::unordered_set<ccd_pt_face_t*>* visible_faces,
1351  std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1352  assert(border_edges);
1353  assert(visible_faces);
1354  assert(internal_edges);
1355  assert(border_edges->empty());
1356  assert(visible_faces->empty());
1357  assert(internal_edges->empty());
1358  assert(isOutsidePolytopeFace(&polytope, &f, &query_point));
1359  std::unordered_set<ccd_pt_face_t*> hidden_faces;
1360  visible_faces->insert(&f);
1361  for (int edge_index = 0; edge_index < 3; ++edge_index) {
1362  ComputeVisiblePatchRecursive(polytope, f, edge_index, query_point,
1363  border_edges, visible_faces, &hidden_faces,
1364  internal_edges);
1365  }
1366 #ifndef NDEBUG
1367  // TODO(SeanCurtis-TRI): Extend the sanity check to include hidden_faces.
1369  polytope, *border_edges, *visible_faces, *internal_edges)) {
1371  "The visible patch failed its sanity check");
1372  }
1373 #endif
1374 }
1375 
1402 static int expandPolytope(ccd_pt_t *polytope, ccd_pt_el_t *el,
1403  const ccd_support_t *newv)
1404 {
1405  // The outline of the algorithm is as follows:
1406  // 1. Compute the visible patch relative to the new vertex (See
1407  // ComputeVisiblePatch() for details).
1408  // 2. Delete the faces and internal edges.
1409  // 3. Build a new face from each border edge and the new vertex.
1410 
1411  // To remove all faces that can be seen from the new vertex, we start with the
1412  // face on which the closest point lives, and then do a depth-first search on
1413  // its neighbouring triangles, until the triangle cannot be seen from the new
1414  // vertex.
1415  // TODO(hongkai.dai@tri.global): it is inefficient to store visible
1416  // faces/edges. A better implementation should remove visible faces and
1417  // internal edges inside ComputeVisiblePatch() function, when traversing the
1418  // faces on the polytope. We focus on the correctness in the first place.
1419  // Later when we make sure that the whole EPA implementation is bug free, we
1420  // will improve the performance.
1421 
1422  ccd_pt_face_t* start_face = NULL;
1423 
1424  if (el->type == CCD_PT_VERTEX) {
1426  "The visible feature is a vertex. This should already have been "
1427  "identified as a touching contact");
1428  }
1429  // Start with the face on which the closest point lives
1430  if (el->type == CCD_PT_FACE) {
1431  start_face = reinterpret_cast<ccd_pt_face_t*>(el);
1432  } else if (el->type == CCD_PT_EDGE) {
1433  // Check the two neighbouring faces of the edge.
1434  ccd_pt_face_t* f[2];
1435  ccdPtEdgeFaces(reinterpret_cast<ccd_pt_edge_t*>(el), &f[0], &f[1]);
1436  if (isOutsidePolytopeFace(polytope, f[0], &newv->v)) {
1437  start_face = f[0];
1438  } else if (isOutsidePolytopeFace(polytope, f[1], &newv->v)) {
1439  start_face = f[1];
1440  } else {
1442  "Both the nearest point and the new vertex are on an edge, thus the "
1443  "nearest distance should be 0. This is touching contact, and should "
1444  "already have been identified");
1445  }
1446  }
1447 
1448  std::unordered_set<ccd_pt_face_t*> visible_faces;
1449  std::unordered_set<ccd_pt_edge_t*> internal_edges;
1450  std::unordered_set<ccd_pt_edge_t*> border_edges;
1451  ComputeVisiblePatch(*polytope, *start_face, newv->v, &border_edges,
1452  &visible_faces, &internal_edges);
1453 
1454  // Now remove all the obsolete faces.
1455  // TODO(hongkai.dai@tri.global): currently we need to loop through each face
1456  // in visible_faces, and then do a linear search in the list pt->faces to
1457  // delete `face`. It would be better if we only loop through the list
1458  // polytope->faces for once. Same for the edges.
1459  for (const auto& f : visible_faces) {
1460  ccdPtDelFace(polytope, f);
1461  }
1462 
1463  // Now remove all the obsolete edges.
1464  for (const auto& e : internal_edges) {
1465  ccdPtDelEdge(polytope, e);
1466  }
1467 
1468  // Note: this does not delete any vertices that were on the interior of the
1469  // deleted patch. There are no longer any faces or edges that reference them.
1470  // Technically, they are still part of the polytope but have no effect (except
1471  // for footprint in memory). It's just as simple to leave them, knowing the
1472  // whole polytope will be destroyed when we're done with the query.
1473 
1474  // A vertex cannot be obsolete, since a vertex is always on the boundary of
1475  // the Minkowski difference A ⊖ B.
1476  // TODO(hongkai.dai@tri.global): as a sanity check, we should make sure that
1477  // all vertices has at least one face/edge invisible from the new vertex
1478  // `newv`.
1479 
1480  // Now add the new vertex.
1481  ccd_pt_vertex_t* new_vertex = ccdPtAddVertex(polytope, newv);
1482 
1483  // Now add the new edges and faces, by connecting the new vertex with vertices
1484  // on border_edges. map_vertex_to_new_edge maps a vertex on the silhouette
1485  // edges to a new edge, with one end being the new vertex, and the other end
1486  // being that vertex on the silhouette edges.
1487  std::unordered_map<ccd_pt_vertex_t*, ccd_pt_edge_t*> map_vertex_to_new_edge;
1488  for (const auto& border_edge : border_edges) {
1489  ccd_pt_edge_t* e[2]; // The two new edges added by connecting new_vertex
1490  // to the two vertices on border_edge.
1491  for (int i = 0; i < 2; ++i) {
1492  auto it = map_vertex_to_new_edge.find(border_edge->vertex[i]);
1493  if (it == map_vertex_to_new_edge.end()) {
1494  // This edge has not been added yet.
1495  e[i] = ccdPtAddEdge(polytope, new_vertex, border_edge->vertex[i]);
1496  map_vertex_to_new_edge.emplace_hint(it, border_edge->vertex[i],
1497  e[i]);
1498  } else {
1499  e[i] = it->second;
1500  }
1501  }
1502  // Now add the face.
1503  ccdPtAddFace(polytope, border_edge, e[0], e[1]);
1504  }
1505 
1506  return 0;
1507 }
1508 
1520 static ccd_vec3_t supportEPADirection(const ccd_pt_t* polytope,
1521  const ccd_pt_el_t* nearest_feature) {
1522  /*
1523  If we denote the nearest point as v, when v is not the origin, then the
1524  support direction is v. If v is the origin, then v should be an interior
1525  point on a face, and the support direction is the normal of that face,
1526  pointing outward from the polytope.
1527  */
1528  ccd_vec3_t dir;
1529  if (ccdIsZero(nearest_feature->dist)) {
1530  // nearest point is the origin.
1531  switch (nearest_feature->type) {
1532  case CCD_PT_VERTEX: {
1534  "The nearest point to the origin is a vertex of the polytope. This "
1535  "should be identified as a touching contact");
1536  break;
1537  }
1538  case CCD_PT_EDGE: {
1539  // When the nearest point is on an edge, the origin must be on that
1540  // edge. The support direction could be in the range between
1541  // edge.faces[0].normal and edge.faces[1].normal, where the face normals
1542  // point outward from the polytope. In this implementation, we
1543  // arbitrarily choose faces[0] normal.
1544  const ccd_pt_edge_t* edge =
1545  reinterpret_cast<const ccd_pt_edge_t*>(nearest_feature);
1546  dir = faceNormalPointingOutward(polytope, edge->faces[0]);
1547  break;
1548  }
1549  case CCD_PT_FACE: {
1550  // If origin is an interior point of a face, then choose the normal of
1551  // that face as the sample direction.
1552  const ccd_pt_face_t* face =
1553  reinterpret_cast<const ccd_pt_face_t*>(nearest_feature);
1554  dir = faceNormalPointingOutward(polytope, face);
1555  break;
1556  }
1557  }
1558  } else {
1559  ccdVec3Copy(&dir, &(nearest_feature->witness));
1560  }
1561  ccdVec3Normalize(&dir);
1562  return dir;
1563 }
1564 
1584 static int nextSupport(const ccd_pt_t* polytope, const void* obj1,
1585  const void* obj2, const ccd_t* ccd,
1586  const ccd_pt_el_t* el, ccd_support_t* out) {
1587  ccd_vec3_t *a, *b, *c;
1588 
1589  if (el->type == CCD_PT_VERTEX) return -1;
1590 
1591  const ccd_vec3_t dir = supportEPADirection(polytope, el);
1592 
1593  __ccdSupport(obj1, obj2, &dir, ccd, out);
1594 
1595  // Compute distance of support point in the support direction, so we can
1596  // determine whether we expanded a polytope surrounding the origin a bit.
1597  const ccd_real_t dist = ccdVec3Dot(&out->v, &dir);
1598 
1599  // el->dist is the squared distance from the feature "el" to the origin..
1600  // dist is an upper bound on the distance from the boundary of the Minkowski
1601  // difference to the origin, and sqrt(el->dist) is a lower bound of that
1602  // distance.
1603  if (dist - std::sqrt(el->dist) < ccd->epa_tolerance) return -1;
1604 
1605  ccd_real_t dist_squared{};
1606  if (el->type == CCD_PT_EDGE) {
1607  // fetch end points of edge
1608  ccdPtEdgeVec3(reinterpret_cast<const ccd_pt_edge_t*>(el), &a, &b);
1609 
1610  // get distance from segment
1611  dist_squared = ccdVec3PointSegmentDist2(&out->v, a, b, NULL);
1612  } else { // el->type == CCD_PT_FACE
1613  // fetch vertices of triangle face
1614  ccdPtFaceVec3(reinterpret_cast<const ccd_pt_face_t*>(el), &a, &b, &c);
1615 
1616  // check if new point can significantly expand polytope
1617  dist_squared = ccdVec3PointTriDist2NoWitness(&out->v, a, b, c);
1618  }
1619 
1620  if (std::sqrt(dist_squared) < ccd->epa_tolerance) return -1;
1621 
1622  return 0;
1623 }
1624 
1625 
1626 static int __ccdGJK(const void *obj1, const void *obj2,
1627  const ccd_t *ccd, ccd_simplex_t *simplex)
1628 {
1629  unsigned long iterations;
1630  ccd_vec3_t dir; // direction vector
1631  ccd_support_t last; // last support point
1632  int do_simplex_res;
1633 
1634  // initialize simplex struct
1635  ccdSimplexInit(simplex);
1636 
1637  // get first direction
1638  ccd->first_dir(obj1, obj2, &dir);
1639  // get first support point
1640  __ccdSupport(obj1, obj2, &dir, ccd, &last);
1641  // and add this point to simplex as last one
1642  ccdSimplexAdd(simplex, &last);
1643 
1644  // set up direction vector to as (O - last) which is exactly -last
1645  ccdVec3Copy(&dir, &last.v);
1646  ccdVec3Scale(&dir, -CCD_ONE);
1647 
1648  // start iterations
1649  for (iterations = 0UL; iterations < ccd->max_iterations; ++iterations) {
1650  // obtain support point
1651  __ccdSupport(obj1, obj2, &dir, ccd, &last);
1652 
1653  // check if farthest point in Minkowski difference in direction dir
1654  // isn't somewhere before origin (the test on negative dot product)
1655  // - because if it is, objects are not intersecting at all.
1656  if (ccdVec3Dot(&last.v, &dir) < CCD_ZERO){
1657  return -1; // intersection not found
1658  }
1659 
1660  // add last support vector to simplex
1661  ccdSimplexAdd(simplex, &last);
1662 
1663  // if doSimplex returns 1 if objects intersect, -1 if objects don't
1664  // intersect and 0 if algorithm should continue
1665  do_simplex_res = doSimplex(simplex, &dir);
1666  if (do_simplex_res == 1){
1667  return 0; // intersection found
1668  }else if (do_simplex_res == -1){
1669  return -1; // intersection not found
1670  }
1671 
1672  if (ccdIsZero(ccdVec3Len2(&dir))){
1673  return -1; // intersection not found
1674  }
1675  }
1676 
1677  // intersection wasn't found
1678  return -1;
1679 }
1680 
1700  assert(polytope->nearest_type == CCD_PT_EDGE);
1701 
1702  // We define epsilon to include an additional bit of noise. The goal is to
1703  // pick the smallest epsilon possible. This factor of two proved necessary
1704  // due to unit test behavior on the mac. In the future, as we collect
1705  // more evidence, it may be necessary to increase to more bits. But the need
1706  // should always be demonstrable and not purely theoretical.
1707  constexpr ccd_real_t kEps = 2 * constants<ccd_real_t>::eps();
1708 
1709  // Only verify the feature if the nearest feature is an edge.
1710 
1711  const ccd_pt_edge_t* const nearest_edge =
1712  reinterpret_cast<ccd_pt_edge_t*>(polytope->nearest);
1713  // Find the outward normals on the two neighbouring faces of the edge, if
1714  // the origin is on the "inner" side of these two faces, then we regard the
1715  // origin to be inside the polytope. Note that these face_normals are
1716  // normalized.
1717  std::array<ccd_vec3_t, 2> face_normals;
1718  std::array<double, 2> origin_to_face_distance;
1719 
1720  // We define the plane equation using vertex[0]. If vertex[0] is far away
1721  // from the origin, it can magnify rounding error. We scale epsilon to account
1722  // for this possibility.
1723  const ccd_real_t v0_dist =
1724  std::sqrt(ccdVec3Len2(&nearest_edge->vertex[0]->v.v));
1725  const ccd_real_t plane_threshold =
1726  kEps * std::max(static_cast<ccd_real_t>(1.0), v0_dist);
1727 
1728  for (int i = 0; i < 2; ++i) {
1729  face_normals[i] =
1730  faceNormalPointingOutward(polytope, nearest_edge->faces[i]);
1731  ccdVec3Normalize(&face_normals[i]);
1732  // If the origin o is on the "inner" side of the face, then
1733  // n̂ ⋅ (o - vₑ) ≤ 0 or, with simplification, -n̂ ⋅ vₑ ≤ 0 (since n̂ ⋅ o = 0).
1734  origin_to_face_distance[i] =
1735  -ccdVec3Dot(&face_normals[i], &nearest_edge->vertex[0]->v.v);
1736  // If the origin lies *on* the edge, then it also lies on the two adjacent
1737  // faces. Rather than failing on strictly *positive* signed distance, we
1738  // introduce an epsilon threshold. This usage of epsilon is to account for a
1739  // discrepancy in the signed distance computation. How GJK (and partially
1740  // EPA) compute the signed distance from origin to face may *not* be exactly
1741  // the same as done in this test (i.e. for a given set of vertices, the
1742  // plane equation can be defined various ways. Those ways are
1743  // *mathematically* equivalent but numerically will differ due to rounding).
1744  // We account for those differences by allowing a very small positive signed
1745  // distance to be considered zero. We assume that the GJK/EPA code
1746  // ultimately classifies inside/outside around *zero* and *not* epsilon.
1747  if (origin_to_face_distance[i] > plane_threshold) {
1748  std::ostringstream oss;
1749  oss << "The origin is outside of the polytope by "
1750  << origin_to_face_distance[i] << ", exceeding the threshold "
1751  << plane_threshold
1752  << ". This should already have been identified as separating.";
1754  }
1755  }
1756 
1757  // We know the reported squared distance to the edge. If that distance is
1758  // functionally zero, then the edge must *truly* be the nearest feature.
1759  // If it isn't, then it must be one of the adjacent faces.
1760  const bool is_edge_closest_feature = nearest_edge->dist < kEps * kEps;
1761 
1762  if (!is_edge_closest_feature) {
1763  // We assume that libccd is not crazily wrong. Although the closest
1764  // feature is not the edge, it is near that edge. Hence we select the
1765  // neighboring face that is closest to the origin.
1766  polytope->nearest_type = CCD_PT_FACE;
1767  // Note origin_to_face_distance is the *signed* distance and it is
1768  // guaranteed to be negative if we are here, hence sense of this
1769  // comparison is reversed.
1770  const int closest_face =
1771  origin_to_face_distance[0] < origin_to_face_distance[1] ? 1 : 0;
1772  polytope->nearest =
1773  reinterpret_cast<ccd_pt_el_t*>(nearest_edge->faces[closest_face]);
1774  // polytope->nearest_dist stores the SQUARED distance.
1775  polytope->nearest_dist = pow(origin_to_face_distance[closest_face], 2);
1776  }
1777 }
1778 
1779 static int __ccdEPA(const void *obj1, const void *obj2,
1780  const ccd_t *ccd,
1781  ccd_simplex_t* simplex,
1782  ccd_pt_t *polytope, ccd_pt_el_t **nearest)
1783 {
1784  ccd_support_t supp; // support point
1785  int ret, size;
1786 
1787 
1788  ret = 0;
1789  *nearest = NULL;
1790 
1791  // transform simplex to polytope - simplex won't be used anymore
1792  size = ccdSimplexSize(simplex);
1793  if (size == 4){
1794  ret = simplexToPolytope4(obj1, obj2, ccd, simplex, polytope, nearest);
1795  } else if (size == 3) {
1796  ret = convert2SimplexToTetrahedron(obj1, obj2, ccd, simplex, polytope,
1797  nearest);
1798  }else{ // size == 2
1799  ret = simplexToPolytope2(obj1, obj2, ccd, simplex, polytope, nearest);
1800  }
1801 
1802 
1803  if (ret == -1){
1804  // touching contact
1805  return 0;
1806  }else if (ret == -2){
1807  // failed memory allocation
1808  return -2;
1809  }
1810 
1811  while (1) {
1812  // get triangle nearest to origin
1813  *nearest = ccdPtNearest(polytope);
1814  if (polytope->nearest_type == CCD_PT_EDGE) {
1815  // When libccd thinks the nearest feature is an edge, that is often
1816  // wrong, hence we validate the nearest feature by ourselves.
1817  // TODO remove this validation step when we can reliably compute the
1818  // nearest feature of a polytope.
1820  *nearest = ccdPtNearest(polytope);
1821  }
1822 
1823  // get next support point
1824  if (nextSupport(polytope, obj1, obj2, ccd, *nearest, &supp) != 0) {
1825  break;
1826  }
1827 
1828  // expand nearest triangle using new point - supp
1829  if (expandPolytope(polytope, *nearest, &supp) != 0) return -2;
1830  }
1831 
1832  return 0;
1833 }
1834 
1837 static void extractObjectPointsFromPoint(ccd_support_t *q, ccd_vec3_t *p1,
1838  ccd_vec3_t *p2) {
1839  // TODO(SeanCurtis-TRI): Determine if I should be demanding that p1 and p2
1840  // are defined.
1841  // Closest points are the ones stored in the simplex
1842  if (p1) *p1 = q->v1;
1843  if (p2) *p2 = q->v2;
1844 }
1845 
1851  ccd_vec3_t *p1, ccd_vec3_t *p2,
1852  ccd_vec3_t *p) {
1853  // Closest points lie on the segment defined by the points in the simplex
1854  // Let the segment be defined by points A and B. We can write p as
1855  //
1856  // p = A + s*AB, 0 <= s <= 1
1857  // p - A = s*AB
1858  ccd_vec3_t AB;
1859  ccdVec3Sub2(&AB, &(b->v), &(a->v));
1860 
1861  // This defines three equations, but we only need one. Taking the i-th
1862  // component gives
1863  //
1864  // p_i - A_i = s*AB_i.
1865  //
1866  // Thus, s is given by
1867  //
1868  // s = (p_i - A_i)/AB_i.
1869  //
1870  // To avoid dividing by an AB_i ≪ 1, we choose i such that |AB_i| is
1871  // maximized
1872  ccd_real_t abs_AB_x{std::abs(ccdVec3X(&AB))};
1873  ccd_real_t abs_AB_y{std::abs(ccdVec3Y(&AB))};
1874  ccd_real_t abs_AB_z{std::abs(ccdVec3Z(&AB))};
1875 
1876  ccd_real_t A_i, AB_i, p_i;
1877  if (abs_AB_x >= abs_AB_y && abs_AB_x >= abs_AB_z) {
1878  A_i = ccdVec3X(&(a->v));
1879  AB_i = ccdVec3X(&AB);
1880  p_i = ccdVec3X(p);
1881  } else if (abs_AB_y >= abs_AB_z) {
1882  A_i = ccdVec3Y(&(a->v));
1883  AB_i = ccdVec3Y(&AB);
1884  p_i = ccdVec3Y(p);
1885  } else {
1886  A_i = ccdVec3Z(&(a->v));
1887  AB_i = ccdVec3Z(&AB);
1888  p_i = ccdVec3Z(p);
1889  }
1890 
1891  if (std::abs(AB_i) < constants<ccd_real_t>::eps()) {
1892  // Points are coincident; treat as a single point.
1893  extractObjectPointsFromPoint(a, p1, p2);
1894  return;
1895  }
1896 
1897  auto calc_p = [](ccd_vec3_t *p_a, ccd_vec3_t *p_b, ccd_vec3_t *p,
1898  ccd_real_t s) {
1899  ccd_vec3_t sAB;
1900  ccdVec3Sub2(&sAB, p_b, p_a);
1901  ccdVec3Scale(&sAB, s);
1902  ccdVec3Copy(p, p_a);
1903  ccdVec3Add(p, &sAB);
1904  };
1905 
1906  // TODO(SeanCurtis-TRI): If p1 or p2 is null, there seems little point in
1907  // calling this method. It seems that both of these being non-null should be
1908  // a *requirement*. Determine that this is the case and do so.
1909  ccd_real_t s = (p_i - A_i) / AB_i;
1910 
1911  if (p1) {
1912  // p1 = A1 + s*A1B1
1913  calc_p(&(a->v1), &(b->v1), p1, s);
1914  }
1915  if (p2) {
1916  // p2 = A2 + s*A2B2
1917  calc_p(&(a->v2), &(b->v2), p2, s);
1918  }
1919 }
1920 
1926 static void extractClosestPoints(ccd_simplex_t *simplex, ccd_vec3_t *p1,
1927  ccd_vec3_t *p2, ccd_vec3_t *p) {
1928  const int simplex_size = ccdSimplexSize(simplex);
1929  assert(simplex_size <= 3);
1930  if (simplex_size == 1)
1931  {
1932  extractObjectPointsFromPoint(&simplex->ps[0], p1, p2);
1933  }
1934  else if (simplex_size == 2)
1935  {
1936  extractObjectPointsFromSegment(&simplex->ps[0], &simplex->ps[1], p1, p2, p);
1937  }
1938  else // simplex_size == 3
1939  {
1940  if (triangle_area_is_zero(simplex->ps[0].v, simplex->ps[1].v,
1941  simplex->ps[2].v)) {
1942  // The triangle is degenerate; compute the nearest point to a line
1943  // segment. The segment is defined by the most-distant vertex pair.
1944  int a_index, b_index;
1945  ccd_vec3_t AB, AC, BC;
1946  ccdVec3Sub2(&AB, &(simplex->ps[1].v), &(simplex->ps[0].v));
1947  ccdVec3Sub2(&AC, &(simplex->ps[2].v), &(simplex->ps[0].v));
1948  ccdVec3Sub2(&BC, &(simplex->ps[2].v), &(simplex->ps[1].v));
1949  ccd_real_t AB_len2 = ccdVec3Len2(&AB);
1950  ccd_real_t AC_len2 = ccdVec3Len2(&AC);
1951  ccd_real_t BC_len2 = ccdVec3Len2(&BC);
1952  if (AB_len2 >= AC_len2 && AB_len2 >= BC_len2) {
1953  a_index = 0;
1954  b_index = 1;
1955  } else if (AC_len2 >= AB_len2 && AC_len2 >= BC_len2) {
1956  a_index = 0;
1957  b_index = 2;
1958  } else {
1959  a_index = 1;
1960  b_index = 2;
1961  }
1962  extractObjectPointsFromSegment(&simplex->ps[a_index],
1963  &simplex->ps[b_index], p1, p2, p);
1964  return;
1965  }
1966 
1967  // Compute the barycentric coordinates of point p in triangle ABC.
1968  //
1969  // A
1970  // ╱╲ p = αA + βB + γC
1971  // ╱ |╲
1972  // ╱ | ╲ α = 1 - β - γ
1973  // ╱ p | ╲ β = AREA(pAC) / AREA(ABC)
1974  // ╱ / \ ╲ γ = AREA(pAB) / AREA(ABC)
1975  // ╱__/_____\_╲
1976  // B C AREA(XYZ) = |r_XY × r_XZ| / 2
1977  //
1978  // Rewrite coordinates in terms of cross products.
1979  //
1980  // β = AREA(pAC) / AREA(ABC) = |r_Ap × r_AC| / |r_AB × r_AC|
1981  // γ = AREA(pAB) / AREA(ABC) = |r_AB × r_Ap| / |r_AB × r_AC|
1982  //
1983  // NOTE: There are multiple options for the cross products, these have been
1984  // selected to re-use as many symbols as possible.
1985  //
1986  // Solving for β and γ:
1987  //
1988  // β = |r_Ap × r_AC| / |r_AB × r_AC|
1989  // β = |r_Ap × r_AC| / |n| n ≙ r_AB × r_AC, n̂ = n / |n|
1990  // β = n̂·(r_Ap × r_AC) / n̂·n This step arises from the fact
1991  // that (r_Ap × r_AC) and n point
1992  // in the same direction. It
1993  // allows us to take a single sqrt
1994  // instead of three.
1995  // β = (n/|n|)·(r_Ap × r_AC) / (n/|n|)·n
1996  // β = n·(r_Ap × r_AC) / n·n
1997  // β = n·(r_Ap × r_AC) / |n|²
1998  //
1999  // A similar process to solve for gamma
2000  // γ = n·(r_AB × r_Ap) / |n|²
2001 
2002  // Compute n and |n|².
2003  ccd_vec3_t r_AB, r_AC, n;
2004  ccdVec3Sub2(&r_AB, &(simplex->ps[1].v), &(simplex->ps[0].v));
2005  ccdVec3Sub2(&r_AC, &(simplex->ps[2].v), &(simplex->ps[0].v));
2006  ccdVec3Cross(&n, &r_AB, &r_AC);
2007  ccd_real_t norm_squared_n{ccdVec3Len2(&n)};
2008 
2009  // Compute r_Ap.
2010  ccd_vec3_t r_Ap;
2011  ccdVec3Sub2(&r_Ap, p, &(simplex->ps[0].v));
2012 
2013  // Compute the cross products in the numerators.
2014  ccd_vec3_t r_Ap_cross_r_AC, r_AB_cross_r_Ap;
2015  ccdVec3Cross(&r_Ap_cross_r_AC, &r_Ap, &r_AC); // r_Ap × r_AC
2016  ccdVec3Cross(&r_AB_cross_r_Ap, &r_AB, &r_Ap); // r_AB × r_Ap
2017 
2018  // Compute beta and gamma.
2019  ccd_real_t beta{ccdVec3Dot(&n, &r_Ap_cross_r_AC) / norm_squared_n};
2020  ccd_real_t gamma{ccdVec3Dot(&n, &r_AB_cross_r_Ap) / norm_squared_n};
2021 
2022  // Evaluate barycentric interpolation (with the locally defined barycentric
2023  // coordinates).
2024  auto interpolate = [&beta, &gamma](const ccd_vec3_t& r_WA,
2025  const ccd_vec3_t& r_WB,
2026  const ccd_vec3_t& r_WC,
2027  ccd_vec3_t* r_WP) {
2028  // r_WP = r_WA + β * r_AB + γ * r_AC
2029  ccdVec3Copy(r_WP, &r_WA);
2030 
2031  ccd_vec3_t beta_r_AB;
2032  ccdVec3Sub2(&beta_r_AB, &r_WB, &r_WA);
2033  ccdVec3Scale(&beta_r_AB, beta);
2034  ccdVec3Add(r_WP, &beta_r_AB);
2035 
2036  ccd_vec3_t gamma_r_AC;
2037  ccdVec3Sub2(&gamma_r_AC, &r_WC, &r_WA);
2038  ccdVec3Scale(&gamma_r_AC, gamma);
2039  ccdVec3Add(r_WP, &gamma_r_AC);
2040  };
2041 
2042  if (p1) {
2043  interpolate(simplex->ps[0].v1, simplex->ps[1].v1, simplex->ps[2].v1, p1);
2044  }
2045 
2046  if (p2) {
2047  interpolate(simplex->ps[0].v2, simplex->ps[1].v2, simplex->ps[2].v2, p2);
2048  }
2049  }
2050 }
2051 
2052 // Computes the distance between two non-penetrating convex objects, `obj1` and
2053 // `obj2` based on the warm-started witness simplex, returning the distance and
2054 // nearest points on each object.
2055 // @param obj1 The first convex object.
2056 // @param obj2 The second convex object.
2057 // @param ccd The libccd configuration.
2058 // @param simplex A witness to the objects' separation generated by the GJK
2059 // algorithm. NOTE: the simplex is not necessarily sufficiently refined to
2060 // report the actual distance and may be further refined in this method.
2061 // @param p1 If the objects are non-penetrating, the point on the surface of
2062 // obj1 closest to obj2 (expressed in the world frame).
2063 // @param p2 If the objects are non-penetrating, the point on the surface of
2064 // obj2 closest to obj1 (expressed in the world frame).
2065 // @returns The minimum distance between the two objects. If they are
2066 // penetrating, -1 is returned.
2067 static inline ccd_real_t _ccdDist(const void *obj1, const void *obj2,
2068  const ccd_t *ccd,
2069  ccd_simplex_t* simplex,
2070  ccd_vec3_t* p1, ccd_vec3_t* p2)
2071 {
2072  ccd_real_t last_dist = CCD_REAL_MAX;
2073 
2074  for (unsigned long iterations = 0UL; iterations < ccd->max_iterations;
2075  ++iterations) {
2076  ccd_vec3_t closest_p; // The point on the simplex that is closest to the
2077  // origin.
2078  ccd_real_t dist;
2079  // get a next direction vector
2080  // we are trying to find out a point on the minkowski difference
2081  // that is nearest to the origin, so we obtain a point on the
2082  // simplex that is nearest and try to exapand the simplex towards
2083  // the origin
2084  if (ccdSimplexSize(simplex) == 1)
2085  {
2086  ccdVec3Copy(&closest_p, &ccdSimplexPoint(simplex, 0)->v);
2087  dist = ccdVec3Len2(&ccdSimplexPoint(simplex, 0)->v);
2088  dist = CCD_SQRT(dist);
2089  }
2090  else if (ccdSimplexSize(simplex) == 2)
2091  {
2092  dist = ccdVec3PointSegmentDist2(ccd_vec3_origin,
2093  &ccdSimplexPoint(simplex, 0)->v,
2094  &ccdSimplexPoint(simplex, 1)->v,
2095  &closest_p);
2096  dist = CCD_SQRT(dist);
2097  }
2098  else if (ccdSimplexSize(simplex) == 3)
2099  {
2101  ccd_vec3_origin, &ccdSimplexPoint(simplex, 0)->v,
2102  &ccdSimplexPoint(simplex, 1)->v, &ccdSimplexPoint(simplex, 2)->v,
2103  &closest_p);
2104  dist = CCD_SQRT(dist);
2105  }
2106  else
2107  { // ccdSimplexSize(&simplex) == 4
2108  dist = simplexReduceToTriangle(simplex, last_dist, &closest_p);
2109  }
2110 
2111  // check whether we improved for at least a minimum tolerance
2112  if ((last_dist - dist) < ccd->dist_tolerance)
2113  {
2114  extractClosestPoints(simplex, p1, p2, &closest_p);
2115  return dist;
2116  }
2117 
2118  // point direction towards the origin
2119  ccd_vec3_t dir; // direction vector
2120  ccdVec3Copy(&dir, &closest_p);
2121  ccdVec3Scale(&dir, -CCD_ONE);
2122  ccdVec3Normalize(&dir);
2123 
2124  // find out support point
2125  ccd_support_t last; // last support point
2126  __ccdSupport(obj1, obj2, &dir, ccd, &last);
2127 
2128  // record last distance
2129  last_dist = dist;
2130 
2131  // check whether we improved for at least a minimum tolerance
2132  // this is here probably only for a degenerate cases when we got a
2133  // point that is already in the simplex
2134  dist = ccdVec3Len2(&last.v);
2135  dist = CCD_SQRT(dist);
2136  if (CCD_FABS(last_dist - dist) < ccd->dist_tolerance)
2137  {
2138  extractClosestPoints(simplex, p1, p2, &closest_p);
2139  return last_dist;
2140  }
2141 
2142  // add a point to simplex
2143  ccdSimplexAdd(simplex, &last);
2144  }
2145 
2146  return -CCD_REAL(1.);
2147 }
2148 
2162 static int penEPAPosClosest(const ccd_pt_el_t* nearest, ccd_vec3_t* p1,
2163  ccd_vec3_t* p2) {
2164  // We reconstruct the simplex on which the nearest point lives, and then
2165  // compute the deepest penetration point on each geometric objects. Note that
2166  // the reconstructed simplex has size up to 3 (at most 3 vertices).
2167  if (nearest->type == CCD_PT_VERTEX) {
2168  ccd_pt_vertex_t* v = (ccd_pt_vertex_t*)nearest;
2169  ccdVec3Copy(p1, &v->v.v1);
2170  ccdVec3Copy(p2, &v->v.v2);
2171  return 0;
2172  } else {
2173  ccd_simplex_t s;
2174  ccdSimplexInit(&s);
2175  if (nearest->type == CCD_PT_EDGE) {
2176  const ccd_pt_edge_t* e = reinterpret_cast<const ccd_pt_edge_t*>(nearest);
2177  ccdSimplexAdd(&s, &(e->vertex[0]->v));
2178  ccdSimplexAdd(&s, &(e->vertex[1]->v));
2179  } else if (nearest->type == CCD_PT_FACE) {
2180  const ccd_pt_face_t* f = reinterpret_cast<const ccd_pt_face_t*>(nearest);
2181  // The face triangle has three edges, each edge consists of two end
2182  // points, so there are 6 end points in total, each vertex of the triangle
2183  // appears twice among the 6 end points. We need to choose the three
2184  // distinctive vertices out of these 6 end points.
2185  // First we pick edge0, the two end points of edge0 are distinct.
2186  ccdSimplexAdd(&s, &(f->edge[0]->vertex[0]->v));
2187  ccdSimplexAdd(&s, &(f->edge[0]->vertex[1]->v));
2188  // Next we pick edge1, one of the two end points on edge1 is distinct from
2189  // the end points in edge0, we will add this distinct vertex to the
2190  // simplex.
2191  for (int i = 0; i < 2; ++i) {
2192  ccd_pt_vertex_t* third_vertex = f->edge[1]->vertex[i];
2193  if (third_vertex != f->edge[0]->vertex[0] &&
2194  third_vertex != f->edge[0]->vertex[1]) {
2195  ccdSimplexAdd(&s, &(third_vertex->v));
2196  break;
2197  }
2198  }
2199  } else {
2200  throw std::logic_error(
2201  "FCL penEPAPosClosest(): Unsupported feature type. The closest point "
2202  "should be either a vertex, on an edge, or on a face.");
2203  }
2204  // Now compute the closest point in the simplex.
2205  // TODO(hongkai.dai@tri.global): we do not need to compute the closest point
2206  // on the simplex, as that is already given in `nearest`. We only need to
2207  // extract the deepest penetration points on each geometric object.
2208  // Sean.Curtis@tri.global and I will refactor this code in the future, to
2209  // avoid calling extractClosestPoints.
2210  ccd_vec3_t p;
2211  ccdVec3Copy(&p, &(nearest->witness));
2212  extractClosestPoints(&s, p1, p2, &p);
2213  return 0;
2214  }
2215 }
2216 
2217 static inline ccd_real_t ccdGJKSignedDist(const void* obj1, const void* obj2,
2218  const ccd_t* ccd, ccd_vec3_t* p1,
2219  ccd_vec3_t* p2)
2220 {
2221  ccd_simplex_t simplex;
2222 
2223  if (__ccdGJK(obj1, obj2, ccd, &simplex) == 0) // in collision, then using the EPA
2224  {
2225  ccd_pt_t polytope;
2226  ccd_pt_el_t *nearest;
2227  ccd_real_t depth;
2228 
2229  ccdPtInit(&polytope);
2230  int ret = __ccdEPA(obj1, obj2, ccd, &simplex, &polytope, &nearest);
2231  if (ret == 0 && nearest)
2232  {
2233  depth = -CCD_SQRT(nearest->dist);
2234 
2235  ccd_vec3_t pos1, pos2;
2236  penEPAPosClosest(nearest, &pos1, &pos2);
2237 
2238  if (p1) *p1 = pos1;
2239  if (p2) *p2 = pos2;
2240 
2241  //ccd_vec3_t dir; // direction vector
2242  //ccdVec3Copy(&dir, &nearest->witness);
2243  //std::cout << dir.v[0] << " " << dir.v[1] << " " << dir.v[2] << std::endl;
2244  //ccd_support_t last;
2245  //__ccdSupport(obj1, obj2, &dir, ccd, &last);
2246 
2247  //if (p1) *p1 = last.v1;
2248  //if (p2) *p2 = last.v2;
2249  }
2250  else
2251  {
2252  depth = -CCD_ONE;
2253  }
2254 
2255  ccdPtDestroy(&polytope);
2256 
2257  return depth;
2258  }
2259  else // not in collision
2260  {
2261  return _ccdDist(obj1, obj2, ccd, &simplex, p1, p2);
2262  }
2263 }
2264 
2265 
2266 // Computes the distance between two non-penetrating convex objects, `obj1` and
2267 // `obj2`, returning the distance and
2268 // nearest points on each object.
2269 // @param obj1 The first convex object.
2270 // @param obj2 The second convex object.
2271 // @param ccd The libccd configuration.
2272 // @param p1 If the objects are non-penetrating, the point on the surface of
2273 // obj1 closest to obj2 (expressed in the world frame).
2274 // @param p2 If the objects are non-penetrating, the point on the surface of
2275 // obj2 closest to obj1 (expressed in the world frame).
2276 // @returns The minimum distance between the two objects. If they are
2277 // penetrating, -1 is returned.
2278 // @note Unlike _ccdDist function, this function does not need a warm-started
2279 // simplex as the input argument.
2280 static inline ccd_real_t ccdGJKDist2(const void *obj1, const void *obj2,
2281  const ccd_t *ccd, ccd_vec3_t* p1,
2282  ccd_vec3_t* p2)
2283 {
2284  ccd_simplex_t simplex;
2285  // first find an intersection
2286  if (__ccdGJK(obj1, obj2, ccd, &simplex) == 0)
2287  return -CCD_ONE;
2288 
2289  return _ccdDist(obj1, obj2, ccd, &simplex, p1, p2);
2290 }
2291 
2292 } // namespace libccd_extension
2293 
2295 template <typename S>
2296 static void shapeToGJK(const ShapeBase<S>& s, const Transform3<S>& tf,
2297  ccd_obj_t* o)
2298 {
2299  FCL_UNUSED(s);
2300 
2301  const Quaternion<S> q(tf.linear());
2302  const Vector3<S>& T = tf.translation();
2303  ccdVec3Set(&o->pos, T[0], T[1], T[2]);
2304  ccdQuatSet(&o->rot, q.x(), q.y(), q.z(), q.w());
2305  ccdQuatInvert2(&o->rot_inv, &o->rot);
2306 }
2307 
2308 template <typename S>
2309 static void boxToGJK(const Box<S>& s, const Transform3<S>& tf, ccd_box_t* box)
2310 {
2311  shapeToGJK(s, tf, box);
2312  box->dim[0] = s.side[0] / 2.0;
2313  box->dim[1] = s.side[1] / 2.0;
2314  box->dim[2] = s.side[2] / 2.0;
2315 }
2316 
2317 template <typename S>
2318 static void capToGJK(const Capsule<S>& s, const Transform3<S>& tf,
2319  ccd_cap_t* cap)
2320 {
2321  shapeToGJK(s, tf, cap);
2322  cap->radius = s.radius;
2323  cap->height = s.lz / 2;
2324 }
2325 
2326 template <typename S>
2327 static void cylToGJK(const Cylinder<S>& s, const Transform3<S>& tf,
2328  ccd_cyl_t* cyl)
2329 {
2330  shapeToGJK(s, tf, cyl);
2331  cyl->radius = s.radius;
2332  cyl->height = s.lz / 2;
2333 }
2334 
2335 template <typename S>
2336 static void coneToGJK(const Cone<S>& s, const Transform3<S>& tf,
2337  ccd_cone_t* cone)
2338 {
2339  shapeToGJK(s, tf, cone);
2340  cone->radius = s.radius;
2341  cone->height = s.lz / 2;
2342 }
2343 
2344 template <typename S>
2345 static void sphereToGJK(const Sphere<S>& s, const Transform3<S>& tf,
2346  ccd_sphere_t* sph)
2347 {
2348  shapeToGJK(s, tf, sph);
2349  sph->radius = s.radius;
2350 }
2351 
2352 template <typename S>
2353 static void ellipsoidToGJK(const Ellipsoid<S>& s, const Transform3<S>& tf,
2354  ccd_ellipsoid_t* ellipsoid)
2355 {
2356  shapeToGJK(s, tf, ellipsoid);
2357  ellipsoid->radii[0] = s.radii[0];
2358  ellipsoid->radii[1] = s.radii[1];
2359  ellipsoid->radii[2] = s.radii[2];
2360 }
2361 
2362 template <typename S>
2363 static void convexToGJK(const Convex<S>& s, const Transform3<S>& tf,
2364  ccd_convex_t<S>* conv)
2365 {
2366  shapeToGJK(s, tf, conv);
2367  conv->convex = &s;
2368 }
2369 
2371 static inline void supportBox(const void* obj, const ccd_vec3_t* dir_,
2372  ccd_vec3_t* v)
2373 {
2374  // Use a customized sign function, so that the support of the box always
2375  // appears in one of the box vertices.
2376  // Picking support vertices on the interior of faces/edges can lead to
2377  // degenerate triangles in the EPA algorithm and are no more correct than just
2378  // picking box corners.
2379  auto sign = [](ccd_real_t x) -> ccd_real_t {
2380  return x >= 0 ? ccd_real_t(1.0) : ccd_real_t(-1.0);
2381  };
2382  const ccd_box_t* o = static_cast<const ccd_box_t*>(obj);
2383  ccd_vec3_t dir;
2384  ccdVec3Copy(&dir, dir_);
2385  ccdQuatRotVec(&dir, &o->rot_inv);
2386  ccdVec3Set(v, sign(ccdVec3X(&dir)) * o->dim[0],
2387  sign(ccdVec3Y(&dir)) * o->dim[1],
2388  sign(ccdVec3Z(&dir)) * o->dim[2]);
2389  ccdQuatRotVec(v, &o->rot);
2390  ccdVec3Add(v, &o->pos);
2391 }
2392 
2393 static inline void supportCap(const void* obj, const ccd_vec3_t* dir_,
2394  ccd_vec3_t* v)
2395 {
2396  const ccd_cap_t* o = static_cast<const ccd_cap_t*>(obj);
2397  ccd_vec3_t dir, pos1, pos2;
2398 
2399  ccdVec3Copy(&dir, dir_);
2400  ccdQuatRotVec(&dir, &o->rot_inv);
2401 
2402  ccdVec3Set(&pos1, CCD_ZERO, CCD_ZERO, o->height);
2403  ccdVec3Set(&pos2, CCD_ZERO, CCD_ZERO, -o->height);
2404 
2405  ccdVec3Copy(v, &dir);
2406  ccdVec3Normalize (v);
2407  ccdVec3Scale(v, o->radius);
2408  ccdVec3Add(&pos1, v);
2409  ccdVec3Add(&pos2, v);
2410 
2411  if (ccdVec3Z (&dir) > 0)
2412  ccdVec3Copy(v, &pos1);
2413  else
2414  ccdVec3Copy(v, &pos2);
2415 
2416  // transform support vertex
2417  ccdQuatRotVec(v, &o->rot);
2418  ccdVec3Add(v, &o->pos);
2419 }
2420 
2421 static inline void supportCyl(const void* obj, const ccd_vec3_t* dir_,
2422  ccd_vec3_t* v)
2423 {
2424  const ccd_cyl_t* cyl = static_cast<const ccd_cyl_t*>(obj);
2425  ccd_vec3_t dir;
2426  double zdist, rad;
2427 
2428  ccdVec3Copy(&dir, dir_);
2429  ccdQuatRotVec(&dir, &cyl->rot_inv);
2430 
2431  zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1];
2432  zdist = sqrt(zdist);
2433  if (ccdIsZero(zdist))
2434  ccdVec3Set(v, 0., 0., ccdSign(ccdVec3Z(&dir)) * cyl->height);
2435  else
2436  {
2437  rad = cyl->radius / zdist;
2438 
2439  ccdVec3Set(v, rad * ccdVec3X(&dir),
2440  rad * ccdVec3Y(&dir),
2441  ccdSign(ccdVec3Z(&dir)) * cyl->height);
2442  }
2443 
2444  // transform support vertex
2445  ccdQuatRotVec(v, &cyl->rot);
2446  ccdVec3Add(v, &cyl->pos);
2447 }
2448 
2449 static inline void supportCone(const void* obj, const ccd_vec3_t* dir_,
2450  ccd_vec3_t* v)
2451 {
2452  const ccd_cone_t* cone = static_cast<const ccd_cone_t*>(obj);
2453  ccd_vec3_t dir;
2454 
2455  ccdVec3Copy(&dir, dir_);
2456  ccdQuatRotVec(&dir, &cone->rot_inv);
2457 
2458  double zdist, len, rad;
2459  zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1];
2460  len = zdist + dir.v[2] * dir.v[2];
2461  zdist = sqrt(zdist);
2462  len = sqrt(len);
2463 
2464  double sin_a = cone->radius / sqrt(cone->radius * cone->radius + 4 * cone->height * cone->height);
2465 
2466  if (dir.v[2] > len * sin_a)
2467  ccdVec3Set(v, 0., 0., cone->height);
2468  else if (zdist > 0)
2469  {
2470  rad = cone->radius / zdist;
2471  ccdVec3Set(v, rad * ccdVec3X(&dir), rad * ccdVec3Y(&dir), -cone->height);
2472  }
2473  else
2474  ccdVec3Set(v, 0, 0, -cone->height);
2475 
2476  // transform support vertex
2477  ccdQuatRotVec(v, &cone->rot);
2478  ccdVec3Add(v, &cone->pos);
2479 }
2480 
2481 static inline void supportSphere(const void* obj, const ccd_vec3_t* dir_,
2482  ccd_vec3_t* v)
2483 {
2484  const ccd_sphere_t* s = static_cast<const ccd_sphere_t*>(obj);
2485  ccd_vec3_t dir;
2486 
2487  ccdVec3Copy(&dir, dir_);
2488  ccdQuatRotVec(&dir, &s->rot_inv);
2489 
2490  ccdVec3Copy(v, &dir);
2491  ccdVec3Scale(v, s->radius);
2492  ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Len2(&dir)));
2493 
2494  // transform support vertex
2495  ccdQuatRotVec(v, &s->rot);
2496  ccdVec3Add(v, &s->pos);
2497 }
2498 
2499 static inline void supportEllipsoid(const void* obj, const ccd_vec3_t* dir_,
2500  ccd_vec3_t* v)
2501 {
2502  const ccd_ellipsoid_t* s = static_cast<const ccd_ellipsoid_t*>(obj);
2503  ccd_vec3_t dir;
2504 
2505  ccdVec3Copy(&dir, dir_);
2506  ccdQuatRotVec(&dir, &s->rot_inv);
2507 
2508  ccd_vec3_t abc2;
2509  abc2.v[0] = s->radii[0] * s->radii[0];
2510  abc2.v[1] = s->radii[1] * s->radii[1];
2511  abc2.v[2] = s->radii[2] * s->radii[2];
2512 
2513  v->v[0] = abc2.v[0] * dir.v[0];
2514  v->v[1] = abc2.v[1] * dir.v[1];
2515  v->v[2] = abc2.v[2] * dir.v[2];
2516 
2517  ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Dot(v, &dir)));
2518 
2519  // transform support vertex
2520  ccdQuatRotVec(v, &s->rot);
2521  ccdVec3Add(v, &s->pos);
2522 }
2523 
2524 template <typename S>
2525 static void supportConvex(const void* obj, const ccd_vec3_t* dir_,
2526  ccd_vec3_t* v)
2527 {
2528  const auto* c = (const ccd_convex_t<S>*)obj;
2529 
2530  // Transform the support direction vector from the query frame Q to the
2531  // convex mesh's local frame C. I.e., dir_Q -> dir_C.
2532  ccd_vec3_t dir;
2533  ccdVec3Copy(&dir, dir_);
2534  ccdQuatRotVec(&dir, &c->rot_inv);
2535  // Note: The scalar type ccd_real_t is fixed w.r.t. S. That means if S is
2536  // float and ccd_real_t is double, this conversion requires narrowing. To
2537  // avoid warning/errors about implicit narrowing, we explicitly convert.
2538  Vector3<S> dir_C{S(dir.v[0]), S(dir.v[1]), S(dir.v[2])};
2539 
2540  // The extremal point E measured and expressed in Frame C.
2541  const Vector3<S>& p_CE = c->convex->findExtremeVertex(dir_C);
2542 
2543  // Now measure and express E in the original query frame Q: p_CE -> p_QE.
2544  v->v[0] = p_CE(0);
2545  v->v[1] = p_CE(1);
2546  v->v[2] = p_CE(2);
2547  ccdQuatRotVec(v, &c->rot);
2548  ccdVec3Add(v, &c->pos);
2549 }
2550 
2551 static void supportTriangle(const void* obj, const ccd_vec3_t* dir_,
2552  ccd_vec3_t* v)
2553 {
2554  const ccd_triangle_t* tri = static_cast<const ccd_triangle_t*>(obj);
2555  ccd_vec3_t dir, p;
2556  ccd_real_t maxdot, dot;
2557  int i;
2558 
2559  ccdVec3Copy(&dir, dir_);
2560  ccdQuatRotVec(&dir, &tri->rot_inv);
2561 
2562  maxdot = -CCD_REAL_MAX;
2563 
2564  for (i = 0; i < 3; ++i)
2565  {
2566  ccdVec3Set(&p, tri->p[i].v[0] - tri->c.v[0], tri->p[i].v[1] - tri->c.v[1],
2567  tri->p[i].v[2] - tri->c.v[2]);
2568  dot = ccdVec3Dot(&dir, &p);
2569  if (dot > maxdot)
2570  {
2571  ccdVec3Copy(v, &tri->p[i]);
2572  maxdot = dot;
2573  }
2574  }
2575 
2576  // transform support vertex
2577  ccdQuatRotVec(v, &tri->rot);
2578  ccdVec3Add(v, &tri->pos);
2579 }
2580 
2581 static inline void centerShape(const void* obj, ccd_vec3_t* c)
2582 {
2583  const ccd_obj_t *o = static_cast<const ccd_obj_t*>(obj);
2584  ccdVec3Copy(c, &o->pos);
2585 }
2586 
2587 template <typename S>
2588 static void centerConvex(const void* obj, ccd_vec3_t* c)
2589 {
2590  const auto *o = static_cast<const ccd_convex_t<S>*>(obj);
2591  const Vector3<S>& p = o->convex->getInteriorPoint();
2592  ccdVec3Set(c, p[0], p[1], p[2]);
2593  ccdQuatRotVec(c, &o->rot);
2594  ccdVec3Add(c, &o->pos);
2595 }
2596 
2597 static void centerTriangle(const void* obj, ccd_vec3_t* c)
2598 {
2599  const ccd_triangle_t *o = static_cast<const ccd_triangle_t*>(obj);
2600  ccdVec3Copy(c, &o->c);
2601  ccdQuatRotVec(c, &o->rot);
2602  ccdVec3Add(c, &o->pos);
2603 }
2604 
2605 template <typename S>
2606 bool GJKCollide(void* obj1, ccd_support_fn supp1, ccd_center_fn cen1,
2607  void* obj2, ccd_support_fn supp2, ccd_center_fn cen2,
2608  unsigned int max_iterations, S tolerance,
2609  Vector3<S>* contact_points, S* penetration_depth,
2610  Vector3<S>* normal)
2611 {
2612  ccd_t ccd;
2613  int res;
2614  ccd_real_t depth;
2615  ccd_vec3_t dir, pos;
2616 
2617 
2618  CCD_INIT(&ccd);
2619  ccd.support1 = supp1;
2620  ccd.support2 = supp2;
2621  ccd.center1 = cen1;
2622  ccd.center2 = cen2;
2623  ccd.max_iterations = max_iterations;
2624  ccd.mpr_tolerance = tolerance;
2625 
2626  if (!contact_points)
2627  {
2628  return ccdMPRIntersect(obj1, obj2, &ccd);
2629  }
2630 
2631 
2634  res = ccdMPRPenetration(obj1, obj2, &ccd, &depth, &dir, &pos);
2635  if (res == 0)
2636  {
2637  *contact_points << ccdVec3X(&pos), ccdVec3Y(&pos), ccdVec3Z(&pos);
2638  *penetration_depth = depth;
2639  *normal << ccdVec3X(&dir), ccdVec3Y(&dir), ccdVec3Z(&dir);
2640 
2641  return true;
2642  }
2643 
2644  return false;
2645 }
2646 
2647 // For two geometric objects, computes the distance between the two objects and
2648 // returns the closest points. The return argument is the distance when the two
2649 // objects are not colliding, thus a non-negative number; it is a negative
2650 // number when the object is colliding, though the meaning of that negative
2651 // number depends on the implementation.
2652 using DistanceFn = std::function<ccd_real_t (
2653  const void*, const void*, const ccd_t*, ccd_vec3_t*, ccd_vec3_t*)>;
2654 
2677 template <typename S>
2678 bool GJKDistanceImpl(void* obj1, ccd_support_fn supp1, void* obj2,
2679  ccd_support_fn supp2, unsigned int max_iterations,
2680  S tolerance, detail::DistanceFn distance_func, S* res,
2681  Vector3<S>* p1, Vector3<S>* p2) {
2682  ccd_t ccd;
2683  ccd_real_t dist;
2684  CCD_INIT(&ccd);
2685  ccd.support1 = supp1;
2686  ccd.support2 = supp2;
2687 
2688  ccd.max_iterations = max_iterations;
2689  ccd.dist_tolerance = tolerance;
2690  ccd.epa_tolerance = tolerance;
2691 
2692  ccd_vec3_t p1_, p2_;
2693  // NOTE(JS): p1_ and p2_ are set to zeros in order to suppress uninitialized
2694  // warning. It seems the warnings occur since libccd_extension::ccdGJKDist2
2695  // conditionally set p1_ and p2_. If this wasn't intentional then please
2696  // remove the initialization of p1_ and p2_, and change the function
2697  // libccd_extension::ccdGJKDist2(...) to always set p1_ and p2_.
2698  ccdVec3Set(&p1_, 0.0, 0.0, 0.0);
2699  ccdVec3Set(&p2_, 0.0, 0.0, 0.0);
2700  dist = distance_func(obj1, obj2, &ccd, &p1_, &p2_);
2701  if (p1) *p1 << ccdVec3X(&p1_), ccdVec3Y(&p1_), ccdVec3Z(&p1_);
2702  if (p2) *p2 << ccdVec3X(&p2_), ccdVec3Y(&p2_), ccdVec3Z(&p2_);
2703  if (res) *res = dist;
2704  if (dist < 0)
2705  return false;
2706  else
2707  return true;
2708 }
2709 
2710 template <typename S>
2711 bool GJKDistance(void* obj1, ccd_support_fn supp1,
2712  void* obj2, ccd_support_fn supp2,
2713  unsigned int max_iterations, S tolerance,
2714  S* res, Vector3<S>* p1, Vector3<S>* p2) {
2715  return detail::GJKDistanceImpl(obj1, supp1, obj2, supp2, max_iterations,
2717  p1, p2);
2718 }
2719 
2733 template <typename S>
2734 bool GJKSignedDistance(void* obj1, ccd_support_fn supp1,
2735  void* obj2, ccd_support_fn supp2,
2736  unsigned int max_iterations,
2737  S tolerance, S* res, Vector3<S>* p1, Vector3<S>* p2) {
2738  return detail::GJKDistanceImpl(
2739  obj1, supp1, obj2, supp2, max_iterations, tolerance,
2740  libccd_extension::ccdGJKSignedDist, res, p1, p2);
2741 }
2742 
2743 template <typename S>
2745 {
2746  return &supportCyl;
2747 }
2748 
2749 template <typename S>
2751 {
2752  return &centerShape;
2753 }
2754 
2755 template <typename S>
2756 void* GJKInitializer<S, Cylinder<S>>::createGJKObject(const Cylinder<S>& s,
2757  const Transform3<S>& tf)
2758 {
2759  ccd_cyl_t* o = new ccd_cyl_t;
2760  cylToGJK(s, tf, o);
2761  return o;
2762 }
2763 
2764 template <typename S>
2765 void GJKInitializer<S, Cylinder<S>>::deleteGJKObject(void* o_)
2766 {
2767  ccd_cyl_t* o = static_cast<ccd_cyl_t*>(o_);
2768  delete o;
2769 }
2770 
2771 template <typename S>
2773 {
2774  return &supportSphere;
2775 }
2776 
2777 template <typename S>
2779 {
2780  return &centerShape;
2781 }
2782 
2783 template <typename S>
2784 void* GJKInitializer<S, Sphere<S>>::createGJKObject(const Sphere<S>& s,
2785  const Transform3<S>& tf)
2786 {
2787  ccd_sphere_t* o = new ccd_sphere_t;
2788  sphereToGJK(s, tf, o);
2789  return o;
2790 }
2791 
2792 template <typename S>
2793 void GJKInitializer<S, Sphere<S>>::deleteGJKObject(void* o_)
2794 {
2795  ccd_sphere_t* o = static_cast<ccd_sphere_t*>(o_);
2796  delete o;
2797 }
2798 
2799 template <typename S>
2801 {
2802  return &supportEllipsoid;
2803 }
2804 
2805 template <typename S>
2807 {
2808  return &centerShape;
2809 }
2810 
2811 template <typename S>
2812 void* GJKInitializer<S, Ellipsoid<S>>::createGJKObject(const Ellipsoid<S>& s,
2813  const Transform3<S>& tf)
2814 {
2816  ellipsoidToGJK(s, tf, o);
2817  return o;
2818 }
2819 
2820 template <typename S>
2821 void GJKInitializer<S, Ellipsoid<S>>::deleteGJKObject(void* o_)
2822 {
2823  ccd_ellipsoid_t* o = static_cast<ccd_ellipsoid_t*>(o_);
2824  delete o;
2825 }
2826 
2827 template <typename S>
2829 {
2830  return &supportBox;
2831 }
2832 
2833 template <typename S>
2835 {
2836  return &centerShape;
2837 }
2838 
2839 template <typename S>
2840 void* GJKInitializer<S, Box<S>>::createGJKObject(const Box<S>& s,
2841  const Transform3<S>& tf)
2842 {
2843  ccd_box_t* o = new ccd_box_t;
2844  boxToGJK(s, tf, o);
2845  return o;
2846 }
2847 
2848 template <typename S>
2849 void GJKInitializer<S, Box<S>>::deleteGJKObject(void* o_)
2850 {
2851  ccd_box_t* o = static_cast<ccd_box_t*>(o_);
2852  delete o;
2853 }
2854 
2855 template <typename S>
2857 {
2858  return &supportCap;
2859 }
2860 
2861 template <typename S>
2863 {
2864  return &centerShape;
2865 }
2866 
2867 template <typename S>
2868 void* GJKInitializer<S, Capsule<S>>::createGJKObject(const Capsule<S>& s,
2869  const Transform3<S>& tf)
2870 {
2871  ccd_cap_t* o = new ccd_cap_t;
2872  capToGJK(s, tf, o);
2873  return o;
2874 }
2875 
2876 template <typename S>
2877 void GJKInitializer<S, Capsule<S>>::deleteGJKObject(void* o_)
2878 {
2879  ccd_cap_t* o = static_cast<ccd_cap_t*>(o_);
2880  delete o;
2881 }
2882 
2883 template <typename S>
2885 {
2886  return &supportCone;
2887 }
2888 
2889 template <typename S>
2891 {
2892  return &centerShape;
2893 }
2894 
2895 template <typename S>
2896 void* GJKInitializer<S, Cone<S>>::createGJKObject(const Cone<S>& s,
2897  const Transform3<S>& tf)
2898 {
2899  ccd_cone_t* o = new ccd_cone_t;
2900  coneToGJK(s, tf, o);
2901  return o;
2902 }
2903 
2904 template <typename S>
2905 void GJKInitializer<S, Cone<S>>::deleteGJKObject(void* o_)
2906 {
2907  ccd_cone_t* o = static_cast<ccd_cone_t*>(o_);
2908  delete o;
2909 }
2910 
2911 template <typename S>
2913 {
2914  return &supportConvex<S>;
2915 }
2916 
2917 template <typename S>
2919 {
2920  return &centerConvex<S>;
2921 }
2922 
2923 template <typename S>
2924 void* GJKInitializer<S, Convex<S>>::createGJKObject(const Convex<S>& s,
2925  const Transform3<S>& tf)
2926 {
2927  auto* o = new ccd_convex_t<S>;
2928  convexToGJK(s, tf, o);
2929  return o;
2930 }
2931 
2932 template <typename S>
2933 void GJKInitializer<S, Convex<S>>::deleteGJKObject(void* o_)
2934 {
2935  auto* o = static_cast<ccd_convex_t<S>*>(o_);
2936  delete o;
2937 }
2938 
2940 {
2941  return &supportTriangle;
2942 }
2943 
2945 {
2946  return &centerTriangle;
2947 }
2948 
2949 template <typename S>
2950 void* triCreateGJKObject(const Vector3<S>& P1, const Vector3<S>& P2,
2951  const Vector3<S>& P3)
2952 {
2953  ccd_triangle_t* o = new ccd_triangle_t;
2954  Vector3<S> center((P1[0] + P2[0] + P3[0]) / 3, (P1[1] + P2[1] + P3[1]) / 3,
2955  (P1[2] + P2[2] + P3[2]) / 3);
2956 
2957  ccdVec3Set(&o->p[0], P1[0], P1[1], P1[2]);
2958  ccdVec3Set(&o->p[1], P2[0], P2[1], P2[2]);
2959  ccdVec3Set(&o->p[2], P3[0], P3[1], P3[2]);
2960  ccdVec3Set(&o->c, center[0], center[1], center[2]);
2961  ccdVec3Set(&o->pos, 0., 0., 0.);
2962  ccdQuatSet(&o->rot, 0., 0., 0., 1.);
2963  ccdQuatInvert2(&o->rot_inv, &o->rot);
2964 
2965  return o;
2966 }
2967 
2968 template <typename S>
2969 void* triCreateGJKObject(const Vector3<S>& P1, const Vector3<S>& P2,
2970  const Vector3<S>& P3, const Transform3<S>& tf)
2971 {
2972  ccd_triangle_t* o = new ccd_triangle_t;
2973  Vector3<S> center((P1[0] + P2[0] + P3[0]) / 3, (P1[1] + P2[1] + P3[1]) / 3,
2974  (P1[2] + P2[2] + P3[2]) / 3);
2975 
2976  ccdVec3Set(&o->p[0], P1[0], P1[1], P1[2]);
2977  ccdVec3Set(&o->p[1], P2[0], P2[1], P2[2]);
2978  ccdVec3Set(&o->p[2], P3[0], P3[1], P3[2]);
2979  ccdVec3Set(&o->c, center[0], center[1], center[2]);
2980  const Quaternion<S> q(tf.linear());
2981  const Vector3<S>& T = tf.translation();
2982  ccdVec3Set(&o->pos, T[0], T[1], T[2]);
2983  ccdQuatSet(&o->rot, q.x(), q.y(), q.z(), q.w());
2984  ccdQuatInvert2(&o->rot_inv, &o->rot);
2985 
2986  return o;
2987 }
2988 
2989 inline void triDeleteGJKObject(void* o_)
2990 {
2991  ccd_triangle_t* o = static_cast<ccd_triangle_t*>(o_);
2992  delete o;
2993 }
2994 
2995 } // namespace detail
2996 } // namespace fcl
2997 
2998 #endif
ccdPtAddFace
ccd_pt_face_t * ccdPtAddFace(ccd_pt_t *pt, ccd_pt_edge_t *e1, ccd_pt_edge_t *e2, ccd_pt_edge_t *e3)
fcl::detail::libccd_extension::extractObjectPointsFromPoint
static void extractObjectPointsFromPoint(ccd_support_t *q, ccd_vec3_t *p1, ccd_vec3_t *p2)
Definition: gjk_libccd-inl.h:1837
_ccd_pt_t::nearest
ccd_pt_el_t * nearest
Definition: polytope.h:97
_ccd_pt_face_t::edge
__CCD_PT_EL ccd_pt_edge_t * edge[3]
Reference to surrounding edges.
Definition: polytope.h:84
kEps
static const double kEps
Definition: test_gjk_libccd-inl_gjk_doSimplex2.cpp:128
_ccd_pt_vertex_t
Definition: polytope.h:56
fcl::detail::ccd_cap_t::radius
ccd_real_t radius
Definition: gjk_libccd-inl.h:153
fcl::Transform3
Eigen::Transform< S, 3, Eigen::Isometry > Transform3
Definition: types.h:92
ccdSimplexSize
_ccd_inline int ccdSimplexSize(const ccd_simplex_t *s)
Definition: simplex.h:54
fcl::detail::libccd_extension::simplexToPolytope4
static int simplexToPolytope4(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest)
Definition: gjk_libccd-inl.h:857
fcl::detail::ccd_cyl_t::radius
ccd_real_t radius
Definition: gjk_libccd-inl.h:158
fcl::Capsule::radius
S radius
Radius of capsule.
Definition: capsule.h:61
ccdPtFaceVec3
_ccd_inline void ccdPtFaceVec3(const ccd_pt_face_t *face, ccd_vec3_t **a, ccd_vec3_t **b, ccd_vec3_t **c)
Definition: polytope.h:251
fcl::detail::libccd_extension::ccdGJKDist2
static ccd_real_t ccdGJKDist2(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_vec3_t *p1, ccd_vec3_t *p2)
Definition: gjk_libccd-inl.h:2280
fcl::detail::libccd_extension::ComputeVisiblePatchRecursiveSanityCheck
static bool ComputeVisiblePatchRecursiveSanityCheck(const ccd_pt_t &polytope, const std::unordered_set< ccd_pt_edge_t * > &border_edges, const std::unordered_set< ccd_pt_face_t * > &visible_faces, const std::unordered_set< ccd_pt_edge_t * > &internal_edges)
Definition: gjk_libccd-inl.h:1146
ccdPtAddEdge
ccd_pt_edge_t * ccdPtAddEdge(ccd_pt_t *pt, ccd_pt_vertex_t *v1, ccd_pt_vertex_t *v2)
_ccd_pt_t::faces
ccd_list_t faces
List of faces.
Definition: polytope.h:95
obj2
CollisionObject< S > * obj2
Definition: broadphase_SaP.h:211
fcl::detail::supportSphere
static void supportSphere(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2481
fcl::detail::cylToGJK
static void cylToGJK(const Cylinder< S > &s, const Transform3< S > &tf, ccd_cyl_t *cyl)
Definition: gjk_libccd-inl.h:2327
ccdPtNearest
ccd_pt_el_t * ccdPtNearest(ccd_pt_t *pt)
ccdSimplexAdd
_ccd_inline void ccdSimplexAdd(ccd_simplex_t *s, const ccd_support_t *v)
Definition: simplex.h:74
fcl::detail::libccd_extension::penEPAPosClosest
static int penEPAPosClosest(const ccd_pt_el_t *nearest, ccd_vec3_t *p1, ccd_vec3_t *p2)
Definition: gjk_libccd-inl.h:2162
fcl::detail::ccd_obj_t::rot
ccd_quat_t rot
Definition: gjk_libccd-inl.h:143
fcl::detail::GJKCollide
template bool GJKCollide(void *obj1, ccd_support_fn supp1, ccd_center_fn cen1, void *obj2, ccd_support_fn supp2, ccd_center_fn cen2, unsigned int max_iterations, double tolerance, Vector3d *contact_points, double *penetration_depth, Vector3d *normal)
fcl::detail::shapeToGJK
static void shapeToGJK(const ShapeBase< S > &s, const Transform3< S > &tf, ccd_obj_t *o)
Definition: gjk_libccd-inl.h:2296
fcl::detail::DistanceFn
std::function< ccd_real_t(const void *, const void *, const ccd_t *, ccd_vec3_t *, ccd_vec3_t *)> DistanceFn
Definition: gjk_libccd-inl.h:2653
fcl::detail::libccd_extension::doSimplex3
static int doSimplex3(ccd_simplex_t *simplex, ccd_vec3_t *dir)
Definition: gjk_libccd-inl.h:429
fcl::Quaternion
Eigen::Quaternion< S > Quaternion
Definition: types.h:89
ccdSimplexSetSize
_ccd_inline void ccdSimplexSetSize(ccd_simplex_t *s, int size)
Definition: simplex.h:86
epsilon
S epsilon()
Definition: test_fcl_simple.cpp:56
_ccd_support_t
Definition: support.h:27
_ccd_simplex_t::ps
ccd_support_t ps[4]
Definition: simplex.h:44
fcl::detail::triDeleteGJKObject
void triDeleteGJKObject(void *o_)
Definition: gjk_libccd-inl.h:2989
fcl::detail::triGetSupportFunction
GJKSupportFunction triGetSupportFunction()
initialize GJK Triangle
Definition: gjk_libccd-inl.h:2939
dir_
ccd_vec3_t dir_
Definition: test_gjk_libccd-inl_gjk_doSimplex2.cpp:114
ccdPtInit
void ccdPtInit(ccd_pt_t *pt)
ccdSimplexSet
_ccd_inline void ccdSimplexSet(ccd_simplex_t *s, size_t pos, const ccd_support_t *a)
Definition: simplex.h:81
fcl::Convex< S >
fcl::constants::eps
static constexpr Real eps()
Returns ε for the precision of the underlying scalar type.
Definition: constants.h:151
fcl::detail::supportEllipsoid
static void supportEllipsoid(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2499
fcl::detail::convexToGJK
static void convexToGJK(const Convex< S > &s, const Transform3< S > &tf, ccd_convex_t< S > *conv)
Definition: gjk_libccd-inl.h:2363
fcl::detail::centerShape
static void centerShape(const void *obj, ccd_vec3_t *c)
Definition: gjk_libccd-inl.h:2581
ccdSimplexLast
const _ccd_inline ccd_support_t * ccdSimplexLast(const ccd_simplex_t *s)
Definition: simplex.h:59
fcl::detail::supportBox
static void supportBox(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2371
fcl::detail::libccd_extension::tripleCross
_ccd_inline void tripleCross(const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c, ccd_vec3_t *d)
Definition: gjk_libccd-inl.h:264
fcl::detail::libccd_extension::__ccdEPA
static int __ccdEPA(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex, ccd_pt_t *polytope, ccd_pt_el_t **nearest)
Definition: gjk_libccd-inl.h:1779
_ccd_support_t::v
ccd_vec3_t v
Support point in minkowski sum.
Definition: support.h:43
fcl::detail::are_coincident
bool are_coincident(const Vector3d &p, const Vector3d &q)
Definition: test_gjk_libccd-inl_extractClosestPoints.cpp:115
fcl::Transform3d
Transform3< double > Transform3d
Definition: types.h:118
unused.h
obj1
CollisionObject< S > * obj1
Definition: broadphase_SaP.h:210
fcl::Ellipsoid::radii
Vector3< S > radii
Radii of the ellipsoid.
Definition: ellipsoid.h:64
fcl::detail::libccd_extension::extractClosestPoints
static void extractClosestPoints(ccd_simplex_t *simplex, ccd_vec3_t *p1, ccd_vec3_t *p2, ccd_vec3_t *p)
Definition: gjk_libccd-inl.h:1926
max
static T max(T x, T y)
Definition: svm.cpp:52
fcl::detail::libccd_extension::_ccdDist
static ccd_real_t _ccdDist(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex, ccd_vec3_t *p1, ccd_vec3_t *p2)
Definition: gjk_libccd-inl.h:2067
fcl::detail::ccd_convex_t
Definition: gjk_libccd-inl.h:177
fcl::detail::libccd_extension::doSimplex2
static int doSimplex2(ccd_simplex_t *simplex, ccd_vec3_t *dir)
Definition: gjk_libccd-inl.h:354
fcl::Capsule::lz
S lz
Length along z axis.
Definition: capsule.h:64
fcl::detail::capToGJK
static void capToGJK(const Capsule< S > &s, const Transform3< S > &tf, ccd_cap_t *cap)
Definition: gjk_libccd-inl.h:2318
fcl::ShapeBase< S >
fcl::detail::GJKInitializer
initialize GJK stuffs
Definition: gjk_libccd.h:76
obj
CollisionObject< S > * obj
object
Definition: broadphase_SaP.h:164
fcl::detail::ccd_obj_t
Definition: gjk_libccd-inl.h:140
_ccd_support_t::v1
ccd_vec3_t v1
Support point in obj1.
Definition: support.h:44
fcl::detail::ccd_triangle_t::c
ccd_vec3_t c
Definition: gjk_libccd-inl.h:185
CCD_PT_EDGE
#define CCD_PT_EDGE
Definition: polytope.h:31
failed_at_this_configuration.h
ccdPtEdgeVec3
_ccd_inline void ccdPtEdgeVec3(const ccd_pt_edge_t *e, ccd_vec3_t **a, ccd_vec3_t **b)
Definition: polytope.h:293
fcl::detail::libccd_extension::doSimplex
static int doSimplex(ccd_simplex_t *simplex, ccd_vec3_t *dir)
Definition: gjk_libccd-inl.h:604
CCD_PT_VERTEX
#define CCD_PT_VERTEX
Definition: polytope.h:30
warning.h
ccdListForEachEntry
#define ccdListForEachEntry(head, pos, postype, member)
Definition: list.h:66
fcl::Vector3
Eigen::Matrix< S, 3, 1 > Vector3
Definition: types.h:71
ccdSimplexPoint
const _ccd_inline ccd_support_t * ccdSimplexPoint(const ccd_simplex_t *s, int idx)
Definition: simplex.h:64
_ccd_support_t::v2
ccd_vec3_t v2
Support point in obj2.
Definition: support.h:45
fcl::detail::ccd_cone_t::radius
ccd_real_t radius
Definition: gjk_libccd-inl.h:163
fcl::detail::libccd_extension::ClassifyInternalEdge
static void ClassifyInternalEdge(ccd_pt_edge_t *edge, std::unordered_set< ccd_pt_edge_t * > *border_edges, std::unordered_set< ccd_pt_edge_t * > *internal_edges)
Definition: gjk_libccd-inl.h:1219
fcl::detail::ccd_box_t
Definition: gjk_libccd-inl.h:146
fcl::detail::sphereToGJK
static void sphereToGJK(const Sphere< S > &s, const Transform3< S > &tf, ccd_sphere_t *sph)
Definition: gjk_libccd-inl.h:2345
fcl::detail::libccd_extension::extractObjectPointsFromSegment
static void extractObjectPointsFromSegment(ccd_support_t *a, ccd_support_t *b, ccd_vec3_t *p1, ccd_vec3_t *p2, ccd_vec3_t *p)
Definition: gjk_libccd-inl.h:1850
fcl::detail::libccd_extension::isAbsValueLessThanEpsSquared
static bool isAbsValueLessThanEpsSquared(ccd_real_t val)
Definition: gjk_libccd-inl.h:420
fcl::detail::ccd_box_t::dim
ccd_real_t dim[3]
Definition: gjk_libccd-inl.h:148
fcl::detail::centerTriangle
static void centerTriangle(const void *obj, ccd_vec3_t *c)
Definition: gjk_libccd-inl.h:2597
_ccd_simplex_t
Definition: simplex.h:28
fcl::detail::libccd_extension::supportEPADirection
static ccd_vec3_t supportEPADirection(const ccd_pt_t *polytope, const ccd_pt_el_t *nearest_feature)
Definition: gjk_libccd-inl.h:1520
fcl::Cone::lz
S lz
Length along z axis.
Definition: cone.h:63
fcl::detail::ccd_obj_t::rot_inv
ccd_quat_t rot_inv
Definition: gjk_libccd-inl.h:143
fcl::detail::triCreateGJKObject
template void * triCreateGJKObject(const Vector3d &P1, const Vector3d &P2, const Vector3d &P3)
fcl::detail::ccd_triangle_t::p
ccd_vec3_t p[3]
Definition: gjk_libccd-inl.h:184
fcl::detail::ccd_cap_t::height
ccd_real_t height
Definition: gjk_libccd-inl.h:153
fcl::detail::libccd_extension::simplexToPolytope2
static int simplexToPolytope2(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest)
Definition: gjk_libccd-inl.h:620
fcl::detail::ccd_ellipsoid_t
Definition: gjk_libccd-inl.h:171
_ccd_pt_edge_t
Definition: polytope.h:68
fcl::detail::ccd_sphere_t
Definition: gjk_libccd-inl.h:166
_ccd_pt_el_t
Definition: polytope.h:45
fcl::detail::centerConvex
static void centerConvex(const void *obj, ccd_vec3_t *c)
Definition: gjk_libccd-inl.h:2588
FCL_THROW_FAILED_AT_THIS_CONFIGURATION
#define FCL_THROW_FAILED_AT_THIS_CONFIGURATION(message)
Definition: failed_at_this_configuration.h:163
_ccd_pt_face_t
Definition: polytope.h:81
fcl::detail::libccd_extension::ccdGJKSignedDist
static ccd_real_t ccdGJKSignedDist(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_vec3_t *p1, ccd_vec3_t *p2)
Definition: gjk_libccd-inl.h:2217
_ccd_pt_t::nearest_type
int nearest_type
Definition: polytope.h:99
ccdSimplexInit
_ccd_inline void ccdSimplexInit(ccd_simplex_t *s)
Definition: simplex.h:49
fcl::detail::coneToGJK
static void coneToGJK(const Cone< S > &s, const Transform3< S > &tf, ccd_cone_t *cone)
Definition: gjk_libccd-inl.h:2336
fcl::Sphere::radius
S radius
Radius of the sphere.
Definition: sphere.h:60
fcl::detail::ccd_triangle_t
Definition: gjk_libccd-inl.h:182
ccdPtEdgeFaces
_ccd_inline void ccdPtEdgeFaces(const ccd_pt_edge_t *e, ccd_pt_face_t **f1, ccd_pt_face_t **f2)
Definition: polytope.h:309
fcl::detail::GJKSupportFunction
void(*)(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v) GJKSupportFunction
callback function used by GJK algorithm
Definition: gjk_libccd.h:71
fcl::detail::libccd_extension::ccdVec3PointTriDist2NoWitness
static ccd_real_t ccdVec3PointTriDist2NoWitness(const ccd_vec3_t *P, const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c)
Definition: gjk_libccd-inl.h:200
fcl::Cone::radius
S radius
Radius of the cone.
Definition: cone.h:60
fcl::detail::libccd_extension::__ccdGJK
static int __ccdGJK(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex)
Definition: gjk_libccd-inl.h:1626
fcl::detail::ccd_sphere_t::radius
ccd_real_t radius
Definition: gjk_libccd-inl.h:168
gjk_libccd.h
ccdPtDestroy
void ccdPtDestroy(ccd_pt_t *pt)
Vector3d
fcl::Vector3d Vector3d
Definition: test_broadphase_dynamic_AABB_tree.cpp:48
ccdPtDelEdge
_ccd_inline int ccdPtDelEdge(ccd_pt_t *pt, ccd_pt_edge_t *)
Definition: polytope.h:204
fcl::Cylinder
Center at zero cylinder.
Definition: cylinder.h:51
fcl::detail::supportConvex
static void supportConvex(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2525
fcl::detail::ccd_ellipsoid_t::radii
ccd_real_t radii[3]
Definition: gjk_libccd-inl.h:173
fcl::detail::libccd_extension::isPolytopeEmpty
static bool isPolytopeEmpty(const ccd_pt_t &polytope)
Definition: gjk_libccd-inl.h:726
fcl::detail::ccd_cone_t::height
ccd_real_t height
Definition: gjk_libccd-inl.h:163
fcl::detail::libccd_extension::ComputeVisiblePatchRecursive
static void ComputeVisiblePatchRecursive(const ccd_pt_t &polytope, ccd_pt_face_t &f, int edge_index, const ccd_vec3_t &query_point, std::unordered_set< ccd_pt_edge_t * > *border_edges, std::unordered_set< ccd_pt_face_t * > *visible_faces, std::unordered_set< ccd_pt_face_t * > *hidden_faces, std::unordered_set< ccd_pt_edge_t * > *internal_edges)
Definition: gjk_libccd-inl.h:1243
fcl::detail::libccd_extension::doSimplex4
static int doSimplex4(ccd_simplex_t *simplex, ccd_vec3_t *dir)
Definition: gjk_libccd-inl.h:515
fcl::detail::libccd_extension::convert2SimplexToTetrahedron
static int convert2SimplexToTetrahedron(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *polytope, ccd_pt_el_t **nearest)
Definition: gjk_libccd-inl.h:766
fcl::detail::libccd_extension::ClassifyBorderEdge
static void ClassifyBorderEdge(ccd_pt_edge_t *edge, std::unordered_set< ccd_pt_edge_t * > *border_edges, std::unordered_set< ccd_pt_edge_t * > *internal_edges)
Definition: gjk_libccd-inl.h:1201
ccdPtDelFace
_ccd_inline int ccdPtDelFace(ccd_pt_t *pt, ccd_pt_face_t *)
Definition: polytope.h:226
fcl::detail::ccd_cyl_t::height
ccd_real_t height
Definition: gjk_libccd-inl.h:158
fcl::detail::ccd_cone_t
Definition: gjk_libccd-inl.h:161
fcl::Box
Center at zero point, axis aligned box.
Definition: box.h:51
_ccd_simplex_t::last
int last
index of last added point
Definition: simplex.h:45
fcl::detail::supportCap
static void supportCap(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2393
FCL_UNUSED
#define FCL_UNUSED(x)
Definition: unused.h:39
_ccd_pt_t::nearest_dist
ccd_real_t nearest_dist
Definition: polytope.h:98
fcl::detail::libccd_extension::simplexReduceToTriangle
static ccd_real_t simplexReduceToTriangle(ccd_simplex_t *simplex, ccd_real_t dist, ccd_vec3_t *best_witness)
Definition: gjk_libccd-inl.h:231
fcl::detail::libccd_extension::validateNearestFeatureOfPolytopeBeingEdge
static void validateNearestFeatureOfPolytopeBeingEdge(ccd_pt_t *polytope)
Definition: gjk_libccd-inl.h:1699
fcl::Cylinder::lz
S lz
Length along z axis.
Definition: cylinder.h:64
fcl::Sphere
Center at zero point sphere.
Definition: sphere.h:51
fcl::detail::ccd_convex_t::convex
const Convex< S > * convex
Definition: gjk_libccd-inl.h:179
ccdSupportCopy
_ccd_inline void ccdSupportCopy(ccd_support_t *, const ccd_support_t *s)
Definition: support.h:46
fcl::detail::libccd_extension::faceNormalPointingOutward
static ccd_vec3_t faceNormalPointingOutward(const ccd_pt_t *polytope, const ccd_pt_face_t *face)
Definition: gjk_libccd-inl.h:1013
fcl::detail::libccd_extension::isOutsidePolytopeFace
static bool isOutsidePolytopeFace(const ccd_pt_t *polytope, const ccd_pt_face_t *f, const ccd_vec3_t *pt)
Definition: gjk_libccd-inl.h:1123
fcl::Convex::getInteriorPoint
const Vector3< S > & getInteriorPoint() const
A point guaranteed to be on the interior of the convex polytope, used for collision.
Definition: convex.h:156
min
static T min(T x, T y)
Definition: svm.cpp:49
tolerance
S tolerance()
Definition: test_fcl_geometric_shapes.cpp:87
fcl::detail::libccd_extension::ccdVec3PointTriDist2WithWitness
static ccd_real_t ccdVec3PointTriDist2WithWitness(const ccd_vec3_t *P, const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c, ccd_vec3_t *w)
Definition: gjk_libccd-inl.h:223
ccdPtAddVertex
ccd_pt_vertex_t * ccdPtAddVertex(ccd_pt_t *pt, const ccd_support_t *v)
fcl::detail::supportCone
static void supportCone(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2449
_ccd_pt_vertex_t::v
ccd_support_t v
Definition: polytope.h:60
fcl::constants
Definition: constants.h:129
_ccd_pt_t
Definition: polytope.h:92
fcl::detail::GJKDistance
template bool GJKDistance(void *obj1, ccd_support_fn supp1, void *obj2, ccd_support_fn supp2, unsigned int max_iterations, double tolerance, double *dist, Vector3d *p1, Vector3d *p2)
CCD_PT_FACE
#define CCD_PT_FACE
Definition: polytope.h:32
fcl::detail::triGetCenterFunction
GJKCenterFunction triGetCenterFunction()
Definition: gjk_libccd-inl.h:2944
fcl::detail::libccd_extension::nextSupport
static int nextSupport(const ccd_pt_t *polytope, const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_pt_el_t *el, ccd_support_t *out)
Definition: gjk_libccd-inl.h:1584
fcl::detail::GJKDistanceImpl
bool GJKDistanceImpl(void *obj1, ccd_support_fn supp1, void *obj2, ccd_support_fn supp2, unsigned int max_iterations, S tolerance, detail::DistanceFn distance_func, S *res, Vector3< S > *p1, Vector3< S > *p2)
Definition: gjk_libccd-inl.h:2678
fcl::Cone
Center at zero cone.
Definition: cone.h:51
fcl::detail::ccd_cyl_t
Definition: gjk_libccd-inl.h:156
fcl::detail::GJKSignedDistance
template bool GJKSignedDistance(void *obj1, ccd_support_fn supp1, void *obj2, ccd_support_fn supp2, unsigned int max_iterations, double tolerance, double *dist, Vector3d *p1, Vector3d *p2)
fcl::detail::supportTriangle
static void supportTriangle(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2551
fcl::detail::supportCyl
static void supportCyl(const void *obj, const ccd_vec3_t *dir_, ccd_vec3_t *v)
Definition: gjk_libccd-inl.h:2421
fcl::detail::libccd_extension::ComputeVisiblePatch
static void ComputeVisiblePatch(const ccd_pt_t &polytope, ccd_pt_face_t &f, const ccd_vec3_t &query_point, std::unordered_set< ccd_pt_edge_t * > *border_edges, std::unordered_set< ccd_pt_face_t * > *visible_faces, std::unordered_set< ccd_pt_edge_t * > *internal_edges)
Definition: gjk_libccd-inl.h:1346
__ccdSupport
void __ccdSupport(const void *obj1, const void *obj2, const ccd_vec3_t *dir, const ccd_t *ccd, ccd_support_t *supp)
_ccd_pt_t::edges
ccd_list_t edges
List of edges.
Definition: polytope.h:94
fcl::detail::boxToGJK
static void boxToGJK(const Box< S > &s, const Transform3< S > &tf, ccd_box_t *box)
Definition: gjk_libccd-inl.h:2309
fcl
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
_ccd_pt_edge_t::faces
struct _ccd_pt_face_t * faces[2]
Reference to faces.
Definition: polytope.h:72
fcl::detail::ccd_obj_t::pos
ccd_vec3_t pos
Definition: gjk_libccd-inl.h:142
fcl::detail::libccd_extension::expandPolytope
static int expandPolytope(ccd_pt_t *polytope, ccd_pt_el_t *el, const ccd_support_t *newv)
Definition: gjk_libccd-inl.h:1402
fcl::detail::ellipsoidToGJK
static void ellipsoidToGJK(const Ellipsoid< S > &s, const Transform3< S > &tf, ccd_ellipsoid_t *ellipsoid)
Definition: gjk_libccd-inl.h:2353
fcl::Box::side
Vector3< S > side
box side length
Definition: box.h:67
fcl::Capsule< S >
fcl::Ellipsoid
Center at zero point ellipsoid.
Definition: ellipsoid.h:51
_ccd_pt_t::vertices
ccd_list_t vertices
List of vertices.
Definition: polytope.h:93
fcl::detail::GJKCenterFunction
void(*)(const void *obj, ccd_vec3_t *c) GJKCenterFunction
Definition: gjk_libccd.h:72
fcl::detail::ccd_cap_t
Definition: gjk_libccd-inl.h:151
fcl::Cylinder::radius
S radius
Radius of the cylinder.
Definition: cylinder.h:61
fcl::detail::triangle_area_is_zero
bool triangle_area_is_zero(const Vector3d &a, const Vector3d &b, const Vector3d &c)
Definition: test_gjk_libccd-inl_extractClosestPoints.cpp:177
_ccd_pt_edge_t::vertex
__CCD_PT_EL ccd_pt_vertex_t * vertex[2]
Reference to vertices.
Definition: polytope.h:71


fcl
Author(s):
autogenerated on Fri Mar 14 2025 02:38:17