Merge pull request #3297 from maxGimeno/Stream_support-Dont_use_vtk_for_vtu-GF

Stream support: VTP and VTU writing functions
This commit is contained in:
Laurent Rineau 2019-02-07 13:31:23 +01:00
commit 9a03d47cb0
18 changed files with 1203 additions and 52 deletions

View File

@ -16,6 +16,7 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h
EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \
${CGAL_Surface_mesh_segmentation_EXAMPLE_DIR} \
${CGAL_Polygon_mesh_processing_EXAMPLE_DIR} \

View File

@ -81,6 +81,13 @@ being marked or not.\n
<b>Default:</b> a default property map where no edge is constrained
\cgalNPEnd
\cgalNPBegin{use_binary_mode} \anchor BGL_use_binary_mode
is a Boolean indicating whether the binary mode or the ASCII mode should be used
when writing data into a stream.\n
<b>Type:</b> `bool`\n
<b>Default:</b> Function specific.
\cgalNPEnd
\cgalNPBegin{METIS_options} \anchor BGL_METIS_options
is a parameter used in `partition_graph()` and `partition_dual_graph()`
to pass options to the METIS graph partitioner. The many options of METIS

View File

@ -709,6 +709,7 @@ user might encounter.
- \link PkgBGLIOFct CGAL::read_off() \endlink
- \link PkgBGLIOFct CGAL::write_off() \endlink
- \link PkgBGLIOFct CGAL::write_wrl() \endlink
- `CGAL::write_vtp()`
*/

View File

@ -34,6 +34,7 @@
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/boost/graph/named_function_params.h>
#include <CGAL/IO/write_vtk.h>
namespace CGAL {
/*!
@ -401,6 +402,278 @@ bool write_inp(std::ostream& os,
{
return write_inp(os, g, name, type, parameters::all_default());
}
namespace internal {
namespace write_vtp {
// writes the polys appended data at the end of the .vtp file
template <class Mesh,
typename NamedParameters>
void
write_polys(std::ostream& os,
const Mesh & mesh,
const NamedParameters& np)
{
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Mesh>::face_iterator face_iterator;
typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap<Mesh, NamedParameters>::type Vimap;
Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index),
get_const_property_map(CGAL::internal_np::vertex_index, mesh));
std::vector<std::size_t> connectivity_table;
std::vector<std::size_t> offsets;
std::vector<unsigned char> cell_type(num_faces(mesh),5); // triangle == 5
std::size_t off = 0;
for( face_iterator fit = faces(mesh).begin() ;
fit != faces(mesh).end() ;
++fit )
{
off += 3;
offsets.push_back(off);
BOOST_FOREACH(vertex_descriptor v,
vertices_around_face(halfedge(*fit, mesh), mesh))
connectivity_table.push_back(V[v]);
}
write_vector<std::size_t>(os,connectivity_table);
write_vector<std::size_t>(os,offsets);
write_vector<unsigned char>(os,cell_type);
}
//todo use named params for maps
template <class Mesh,
typename NamedParameters>
void
write_polys_tag(std::ostream& os,
const Mesh & mesh,
bool binary,
std::size_t& offset,
const NamedParameters& np)
{
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Mesh>::face_iterator face_iterator;
typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap<Mesh, NamedParameters>::type Vimap;
Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index),
get_const_property_map(CGAL::internal_np::vertex_index, mesh));
std::string formatattribute =
binary ? " format=\"appended\"" : " format=\"ascii\"";
std::string typeattribute;
switch(sizeof(std::size_t)) {
case 8: typeattribute = " type=\"UInt64\""; break;
case 4: typeattribute = " type=\"UInt32\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
// Write connectivity table
os << " <Polys>\n"
<< " <DataArray Name=\"connectivity\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t);
// 3 indices (size_t) per triangle + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( face_iterator fit = faces(mesh).begin() ;
fit != faces(mesh).end() ;
++fit )
{
BOOST_FOREACH(vertex_descriptor v,
vertices_around_face(halfedge(*fit, mesh), mesh))
os << V[v] << " ";
}
os << " </DataArray>\n";
}
// Write offsets
os << " <DataArray Name=\"offsets\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (num_faces(mesh) + 1) * sizeof(std::size_t);
// 1 offset (size_t) per triangle + length of the encoded data (size_t)
}
else {
os << "\">\n";
std::size_t polys_offset = 0;
for( face_iterator fit = faces(mesh).begin() ;
fit != faces(mesh).end() ;
++fit )
{
polys_offset += 3;
os << polys_offset << " ";
}
os << " </DataArray>\n";
}
// Write cell type (triangle == 5)
os << " <DataArray Name=\"types\""
<< formatattribute << " type=\"UInt8\"";
if (binary) {
os << " offset=\"" << offset << "\"/>\n";
offset += num_faces(mesh) + sizeof(std::size_t);
// 1 unsigned char per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
for(std::size_t i = 0; i< num_faces(mesh); ++i)
os << "5 ";
os << " </DataArray>\n";
}
os << " </Polys>\n";
}
//todo : use namedparams for points and ids
//overload for facegraph
template <class Mesh,
typename NamedParameters>
void
write_points_tag(std::ostream& os,
const Mesh & mesh,
bool binary,
std::size_t& offset,
const NamedParameters& np)
{
typedef typename boost::graph_traits<Mesh>::vertex_iterator vertex_iterator;
typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap<Mesh, NamedParameters>::const_type Vpmap;
Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point),
get_const_property_map(CGAL::vertex_point, mesh));
typedef typename boost::property_traits<Vpmap>::value_type Point_t;
typedef typename CGAL::Kernel_traits<Point_t>::Kernel Gt;
typedef typename Gt::FT FT;
std::string format = binary ? "appended" : "ascii";
std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32";
os << " <Points>\n"
<< " <DataArray type =\"" << type << "\" NumberOfComponents=\"3\" format=\""
<< format;
if (binary) {
os << "\" offset=\"" << offset << "\"/>\n";
offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t);
// 3 coords per points + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( vertex_iterator vit = vertices(mesh).begin();
vit != vertices(mesh).end();
++vit)
{
os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " "
<< get(vpm, *vit).z() << " ";
}
os << " </DataArray>\n";
}
os << " </Points>\n";
}
// writes the points appended data at the end of the .vtp file
template <class Mesh,
class NamedParameters>
void
write_polys_points(std::ostream& os,
const Mesh & mesh,
const NamedParameters& np)
{
typedef typename boost::graph_traits<Mesh>::vertex_iterator vertex_iterator;
typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap<Mesh, NamedParameters>::const_type Vpmap;
Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point),
get_const_property_map(CGAL::vertex_point, mesh));
typedef typename boost::property_traits<Vpmap>::value_type Point_t;
typedef typename CGAL::Kernel_traits<Point_t>::Kernel Gt;
typedef typename Gt::FT FT;
std::vector<FT> coordinates;
for( vertex_iterator vit = vertices(mesh).begin();
vit != vertices(mesh).end();
++vit)
{
coordinates.push_back(get(vpm, *vit).x());
coordinates.push_back(get(vpm, *vit).y());
coordinates.push_back(get(vpm, *vit).z());
}
write_vector<FT>(os,coordinates);
}
} // end namespace CGAL::internal::write_vtp
} // end namespace CGAL::internal
/*!\ingroup PkgBGLIOFct
*
* \brief writes a triangulated surface mesh in the `PolyData` XML format.
*
* \tparam TriangleMesh a model of `FaceListGraph` with only triangle faces.
* \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters"
*
* \param os the stream used for writing.
* \param mesh the triangle mesh to be written.
* \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the
* ones listed below
*
* \cgalNamedParamsBegin
* \cgalParamBegin{use_binary_mode} a Boolean indicating if the
* data should be written in binary (`true`, the default) or in ASCII (`false`).
* \cgalParamEnd
* \cgalParamBegin{vertex_point_map} the property map with the points associated to
* the vertices of `mesh`. If this parameter is omitted, an internal property map for
* `CGAL::vertex_point_t` must be available in `TriangleMesh`.
* \cgalParamEnd
* \cgalParamBegin{vertex_index_map} the property map with the indices associated to
* the vertices of `mesh`. If this parameter is omitted, an internal property map for
* `CGAL::vertex_index_t` must be available in `TriangleMesh`.
* \cgalParamEnd
* \cgalNamedParamsEnd
*/
template<class TriangleMesh,
class NamedParameters>
void write_vtp(std::ostream& os,
const TriangleMesh& mesh,
const NamedParameters& np)
{
os << "<?xml version=\"1.0\"?>\n"
<< "<VTKFile type=\"PolyData\" version=\"0.1\"";
#ifdef CGAL_LITTLE_ENDIAN
os << " byte_order=\"LittleEndian\"";
#else // CGAL_BIG_ENDIAN
os << " byte_order=\"BigEndian\"";
#endif
switch(sizeof(std::size_t)) {
case 4: os << " header_type=\"UInt32\""; break;
case 8: os << " header_type=\"UInt64\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
os << ">\n"
<< " <PolyData>" << "\n";
os << " <Piece NumberOfPoints=\"" << num_vertices(mesh)
<< "\" NumberOfPolys=\"" << num_faces(mesh) << "\">\n";
std::size_t offset = 0;
const bool binary = boost::choose_param(boost::get_param(np, internal_np::use_binary_mode), true);
internal::write_vtp::write_points_tag(os,mesh,binary,offset, np);
internal::write_vtp::write_polys_tag(os,mesh,binary,offset, np);
os << " </Piece>\n"
<< " </PolyData>\n";
if (binary) {
os << "<AppendedData encoding=\"raw\">\n_";
internal::write_vtp::write_polys_points(os,mesh, np);
internal::write_vtp::write_polys(os,mesh, np);
}
os << "</VTKFile>\n";
}
template<class TriangleMesh>
void write_vtp(std::ostream& os,
const TriangleMesh& mesh)
{
write_vtp(os, mesh, CGAL::parameters::all_default());
}
} // namespace CGAL
#endif // CGAL_BOOST_GRAPH_IO_H

View File

@ -28,6 +28,7 @@ CGAL_add_named_parameter(edge_is_constrained_t, edge_is_constrained, edge_is_con
CGAL_add_named_parameter(first_index_t, first_index, first_index)
CGAL_add_named_parameter(number_of_iterations_t, number_of_iterations, number_of_iterations)
CGAL_add_named_parameter(verbosity_level_t, verbosity_level, verbosity_level)
CGAL_add_named_parameter(use_binary_mode_t, use_binary_mode, use_binary_mode)
CGAL_add_named_parameter(metis_options_t, METIS_options, METIS_options)
CGAL_add_named_parameter(vertex_partition_id_t, vertex_partition_id, vertex_partition_id_map)

View File

@ -102,6 +102,7 @@ void test(const NamedParameters& np)
assert(get_param(np, CGAL::internal_np::weight_calculator).v == 39);
assert(get_param(np, CGAL::internal_np::preserve_genus).v == 40);
assert(get_param(np, CGAL::internal_np::verbosity_level).v == 41);
assert(get_param(np, CGAL::internal_np::use_binary_mode).v == 51);
assert(get_param(np, CGAL::internal_np::projection_functor).v == 42);
assert(get_param(np, CGAL::internal_np::apply_per_connected_component).v == 46);
assert(get_param(np, CGAL::internal_np::output_iterator).v == 47);
@ -182,6 +183,7 @@ void test(const NamedParameters& np)
check_same_type<39>(get_param(np, CGAL::internal_np::weight_calculator));
check_same_type<40>(get_param(np, CGAL::internal_np::preserve_genus));
check_same_type<41>(get_param(np, CGAL::internal_np::verbosity_level));
check_same_type<51>(get_param(np, CGAL::internal_np::use_binary_mode));
check_same_type<42>(get_param(np, CGAL::internal_np::projection_functor));
check_same_type<46>(get_param(np, CGAL::internal_np::apply_per_connected_component));
check_same_type<47>(get_param(np, CGAL::internal_np::output_iterator));
@ -241,6 +243,7 @@ int main()
.weight_calculator(A<39>(39))
.preserve_genus(A<40>(40))
.verbosity_level(A<41>(41))
.use_binary_mode(A<51>(51))
.projection_functor(A<42>(42))
.throw_on_self_intersection(A<43>(43))
.clip_volume(A<44>(44))

View File

@ -22,6 +22,7 @@
#include <CGAL/Random.h>
#include <CGAL/point_generators_2.h>
#include <CGAL/Timer.h>
#include <CGAL/IO/write_vtu.h>
// Qt headers
#include <QtGui>
@ -658,7 +659,8 @@ MainWindow::on_actionSaveConstraints_triggered()
tr("Save Constraints"),
".",
tr("Poly files (*.poly)\n"
"Edge files (*.edg)"));
"Edge files (*.edg)\n"
"VTU files (*.vtu)"));
if(! fileName.isEmpty()){
saveConstraints(fileName);
}
@ -669,7 +671,13 @@ void
MainWindow::saveConstraints(QString fileName)
{
std::ofstream output(qPrintable(fileName));
if (output) output << cdt;
if(!fileName.endsWith("vtu") && output)
output << cdt;
else if (output)
{
CGAL::write_vtu(output, cdt);
}
}

View File

@ -91,6 +91,12 @@ Release date: March 2019
`Arr_polyline_traits_2`, `Arr_polycurve_traits_2`, and
`Arr_polycurve_basic_traits_2`.
### 2D and 3D Mesh Generation
- Added two functions for writing in XML VTK formats:
- `CGAL::write_vtu()`, that writes a 2D mesh in a `.vtu` file,
- `CGAL::output_to_vtu()`, that writes a 3D mesh in a `.vtu` file.
### 2D Minkowski Sums
- Fixed a bug in the function that computed the Minkowski sum using the
@ -99,7 +105,10 @@ Release date: March 2019
### CGAL and the Boost Graph Library (BGL)
- Add function `write_wrl()` for writing into VRML 2.0 format.
- Added function `write_wrl()` for writing into VRML 2.0 format.
- Added functions `CGAL::write_vtp()` for writing a triangulated
face graph in a `.vtp` file (XML VTK format).
Release 4.13

View File

@ -0,0 +1,19 @@
namespace CGAL{
//!\ingroup PkgMesh2IO
//! \brief writes the faces of a domain and its constrained edges embedded in
//! a 2D constrained Delaunay triangulation using the `PolyData` XML format.
//!
//! The faces output are those for which `DelaunayMeshFaceBase_2::is_in_domain()` returns `true`,
//! the edges are those for which `ConstrainedTriangulationFaceBase_2::is_constrained()` returns `true`.
//! \tparam CDT a `Constrained_Delaunay_triangulation_2` with face type model of `DelaunayMeshFaceBase_2`.
//!
//! \param os the stream used for writing.
//! \param tr the triangulated domain to be written.
//! \param mode decides if the data should be written in binary (`IO::BINARY`)
//! or in ASCII (`IO::ASCII`).
//!
template <class CDT>
void write_vtu(std::ostream& os,
const CDT& tr,
IO::Mode mode = IO::BINARY);
}

View File

@ -11,6 +11,11 @@
/// \defgroup PkgMesh2Enum Enumerations
/// \ingroup PkgMesh2Ref
/// \defgroup PkgMesh2IO I/O Functions
/// \ingroup PkgMesh2Ref
/// In addition to the stream extraction and insertion operators for
/// %CGAL 2D triangulations, the following functions can be used.
/*!
\addtogroup PkgMesh2Ref
\cgalPkgDescriptionBegin{2D Conforming Triangulations and Meshes,PkgMesh2}
@ -58,6 +63,9 @@ The package can handle intersecting input constraints and set no restriction on
- `CGAL::refine_Delaunay_mesh_2`
- `CGAL::lloyd_optimize_mesh_2`
## I/O Functions ##
- `CGAL::write_vtu()`
## Enumerations ##
- `CGAL::Mesh_optimization_return_code`

View File

@ -0,0 +1,387 @@
// Copyright (c) 2018 GeometryFactory (France).
// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France).
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
//
// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno
#ifndef CGAL_WRITE_VTU_H
#define CGAL_WRITE_VTU_H
#include <CGAL/license/Mesh_2.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <CGAL/assertions.h>
#include <CGAL/IO/io.h>
//todo try to factorize with functors
namespace CGAL{
// writes the appended data into the .vtu file
template <class FT>
void
write_vector(std::ostream& os,
const std::vector<FT>& vect)
{
const char* buffer = reinterpret_cast<const char*>(&(vect[0]));
std::size_t size = vect.size()*sizeof(FT);
os.write(reinterpret_cast<const char *>(&size), sizeof(std::size_t)); // number of bytes encoded
os.write(buffer, vect.size()*sizeof(FT)); // encoded data
}
// writes the cells tags before binary data is appended
template <class CDT>
void
write_cells_tag_2(std::ostream& os,
const CDT & tr,
std::size_t number_of_triangles,
std::map<typename CDT::Vertex_handle, std::size_t> & V,
bool binary,
std::size_t& offset)
{
std::string formatattribute =
binary ? " format=\"appended\"" : " format=\"ascii\"";
std::string typeattribute;
switch(sizeof(std::size_t)) {
case 8: typeattribute = " type=\"UInt64\""; break;
case 4: typeattribute = " type=\"UInt32\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
// Write connectivity table
os << " <Cells>\n"
<< " <DataArray Name=\"connectivity\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
// 3 indices (size_t) per triangle + length of the encoded data (size_t)
offset += (3 * number_of_triangles + 1) * sizeof(std::size_t);
// 2 indices (size_t) per edge (size_t)
offset += (2 * std::distance(tr.constrained_edges_begin(),
tr.constrained_edges_end())) * sizeof(std::size_t);
}
else {
os << "\">\n";
for(typename CDT::Finite_faces_iterator
fit = tr.finite_faces_begin(),
end = tr.finite_faces_end();
fit != end; ++fit)
{
if(fit->is_in_domain())
{
os << V[fit->vertex(0)] << " ";
os << V[fit->vertex(2)] << " ";
os << V[fit->vertex(1)] << " ";
}
}
os << " </DataArray>\n";
}
// Write offsets
os << " <DataArray Name=\"offsets\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (number_of_triangles +std::distance(tr.constrained_edges_begin(),
tr.constrained_edges_end()) + 1)
* sizeof(std::size_t);
// 1 offset (size_t) per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
std::size_t cells_offset = 0;
for(typename CDT::Finite_faces_iterator fit =
tr.finite_faces_begin() ;
fit != tr.finite_faces_end() ;
++fit )
{
if(fit->is_in_domain())
{
cells_offset += 3;
os << cells_offset << " ";
}
}
os << " </DataArray>\n";
}
// Write cell type (triangles == 5)
os << " <DataArray Name=\"types\""
<< formatattribute << " type=\"UInt8\"";
if (binary) {
os << " offset=\"" << offset << "\"/>\n";
offset += number_of_triangles
+ std::distance(tr.constrained_edges_begin(),
tr.constrained_edges_end())
+ sizeof(std::size_t);
// 1 unsigned char per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
for(typename CDT::Finite_faces_iterator fit =
tr.finite_faces_begin() ;
fit != tr.finite_faces_end() ;
++fit )
{
if(fit->is_in_domain())
{
os << "5 ";
}
}
os << " </DataArray>\n";
}
os << " </Cells>\n";
}
// writes the cells appended data at the end of the .vtu file
template <class CDT>
void
write_cells_2(std::ostream& os,
const CDT & tr,
std::size_t number_of_triangles,
std::map<typename CDT::Vertex_handle, std::size_t> & V)
{
std::vector<std::size_t> connectivity_table;
std::vector<std::size_t> offsets;
std::vector<unsigned char> cell_type(number_of_triangles,5); // triangles == 5
cell_type.resize(cell_type.size() + std::distance(tr.constrained_edges_begin(),
tr.constrained_edges_end()), 3); // line == 3
std::size_t off = 0;
for(typename CDT::Finite_faces_iterator
fit = tr.finite_faces_begin(),
end = tr.finite_faces_end();
fit != end; ++fit)
{
if(fit->is_in_domain())
{
off += 3;
offsets.push_back(off);
connectivity_table.push_back(V[fit->vertex(0)]);
connectivity_table.push_back(V[fit->vertex(2)]);
connectivity_table.push_back(V[fit->vertex(1)]);
}
}
for(typename CDT::Constrained_edges_iterator
cei = tr.constrained_edges_begin(),
end = tr.constrained_edges_end();
cei != end; ++cei)
{
off += 2;
offsets.push_back(off);
for(int i=0; i<3; ++i)
{
if(i != cei->second)
connectivity_table.push_back(V[cei->first->vertex(i)]);
}
}
write_vector<std::size_t>(os,connectivity_table);
write_vector<std::size_t>(os,offsets);
write_vector<unsigned char>(os,cell_type);
}
// writes the points tags before binary data is appended
template <class Tr>
void
write_cdt_points_tag(std::ostream& os,
const Tr & tr,
std::map<typename Tr::Vertex_handle, std::size_t> & V,
bool binary,
std::size_t& offset)
{
std::size_t dim = 2;
typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
typedef typename Tr::Geom_traits Gt;
typedef typename Gt::FT FT;
std::size_t inum = 0;
std::string format = binary ? "appended" : "ascii";
std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32";
os << " <Points>\n"
<< " <DataArray type =\"" << type << "\" NumberOfComponents=\"3\" format=\""
<< format;
if (binary) {
os << "\" offset=\"" << offset << "\"/>\n";
offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t);
// dim coords per points + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( Finite_vertices_iterator vit = tr.finite_vertices_begin();
vit != tr.finite_vertices_end();
++vit)
{
V[vit] = inum++;
os << vit->point()[0] << " ";
os << vit->point()[1] << " ";
if(dim == 3)
os << vit->point()[2] << " ";
else
os << 0.0 << " ";
}
os << " </DataArray>\n";
}
os << " </Points>\n";
}
// writes the points appended data at the end of the .vtu file
template <class Tr>
void
write_cdt_points(std::ostream& os,
const Tr & tr,
std::map<typename Tr::Vertex_handle,
std::size_t> & V)
{
std::size_t dim = 2;
typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
typedef typename Tr::Geom_traits Gt;
typedef typename Gt::FT FT;
std::size_t inum = 0;
std::vector<FT> coordinates;
for( Finite_vertices_iterator vit = tr.finite_vertices_begin();
vit != tr.finite_vertices_end();
++vit)
{
V[vit] = inum++; // binary output => the map has not been filled yet
coordinates.push_back(vit->point()[0]);
coordinates.push_back(vit->point()[1]);
coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0);
}
write_vector<FT>(os,coordinates);
}
// writes the attribute tags before binary data is appended
template <class T>
void
write_attribute_tag_2 (std::ostream& os,
const std::string& attr_name,
const std::vector<T>& attribute,
bool binary,
std::size_t& offset)
{
std::string format = binary ? "appended" : "ascii";
std::string type = (sizeof(T) == 8) ? "Float64" : "Float32";
os << " <DataArray type=\"" << type << "\" Name=\"" << attr_name << "\" format=\"" << format;
if (binary) {
os << "\" offset=\"" << offset << "\"/>\n";
offset += attribute.size() * sizeof(T) + sizeof(std::size_t);
}
else {
typedef typename std::vector<T>::const_iterator Iterator;
os << "\">\n";
for (Iterator it = attribute.begin();
it != attribute.end();
++it )
os << *it << " ";
os << " </DataArray>\n";
}
}
// writes the attributes appended data at the end of the .vtu file
template <typename FT>
void
write_attributes_2(std::ostream& os,
const std::vector<FT>& att)
{
write_vector(os,att);
}
template <class CDT>
void write_vtu_with_attributes(std::ostream& os,
const CDT& tr,
std::vector<std::pair<const char*, const std::vector<double>*> >& attributes,
IO::Mode mode = IO::BINARY)
{
typedef typename CDT::Vertex_handle Vertex_handle;
std::map<Vertex_handle, std::size_t> V;
//write header
os << "<?xml version=\"1.0\"?>\n"
<< "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\"";
#ifdef CGAL_LITTLE_ENDIAN
os << " byte_order=\"LittleEndian\"";
#else // CGAL_BIG_ENDIAN
os << " byte_order=\"BigEndian\"";
#endif
switch(sizeof(std::size_t)) {
case 4: os << " header_type=\"UInt32\""; break;
case 8: os << " header_type=\"UInt64\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
os << ">\n"
<< " <UnstructuredGrid>" << "\n";
int number_of_triangles = 0;
for(typename CDT::Finite_faces_iterator
fit = tr.finite_faces_begin(),
end = tr.finite_faces_end();
fit != end; ++fit)
{
if(fit->is_in_domain()) ++number_of_triangles;
}
os << " <Piece NumberOfPoints=\"" << tr.number_of_vertices()
<< "\" NumberOfCells=\"" << number_of_triangles + std::distance(tr.constrained_edges_begin(), tr.constrained_edges_end()) << "\">\n";
std::size_t offset = 0;
const bool binary = (mode == IO::BINARY);
write_cdt_points_tag(os,tr,V,binary,offset);
write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset);
if(attributes.empty())
os << " <CellData >\n";
else
os << " <CellData Scalars=\""<<attributes.front().first<<"\">\n";
for(std::size_t i = 0; i< attributes.size(); ++i)
{
write_attribute_tag_2(os,attributes[i].first, *attributes[i].second, binary,offset);
}
os << " </CellData>\n";
os << " </Piece>\n"
<< " </UnstructuredGrid>\n";
if (binary) {
os << "<AppendedData encoding=\"raw\">\n_";
write_cdt_points(os,tr,V); // write points before cells to fill the std::map V
write_cells_2(os,tr, number_of_triangles, V);
for(std::size_t i = 0; i< attributes.size(); ++i)
write_attributes_2(os, *attributes[i].second);
}
os << "</VTKFile>\n";
}
template <class CDT>
void write_vtu(std::ostream& os,
const CDT& tr,
IO::Mode mode = IO::BINARY)
{
std::vector<std::pair<const char*, const std::vector<double>*> > dummy_atts;
write_vtu_with_attributes(os, tr, dummy_atts, mode);
}
} //end CGAL
#endif // CGAL_WRITE_VTU_H

View File

@ -0,0 +1,17 @@
namespace CGAL{
//! \ingroup PkgMesh3IOFunctions
//!
//! \brief writes a tetrahedron mesh using the `UnstructuredGrid` XML format.
//!
//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`.
//!
//! \param os the stream used for writing.
//! \param c3t3 the instance of `C3T3` to be written.
//! \param mode decides if the data should be written in binary (`IO::BINARY`)
//! or in ASCII (`IO::ASCII`).
//!
template <class C3T3>
void output_to_vtu(std::ostream& os,
const C3T3& c3t3,
IO::Mode mode = IO::BINARY);
}

View File

@ -1,5 +1,19 @@
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
# macros to be used inside the code
ALIASES += "cgalNamedParamsBegin=<dl class=\"params\"><dt>Named Parameters</dt><dd> <table class=\"params\">"
ALIASES += "cgalNamedParamsEnd=</table> </dd> </dl>"
ALIASES += "cgalParamBegin{1}=<tr><td class=\"paramname\">\ref PMP_\1 \"\1\"</td><td>"
ALIASES += "cgalParamEnd=</td></tr>"
ALIASES += "cgalDescribePolylineType=A polyline is defined as a sequence of points, each pair of contiguous points defines a segment of the polyline. If the first and last points of the polyline are identical, the polyline is closed."
#macros for NamedParameters.txt
ALIASES += "cgalNPTableBegin=<dl class=\"params\"><dt></dt><dd> <table class=\"params\">"
ALIASES += "cgalNPTableEnd=</table> </dd> </dl>"
ALIASES += "cgalNPBegin{1}=<tr><td class=\"paramname\">\1 </td><td>"
ALIASES += "cgalNPEnd=</td></tr>"
INPUT += \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Polyhedral_complex_mesh_domain_3.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_domain_with_polyline_features_3.h

View File

@ -139,6 +139,6 @@ and their associated classes:
## Input/Output Functions ##
- `CGAL::output_to_medit()`
- `CGAL::output_to_vtu()`
*/

View File

@ -50,7 +50,7 @@ output_c3t3_to_vtk_unstructured_grid(const C3T3& c3t3,
vtkCellArray* const vtk_facets = vtkCellArray::New();
vtkCellArray* const vtk_cells = vtkCellArray::New();
vtk_points->Allocate(c3t3.triangulation().number_of_vertices());
vtk_points->Allocate(c3t3.triangulation().number_of_vertices()- c3t3.number_of_far_points());
vtk_facets->Allocate(c3t3.number_of_facets_in_complex());
vtk_cells->Allocate(c3t3.number_of_cells_in_complex());
@ -64,12 +64,15 @@ output_c3t3_to_vtk_unstructured_grid(const C3T3& c3t3,
++vit)
{
typedef typename Triangulation::Weighted_point Weighted_point;
if(vit->in_dimension() > -1)
{
const Weighted_point& p = tr.point(vit);
vtk_points->InsertNextPoint(CGAL::to_double(p.x()),
CGAL::to_double(p.y()),
CGAL::to_double(p.z()));
V[vit] = inum++;
}
}
for(typename C3T3::Facets_in_complex_iterator
fit = c3t3.facets_in_complex_begin(),
end = c3t3.facets_in_complex_end();

View File

@ -0,0 +1,336 @@
// Copyright (c) 2018 GeometryFactory (France).
// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France).
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno
#ifndef CGAL_OUTPUT_TO_VTU_H
#define CGAL_OUTPUT_TO_VTU_H
#include <CGAL/license/Mesh_3.h>
#include <iostream>
#include <vector>
#include <map>
#include <CGAL/assertions.h>
#include <CGAL/IO/io.h>
#include <CGAL/IO/write_vtk.h>
//todo try to factorize with functors
namespace CGAL{
template <class C3T3>
void
write_cells_tag(std::ostream& os,
const C3T3 & c3t3,
std::map<typename C3T3::Triangulation::Vertex_handle, std::size_t> & V,
bool binary,
std::size_t& offset)
{
typedef typename C3T3::Cells_in_complex_iterator Cell_iterator;
std::string formatattribute =
binary ? " format=\"appended\"" : " format=\"ascii\"";
std::string typeattribute;
switch(sizeof(std::size_t)) {
case 8: typeattribute = " type=\"UInt64\""; break;
case 4: typeattribute = " type=\"UInt32\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
// Write connectivity table
os << " <Cells>\n"
<< " <DataArray Name=\"connectivity\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t);
// 4 indices (size_t) per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( Cell_iterator cit = c3t3.cells_in_complex_begin() ;
cit != c3t3.cells_in_complex_end() ;
++cit )
{
for (int i=0; i<4; i++)
os << V[cit->vertex(i)] << " ";
}
os << " </DataArray>\n";
}
// Write offsets
os << " <DataArray Name=\"offsets\""
<< formatattribute << typeattribute;
if (binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t);
// 1 offset (size_t) per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
std::size_t cells_offset = 0;
for( Cell_iterator cit = c3t3.cells_in_complex_begin() ;
cit != c3t3.cells_in_complex_end() ;
++cit )
{
cells_offset += 4;
os << cells_offset << " ";
}
os << " </DataArray>\n";
}
// Write cell type (tetrahedra == 10)
os << " <DataArray Name=\"types\""
<< formatattribute << " type=\"UInt8\"";
if (binary) {
os << " offset=\"" << offset << "\"/>\n";
offset += c3t3.number_of_cells() + sizeof(std::size_t);
// 1 unsigned char per cell + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( Cell_iterator cit = c3t3.cells_in_complex_begin() ;
cit != c3t3.cells_in_complex_end() ;
++cit )
os << "10 ";
os << " </DataArray>\n";
}
os << " </Cells>\n";
}
template <class C3T3>
void
write_cells(std::ostream& os,
const C3T3 & c3t3,
std::map<typename C3T3::Triangulation::Vertex_handle, std::size_t> & V)
{
typedef typename C3T3::Cells_in_complex_iterator Cell_iterator;
std::vector<std::size_t> connectivity_table;
std::vector<std::size_t> offsets;
std::vector<unsigned char> cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10
std::size_t off = 0;
for( Cell_iterator cit = c3t3.cells_in_complex_begin() ;
cit != c3t3.cells_in_complex_end() ;
++cit )
{
off += 4;
offsets.push_back(off);
for (int i=0; i<4; i++)
connectivity_table.push_back(V[cit->vertex(i)]);
}
write_vector<std::size_t>(os,connectivity_table);
write_vector<std::size_t>(os,offsets);
write_vector<unsigned char>(os,cell_type);
}
template <class Tr>
void
write_c3t3_points_tag(std::ostream& os,
const Tr & tr,
std::size_t size_of_vertices,
std::map<typename Tr::Vertex_handle, std::size_t> & V,
bool binary,
std::size_t& offset)
{
std::size_t dim = 3;
typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
typedef typename Tr::Geom_traits Gt;
typedef typename Gt::FT FT;
std::size_t inum = 0;
std::string format = binary ? "appended" : "ascii";
std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32";
os << " <Points>\n"
<< " <DataArray type =\"" << type << "\" NumberOfComponents=\"3\" format=\""
<< format;
if (binary) {
os << "\" offset=\"" << offset << "\"/>\n";
offset += 3 * size_of_vertices * sizeof(FT) + sizeof(std::size_t);
// dim coords per points + length of the encoded data (size_t)
}
else {
os << "\">\n";
for( Finite_vertices_iterator vit = tr.finite_vertices_begin();
vit != tr.finite_vertices_end();
++vit)
{
if(vit->in_dimension() <= -1) continue;
V[vit] = inum++;
os << vit->point()[0] << " ";
os << vit->point()[1] << " ";
if(dim == 3)
os << vit->point()[2] << " ";
else
os << 0.0 << " ";
}
os << " </DataArray>\n";
}
os << " </Points>\n";
}
// writes the points appended data at the end of the .vtu file
template <class Tr>
void
write_c3t3_points(std::ostream& os,
const Tr & tr,
std::map<typename Tr::Vertex_handle,
std::size_t> & V)
{
std::size_t dim = 3;
typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator;
typedef typename Tr::Geom_traits Gt;
typedef typename Gt::FT FT;
std::size_t inum = 0;
std::vector<FT> coordinates;
for( Finite_vertices_iterator vit = tr.finite_vertices_begin();
vit != tr.finite_vertices_end();
++vit)
{
if(vit->in_dimension() <= -1) continue;
V[vit] = inum++; // binary output => the map has not been filled yet
coordinates.push_back(vit->point()[0]);
coordinates.push_back(vit->point()[1]);
coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0);
}
write_vector<FT>(os,coordinates);
}
// writes the attribute tags before binary data is appended
template <class T>
void
write_attribute_tag(std::ostream& os,
const std::string& attr_name,
const std::vector<T>& attribute,
bool binary,
std::size_t& offset)
{
std::string format = binary ? "appended" : "ascii";
std::string type = (sizeof(T) == 8) ? "Float64" : "Float32";
os << " <DataArray type=\"" << type << "\" Name=\"" << attr_name << "\" format=\"" << format;
if (binary) {
os << "\" offset=\"" << offset << "\"/>\n";
offset += attribute.size() * sizeof(T) + sizeof(std::size_t);
}
else {
typedef typename std::vector<T>::const_iterator Iterator;
os << "\">\n";
for (Iterator it = attribute.begin();
it != attribute.end();
++it )
os << *it << " ";
os << " </DataArray>\n";
}
}
// writes the attributes appended data at the end of the .vtu file
template <typename FT>
void
write_attributes(std::ostream& os,
const std::vector<FT>& att)
{
write_vector(os,att);
}
template <class C3T3>
void output_to_vtu_with_attributes(std::ostream& os,
const C3T3& c3t3,
std::vector<std::pair<const char*, const std::vector<double>*> >& attributes,
IO::Mode mode = IO::BINARY)
{
typedef typename C3T3::Triangulation Tr;
typedef typename Tr::Vertex_handle Vertex_handle;
const Tr& tr = c3t3.triangulation();
std::map<Vertex_handle, std::size_t> V;
//write header
os << "<?xml version=\"1.0\"?>\n"
<< "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\"";
#ifdef CGAL_LITTLE_ENDIAN
os << " byte_order=\"LittleEndian\"";
#else // CGAL_BIG_ENDIAN
os << " byte_order=\"BigEndian\"";
#endif
switch(sizeof(std::size_t)) {
case 4: os << " header_type=\"UInt32\""; break;
case 8: os << " header_type=\"UInt64\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
os << ">\n"
<< " <UnstructuredGrid>" << "\n";
const std::size_t number_of_vertices =
tr.number_of_vertices() - c3t3.number_of_far_points();
os << " <Piece NumberOfPoints=\"" << number_of_vertices
<< "\" NumberOfCells=\"" << c3t3.number_of_cells() << "\">\n";
std::size_t offset = 0;
const bool binary = (mode == IO::BINARY);
write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset);
write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII
os << " <CellData Scalars=\""<<attributes.front().first<<"\">\n";
for(std::size_t i = 0; i< attributes.size(); ++i)
{
write_attribute_tag(os,attributes[i].first, *attributes[i].second, binary,offset);
}
os << " </CellData>\n";
os << " </Piece>\n"
<< " </UnstructuredGrid>\n";
if (binary) {
os << "<AppendedData encoding=\"raw\">\n_";
write_c3t3_points(os,tr,V); // fills V if the mode is BINARY
write_cells(os,c3t3,V);
for(std::size_t i = 0; i< attributes.size(); ++i)
write_attributes(os, *attributes[i].second);
}
os << "</VTKFile>\n";
}
//public API
template <class C3T3>
void output_to_vtu(std::ostream& os,
const C3T3& c3t3,
IO::Mode mode = IO::BINARY)
{
typedef typename C3T3::Cells_in_complex_iterator Cell_iterator;
std::vector<double> mids;
for( Cell_iterator cit = c3t3.cells_in_complex_begin() ;
cit != c3t3.cells_in_complex_end() ;
++cit )
{
mids.push_back(cit->subdomain_index());
}
std::vector<std::pair<const char*, const std::vector<double>* > > atts;
atts.push_back(std::make_pair("MeshDomain", &mids));
output_to_vtu_with_attributes(os, c3t3, atts, mode);
}
} //end CGAL
#endif // CGAL_VTK_IO_H

