mirror of https://github.com/CGAL/cgal
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:
commit
9a03d47cb0
|
|
@ -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} \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()`
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -84,12 +85,12 @@ discoverInfiniteComponent(const CDT & ct)
|
|||
Face_handle fh = queue.front();
|
||||
queue.pop_front();
|
||||
fh->set_in_domain(false);
|
||||
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
Face_handle fi = fh->neighbor(i);
|
||||
if(fi->is_in_domain()
|
||||
&& !ct.is_constrained(CDT::Edge(fh,i)))
|
||||
&& !ct.is_constrained(CDT::Edge(fh,i)))
|
||||
queue.push_back(fi);
|
||||
}
|
||||
}
|
||||
|
|
@ -269,7 +270,7 @@ MainWindow::MainWindow()
|
|||
dgi->setFacesInDomainBrush(facesColor);
|
||||
|
||||
QObject::connect(this, SIGNAL(changed()),
|
||||
dgi, SLOT(modelChanged()));
|
||||
dgi, SLOT(modelChanged()));
|
||||
dgi->setVerticesPen(
|
||||
QPen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
dgi->setVoronoiPen(
|
||||
|
|
@ -285,8 +286,8 @@ MainWindow::MainWindow()
|
|||
// the signal/slot mechanism
|
||||
pi = new CGAL::Qt::GraphicsViewPolylineInput<K>(this, &scene, 0, true); // inputs polylines which are not closed
|
||||
QObject::connect(pi, SIGNAL(generate(CGAL::Object)),
|
||||
this, SLOT(processInput(CGAL::Object)));
|
||||
|
||||
this, SLOT(processInput(CGAL::Object)));
|
||||
|
||||
tcc = new CGAL::Qt::TriangulationCircumcircle<CDT>(&scene, &cdt, this);
|
||||
tcc->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
|
||||
|
|
@ -298,8 +299,8 @@ MainWindow::MainWindow()
|
|||
// Manual handling of actions
|
||||
//
|
||||
QObject::connect(this->actionQuit, SIGNAL(triggered()),
|
||||
this, SLOT(close()));
|
||||
|
||||
this, SLOT(close()));
|
||||
|
||||
// We put mutually exclusive actions in an QActionGroup
|
||||
QActionGroup* ag = new QActionGroup(this);
|
||||
ag->addAction(this->actionInsertPolyline);
|
||||
|
|
@ -338,7 +339,7 @@ MainWindow::MainWindow()
|
|||
|
||||
this->addRecentFiles(this->menuFile, this->actionQuit);
|
||||
connect(this, SIGNAL(openRecentFile(QString)),
|
||||
this, SLOT(open(QString)));
|
||||
this, SLOT(open(QString)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -534,11 +535,11 @@ void
|
|||
MainWindow::on_actionLoadConstraints_triggered()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open Constraint File"),
|
||||
".",
|
||||
tr("Edge files (*.edg);;"
|
||||
tr("Open Constraint File"),
|
||||
".",
|
||||
tr("Edge files (*.edg);;"
|
||||
"Plg files (*.plg);;"
|
||||
"Poly files (*.poly)"));
|
||||
"Poly files (*.poly)"));
|
||||
open(fileName);
|
||||
}
|
||||
|
||||
|
|
@ -655,12 +656,13 @@ void
|
|||
MainWindow::on_actionSaveConstraints_triggered()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this,
|
||||
tr("Save Constraints"),
|
||||
".",
|
||||
tr("Poly files (*.poly)\n"
|
||||
"Edge files (*.edg)"));
|
||||
tr("Save Constraints"),
|
||||
".",
|
||||
tr("Poly files (*.poly)\n"
|
||||
"Edge files (*.edg)\n"
|
||||
"VTU files (*.vtu)"));
|
||||
if(! fileName.isEmpty()){
|
||||
saveConstraints(fileName);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -796,15 +804,15 @@ MainWindow::on_actionInsertRandomPoints_triggered()
|
|||
bool ok = false;
|
||||
|
||||
const int number_of_points =
|
||||
QInputDialog::getInt(this,
|
||||
tr("Number of random points"),
|
||||
tr("Enter number of random points"),
|
||||
100,
|
||||
0,
|
||||
(std::numeric_limits<int>::max)(),
|
||||
1,
|
||||
&ok);
|
||||
|
||||
QInputDialog::getInt(this,
|
||||
tr("Number of random points"),
|
||||
tr("Enter number of random points"),
|
||||
100,
|
||||
0,
|
||||
(std::numeric_limits<int>::max)(),
|
||||
1,
|
||||
&ok);
|
||||
|
||||
if(!ok) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -139,6 +139,6 @@ and their associated classes:
|
|||
|
||||
## Input/Output Functions ##
|
||||
- `CGAL::output_to_medit()`
|
||||
|
||||
- `CGAL::output_to_vtu()`
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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,11 +64,14 @@ output_c3t3_to_vtk_unstructured_grid(const C3T3& c3t3,
|
|||
++vit)
|
||||
{
|
||||
typedef typename Triangulation::Weighted_point Weighted_point;
|
||||
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++;
|
||||
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(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -315,12 +339,12 @@ public:
|
|||
qobject_cast<const Scene_c3t3_item*>(item);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue