Merge pull request #2101 from afabri/BGL-read_write_off-GF

BGL: Add generic functions read_off() and write_off()
This commit is contained in:
Laurent Rineau 2017-07-17 12:45:07 +02:00
commit 89acad2d14
24 changed files with 505 additions and 58 deletions

View File

@ -11,7 +11,9 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Face_filtered_graph.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Dual.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Seam_mesh.h
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Seam_mesh.h \
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h
EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \
${CGAL_Surface_mesh_segmentation_EXAMPLE_DIR} \
${CGAL_Polygon_mesh_processing_EXAMPLE_DIR} \

View File

@ -215,6 +215,9 @@ for conversion between models of different `FaceGraph` concepts, etc.
Most functions are in the header file `<CGAL/boost/graph/helpers.h>`
*/
/// \defgroup PkgBGLIOFct I/O Functions
/// \ingroup PkgBGL
/*!
\addtogroup PkgBGLIterators
@ -412,12 +415,18 @@ user might encounter.
- `CGAL::convert_nef_polyhedron_to_polygon_mesh()`
- `CGAL::split_graph_into_polylines()`
## Graph Adaptors ##
- `CGAL::Dual`
- `CGAL::Face_filtered_graph`
- `CGAL::Graph_with_descriptor_with_graph`
- `CGAL::Graph_with_descriptor_with_graph_property_map`
- `CGAL::Seam_mesh`
## I/O Functions ##
- `CGAL::read_off()`
- `CGAL::write_off()`
*/
/*!

View File

@ -31,18 +31,13 @@ int main(int argc, char** argv )
Mesh mesh;
std::vector<vertex_descriptor> V;
V.push_back(add_vertex(mesh));
V.push_back(add_vertex(mesh));
V.push_back(add_vertex(mesh));
add_face(V.begin(), V.end(), mesh);
// OpenMesh::IO::read_mesh(mesh, (argc>1)?argv[1]:"in.off");
std::ifstream in((argc>1)?argv[1]:"in.off");
CGAL::read_off(in, mesh);
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)){
BOOST_FOREACH(halfedge_descriptor hd, CGAL::halfedges_around_target(vd,mesh)){
if(! CGAL::is_border(edge(hd,mesh),mesh)){
CGAL::Euler::flip_edge(hd,mesh);
OpenMesh::IO::write_mesh(mesh, (argc>2)?argv[2]:"out.off");
CGAL::write_off((argc>2)?argv[2]:"out.off", mesh);
return 0;
}
}

View File

@ -0,0 +1,8 @@
OFF
4 2 0
0 0 0
1 0 0
1 1 0
0 1 0
3 0 1 2
3 0 2 3

View File

@ -28,11 +28,14 @@
#include <boost/iterator/transform_iterator.hpp>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/internal/OM_iterator_from_circulator.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Iterator_range.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/io.h>
#include <CGAL/assertions.h>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
@ -208,6 +211,15 @@ degree(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::vertex
return sm.valence(v);
}
template <typename K>
typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::degree_size_type
degree(typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::face_descriptor f,
const OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
{
return sm.valence(f);
}
template <typename K>
typename boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >::degree_size_type
@ -682,6 +694,20 @@ void clear(OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
CGAL_postcondition(num_faces(sm) == 0);
}
template<typename K>
bool read_off(std::istream& is, OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
{
return OpenMesh::IO::read_mesh(sm, is, ".OFF");
}
template<typename K>
bool write_off(std::ostream& os, OpenMesh::PolyMesh_ArrayKernelT<K>& sm)
{
return OpenMesh::IO::write_mesh(sm, os, ".OFF");
}
}
#ifndef CGAL_NO_DEPRECATED_CODE
#include <CGAL/boost/graph/backward_compatibility_functions.h>

View File

@ -25,12 +25,15 @@
#include <boost/iterator/transform_iterator.hpp>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/internal/OM_iterator_from_circulator.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Iterator_range.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/io.h>
#include <CGAL/assertions.h>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
@ -136,6 +139,15 @@ degree(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::vertex_
return sm.valence(v);
}
template <typename K>
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::degree_size_type
degree(typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::face_descriptor,
const OpenMesh::TriMesh_ArrayKernelT<K>& )
{
return 3;
}
template <typename K>
typename boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >::degree_size_type
@ -601,7 +613,40 @@ bool is_valid(OpenMesh::TriMesh_ArrayKernelT<K>& sm, bool /* verbose */ = false)
} // namespace OpenMesh
namespace CGAL {
// Overload CGAL::clear function. TriMesh_ArrayKernel behaves
// differently from other meshes. Calling clear does not affect the
// number of vertices, edges, or faces in the mesh. To get actual
// numbers it is necessary to first collect garbage. We add an
// overlaod to get consistent behavior.
template<typename K>
void clear(OpenMesh::TriMesh_ArrayKernelT<K>& sm)
{
sm.clear();
sm.garbage_collection(true, true, true);
CGAL_postcondition(num_edges(sm) == 0);
CGAL_postcondition(num_vertices(sm) == 0);
CGAL_postcondition(num_faces(sm) == 0);
}
template<typename K>
bool read_off(std::istream& is, OpenMesh::TriMesh_ArrayKernelT<K>& sm)
{
OpenMesh::IO::Options ropt;
return OpenMesh::IO::read_mesh(sm, is, ".OFF", ropt, false);
}
template<typename K>
bool write_off(std::ostream& os, OpenMesh::TriMesh_ArrayKernelT<K>& sm)
{
OpenMesh::IO::Options ropt;
return OpenMesh::IO::write_mesh(sm, os, ".OFF", ropt);
}
}
#ifndef CGAL_NO_DEPRECATED_CODE
#include <CGAL/boost/graph/backward_compatibility_functions.h>

