iMSTK
Interactive Medical Simulation Toolkit
imstkVegaMeshIO.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkHexahedralMesh.h"
8 #include "imstkLogger.h"
9 #include "imstkMacros.h"
10 #include "imstkTetrahedralMesh.h"
11 #include "imstkVecDataArray.h"
12 #include "imstkVegaMeshIO.h"
13 
14 DISABLE_WARNING_PUSH
15  DISABLE_WARNING_HIDES_CLASS_MEMBER
16 
17 #include <tetMesh.h>
18 #include <volumetricMeshLoader.h>
19 
20 DISABLE_WARNING_POP
21 
22 namespace imstk
23 {
24 std::shared_ptr<PointSet>
25 VegaMeshIO::read(const std::string& filePath, MeshFileType meshType)
26 {
27  CHECK(meshType == MeshFileType::VEG) << "@VegaMeshIO::read error: input file type is not veg for input " << filePath;
28 
29  // Read Vega Mesh
30  std::shared_ptr<vega::VolumetricMesh> vegaMesh = VegaMeshIO::readVegaMesh(filePath);
31 
32  // Convert to Volumetric Mesh
34 }
35 
36 bool
37 VegaMeshIO::write(const std::shared_ptr<PointSet> imstkMesh, const std::string& filePath, const MeshFileType meshType)
38 {
39  CHECK(meshType == MeshFileType::VEG) << "@VegaMeshIO::write error: file type is not veg for input " << filePath;
40 
41  // Extract volumetric mesh
42  auto imstkVolMesh = std::dynamic_pointer_cast<PointSet>(imstkMesh);
43 
44  CHECK(imstkVolMesh != nullptr) << "@VegaMeshIO::write error: imstk::PointSet object supplied is not a imstk::VolumetricMesh type for input" << filePath;
45 
46  const std::string geometryType = imstkVolMesh->getTypeName();
47  if (geometryType == TetrahedralMesh::getStaticTypeName() || geometryType == HexahedralMesh::getStaticTypeName())
48  {
49  auto vegaMesh = convertVolumetricMeshToVegaMesh(imstkVolMesh);
50 
51  CHECK(vegaMesh != nullptr) << "@VegaMeshIO::write error: failed to convert volumetric mesh to vega mesh for input" << filePath;
52 
53  const auto fileName = const_cast<char*>(filePath.c_str());
54  const int write_status = vegaMesh->save(fileName);
55 
56  CHECK(write_status == 0) << "@VegaMeshIO::write error: failed (vega fail code " << write_status <<
57  ". Check vega::VolumetricMesh::save for documentation)to write .veg file for input" << filePath;
58 
59  return true;
60  }
61 
62  LOG(WARNING) << "Error: Unknown element type (only tetrahedral and hexahedral elements supported) for input " << filePath;
63  return false;
64 }
65 
66 std::shared_ptr<vega::VolumetricMesh>
67 VegaMeshIO::readVegaMesh(const std::string& filePath)
68 {
69  auto fileName = const_cast<char*>(filePath.c_str());
70  std::shared_ptr<vega::VolumetricMesh> vegaMesh(vega::VolumetricMeshLoader::load(fileName));
71  return vegaMesh;
72 }
73 
74 std::shared_ptr<PointSet>
75 VegaMeshIO::convertVegaMeshToVolumetricMesh(std::shared_ptr<vega::VolumetricMesh> vegaMesh)
76 {
77  // Copy vertices
78  std::shared_ptr<VecDataArray<double, 3>> vertices = std::make_shared<VecDataArray<double, 3>>();
79  VegaMeshIO::copyVertices(vegaMesh, *vertices);
80 
81  // Copy cells
82  auto cellType = vegaMesh->getElementType();
83  std::shared_ptr<PointSet> mesh;
84  if (cellType == vega::VolumetricMesh::TET)
85  {
86  std::shared_ptr<VecDataArray<int, 4>> cellsPtr = std::make_shared<VecDataArray<int, 4>>();
87  VecDataArray<int, 4>& cells = *cellsPtr;
88  VegaMeshIO::copyCells<4>(vegaMesh, cells);
89 
90  auto tetMesh = std::make_shared<TetrahedralMesh>();
91  tetMesh->initialize(vertices, cellsPtr);
92  mesh = tetMesh;
93  }
94  else if (cellType == vega::VolumetricMesh::CUBIC)
95  {
96  std::shared_ptr<VecDataArray<int, 8>> cellsPtr = std::make_shared<VecDataArray<int, 8>>();
97  VecDataArray<int, 8>& cells = *cellsPtr;
98  VegaMeshIO::copyCells<8>(vegaMesh, cells);
99 
100  auto hexMesh = std::make_shared<HexahedralMesh>();
101  hexMesh->initialize(vertices, cellsPtr);
102  mesh = hexMesh;
103  }
104  else
105  {
106  vegaMesh.reset();
107  LOG(WARNING) << "Error: invalid cell type";
108  return nullptr;
109  }
110  return mesh;
111 }
112 
113 void
114 VegaMeshIO::copyVertices(std::shared_ptr<vega::VolumetricMesh> vegaMesh,
115  VecDataArray<double, 3>& vertices)
116 {
117  for (int i = 0; i < vegaMesh->getNumVertices(); ++i)
118  {
119  auto pos = vegaMesh->getVertex(i);
120  vertices.push_back(Vec3d(pos[0], pos[1], pos[2]));
121  }
122 }
123 
124 template<size_t dim>
125 void
126 VegaMeshIO::copyCells(std::shared_ptr<vega::VolumetricMesh> vegaMesh,
127  VecDataArray<int, dim>& cells)
128 {
129  typename VecDataArray<int, dim>::ValueType cell;
130  for (int cellId = 0; cellId < vegaMesh->getNumElements(); ++cellId)
131  {
132  for (int i = 0; i < vegaMesh->getNumElementVertices(); ++i)
133  {
134  cell[i] = vegaMesh->getVertexIndex(static_cast<int>(cellId), i);
135  }
136  cells.push_back(cell);
137  }
138 }
139 
140 std::shared_ptr<vega::VolumetricMesh>
141 VegaMeshIO::convertVolumetricMeshToVegaMesh(const std::shared_ptr<PointSet> imstkVolMesh)
142 {
143  // as of now, only works for TET elements
144  if (imstkVolMesh->getTypeName() == TetrahedralMesh::getStaticTypeName())
145  {
146  auto imstkVolTetMesh = std::dynamic_pointer_cast<imstk::TetrahedralMesh>(imstkVolMesh);
147 
148  auto vertexArray = *imstkVolMesh->getVertexPositions();
149  std::vector<double> vertices;
150  for (const auto& node : vertexArray)
151  {
152  vertices.emplace_back(node(0));
153  vertices.emplace_back(node(1));
154  vertices.emplace_back(node(2));
155  }
156 
157  VecDataArray<int, 4>& tetArray = *imstkVolTetMesh->getCells();
158  std::vector<int> elements;
159  for (const Vec4i& tet : tetArray)
160  {
161  elements.emplace_back(int(tet[0]));
162  elements.emplace_back(int(tet[1]));
163  elements.emplace_back(int(tet[2]));
164  elements.emplace_back(int(tet[3]));
165  }
166 
167  // Using default material properties to append to the .veg file
168  auto vegaMesh = std::make_shared<vega::TetMesh>(int(imstkVolTetMesh->getNumVertices()),
169  &vertices[0],
170  int(imstkVolTetMesh->getNumCells()),
171  &elements[0],
172  1E7, /* Young's modulus */
173  0.4, /* Poisson's ratio */
174  1000.0 /* density */);
175 
176  CHECK(vegaMesh != nullptr) << "@VegaMeshIO::convertVolumetricMeshToVegaMesh error: Failed to create vega mesh. "
177  << "Check vega::TetMesh::TetMesh() for clues";
178 
179  return vegaMesh;
180  }
181  else
182  {
183  LOG(WARNING) << "Error: Geometry type other than tetrahedral mesh not supported";
184  return nullptr;
185  }
186 }
187 } // namespace imstk
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
Definition: imstkPointSet.h:25
static std::shared_ptr< PointSet > convertVegaMeshToVolumetricMesh(std::shared_ptr< vega::VolumetricMesh > vegaVolumeMesh)
Generate volumetric mesh given a vega volume mesh.
MeshFileType
Enumeration the mesh file type.
Definition: imstkMeshIO.h:19
Compound Geometry.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
static bool write(const std::shared_ptr< imstk::PointSet > imstkMesh, const std::string &filePath, const MeshFileType meshType)
Write a volumetric mesh in vega file format.
static std::shared_ptr< PointSet > read(const std::string &filePath, MeshFileType meshType)
Read and generate volumetric mesh given a external vega mesh file.
static std::shared_ptr< vega::VolumetricMesh > convertVolumetricMeshToVegaMesh(const std::shared_ptr< PointSet > volumeMesh)
Generate a vega volume mesh given volumetric mesh.
static std::shared_ptr< vega::VolumetricMesh > readVegaMesh(const std::string &filePath)
Read vega volume mesh from a file.