Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions BGL/doc/BGL/PackageDescription.txt
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,10 @@ the requirement for traversal of all faces in a graph.
/// I/O Functions for the \ref IOStreamVTK
/// \ingroup PkgBGLIOFct

/// \defgroup PkgBGLIoFuncsVTU VTU I/O Functions
/// I/O Functions for the \ref IOStreamVTK
/// \ingroup PkgBGLIOFct

/// \defgroup PkgBGLIoFuncsGOCAD GOCAD I/O Functions
/// I/O Functions for the \ref IOStreamGocad
/// \ingroup PkgBGLIOFct
Expand Down Expand Up @@ -795,6 +799,7 @@ user might encounter.
- \link PkgBGLIoFuncsOFF I/O for OFF files \endlink
- \link PkgBGLIoFuncsGOCAD I/O for GOCAD files \endlink
- \link PkgBGLIoFuncsVTP I/O for VTP files \endlink
- \link PkgBGLIoFuncsVTU I/O for VTU files \endlink
- \link PkgBGLIoFuncs3MF I/O for 3MF files \endlink
- \link PkgBGLIoFuncsWRL I/O for WRL files \endlink
*/
Expand Down
10 changes: 9 additions & 1 deletion BGL/include/CGAL/IO/polygon_mesh_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ bool read_polygon_mesh(std::istream& is,
* - \ref IOStreamSTL (`.stl`)
* - \ref IOStreamPLY (`.ply`)
* - \ref IOStreamGocad (`.ts`)
* - \ref IOStreamVTK (`.vtp`)
* - \ref IOStreamVTK (`.vtu`, `.vtp`)
*
* The format is detected from the filename extension (letter case is not important).
*
Expand Down Expand Up @@ -153,6 +153,8 @@ bool read_polygon_mesh(const std::string& fname,
#ifdef CGAL_USE_VTK
else if(ext == "vtp")
return read_VTP(fname, g, np);
else if(ext == "vtu")
return read_VTU(fname, g, np);
#endif

if(verbose)
Expand Down Expand Up @@ -244,6 +246,10 @@ bool write_polygon_mesh(const std::string& fname,
return write_OBJ(fname, g, np);
else if(ext == "off")
return write_OFF(fname, g, np);
#ifdef CGAL_USE_OPENMESH
else if(ext == "om")
return write_OM(fname, g, np);
#endif
else if(ext == "ply")
return write_PLY(fname, g, np);
else if(ext == "stl")
Expand All @@ -253,6 +259,8 @@ bool write_polygon_mesh(const std::string& fname,
#ifdef CGAL_USE_VTK
else if(ext == "vtp")
return write_VTP(fname, g, np);
else if(ext == "vtu")
return write_VTU(fname, g, np);
#endif

if(verbose)
Expand Down
131 changes: 131 additions & 0 deletions BGL/include/CGAL/boost/graph/IO/VTK.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <vtkXMLPolyDataReader.h>
#include <vtkPointSet.h>
#include <vtkPolyData.h>
#include <vtkXMLUnstructuredGridReader.h>
#include <vtkXMLUnstructuredGridWriter.h>
#endif

#if defined(CGAL_USE_VTK) || defined(DOXYGEN_RUNNING)
Expand Down Expand Up @@ -162,6 +164,72 @@ bool read_VTP(const std::string& fname,
return internal::vtkPointSet_to_polygon_mesh(data, g, np);
}

/*!
* \ingroup PkgBGLIoFuncsVTU
*
* \brief reads a PolyData in the \ref IOStreamVTK into a triangulated surface mesh.
*
* The data is expected to represent a 2-manifold (possibly with borders).
*
* \attention The graph `g` is not cleared, and the data from the file are appended.
*
* \tparam Graph a model of `MutableFaceGraph`
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
*
* \param fname the path to the file that will be read
* \param g the output mesh
* \param np optional \ref bgl_namedparameters "Named Parameters" described below
*
* \cgalNamedParamsBegin
* \cgalParamNBegin{vertex_point_map}
* \cgalParamDescription{a property map associating points to the vertices of `g`}
* \cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
* as key type and `%Point_3` as value type}
* \cgalParamDefault{`boost::get(CGAL::vertex_point, g)`}
* \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
* must be available in `Graph`.}
* \cgalParamNEnd
* \cgalParamNBegin{verbose}
* \cgalParamDescription{whether extra information is printed when an incident occurs during reading}
* \cgalParamType{Boolean}
* \cgalParamDefault{`false`}
* \cgalParamNEnd
* \cgalNamedParamsEnd
*
* \returns `true` if reading was successful, `false` otherwise.
*/
template<typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_VTU(const std::string& fname,
Graph& g,
const CGAL_NP_CLASS& np = parameters::default_values())
{
using CGAL::parameters::get_parameter;
using CGAL::parameters::choose_parameter;
bool verbose = choose_parameter(get_parameter(np, internal_np::verbose), false);

std::ifstream test(fname);
if(!test.good())
{
if(verbose) std::cerr<<"File doesn't exist."<<std::endl;
return false;
}
test.close();

vtkSmartPointer<vtkPointSet> data;
vtkSmartPointer<CGAL::IO::internal::ErrorObserverVtk> obs =
vtkSmartPointer<CGAL::IO::internal::ErrorObserverVtk>::New();

data = internal::read_vtk_file<vtkXMLUnstructuredGridReader>(fname, obs)->GetOutput();
if(obs->GetError())
return false;
if(obs->GetWarning() && verbose)
std::cout << "VTK Warning message : " << obs->GetWarningMessage().data() << std::endl;

return internal::vtkPointSet_to_polygon_mesh(data, g, np);
}


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Write
Expand Down Expand Up @@ -526,6 +594,69 @@ bool write_VTP(const std::string& fname, const Graph& g, const CGAL_NP_CLASS& np
return write_VTP(os, g, np);
}

template <typename Graph, typename CGAL_NP_TEMPLATE_PARAMETERS>
bool write_VTU(const std::string& fname, const Graph& g, const CGAL_NP_CLASS& np = parameters::default_values())
{
const bool binary = CGAL::parameters::choose_parameter(CGAL::parameters::get_parameter(np, internal_np::use_binary_mode), true);
std::ofstream os;
if(binary)
{
os.open(fname, std::ios::binary);
CGAL::IO::set_mode(os, CGAL::IO::BINARY);
}
else
os.open(fname);

typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Graph>::face_descriptor face_descriptor;
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

typedef typename boost::property_map<Graph, CGAL::vertex_point_t>::const_type VPMap;
typedef typename boost::property_map_value<Graph, CGAL::vertex_point_t>::type Point_3;
VPMap vpmap = get(CGAL::vertex_point, g);

vtkPoints* const vtk_points = vtkPoints::New();
vtkCellArray* const vtk_cells = vtkCellArray::New();

vtk_points->Allocate(num_vertices(g));
vtk_cells->Allocate(num_faces(g));

std::map<vertex_descriptor, vtkIdType> Vids;
vtkIdType inum = 0;

for(vertex_descriptor v : vertices(g))
{
const Point_3& p = get(vpmap, v);
vtk_points->InsertNextPoint(CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()));
Vids[v] = inum++;
}
for(face_descriptor f : faces(g))
{
vtkIdList* cell = vtkIdList::New();
for(halfedge_descriptor h : halfedges_around_face(halfedge(f, g), g)) {
cell->InsertNextId(Vids[target(h, g)]);
}
vtk_cells->InsertNextCell(cell);
cell->Delete();
}

vtkSmartPointer<vtkUnstructuredGrid> usg = vtkSmartPointer<vtkUnstructuredGrid>::New();

usg->SetPoints(vtk_points);
vtk_points->Delete();

usg->SetCells(5, vtk_cells);
vtk_cells->Delete();

// Write the unstructured grid
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer
= vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(fname.data());
writer->SetInputData(usg);
writer->Write();

return true;
}

} // namespace IO

Expand Down