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();