47 #include <gtest/gtest.h>
86 std::vector<ccd_pt_vertex_t*>&
v() {
return v_; }
87 std::vector<ccd_pt_edge_t*>&
e() {
return e_; }
88 std::vector<ccd_pt_face_t*>&
f() {
return f_; }
91 std::vector<ccd_pt_vertex_t*>
v_;
92 std::vector<ccd_pt_edge_t*>
e_;
93 std::vector<ccd_pt_face_t*>
f_;
110 for (
int i = 0; i < 4; ++i) {
112 vertices[i](1), vertices[i](2));
128 ccd_real_t bottom_center_x, ccd_real_t bottom_center_y,
129 ccd_real_t bottom_center_z, ccd_real_t edge_length) {
130 std::array<fcl::Vector3<ccd_real_t>, 4> vertices;
131 auto compute_vertex = [bottom_center_x, bottom_center_y, bottom_center_z,
132 edge_length](ccd_real_t x, ccd_real_t y, ccd_real_t z,
134 *vertex << x * edge_length + bottom_center_x,
135 y * edge_length + bottom_center_y, z * edge_length + bottom_center_z;
137 compute_vertex(0.5, -0.5 / std::sqrt(3), 0, &vertices[0]);
138 compute_vertex(-0.5, -0.5 / std::sqrt(3), 0, &vertices[1]);
139 compute_vertex(0, 1 / std::sqrt(3), 0, &vertices[2]);
140 compute_vertex(0, 0, std::sqrt(2.0 / 3.0), &vertices[3]);
149 vertices[3] = (vertices[0] + vertices[1]) / 2;
159 for (
int i = 0; i < 3; ++i) vertices[i] *= delta;
186 ccd_real_t bottom_center_y = 0,
187 ccd_real_t bottom_center_z = 0,
188 ccd_real_t edge_length = 1)
190 bottom_center_x, bottom_center_y, bottom_center_z, edge_length)) {}
194 for (
int i = 0; i < 4; ++i) {
197 for (
int j = 0; j < 4; ++j) {
198 EXPECT_LE(ccdVec3Dot(&n, &p.
v(j).
v.
v),
242 -0.01 * std::sqrt(6) / 9, 0.01);
246 GTEST_TEST(FCL_GJK_EPA, faceNormalPointingOutwardOriginNearFace1) {
254 const double face0_origin_distance = 0.005;
255 std::array<fcl::Vector3<ccd_real_t>, 4> vertices;
256 vertices[0] << 0.5, -0.5, face0_origin_distance;
257 vertices[1] << 0, 1, face0_origin_distance;
258 vertices[2] << -0.5, -0.5, face0_origin_distance;
259 vertices[3] << 0, 0, -1;
261 Eigen::AngleAxis<ccd_real_t> rotation(0.05 * kPi,
263 for (
int i = 0; i < 4; ++i) {
264 vertices[i] = rotation * vertices[i];
269 ccd_vec3_t f0_e0, f0_e1;
274 ccd_vec3_t f0_e0_cross_e1;
275 ccdVec3Cross(&f0_e0_cross_e1, &f0_e0, &f0_e1);
276 EXPECT_GE(f0_e0_cross_e1.v[2], 0);
281 GTEST_TEST(FCL_GJK_EPA, faceNormalPointingOutwardOriginNearFace2) {
288 const double face0_origin_distance = 0.005;
289 std::array<fcl::Vector3<ccd_real_t>, 4> vertices;
290 vertices[0] << 0.5, -0.5, face0_origin_distance;
291 vertices[1] << 0, 1, face0_origin_distance;
292 vertices[2] << -0.5, -0.5, face0_origin_distance;
293 vertices[3] << 0, 0, -0.001;
311 ".*faceNormalPointingOutward.*zero-area.*");
323 ".*faceNormalPointingOutward.*zero-area.*");
328 auto CheckSupportEPADirection = [](
330 const Eigen::Ref<const Vector3<ccd_real_t>>& dir_expected,
332 const ccd_vec3_t dir =
334 for (
int i = 0; i < 3; ++i) {
345 const ccd_real_t tol = 3E-5;
346 CheckSupportEPADirection(&p1.
polytope(),
353 if (p2.
e(0).
faces[0] == &p2.
f(0)) {
355 CheckSupportEPADirection(&p2.
polytope(),
360 CheckSupportEPADirection(
373 CheckSupportEPADirection(&p4.
polytope(),
379 -std::sqrt(6) / 9 + 0.01);
380 CheckSupportEPADirection(
394 ".+supportEPADirection.+nearest point to the origin is a vertex.+");
400 auto CheckPointOutsidePolytopeFace = [&p](ccd_real_t x, ccd_real_t y,
401 ccd_real_t z,
int face_index,
402 bool is_outside_expected) {
408 &p.
f(face_index), &pt),
409 is_outside_expected);
412 const bool expect_inside =
false;
413 const bool expect_outside =
true;
415 CheckPointOutsidePolytopeFace(0, 0, 0.1, 0, expect_inside);
416 CheckPointOutsidePolytopeFace(0, 0, 0.1, 1, expect_inside);
417 CheckPointOutsidePolytopeFace(0, 0, 0.1, 2, expect_inside);
418 CheckPointOutsidePolytopeFace(0, 0, 0.1, 3, expect_inside);
422 CheckPointOutsidePolytopeFace(0, 0, 2, 0, expect_inside);
423 CheckPointOutsidePolytopeFace(0, 0, 2, 1, expect_outside);
424 CheckPointOutsidePolytopeFace(0, 0, 2, 2, expect_outside);
425 CheckPointOutsidePolytopeFace(0, 0, 2, 3, expect_outside);
428 CheckPointOutsidePolytopeFace(0, 0, 0, 0, expect_inside);
429 CheckPointOutsidePolytopeFace(0, 0, 0, 1, expect_inside);
430 CheckPointOutsidePolytopeFace(0, 0, 0, 2, expect_inside);
431 CheckPointOutsidePolytopeFace(0, 0, 0, 3, expect_inside);
439 ccd_vec3_t pt{{10, 10, 10}};
450 ".*faceNormalPointingOutward.*zero-area.*");
462 ".*faceNormalPointingOutward.*zero-area.*");
499 Hexagram(ccd_real_t bottom_center_x = 0, ccd_real_t bottom_center_y = 0,
500 ccd_real_t bottom_center_z = 0)
505 auto AddHexagramVertex = [bottom_center_x, bottom_center_y, bottom_center_z,
506 this](ccd_real_t x, ccd_real_t y, ccd_real_t z) {
508 y + bottom_center_y, z + bottom_center_z);
511 v()[0] = AddHexagramVertex(0.5, -1 / std::sqrt(3), 1);
513 v()[1] = AddHexagramVertex(0, -2 / std::sqrt(3), 0);
515 v()[2] = AddHexagramVertex(-0.5, -1 / std::sqrt(3), 1);
517 v()[3] = AddHexagramVertex(-0.5, 1 / std::sqrt(3), 0);
519 v()[4] = AddHexagramVertex(0, 2 / std::sqrt(3), 1);
521 v()[5] = AddHexagramVertex(0.5, 1 / std::sqrt(3), 0);
532 for (
int i = 0; i < 6; ++i) {
550 template <
typename T>
552 return S.count(
const_cast<T*
>(element)) > 0;
560 const std::unordered_set<ccd_pt_edge_t*>& border_edges,
561 const std::unordered_set<ccd_pt_face_t*>& visible_faces,
562 const std::unordered_set<ccd_pt_edge_t*>& internal_edges,
563 const std::unordered_set<int>& border_edge_indices_expected,
564 const std::unordered_set<int>& visible_face_indices_expected,
565 const std::unordered_set<int> internal_edges_indices_expected) {
567 EXPECT_EQ(border_edges.size(), border_edge_indices_expected.size());
568 for (
const int edge_index : border_edge_indices_expected) {
572 EXPECT_EQ(visible_faces.size(), visible_face_indices_expected.size());
573 for (
const int face_index : visible_face_indices_expected) {
577 EXPECT_EQ(internal_edges.size(), internal_edges_indices_expected.size());
578 for (
const auto edge_index : internal_edges_indices_expected) {
588 const std::vector<int>& edge_indices,
const ccd_vec3_t& new_vertex,
589 const std::unordered_set<int>& border_edge_indices_expected,
590 const std::unordered_set<int>& visible_face_indices_expected,
591 const std::unordered_set<int>& internal_edges_indices_expected) {
592 std::unordered_set<ccd_pt_edge_t*> border_edges;
593 std::unordered_set<ccd_pt_face_t*> visible_faces;
594 std::unordered_set<ccd_pt_face_t*> hidden_faces;
595 visible_faces.insert(&face);
596 std::unordered_set<ccd_pt_edge_t*> internal_edges;
597 for (
const int edge_index : edge_indices) {
599 polytope.
polytope(), face, edge_index, new_vertex, &border_edges,
600 &visible_faces, &hidden_faces, &internal_edges);
603 internal_edges, border_edge_indices_expected,
604 visible_face_indices_expected,
605 internal_edges_indices_expected);
608 for (
const auto hidden_face : hidden_faces) {
609 EXPECT_EQ(visible_faces.count(hidden_face), 0u);
615 const std::unordered_set<int>& border_edge_indices_expected,
616 const std::unordered_set<int>& visible_face_indices_expected,
617 const std::unordered_set<int>& internal_edges_indices_expected) {
618 std::unordered_set<ccd_pt_edge_t*> border_edges;
619 std::unordered_set<ccd_pt_face_t*> visible_faces;
620 std::unordered_set<ccd_pt_edge_t*> internal_edges;
622 &border_edges, &visible_faces,
626 internal_edges, border_edge_indices_expected,
627 visible_face_indices_expected,
628 internal_edges_indices_expected);
631 GTEST_TEST(FCL_GJK_EPA, ComputeVisiblePatch_TopFaceVisible) {
640 const std::unordered_set<int> empty_set;
662 CheckComputeVisiblePatch(hex, hex.
f(0), p, {6, 7, 8, 9, 10, 11}, {0, 2, 4, 6},
666 GTEST_TEST(FCL_GJK_EPA, ComputeVisiblePatch_TopAndSideFacesVisible) {
673 p.
v[1] = -1 / std::sqrt(3) - 0.1;
688 p.v[1] = -1 / std::sqrt(3) - 0.1;
719 ccd_vec3_t query_point;
720 for (
int i = 0; i < 3; ++i) {
721 query_point.v[i] = (1 + rho) * tet.
v(0).
v.
v.v[i] - rho * tet.
v(1).
v.
v.v[i];
723 std::unordered_set<ccd_pt_edge_t*> border_edges;
724 std::unordered_set<ccd_pt_face_t*> visible_faces;
725 std::unordered_set<ccd_pt_edge_t*> internal_edges;
727 &border_edges, &visible_faces,
731 EXPECT_EQ(border_edges, std::unordered_set<ccd_pt_edge_t*>(
732 {&(tet.
e(1)), &(tet.
e(4)), &(tet.
e(5))}));
734 EXPECT_EQ(visible_faces, std::unordered_set<ccd_pt_face_t*>(
735 {&(tet.
f(0)), &(tet.
f(1)), &(tet.
f(3))}));
737 EXPECT_EQ(internal_edges, std::unordered_set<ccd_pt_edge_t*>(
738 {&(tet.
e(0)), &(tet.
e(2)), &(tet.
e(3))}));
741 GTEST_TEST(FCL_GJK_EPA, ComputeVisiblePatchColinearNewVertex) {
758 std::unordered_set<ccd_pt_edge_t*> border_edges;
759 std::unordered_set<ccd_pt_face_t*> visible_faces;
760 std::unordered_set<ccd_pt_edge_t*> internal_edges;
781 auto set_ideal = [&border_edges, &internal_edges, &visible_faces, &tet]() {
783 std::unordered_set<ccd_pt_edge_t*>{&tet.
e(0), &tet.
e(1), &tet.
e(2)};
785 std::unordered_set<ccd_pt_edge_t*>{&tet.
e(3), &tet.
e(4), &tet.
e(5)};
787 std::unordered_set<ccd_pt_face_t*>{&tet.
f(1), &tet.
f(2), &tet.
f(3)};
792 tet.
polytope(), border_edges, visible_faces, internal_edges));
797 internal_edges.erase(&tet.
e(5));
799 tet.
polytope(), border_edges, visible_faces, internal_edges));
803 visible_faces.erase(&tet.
f(3));
805 tet.
polytope(), border_edges, visible_faces, internal_edges));
809 internal_edges.erase(&tet.
e(5));
810 border_edges.insert(&tet.
e(5));
812 tet.
polytope(), border_edges, visible_faces, internal_edges));
821 return ccdVec3Dist2(&v1->
v.
v, &v2->
v.
v) < tol * tol;
827 const std::unordered_map<ccd_pt_vertex_t*, ccd_pt_vertex_t*>&
830 for (
int i = 0; i < 2; ++i) {
831 auto it = map_v1_to_v2.find(e1->
vertex[i]);
832 if (it == map_v1_to_v2.end()) {
833 throw std::logic_error(
"vertex[" + std::to_string(i) +
834 "] in e1 is not found in map_v1_to_v2");
836 v2_expected[i] = it->second;
838 return (v2_expected[0] == e2->
vertex[0] && v2_expected[1] == e2->
vertex[1]) ||
839 (v2_expected[0] == e2->
vertex[1] && v2_expected[1] == e2->
vertex[0]);
846 const std::unordered_map<ccd_pt_edge_t*, ccd_pt_edge_t*>& map_e1_to_e2) {
847 std::unordered_set<ccd_pt_edge_t*> e2_expected;
848 for (
int i = 0; i < 3; ++i) {
849 auto it = map_e1_to_e2.find(f1->
edge[i]);
850 if (it == map_e1_to_e2.end()) {
851 throw std::logic_error(
"edge[" + std::to_string(i) +
852 "] in f1 is not found in map_e1_to_e2");
854 e2_expected.insert(it->second);
858 for (
int i = 0; i < 3; ++i) {
859 auto it = e2_expected.find(f2->
edge[i]);
860 if (it == e2_expected.end()) {
879 template <
typename T>
882 std::function<
bool(
const T*,
const T*)> cmp_feature,
883 std::unordered_set<T*>* feature1, std::unordered_set<T*>* feature2,
884 std::unordered_map<T*, T*>* map_feature1_to_feature2) {
887 map_feature1_to_feature2->clear();
890 auto it = feature1->find(f);
891 assert(it == feature1->end());
892 feature1->emplace_hint(it, f);
895 auto it = feature2->find(f);
896 assert(it == feature2->end());
897 feature2->emplace_hint(it, f);
899 EXPECT_EQ(feature1->size(), feature2->size());
900 for (
const auto& f1 : *feature1) {
901 bool found_match =
false;
902 for (
const auto& f2 : *feature2) {
903 if (cmp_feature(f1, f2)) {
905 map_feature1_to_feature2->emplace_hint(
906 map_feature1_to_feature2->end(), f1, f2);
909 GTEST_FAIL() <<
"There should be only one element in feature2_list "
910 "that matches with an element in feature1_list.";
918 EXPECT_EQ(map_feature1_to_feature2->size(), feature1->size());
925 std::unordered_set<ccd_pt_vertex_t *> v1_set, v2_set;
926 std::unordered_map<ccd_pt_vertex_t*, ccd_pt_vertex_t*> map_v1_to_v2;
927 MapFeature1ToFeature2<ccd_pt_vertex_t>(
930 return VertexPositionCoincide(v1, v2, tol);
932 &v1_set, &v2_set, &map_v1_to_v2);
935 std::unordered_set<ccd_pt_edge_t *> e1_set, e2_set;
936 std::unordered_map<ccd_pt_edge_t*, ccd_pt_edge_t*> map_e1_to_e2;
937 MapFeature1ToFeature2<ccd_pt_edge_t>(
940 return EdgeMatch(e1, e2, map_v1_to_v2);
942 &e1_set, &e2_set, &map_e1_to_e2);
945 std::unordered_set<ccd_pt_face_t *> f1_set, f2_set;
946 std::unordered_map<ccd_pt_face_t*, ccd_pt_face_t*> map_f1_to_f2;
947 MapFeature1ToFeature2<ccd_pt_face_t>(
950 return TriangleMatch(f1, f2, map_e1_to_e2);
952 &f1_set, &f2_set, &map_f1_to_f2);
982 for (
const auto& e1 : e1_set) {
983 auto e2 = map_e1_to_e2[e1];
985 for (
int i = 0; i < 2; ++i) {
986 f2_expected[i] = map_f1_to_f2[e1->
faces[i]];
989 (f2_expected[0] == e2->
faces[0] && f2_expected[1] == e2->
faces[1]) ||
990 (f2_expected[0] == e2->
faces[1] && f2_expected[1] == e2->
faces[0]));
1021 for (
int i = 0; i < 3; ++i) {
1023 ccdPtAddEdge(&polytope_expected, new_vertex, &tetrahedron.
v(i));
1026 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(0), new_edges[0],
1028 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(1), new_edges[1],
1030 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(2), new_edges[2],
1037 GTEST_TEST(FCL_GJK_EPA, expandPolytope_tetrahedron_2visible_faces) {
1046 newv.
v.v[1] = -0.5 / std::sqrt(3) - 0.1;
1065 &polytope_expected, newv.
v.v[0], newv.
v.v[1], newv.
v.v[2]);
1069 ccdPtAddEdge(&polytope_expected, new_vertex, &tetrahedron.
v(0));
1071 ccdPtAddEdge(&polytope_expected, new_vertex, &tetrahedron.
v(1));
1073 ccdPtAddEdge(&polytope_expected, new_vertex, &tetrahedron.
v(2));
1075 ccdPtAddEdge(&polytope_expected, new_vertex, &tetrahedron.
v(3));
1077 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(3), new_edges[0],
1079 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(2), new_edges[0],
1081 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(4), new_edges[1],
1083 ccdPtAddFace(&polytope_expected, &tetrahedron.
e(1), new_edges[1],
1106 Hexagram hex_duplicate(0, 0, -0.9);
1113 &polytope_expected, newv.
v.v[0], newv.
v.v[1], newv.
v.v[2]);
1117 ccdPtAddEdge(&polytope_expected, new_vertex, &hex_duplicate.
v(0));
1119 ccdPtAddEdge(&polytope_expected, new_vertex, &hex_duplicate.
v(2));
1121 ccdPtAddEdge(&polytope_expected, new_vertex, &hex_duplicate.
v(4));
1123 ccdPtAddFace(&polytope_expected, new_edges[0], new_edges[1],
1124 &hex_duplicate.
e(0));
1125 ccdPtAddFace(&polytope_expected, new_edges[1], new_edges[2],
1126 &hex_duplicate.
e(1));
1127 ccdPtAddFace(&polytope_expected, new_edges[2], new_edges[0],
1128 &hex_duplicate.
e(2));
1134 GTEST_TEST(FCL_GJK_EPA, expandPolytope_hexagram_4_visible_faces) {
1152 Hexagram hex_duplicate(0, 0, -0.9);
1168 &polytope_expected, newv.
v.v[0], newv.
v.v[1], newv.
v.v[2]);
1171 for (
int i = 0; i < 6; ++i) {
1173 ccdPtAddEdge(&polytope_expected, new_vertex, &hex_duplicate.
v(i));
1176 for (
int i = 0; i < 6; ++i) {
1177 ccdPtAddFace(&polytope_expected, new_edges[i % 6], new_edges[(i + 1) % 6],
1178 &hex_duplicate.
e(i + 6));
1193 ".*expandPolytope.*The visible feature is a vertex.*");
1197 ccdVec3Copy(&nearest, &tet.
v(0).
v.
v);
1198 ccdVec3Add(&nearest, &tet.
v(1).
v.
v);
1199 ccdVec3Scale(&nearest, 0.5);
1205 ".*expandPolytope.* nearest point and the new vertex are on an edge.*");
1210 for (
int i = 0; i < 3; ++i) {
1220 tetrahedron.
v(0).
v.
v1.v[0] = 1;
1221 tetrahedron.
v(0).
v.
v1.v[1] = 2;
1222 tetrahedron.
v(0).
v.
v1.v[2] = 3;
1223 for (
int i = 0; i < 3; ++i) {
1224 tetrahedron.
v(0).
v.
v2.v[i] = tetrahedron.
v(0).
v.
v1.v[i];
1229 reinterpret_cast<const ccd_pt_el_t*
>(&tetrahedron.
v(0)), &p1, &p2),
1241 ccdVec3Set(&tetrahedron.
v(1).
v.
v1, 1, 2, 3);
1242 ccdVec3Set(&tetrahedron.
v(2).
v.
v1, 4, 5, 6);
1243 for (
int i = 1; i <= 2; ++i) {
1244 for (
int j = 0; j < 3; ++j) {
1245 tetrahedron.
v(i).
v.
v2.v[j] =
1246 tetrahedron.
v(i).
v.
v1.v[j] - tetrahedron.
v(i).
v.
v.v[j];
1255 reinterpret_cast<const ccd_pt_el_t*
>(&tetrahedron.
e(1)), &p1, &p2),
1257 ccd_vec3_t p1_expected, p2_expected;
1258 ccdVec3Copy(&p1_expected, &tetrahedron.
v(1).
v.
v1);
1259 ccdVec3Add(&p1_expected, &tetrahedron.
v(2).
v.
v1);
1260 ccdVec3Scale(&p1_expected, ccd_real_t(0.5));
1261 ccdVec3Copy(&p2_expected, &tetrahedron.
v(1).
v.
v2);
1262 ccdVec3Add(&p2_expected, &tetrahedron.
v(2).
v.
v2);
1263 ccdVec3Scale(&p2_expected, ccd_real_t(0.5));
1276 bottom_center_pos(2));
1279 tetrahedron.
v(0).
v.
v1.v[0] = 1;
1280 tetrahedron.
v(0).
v.
v1.v[1] = 2;
1281 tetrahedron.
v(0).
v.
v1.v[2] = 3;
1282 tetrahedron.
v(1).
v.
v1.v[0] = 4;
1283 tetrahedron.
v(1).
v.
v1.v[1] = 5;
1284 tetrahedron.
v(1).
v.
v1.v[2] = 6;
1285 tetrahedron.
v(3).
v.
v1.v[0] = 7;
1286 tetrahedron.
v(3).
v.
v1.v[1] = 8;
1287 tetrahedron.
v(3).
v.
v1.v[2] = 9;
1288 for (
int i : {0, 1, 3}) {
1289 for (
int j = 0; j < 3; ++j) {
1290 tetrahedron.
v(i).
v.
v2.v[j] =
1291 tetrahedron.
v(i).
v.
v1.v[j] - tetrahedron.
v(i).
v.
v.v[j];
1298 reinterpret_cast<const ccd_pt_el_t*
>(&tetrahedron.
f(1)), &p1, &p2),
1304 ccd_vec3_t p1_expected, p2_expected;
1305 ccdVec3Copy(&p1_expected, &tetrahedron.
v(0).
v.
v1);
1306 ccdVec3Add(&p1_expected, &tetrahedron.
v(1).
v.
v1);
1307 ccdVec3Add(&p1_expected, &tetrahedron.
v(3).
v.
v1);
1308 ccdVec3Scale(&p1_expected, ccd_real_t(1.0 / 3));
1309 ccdVec3Copy(&p2_expected, &tetrahedron.
v(0).
v.
v2);
1310 ccdVec3Add(&p2_expected, &tetrahedron.
v(1).
v.
v2);
1311 ccdVec3Add(&p2_expected, &tetrahedron.
v(3).
v.
v2);
1312 ccdVec3Scale(&p2_expected, ccd_real_t(1.0 / 3));
1335 template <
typename S>
1341 X_FB1->setIdentity();
1342 X_FB1->translation() << 0, 0, 1;
1343 X_FB2->setIdentity();
1344 X_FB2->translation() << -0.6, 0, 1;
1357 ccd->max_iterations = 1000;
1358 ccd->dist_tolerance = 1E-6;
1361 template <
typename S>
1363 return (
Vector3<S>() << v.v[0], v.v[1], v.v[2]).finished();
1366 template <
typename S>
1375 template <
typename S>
1393 pts[0].
v = ToCcdVec3<S>(p_FPa1 - p_FPa2);
1394 pts[0].
v1 = ToCcdVec3<S>(p_FPa1);
1395 pts[0].
v2 = ToCcdVec3<S>(p_FPa2);
1399 pts[1].
v = ToCcdVec3<S>(p_FPb1 - p_FPb2);
1400 pts[1].
v1 = ToCcdVec3<S>(p_FPb1);
1401 pts[1].
v2 = ToCcdVec3<S>(p_FPb2);
1405 pts[2].
v = ToCcdVec3<S>(p_FPc1 - p_FPc2);
1406 pts[2].
v1 = ToCcdVec3<S>(p_FPc1);
1407 pts[2].
v2 = ToCcdVec3<S>(p_FPc2);
1408 for (
int i = 0; i < 3; ++i) {
1412 const Vector3<S> a = ToEigenVector<S>(pts[0].v);
1413 const Vector3<S> b = ToEigenVector<S>(pts[1].v);
1414 const Vector3<S> c = ToEigenVector<S>(pts[2].v);
1426 EXPECT_GE(a.cross(b).dot(b.cross(c)), 0);
1427 EXPECT_GE(b.cross(c).dot(c.cross(a)), 0);
1428 EXPECT_GE(c.cross(a).dot(a.cross(b)), 0);
1434 &polytope, &nearest);
1443 std::unordered_set<ccd_pt_vertex_t*> polytope_vertices;
1447 const auto it = polytope_vertices.find(v);
1449 polytope_vertices.emplace_hint(it, v);
1452 EXPECT_EQ(polytope_vertices.size(), 4u);
1457 int num_matched_vertices = 0;
1458 for (
const auto& v : polytope_vertices) {
1459 bool found_match =
false;
1460 for (
int i = 0; i < 3; ++i) {
1462 num_matched_vertices++;
1468 non_simplex_vertex = v;
1472 EXPECT_NE(non_simplex_vertex,
nullptr);
1478 ab = ToEigenVector<S>(pts[1].v) - ToEigenVector<S>(pts[0].v);
1479 ac = ToEigenVector<S>(pts[2].v) - ToEigenVector<S>(pts[0].v);
1480 dir1 = ab.cross(ac);
1487 Eigen::Matrix<S, 3, 8> p_B1V1, p_B2V2;
1488 p_B1V1 << -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1,
1490 p_B2V2 << -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1,
1492 for (
int i = 0; i < 3; ++i) {
1493 p_B1V1.row(i) *= box1_size[i] / 2;
1494 p_B2V2.row(i) *= box2_size[i] / 2;
1497 const Eigen::Matrix<S, 3, 8> p_FV1 = X_FB1 * p_B1V1;
1498 const Eigen::Matrix<S, 3, 8> p_FV2 = X_FB2 * p_B2V2;
1500 const S max_support1 = (dir1.transpose() * p_FV1).maxCoeff() -
1501 (dir1.transpose() * p_FV2).minCoeff();
1503 const S max_support2 = (dir2.transpose() * p_FV1).maxCoeff() -
1504 (dir2.transpose() * p_FV2).minCoeff();
1506 const double expected_max_support =
std::max(max_support1, max_support2);
1507 const double non_simplex_vertex_support1 =
1508 ToEigenVector<S>(non_simplex_vertex->v.v).dot(dir1);
1509 const double non_simplex_vertex_support2 =
1510 ToEigenVector<S>(non_simplex_vertex->v.v).dot(dir2);
1512 std::max(non_simplex_vertex_support1, non_simplex_vertex_support2),
1520 (X_WF * X_FB1).inverse() * ToEigenVector<S>(non_simplex_vertex->v.v1);
1522 (X_WF * X_FB2).inverse() * ToEigenVector<S>(non_simplex_vertex->v.v2);
1524 for (
int i = 0; i < 3; ++i) {
1539 for (
const auto& v : polytope_vertices) {
1540 vertices_expected[v_count++] =
ccdPtAddVertex(&polytope_expected, &v->v);
1543 edges_expected[0] =
ccdPtAddEdge(&polytope_expected, vertices_expected[0],
1544 vertices_expected[1]);
1545 edges_expected[1] =
ccdPtAddEdge(&polytope_expected, vertices_expected[1],
1546 vertices_expected[2]);
1547 edges_expected[2] =
ccdPtAddEdge(&polytope_expected, vertices_expected[2],
1548 vertices_expected[0]);
1549 edges_expected[3] =
ccdPtAddEdge(&polytope_expected, vertices_expected[3],
1550 vertices_expected[0]);
1551 edges_expected[4] =
ccdPtAddEdge(&polytope_expected, vertices_expected[3],
1552 vertices_expected[1]);
1553 edges_expected[5] =
ccdPtAddEdge(&polytope_expected, vertices_expected[3],
1554 vertices_expected[2]);
1556 ccdPtAddFace(&polytope_expected, edges_expected[0], edges_expected[3],
1558 ccdPtAddFace(&polytope_expected, edges_expected[1], edges_expected[4],
1560 ccdPtAddFace(&polytope_expected, edges_expected[2], edges_expected[3],
1562 ccdPtAddFace(&polytope_expected, edges_expected[0], edges_expected[1],
1571 template <
typename S>
1577 X_WF.translation() << 0, 0, 1;
1580 X_WF.translation() << -0.2, 0.4, 0.1;
1585 TestSimplexToPolytope3<double>();
1586 TestSimplexToPolytope3<float>();
1594 ::testing::InitGoogleTest(&argc, argv);
1595 return RUN_ALL_TESTS();