38 #ifndef FCL_NARROWPHASE_DETAIL_EPA_INL_H 39 #define FCL_NARROWPHASE_DETAIL_EPA_INL_H 41 #include "fcl/narrowphase/detail/convexity_based_algorithm/epa.h" 55 EPA<S>::SimplexList::SimplexList()
56 : root(nullptr), count(0)
63 void EPA<S>::SimplexList::append(
typename EPA<S>::SimplexF* face)
67 if(root) root->l[0] = face;
74 void EPA<S>::SimplexList::remove(
typename EPA<S>::SimplexF* face)
76 if(face->l[1]) face->l[1]->l[0] = face->l[0];
77 if(face->l[0]) face->l[0]->l[1] = face->l[1];
78 if(face == root) root = face->l[1];
84 void EPA<S>::bind(SimplexF* fa,
size_t ea, SimplexF* fb,
size_t eb)
86 fa->e[ea] = eb; fa->f[ea] = fb;
87 fb->e[eb] = ea; fb->f[eb] = fa;
93 unsigned int max_face_num_,
94 unsigned int max_vertex_num_,
95 unsigned int max_iterations_, S tolerance_)
96 : max_face_num(max_face_num_),
97 max_vertex_num(max_vertex_num_),
98 max_iterations(max_iterations_),
105 template <
typename S>
113 template <
typename S>
114 void EPA<S>::initialize()
116 sv_store =
new SimplexV[max_vertex_num];
117 fc_store =
new SimplexF[max_face_num];
119 normal = Vector3<S>(0, 0, 0);
122 for(
size_t i = 0; i < max_face_num; ++i)
123 stock.append(&fc_store[max_face_num-i-1]);
127 template <
typename S>
128 bool EPA<S>::getEdgeDist(SimplexF* face, SimplexV* a, SimplexV* b, S& dist)
130 Vector3<S> ba = b->w - a->w;
131 Vector3<S> n_ab = ba.cross(face->n);
132 S a_dot_nab = a->w.dot(n_ab);
138 S a_dot_ba = a->w.dot(ba);
139 S b_dot_ba = b->w.dot(ba);
143 else if(b_dot_ba < 0)
147 S a_dot_b = a->w.dot(b->w);
148 dist = std::sqrt(std::max(a->w.squaredNorm() * b->w.squaredNorm() - a_dot_b * a_dot_b, (S)0));
158 template <
typename S>
159 typename EPA<S>::SimplexF* EPA<S>::newFace(
160 typename GJK<S>::SimplexV* a,
161 typename GJK<S>::SimplexV* b,
162 typename GJK<S>::SimplexV* c,
167 SimplexF* face = stock.root;
174 face->n.noalias() = (b->w - a->w).cross(c->w - a->w);
175 S l = face->n.norm();
179 if(!(getEdgeDist(face, a, b, face->d) ||
180 getEdgeDist(face, b, c, face->d) ||
181 getEdgeDist(face, c, a, face->d)))
183 face->d = a->w.dot(face->n) / l;
187 if(forced || face->d >= -tolerance)
193 status = Degenerated;
200 status = stock.root ? OutOfVertices : OutOfFaces;
206 template <
typename S>
209 SimplexF* minf = hull.root;
210 S mind = minf->d * minf->d;
211 for(SimplexF* f = minf->l[1]; f; f = f->l[1])
224 template <
typename S>
232 SimplexF* f = hull.root;
240 if((simplex.
c[0]->
w - simplex.
c[3]->
w).dot((simplex.
c[1]->
w - simplex.
c[3]->
w).cross(simplex.
c[2]->
w - simplex.
c[3]->
w)) < 0)
242 SimplexV* tmp = simplex.
c[0];
243 simplex.
c[0] = simplex.
c[1];
246 S tmpv = simplex.
p[0];
247 simplex.
p[0] = simplex.
p[1];
251 SimplexF* tetrahedron[] = {newFace(simplex.
c[0], simplex.
c[1], simplex.
c[2],
true),
252 newFace(simplex.
c[1], simplex.
c[0], simplex.
c[3],
true),
253 newFace(simplex.
c[2], simplex.
c[1], simplex.
c[3],
true),
254 newFace(simplex.
c[0], simplex.
c[2], simplex.
c[3],
true) };
258 SimplexF* best = findBest();
259 SimplexF outer = *best;
261 size_t iterations = 0;
264 bind(tetrahedron[0], 0, tetrahedron[1], 0);
265 bind(tetrahedron[0], 1, tetrahedron[2], 0);
266 bind(tetrahedron[0], 2, tetrahedron[3], 0);
267 bind(tetrahedron[1], 1, tetrahedron[3], 2);
268 bind(tetrahedron[1], 2, tetrahedron[2], 1);
269 bind(tetrahedron[2], 2, tetrahedron[3], 1);
272 for(; iterations < max_iterations; ++iterations)
274 if(nextsv < max_vertex_num)
276 SimplexHorizon horizon;
277 SimplexV* w = &sv_store[nextsv++];
281 S wdist = best->n.dot(w->w) - best->d;
282 if(wdist > tolerance)
284 for(
size_t j = 0; (j < 3) && valid; ++j)
286 valid &= expand(pass, w, best->f[j], best->e[j], horizon);
290 if(valid && horizon.nf >= 3)
293 bind(horizon.ff, 2, horizon.cf, 1);
301 status = InvalidHull;
break;
306 status = AccuracyReached;
break;
311 status = OutOfVertices;
break;
315 Vector3<S> projection = outer.n * outer.d;
319 result.c[0] = outer.c[0];
320 result.c[1] = outer.c[1];
321 result.c[2] = outer.c[2];
322 result.p[0] = ((outer.c[1]->w - projection).cross(outer.c[2]->w - projection)).norm();
323 result.p[1] = ((outer.c[2]->w - projection).cross(outer.c[0]->w - projection)).norm();
324 result.p[2] = ((outer.c[0]->w - projection).cross(outer.c[1]->w - projection)).norm();
326 S sum = result.p[0] + result.p[1] + result.p[2];
336 S nl = normal.norm();
337 if(nl > 0) normal /= nl;
338 else normal = Vector3<S>(1, 0, 0);
341 result.c[0] = simplex.
c[0];
348 template <
typename S>
349 bool EPA<S>::expand(
size_t pass, SimplexV* w, SimplexF* f,
size_t e, SimplexHorizon& horizon)
351 static const size_t nexti[] = {1, 2, 0};
352 static const size_t previ[] = {2, 0, 1};
356 const size_t e1 = nexti[e];
359 if(f->n.dot(w->w) - f->d < -tolerance)
361 SimplexF* nf = newFace(f->c[e1], f->c[e], w,
false);
371 bind(nf, 2, horizon.cf, 1);
382 const size_t e2 = previ[e];
384 if(expand(pass, w, f->f[e1], f->e[e1], horizon) && expand(pass, w, f->f[e2], f->e[e2], horizon))
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
bool encloseOrigin()
whether the simplex enclose the origin
Definition: gjk-inl.h:236
bool expand(size_t pass, SimplexV *w, SimplexF *f, size_t e, SimplexHorizon &horizon)
the goal is to add a face connecting vertex w and face edge f[e]
Definition: epa-inl.h:349
class for EPA algorithm
Definition: epa.h:57
S p[4]
weight
Definition: gjk.h:67
void getSupport(const Vector3< S > &d, SimplexV &sv) const
apply the support function along a direction, the result is return in sv
Definition: gjk-inl.h:204
size_t rank
size of simplex (number of vertices)
Definition: gjk.h:69
SimplexF * findBest()
Find the best polytope face to split.
Definition: epa-inl.h:207
SimplexV * c[4]
simplex vertex
Definition: gjk.h:65
Simplex * getSimplex() const
get the underlying simplex using in GJK, can be used for cache in next iteration
Definition: gjk-inl.h:302
class for GJK algorithm
Definition: gjk.h:52
Vector3< S > w
support vector (i.e., the furthest point on the shape along the support direction) ...
Definition: gjk.h:59