cheshirekow  v0.1.0
gjk88.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
27 #ifndef MPBLOCKS_GJK_H_
28 #define MPBLOCKS_GJK_H_
29 
30 #include <vector>
31 #include <set>
32 #include <cassert>
33 
34 namespace mpblocks {
35 namespace gjk88 {
36 
37 
38 
39 template <typename T> int sgn(T val) {
40  return (T(0) < val) - (val < T(0));
41 }
42 
43 
44 template <class Point>
46 {
47  Point a; //< point from a
48  Point b; //< point from b
49  Point d; //< (a-b)
50 
52 
53  MinkowskiPair( const Point& a, const Point& b ):
54  a(a),
55  b(b),
56  d(a-b)
57  {}
58 };
59 
60 
61 enum Result
62 {
66 };
67 
68 
69 template <class Point>
70 using PairVec = std::vector< MinkowskiPair<Point> >;
71 
72 
74 template < class Ops, class Point >
75 bool advanceSimplex2( Ops& ops, PairVec<Point>& simplex, Point& dir )
76 {
77  Point& b = simplex[0].d;
78  Point& a = simplex[1].d;
79 
80  Point ab = b-a;
81  Point ao = -a;
82 
83  if( ops.dot( ab,ao ) > 0 )
84  {
85  // ops.threshold returns true if the origin is sufficiently
86  if( ops.threshold( ab,ao ) )
87  return true;
88 
89  // simplex is unchanged
90  dir = ops.cross( ops.cross( ab, ao ), ab );
91  }
92  else
93  {
94  simplex[0] = simplex[1];
95  simplex.resize(1);
96  dir = ao;
97  }
98  return false;
99 }
100 
102 template < class Ops, class Point >
103 bool advanceSimplex3( Ops& ops, PairVec<Point>& simplex, Point& dir )
104 {
105  // the points, v0 is the newest
106  Point& v2 = simplex[0].d;
107  Point& v1 = simplex[1].d;
108  Point& v0 = simplex[2].d;
109 
110  // rays
111  Point r_01 = v1-v0;
112  Point r_02 = v2-v0;
113  Point r_o = -v0;
114 
115  // [0]
116  if( (ops.dot( r_01, r_o ) < 0) && (ops.dot( r_02, r_o ) < 0) )
117  {
118  simplex[0] = simplex[2];
119  simplex.resize(1);
120  dir = r_o;
121  }
122  else
123  {
124  // normal to the triangle
125  Point f_012 = ops.cross( r_01, r_02 );
126 
127  // normals of the two edges
128  Point e_01 = ops.cross( r_01, f_012 );
129  Point e_02 = ops.cross( f_012, r_02 );
130 
131  auto test_e_01 = ops.dot( e_01, r_o );
132  auto test_e_02 = ops.dot( e_02, r_o );
133 
134  // [3] or [4]
135  if( (test_e_01 < 0) && (test_e_02 < 0) )
136  {
137  // ops.threshold returns true if the origin is sufficiently
138  // close to the surface of this simplex, or always in 2D
139  if( ops.threshold( v0,v1,v2 ) )
140  return true;
141 
142  // [3]
143  if( ops.dot( f_012, r_o ) > 0 )
144  {
145  // the simplex is maintained as is for the next iteration
146  dir = f_012;
147  }
148  // [4]
149  else
150  {
151  // flip v1 and v2 so that the picture in our heads is consistent
152  std::swap( simplex[0], simplex[1] );
153  dir = -f_012;
154  }
155  }
156  // [1], or [2]
157  else
158  {
159  // [1]
160  if( test_e_01 > 0 )
161  {
162  simplex[0] = simplex[1];
163  simplex[1] = simplex[2];
164  simplex.resize(2);
165  dir = ops.cross( ops.cross( r_01, r_o ), r_01 );
166  }
167  // [2]
168  else
169  {
170  simplex[1] = simplex[2];
171  simplex.resize(2);
172  dir = ops.cross( ops.cross( r_02, r_o ), r_02 );
173  }
174  }
175  }
176 
177  return false;
178 }
179 
180 
182 template < class Ops, class Point >
183 bool advanceSimplex4( Ops& ops, PairVec<Point>& simplex, Point& dir )
184 {
185  Point& v3 = simplex[0].d;
186  Point& v2 = simplex[1].d;
187  Point& v1 = simplex[2].d;
188  Point& v0 = simplex[3].d;
189 
190  Point r3 = v3-v0;
191  Point r2 = v2-v0;
192  Point r1 = v1-v0;
193  Point ro = -v0;
194 
195  // exterior
196  if( ops.dot(r3,ro) < 0
197  && ops.dot(r2,ro) < 0
198  && ops.dot(r1,ro) < 0 )
199  {
200  simplex[0] = simplex[3];
201  simplex.resize(1);
202  dir = ro;
203  }
204  else
205  {
206  Point f_12 = ops.cross(r1,r2);
207  Point f_23 = ops.cross(r2,r3);
208  Point f_31 = ops.cross(r3,r1);
209 
210  auto test_f_12 = ops.dot(f_12,ro);
211  auto test_f_23 = ops.dot(f_23,ro);
212  auto test_f_31 = ops.dot(f_31,ro);
213 
214  // interior
215  if( test_f_12 < 0
216  && test_f_23 < 0
217  && test_f_31 < 0 )
218  {
219  return true;
220  }
221  else
222  {
223  Point e_21 = ops.cross(f_12, r2);
224  Point e_23 = ops.cross(r2, f_23);
225  Point e_13 = ops.cross(f_31, r1);
226  Point e_12 = ops.cross(r1, f_12);
227  Point e_32 = ops.cross(f_23, r3);
228  Point e_31 = ops.cross(r3, f_31);
229 
230  auto test_21 = ops.dot( e_21, ro );
231  auto test_23 = ops.dot( e_23, ro );
232  auto test_13 = ops.dot( e_13, ro );
233  auto test_12 = ops.dot( e_12, ro );
234  auto test_32 = ops.dot( e_32, ro );
235  auto test_31 = ops.dot( e_31, ro );
236 
237  // v is on edge(v0,v1)
238  if( test_12 > 0 && test_13 > 0 )
239  {
240  simplex[0] = simplex[2];
241  simplex[1] = simplex[3];
242  simplex.resize(2);
243  dir = ops.cross( ops.cross (r1, ro ), r1 );
244  }
245  // wedge 02
246  else if( test_23 > 0 && test_21 > 0 )
247  {
248  simplex[0] = simplex[1];
249  simplex[1] = simplex[3];
250  simplex.resize(2);
251  dir = ops.cross( ops.cross (r2, ro ), r2 );
252  }
253  // wedge 03
254  else if( test_32 > 0 && test_31 > 0)
255  {
256  simplex[1] = simplex[3];
257  simplex.resize(2);
258  dir = ops.cross( ops.cross (r3, ro ), r3 );
259  }
260  // prism 012
261  else if( test_f_12 > 0 && test_12 < 0 && test_21 < 0 )
262  {
263  simplex[0] = simplex[1];
264  simplex[1] = simplex[2];
265  simplex[2] = simplex[3];
266  simplex.resize(3);
267  dir = f_12;
268  }
269  // prism 023
270  else if( test_f_23 > 0 && test_23 < 0 && test_32 < 0 )
271  {
272  simplex[2] = simplex[3];
273  simplex.resize(3);
274  dir = f_23;
275  }
276  // prism 031
277  else
278  {
279  simplex[1] = simplex[2];
280  simplex[2] = simplex[3];
281  simplex.resize(3);
282  dir = f_31;
283  }
284 
285  }
286  }
287 
288  return false;
289 }
290 
291 
294 template < class Ops, class Point >
295 bool advanceSimplex( Ops& ops, std::vector< MinkowskiPair<Point> >& simplex, Point& dir )
296 {
297  switch(simplex.size())
298  {
299  case 2:
300  return advanceSimplex2(ops,simplex,dir);
301  break;
302 
303  case 3:
304  return advanceSimplex3(ops,simplex,dir);
305  break;
306 
307  case 4:
308  return advanceSimplex4(ops,simplex,dir);
309  break;
310 
311  default:
312  assert(!"GJK: attempting to advance an overfull simplex");
313  break;
314  }
315 
316  return INDETERMINANT;
317 }
318 
319 
320 
321 
323 
364 template <class Ops, class SupportFn, class Point>
365 Result isCollision( Ops ops, SupportFn supportFn,
366  Point& a, Point& b, Point& d, int maxIter=100 )
367 {
368  typedef MinkowskiPair<Point> MPair;
369  typedef std::vector<MPair> PointVec;
370 
371  PairVec<Point> simplex;
372 
373  d = -(a-b);
374  simplex.emplace_back( a, b );
375 
376  while( maxIter-- > 0 )
377  {
378  supportFn(d,a,b);
379  if( ops.dot( d,(a-b) ) < 0 )
380  return COLLISION_FREE;
381  simplex.emplace_back( a, b );
382 
383  if( advanceSimplex(ops,simplex,d) )
384  return COLLISION;
385  }
386 
387  return INDETERMINANT;
388 }
389 
390 
391 
392 
393 
394 
395 
396 
397 
398 
399 
400 
401 
402 
403 
404 
405 
406 
407 
408 
409 
410 
411 
413 template < class Ops, class Point >
414 bool growSimplex2( Ops& ops, PairVec<Point>& simplex, Point& v )
415 {
416  Point& b = simplex[0].d;
417  Point& a = simplex[1].d;
418 
419  Point ab = b-a;
420  Point ao = -a;
421  Point ab_n = ops.normalize(ab);
422 
423  auto d_ab = ops.dot( -a, ab_n );
424  if( d_ab > 0 )
425  {
426  Point c = a + d_ab * ab_n;
427  v = c;
428  }
429  else
430  {
431  simplex[0] = simplex[1];
432  simplex.resize(1);
433  v = a;
434  }
435  return false;
436 }
437 
439 template < class Ops, class Point >
440 bool growSimplex3_2d( Ops& ops, PairVec<Point>& simplex, Point& v )
441 {
442  // the points, v0 is the newest
443  Point& v2 = simplex[0].d;
444  Point& v1 = simplex[1].d;
445  Point& v0 = simplex[2].d;
446 
447  // compute barycentric coordinates
448  if( ops.containsOrigin(v0,v1,v2) )
449  return true;
450 
451  // rays
452  Point r_01 = ops.normalize(v1-v0);
453  Point r_02 = ops.normalize(v2-v0);
454  Point r_o = -v0;
455 
456  // project origin onto each of the sides of the triangle
457  auto p_01 = ops.dot(r_01,r_o);
458  auto p_02 = ops.dot(r_02,r_o);
459 
460  // if both are negative then origin is closes to the vertex
461  if( p_01 < 0 && p_02 < 0 )
462  {
463  simplex[0] = simplex[2];
464  simplex.resize(1);
465  v = v0;
466  }
467 
468  // otherwise the origin is closer to one of the faces, so see which
469  else if( p_01 > 0 )
470  {
471  v = (v0 + p_01*ops.normalize(r_01));
472  simplex.resize(2);
473  }
474  else
475  {
476  v = (v0 + p_02*ops.normalize(r_02));
477  simplex[1] = simplex[2];
478  simplex.resize(2);
479  }
480  return false;
481 }
482 
484 template < class Ops, class Point >
485 bool growSimplex3_3d( Ops& ops, PairVec<Point>& simplex, Point& v )
486 {
487  // the points, v0 is the newest
488  Point& v2 = simplex[0].d;
489  Point& v1 = simplex[1].d;
490  Point& v0 = simplex[2].d;
491 
492  // rays
493  Point r_01 = ops.normalize(v1-v0);
494  Point r_02 = ops.normalize(v2-v0);
495  Point r_o = -v0;
496 
497  Point n = ops.normalize( ops.cross(r_01,r_02) );
498  auto f = ops.dot(n,v0);
499 
500  // origin, projected onto plane of three points
501  Point o = f*n;
502  Point r_op = o - v0;
503 
504  // find cross product of the two edges of the triangle and of the vector
505  // from v0 to the projection of the origin onto the plane, and then
506  // use these to determine if projection of the origin lies inside the
507  // triangle
508 // Point x1 = ops.normalize( ops.cross(v0-o,v1-o) );
509 // Point x2 = ops.normalize( ops.cross(v1-o,v2-o) );
510 // Point x3 = ops.normalize( ops.cross(v2-o,v0-o) );
511 
512  // if the projection of the origin onto the plane of the three points lies
513  // inside the triangle, then that point is the nearest point to the origin,
514  // and the simplex remains as is
515 // if( sgn( ops.dot(x1,x2) ) == sgn( ops.dot(x2,x3) )
516 // && sgn( ops.dot(x2,x3) ) == sgn( ops.dot(x3,x1) ) )
517 // v = o;
518 
519  // find cross product of the two edges of the triangle and of the vector
520  // from v0 to the projection of the origin onto the plane, and then
521  // use these to determine if projection of the origin lies inside the
522  // triangle
523  Point bxo = ops.normalize( ops.cross(r_01,r_op) );
524  Point oxc = ops.normalize( ops.cross(r_op,r_02) );
525  Point bxc = ops.normalize( ops.cross(r_01,r_02) );
526 
527  // if the projection of the origin onto the plane of the three points lies
528  // inside the triangle, then that point is the nearest point to the origin,
529  // and the simplex remains as is
530  if( sgn( ops.dot(bxo,oxc) ) > 0 && sgn( ops.dot(bxo,bxc) ) > 0 )
531  v = o;
532  else
533  {
534  // project origin onto each of the sides of the triangle
535  auto p_01 = ops.dot(r_01,r_o);
536  auto p_02 = ops.dot(r_02,r_o);
537 
538  // if both are negative then origin is closes to the vertex
539  if( p_01 < 0 && p_02 < 0 )
540  {
541  simplex[0] = simplex[2];
542  simplex.resize(1);
543  v = v0;
544  }
545 
546  // otherwise the origin is closer to one of the faces, so see which
547  else if( p_01 > 0 )
548  {
549  v = (v0 + p_01*ops.normalize(r_01));
550  simplex[0] = simplex[1];
551  simplex[1] = simplex[2];
552  simplex.resize(2);
553  }
554  else
555  {
556  v = (v0 + p_02*ops.normalize(r_02));
557  simplex[1] = simplex[2];
558  simplex.resize(2);
559  }
560  }
561  return false;
562 }
563 
564 
566 template < class Ops, class Point >
568  Ops& ops, PairVec<Point>& simplex, Point& v, int depth=0 )
569 {
570  Point& v3 = simplex[0].d;
571  Point& v2 = simplex[1].d;
572  Point& v1 = simplex[2].d;
573  Point& v0 = simplex[3].d;
574 
575  // if triangle(v1,v2,v3) points in the same direction as
576  // v0 then we need to flip the order
577  Point r12 = ops.normalize(v2-v1);
578  Point r13 = ops.normalize(v3-v1);
579  if( ops.dot( ops.cross(r12,r13), v0-v1 ) < 0 )
580  {
581  std::swap(simplex[0],simplex[2]);
582  if( depth > 3 )
583  {
584  v = v0;
585  simplex[0] = simplex[3];
586  simplex.resize(1);
587  return false;
588  }
589  return growSimplex4_3d(ops,simplex,v,depth+1);
590  }
591 
592  Point r3 = ops.normalize(v3-v0);
593  Point r2 = ops.normalize(v2-v0);
594  Point r1 = ops.normalize(v1-v0);
595  Point ro = -v0;
596 
597  // projection of origin onto each of the edges
598  auto p_1 = ops.dot(ro,r1);
599  auto p_2 = ops.dot(ro,r2);
600  auto p_3 = ops.dot(ro,r3);
601 
602  // if the projection of the origin onto all edges is in the negative
603  // direction then v is v0 and the new simplex is just v0
604  if( p_1 < 0 && p_2 < 0 && p_3 < 0 )
605  {
606  simplex[0] = simplex[3];
607  simplex.resize(1);
608  v = v0;
609  }
610  else
611  {
612  // compute the normal for each of the three new tetrahedral faces,
613  // ignore the fourth face which was pruned by the previous simplex
614  // expansion
615  Point n_12 = ops.normalize( ops.cross(r1,r2) );
616  Point n_23 = ops.normalize( ops.cross(r2,r3) );
617  Point n_31 = ops.normalize( ops.cross(r3,r1) );
618 
619  auto f_12 = ops.dot(n_12,ro);
620  auto f_23 = ops.dot(n_23,ro);
621  auto f_31 = ops.dot(n_31,ro);
622 
623  // if all faces are oriented outward, then the origin is interior
624  // to the simplex
625  if( f_12 < 0 && f_23 < 0 && f_31 < 0 )
626  return true;
627  else
628  {
629  // For each edge of the tetrahedron, compute two normals, each one
630  // pointing "outside" of a face, for each of the two faces that
631  // the edge is a member of
632  Point n_12_2 = ops.normalize( ops.cross(n_12, r2) );
633  Point n_23_2 = ops.normalize( ops.cross(r2, n_23) );
634  Point n_31_1 = ops.normalize( ops.cross(n_31, r1) );
635  Point n_12_1 = ops.normalize( ops.cross(r1, n_12) );
636  Point n_23_3 = ops.normalize( ops.cross(n_23, r3) );
637  Point n_31_3 = ops.normalize( ops.cross(r3, n_31) );
638 
639  // also compute the projection of ray(v0,o) onto that normal
640  auto f_12_2 = ops.dot( n_12_2, ro );
641  auto f_23_2 = ops.dot( n_23_2, ro );
642  auto f_31_1 = ops.dot( n_31_1, ro );
643  auto f_12_1 = ops.dot( n_12_1, ro );
644  auto f_23_3 = ops.dot( n_23_3, ro );
645  auto f_31_3 = ops.dot( n_31_3, ro );
646 
647  // v is on edge(v0,v1)
648  if( f_12_1 > 0 && f_31_1 > 0 )
649  {
650  simplex[0] = simplex[2];
651  simplex[1] = simplex[3];
652  simplex.resize(2);
653  v = v0 + p_1*r1;
654  }
655 
656  // v is on edge(v0,v2)
657  else if( f_12_2 > 0 && f_23_2 > 0 )
658  {
659  simplex[0] = simplex[1];
660  simplex[1] = simplex[3];
661  simplex.resize(2);
662  v = v0 + p_2*r2;
663  }
664 
665  // v is on edge(v0,v3)
666  else if( f_31_3 > 0 && f_23_3 > 0)
667  {
668  simplex[1] = simplex[3];
669  simplex.resize(2);
670  v = v0 + p_3*r3;
671  }
672 
673  // v is on face(v0,v1,v2)
674  else if( f_12 > 0 && f_12_1 < 0 && f_12_2 < 0 )
675  {
676  simplex[0] = simplex[1];
677  simplex[1] = simplex[2];
678  simplex[2] = simplex[3];
679  simplex.resize(3);
680  v = ops.dot(v0,n_12)*n_12;
681  }
682 
683  // v is on face(v0,v2,v3)
684  else if( f_23 > 0 && f_23_2 < 0 && f_23_3 < 0 )
685  {
686  simplex[2] = simplex[3];
687  simplex.resize(3);
688  v = ops.dot(v0,n_23)*n_23;
689  }
690  // v is on face(v0,v3,v1)
691  else
692  {
693  simplex[1] = simplex[2];
694  simplex[2] = simplex[3];
695  simplex.resize(3);
696  v = ops.dot(v0,n_31)*n_31;
697  }
698  }
699  }
700 
701  return false;
702 }
703 
704 
705 
708 template < class Ops, class Point >
709 bool growSimplex_2d( Ops& ops, std::vector< MinkowskiPair<Point> >& simplex, Point& v )
710 {
711  switch(simplex.size())
712  {
713  case 2:
714  return growSimplex2(ops,simplex,v);
715  break;
716 
717  case 3:
718  return growSimplex3_2d(ops,simplex,v);
719  break;
720 
721  default:
722  assert(!"GJK: attempting to advance an overfull simplex");
723  break;
724  }
725  return false;
726 }
727 
730 template < class Ops, class Point >
732  Ops& ops, std::vector< MinkowskiPair<Point> >& simplex, Point& v )
733 {
734  switch(simplex.size())
735  {
736  case 2:
737  return growSimplex2(ops,simplex,v);
738  break;
739 
740  case 3:
741  return growSimplex3_3d(ops,simplex,v);
742  break;
743 
744  case 4:
745  return growSimplex4_3d(ops,simplex,v);
746  break;
747 
748  default:
749  assert(!"GJK: attempting to advance an overfull simplex");
750  break;
751  }
752  return false;
753 }
754 
755 
756 
757 
758 
759 
760 
761 
762 template <class Ops, class SupportFn, class Point,
763  class SimplexHistory,
764  class PointHistory>
765 Result collisionDistance_2d_debug( Ops ops, SupportFn supportFn,
766  Point& a, Point& b, Point& v,
767  SimplexHistory sHist,
768  PointHistory vHist, int maxIter=100 )
769 {
770  typedef MinkowskiPair<Point> MPair;
771  PairVec<Point> simplex;
772 
773  simplex.reserve(4);
774  simplex.push_back( MPair(a,b) );
775  v = (a-b);
776 
777  *(sHist++) = simplex;
778  *(vHist++) = v;
779 
780  while( maxIter-- > 0 )
781  {
782  supportFn(-v,a,b);
783  if( std::abs( ops.dot(v,v) + ops.dot( -v,(a-b) ) ) < 1e-6 )
784  return COLLISION_FREE;
785 
786  simplex.push_back( MPair(a,b) );
787  *(sHist++) = simplex;
788  bool isCollision = growSimplex_2d(ops,simplex,v);
789  *(vHist++) = v;
790 
791  if( isCollision )
792  return COLLISION;
793  }
794 
795  return INDETERMINANT;
796 }
797 
798 
799 template< int NDim, class Point >
800 bool isEqual( const Point& a, const Point& b )
801 {
802  for(int i=0; i < NDim; i++)
803  if( a[i] != b[i] )
804  return false;
805  return true;
806 }
807 
808 
809 template <class Ops, class SupportFn, class Point>
810 Result collisionDistance_3d( Ops ops, SupportFn supportFn,
811  Point& a, Point& b, Point& v, int maxIter=100 )
812 {
813  typedef MinkowskiPair<Point> MPair;
814  PairVec<Point> simplex;
815 
816  simplex.reserve(4);
817  simplex.push_back( MPair(a,b) );
818  v = (a-b);
819 
820  while( maxIter-- > 0 )
821  {
822  supportFn(-v,a,b);
823  if( std::abs( ops.dot(v,v) + ops.dot( -v,(a-b) ) ) < 1e-6 )
824  return COLLISION_FREE;
825 
826  MPair newPair(a,b);
827  for( auto& m : simplex )
828  if( isEqual<3>(m.d,newPair.d) )
829  return COLLISION_FREE;
830 
831  simplex.push_back( newPair );
832  if( growSimplex_3d(ops,simplex,v) )
833  return COLLISION;
834  }
835 
836  return INDETERMINANT;
837 }
838 
839 
840 
841 
842 template <class Ops, class SupportFn, class Point,
843  class SimplexHistory,
844  class PointHistory,
845  class ErrorHistory>
846 Result collisionDistance_3d_debug( Ops ops, SupportFn supportFn,
847  Point& a, Point& b, Point& v,
848  SimplexHistory sHist,
849  PointHistory vHist,
850  ErrorHistory eHist, int maxIter=100 )
851 {
852  typedef MinkowskiPair<Point> MPair;
853  PairVec<Point> simplex;
854 
855  simplex.reserve(4);
856  simplex.push_back( MPair(a,b) );
857  v = (a-b);
858 
859  *(sHist++) = simplex;
860  *(vHist++) = v;
861  *(eHist++) = 0;
862 
863  while( maxIter-- > 0 )
864  {
865  supportFn(-v,a,b);
866  auto e = ops.dot(v,v) + ops.dot( -v,(a-b) );
867  *(eHist++) = e;
868  if( std::abs( e ) < 1e-6 )
869  {
870  *(sHist++) = simplex;
871  *(vHist++) = v;
872  return COLLISION_FREE;
873  }
874 
875  MPair newPair(a,b);
876  for( auto& m : simplex )
877  {
878  if( isEqual<3>(m.d,newPair.d) )
879  {
880  *(sHist++) = simplex;
881  *(vHist++) = v;
882  return COLLISION_FREE;
883  }
884  }
885  simplex.push_back( newPair );
886  *(sHist++) = simplex;
887 
888  bool isCollision = growSimplex_3d(ops,simplex,v);
889  *(vHist++) = v;
890 
891  if( isCollision )
892  return COLLISION;
893  }
894 
895  return INDETERMINANT;
896 }
897 
898 
899 
900 
901 
902 
903 
904 
905 
906 } //< namespace gjk88
907 } //< namespace mpblocks
908 
909 
910 
911 
912 
913 
914 
915 
916 
917 
918 
919 
920 
921 
922 
923 #endif // GJK_H_
bool advanceSimplex3(Ops &ops, PairVec< Point > &simplex, Point &dir)
returns true if the origin is contained in the triangle
Definition: gjk88.h:103
bool growSimplex3_2d(Ops &ops, PairVec< Point > &simplex, Point &v)
returns true if the origin is contained in the triangle
Definition: gjk88.h:440
bool advanceSimplex(Ops &ops, std::vector< MinkowskiPair< Point > > &simplex, Point &dir)
returns true if the origin is contained in the simplex, and if it is not, returns false and generates...
Definition: gjk88.h:295
std::vector< MinkowskiPair< Point > > PairVec
Definition: gjk88.h:70
bool advanceSimplex2(Ops &ops, PairVec< Point > &simplex, Point &dir)
returns true if the origin is contained in the segment
Definition: gjk88.h:75
Result collisionDistance_3d_debug(Ops ops, SupportFn supportFn, Point &a, Point &b, Point &v, SimplexHistory sHist, PointHistory vHist, ErrorHistory eHist, int maxIter=100)
Definition: gjk88.h:846
bool growSimplex4_3d(Ops &ops, PairVec< Point > &simplex, Point &v, int depth=0)
returns true if the origin is contained in the tetrahedron
Definition: gjk88.h:567
Result collisionDistance_3d(Ops ops, SupportFn supportFn, Point &a, Point &b, Point &v, int maxIter=100)
Definition: gjk88.h:810
MinkowskiPair(const Point &a, const Point &b)
Definition: gjk88.h:53
bool growSimplex2(Ops &ops, PairVec< Point > &simplex, Point &v)
returns true if the origin is contained in the segment
Definition: gjk88.h:414
bool growSimplex3_3d(Ops &ops, PairVec< Point > &simplex, Point &v)
returns true if the origin is contained in the triangle
Definition: gjk88.h:485
bool growSimplex_2d(Ops &ops, std::vector< MinkowskiPair< Point > > &simplex, Point &v)
returns true if the origin is contained in the simplex, and if it is not, returns false and generates...
Definition: gjk88.h:709
int sgn(T val)
Definition: gjk88.h:39
bool advanceSimplex4(Ops &ops, PairVec< Point > &simplex, Point &dir)
returns true if the origin is contained in the tetrahedron
Definition: gjk88.h:183
bool isEqual(const Point &a, const Point &b)
Definition: gjk88.h:800
Result collisionDistance_2d_debug(Ops ops, SupportFn supportFn, Point &a, Point &b, Point &v, SimplexHistory sHist, PointHistory vHist, int maxIter=100)
Definition: gjk88.h:765
bool growSimplex_3d(Ops &ops, std::vector< MinkowskiPair< Point > > &simplex, Point &v)
returns true if the origin is contained in the simplex, and if it is not, returns false and generates...
Definition: gjk88.h:731
Result isCollision(Ops ops, SupportFn supportFn, Point &a, Point &b, Point &d, int maxIter=100)
GJK algorithm, determines if two convex objects are in collision.
Definition: gjk88.h:365