61 COAL_ASSERT(tolerance_ > 0,
"Tolerance must be positive.",
62 std::invalid_argument);
97 assert(vs[i]->w.isApprox(vs[i]->
w0 - vs[i]->
w1));
100 Project::ProjectResult projection;
101 switch (simplex.
rank) {
107 const Vec3s &
a = vs[0]->
w, a0 = vs[0]->
w0, a1 = vs[0]->
w1,
b = vs[1]->
w,
108 b0 = vs[1]->
w0, b1 = vs[1]->
w1;
117 lb = N.squaredNorm();
125 w0 = la * a0 + lb * b0;
126 w1 = la * a1 + lb * b1;
133 projection = Project::projectTriangleOrigin(vs[0]->w, vs[1]->w, vs[2]->w);
136 projection = Project::projectTetrahedraOrigin(vs[0]->w, vs[1]->w,
146 w0 += projection.parameterization[i] * vs[i]->
w0;
147 w1 += projection.parameterization[i] * vs[i]->
w1;
157 template <
bool Separated>
162 Eigen::NumTraits<CoalScalar>::dummy_precision();
163 assert((normal.norm() - 1) < dummy_precision);
167 Eigen::Array<bool, 1, 2>
inflate(I > 0);
170 if (
inflate[0]) w0 += I[0] * normal;
171 if (
inflate[1]) w1 -= I[1] * normal;
179 if ((w1 - w0).norm() > Eigen::NumTraits<CoalScalar>::dummy_precision()) {
180 normal = (w1 - w0).normalized();
182 normal = -this->
ray.normalized();
184 details::inflate<true>(
shape, normal, w0, w1);
245 switch (current_gjk_variant) {
253 if (normalize_support_direction) {
256 y = momentum *
ray + (1 - momentum) * w;
263 dir = momentum * dir / dir.norm() + (1 - momentum) *
y / y_norm;
267 y = momentum *
ray + (1 - momentum) * w;
268 dir = momentum * dir + (1 - momentum) *
y;
274 dir = momentum * dir + (1 - momentum) *
ray;
290 if (omega > upper_bound) {
291 distance = omega - swept_sphere_radius;
299 if (frank_wolfe_duality_gap -
tolerance <= 0) {
320 distance = rl - swept_sphere_radius;
332 switch (curr_simplex.
rank) {
337 next_simplex.
rank = 1;
355 if (inside || rl == 0) {
383 alpha = std::max(alpha, omega);
407 alpha = std::max(alpha, omega);
409 const CoalScalar diff = rl * rl - alpha * alpha;
443 for (
int i = 0; i < 3; ++i) {
457 for (
int i = 0; i < 3; ++i) {
475 if (!
axis.isZero()) {
508 ray = AB.dot(
B) *
A + ABdotAO *
B;
515 ray /= AB.squaredNorm();
540 ray = -ABCdotAO / ABC.squaredNorm() * ABC;
552 assert(
d <= AB.squaredNorm());
578 const Vec3s AB =
B -
A, AC = C -
A, ABC = AB.cross(AC);
640 const Vec3s a_cross_b =
A.cross(
B);
641 const Vec3s a_cross_c =
A.cross(C);
647 #define REGION_INSIDE() \
649 next.vertex[0] = current.vertex[d]; \
650 next.vertex[1] = current.vertex[c]; \
651 next.vertex[2] = current.vertex[b]; \
652 next.vertex[3] = current.vertex[a]; \
658 if (-
D.dot(a_cross_b) <= 0) {
659 if (ba * da_ba + bd * ba_aa - bb * da_aa <=
662 assert(da * da_ba + dd * ba_aa - db * da_aa <=
664 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
668 -C.dot(a_cross_b), next,
ray);
677 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
679 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
681 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
685 -
D.dot(a_cross_c), next,
ray);
696 -C.dot(a_cross_b), next,
ray);
707 if (da * da_ba + dd * ba_aa - db * da_aa <=
711 D.dot(a_cross_b), next,
ray);
714 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
716 if (da * ca_da + dc * da_aa - dd * ca_aa <=
725 -
D.dot(a_cross_c), next,
ray);
729 if (da * ca_da + dc * da_aa - dd * ca_aa <=
745 if (C.dot(a_cross_b) <= 0) {
746 if (ba * ba_ca + bb * ca_aa - bc * ba_aa <=
748 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
750 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
754 -
D.dot(a_cross_c), next,
ray);
765 -C.dot(a_cross_b), next,
ray);
775 if (
D.dot(a_cross_c) <= 0) {
776 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
778 if (da * ca_da + dc * da_aa - dd * ca_aa <=
787 -
D.dot(a_cross_c), next,
ray);
811 if (
D.dot(a_cross_c) <= 0) {
813 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
815 if (da * ca_da + dc * da_aa - dd * ca_aa <=
817 if (da * da_ba + dd * ba_aa - db * da_aa <=
821 D.dot(a_cross_b), next,
ray);
832 -
D.dot(a_cross_c), next,
ray);
836 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
839 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
848 -C.dot(a_cross_b), next,
ray);
853 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
855 if (ca * ca_da + cc * da_aa - cd * ca_aa <=
857 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
862 -
D.dot(a_cross_c), next,
ray);
871 if (C.dot(a_cross_b) <=
873 assert(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
878 -C.dot(a_cross_b), next,
ray);
881 assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=
886 -
D.dot(a_cross_c), next,
ray);
892 if (C.dot(a_cross_b) <= 0) {
893 if (ca * ba_ca + cb * ca_aa - cc * ba_aa <=
900 assert(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
905 -C.dot(a_cross_b), next,
ray);
909 if (-
D.dot(a_cross_b) <= 0) {
910 if (da * da_ba + dd * ba_aa - db * da_aa <=
914 D.dot(a_cross_b), next,
ray);
930 if (-
D.dot(a_cross_b) <= 0) {
931 if (da * ca_da + dc * da_aa - dd * ca_aa <=
933 if (da * da_ba + dd * ba_aa - db * da_aa <=
935 assert(!(ba * da_ba + bd * ba_aa - bb * da_aa <=
940 D.dot(a_cross_b), next,
ray);
949 if (
D.dot(a_cross_c) <=
951 assert(ca * ca_da + cc * da_aa - cd * ca_aa <=
956 -
D.dot(a_cross_c), next,
ray);
959 if (C.dot(a_cross_b) <=
961 assert(!(ba * ba_ca + bb * ca_aa - bc * ba_aa <=
966 D.dot(a_cross_b), next,
ray);
971 D.dot(a_cross_b), next,
ray);
977 if (
D.dot(a_cross_c) <= 0) {
978 if (da * ca_da + dc * da_aa - dd * ca_aa <=
985 assert(ca * ca_da + cc * da_aa - cd * ca_aa <=
990 -
D.dot(a_cross_c), next,
ray);
1009 #undef REGION_INSIDE
1035 for (
size_t i = 0; i <
fc_store.size(); ++i)
1043 Vec3s n_ab = ab.cross(face->
n);
1056 else if (b_dot_ab < 0)
1059 dist = std::sqrt(std::max(
1060 a.w.squaredNorm() - a_dot_ab * a_dot_ab / ab.squaredNorm(), 0.));
1082 face->
n = (
b.w -
a.w).cross(
c.w -
a.w);
1085 face->
n.normalize();
1096 face->
d =
a.w.dot(face->
n);
1101 face->
d = std::numeric_limits<CoalScalar>::max();
1144 CoalScalar mind = std::numeric_limits<CoalScalar>::max();
1146 if (f->ignore)
continue;
1153 assert(minf && !(minf->
ignore) &&
"EPA: minf should not be flagged ignored.");
1163 bool enclosed_origin =
gjk.encloseOrigin();
1164 if ((simplex.
rank > 1) && enclosed_origin) {
1165 assert(simplex.
rank == 4 &&
1166 "When starting EPA, simplex should be of rank 4.");
1188 for (
size_t i = 0; i < 4; ++i) {
1199 bind(tetrahedron[0], 0, tetrahedron[1], 0);
1200 bind(tetrahedron[0], 1, tetrahedron[2], 0);
1201 bind(tetrahedron[0], 2, tetrahedron[3], 0);
1202 bind(tetrahedron[1], 1, tetrahedron[3], 2);
1203 bind(tetrahedron[1], 2, tetrahedron[2], 1);
1204 bind(tetrahedron[2], 2, tetrahedron[3], 1);
1239 "The support is not in the right direction.");
1271 for (
size_t j = 0; (j < 3) && valid; ++j)
1290 depth = outer.
d +
gjk.shape->swept_sphere_radius.sum();
1297 assert(
false &&
"The tetrahedron with which EPA started is degenerated.");
1306 assert(simplex.
rank == 1 && simplex.
vertex[0]->
w.isZero(
gjk.getTolerance()));
1364 static const size_t nexti[] = {1, 2, 0};
1365 static const size_t previ[] = {2, 0, 1};
1370 if (f->
pass == pass) {
1374 assert(f !=
closest_face &&
"EPA is looping indefinitely.");
1379 const size_t e1 = nexti[e];
1414 if (f->
n.dot(w.
w - vf.
w) < dummy_precision) {
1417 if (new_face !=
nullptr) {
1419 bind(new_face, 0, f, e);
1441 const size_t e2 = previ[e];
1455 if ((w0 - w1).norm() > Eigen::NumTraits<CoalScalar>::dummy_precision()) {
1456 if (this->
depth >= 0) {
1458 normal = (w0 - w1).normalized();
1461 normal = (w1 - w0).normalized();
1466 details::inflate<false>(shape,
normal, w0, w1);
1480 Vec3s axiis(0, 0, 0);
1482 int support_hint = 0;
1483 for (
int i = 0; i < 3; ++i) {
1487 coal::details::getShapeSupport<false>(
this, axiis, support, support_hint,
1496 coal::details::getShapeSupport<false>(
this, axiis, support, support_hint,
1505 std::array<Vec3s, 4> eis = {
Vec3s(1, 1, 1),
1510 for (
size_t ei_index = 0; ei_index < 4; ++ei_index) {
1513 coal::details::getShapeSupport<false>(
this, eis[ei_index], support,
1514 support_hint, support_data);
1521 coal::details::getShapeSupport<false>(
this, -eis[ei_index], support,
1522 support_hint, support_data);
1530 this->support_warm_starts.indices.size() !=
1533 std::runtime_error);