View File

@ -45,6 +45,8 @@
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/property_map.h>
#include <CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h>
#include <CGAL/IO/output_to_vtu.h>
#include <CGAL/boost/graph/io.h>
#include <vtkSmartPointer.h>
#include <vtkDataSetReader.h>
@ -52,6 +54,7 @@
#include <vtkPolyDataWriter.h>
#include <vtkUnstructuredGrid.h>
#include <vtkXMLUnstructuredGridReader.h>
#include <vtkXMLUnstructuredGridWriter.h>
#include <vtkXMLPolyDataWriter.h>
#include <vtkPolyData.h>
#include <vtkIdTypeArray.h>
@ -71,10 +74,16 @@
#include <vtkCommand.h>
#include <vtkXMLUnstructuredGridWriter.h>
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
typedef Scene_surface_mesh_item Scene_facegraph_item;
typedef Scene_facegraph_item::Face_graph FaceGraph;
typedef boost::property_traits<boost::property_map<FaceGraph, CGAL::vertex_point_t>::type>::value_type Point;
typedef boost::property_traits<boost::property_map<FaceGraph,
CGAL::vertex_point_t>::type>::value_type Point;
namespace CGAL{
class ErrorObserverVtk : public vtkCommand
@ -237,13 +246,13 @@ namespace CGAL{
cell->Delete();
}
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkUnstructuredGrid> usg =
vtkSmartPointer<vtkUnstructuredGrid>::New();
polydata->SetPoints(vtk_points);
usg->SetPoints(vtk_points);
vtk_points->Delete();
polydata->SetPolys(vtk_cells);
usg->SetCells(5,vtk_cells);
vtk_cells->Delete();
// Combine the two data sets
@ -260,7 +269,7 @@ namespace CGAL{
vtkSmartPointer<VtkWriter> writer =
vtkSmartPointer<VtkWriter>::New();
writer->SetFileName(filename);
writer->SetInputData(polydata);
writer->SetInputData(usg);
writer->Write();
}
}//end namespace CGAL
@ -287,6 +296,8 @@ public:
return (qobject_cast<const Scene_facegraph_item*>(item)
|| qobject_cast<const Scene_c3t3_item*>(item));
}
bool save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
{
std::string extension = fileinfo.suffix().toLower().toStdString();
@ -301,13 +312,26 @@ public:
if (poly_item)
{
if (extension != "vtp")
CGAL::polygon_mesh_to_vtkUnstructured<vtkPolyDataWriter>(
{
if(!CGAL::is_triangle_mesh(*poly_item->polyhedron()))
{
QMessageBox::warning(0, "Error",
"Cannot save a mesh in vtu format if "
"it is not pure triangle.");
return false;
}
CGAL::polygon_mesh_to_vtkUnstructured<vtkXMLUnstructuredGridWriter>(
*poly_item->polyhedron(),
output_filename.data());
}
else
CGAL::polygon_mesh_to_vtkUnstructured<vtkXMLPolyDataWriter>(
*poly_item->polyhedron(),
output_filename.data());
{
const FaceGraph* mesh = poly_item->face_graph();
std::ofstream os(output_filename.data());
os << std::setprecision(16);
//write header
CGAL::write_vtp(os, *mesh);
}
}
else
{
@ -316,11 +340,11 @@ public:
if(!c3t3_item || extension != "vtu")
return false;
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName( output_filename.data());
writer->SetInputData(CGAL::output_c3t3_to_vtk_unstructured_grid(c3t3_item->c3t3()));
writer->Write();
std::ofstream os(output_filename.data());
os << std::setprecision(16);
const C3t3& c3t3 = c3t3_item->c3t3();
CGAL::output_to_vtu(os, c3t3);
}
return true;
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2018
// GeometryFactory( France) All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
//
// Author(s) : Stephane Tayeb
#ifndef CGAL_WRITE_VTK_IO_H
#define CGAL_WRITE_VTK_IO_H
#include <CGAL/license/Polyhedron.h>
#include <fstream>
#include <vector>
template <class FT>
void
write_vector(std::ostream& os,
const std::vector<FT>& vect)
{
const char* buffer = reinterpret_cast<const char*>(&(vect[0]));
std::size_t size = vect.size()*sizeof(FT);
os.write(reinterpret_cast<const char *>(&size), sizeof(std::size_t)); // number of bytes encoded
os.write(buffer, vect.size()*sizeof(FT)); // encoded data
}
#endif