View File

@ -0,0 +1,203 @@
// 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 <boost/container/flat_map.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <fstream>
#include <string>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/helpers.h>
namespace CGAL {
/*!
\ingroup PkgBGLIOFct
writes the graph `g` in the OFF format.
\sa Overloads of this function for specific models of the concept `FaceGraph`.
*/
template <typename FaceGraph>
bool write_off(std::ostream& os,
const FaceGraph& g)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
typedef typename boost::graph_traits<FaceGraph>::vertices_size_type vertices_size_type;
typedef typename boost::graph_traits<FaceGraph>::faces_size_type faces_size_type;
typename boost::property_map<FaceGraph, CGAL::vertex_point_t>::const_type vpm = get(CGAL::vertex_point,g);
vertices_size_type nv = static_cast<vertices_size_type>(std::distance(vertices(g).first, vertices(g).second));
faces_size_type nf = static_cast<faces_size_type>(std::distance(faces(g).first, faces(g).second));
os << "OFF\n" << nv << " " << nf << " 0\n";
boost::container::flat_map<vertex_descriptor,vertices_size_type> 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';
}
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`.
*/
template <typename FaceGraph>
bool write_off(const char* fname,
const FaceGraph& g)
{
std::ofstream out(fname);
if(out.good()){
return write_off(out,g);
}
return false;
}
namespace internal { namespace read_off_tools {
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;
}
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
\attention The graph `g` is not cleared, and the data from the stream are added.
*/
template <typename FaceGraph>
bool read_off(std::istream& is,
FaceGraph& g)
{
using namespace internal::read_off_tools;
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::vertices_size_type vertices_size_type;
typedef typename boost::graph_traits<FaceGraph>::faces_size_type faces_size_type;
typedef typename boost::property_map<FaceGraph, CGAL::vertex_point_t>::type Vpm;
typedef typename boost::property_traits<Vpm>::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" || off == "COFF");
}
line = next_non_comment(is);
{
std::istringstream iss(line);
iss >> nv >> nf >> ignore;
}
std::vector<vertex_descriptor> 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<vertex_descriptor> 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;
}
/*!
\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.
*/
template <typename FaceGraph>
bool read_off(const char* fname,
FaceGraph& g)
{
std::ifstream in(fname);
if(in.good()){
return read_off(in, g);
}
return false;
}
} // namespace CGAL
#endif // CGAL_BOOST_GRAPH_IO_H

View File

@ -91,6 +91,8 @@ create_single_source_cgal_program( "test_Has_member_id.cpp" )
create_single_source_cgal_program( "test_cgal_bgl_named_params.cpp" )
create_single_source_cgal_program( "test_bgl_read_write.cpp" )
create_single_source_cgal_program( "graph_concept_Face_filtered_graph.cpp" )
create_single_source_cgal_program( "test_Face_filtered_graph.cpp" )

View File

@ -0,0 +1,24 @@
OFF
11 7 0
# vertices
-1 -1 1
-1 1 1
1 1 1
1 -1 1
-1 -1 -1
-1 1 -1
1 1 -1
1 -1 -1
2 2 2
3 2 2
3 3 3
# facets
3 3 2 1
3 3 1 0
4 0 1 5 4
4 6 5 1 2
4 3 7 6 2
4 4 7 3 0
4 4 5 6 7
3 8 9 10

View File

@ -0,0 +1,23 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/io.h>
#include <iostream>
#include <fstream>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Mesh;
int main(int argc, char* argv[])
{
Mesh sm;
std::ifstream in((argc>1)?argv[1]:"data/prim.off");
CGAL::read_off(in,sm);
CGAL::write_off(std::cout, sm);
return 0;
}

View File

@ -395,6 +395,8 @@ and <code>src/</code> directories).
a graph adaptor which allows to create virtual borders when marking edges
as seam edges.
</li>
<li>Add the functions <code>read_off()</code> and <code>write_off()</code>.
</li>
</ul>
<!-- Visualization -->

View File

@ -4,7 +4,7 @@ namespace CGAL {
\relates Polyhedron_3
\ingroup PkgPolyhedronIOFunc
This operator reads a polyhedral surface in Object File Format, OFF,
This function reads a polyhedral surface in %Object File Format, OFF,
with file extension <TT>.off</TT>, which is also understood by
Geomview \cgalCite{cgal:p-gmgv16-96}, from the input stream `in` and
appends it to the polyhedral surface \f$ P\f$. Only the point coordinates
@ -19,46 +19,65 @@ format automatically and can read both.
\sa `CGAL::Polyhedron_3<Traits>`
\sa `CGAL::Polyhedron_incremental_builder_3<HDS>`
\sa `operator<<(std::ostream&, CGAL::Polyhedron_3<PolyhedronTraits_3>&)`
\sa \link PkgPolyhedronIOFunc `operator<<(std::ostream&, Polyhedron_3<PolyhedronTraits_3>&)`\endlink
This function overloads the generic function \link PkgBGLIOFct `read_off(std::istream&,FaceGraph)`\endlink.
\cgalHeading{Implementation}
This operator is implemented using the modifier mechanism for
polyhedral surfaces and the `CGAL::Polyhedron_incremental_builder_3`
polyhedral surfaces and the `Polyhedron_incremental_builder_3`
class, which allows the construction in a single, efficient scan pass
of the input and handles also all the possible flexibility of the
polyhedral surface.
*/
template <class PolyhedronTraits_3>
std::istream& operator>>( std::istream& in, CGAL::Polyhedron_3<PolyhedronTraits_3>& P);
bool read_off( std::istream& in, Polyhedron_3<PolyhedronTraits_3>& P);
/*!
\relates Polyhedron_3
\ingroup PkgPolyhedronIOFunc
calls \link read_off() `read_off(in, P)` \endlink.
*/
template <class PolyhedronTraits_3>
std::istream& operator>>( std::istream& in, Polyhedron_3<PolyhedronTraits_3>& P);
/*!
\relates Polyhedron_3
\ingroup PkgPolyhedronIOFunc
This operator writes the polyhedral surface \f$P\f$ to the output
stream out using the Object File Format, OFF, with file extension
This function writes the polyhedral surface \f$P\f$ to the output
stream `out` using the %Object File Format, OFF, with file extension
<TT>.off</TT>, which is also understood by GeomView \cgalCite{cgal:p-gmgv16-96}. The
output is in ASCII format. From the polyhedral surface, only the point
coordinates and facets are written. Neither normal vectors nor color
attributes are used.
For OFF an ASCII and a binary format exist. The format can be selected
with the \cgal modifiers for streams, ::set_ascii_mode and
set_binary_mode respectively. The modifier ::set_pretty_mode can be used
with the \cgal modifiers for streams, `set_ascii_mode()` and
`set_binary_mode()` respectively. The modifier `set_pretty_mode()` can be used
to allow for (a few) structuring comments in the output. Otherwise,
the output would be free of comments. The default for writing is ASCII
without comments.
This function overloads the generic function \link PkgBGLIOFct `write_off(std::istream&,FaceGraph)` \endlink.
\sa `CGAL::Polyhedron_3<Traits>`
\sa `CGAL::Polyhedron_incremental_builder_3<HDS>`
\sa `operator>>(std::istream&, CGAL::Polyhedron_3<PolyhedronTraits_3>&)`
\sa \link PkgPolyhedronIOFunc `operator>>(std::istream& in, Polyhedron_3<PolyhedronTraits_3>& P)` \endlink
*/
template <class PolyhedronTraits_3>
std::ostream& operator<<( std::ostream& out, CGAL::Polyhedron_3<PolyhedronTraits_3>& P);
bool write_off( std::ostream& out, Polyhedron_3<PolyhedronTraits_3>& P);
/*!
\relates Polyhedron_3
\ingroup PkgPolyhedronIOFunc
calls \link write_off() `write_off(out, P)` \endlink.
*/
template <class PolyhedronTraits_3>
std::ostream& operator<<( std::ostream& out, Polyhedron_3<PolyhedronTraits_3>& P);
} /* namespace CGAL */

View File

@ -1594,7 +1594,11 @@ public:
*/
void delegate( CGAL::Modifier_base<HDS>& m);
/// @}
}; /* end Polyhedron_3 */
} /* end namespace CGAL */

View File

@ -60,6 +60,7 @@ surface can be used without knowing the halfedge data structure.
## Functions ##
- \link PkgPolyhedronIOFunc `CGAL::operator<<()` \endlink
- \link PkgPolyhedronIOFunc `CGAL::operator>>()` \endlink
- \link PkgPolyhedronIOFunc `write_off()` \endlink
- \link PkgPolyhedronIOFunc `read_off()` \endlink
*/

View File

@ -6,3 +6,4 @@ Circulator
Stream_support
HalfedgeDS
Miscellany
BGL

View File

@ -100,6 +100,14 @@ in_degree(typename boost::graph_traits< CGAL::Polyhedron_3<Gt,I,HDS,A> const>::v
return v->vertex_degree();
}
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
typename boost::graph_traits< CGAL::Polyhedron_3<Gt,I,HDS,A> const>::degree_size_type
degree(typename boost::graph_traits< CGAL::Polyhedron_3<Gt,I,HDS,A> const>::face_descriptor f
, const CGAL::Polyhedron_3<Gt,I,HDS,A>&)
{
return f->facet_degree();
}
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
typename boost::graph_traits< CGAL::Polyhedron_3<Gt,I,HDS,A> const>::vertex_descriptor
source(typename boost::graph_traits< CGAL::Polyhedron_3<Gt,I,HDS,A> const>::edge_descriptor e

View File

@ -31,28 +31,55 @@
namespace CGAL {
template < class Traits,
class Items,
template < class T, class I, class A>
class HDS, class Alloc>
bool
write_off( std::ostream& out, const Polyhedron_3<Traits,Items,HDS,Alloc>& P){
// writes P to `out' in PRETTY, ASCII or BINARY format
// as the stream indicates.
File_header_OFF header( is_binary( out), ! is_pretty( out), false);
CGAL::print_polyhedron_with_header_OFF( out, P, header);
return out.good();
}
template < class Traits,
class Items,
template < class T, class I, class A>
class HDS, class Alloc>
bool
read_off(std::istream& in,
Polyhedron_3<Traits,Items,HDS,Alloc>& P) {
// reads a polyhedron from `in' and appends it to P.
CGAL::scan_OFF( in, P);
return in.good();
}
template < class Traits,
class Items,
template < class T, class I, class A>
class HDS, class Alloc>
std::ostream&
operator<<( std::ostream& out, const Polyhedron_3<Traits,Items,HDS,Alloc>& P) {
// writes P to `out' in PRETTY, ASCII or BINARY format
// as the stream indicates.
File_header_OFF header( is_binary( out), ! is_pretty( out), false);
CGAL::print_polyhedron_with_header_OFF( out, P, header);
return out;
operator<<( std::ostream& out, const Polyhedron_3<Traits,Items,HDS,Alloc>& P)
{
write_off(out,P);
return out;
}
template < class Traits,
class Items,
template < class T, class I, class A>
class HDS, class Alloc>
std::istream& operator>>(std::istream& in,
Polyhedron_3<Traits,Items,HDS,Alloc>& P) {
// reads a polyhedron from `in' and appends it to P.
CGAL::scan_OFF( in, P);
return in;
Polyhedron_3<Traits,Items,HDS,Alloc>& P)
{
read_off(in,P);
return in;
}
} //namespace CGAL

