Wildmeshing Toolkit
cdt_lib.cpp
Go to the documentation of this file.
1 #include "cdt_lib.hpp"
2 
3 #include <CDT/PLC.h>
4 #include <CDT/delaunay.h>
5 #include <CDT/inputPLC.h>
6 #include <map>
7 
8 namespace cdt_lib {
9 
11  const std::vector<double>& V,
12  const uint32_t npts,
13  const std::vector<uint32_t>& F,
14  const uint32_t ntri,
15  cdt::inputPLC& plc)
16 {
17  plc.initFromVectors(
18  const_cast<double*>(V.data()),
19  npts,
20  const_cast<uint32_t*>(F.data()),
21  ntri,
22  true);
23 }
24 
25 cdt::TetMesh* createSteinerCDT(cdt::inputPLC& plc, bool bbox, bool snap)
26 {
27  if (bbox) {
28  plc.addBoundingBoxVertices();
29  }
30 
31  cdt::TetMesh* tin = new cdt::TetMesh;
32  tin->init_vertices(plc.coordinates.data(), plc.numVertices());
33  tin->tetrahedrize();
34 
35  // copied from cdt/main.cpp
36  // Build a structured PLC linked to the Delaunay tetrahedrization
37  cdt::PLCx Steiner_plc(*tin, plc.triangle_vertices.data(), plc.numTriangles());
38 
39  // Recover segments by inserting Steiner points in both the PLC and the
40  // tetrahedrization
41  Steiner_plc.segmentRecovery_HSi(true);
42 
43  // Recover PLC faces by locally remeshing the tetrahedrization
44  bool sisMethodWorks = Steiner_plc.faceRecovery(true);
45 
46  // Mark the tets which are bounded by the PLC.
47  // If the PLC is not a valid polyhedron (i.e. it has odd-valency edges)
48  // all the tets but the ghosts are marked as "internal".
49  uint32_t num_inner_tets = (uint32_t)Steiner_plc.markInnerTets();
50 
51  return tin;
52 }
53 
55  cdt::TetMesh& tin,
56  std::vector<std::array<bool, 4>>& local_f_on_input,
57  std::vector<std::array<int64_t, 4>>& T_final,
58  std::vector<std::array<std::string, 3>>& V_final,
59  bool inner_only)
60 {
61  std::vector<std::array<int64_t, 4>> T;
62  std::vector<std::array<std::string, 3>> V;
63 
64  uint32_t ngnt = 0;
65  for (uint32_t i = 0; i < tin.numTets(); ++i) {
66  if (tin.mark_tetrahedra[i] == 2) {
67  ngnt++;
68  }
69  }
70 
71  for (uint32_t i = 0; i < tin.numVertices(); ++i) {
72  cdt::bigrational c[3];
73  tin.vertices[i]->getExactXYZCoordinates(c[0], c[1], c[2]);
74 
75  std::array<std::string, 3> v;
76 
77 #ifdef USE_GNU_GMP_CLASSES // TODO
78  v[0].init(c[0].get_mpq_t());
79  v[1].init(c[1].get_mpq_t());
80  v[2].init(c[2].get_mpq_t());
81 #else
82  v[0] = c[0].get_str();
83  v[1] = c[1].get_str();
84  v[2] = c[2].get_str();
85 #endif
86  V.push_back(v);
87  }
88 
89  int64_t row = 0;
90  for (uint32_t i = 0; i < tin.numTets(); ++i) {
91  if (tin.mark_tetrahedra[i] == 2) {
92  T.push_back(
93  {{tin.tet_node[i * 4],
94  tin.tet_node[i * 4 + 1],
95  tin.tet_node[i * 4 + 2],
96  tin.tet_node[i * 4 + 3]}});
97 
98  // mark surfaces
99  // assuming opposite face to node
100  std::array<bool, 4> on_input = {{false, false, false, false}};
101  for (uint64_t j = i; j < i + 4; ++j) {
102  if (tin.mark_tetrahedra[tin.tet_neigh[j] >> 2] != tin.mark_tetrahedra[j >> 2]) {
103  on_input[j - i] = true;
104  }
105  }
106 
107  local_f_on_input.push_back(on_input);
108 
109  row++;
110  }
111  }
112 
113  if (!inner_only) {
114  for (uint32_t i = 0; i < tin.numTets(); ++i) {
115  if (!tin.isGhost(i) && tin.mark_tetrahedra[i] != 2) {
116  T.push_back(
117  {{tin.tet_node[i * 4],
118  tin.tet_node[i * 4 + 1],
119  tin.tet_node[i * 4 + 2],
120  tin.tet_node[i * 4 + 3]}});
121 
122  // mark surfaces
123  // assuming opposite face to node
124  std::array<bool, 4> on_input = {{false, false, false, false}};
125  for (uint64_t j = i; j < i + 4; ++j) {
126  if (tin.mark_tetrahedra[tin.tet_neigh[j] >> 2] != tin.mark_tetrahedra[j >> 2]) {
127  on_input[j] = true;
128  }
129  }
130 
131  local_f_on_input.push_back(on_input);
132 
133  row++;
134  }
135  }
136  }
137 
138  // remove unused vertices
139  std::vector<int> v_is_used_in_tet(V.size(), 0);
140  for (int64_t i = 0; i < T.size(); ++i) {
141  for (int64_t j = 0; j < 4; ++j) {
142  v_is_used_in_tet[T[i][j]] = 1;
143  }
144  }
145 
146  int64_t v_used_cnt = std::count(v_is_used_in_tet.begin(), v_is_used_in_tet.end(), 1);
147 
148  std::map<int64_t, int64_t> v_map;
149 
150  for (int64_t i = 0; i < V.size(); ++i) {
151  if (v_is_used_in_tet[i]) {
152  v_map[i] = V_final.size();
153  V_final.push_back(V[i]);
154  }
155  }
156 
157  T_final = T;
158 
159  for (int64_t i = 0; i < T.size(); ++i) {
160  for (int64_t j = 0; j < 4; ++j) {
161  T_final[i][j] = v_map[T[i][j]];
162  }
163  }
164 }
165 
167  const std::vector<double>& V,
168  const uint32_t npts,
169  const std::vector<uint32_t>& F,
170  const uint32_t ntri,
171  std::vector<std::array<bool, 4>>& local_f_on_input,
172  std::vector<std::array<int64_t, 4>>& T_final,
173  std::vector<std::array<std::string, 3>>& V_final,
174  bool inner_only)
175 {
176  cdt::inputPLC plc;
177 
178  convert_trimesh_to_input_plc(V, npts, F, ntri, plc);
179 
180  cdt::TetMesh* tin = createSteinerCDT(plc, true, false);
181  convert_cdt_to_stl(*tin, local_f_on_input, T_final, V_final, inner_only);
182 }
183 } // namespace cdt_lib
void cdt_to_string(const std::vector< double > &V, const uint32_t npts, const std::vector< uint32_t > &F, const uint32_t ntri, std::vector< std::array< bool, 4 >> &local_f_on_input, std::vector< std::array< int64_t, 4 >> &T_final, std::vector< std::array< std::string, 3 >> &V_final, bool inner_only)
Definition: cdt_lib.cpp:166
void convert_trimesh_to_input_plc(const std::vector< double > &V, const uint32_t npts, const std::vector< uint32_t > &F, const uint32_t ntri, cdt::inputPLC &plc)
Definition: cdt_lib.cpp:10
cdt::TetMesh * createSteinerCDT(cdt::inputPLC &plc, bool bbox, bool snap)
Definition: cdt_lib.cpp:25
void convert_cdt_to_stl(cdt::TetMesh &tin, std::vector< std::array< bool, 4 >> &local_f_on_input, std::vector< std::array< int64_t, 4 >> &T_final, std::vector< std::array< std::string, 3 >> &V_final, bool inner_only)
Definition: cdt_lib.cpp:54