55 support = triangle->
c;
57 support = triangle->
a;
60 support = triangle->
c;
62 support = triangle->
b;
85 Vec3f v(a2 * dir[0], b2 * dir[1],
c2 * dir[2]);
108 if (dir.head<2>().isZero()) {
116 FCL_REAL zdist = dir[0] * dir[0] + dir[1] * dir[1];
117 FCL_REAL len = zdist + dir[2] * dir[2];
118 zdist = std::sqrt(zdist);
122 support.head<2>() = rad * dir.head<2>();
127 len = std::sqrt(len);
130 if (dir[2] > len * sin_a)
134 support.head<2>() = rad * dir.head<2>();
148 if (dir.head<2>() == Eigen::Matrix<FCL_REAL, 2, 1>::Zero()) half_h *=
inflate;
153 support[2] = -half_h;
158 if (dir.head<2>() == Eigen::Matrix<FCL_REAL, 2, 1>::Zero())
161 support.head<2>() = dir.head<2>().normalized() *
r;
162 assert(fabs(support[0] * dir[1] - support[1] * dir[0]) <
170 Vec3f& support,
int& hint,
172 assert(
data != NULL);
177 if (hint < 0 || hint >= (
int)convex->
num_points) hint = 0;
178 FCL_REAL maxdot = pts[hint].dot(dir);
179 std::vector<int8_t>& visited =
data->visited;
181 visited[
static_cast<std::size_t
>(hint)] =
true;
184 bool found =
true, loose_check =
true;
188 for (
int in = 0; in < n.
count(); ++in) {
189 const unsigned int ip = n[in];
190 if (visited[ip])
continue;
192 const FCL_REAL dot = pts[ip].dot(dir);
197 }
else if (loose_check && dot == maxdot)
201 hint =
static_cast<int>(ip);
211 Vec3f& support,
int& hint,
217 for (
int i = 1; i < (int)convex->
num_points; ++i) {
239 Vec3f& support,
int& hint,
242 support, hint,
data);
246 Vec3f& support,
int& hint,
252 #define CALL_GET_SHAPE_SUPPORT(ShapeType) \
254 static_cast<const ShapeType*>(shape), \
255 (shape_traits<ShapeType>::NeedNormalizedDir && !dirIsNormalized) \
298 #undef CALL_GET_SHAPE_SUPPORT
300 template <
typename Shape0,
typename Shape1,
bool TransformIsIdentity>
306 if (TransformIsIdentity)
310 support1 = oR1 * support1 + ot1;
314 template <
typename Shape0,
typename Shape1,
bool TransformIsIdentity>
316 bool dirIsNormalized,
Vec3f& support0,
Vec3f& support1,
325 assert(!NeedNormalizedDir || !dirIsNormalized ||
326 fabs(dir.squaredNorm() - 1) < 1e-6);
328 assert(!NeedNormalizedDir || dirIsNormalized ||
329 fabs(dir.normalized().squaredNorm() - 1) < 1e-6);
331 assert(NeedNormalizedDir || dir.cwiseAbs().maxCoeff() >= 1e-6);
333 getSupportTpl<Shape0, Shape1, TransformIsIdentity>(
334 static_cast<const Shape0*
>(md.
shapes[0]),
335 static_cast<const Shape1*
>(md.
shapes[1]), md.
oR1, md.
ot1,
336 (NeedNormalizedDir && !dirIsNormalized) ? dir.normalized() : dir,
337 support0, support1, hint,
data);
340 template <
typename Shape0>
342 const ShapeBase* s1,
bool identity, Eigen::Array<FCL_REAL, 1, 2>& inflation,
343 int linear_log_convex_threshold) {
348 return getSupportFuncTpl<Shape0, TriangleP, true>;
350 return getSupportFuncTpl<Shape0, TriangleP, false>;
353 return getSupportFuncTpl<Shape0, Box, true>;
355 return getSupportFuncTpl<Shape0, Box, false>;
357 inflation[1] =
static_cast<const Sphere*
>(s1)->radius;
359 return getSupportFuncTpl<Shape0, Sphere, true>;
361 return getSupportFuncTpl<Shape0, Sphere, false>;
364 return getSupportFuncTpl<Shape0, Ellipsoid, true>;
366 return getSupportFuncTpl<Shape0, Ellipsoid, false>;
368 inflation[1] =
static_cast<const Capsule*
>(s1)->radius;
370 return getSupportFuncTpl<Shape0, Capsule, true>;
372 return getSupportFuncTpl<Shape0, Capsule, false>;
375 return getSupportFuncTpl<Shape0, Cone, true>;
377 return getSupportFuncTpl<Shape0, Cone, false>;
380 return getSupportFuncTpl<Shape0, Cylinder, true>;
382 return getSupportFuncTpl<Shape0, Cylinder, false>;
384 if ((
int)
static_cast<const ConvexBase*
>(s1)->num_points >
385 linear_log_convex_threshold) {
387 return getSupportFuncTpl<Shape0, LargeConvex, true>;
389 return getSupportFuncTpl<Shape0, LargeConvex, false>;
392 return getSupportFuncTpl<Shape0, SmallConvex, true>;
394 return getSupportFuncTpl<Shape0, SmallConvex, false>;
397 throw std::logic_error(
"Unsupported geometric shape");
403 Eigen::Array<FCL_REAL, 1, 2>& inflation,
int linear_log_convex_threshold) {
407 return makeGetSupportFunction1<TriangleP>(s1, identity, inflation,
408 linear_log_convex_threshold);
411 return makeGetSupportFunction1<Box>(s1, identity, inflation,
412 linear_log_convex_threshold);
415 inflation[0] =
static_cast<const Sphere*
>(s0)->radius;
416 return makeGetSupportFunction1<Sphere>(s1, identity, inflation,
417 linear_log_convex_threshold);
420 return makeGetSupportFunction1<Ellipsoid>(s1, identity, inflation,
421 linear_log_convex_threshold);
424 inflation[0] =
static_cast<const Capsule*
>(s0)->radius;
425 return makeGetSupportFunction1<Capsule>(s1, identity, inflation,
426 linear_log_convex_threshold);
429 return makeGetSupportFunction1<Cone>(s1, identity, inflation,
430 linear_log_convex_threshold);
433 return makeGetSupportFunction1<Cylinder>(s1, identity, inflation,
434 linear_log_convex_threshold);
437 if ((
int)
static_cast<const ConvexBase*
>(s0)->num_points >
438 linear_log_convex_threshold)
439 return makeGetSupportFunction1<LargeConvex>(
440 s1, identity, inflation, linear_log_convex_threshold);
442 return makeGetSupportFunction1<SmallConvex>(
443 s1, identity, inflation, linear_log_convex_threshold);
446 throw std::logic_error(
"Unsupported geometric shape");
477 throw std::logic_error(
"Unsupported geometric shape");
483 bool& normalize_support_direction) {
499 bool identity = (
oR1.isIdentity() &&
ot1.isZero());
536 assert(vs[i]->w.isApprox(vs[i]->
w0 - vs[i]->
w1));
539 Project::ProjectResult projection;
540 switch (simplex.
rank) {
546 const Vec3f &
a = vs[0]->
w, a0 = vs[0]->
w0, a1 = vs[0]->
w1,
b = vs[1]->
w,
547 b0 = vs[1]->
w0, b1 = vs[1]->
w1;
556 lb = N.squaredNorm();
564 w0 = la * a0 + lb * b0;
565 w1 = la * a1 + lb * b1;
572 projection = Project::projectTriangleOrigin(vs[0]->w, vs[1]->w, vs[2]->w);
575 projection = Project::projectTetrahedraOrigin(vs[0]->w, vs[1]->w,
579 throw std::logic_error(
"The simplex rank must be in [ 1, 4 ]");
584 w0 += projection.parameterization[i] * vs[i]->
w0;
585 w1 += projection.parameterization[i] * vs[i]->
w1;
591 template <
bool Separated>
593 const Eigen::Array<FCL_REAL, 1, 2>& I(shape.
inflation);
594 Eigen::Array<bool, 1, 2>
inflate(I > 0);
600 if (
inflate[0]) w0[0] += I[0] * (Separated ? -1 : 1);
601 if (
inflate[1]) w1[0] += I[1] * (Separated ? 1 : -1);
607 if (
inflate[0]) w0 -= I[0] * w;
608 if (
inflate[1]) w1 += I[1] * w;
610 if (
inflate[0]) w0 += I[0] * w;
611 if (
inflate[1]) w1 -= I[1] * w;
619 if (!
res)
return false;
620 details::inflate<true>(
shape, w0, w1);
678 switch (current_gjk_variant) {
686 if (normalize_support_direction) {
688 y = momentum *
ray + (1 - momentum) * w;
695 dir = momentum * dir / dir.norm() + (1 - momentum) *
y / y_norm;
698 y = momentum *
ray + (1 - momentum) * w;
699 dir = momentum * dir + (1 - momentum) *
y;
704 throw std::logic_error(
"Invalid momentum variant.");
715 FCL_REAL omega = dir.dot(w) / dir.norm();
716 if (omega > upper_bound) {
725 if (frank_wolfe_duality_gap -
tolerance <= 0) {
755 switch (curr_simplex.
rank) {
760 next_simplex.
rank = 1;
773 throw std::logic_error(
"Invalid simplex rank");
777 if (!inside) rl =
ray.norm();
778 if (inside || rl == 0) {
805 alpha = std::max(alpha, omega);
810 throw std::logic_error(
"VDB convergence criterion is relative.");
813 check_passed = (diff -
tolerance * rl) <= 0;
816 throw std::logic_error(
"Invalid convergence criterion type.");
822 diff = 2 *
ray.dot(
ray - w);
831 throw std::logic_error(
"Invalid convergence criterion type.");
837 alpha = std::max(alpha, omega);
839 diff = rl * rl - alpha * alpha;
848 throw std::logic_error(
"Invalid convergence criterion type.");
853 throw std::logic_error(
"Invalid convergence criterion.");
873 for (
int i = 0; i < 3; ++i) {
887 for (
int i = 0; i < 3; ++i) {
905 if (!
axis.isZero()) {
938 ray = AB.dot(
B) *
A + ABdotAO *
B;
945 ray /= AB.squaredNorm();
970 ray = -ABCdotAO / ABC.squaredNorm() * ABC;
982 assert(d <= AB.squaredNorm());
1008 const Vec3f AB =
B -
A, AC = C -
A, ABC = AB.cross(AC);
1010 FCL_REAL edgeAC2o = ABC.cross(AC).dot(-
A);
1011 if (edgeAC2o >= 0) {
1013 if (towardsC >= 0) {
1027 FCL_REAL edgeAB2o = AB.cross(ABC).dot(-
A);
1028 if (edgeAB2o >= 0) {
1070 const Vec3f a_cross_b =
A.cross(
B);
1071 const Vec3f a_cross_c =
A.cross(C);
1076 #define REGION_INSIDE() \
1078 next.vertex[0] = current.vertex[d]; \
1079 next.vertex[1] = current.vertex[c]; \
1080 next.vertex[2] = current.vertex[b]; \
1081 next.vertex[3] = current.vertex[a]; \
1086 if (-
D.dot(a_cross_b) <= 0) {
1087 if (ba * da_ba + bd * ba_aa - bb * da_aa <=
1090 assert(da * da_ba + dd * ba_aa - db * da_aa <=
1092 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1096 -C.dot(a_cross_b), next,
ray);
1105 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1107 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
1109 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1113 -
D.dot(a_cross_c), next,
ray);
1124 -C.dot(a_cross_b), next,
ray);
1135 if (da * da_ba + dd * ba_aa - db * da_aa <=
1139 D.dot(a_cross_b), next,
ray);
1142 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1144 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1153 -
D.dot(a_cross_c), next,
ray);
1157 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1173 if (C.dot(a_cross_b) <= 0) {
1174 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1176 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
1178 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1182 -
D.dot(a_cross_c), next,
ray);
1193 -C.dot(a_cross_b), next,
ray);
1203 if (
D.dot(a_cross_c) <= 0) {
1204 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1206 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1215 -
D.dot(a_cross_c), next,
ray);
1239 if (
D.dot(a_cross_c) <= 0) {
1241 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1243 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1245 if (da * da_ba + dd * ba_aa - db * da_aa <=
1249 D.dot(a_cross_b), next,
ray);
1260 -
D.dot(a_cross_c), next,
ray);
1264 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
1267 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
1276 -C.dot(a_cross_b), next,
ray);
1281 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
1283 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
1285 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
1290 -
D.dot(a_cross_c), next,
ray);
1299 if (C.dot(a_cross_b) <=
1301 assert(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1306 -C.dot(a_cross_b), next,
ray);
1309 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
1314 -
D.dot(a_cross_c), next,
ray);
1320 if (C.dot(a_cross_b) <= 0) {
1321 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
1328 assert(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1333 -C.dot(a_cross_b), next,
ray);
1337 if (-
D.dot(a_cross_b) <= 0) {
1338 if (da * da_ba + dd * ba_aa - db * da_aa <=
1342 D.dot(a_cross_b), next,
ray);
1358 if (-
D.dot(a_cross_b) <= 0) {
1359 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1361 if (da * da_ba + dd * ba_aa - db * da_aa <=
1363 assert(!(ba * da_ba + bd * ba_aa - bb * da_aa <=
1368 D.dot(a_cross_b), next,
ray);
1377 if (
D.dot(a_cross_c) <=
1379 assert(ca * ca_da + cc * da_aa - cd * ca_aa <=
1384 -
D.dot(a_cross_c), next,
ray);
1387 if (C.dot(a_cross_b) <=
1389 assert(!(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
1394 D.dot(a_cross_b), next,
ray);
1399 D.dot(a_cross_b), next,
ray);
1405 if (
D.dot(a_cross_c) <= 0) {
1406 if (da * ca_da + dc * da_aa - dd * ca_aa <=
1413 assert(ca * ca_da + cc * da_aa - cd * ca_aa <=
1418 -
D.dot(a_cross_c), next,
ray);
1436 #undef REGION_INSIDE
1454 Vec3f n_ab = ab.cross(face->
n);
1467 else if (b_dot_ab < 0)
1470 dist = std::sqrt(std::max(
1471 a->w.squaredNorm() - a_dot_ab * a_dot_ab / ab.squaredNorm(), 0.));
1490 face->
n = (
b->w -
a->w).cross(
c->w -
a->w);
1499 face->
d =
a->w.dot(face->
n);
1522 for (
SimplexF* f = minf->
l[1]; f; f = f->
l[1]) {
1535 if ((simplex.
rank > 1) &&
gjk.encloseOrigin()) {
1564 size_t iterations = 0;
1567 bind(tetrahedron[0], 0, tetrahedron[1], 0);
1568 bind(tetrahedron[0], 1, tetrahedron[2], 0);
1569 bind(tetrahedron[0], 2, tetrahedron[3], 0);
1570 bind(tetrahedron[1], 1, tetrahedron[3], 2);
1571 bind(tetrahedron[1], 2, tetrahedron[2], 1);
1572 bind(tetrahedron[2], 2, tetrahedron[3], 1);
1584 best->
pass = ++pass;
1587 gjk.getSupport(best->
n,
true, *w, hint);
1593 for (
size_t j = 0; (j < 3) && valid; ++j)
1594 valid &=
expand(pass, w, best->
f[j], best->
e[j], horizon);
1596 if (!valid || horizon.
nf < 3) {
1602 bind(horizon.
ff, 2, horizon.
cf, 1);
1625 assert(simplex.
rank == 1 && simplex.
vertex[0]->
w.isZero(
gjk.getTolerance()));
1641 static const size_t nexti[] = {1, 2, 0};
1642 static const size_t previ[] = {2, 0, 1};
1644 if (f->
pass == pass) {
1649 const size_t e1 = nexti[e];
1667 bind(nf, 2, horizon.
cf, 1);
1680 const size_t e2 = previ[e];
1682 if (
expand(pass, w, f->
f[e1], f->
e[e1], horizon) &&
1683 expand(pass, w, f->
f[e2], f->
e[e2], horizon)) {
1693 if (!
res)
return false;
1694 details::inflate<false>(shape, w0, w1);