Skip to content
Snippets Groups Projects
Commit f2b6e613 authored by Alexis Girault's avatar Alexis Girault
Browse files

Merge branch 'writing-surface-meshes' into 'master'

ENH: adding write support for SurfaceMesh via VTKMeshIO

See merge request !161
parents eb6f5aa4 212b356b
No related branches found
No related tags found
No related merge requests found
......@@ -149,6 +149,12 @@ MeshIO::write(const std::shared_ptr<imstk::Mesh> imstkMesh, const std::string& f
case MeshFileType::VEG:
return VegaMeshIO::write(imstkMesh, filePath, meshType);
break;
case MeshFileType::VTU:
case MeshFileType::VTP:
case MeshFileType::STL:
case MeshFileType::PLY:
return VTKMeshIO::write(imstkMesh, filePath, meshType);
break;
}
LOG(WARNING) << "MeshIO::write error: file type not supported";
......
......@@ -28,6 +28,10 @@
#include "vtkPLYReader.h"
#include "vtkOBJReader.h"
#include "vtkSTLReader.h"
#include "vtkUnstructuredGridWriter.h"
#include "vtkXMLPolyDataWriter.h"
#include "vtkPLYWriter.h"
#include "vtkSTLWriter.h"
#include "vtkFloatArray.h"
#include "vtkTriangleFilter.h"
......@@ -44,42 +48,71 @@ VTKMeshIO::read(const std::string& filePath, MeshFileType meshType)
case MeshFileType::VTK :
{
return VTKMeshIO::readVtkGenericFormatData<vtkGenericDataObjectReader>(filePath);
break;
}
case MeshFileType::VTU :
{
return VTKMeshIO::readVtkUnstructuredGrid<vtkXMLUnstructuredGridReader>(filePath);
break;
}
case MeshFileType::VTP :
{
return VTKMeshIO::readVtkPolyData<vtkXMLPolyDataReader>(filePath);
break;
}
case MeshFileType::STL :
{
return VTKMeshIO::readVtkPolyData<vtkSTLReader>(filePath);
break;
}
case MeshFileType::PLY :
{
return VTKMeshIO::readVtkPolyData<vtkPLYReader>(filePath);
break;
}
case MeshFileType::OBJ :
{
return VTKMeshIO::readVtkPolyData<vtkOBJReader>(filePath);
break;
}
default :
{
LOG(WARNING) << "VTKMeshIO::read error: file type not supported";
return nullptr;
break;
}
}
}
bool
VTKMeshIO::write(const std::shared_ptr<Mesh> imstkMesh, const std::string & filePath, const MeshFileType meshType)
{
if (auto vMesh = std::dynamic_pointer_cast<VolumetricMesh>(imstkMesh))
{
switch (meshType)
{
case MeshFileType::VTU:
return VTKMeshIO::writeVtkUnstructuredGrid(vMesh, filePath);
default:
LOG(WARNING) << "VTKMeshIO::write error: file type not supported for volumetric mesh.";
return false;
}
}
else if (auto sMesh = std::dynamic_pointer_cast<SurfaceMesh>(imstkMesh))
{
switch (meshType)
{
case MeshFileType::VTP:
return VTKMeshIO::writeVtkPolyData<vtkXMLPolyDataWriter>(sMesh, filePath);
case MeshFileType::STL:
return VTKMeshIO::writeVtkPolyData<vtkSTLWriter>(sMesh, filePath);
case MeshFileType::PLY:
return VTKMeshIO::writeVtkPolyData<vtkPLYWriter>(sMesh, filePath);
default:
LOG(WARNING) << "VTKMeshIO::write error: file type not supported for surface mesh.";
return false;
}
}
else
{
LOG(WARNING) << "VTKMeshIO::write error: the provided mesh is not a surface or volumetric mesh.";
return false;
}
}
template<typename ReaderType>
std::shared_ptr<Mesh>
VTKMeshIO::readVtkGenericFormatData(const std::string& filePath)
......@@ -119,6 +152,25 @@ VTKMeshIO::readVtkPolyData(const std::string& filePath)
return VTKMeshIO::convertVtkPolyDataToSurfaceMesh(vtkMesh);
}
template<typename WriterType>
bool
VTKMeshIO::writeVtkPolyData(const std::shared_ptr<SurfaceMesh> imstkMesh, const std::string & filePath)
{
vtkPolyData* vtkMesh = convertSurfaceMeshToVtkPolyData(imstkMesh);
if (!vtkMesh) //conversion unsuccessful
{
return false;
}
auto writer = vtkSmartPointer<WriterType>::New();
writer->SetInputData(vtkMesh);
writer->SetFileName(filePath.c_str());
writer->Update();
vtkMesh->Delete();
return true;
}
template<typename ReaderType>
std::shared_ptr<VolumetricMesh>
VTKMeshIO::readVtkUnstructuredGrid(const std::string& filePath)
......@@ -131,6 +183,41 @@ VTKMeshIO::readVtkUnstructuredGrid(const std::string& filePath)
return VTKMeshIO::convertVtkUnstructuredGridToVolumetricMesh(vtkMesh);
}
bool
VTKMeshIO::writeVtkUnstructuredGrid(const std::shared_ptr<VolumetricMesh> imstkMesh, const std::string & filePath)
{
auto tMesh = std::dynamic_pointer_cast<TetrahedralMesh>(imstkMesh);
auto hMesh = std::dynamic_pointer_cast<HexahedralMesh>(imstkMesh);
vtkUnstructuredGrid* vtkMesh = nullptr;
if (tMesh)
{
vtkMesh = convertTetrahedralMeshToVtkUnstructuredGrid(tMesh);
}
else if (hMesh)
{
vtkMesh = convertHexahedralMeshToVtkUnstructuredGrid(hMesh);
}
else
{
LOG(WARNING) << "VTKMeshIO::writeVtkUnstructuredGrid error: mesh is neither tetrahedral nor hexahedral";
return false;
}
if (!vtkMesh)
{
LOG(WARNING) << "VTKMeshIO::writeVtkUnstructuredGrid error: conversion unsuccessful";
return false;
}
auto writer = vtkSmartPointer<vtkUnstructuredGridWriter>::New();
writer->SetInputData(vtkMesh);
writer->SetFileName(filePath.c_str());
writer->Update();
vtkMesh->Delete();
return true;
}
std::shared_ptr<SurfaceMesh>
VTKMeshIO::convertVtkPolyDataToSurfaceMesh(vtkPolyData* vtkMesh)
{
......@@ -141,10 +228,10 @@ VTKMeshIO::convertVtkPolyDataToSurfaceMesh(vtkPolyData* vtkMesh)
}
StdVectorOfVec3d vertices;
VTKMeshIO::copyVertices(vtkMesh->GetPoints(), vertices);
VTKMeshIO::copyVerticesFromVtk(vtkMesh->GetPoints(), vertices);
std::vector<SurfaceMesh::TriangleArray> triangles;
VTKMeshIO::copyCells<3>(vtkMesh->GetPolys(), triangles);
VTKMeshIO::copyCellsFromVtk<3>(vtkMesh->GetPolys(), triangles);
auto mesh = std::make_shared<SurfaceMesh>();
mesh->initialize(vertices, triangles, true);
......@@ -167,6 +254,51 @@ VTKMeshIO::convertVtkPolyDataToSurfaceMesh(vtkPolyData* vtkMesh)
return mesh;
}
vtkPolyData*
VTKMeshIO::convertSurfaceMeshToVtkPolyData(std::shared_ptr<SurfaceMesh> imstkMesh)
{
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
VTKMeshIO::copyVerticesToVtk(imstkMesh->getVertexPositions(), points.Get());
vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
VTKMeshIO::copyCellsToVtk<3>(imstkMesh->getTrianglesVertices(), polys.Get());
vtkPolyData *polydata = vtkPolyData::New();
polydata->SetPoints(points);
polydata->SetPolys(polys);
return polydata;
}
vtkUnstructuredGrid*
VTKMeshIO::convertTetrahedralMeshToVtkUnstructuredGrid(std::shared_ptr<TetrahedralMesh> imstkMesh)
{
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
VTKMeshIO::copyVerticesToVtk(imstkMesh->getVertexPositions(), points.Get());
vtkSmartPointer<vtkCellArray> tetras = vtkSmartPointer<vtkCellArray>::New();
VTKMeshIO::copyCellsToVtk<4>(imstkMesh->getTetrahedraVertices(), tetras.Get());
vtkUnstructuredGrid *ug = vtkUnstructuredGrid::New();
ug->SetPoints(points);
ug->SetCells(VTK_TETRA, tetras);
return ug;
}
vtkUnstructuredGrid*
VTKMeshIO::convertHexahedralMeshToVtkUnstructuredGrid(std::shared_ptr<HexahedralMesh> imstkMesh)
{
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
VTKMeshIO::copyVerticesToVtk(imstkMesh->getVertexPositions(), points.Get());
vtkSmartPointer<vtkCellArray> bricks = vtkSmartPointer<vtkCellArray>::New();
VTKMeshIO::copyCellsToVtk<8>(imstkMesh->getHexahedraVertices(), bricks.Get());
vtkUnstructuredGrid *ug = vtkUnstructuredGrid::New();
ug->SetPoints(points);
ug->SetCells(VTK_HEXAHEDRON, bricks);
return ug;
}
std::shared_ptr<VolumetricMesh>
VTKMeshIO::convertVtkUnstructuredGridToVolumetricMesh(vtkUnstructuredGrid* vtkMesh)
{
......@@ -177,13 +309,13 @@ VTKMeshIO::convertVtkUnstructuredGridToVolumetricMesh(vtkUnstructuredGrid* vtkMe
}
StdVectorOfVec3d vertices;
VTKMeshIO::copyVertices(vtkMesh->GetPoints(), vertices);
VTKMeshIO::copyVerticesFromVtk(vtkMesh->GetPoints(), vertices);
int cellType = vtkMesh->GetCellType(vtkMesh->GetNumberOfCells()-1);
if( cellType == VTK_TETRA )
{
std::vector<TetrahedralMesh::TetraArray> cells;
VTKMeshIO::copyCells<4>(vtkMesh->GetCells(), cells);
VTKMeshIO::copyCellsFromVtk<4>(vtkMesh->GetCells(), cells);
auto mesh = std::make_shared<TetrahedralMesh>();
mesh->initialize(vertices, cells, false);
......@@ -192,7 +324,7 @@ VTKMeshIO::convertVtkUnstructuredGridToVolumetricMesh(vtkUnstructuredGrid* vtkMe
else if( cellType == VTK_HEXAHEDRON )
{
std::vector<HexahedralMesh::HexaArray> cells;
VTKMeshIO::copyCells<8>(vtkMesh->GetCells(), cells);
VTKMeshIO::copyCellsFromVtk<8>(vtkMesh->GetCells(), cells);
auto mesh = std::make_shared<HexahedralMesh>();
mesh->initialize(vertices, cells, false);
......@@ -207,14 +339,15 @@ VTKMeshIO::convertVtkUnstructuredGridToVolumetricMesh(vtkUnstructuredGrid* vtkMe
}
void
VTKMeshIO::copyVertices(vtkPoints* points, StdVectorOfVec3d& vertices)
VTKMeshIO::copyVerticesFromVtk(vtkPoints* points, StdVectorOfVec3d& vertices)
{
if(!points)
{
LOG(WARNING) << "VTKMeshIO::copyVertices error: No points found.";
LOG(WARNING) << "VTKMeshIO::copyVerticesFromVtk error: No points found.";
return;
}
vertices.reserve(points->GetNumberOfPoints());
for(vtkIdType i = 0; i < points->GetNumberOfPoints(); ++i)
{
double pos[3];
......@@ -223,16 +356,52 @@ VTKMeshIO::copyVertices(vtkPoints* points, StdVectorOfVec3d& vertices)
}
}
void VTKMeshIO::copyVerticesToVtk(const StdVectorOfVec3d & vertices, vtkPoints * points)
{
if (!points)
{
LOG(WARNING) << "VTKMeshIO::copyVerticesToVtk error: No points found.";
return;
}
points->SetNumberOfPoints(vertices.size());
for (size_t i = 0; i < vertices.size(); i++)
{
points->SetPoint(i, vertices[i][0], vertices[i][1], vertices[i][2]);
}
}
template<size_t dim>
void VTKMeshIO::copyCellsToVtk(const std::vector<std::array<size_t, dim>>& cells, vtkCellArray * vtkCells)
{
if (!vtkCells)
{
LOG(WARNING) << "VTKMeshIO::copyCellsToVtk error: No cells found.";
return;
}
for (size_t i = 0; i < cells.size(); i++)
{
vtkCells->InsertNextCell(dim);
for (size_t k = 0; k < dim; k++)
{
vtkCells->InsertCellPoint(cells[i][k]);
}
}
}
template<size_t dim>
void
VTKMeshIO::copyCells(vtkCellArray* vtkCells, std::vector<std::array<size_t,dim>>& cells)
VTKMeshIO::copyCellsFromVtk(vtkCellArray* vtkCells, std::vector<std::array<size_t,dim>>& cells)
{
if(!vtkCells)
{
LOG(WARNING) << "VTKMeshIO::copyCells error: No cells found.";
LOG(WARNING) << "VTKMeshIO::copyCellsFromVtk error: No cells found.";
return;
}
cells.reserve(vtkCells->GetNumberOfCells());
vtkCells->InitTraversal();
auto vtkCell = vtkSmartPointer<vtkIdList>::New();
std::array<size_t, dim> cell;
......@@ -258,19 +427,19 @@ VTKMeshIO::copyPointData(vtkPointData* pointData, std::map<std::string, StdVecto
return;
}
for (unsigned int i = 0; i < pointData->GetNumberOfArrays(); ++i)
for (int i = 0; i < pointData->GetNumberOfArrays(); ++i)
{
vtkDataArray* array = pointData->GetArray(i);
std::string name = array->GetName();
int nbrOfComp = array->GetNumberOfComponents();
int nbrOfTuples = array->GetNumberOfTuples();
vtkIdType nbrOfTuples = array->GetNumberOfTuples();
StdVectorOfVectorf data;
for(unsigned int j = 0; j < nbrOfTuples; ++j)
for(vtkIdType j = 0; j < nbrOfTuples; ++j)
{
double* tupleData = new double [nbrOfComp];
array->GetTuple(j, tupleData);
Vectorf tuple(nbrOfComp);
for (unsigned int k = 0; k < nbrOfComp; k++)
for (int k = 0; k < nbrOfComp; k++)
{
tuple[k] = tupleData[k];
}
......
......@@ -62,6 +62,11 @@ public:
///
static std::shared_ptr<Mesh> read(const std::string& filePath, MeshFileType meshType);
///
/// \brief Writes the given mesh to the specified file path.
///
static bool write(const std::shared_ptr<Mesh> imstkMesh, const std::string& filePath, const MeshFileType meshType);
protected:
///
......@@ -76,6 +81,17 @@ protected:
template<typename ReaderType>
static std::shared_ptr<SurfaceMesh> readVtkPolyData(const std::string& filePath);
///
/// \brief Writes the given surfase mesh to given file path using the provided writer type
///
template<typename WriterType>
static bool writeVtkPolyData(const std::shared_ptr<SurfaceMesh> imstkMesh, const std::string& filePath);
///
/// \brief Writes the given volumetric mesh to given file path
///
static bool writeVtkUnstructuredGrid(const std::shared_ptr<VolumetricMesh> imstkMesh, const std::string& filePath);
///
/// \brief
///
......@@ -87,6 +103,21 @@ protected:
///
static std::shared_ptr<SurfaceMesh> convertVtkPolyDataToSurfaceMesh(vtkPolyData* vtkMesh);
///
/// \brief Converts imstk surface mesh into a vtk polydata suitable for writing to file
///
static vtkPolyData* convertSurfaceMeshToVtkPolyData(std::shared_ptr<SurfaceMesh> imstkMesh);
///
/// \brief Converts imstk tetrahedral mesh into a vtk unstructured grid suitable for writing to file
///
static vtkUnstructuredGrid* convertTetrahedralMeshToVtkUnstructuredGrid(std::shared_ptr<TetrahedralMesh> imstkMesh);
///
/// \brief Converts imstk hexahedral mesh into a vtk unstructured grid suitable for writing to file
///
static vtkUnstructuredGrid * convertHexahedralMeshToVtkUnstructuredGrid(std::shared_ptr<HexahedralMesh> imstkMesh);
///
/// \brief
///
......@@ -95,13 +126,24 @@ protected:
///
/// \brief
///
static void copyVertices(vtkPoints* points, StdVectorOfVec3d& vertices);
static void copyVerticesFromVtk(vtkPoints* points, StdVectorOfVec3d& vertices);
///
/// \brief Copies vertices from imstk structure to VTK one
///
static void copyVerticesToVtk(const StdVectorOfVec3d& vertices, vtkPoints* points);
///
/// \brief Copies cells of the given dimension from imstk structure to VTK one
///
template<size_t dim>
static void copyCellsToVtk(const std::vector<std::array<size_t, dim>>& cells, vtkCellArray* vtkCells);
///
/// \brief
///
template<size_t dim>
static void copyCells(vtkCellArray* vtkCells, std::vector<std::array<size_t,dim>>& cells);
static void copyCellsFromVtk(vtkCellArray* vtkCells, std::vector<std::array<size_t,dim>>& cells);
///
/// \brief
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment