Guest User

marchinng_tets_hash_opimized

a guest
Mar 13th, 2018
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.11 KB | None | 0 0
  1. template <typename DerivedTV,
  2.           typename DerivedTT,
  3.           typename Derivedisovalues,
  4.           typename DerivedoutV,
  5.           typename DerivedoutF>
  6. void igl::marching_tets_3(
  7.     const Eigen::PlainObjectBase<DerivedTV>& TV,
  8.     const Eigen::PlainObjectBase<DerivedTT>& TT,
  9.     const Eigen::PlainObjectBase<Derivedisovalues>& isovals,
  10.     double isovalue,
  11.     Eigen::PlainObjectBase<DerivedoutV>& outV,
  12.     Eigen::PlainObjectBase<DerivedoutF>& outF) {
  13.   using namespace std;
  14.  
  15.   const auto make_edge_key = [](const std::pair<std::int32_t, std::int32_t>& p) -> std::int64_t {
  16.     static_assert(sizeof(std::int64_t) == 2*sizeof(std::int32_t), "need to fit 2 ints into a size_t");
  17.     std::int64_t ret = 0;
  18.     ret |= p.first;
  19.     ret |= static_cast<std::int64_t>(p.second) << 32;
  20.     return ret;
  21.   };
  22.  
  23.   const int mt_cell_lookup[16][4] = {
  24.     { -1, -1, -1, -1 }, // 0000 0a
  25.     {  0,  2,  1, -1 }, // 0001 1a
  26.     {  0,  3,  4, -1 }, // 0010 1b
  27.     {  2,  1,  3,  4 }, // 0011 2b
  28.     {  5,  3,  1, -1 }, // 0100 1d
  29.     {  0,  2,  5,  3 }, // 0101 2a
  30.     {  0,  1,  5,  4 }, // 0110 2d
  31.     {  2,  5,  4, -1 }, // 0111 3a
  32.     {  4,  5,  2, -1 }, // 1000 1c
  33.     {  0,  4,  5,  1 }, // 1001 2c
  34.     {  0,  3,  5,  2 }, // 1010 2f
  35.     {  1,  3,  5, -1 }, // 1011 3d
  36.     {  4,  3,  1,  2 }, // 1100 2e
  37.     {  0,  4,  3, -1 }, // 1101 3c
  38.     {  0,  1,  2, -1 }, // 1110 3b
  39.     { -1, -1, -1, -1 }, // 1111 0b
  40.   };
  41.  
  42.   const int mt_edge_lookup[6][2] = {
  43.     {0, 1},
  44.     {0, 2},
  45.     {0, 3},
  46.     {1, 2},
  47.     {1, 3},
  48.     {2, 3},
  49.   };
  50.  
  51. //  vector<Eigen::RowVector3d> vertices;
  52.   vector<Eigen::RowVector3i> faces;
  53.   vector<pair<int, int>> edge_table;
  54.  
  55.  
  56.   assert(TT.cols() == 4 && TT.rows() >= 1);
  57.   assert(TV.cols() == 3 && TV.rows() >= 4);
  58.   assert(isovals.cols() == 1);
  59.  
  60.   static_assert(sizeof(std::int64_t) == 2*sizeof(std::int32_t), "need to fit 2 ints into a size_t");
  61.  
  62.   // For each tet
  63.   for (int i = 0; i < TT.rows(); i++) {
  64.     uint8_t key = 0;
  65.     for (int v = 0; v < 4; v++) {
  66.       int vid = TT(i, v);
  67.       uint8_t flag = isovals[vid] > isovalue;
  68.       key |= flag << v;
  69.     }
  70.  
  71.     // Insert the vertices if they don't exist
  72.     int v_ids[4] = {-1, -1, -1, -1}; // This will contain the index in TV of each vertex in the tet
  73.     for (int e = 0; e < 4 && mt_cell_lookup[key][e] != -1; e++) {
  74.       const int v1id = mt_edge_lookup[mt_cell_lookup[key][e]][0];
  75.       const int v2id = mt_edge_lookup[mt_cell_lookup[key][e]][1];
  76.       const int v1i = TT(i, v1id), v2i = TT(i, v2id);
  77.       const int vertex_id = edge_table.size();
  78.       edge_table.push_back(make_pair(min(v1i, v2i), max(v1i, v2i)));
  79.       v_ids[e] = vertex_id;
  80.     }
  81.  
  82.     if (v_ids[0] != -1) {
  83.       bool is_quad = mt_cell_lookup[key][3] != -1;
  84.       if (is_quad) {
  85.         Eigen::RowVector3i f1(v_ids[0], v_ids[1], v_ids[3]);
  86.         Eigen::RowVector3i f2(v_ids[1], v_ids[2], v_ids[3]);
  87.         faces.push_back(f1);
  88.         faces.push_back(f2);
  89.       } else {
  90.         Eigen::RowVector3i f(v_ids[0], v_ids[1], v_ids[2]);
  91.         faces.push_back(f);
  92.       }
  93.     }
  94.   }
  95.  
  96.   // Deduplicate vertices
  97.   int num_unique = 0;
  98.   outV.resize(edge_table.size(), 3);
  99.   outF.resize(faces.size(), 3);
  100.   unordered_map<int64_t, int> emap;
  101.   emap.max_load_factor(0.5);
  102.   emap.reserve(edge_table.size());
  103.  
  104.   for (int i = 0; i < faces.size(); i++) {
  105.     for (int v = 0; v < 3; v++) {
  106.       const int vi = faces[i][v];
  107.       const pair<int32_t, int32_t> edge = edge_table[vi];
  108.       const int64_t key = make_edge_key(edge);
  109.       auto it = emap.find(key);
  110.       if (it == emap.end()) { // New unique vertex, insert it
  111.         const Eigen::RowVector3d v1 = TV.row(edge.first);
  112.         const Eigen::RowVector3d v2 = TV.row(edge.second);
  113.         const double a = fabs(isovals[edge.first] - isovalue), b = fabs(isovals[edge.second] - isovalue);
  114.         const double w = a / (a+b);
  115.  
  116.         outV.row(num_unique) = (1-w)*v1 + w*v2;
  117.         outF(i, v) = num_unique;
  118.         emap.insert(make_pair(key, num_unique));
  119.         num_unique += 1;
  120.       } else {
  121.         outF(i, v) = it->second;
  122.       }
  123.     }
  124.   }
  125.   outV.conservativeResize(num_unique, 3);
  126. }
Advertisement
Add Comment
Please, Sign In to add comment