View File

@ -124,6 +124,7 @@ Returns the previous mode of `s`.
*/
IO::Mode set_pretty_mode(std::ios& s);
/*!
\ingroup PkgIOstreams

View File

@ -229,6 +229,8 @@ There are a 11 predefined `Color` constants available:
`DEEPBLUE`, `BLUE`, `PURPLE`, `VIOLET`, `ORANGE`,
and `YELLOW`.
\section IOstreamStream Stream Support
Three classes are provided by \cgal as adaptors to input and output stream

View File

@ -1,3 +1,5 @@
Manual
STL_Extension
Geomview
Surface_mesh
Polyhedron

View File

@ -41,18 +41,27 @@
namespace CGAL {
class IO {
namespace IO {
class Static {
public:
static int get_static_mode()
static int get_mode()
{
static const int mode = std::ios::xalloc();
return mode;
}
enum Mode {ASCII = 0, PRETTY, BINARY};
};
enum Mode {ASCII = 0, PRETTY, BINARY};
}
template <typename Dummy>
struct IO_rep_is_specialized_aux
{

View File

@ -40,7 +40,7 @@ CGAL_INLINE_FUNCTION
IO::Mode
get_mode(std::ios& i)
{
return static_cast<IO::Mode>(i.iword(IO::get_static_mode()));
return static_cast<IO::Mode>(i.iword(IO::Static::get_mode()));
}
CGAL_INLINE_FUNCTION
@ -48,7 +48,7 @@ IO::Mode
set_ascii_mode(std::ios& i)
{
IO::Mode m = get_mode(i);
i.iword(IO::get_static_mode()) = IO::ASCII;
i.iword(IO::Static::get_mode()) = IO::ASCII;
return m;
}
@ -57,7 +57,7 @@ IO::Mode
set_binary_mode(std::ios& i)
{
IO::Mode m = get_mode(i);
i.iword(IO::get_static_mode()) = IO::BINARY;
i.iword(IO::Static::get_mode()) = IO::BINARY;
return m;
}
@ -67,7 +67,7 @@ IO::Mode
set_pretty_mode(std::ios& i)
{
IO::Mode m = get_mode(i);
i.iword(IO::get_static_mode()) = IO::PRETTY;
i.iword(IO::Static::get_mode()) = IO::PRETTY;
return m;
}
@ -76,7 +76,7 @@ IO::Mode
set_mode(std::ios& i, IO::Mode m)
{
IO::Mode old = get_mode(i);
i.iword(IO::get_static_mode()) = m;
i.iword(IO::Static::get_mode()) = m;
return old;
}
@ -84,21 +84,21 @@ CGAL_INLINE_FUNCTION
bool
is_pretty(std::ios& i)
{
return i.iword(IO::get_static_mode()) == IO::PRETTY;
return i.iword(IO::Static::get_mode()) == IO::PRETTY;
}
CGAL_INLINE_FUNCTION
bool
is_ascii(std::ios& i)
{
return i.iword(IO::get_static_mode()) == IO::ASCII;
return i.iword(IO::Static::get_mode()) == IO::ASCII;
}
CGAL_INLINE_FUNCTION
bool
is_binary(std::ios& i)
{
return i.iword(IO::get_static_mode()) == IO::BINARY;
return i.iword(IO::Static::get_mode()) == IO::BINARY;
}
CGAL_INLINE_FUNCTION

View File

@ -42,9 +42,9 @@
#include <CGAL/circulator.h>
#include <CGAL/assertions.h>
#include <CGAL/Surface_mesh/Surface_mesh_fwd.h>
#include <CGAL/Surface_mesh/IO.h>
#include <CGAL/Surface_mesh/Properties.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/IO/File_scanner_OFF.h>
@ -1958,13 +1958,14 @@ private: //------------------------------------------------------- private data
return sm;
}
/// \relates Surface_mesh
/// Inserts the surface mesh in an output stream in Ascii OFF format.
/// Only the \em point property is inserted in the stream.
/// \pre `operator<<(std::ostream&,const P&)` must be defined.
template <typename P>
std::ostream& operator<<(std::ostream& os, const Surface_mesh<P>& sm)
{
bool write_off(std::ostream& os, const Surface_mesh<P>& sm) {
typedef Surface_mesh<P> Mesh;
typedef typename Mesh::Vertex_index Vertex_index;
typedef typename Mesh::Face_index Face_index;
@ -2006,9 +2007,20 @@ private: //------------------------------------------------------- private data
}
os << '\n';
}
return os.good();
}
/// \relates Surface_mesh
///
/// This operator calls `write_off(std::istream& , CGAL::Surface_mesh)`.
template <typename P>
std::ostream& operator<<(std::ostream& os, const Surface_mesh<P>& sm)
{
write_off(os, sm);
return os;
}
/// @cond CGAL_DOCUMENT_INTERNALS
inline std::istream& sm_skip_comments( std::istream& in) {
@ -2022,18 +2034,20 @@ private: //------------------------------------------------------- private data
in.putback(c);
return in;
}
/// @endcond
/// \relates Surface_mesh
/// \relates Surface_mesh
/// Extracts the surface mesh from an input stream in Ascii OFF, COFF, NOFF, CNOFF format.
/// Extracts the surface mesh from an input stream in Ascii OFF, COFF, NOFF, CNOFF
/// format and appends it to the surface mesh `sm`.
/// 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 <typename P>
std::istream& operator>>(std::istream& is, Surface_mesh<P>& sm)
bool read_off(std::istream& is, Surface_mesh<P>& sm)
{
typedef Surface_mesh<P> Mesh;
typedef typename Kernel_traits<P>::Kernel K;
@ -2041,7 +2055,6 @@ private: //------------------------------------------------------- private data
typedef typename Mesh::Face_index Face_index;
typedef typename Mesh::Vertex_index Vertex_index;
typedef typename Mesh::size_type size_type;
sm.clear();
int n, f, e;
std::string off;
is >> sm_skip_comments;
@ -2050,7 +2063,8 @@ private: //------------------------------------------------------- private data
is >> n >> f >> e;
sm.reserve(n,2*f,e);
sm.reserve(sm.num_vertices()+n, sm.num_faces()+2*f, sm.num_edges()+e);
std::vector<Vertex_index> vertexmap(n);
P p;
Vector_3 v;
typename Mesh::template Property_map<Vertex_index,CGAL::Color> vcolor;
@ -2068,6 +2082,7 @@ private: //------------------------------------------------------- private data
is >> sm_skip_comments;
is >> p;
Vertex_index vi= sm.add_vertex(p);
vertexmap[i] = vi;
if(v_has_normals){
is >> v;
vnormal[vi] = v;
@ -2092,9 +2107,8 @@ private: //------------------------------------------------------- private data
}
}
}
std::vector<size_type> vr;
std::size_t d;
std::vector<Vertex_index> vr;
size_type d, vi;
bool fcolored = false;
typename Mesh::template Property_map<Face_index,CGAL::Color> fcolor;
@ -2103,14 +2117,15 @@ private: //------------------------------------------------------- private data
is >> d;
vr.resize(d);
for(std::size_t j=0; j<d; j++){
is >> vr[j];
is >> vi;
vr[j] = vertexmap[vi];
}
Face_index fi = sm.add_face(vr);
if(fi == sm.null_face())
{
std::cout<< "Warning: Facets don't seem to be oriented. Loading a Soup of polygons instead."<<std::endl;
sm.clear();
return is;
return false;
}
// the first face will tell us if faces have a color map
@ -2132,10 +2147,20 @@ private: //------------------------------------------------------- private data
}
}
}
return is.good();
}
/// \relates Surface_mesh
/// This operator calls `read_off(std::istream& , CGAL::Surface_mesh)`.
template <typename P>
std::istream& operator>>(std::istream& is, Surface_mesh<P>& sm)
{
read_off(is, sm);
return is;
}
/*! @} */
template <typename P>

View File

@ -127,6 +127,15 @@ degree(typename boost::graph_traits<CGAL::Surface_mesh<P> >::vertex_descriptor v
return sm.degree(v);
}
template <typename P>
typename boost::graph_traits<CGAL::Surface_mesh<P> >::degree_size_type
degree(typename boost::graph_traits<CGAL::Surface_mesh<P> >::face_descriptor f,
const CGAL::Surface_mesh<P>& sm)
{
return sm.degree(f);
}
template <typename P>
typename boost::graph_traits<CGAL::Surface_mesh<P> >::degree_size_type