From 423ae6ec843cb404597d501638d1f885c69f1cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 24 Jan 2020 17:48:02 +0100 Subject: [PATCH] Re-organize and improve BGL IO --- BGL/include/CGAL/boost/graph/IO/GOCAD.h | 287 ++++ .../graph/IO/Generic_facegraph_builder.h | 99 ++ BGL/include/CGAL/boost/graph/IO/INP.h | 96 ++ BGL/include/CGAL/boost/graph/IO/OBJ.h | 228 ++++ BGL/include/CGAL/boost/graph/IO/OFF.h | 289 ++++ BGL/include/CGAL/boost/graph/IO/STL.h | 218 +++ BGL/include/CGAL/boost/graph/IO/VTK.h | 431 ++++++ BGL/include/CGAL/boost/graph/IO/WRL.h | 125 ++ BGL/include/CGAL/boost/graph/io.h | 1204 +---------------- Stream_support/include/CGAL/IO/OBJ.h | 19 +- .../CGAL/IO/OBJ/File_writer_wavefront.h | 8 +- Stream_support/include/CGAL/IO/STL.h | 16 +- .../include/CGAL/IO/STL/STL_reader.h | 4 +- Stream_support/include/CGAL/IO/VTK.h | 3 +- .../include/CGAL/IO/VTK/VTK_reader.h | 73 + .../include/CGAL/IO/VTK/VTK_writer.h | 68 +- .../CGAL/internal/Generic_facegraph_builder.h | 60 - 17 files changed, 1883 insertions(+), 1345 deletions(-) create mode 100644 BGL/include/CGAL/boost/graph/IO/GOCAD.h create mode 100644 BGL/include/CGAL/boost/graph/IO/Generic_facegraph_builder.h create mode 100644 BGL/include/CGAL/boost/graph/IO/INP.h create mode 100644 BGL/include/CGAL/boost/graph/IO/OBJ.h create mode 100644 BGL/include/CGAL/boost/graph/IO/OFF.h create mode 100644 BGL/include/CGAL/boost/graph/IO/STL.h create mode 100644 BGL/include/CGAL/boost/graph/IO/VTK.h create mode 100644 BGL/include/CGAL/boost/graph/IO/WRL.h delete mode 100644 Stream_support/include/CGAL/internal/Generic_facegraph_builder.h diff --git a/BGL/include/CGAL/boost/graph/IO/GOCAD.h b/BGL/include/CGAL/boost/graph/IO/GOCAD.h new file mode 100644 index 00000000000..1f2ed4feff2 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/GOCAD.h @@ -0,0 +1,287 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_GOCAD_H +#define CGAL_BGL_IO_GOCAD_H + +#include + +#include +#include + +#include + +#include +#include + +namespace CGAL { + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Read + +namespace IO { +namespace internal { + +// Use CRTP to gain access to the protected members without getters/setters. +template +class GOCAD_builder + : public Generic_facegraph_builder > +{ + typedef GOCAD_builder Self; + typedef Generic_facegraph_builder Base; + + typedef typename Base::Point_container Point_container; + typedef typename Base::Face Face; + typedef typename Base::Face_container Face_container; + +public: + GOCAD_builder(std::istream& is_) : Base(is_) { } + + // Implementation of the two functions required by the generic builder + bool read(std::istream& input, + Point_container& points, + Face_container& faces) + { + int offset = 0; + char c; + std::string s, tface("TFACE"); + int i,j,k; + Point p; + bool vertices_read = false; + + while(input >> s) + { + if(s == tface) + break; + + std::string::size_type idx; + if((idx = s.find("name")) != std::string::npos) + { + std::istringstream str(s.substr(idx + 5)); + str >> this->name; + } + + if((idx = s.find("color")) != std::string::npos) + { + std::istringstream str(s.substr(idx + 6)); + str >> this->color; + } + } + std::getline(input, s); + + while(input.get(c)) + { + if((c == 'V') || (c == 'P')) + { + input >> s >> i >> p; // @fixme check for failure + if(!vertices_read) + { + vertices_read = true; + offset -= i; // Some files start with index 0 others with 1 + } + + points.push_back(p); + } + else if(vertices_read && (c == 'T')) + { + input >> c >> c >> c >> i >> j >> k; + typename Base::Face new_face(3); + new_face[0] = offset+i; + new_face[1] = offset+j; + new_face[2] = offset+k; + faces.push_back(new_face); + } + else if(c == 'E') + { + break; + } + + std::getline(input, s); + } + + return true; + } +}; + +} // namespace internal +} // namespace IO + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from data in the TS format. + `name` and `color` will be filled according to the values contained in the file. + + \pre The data must represent a 2-manifold + + \attention The graph `g` is not cleared, and the data from the stream are added. + + \see \ref IOStreamGocad +*/ +template +bool read_GOCAD(std::istream& in, + std::string& name, + std::string& color, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename CGAL::GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; + + IO::internal::GOCAD_builder builder(in); + if(!builder(g, np)) + return false; + + name = builder.name; + color = builder.color; + + return g.is_valid(); // @fixme keep validity check? +} + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from data in the TS format. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \pre The data must represent a 2-manifold + + \see \ref IOStreamGOCAD +*/ +template +bool read_GOCAD(const char* fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + std::ifstream in(fname); + std::string unused_name; + std::string unused_color; + + return read_GOCAD(in, unused_name, unused_color, g, np); +} + +template +bool read_GOCAD(const std::string& fname, FaceGraph& g, CGAL_BGL_NP_CLASS np) +{ + return read_GOCAD(fname.c_str(), g, np); +} + +template +bool read_GOCAD(std::istream& is, FaceGraph& g) { return read_GOCAD(is, g, parameters::all_default()); } +template +bool read_GOCAD(const char* fname, FaceGraph& g) { return read_GOCAD(fname, g, parameters::all_default()); } +template +bool read_GOCAD(const std::string& fname, FaceGraph& g) { return read_GOCAD(fname, g, parameters::all_default()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Write + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the TS format into `os`. `fname` is the + mandatory name that will be assigned to `g`in the file. + + \see \ref IOStreamGocad +*/ +template +bool write_GOCAD(std::ostream& os, + const char* fname, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + + using parameters::choose_parameter; + using parameters::get_parameter; + + typename CGAL::GetVertexPointMap::const_type + vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + if(!os.good()) + return false; + + os << "GOCAD TSurf 1\n" + "HEADER {\n" + "name:"; + os << fname << std::endl; + os << "*border:on\n" + "*border*bstone:on\n" + "}\n" + "GOCAD_ORIGINAL_COORDINATE_SYSTEM\n" + "NAME Default\n" + "AXIS_NAME \"X\" \"Y\" \"Z\"\n" + "AXIS_UNIT \"m\" \"m\" \"m\"\n" + "ZPOSITIVE Elevation\n" + "END_ORIGINAL_COORDINATE_SYSTEM\n" + "TFACE\n"; + + os.precision(16); + + boost::container::flat_map reindex; + + vertices_size_type i = 0; + for(const vertex_descriptor v : vertices(g)) + { + os << "VRTX " << i << " " << get(vpm, v) << "\n"; + reindex[v] = i++; + } + + for(const face_descriptor f : faces(g)) + { + halfedge_descriptor h = halfedge(f, g); + os << "TRGL " << reindex[target(prev(h, g), g)] << " " + << reindex[target(h, g)] << " " + << reindex[target(next(h, g), g)] << "\n"; + } + + os << "END" << std::endl; + + return os.good(); +} + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the TS format into a file named `fname`. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \see \ref IOStreamGOCAD +*/ +template +bool write_GOCAD(const char* fname, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ofstream out(fname); + return write_GOCAD(out, fname, g, np); +} + +template +bool write_GOCAD(const std::string& fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return write_GOCAD(fname.c_str(), g, np); +} + +template +bool write_GOCAD(const char* fname, const FaceGraph& g) { return write_GOCAD(fname, g, parameters::all_default()); } +template +bool write_GOCAD(const std::string& fname, const FaceGraph& g) { return write_GOCAD(fname, g, parameters::all_default()); } + +} // namespace CGAL + +#endif // CGAL_BGL_IO_GOCAD_H diff --git a/BGL/include/CGAL/boost/graph/IO/Generic_facegraph_builder.h b/BGL/include/CGAL/boost/graph/IO/Generic_facegraph_builder.h new file mode 100644 index 00000000000..8ebf93371e1 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/Generic_facegraph_builder.h @@ -0,0 +1,99 @@ +// Copyright (c) 2019 GeometryFactory +// +// This file is part of CGAL (www.cgal.org); +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Maxime Gimeno + +#ifndef CGAL_BGL_IO_GENERIC_FACEGRAPH_BUILDER_H +#define CGAL_BGL_IO_GENERIC_FACEGRAPH_BUILDER_H + +#include + +#include +#include +#include + +namespace CGAL{ +namespace IO { +namespace internal { + +template +class Generic_facegraph_builder +{ +protected: + typedef std::vector Point_container; + typedef typename Point_container::size_type size_type; + typedef std::vector Face; + typedef std::vector Face_container; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + +public: + Generic_facegraph_builder(std::istream& in_) : m_in(in_) { } + + // must be implemented by the derived class + bool read() + { + if(!m_in.good()) + return false; + + return static_cast(this)->read(m_in, m_points, m_faces); + } + + template + bool construct(FaceGraph& g, + const NamedParameters& np) + { + typedef typename CGAL::GetVertexPointMap::type VPM; + VPM vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_property_map(CGAL::vertex_point, g)); + + std::vector vertices(m_points.size()); + for(std::size_t id = 0, ps=m_points.size(); id face(m_faces[i].size()); + for(std::size_t j=0, fs=face.size(); j::null_face()) + return false; + } + + return is_valid_polygon_mesh(g); + } + + template + bool operator()(FaceGraph& g, const NamedParameters& np) + { + if(!read()) + return false; + + return construct(g, np); + } + + std::string name, color; + +protected: + std::istream& m_in; + + Point_container m_points; + Face_container m_faces; +}; + +} // end internal +} // end IO +} // end CGAL + +#endif // CGAL_BGL_IO_GENERIC_FACEGRAPH_BUILDER_H diff --git a/BGL/include/CGAL/boost/graph/IO/INP.h b/BGL/include/CGAL/boost/graph/IO/INP.h new file mode 100644 index 00000000000..fe589a5689b --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/INP.h @@ -0,0 +1,96 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_INP_H +#define CGAL_BGL_IO_INP_H + +#include +#include +#include + +#include + +namespace CGAL { + +template +bool write_INP(std::ostream& os, + std::string name, + std::string type, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + + typedef typename CGAL::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + + using parameters::choose_parameter; + using parameters::get_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + if(!os.good()) + return false; + + os << "*Part, name=" << name << "\n*Node\n"; + boost::container::flat_map reindex; + int n = 1; + for(const vertex_descriptor v : vertices(g)) + { + Point_ref p = get(vpm,v); + os << n << ", " << p.x() << ", " << p.y() << ", " << p.z() << '\n'; + reindex[v] = n++; + } + + n = 1; + os << "*Element, type=" << type << std::endl; + for(const face_descriptor f : faces(g)) + { + os << n++; + for(const vertex_descriptor v : CGAL::vertices_around_face(halfedge(f, g), g)) + os << ", " << reindex[v]; + + os << '\n'; + } + + os << "*End Part"<< std::endl; + + return os.good(); +} + +template +bool write_INP(const char* fname, + const std::string type, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ofstream out(fname); + return write_INP(out, fname, type, g, np); +} + +template +bool write_INP(std::ostream& os, std::string name, std::string type, const FaceGraph& g) +{ + return write_INP(os, name, type, g, parameters::all_default()); +} + +template +bool write_INP(const char* fname, const std::string type, const FaceGraph& g) +{ + return write_INP(fname, type, g, parameters::all_default()); +} + +} // namespace CGAL + +#endif // CGAL_BGL_IO_INP_H diff --git a/BGL/include/CGAL/boost/graph/IO/OBJ.h b/BGL/include/CGAL/boost/graph/IO/OBJ.h new file mode 100644 index 00000000000..59fd1f0b9ac --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/OBJ.h @@ -0,0 +1,228 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_OBJ_H +#define CGAL_BGL_IO_OBJ_H + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Read + +namespace IO { +namespace internal { + +// Use CRTP to gain access to the protected members without getters/setters. +template +class OBJ_builder + : public Generic_facegraph_builder > +{ + typedef OBJ_builder Self; + typedef Generic_facegraph_builder Base; + + typedef typename Base::Point_container Point_container; + typedef typename Base::Face Face; + typedef typename Base::Face_container Face_container; + +public: + OBJ_builder(std::istream& is_) : Base(is_) { } + + // Implementation of the two functions required by the generic builder + bool read(std::istream& input, Point_container& points, Face_container& faces) + { + return read_OBJ(input, points, faces); + } +}; + +} // namespace internal +} // namespace IO + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from the stream `in` in the OBJ format. + + \returns `true` if the resulting mesh is valid. + + \pre The data must represent a 2-manifold + + \see \ref IOStreamOBJ +*/ +template +bool read_OBJ(std::istream& in, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename CGAL::GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; + + IO::internal::OBJ_builder builder(in); + return builder(g, np); +} + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from data in the OFF format. Ignores comment lines which start with a hash, + and lines with whitespace. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \pre The data must represent a 2-manifold + + \attention The graph `g` is not cleared, and the data from the stream are added. + + \see \ref IOStreamOFF +*/ +template +bool read_OBJ(const char* fname, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ifstream in(fname); + return read_OBJ(in, g, np); +} + +template +bool read_OBJ(const std::string& fname, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + return read_OBJ(fname.c_str(), g, np); +} + +template +bool read_OBJ(std::istream& is, FaceGraph& g) { return read_OBJ(is, g, parameters::all_default()); } +template +bool read_OBJ(const char* fname, FaceGraph& g) { return read_OBJ(fname, g, parameters::all_default()); } +template +bool read_OBJ(const std::string& fname, FaceGraph& g) { return read_OBJ(fname, g, parameters::all_default()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Write + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the OBJ format. + + \returns `true` if writing was successful. + + \see \ref IOStreamOBJ +*/ +template +bool write_OBJ(std::ostream& os, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename CGAL::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + + VPM vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + if(!os.good()) + return false; + + CGAL::File_writer_wavefront writer; + writer.write_header(os, num_vertices(g), num_halfedges(g), num_faces(g)); + + boost::container::flat_map index_map; + vertices_size_type id = 0; + + for(vertex_descriptor v : vertices(g)) + { + Point_ref p = get(vpm, v); + writer.write_vertex(::CGAL::to_double(p.x()), + ::CGAL::to_double(p.y()), + ::CGAL::to_double(p.z())); + index_map[v] = id++; + } + + writer.write_facet_header(); + for(face_descriptor f : faces(g)) + { + CGAL::Halfedge_around_face_circulator hc(halfedge(f, g), g); + CGAL::Halfedge_around_face_circulator hc_end = hc; + + const std::size_t n = circulator_size(hc); + CGAL_assertion(n >= 3); + + writer.write_facet_begin(n); + do + { + writer.write_facet_vertex_index(index_map[target(*hc, g)]); + ++hc; + } + while(hc != hc_end); + + writer.write_facet_end(); + } + writer.write_footer(); + + return os.good(); +} + +/*! +\ingroup PkgBGLIOFct + + writes the graph `g` in the OFF format into a file named `fname`. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \see \ref IOStreamOFF +*/ +template +bool write_OBJ(const char* fname, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ofstream out(fname); + return write_OBJ(out, g, np); +} + +template +bool write_OBJ(const std::string& fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return write_OBJ(fname.c_str(), g, np); +} + +template +bool write_OBJ(std::ostream& os, const FaceGraph& g) { return write_OBJ(os, g, parameters::all_default()); } +template +bool write_OBJ(const char* fname, const FaceGraph& g) { return write_OBJ(fname, g, parameters::all_default()); } +template +bool write_OBJ(const std::string& fname, const FaceGraph& g) { return write_OBJ(fname, g, parameters::all_default()); } + +} // namespace CGAL + +#endif // CGAL_BGL_IO_OBJ_H diff --git a/BGL/include/CGAL/boost/graph/IO/OFF.h b/BGL/include/CGAL/boost/graph/IO/OFF.h new file mode 100644 index 00000000000..590fce8c091 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/OFF.h @@ -0,0 +1,289 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_BGL_IO_OFF_H +#define CGAL_BGL_IO_OFF_H + +#include +#include +#include +#include + +#include + +#include +#include +#include + +// @todo reintroduce deprecated versions of the functions using lower case file formats + +namespace CGAL { + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Read + +namespace IO { +namespace internal { +namespace read_off_tools { + +inline bool is_whitespace(const std::string& s) +{ + for(unsigned int i=0; i +bool read_OFF(std::istream& is, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::faces_size_type faces_size_type; + + typedef typename CGAL::GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; + + using namespace IO::internal::read_off_tools; + + using parameters::choose_parameter; + using parameters::get_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_property_map(CGAL::vertex_point, g)); + + vertices_size_type nv, nvf; + faces_size_type nf; + int ignore; + + std::string line = next_non_comment(is); + { + std::istringstream iss(line); + std::string off; + iss >> off; + CGAL_assertion( off == "OFF" || off == "COFF"); + } + + line = next_non_comment(is); + { + std::istringstream iss(line); + iss >> nv >> nf >> ignore; + } + + std::vector vertices(nv); + Point p; + + for(vertices_size_type i=0; i> p; + vertices[i] = add_vertex(g); + put(vpm, vertices[i], p); + } + + for(faces_size_type i=0; i> nvf; + std::vector face(nvf); + for(vertices_size_type j=0; j> fvi; + face[j] = vertices[fvi]; + } + + face_descriptor f = CGAL::Euler::add_face(face, g); + if(f == boost::graph_traits::null_face()) + return false; + } + + return true; +} + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from data in the OFF format. Ignores comment lines which start with a hash, + and lines with whitespace. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \pre The data must represent a 2-manifold + + \attention The graph `g` is not cleared, and the data from the stream are added. + + \see \ref IOStreamOFF +*/ +template +bool read_OFF(const char* fname, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ifstream in(fname); + return read_OFF(in, g, np); +} + +template +bool read_OFF(const std::string& fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return read_OFF(fname.c_str(), g, np); +} + +template +bool read_OFF(std::istream& is, FaceGraph& g) { return read_OFF(is, g, parameters::all_default()); } +template +bool read_OFF(const char* fname, FaceGraph& g) { return read_OFF(fname, g, parameters::all_default()); } +template +bool read_OFF(const std::string& fname, FaceGraph& g) { return read_OFF(fname, g, parameters::all_default()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Write + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the OFF format. + + \cgalNamedParamsBegin + \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`. + If this parameter is omitted, an internal property map for + `CGAL::vertex_point_t` should be available in `FaceGraph` + \cgalParamEnd + \cgalNamedParamsEnd + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \see \ref IOStreamOFF +*/ +template +bool write_OFF(std::ostream& os, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::faces_size_type faces_size_type; + + using parameters::choose_parameter; + using parameters::get_parameter; + + typename CGAL::GetVertexPointMap::const_type + vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + vertices_size_type nv = static_cast(std::distance(vertices(g).first, vertices(g).second)); + faces_size_type nf = static_cast(std::distance(faces(g).first, faces(g).second)); + + if(!os.good()) + return false; + + os << "OFF\n" + << nv << " " << nf << " 0\n"; + + boost::container::flat_map reindex; + int n = 0; + for(vertex_descriptor v : vertices(g)) + { + os << get(vpm, v) << '\n'; + reindex[v] = n++; + } + + for(face_descriptor f : faces(g)) + { + os << degree(f, g); + for(vertex_descriptor v : vertices_around_face(halfedge(f, g), g)) + os << " " << reindex[v]; + os << '\n'; + } + + return os.good(); +} + +/*! +\ingroup PkgBGLIOFct + + writes the graph `g` in the OFF format into a file named `fname`. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \see \ref IOStreamOFF +*/ +template +bool write_OFF(const char* fname, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + std::ofstream out(fname); + return write_OFF(out, g, np); +} + +template +bool write_OFF(const std::string& fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return write_OFF(fname.c_str(), g, np); +} + +template +bool write_OFF(std::ostream& os, const FaceGraph& g) { return write_OFF(os, g, parameters::all_default()); } +template +bool write_OFF(const char* fname, const FaceGraph& g) { return write_OFF(fname, g, parameters::all_default()); } +template +bool write_OFF(const std::string& fname, const FaceGraph& g) { return write_OFF(fname, g, parameters::all_default()); } + +} // namespace CGAL + +#endif // CGAL_BGL_IO_OFF_H diff --git a/BGL/include/CGAL/boost/graph/IO/STL.h b/BGL/include/CGAL/boost/graph/IO/STL.h new file mode 100644 index 00000000000..65b6ab2d4fc --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/STL.h @@ -0,0 +1,218 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_STL_H +#define CGAL_BGL_IO_STL_H + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace CGAL { + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Read + +namespace IO { +namespace internal { + +// Use CRTP to gain access to the protected members without getters/setters. +template +class STL_builder + : public Generic_facegraph_builder > +{ + typedef STL_builder Self; + typedef Generic_facegraph_builder Base; + + typedef typename Base::Point_container Point_container; + typedef typename Base::Face Face; + typedef typename Base::Face_container Face_container; + +public: + STL_builder(std::istream& is_) : Base(is_) { } + + bool read(std::istream& input, Point_container& points, Face_container& faces) + { + return read_STL(input, points, faces); + } +}; + +} // namespace internal +} // namespace IO + +template +bool read_STL(std::istream& in, + FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename CGAL::GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; + + IO::internal::STL_builder builder(in); + return builder(g, np); +} + +/*! + \ingroup PkgBGLIOFct + + reads the graph `g` from data in the STL format. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \pre The data must represent a 2-manifold + + \see \ref IOStreamSTL +*/ +template +bool read_STL(const char* fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + std::ifstream in(fname); + return read_STL(in, g, np); +} + +template +bool read_STL(const std::string& fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return read_STL(fname.c_str(), g, np); +} + +template +bool read_STL(std::istream& is, FaceGraph& g) { return read_STL(is, g, parameters::all_default()); } +template +bool read_STL(const char* fname, FaceGraph& g) { return read_STL(fname, g, parameters::all_default()); } +template +bool read_STL(const std::string& fname, FaceGraph& g) { return read_STL(fname, g, parameters::all_default()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Write + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the stream `out` in the STL format. + + \pre The graph must contain only triangle faces. + + \see \ref IOStreamSTL +*/ +template +bool write_STL(std::ostream& out, + const FaceGraph& g, + const CGAL_BGL_NP_CLASS& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename CGAL::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + typedef typename boost::property_traits::value_type Point; + typedef typename Kernel_traits::Kernel::Vector_3 Vector; + + using parameters::choose_parameter; + using parameters::get_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + if(!out.good()) + return false; + + if(get_mode(out) == IO::BINARY) + { + out << "FileType: Binary "; + const boost::uint32_t N32 = static_cast(faces(g).size()); + out.write(reinterpret_cast(&N32), sizeof(N32)); + + for(const face_descriptor f : faces(g)) + { + const halfedge_descriptor h = halfedge(f, g); + Point_ref p = get(vpm, target(h, g)); + Point_ref q = get(vpm, target(next(h, g), g)); + Point_ref r = get(vpm, source(h, g)); + + Vector n = collinear(p, q, r) ? Vector(1, 0, 0) : unit_normal(p, q, r); + + const float coords[12] = + { + static_cast(n.x()), static_cast(n.y()), static_cast(n.z()), + static_cast(p.x()), static_cast(p.y()), static_cast(p.z()), + static_cast(q.x()), static_cast(q.y()), static_cast(q.z()), + static_cast(r.x()), static_cast(r.y()), static_cast(r.z()) }; + + for(int i=0; i<12; ++i) + out.write(reinterpret_cast(&coords[i]), sizeof(coords[i])); + out << " "; + } + } + else + { + out << "solid\n"; + for(const face_descriptor f : faces(g)) + { + halfedge_descriptor h = halfedge(f, g); + Point_ref p = get(vpm, target(h, g)); + Point_ref q = get(vpm, target(next(h, g), g)); + Point_ref r = get(vpm, source(h, g)); + Vector n = collinear(p, q, r) ? Vector(1, 0, 0) : unit_normal(p, q, r); + + out << "facet normal " << n << "\nouter loop\n"; + out << "vertex " << p << "\n"; + out << "vertex " << q << "\n"; + out << "vertex " << r << "\n"; + out << "endloop\nendfacet\n"; + } + out << "endsolid\n"; + } + + return out.good(); +} + +/*! +\ingroup PkgBGLIOFct + + writes the graph `g` in the STL format into a file named `fname`. + + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + \see \ref IOStreamSTL +*/ +template +bool write_STL(const char* fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + std::ofstream out(fname); + return write_STL(out, g, np); +} + +template +bool write_STL(const std::string& fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return write_STL(fname.c_str(), g, np); +} + +template +bool write_STL(std::ostream& os, const FaceGraph& g) { return write_STL(os, g, parameters::all_default()); } +template +bool write_STL(const char* fname, const FaceGraph& g) { return write_STL(fname, g, parameters::all_default()); } +template +bool write_STL(const std::string& fname, const FaceGraph& g) { return write_STL(fname, g, parameters::all_default()); } + +} // namespace CGAL + +#endif // CGAL_BGL_IO_STL_H diff --git a/BGL/include/CGAL/boost/graph/IO/VTK.h b/BGL/include/CGAL/boost/graph/IO/VTK.h new file mode 100644 index 00000000000..5a37df5420a --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/VTK.h @@ -0,0 +1,431 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_VTK_H +#define CGAL_BGL_IO_VTK_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace CGAL { + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Read + +#ifdef CGAL_USE_VTK + +namespace IO { +namespace internal { + +template +bool vtkPointSet_to_polygon_mesh(vtkPointSet* poly_data, + FaceGraph& g, + const NamedParameters& np) +{ + typedef typename CGAL::GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + using parameters::get_parameter; + using parameters::choose_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + vtkIdType nb_points = poly_data->GetNumberOfPoints(); + vtkIdType nb_cells = poly_data->GetNumberOfCells(); + + // extract points + std::vector vertex_map(nb_points); + for(vtkIdType i=0; iGetPoint(i, coords); + + vertex_descriptor v = add_vertex(g); + put(vpm, v, Point(coords[0], coords[1], coords[2])); + vertex_map[i] = v; + } + + // extract cells + for(vtkIdType i=0; iGetCellType(i); + if(cell_type != 5 + && cell_type != 7 + && cell_type != 9) // only supported cells are triangles, quads and polygons + continue; + + vtkCell* cell_ptr = poly_data->GetCell(i); + + vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); + if(nb_vertices < 3) + return false; + + std::vector vr(nb_vertices); + for(vtkIdType k=0; kGetPointId(k); + vr[k] = vertex_map[id]; + } + + face_descriptor f = CGAL::Euler::add_face(vr, g); + if(f == boost::graph_traits::null_face()) + return false; + } + + return true; +} + +} // namespace internal +} // namespace IO + +template +bool read_VTP(const char* fname, FaceGraph& g, const NamedParameters& np) +{ + vtkSmartPointer data; + vtkSmartPointer obs = + vtkSmartPointer::New(); + + data = IO::internal::read_vtk_file(fname, obs)->GetOutput();; + + return IO::internal::vtkPointSet_to_polygon_mesh(data, g, np); +} + +template +bool read_VTP(const char* fname, FaceGraph& g) { return read_VTP(fname, g, parameters::all_default()); } + +#endif // CGAL_USE_VTK + +#ifdef DOXYGEN_RUNNING +/*! \ingroup PkgBGLIOFct + * \brief reads a PolyData in the VTP format into a triangulated surface mesh. + * + * \tparam FaceGraph a model of `FaceListGraph`. + * + * \param fname the path to the file that will be read. + * \param g the output mesh. + * + * \pre \cgal needs to be configured with the VTK Libraries for this function to be available. + */ +template +bool read_VTP(const char* fname, FaceGraph& g, const NamedParameters& np); +#endif // DOXYGEN_RUNNING + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Write + +namespace IO { +namespace internal { + +// writes the polys appended data at the end of the .vtp file +template +void write_polys(std::ostream& os, + const FaceGraph& g, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename CGAL::GetVertexIndexMap::type VIM; + + using parameters::get_parameter; + using parameters::choose_parameter; + + VIM V = choose_parameter(get_parameter(np, internal_np::vertex_index), + get_const_property_map(boost::vertex_index, g)); + + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(g), 5); // triangle == 5 + + std::size_t off = 0; + + for(const face_descriptor f : faces(g)) + { + off += 3; + offsets.push_back(off); + for(const vertex_descriptor v : vertices_around_face(halfedge(f, g), g)) + connectivity_table.push_back(get(V, v)); + } + + write_vector(os, connectivity_table); + write_vector(os, offsets); + write_vector(os, cell_type); +} + +//todo use named params for maps +template +void write_polys_tag(std::ostream& os, + const FaceGraph& g, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename CGAL::GetVertexIndexMap::type VIM; + + using parameters::get_parameter; + using parameters::choose_parameter; + + VIM V = choose_parameter(get_parameter(np, internal_np::vertex_index), + get_const_property_map(boost::vertex_index, g)); + + 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 << " \n" + << " \n"; + offset += (3 * num_faces(g)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else + { + os << "\">\n"; + + for(face_descriptor f : faces(g)) + { + for(vertex_descriptor v : vertices_around_face(halfedge(f, g), g)) + os << get(V, v) << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(g) + 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_descriptor f : faces(g)) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(g) + 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(g); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} + +//todo : use namedparams for points and ids +//overload for facegraph +template +void write_points_tag(std::ostream& os, + const FaceGraph& g, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename CGAL::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::value_type Point; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + using parameters::get_parameter; + using parameters::choose_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(g) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else + { + os << "\">\n"; + for(const vertex_descriptor v : vertices(g)) + os << get(vpm, v).x() << " " << get(vpm, v).y() << " " << get(vpm, v).z() << " "; + os << " \n"; + } + os << " \n"; +} + +// writes the points appended data at the end of the .vtp file +template +void write_polys_points(std::ostream& os, + const FaceGraph& g, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename CGAL::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::value_type Point; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + using parameters::get_parameter; + using parameters::choose_parameter; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + std::vector coordinates; + + for(vertex_descriptor v : vertices(g)) + { + coordinates.push_back(get(vpm, v).x()); + coordinates.push_back(get(vpm, v).y()); + coordinates.push_back(get(vpm, v).z()); + } + + write_vector(os, coordinates); +} + +} // namespace internal +} // namespace IO + +/*! \ingroup PkgBGLIOFct + * + * \brief writes a triangulated surface mesh in the `PolyData` XML format. + * + * \tparam FaceGraph 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 g 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 `g`. If this parameter is omitted, an internal property map for + * `CGAL::vertex_Point` must be available in `FaceGraph`. + * \cgalParamEnd + * \cgalParamBegin{vertex_index_map} the property map with the indices associated to + * the vertices of `g`. If this parameter is omitted, an internal property map for + * `CGAL::vertex_index_t` must be available in `FaceGraph`. + * \cgalParamEnd + * \cgalNamedParamsEnd + * \see \ref IOStreamVTK + */ +template +void write_VTP(std::ostream& os, + const FaceGraph& g, + const NamedParameters& np) +{ + using parameters::get_parameter; + using parameters::choose_parameter; + + os << "\n" + << "\n" + << " " << "\n"; + os << " \n"; + + std::size_t offset = 0; + const bool binary = choose_parameter(get_parameter(np, internal_np::use_binary_mode), true); + + IO::internal::write_points_tag(os, g, binary, offset, np); + IO::internal::write_polys_tag(os, g, binary, offset, np); + + os << " \n" + << " \n"; + if(binary) + { + os << "\n_"; + IO::internal::write_polys_points(os, g, np); + IO::internal::write_polys(os, g, np); + } + os << "\n"; +} + +template +void write_VTP(std::ostream& os, const FaceGraph& g) +{ + write_VTP(os, g, CGAL::parameters::all_default()); +} + +} // namespace CGAL + +#endif // CGAL_BGL_IO_VTK_H diff --git a/BGL/include/CGAL/boost/graph/IO/WRL.h b/BGL/include/CGAL/boost/graph/IO/WRL.h new file mode 100644 index 00000000000..7b11f7e09ed --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/WRL.h @@ -0,0 +1,125 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// Mael Rouxel-Labbé + +#ifndef CGAL_BGL_IO_WRL_H +#define CGAL_BGL_IO_WRL_H + +#include +#include + +#include + +#include + +namespace CGAL { + +/*! + \ingroup PkgBGLIOFct + + writes the graph `g` in the wrl format (VRML 2.0). + + \cgalNamedParamsBegin + \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`. + If this parameter is omitted, an internal property map for + `CGAL::vertex_point_t` should be available in `FaceGraph` + \cgalParamEnd + \cgalNamedParamsEnd + + \see \ref IOStreamWRL +*/ +template +bool write_WRL(std::ostream& os, + const FaceGraph& g, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + + using parameters::get_parameter; + using parameters::choose_parameter; + + typename CGAL::GetVertexPointMap::const_type + vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); + + boost::container::flat_map reindex; + int n = 0; + + os << "#VRML V2.0 utf8\n" + "Group {\n" + "children [\n" + "Shape {\n" + "appearance DEF A1 Appearance {\n" + "material Material {\n" + "diffuseColor .6 .5 .9\n" + "}\n" + "}\n" + "appearance\n" + "Appearance {\n" + "material DEF Material Material {}\n" + "}\n" + "}\n" + "Group {\n" + "children [\n" + "Shape {\n" + "appearance Appearance { material USE Material }\n" + "geometry IndexedFaceSet {\n" + "convex FALSE\n" + "solid FALSE\n" + "coord Coordinate {\n" + "point [\n"; + + for(vertex_descriptor v : vertices(g)) + { + os << get(vpm,v) << ",\n"; + reindex[v] = n++; + } + + os << "] #point\n" + "} #coord Coordinate\n" + "coordIndex [\n"; + + for(face_descriptor f : faces(g)) + { + for(vertex_descriptor v : vertices_around_face(halfedge(f, g), g)) + os << reindex[v] << ","; + os << "-1,\n"; + } + + os << "] #coordIndex\n" + "} #geometry\n" + "} #Shape\n" + "] #children\n" + "} #group\n" + "]\n" + "}\n"; + + return os.good(); +} + +template +bool write_WRL(const std::string& fname, const FaceGraph& g, const CGAL_BGL_NP_CLASS& np) +{ + return write_WRL(fname.c_str(), g, np); +} + +template +bool write_WRL(std::ostream& os, const FaceGraph& g) { return write_WRL(os, g, parameters::all_default()); } +template +bool write_WRL(const char* fname, const FaceGraph& g) { return write_WRL(fname, g, parameters::all_default()); } +template +bool write_WRL(const std::string& fname, const FaceGraph& g) { return write_WRL(fname, g, parameters::all_default()); } + + +} // namespace CGAL + +#endif // CGAL_BGL_IO_WRL_H diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index 2eb5d55878f..f922106b08f 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -6,1207 +6,17 @@ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // -// // Author(s) : Andreas Fabri #ifndef CGAL_BOOST_GRAPH_IO_H #define CGAL_BOOST_GRAPH_IO_H -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace CGAL { - /*! - \ingroup PkgBGLIOFct - writes the graph `g` in the wrl format (VRML 2.0). - - \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` should be available in `FaceGraph`\cgalParamEnd - * \cgalNamedParamsEnd - * \see \ref IOStreamWRL - */ -template -bool write_wrl(std::ostream& os, - const FaceGraph& g, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - - using parameters::get_parameter; - using parameters::choose_parameter; - - typename CGAL::GetVertexPointMap::const_type - vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, g)); - - boost::container::flat_map reindex; - int n = 0; - - os << "#VRML V2.0 utf8\n" - "Group {\n" - "children [\n" - "Shape {\n" - "appearance DEF A1 Appearance {\n" - "material Material {\n" - "diffuseColor .6 .5 .9\n" - "}\n" - "}\n" - "appearance\n" - "Appearance {\n" - "material DEF Material Material {}\n" - "}\n" - "}\n" - "Group {\n" - "children [\n" - "Shape {\n" - "appearance Appearance { material USE Material }\n" - "geometry IndexedFaceSet {\n" - "convex FALSE\n" - "solid FALSE\n" - "coord Coordinate {\n" - "point [\n"; - - for(vertex_descriptor v : vertices(g)){ - os << get(vpm,v) << ",\n"; - reindex[v]=n++; - } - os << "] #point\n" - "} #coord Coordinate\n" - "coordIndex [\n"; - for(face_descriptor f : faces(g)){ - for(vertex_descriptor v : vertices_around_face(halfedge(f,g),g)){ - os << reindex[v] << ","; - } - os << "-1,\n"; - } - - os << "] #coordIndex\n" - "} #geometry\n" - "} #Shape\n" - "] #children\n" - "} #group\n" - "]\n" - "}\n"; - - return os.good(); -} - -template -bool write_wrl(std::ostream& os, - const FaceGraph& g) -{ - return write_wrl(os, g, - parameters::all_default()); -} - -/*! - \ingroup PkgBGLIOFct - writes the graph `g` in the OFF format. - - \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` should be available in `FaceGraph`\cgalParamEnd - * \cgalNamedParamsEnd - - \sa Overloads of this function for specific models of the concept `FaceGraph`. - \see \ref IOStreamOFF - - */ -template -bool write_off(std::ostream& os, - const FaceGraph& g, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - typedef typename boost::graph_traits::faces_size_type faces_size_type; - - using parameters::choose_parameter; - using parameters::get_parameter; - - typename CGAL::GetVertexPointMap::const_type - vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, g)); - vertices_size_type nv = static_cast(std::distance(vertices(g).first, vertices(g).second)); - faces_size_type nf = static_cast(std::distance(faces(g).first, faces(g).second)); - - os << "OFF\n" << nv << " " << nf << " 0\n"; - boost::container::flat_map reindex; - int n = 0; - for(vertex_descriptor v : vertices(g)){ - os << get(vpm,v) << '\n'; - reindex[v]=n++; - } - - for(face_descriptor f : faces(g)){ - os << degree(f,g); - for(vertex_descriptor v : vertices_around_face(halfedge(f,g),g)){ - os << " " << reindex[v]; - } - os << '\n'; - } - return os.good(); -} - - -/*! - \ingroup PkgBGLIOFct - writes the graph `g` in the OFF format into a file named `fname`. - \sa Overloads of this function for specific models of the concept `FaceGraph`. - \see \ref IOStreamOFF - */ -template -bool write_off(const char* fname, - const FaceGraph& g, - const NamedParameters& np) -{ - std::ofstream out(fname); - if(out.good()){ - return write_off(out,g, np); - } - return false; -} - -template -bool write_off(const std::string& fname, - const FaceGraph& g, - const NamedParameters& np) -{ return write_off(fname.c_str(), g, np); } - - -template -bool write_off(std::ostream& os, - const FaceGraph& g) -{ - return write_off(os, g, - parameters::all_default()); -} -template -bool write_off(const char* fname, - const FaceGraph& g) -{ - return write_off(fname,g, - parameters::all_default()); -} - -template -bool write_off(const std::string& fname, - const FaceGraph& g) -{ return write_off(fname, g, - parameters::all_default()); } - - namespace internal { namespace read_off_tools { - - inline bool is_whitespace(const std::string& s) - { - for(unsigned int i=0; i < s.size(); i++){ - if(s[i] != ' ' && s[i] != '\t'){ - return false; - } - } - return true; - } - -inline std::string next_non_comment(std::istream& is) -{ - std::string line; - do { - std::getline(is, line); - }while(line[0] == '#' || is_whitespace(line)); - return line; -} - - } - } // namespace internal - - -/*! - \ingroup PkgBGLIOFct - reads the graph `g` from data in the OFF format. Ignores comment lines which start with a hash, and lines with whitespace. - - \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` should be available in `FaceGraph`\cgalParamEnd - * \cgalNamedParamsEnd - \sa Overloads of this function for specific models of the concept `FaceGraph`. - \pre The data must represent a 2-manifold - \attention The graph `g` is not cleared, and the data from the stream are added. - \see \ref IOStreamOFF - - */ -template -bool read_off(std::istream& is, - FaceGraph& g, - NamedParameters np) -{ - using namespace internal::read_off_tools; - using parameters::choose_parameter; - using parameters::get_parameter; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - typedef typename boost::graph_traits::faces_size_type faces_size_type; - - typedef typename CGAL::GetVertexPointMap::type Vpm; - typedef typename boost::property_traits::value_type Point_3; - - Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_property_map(CGAL::vertex_point, g)); - vertices_size_type nv, nvf; - faces_size_type nf; - int ignore; - - std::string line = next_non_comment(is); - { - std::istringstream iss(line); - std::string off; - iss >> off; - CGAL_assertion( off == "OFF" || off == "COFF"); - } - line = next_non_comment(is); - { - std::istringstream iss(line); - iss >> nv >> nf >> ignore; - } - - std::vector vertices(nv); - Point_3 p; - for(vertices_size_type i=0; i < nv; i++){ - line = next_non_comment(is); - std::istringstream iss(line); - iss >> p; - vertices[i] = add_vertex(g); - put(vpm,vertices[i],p); - } - - for(faces_size_type i=0; i < nf; i++){ - line = next_non_comment(is); - std::istringstream iss(line); - iss >> nvf; - std::vector face(nvf); - for(vertices_size_type j = 0; j < nvf; j++){ - faces_size_type fvi; - iss >> fvi; - face[j] = vertices[fvi]; - } - Euler::add_face(face,g); - } - return true; -} - -template -bool read_off(std::istream& is, - FaceGraph& g) -{ - return read_off(is, g, parameters::all_default()); -} - -/*! - \ingroup PkgBGLIOFct - reads the graph `g` from data in the OFF format. Ignores comment lines which start with a hash, and lines with whitespace. - \sa Overloads of this function for specific models of the concept `FaceGraph`. - \pre The data must represent a 2-manifold - \attention The graph `g` is not cleared, and the data from the stream are added. - \see \ref IOStreamOFF - - */ -template -bool read_off(const char* fname, - FaceGraph& g, - NamedParameters np) -{ - std::ifstream in(fname); - if(in.good()){ - return read_off(in, g, np); - } - return false; -} - -template -bool read_off(const char* fname, - FaceGraph& g) -{ - return read_off(fname, g, parameters::all_default()); -} - -template -bool read_off(const std::string& fname, - FaceGraph& g, - NamedParameters np) -{ return read_off(fname.c_str(), g, np); } - -template -bool read_off(const std::string& fname, - FaceGraph& g) -{ return read_off(fname, g, parameters::all_default()); } - -template -bool write_inp(std::ostream& os, - const FaceGraph& g, - std::string name, - std::string type, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - - typedef typename CGAL::GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::value_type Point_3; - - using parameters::choose_parameter; - using parameters::get_parameter; - - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, g)); - - os << "*Part, name=" << name << "\n*Node\n"; - boost::container::flat_map reindex; - int n = 1; - for(vertex_descriptor v : vertices(g)){ - Point_3 p = get(vpm,v); - os << n << ", " << p.x() << ", " << p.y() << ", " << p.z() << '\n'; - reindex[v]=n++; - } - n = 1; - os << "*Element, type=" << type << std::endl; - for(face_descriptor f : faces(g)){ - os << n++; - for(vertex_descriptor v : vertices_around_face(halfedge(f,g),g)){ - os << ", " << reindex[v]; - } - os << '\n'; - } - os << "*End Part"<< std::endl; - return os.good(); -} -// conveniance overload -template -bool write_inp(std::ostream& os, - const FaceGraph& g, - std::string name, - std::string type) -{ - return write_inp(os, g, name, type, parameters::all_default()); -} - -namespace GOCAD_internal{ -//Use CRTP to gain access to the protected members without getters/setters. -template -class GOCAD_builder : public CGAL::internal::IO::Generic_facegraph_builder > -{ - typedef GOCAD_builder Self; - typedef CGAL::internal::IO::Generic_facegraph_builder Base; - typedef typename Base::Point_3 Point_3; - typedef typename Base::Points_3 Points_3; - typedef typename Base::Facet Facet; - typedef typename Base::Surface Surface; -public: - GOCAD_builder(std::istream& is_) - :Base(is_){} - void do_construct(Facegraph& graph) - { - typedef typename boost::graph_traits::vertex_descriptor - vertex_descriptor; - - std::vector vertices(this->meshPoints.size()); - for(std::size_t id = 0; id < this->meshPoints.size(); ++id) - { - vertices[id] = add_vertex( this->meshPoints[id], graph); - } - // graph.begin_surface( meshPoints.size(), mesh.size()); - typedef typename Points_3::size_type size_type; - - for(size_type i=0; i < this->mesh.size(); i++){ - std::array face; - face[0] = vertices[this->mesh[i][0]]; - face[1] = vertices[this->mesh[i][1]]; - face[2] = vertices[this->mesh[i][2]]; - - CGAL::Euler::add_face(face, graph); - } - } - - void - read(std::istream& input, Points_3& points, Surface& surface) - { - int offset = 0; - char c; - std::string s, tface("TFACE"); - int i,j,k; - Point_3 p; - bool vertices_read = false; - while(input >> s){ - if(s == tface){ - break; - } - std::string::size_type idx; - - if((idx = s.find("name")) != std::string::npos){ - std::istringstream str(s.substr(idx+5)); - str >> this->name; - } - if((idx = s.find("color")) != std::string::npos){ - std::istringstream str(s.substr(idx+6)); - str >> this->color; - } - } - std::getline(input, s); - - while(input.get(c)){ - if((c == 'V')||(c == 'P')){ - input >> s >> i >> p; - if(! vertices_read){ - vertices_read = true; - offset -= i; // Some files start with index 0 others with 1 - } - - points.push_back(p); - - } else if(vertices_read && (c == 'T')){ - input >> c >> c >> c >> i >> j >> k; - typename Base::Facet new_face(3); - new_face[0] = offset+i; - new_face[1] = offset+j; - new_face[2] = offset+k; - surface.push_back(new_face); - } else if(c == 'E'){ - break; - } - std::getline(input, s); - } - } - -}; -}//end GOCAD_internal - -/*! - \ingroup PkgBGLIOFct - reads the graph `face_graph` from data in the TS format. - `name` and `color` will be filled according to the values contained in the file. - - \pre The data must represent a 2-manifold - \attention The graph `face_graph` is not cleared, and the data from the stream are added. - \see \ref IOStreamGocad - */ -template -bool -read_gocad(FaceGraph& face_graph, std::istream& in, std::string& name, std::string& color) -{ - //typedef typename Polyhedron::HalfedgeDS HDS; - typedef typename boost::property_traits::type>::value_type Point_3; - - GOCAD_internal::GOCAD_builder builder(in); - builder(face_graph); - name=builder.name; - color=builder.color; - - return in.good() && face_graph.is_valid(); -} - -/*! - \ingroup PkgBGLIOFct - writes the graph `face_graph` in the TS format into `os`. `name` is the - mandatory name that will be assigned to `face_graph`in the file. - \see \ref IOStreamGocad - */ -template -bool -write_gocad(FaceGraph& face_graph, std::ostream& os, const std::string& name) -{ - os << "GOCAD TSurf 1\n" - "HEADER {\n" - "name:"; - os << name << std::endl; - os << "*border:on\n" - "*border*bstone:on\n" - "}\n" - "GOCAD_ORIGINAL_COORDINATE_SYSTEM\n" - "NAME Default\n" - "AXIS_NAME \"X\" \"Y\" \"Z\"\n" - "AXIS_UNIT \"m\" \"m\" \"m\"\n" - "ZPOSITIVE Elevation\n" - "END_ORIGINAL_COORDINATE_SYSTEM\n" - "TFACE\n"; - - os.precision(16); - typedef typename boost::property_map::type VPMap; - VPMap vpmap = get(CGAL::vertex_point, face_graph); - std::map::vertex_descriptor, int> id_map; - { - typename boost::graph_traits::vertex_iterator it, end; - it = vertices(face_graph).begin(); - end = vertices(face_graph).end(); - int i=0; - for(; it != end; ++it){ - id_map[*it] = i; - os << "VRTX " << i << " " << get(vpmap, *it) << "\n"; - ++i; - } - } - - { - typename boost::graph_traits::face_iterator it, end; - it = faces(face_graph).begin(); - end = faces(face_graph).end(); - for(; it != end; ++it){ - os << "TRGL " << id_map[target(prev(halfedge(*it, face_graph), face_graph), face_graph)] << " " - << id_map[target(halfedge(*it, face_graph), face_graph)] << " " - << id_map[target(next(halfedge(*it, face_graph), face_graph), face_graph)] << "\n"; - } - } - - os << "END" << std::endl; - - return true; -} - -namespace internal { -namespace write_vtp { - -// writes the polys appended data at the end of the .vtp file -template -void -write_polys(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::GetVertexIndexMap::type Vimap; - - using parameters::get_parameter; - using parameters::choose_parameter; - - Vimap V = choose_parameter(get_parameter(np, internal_np::vertex_index), - get_const_property_map(boost::vertex_index, mesh)); - - std::vector connectivity_table; - std::vector offsets; - std::vector 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); - for(vertex_descriptor v : - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(get(V, v)); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} -//todo use named params for maps -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::GetVertexIndexMap::type Vimap; - - using parameters::get_parameter; - using parameters::choose_parameter; - - Vimap V = choose_parameter(get_parameter(np, internal_np::vertex_index), - get_const_property_map(boost::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 << " \n" - << " \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 ) - { - for(vertex_descriptor v : - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << get(V, v) << " "; - } - os << " \n"; - } - - // Write offsets - os << " \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 << " \n"; - } - - // Write cell type (triangle == 5) - os << " \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 << " \n"; - } - os << " \n"; -} - -//todo : use namedparams for points and ids -//overload for facegraph -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::GetVertexPointMap::const_type Vpmap; - using parameters::get_parameter; - using parameters::choose_parameter; - Vpmap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \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 << " \n"; - } - os << " \n"; -} - - -// writes the points appended data at the end of the .vtp file -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::GetVertexPointMap::const_type Vpmap; - using parameters::get_parameter; - using parameters::choose_parameter; - Vpmap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector 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(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 - * \see \ref IOStreamVTK - */ -template -void write_vtp(std::ostream& os, - const TriangleMesh& mesh, - const NamedParameters& np) -{ - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - std::size_t offset = 0; - const bool binary = parameters::choose_parameter(parameters::get_parameter(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 << " \n" - << " \n"; - if (binary) { - os << "\n_"; - internal::write_vtp::write_polys_points(os,mesh, np); - internal::write_vtp::write_polys(os,mesh, np); - } - os << "\n"; -} - -template -void write_vtp(std::ostream& os, - const TriangleMesh& mesh) -{ - write_vtp(os, mesh, CGAL::parameters::all_default()); -} - -#ifdef CGAL_USE_VTK -namespace VTK_internal{ - -template -bool vtkPointSet_to_polygon_mesh(vtkPointSet* poly_data, - FaceGraph& face_graph) -{ - typedef typename boost::property_map::type VPMap; - typedef typename boost::property_map_value::type Point_3; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - VPMap vpmap = get(CGAL::vertex_point, face_graph); - - // get nb of points and cells - vtkIdType nb_points = poly_data->GetNumberOfPoints(); - vtkIdType nb_cells = poly_data->GetNumberOfCells(); - //extract points - std::vector vertex_map(nb_points); - for (vtkIdType i = 0; iGetPoint(i, coords); - - vertex_descriptor v = add_vertex(face_graph); - put(vpmap, v, Point_3(coords[0], coords[1], coords[2])); - vertex_map[i]=v; - } - - //extract cells - for (vtkIdType i = 0; iGetCellType(i); - if(cell_type != 5 - && cell_type != 7 - && cell_type != 9) //only supported cells are triangles, quads and polygons - continue; - vtkCell* cell_ptr = poly_data->GetCell(i); - - vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); - if (nb_vertices < 3) - return false; - std::vector vr(nb_vertices); - for (vtkIdType k=0; kGetPointId(k); - vr[k]=vertex_map[id]; - } - - CGAL::Euler::add_face(vr, face_graph); - } - return true; -} -} //end VTK_internal - -template -bool read_vtp(const char* filename, FaceGraph& face_graph) -{ - vtkSmartPointer data; - if(!CGAL::read_vtp_file(filename, data)) - { - return false; - } - return VTK_internal::vtkPointSet_to_polygon_mesh(data, face_graph); -} -#endif //CGAL_USE_VTK - -#ifdef DOXYGEN_RUNNING -/*! \ingroup PkgBGLIOFct - * \brief reads a PolyData in the VTP format into a triangulated surface mesh. - * - * \tparam FaceGraph a model of `FaceListGraph`. - * - * \param filename the path to the file that will be read. - * \param face_graph the output mesh. - * - * \pre \cgal needs to be configured with the VTK Libraries for this function to be available. - */ -template -bool read_vtp(const char* filename, FaceGraph& face_graph); - -#endif - -/*! - \ingroup PkgBGLIOFct - writes the graph `tm` in the stream `out` in the STL format. - \pre The graph must contain only triangle faces. - \see \ref IOStreamSTL - */ -template -std::ostream& -write_STL(const TriangleMesh& tm, std::ostream& out) -{ - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::reference Point_3_ref; - typedef typename boost::property_traits::value_type Point_3; - typedef typename Kernel_traits::Kernel::Vector_3 Vector_3; - - Vpm vpm = get(boost::vertex_point, tm); - - if (get_mode(out) == IO::BINARY) - { - out << "FileType: Binary "; - const boost::uint32_t N32 = static_cast(faces(tm).size()); - out.write(reinterpret_cast(&N32), sizeof(N32)); - - for(face_descriptor f : faces(tm)) - { - halfedge_descriptor h = halfedge(f, tm); - Point_3_ref p = get(vpm, target(h, tm)); - Point_3_ref q = get(vpm, target(next(h, tm), tm)); - Point_3_ref r = get(vpm, source(h, tm)); - - Vector_3 n = collinear(p,q,r) ? Vector_3(1,0,0): - unit_normal(p,q,r); - - const float coords[12]={ - static_cast(n.x()), static_cast(n.y()), static_cast(n.z()), - static_cast(p.x()), static_cast(p.y()), static_cast(p.z()), - static_cast(q.x()), static_cast(q.y()), static_cast(q.z()), - static_cast(r.x()), static_cast(r.y()), static_cast(r.z()) }; - - for (int i=0; i<12; ++i) - out.write(reinterpret_cast(&coords[i]), sizeof(coords[i])); - out << " "; - } - } - else - { - out << "solid\n"; - for(face_descriptor f : faces(tm)) - { - halfedge_descriptor h = halfedge(f, tm); - Point_3_ref p = get(vpm, target(h, tm)); - Point_3_ref q = get(vpm, target(next(h, tm), tm)); - Point_3_ref r = get(vpm, source(h, tm)); - - Vector_3 n = collinear(p,q,r) ? Vector_3(1,0,0): - unit_normal(p,q,r); - out << "facet normal " << n << "\nouter loop\n"; - out << "vertex " << p << "\n"; - out << "vertex " << q << "\n"; - out << "vertex " << r << "\n"; - out << "endloop\nendfacet\n"; - } - out << "endsolid\n"; - } - return out; -} - - -namespace STL_internal -{ -//Use CRTP to gain access to the protected members without getters/setters. -template -class STL_builder : public CGAL::internal::IO::Generic_facegraph_builder > -{ - typedef STL_builder Self; - typedef CGAL::internal::IO::Generic_facegraph_builder Base; - typedef typename Base::Point_3 Point_3; - typedef typename Base::Points_3 Points_3; - typedef typename Base::Facet Facet; - typedef typename Base::Surface Surface; -public: - STL_builder(std::istream& is_) - :Base(is_){} - void do_construct(Facegraph& graph) - { - typedef typename boost::graph_traits::vertex_descriptor - vertex_descriptor; - - std::vector vertices(this->meshPoints.size()); - for(std::size_t id = 0; id < this->meshPoints.size(); ++id) - { - vertices[id] = add_vertex( this->meshPoints[id], graph); - } - // graph.begin_surface( meshPoints.size(), mesh.size()); - typedef typename Points_3::size_type size_type; - - for(size_type i=0; i < this->mesh.size(); i++){ - std::array face; - face[0] = vertices[this->mesh[i][0]]; - face[1] = vertices[this->mesh[i][1]]; - face[2] = vertices[this->mesh[i][2]]; - - CGAL::Euler::add_face(face, graph); - } - } - - void - read(std::istream& input, Points_3& points, Surface& surface) - { - read_STL(input, points, surface); - } - -}; -} // end STL_internal - -/*! - \ingroup PkgBGLIOFct - - reads the graph `tm` from the stream `in` in the STL format. - - \returns `true` if the resulting mesh is valid. - - \pre The data must represent a 2-manifold - - \see \ref IOStreamSTL - */ -template -bool read_STL(std::istream& in, - TriangleMesh& tm) -{ - typedef typename boost::property_traits::type>::value_type Point_3; - - STL_internal::STL_builder builder(in); - builder(tm); - bool ok = in.good() || in.eof(); - ok &= tm.is_valid(); - return ok; -} - -namespace OBJ_internal { - -//Use CRTP to gain access to the protected members without getters/setters. -template -class OBJ_builder : public CGAL::internal::IO::Generic_facegraph_builder > -{ - typedef OBJ_builder Self; - typedef CGAL::internal::IO::Generic_facegraph_builder Base; - typedef typename Base::Point_3 Point_3; - typedef typename Base::Points_3 Points_3; - typedef typename Base::Facet Facet; - typedef typename Base::Surface Surface; -public: - OBJ_builder(std::istream& is_) - :Base(is_){} - void do_construct(Facegraph& graph) - { - typedef typename boost::graph_traits::vertex_descriptor - vertex_descriptor; - - std::vector vertices(this->meshPoints.size()); - for(std::size_t id = 0; id < this->meshPoints.size(); ++id) - { - vertices[id] = add_vertex( this->meshPoints[id], graph); - } - typedef typename Points_3::size_type size_type; - - for(size_type i=0; i < this->mesh.size(); i++){ - std::vector face(this->mesh[i].size()); - for(std::size_t j=0; j< face.size(); ++j) - face[j] = vertices[this->mesh[i][j]]; - - CGAL::Euler::add_face(face, graph); - } - } - - void - read(std::istream& input, Points_3& points, Surface& surface) - { - read_OBJ(input, points, surface); - } - -}; -} // end STL_internal - -/*! - \ingroup PkgBGLIOFct - reads the graph `tm` from the stream `in` in the OBJ format. - \returns `true` if the resulting mesh is valid. - \pre The data must represent a 2-manifold - \see \ref IOStreamOBJ - */ -template -bool -read_OBJ(TriangleMesh& tm, std::istream& in) -{ - //typedef typename Polyhedron::HalfedgeDS HDS; - typedef typename boost::property_traits::type>::value_type Point_3; - - OBJ_internal::OBJ_builder builder(in); - builder(tm); - bool ok = in.good() || in.eof(); - ok &= tm.is_valid(); - return ok; -} - -/*! - \ingroup PkgBGLIOFct - writes the graph `face_graph` in the OBJ format. - \returns `true` if writing was successful. - \see \ref IOStreamOBJ - */ -template -bool -write_OBJ(const FaceGraph& face_graph, std::ostream& os) -{ - // writes M to `out' in the format provided by `writer'. - CGAL::File_writer_wavefront writer; - typedef typename boost::graph_traits::vertex_iterator VCI; - typedef typename boost::graph_traits::face_iterator FCI; - typedef typename boost::property_map::type VPmap; - VPmap map = get(CGAL::vertex_point, face_graph); - // Print header. - writer.write_header( os, - num_vertices(face_graph), - num_halfedges(face_graph), - num_faces(face_graph)); - - std::map::vertex_descriptor, std::size_t> index_map; - auto hint = index_map.begin(); - std::size_t id = 0; - - for( VCI vi = vertices(face_graph).begin(); vi != vertices(face_graph).end(); ++vi) { - writer.write_vertex( ::CGAL::to_double( get(map, *vi).x()), - ::CGAL::to_double( get(map, *vi).y()), - ::CGAL::to_double( get(map, *vi).z())); - - hint = index_map.insert(hint, std::make_pair(*vi, id++)); - } - - writer.write_facet_header(); - for( FCI fi = faces(face_graph).begin(); fi != faces(face_graph).end(); ++fi) { - CGAL::Halfedge_around_face_circulator hc(halfedge(*fi, face_graph), face_graph); - auto hc_end = hc; - std::size_t n = circulator_size( hc); - CGAL_assertion( n >= 3); - writer.write_facet_begin( n); - do { - writer.write_facet_vertex_index(index_map[target(*hc, face_graph)]); - ++hc; - } while( hc != hc_end); - writer.write_facet_end(); - } - writer.write_footer(); - return os.good(); -} -} // namespace CGAL - +#include +#include +#include +#include +#include +#include +#include #endif // CGAL_BOOST_GRAPH_IO_H diff --git a/Stream_support/include/CGAL/IO/OBJ.h b/Stream_support/include/CGAL/IO/OBJ.h index 3928a2cb1aa..a107da052d7 100644 --- a/Stream_support/include/CGAL/IO/OBJ.h +++ b/Stream_support/include/CGAL/IO/OBJ.h @@ -22,20 +22,20 @@ namespace CGAL { //! /// reads the content of `input` into `points` and `faces`, using the `OBJ` format. /// -/// \tparam Points_3 a `RandomAccessContainer` of `Point_3, +/// \tparam Points a `RandomAccessContainer` of `Point_3, /// \tparam Faces a `RandomAccessContainer` of `RandomAccessContainer` of `std::size_t` /// /// \see \ref IOStreamOBJ -template +template bool read_OBJ(std::istream& input, - Points_3& points, + Points& points, Faces& faces) { - typedef typename Points_3::value_type Point_3; + typedef typename Points::value_type Point; int mini(1), maxi(-INT_MAX); - Point_3 p; + Point p; std::string line; while(getline(input, line)) @@ -46,6 +46,7 @@ bool read_OBJ(std::istream& input, iss >> p; if(!iss) return false; + points.push_back(p); } else if(line[0] == 'f') @@ -57,9 +58,9 @@ bool read_OBJ(std::istream& input, { if(i < 1) { - faces.back().push_back(points.size()+i);//negative indices are relative references - if(i points.size() || mini < -static_cast(points.size())) + if(maxi > static_cast(points.size()) || mini < -static_cast(points.size())) { std::cerr << "a face index is invalid " << std::endl; return false; diff --git a/Stream_support/include/CGAL/IO/OBJ/File_writer_wavefront.h b/Stream_support/include/CGAL/IO/OBJ/File_writer_wavefront.h index 15c45afba4f..dc2ba242c0b 100644 --- a/Stream_support/include/CGAL/IO/OBJ/File_writer_wavefront.h +++ b/Stream_support/include/CGAL/IO/OBJ/File_writer_wavefront.h @@ -17,11 +17,6 @@ #ifndef CGAL_IO_OBJ_FILE_WRITER_WAVEFRONT_H #define CGAL_IO_OBJ_FILE_WRITER_WAVEFRONT_H -#include - -#include -#include - namespace CGAL { class File_writer_wavefront @@ -31,7 +26,8 @@ class File_writer_wavefront public: std::ostream& out() const { return *m_out; } - void write_header(std::ostream& out, + + void write_header(std::ostream& o, std::size_t vertices, std::size_t halfedges, std::size_t facets) diff --git a/Stream_support/include/CGAL/IO/STL.h b/Stream_support/include/CGAL/IO/STL.h index fa504efb174..2dd862d46a8 100644 --- a/Stream_support/include/CGAL/IO/STL.h +++ b/Stream_support/include/CGAL/IO/STL.h @@ -57,7 +57,7 @@ bool read_STL(std::istream& input, // If we have gone beyond 80 characters and have not read anything yet, // then this must be an ASCII file. if(pos > 80) - return parse_ASCII_STL(input, points, facets, verbose); + return IO::internal::parse_ASCII_STL(input, points, facets, verbose); // We are within the first 80 characters, both ASCII and binary are possible @@ -81,7 +81,7 @@ bool read_STL(std::istream& input, // If the first word is not 'solid', the file must be binary if(s != "solid" || (word[5] !='\n' && word[5] != ' ')) { - if(parse_binary_STL(input, points, facets, verbose)) + if(IO::internal::parse_binary_STL(input, points, facets, verbose)) { return true; } @@ -91,14 +91,14 @@ bool read_STL(std::istream& input, // The file does not start with 'solid' anyway, so it's fine to reset it. input.clear(); input.seekg(0, std::ios::beg); - return parse_ASCII_STL(input, points, facets, verbose); + return IO::internal::parse_ASCII_STL(input, points, facets, verbose); } } // Now, we have found the keyword "solid" which is supposed to indicate that the file is ASCII input.clear(); input.seekg(0, std::ios::beg); //the parser needs to read all "solid" to work correctly. - if(parse_ASCII_STL(input, points, facets, verbose)) + if(IO::internal::parse_ASCII_STL(input, points, facets, verbose)) { // correctly read the input as an ASCII file return true; @@ -106,7 +106,7 @@ bool read_STL(std::istream& input, else // Failed to read the ASCII file { // It might have actually have been a binary file... ? - return parse_binary_STL(input, points, facets, verbose); + return IO::internal::parse_binary_STL(input, points, facets, verbose); } } @@ -122,9 +122,9 @@ bool read_STL(std::istream& input, * \see \ref IOStreamSTL */ template -std::ostream& write_STL(const PointRange& points, - const TriangleRange& facets, - std::ostream& out) +std::ostream& write_STL(std::ostream& out, + const PointRange& points, + const TriangleRange& facets) { typedef typename PointRange::value_type Point; typedef typename CGAL::Kernel_traits::Kernel K; diff --git a/Stream_support/include/CGAL/IO/STL/STL_reader.h b/Stream_support/include/CGAL/IO/STL/STL_reader.h index 844c07b7213..66123767d42 100644 --- a/Stream_support/include/CGAL/IO/STL/STL_reader.h +++ b/Stream_support/include/CGAL/IO/STL/STL_reader.h @@ -24,7 +24,7 @@ #include namespace CGAL { -namespace Stream_support { +namespace IO { namespace internal { template @@ -285,7 +285,7 @@ bool parse_binary_STL(std::istream& input, } } // namespace internal -} // namespace Stream_support +} // namespace IO } // namespace CGAL #endif // CGAL_IO_STL_STL_READER_H diff --git a/Stream_support/include/CGAL/IO/VTK.h b/Stream_support/include/CGAL/IO/VTK.h index 12d432dea87..f5873dd16a3 100644 --- a/Stream_support/include/CGAL/IO/VTK.h +++ b/Stream_support/include/CGAL/IO/VTK.h @@ -15,6 +15,7 @@ #ifndef CGAL_IO_VTK_H #define CGAL_IO_VTK_H -#include +#include +#include #endif // CGAL_IO_VTK_H diff --git a/Stream_support/include/CGAL/IO/VTK/VTK_reader.h b/Stream_support/include/CGAL/IO/VTK/VTK_reader.h index 0a2078ed705..8dfc0766273 100644 --- a/Stream_support/include/CGAL/IO/VTK/VTK_reader.h +++ b/Stream_support/include/CGAL/IO/VTK/VTK_reader.h @@ -13,4 +13,77 @@ #ifndef CGAL_IO_VTK_READER_H #define CGAL_IO_VTK_READER_H +#include +#include + +#include + +namespace CGAL { +namespace IO { +namespace internal { + +class ErrorObserverVtk + : public vtkCommand +{ +public: + ErrorObserverVtk() + : Error(false), Warning(false), ErrorMessage(""), WarningMessage("") + { } + + static ErrorObserverVtk *New() { return new ErrorObserverVtk; } + + bool GetError() const { return this->Error; } + bool GetWarning() const { return this->Warning; } + std::string GetErrorMessage() { return ErrorMessage; } + std::string GetWarningMessage() { return WarningMessage; } + + void Clear() + { + this->Error = false; + this->Warning = false; + this->ErrorMessage = ""; + this->WarningMessage = ""; + } + + virtual void Execute(vtkObject *vtkNotUsed(caller), + unsigned long event, + void *calldata) + { + switch (event) + { + case vtkCommand::ErrorEvent: + ErrorMessage = static_cast(calldata); + this->Error = true; + break; + case vtkCommand::WarningEvent: + WarningMessage = static_cast(calldata); + this->Warning = true; + break; + } + } + +private: + bool Error; + bool Warning; + std::string ErrorMessage; + std::string WarningMessage; +}; + +template +vtkSmartPointer read_vtk_file(const std::string& input_filename, + vtkSmartPointer errorObserver) +{ + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->AddObserver(vtkCommand::ErrorEvent, errorObserver); + reader->AddObserver(vtkCommand::WarningEvent, errorObserver); + reader->SetFileName(input_filename.data()); + reader->Update(); + + return reader; +} + +} // namespace internal +} // namespace IO +} // namespace CGAL + #endif // CGAL_IO_VTK_READER_H diff --git a/Stream_support/include/CGAL/IO/VTK/VTK_writer.h b/Stream_support/include/CGAL/IO/VTK/VTK_writer.h index 6271cdde7e9..9be80302861 100644 --- a/Stream_support/include/CGAL/IO/VTK/VTK_writer.h +++ b/Stream_support/include/CGAL/IO/VTK/VTK_writer.h @@ -13,8 +13,12 @@ #ifndef CGAL_IO_VTK_WRITER_H #define CGAL_IO_VTK_WRITER_H +#include +#include +#include + namespace CGAL { -namespace Stream_support { +namespace IO { namespace internal { template @@ -28,68 +32,8 @@ void write_vector(std::ostream& os, os.write(buffer, vect.size()*sizeof(FT)); // encoded data } -class ErrorObserverVtk - : public vtkCommand -{ -public: - ErrorObserverVtk() - : Error(false), Warning(false), ErrorMessage(""), WarningMessage("") - { } - - static ErrorObserverVtk *New() { return new ErrorObserverVtk; } - - bool GetError() const { return this->Error; } - bool GetWarning() const { return this->Warning; } - std::string GetErrorMessage() { return ErrorMessage; } - std::string GetWarningMessage() { return WarningMessage; } - - void Clear() - { - this->Error = false; - this->Warning = false; - this->ErrorMessage = ""; - this->WarningMessage = ""; - } - - virtual void Execute(vtkObject *vtkNotUsed(caller), - unsigned long event, - void *calldata) - { - switch (event) - { - case vtkCommand::ErrorEvent: - ErrorMessage = static_cast(calldata); - this->Error = true; - break; - case vtkCommand::WarningEvent: - WarningMessage = static_cast(calldata); - this->Warning = true; - break; - } - } - -private: - bool Error; - bool Warning; - std::string ErrorMessage; - std::string WarningMessage; -}; - -template -vtkSmartPointer -read_vtk_file(const std::string& input_filename, - vtkSmartPointer errorObserver) -{ - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->AddObserver(vtkCommand::ErrorEvent, errorObserver); - reader->AddObserver(vtkCommand::WarningEvent, errorObserver); - reader->SetFileName(input_filename.data()); - reader->Update(); - return reader; -} - } // namespace internal -} // namespace Stream_support +} // namespace IO } // namespace CGAL #endif // CGAL_IO_VTK_WRITER_H diff --git a/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h b/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h deleted file mode 100644 index 6fb9961e616..00000000000 --- a/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2019 GeometryFactory -// -// This file is part of CGAL (www.cgal.org); -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial -// -// Author(s) : Maxime Gimeno - -#ifndef CGAL_INTERNAL_IO_GENERIC_FACEGRAPH_BUILDER_H -#define CGAL_INTERNAL_IO_GENERIC_FACEGRAPH_BUILDER_H - -#include -#include -#include -#include -#include - -namespace CGAL{ - -namespace internal { -namespace IO{ -template -class Generic_facegraph_builder -{ -protected: - typedef P Point_3; - typedef std::deque Points_3; - typedef std::vector Facet; - typedef std::deque Surface; - -public: - std::string name, color; - Generic_facegraph_builder(std::istream& is_) - : is(is_), counter(0) - {} - - void do_construct(){} //specific to Facegraph (declared in BGL) - void - read(std::istream&, Points_3&, Surface&) {} - - void operator()( Facegraph& graph) - { - static_cast(this)->read(this->is, this->meshPoints, this->mesh); - static_cast(this)->do_construct(graph); - } - -protected: - std::istream& is; - int counter; - Points_3 meshPoints; - Surface mesh; -}; - - -} //end IO -}//end internal -}//end CGAL -#endif // CGAL_INTERNAL_IO_GENERIC_FACEGRAPH_BUILDER_H