7 #include "imstkTetrahedralMesh.h" 8 #include "imstkLogger.h" 9 #include "imstkParallelUtils.h" 10 #include "imstkGeometryUtilities.h" 11 #include "imstkSurfaceMesh.h" 20 for (
const Vec4i& tet : *m_indices)
22 const double tetVol = tetVolume(vertices[tet[0]], vertices[tet[1]], vertices[tet[2]], vertices[tet[3]]);
25 LOG(WARNING) <<
"Tetrahedron is inverted, has negative volume!";
36 CHECK(strainParameters->size() == m_indices->size()) <<
"Strain parameters must be the same size as the number of tetrahedra";
37 setCellAttribute(StrainParameterName, strainParameters);
40 std::shared_ptr<imstk::VecDataArray<double, 3>>
43 std::shared_ptr<VecDataArray<double, 3>> params;
49 if (params ==
nullptr)
51 params = std::make_shared<VecDataArray<double, 3>>(m_indices->size());
52 for (
int i = 0; i < params->size(); ++i)
54 (*params)[i] = Vec3d(-1.0, 0.0, 0.0);
56 setCellAttribute(StrainParameterName, params);
59 if (params->size() != m_indices->size())
61 LOG(WARNING) <<
"Strain parameters are not the same size as the number of tetrahedra";
68 std::string TetrahedralMesh::StrainParameterName =
"StrainParameters";
70 std::shared_ptr<SurfaceMesh>
73 const std::array<Vec3i, 4> facePattern = {
74 Vec3i(0, 1, 2), Vec3i(0, 1, 3), Vec3i(0, 2, 3), Vec3i(1, 2, 3)
76 const std::array<int, 4> unusedVert = { 3, 2, 1, 0 };
82 std::shared_ptr<VecDataArray<int, 3>> triIndicesPtr = std::make_shared<VecDataArray<int, 3>>();
87 std::vector<size_t> tetRemainingVert;
94 for (
int i = 0; i < tetraIndices.size(); i++)
96 const Vec4i& tet = tetraIndices[i];
99 for (
int t = 0; t < 4; ++t)
103 a = tet[facePattern[t][0]];
104 b = tet[facePattern[t][1]];
105 c = tet[facePattern[t][2]];
108 for (
int j = triIndices.size() - 1; j != -1; j--)
110 const Vec3i& tri = triIndices[j];
113 && ((tri[1] == b && tri[2] == c) || (tri[1] == c && tri[2] == b)))
115 && ((tri[0] == b && tri[2] == c) || (tri[0] == c && tri[2] == b)))
117 && ((tri[1] == b && tri[0] == c) || (tri[1] == c && tri[0] == b))))
130 tetRemainingVert.push_back(tet[unusedVert[t]]);
135 triIndices.erase(foundAt);
136 tetRemainingVert.erase(tetRemainingVert.begin() + foundAt);
143 for (
int i = 0; i < triIndices.size(); i++)
145 const Vec3d& v0 = tetVertices[triIndices[i][0]];
146 const Vec3d& v1 = tetVertices[triIndices[i][1]];
147 const Vec3d& v2 = tetVertices[triIndices[i][2]];
148 const Vec3d normal = ((v1 - v0).cross(v2 - v0));
149 const Vec3d centroid = (v0 + v1 + v2) / 3.0;
152 const Vec3d unusedVertex = tetVertices[tetRemainingVert.at(i)];
155 if (normal.dot(centroid - unusedVertex) < 0)
157 std::swap(triIndices[i][2], triIndices[i][1]);
165 std::unordered_map<int, int> oldToNewVertId;
166 for (
int i = 0; i < triIndices.size(); i++)
168 Vec3i& face = triIndices[i];
171 if (oldToNewVertId.count(face[0]) == 0)
174 const int newVertexId =
static_cast<int>(oldToNewVertId.size());
175 oldToNewVertId[face[0]] = newVertexId;
176 face[0] = newVertexId;
181 face[0] = oldToNewVertId[face[0]];
184 if (oldToNewVertId.count(face[1]) == 0)
186 const int newVertexId =
static_cast<int>(oldToNewVertId.size());
187 oldToNewVertId[face[1]] = newVertexId;
188 face[1] = newVertexId;
192 face[1] = oldToNewVertId[face[1]];
195 if (oldToNewVertId.count(face[2]) == 0)
197 const int newVertexId =
static_cast<int>(oldToNewVertId.size());
198 oldToNewVertId[face[2]] = newVertexId;
199 face[2] = newVertexId;
203 face[2] = oldToNewVertId[face[2]];
207 auto triVerticesPtr = std::make_shared<VecDataArray<double, 3>>(
static_cast<int>(oldToNewVertId.size()));
210 for (
auto vertIndexPair : oldToNewVertId)
212 const int tetVertId = vertIndexPair.first;
213 const int triVertId = vertIndexPair.second;
215 triVertices[triVertId] = tetVertices[tetVertId];
221 auto surfMesh = std::make_shared<SurfaceMesh>();
222 surfMesh->initialize(triVerticesPtr, triIndicesPtr);
231 return baryCentric(pos,
232 vertices[tetraIndices[tetId][0]],
233 vertices[tetraIndices[tetId][1]],
234 vertices[tetraIndices[tetId][2]],
235 vertices[tetraIndices[tetId][3]]);
243 auto v1 = vertices[tetraIndices[tetId][0]];
244 auto v2 = vertices[tetraIndices[tetId][1]];
245 auto v3 = vertices[tetraIndices[tetId][2]];
246 auto v4 = vertices[tetraIndices[tetId][3]];
248 std::array<double, 4> arrayx = { v1[0], v2[0], v3[0], v4[0] };
249 std::array<double, 4> arrayy = { v1[1], v2[1], v3[1], v4[1] };
250 std::array<double, 4> arrayz = { v1[2], v2[2], v3[2], v4[2] };
252 min[0] = *std::min_element(arrayx.begin(), arrayx.end());
253 min[1] = *std::min_element(arrayy.begin(), arrayy.end());
254 min[2] = *std::min_element(arrayz.begin(), arrayz.end());
256 max[0] = *std::max_element(arrayx.begin(), arrayx.end());
257 max[1] = *std::max_element(arrayy.begin(), arrayy.end());
258 max[2] = *std::max_element(arrayz.begin(), arrayz.end());
262 TetrahedralMesh::cloneImplementation()
const 267 geom->m_indices = std::make_shared<VecDataArray<int, 4>>(*m_indices);
268 for (
auto i : m_cellAttributes)
270 geom->m_cellAttributes[i.first] = i.second->clone();
272 geom->m_initialVertexPositions = std::make_shared<VecDataArray<double, 3>>(*m_initialVertexPositions);
273 geom->m_vertexPositions = std::make_shared<VecDataArray<double, 3>>(*m_vertexPositions);
274 for (
auto i : m_vertexAttributes)
276 geom->m_vertexAttributes[i.first] = i.second->clone();
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
std::shared_ptr< SurfaceMesh > extractSurfaceMesh() override
This method extracts the conforming triangular mesh from the tetrahedral mesh.
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
std::shared_ptr< VecDataArray< double, 3 > > getStrainParameters()
Get/Set the strain parameters for the tetrahedral mesh the strain parameters are expected to be a Vec...
void computeTetrahedronBoundingBox(const size_t &tetId, Vec3d &min, Vec3d &max) const
Compute the bounding box of a given tetrahedron.
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
Vec4d computeBarycentricWeights(const int tetId, const Vec3d &pos) const override
compute the barycentric weights of a given point in 3D space for a given the tetrahedra ...
bool hasCellAttribute(const std::string &arrayName) const
Check if a specific data array exists.
double getVolume() override
Compute and return the volume of the tetrahedral mesh.