diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h new file mode 100644 index 00000000000..e4ba207be85 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/io.h @@ -0,0 +1,159 @@ +// Copyright (c) 2015 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$ +// +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_BOOST_GRAPH_IO_H +#define CGAL_BOOST_GRAPH_IO_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { +/*! + \ingroup PkgBGLHelperFct + writes the graph `g` in the OFF format. + \sa Overloads of this function for specific models of the concept `FaceGraph`. + + */ +template +void write_off(std::ostream& os, + const FaceGraph& g) +{ + 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; + + typename boost::property_map::type vpm = get(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; + BOOST_FOREACH(vertex_descriptor v, vertices(g)){ + os << get(vpm,v) << '\n'; + reindex[v]=n++; + } + + BOOST_FOREACH(face_descriptor f, faces(g)){ + os << degree(f,g); + BOOST_FOREACH(vertex_descriptor v, vertices_around_face(halfedge(f,g),g)){ + os << " " << reindex[v]; + } + os << '\n'; + } +} + + namespace internal { namespace read_off { + + bool is_whitespace(const std::string& s) + { + for(int i=0; i < s.size(); i++){ + if(s[i] != ' ' && s[i] != '\t'){ + return false; + } + } + return true; + } + +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. + \sa Overloads of this function for specific models of the concept `FaceGraph`. + \pre The data must represent a 2-manifold + + */ +template +bool read_off(std::istream& is, + FaceGraph& g) +{ + using namespace internal::read_off; + + 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; + + typedef typename boost::property_map::type Vpm; + typedef typename boost::property_traits::value_type Point_3; + Vpm vpm = get(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"); + } + 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; +} + +} // namespace CGAL + +#endif // CGAL_BOOST_GRAPH_IO_H diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 834ca989f38..1b442ee9c92 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -2015,17 +2016,11 @@ private: //------------------------------------------------------- private data in.putback(c); return in; } -/// @endcond - /// \relates Surface_mesh - /// Extracts the surface mesh from an input stream in Ascii OFF, COFF, NOFF, CNOFF format. - /// The operator reads the point property as well as "v:normal", "v:color", and "f:color". - /// Vertex texture coordinates are ignored. - /// \pre `operator>>(std::istream&,const P&)` must be defined. template - bool read_off(std::istream& is, Surface_mesh

& sm) + bool read_off_clear(std::istream& is, Surface_mesh

& sm) { typedef Surface_mesh

Mesh; typedef typename Kernel_traits

::Kernel K; @@ -2126,6 +2121,27 @@ private: //------------------------------------------------------- private data } return is.good(); } +/// @endcond + + /// \relates Surface_mesh + /// Extracts the surface mesh from an input stream in Ascii OFF, COFF, NOFF, CNOFF format. + /// The operator reads the point property as well as "v:normal", "v:color", and "f:color". + /// Vertex texture coordinates are ignored. + /// \pre `operator>>(std::istream&,const P&)` must be defined. + + template + bool read_off(std::istream& is, Surface_mesh

& sm) + { + if( (sm.num_vertices() == 0) && (sm.num_halfedges() == 0)&& (sm.num_faces() == 0) ){ + return read_off_clear(is,sm); + } + Surface_mesh

other; + if(read_off_clear(is,other)){ + copy_face_graph(other,sm); + return true; + } + return false; + } /// \relates Surface_mesh