Re-organize and improve BGL IO

This commit is contained in:
Mael Rouxel-Labbé 2020-01-24 17:48:02 +01:00
parent 6a5972cc3b
commit 423ae6ec84
17 changed files with 1883 additions and 1345 deletions

View File

@ -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 <CGAL/boost/graph/IO/Generic_facegraph_builder.h>
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/iterator.h>
#include <boost/container/flat_map.hpp>
#include <fstream>
#include <iostream>
namespace CGAL {
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Read
namespace IO {
namespace internal {
// Use CRTP to gain access to the protected members without getters/setters.
template <typename FaceGraph, typename Point>
class GOCAD_builder
: public Generic_facegraph_builder<FaceGraph, Point, GOCAD_builder<FaceGraph, Point> >
{
typedef GOCAD_builder<FaceGraph, Point> Self;
typedef Generic_facegraph_builder<FaceGraph, Point, Self> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_GOCAD(std::istream& in,
std::string& name,
std::string& color,
FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
IO::internal::GOCAD_builder<FaceGraph, Point> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_GOCAD(const std::string& fname, FaceGraph& g, CGAL_BGL_NP_CLASS np)
{
return read_GOCAD(fname.c_str(), g, np);
}
template <typename FaceGraph>
bool read_GOCAD(std::istream& is, FaceGraph& g) { return read_GOCAD(is, g, parameters::all_default()); }
template <typename FaceGraph>
bool read_GOCAD(const char* fname, FaceGraph& g) { return read_GOCAD(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool write_GOCAD(std::ostream& os,
const char* fname,
const FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
typedef typename boost::graph_traits<FaceGraph>::vertices_size_type vertices_size_type;
using parameters::choose_parameter;
using parameters::get_parameter;
typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::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<vertex_descriptor, vertices_size_type> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
bool write_GOCAD(const char* fname, const FaceGraph& g) { return write_GOCAD(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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

View File

@ -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 <CGAL/boost/graph/Euler_operations.h>
#include <iostream>
#include <string>
#include <vector>
namespace CGAL{
namespace IO {
namespace internal {
template <class FaceGraph, class Point, class Derived>
class Generic_facegraph_builder
{
protected:
typedef std::vector<Point> Point_container;
typedef typename Point_container::size_type size_type;
typedef std::vector<std::size_t> Face;
typedef std::vector<Face> Face_container;
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::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<Derived*>(this)->read(m_in, m_points, m_faces);
}
template <typename NamedParameters>
bool construct(FaceGraph& g,
const NamedParameters& np)
{
typedef typename CGAL::GetVertexPointMap<FaceGraph, NamedParameters>::type VPM;
VPM vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point),
get_property_map(CGAL::vertex_point, g));
std::vector<vertex_descriptor> vertices(m_points.size());
for(std::size_t id = 0, ps=m_points.size(); id<ps; ++id)
{
vertices[id] = add_vertex(g);
put(vpm, vertices[id], m_points[id]);
}
for(size_type i=0, fs=m_faces.size(); i<fs; ++i)
{
std::vector<vertex_descriptor> face(m_faces[i].size());
for(std::size_t j=0, fs=face.size(); j<fs; ++j)
face[j] = vertices[m_faces[i][j]];
face_descriptor f = CGAL::Euler::add_face(face, g);
if(f == boost::graph_traits<FaceGraph>::null_face())
return false;
}
return is_valid_polygon_mesh(g);
}
template <typename NamedParameters>
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

View File

@ -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 <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <boost/container/flat_map.hpp>
namespace CGAL {
template <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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<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 CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::const_type VPM;
typedef typename boost::property_traits<VPM>::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<vertex_descriptor,vertices_size_type> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
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 <typename FaceGraph>
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

View File

@ -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 <CGAL/boost/graph/IO/Generic_facegraph_builder.h>
#include <CGAL/IO/OBJ.h>
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
namespace CGAL {
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Read
namespace IO {
namespace internal {
// Use CRTP to gain access to the protected members without getters/setters.
template <typename FaceGraph, typename Point>
class OBJ_builder
: public Generic_facegraph_builder<FaceGraph, Point, OBJ_builder<FaceGraph, Point> >
{
typedef OBJ_builder<FaceGraph, Point> Self;
typedef Generic_facegraph_builder<FaceGraph, Point, Self> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_OBJ(std::istream& in,
FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
IO::internal::OBJ_builder<FaceGraph, Point> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_OBJ(const std::string& fname,
FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
return read_OBJ(fname.c_str(), g, np);
}
template <typename FaceGraph>
bool read_OBJ(std::istream& is, FaceGraph& g) { return read_OBJ(is, g, parameters::all_default()); }
template <typename FaceGraph>
bool read_OBJ(const char* fname, FaceGraph& g) { return read_OBJ(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool write_OBJ(std::ostream& os,
const FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
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>::face_descriptor face_descriptor;
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::const_type VPM;
typedef typename boost::property_traits<VPM>::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<vertex_descriptor, vertices_size_type> 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<FaceGraph> hc(halfedge(f, g), g);
CGAL::Halfedge_around_face_circulator<FaceGraph> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
bool write_OBJ(std::ostream& os, const FaceGraph& g) { return write_OBJ(os, g, parameters::all_default()); }
template <typename FaceGraph>
bool write_OBJ(const char* fname, const FaceGraph& g) { return write_OBJ(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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

View File

@ -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 <CGAL/assertions.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <boost/container/flat_map.hpp>
#include <fstream>
#include <iostream>
#include <string>
// @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<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 read_off_tools
} // namespace internal
} // namespace IO
/*!
\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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_OFF(std::istream& is,
FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
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>::face_descriptor face_descriptor;
typedef typename boost::graph_traits<FaceGraph>::faces_size_type faces_size_type;
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::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<vertex_descriptor> vertices(nv);
Point 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];
}
face_descriptor f = CGAL::Euler::add_face(face, g);
if(f == boost::graph_traits<FaceGraph>::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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_OFF(const std::string& fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np)
{
return read_OFF(fname.c_str(), g, np);
}
template <typename FaceGraph>
bool read_OFF(std::istream& is, FaceGraph& g) { return read_OFF(is, g, parameters::all_default()); }
template <typename FaceGraph>
bool read_OFF(const char* fname, FaceGraph& g) { return read_OFF(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool write_OFF(std::ostream& os,
const FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
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;
using parameters::choose_parameter;
using parameters::get_parameter;
typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::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<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));
if(!os.good())
return false;
os << "OFF\n"
<< nv << " " << nf << " 0\n";
boost::container::flat_map<vertex_descriptor, vertices_size_type> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
bool write_OFF(std::ostream& os, const FaceGraph& g) { return write_OFF(os, g, parameters::all_default()); }
template <typename FaceGraph>
bool write_OFF(const char* fname, const FaceGraph& g) { return write_OFF(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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

View File

@ -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 <CGAL/boost/graph/IO/Generic_facegraph_builder.h>
#include <CGAL/IO/STL.h>
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <fstream>
#include <iostream>
#include <string>
namespace CGAL {
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Read
namespace IO {
namespace internal {
// Use CRTP to gain access to the protected members without getters/setters.
template <typename FaceGraph, typename Point>
class STL_builder
: public Generic_facegraph_builder<FaceGraph, Point, STL_builder<FaceGraph, Point> >
{
typedef STL_builder<FaceGraph, Point> Self;
typedef Generic_facegraph_builder<FaceGraph, Point, Self> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_STL(std::istream& in,
FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
IO::internal::STL_builder<FaceGraph, Point> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool read_STL(const std::string& fname, FaceGraph& g, const CGAL_BGL_NP_CLASS& np)
{
return read_STL(fname.c_str(), g, np);
}
template <typename FaceGraph>
bool read_STL(std::istream& is, FaceGraph& g) { return read_STL(is, g, parameters::all_default()); }
template <typename FaceGraph>
bool read_STL(const char* fname, FaceGraph& g) { return read_STL(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
bool write_STL(std::ostream& out,
const FaceGraph& g,
const CGAL_BGL_NP_CLASS& np)
{
typedef typename boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
typedef typename CGAL::GetVertexPointMap<FaceGraph, CGAL_BGL_NP_CLASS>::const_type VPM;
typedef typename boost::property_traits<VPM>::reference Point_ref;
typedef typename boost::property_traits<VPM>::value_type Point;
typedef typename Kernel_traits<Point>::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<boost::uint32_t>(faces(g).size());
out.write(reinterpret_cast<const char *>(&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<float>(n.x()), static_cast<float>(n.y()), static_cast<float>(n.z()),
static_cast<float>(p.x()), static_cast<float>(p.y()), static_cast<float>(p.z()),
static_cast<float>(q.x()), static_cast<float>(q.y()), static_cast<float>(q.z()),
static_cast<float>(r.x()), static_cast<float>(r.y()), static_cast<float>(r.z()) };
for(int i=0; i<12; ++i)
out.write(reinterpret_cast<const char *>(&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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
bool write_STL(std::ostream& os, const FaceGraph& g) { return write_STL(os, g, parameters::all_default()); }
template <typename FaceGraph>
bool write_STL(const char* fname, const FaceGraph& g) { return write_STL(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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

View File

@ -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 <CGAL/IO/VTK.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <vtkCell.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkPointSet.h>
namespace CGAL {
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Read
#ifdef CGAL_USE_VTK
namespace IO {
namespace internal {
template <typename FaceGraph, typename NamedParameters>
bool vtkPointSet_to_polygon_mesh(vtkPointSet* poly_data,
FaceGraph& g,
const NamedParameters& np)
{
typedef typename CGAL::GetVertexPointMap<FaceGraph, NamedParameters>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::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_descriptor> vertex_map(nb_points);
for(vtkIdType i=0; i<nb_points; ++i)
{
double coords[3];
poly_data->GetPoint(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; i<nb_cells; ++i)
{
int cell_type = poly_data->GetCellType(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<vertex_descriptor> vr(nb_vertices);
for(vtkIdType k=0; k<nb_vertices; ++k)
{
vtkIdType id = cell_ptr->GetPointId(k);
vr[k] = vertex_map[id];
}
face_descriptor f = CGAL::Euler::add_face(vr, g);
if(f == boost::graph_traits<FaceGraph>::null_face())
return false;
}
return true;
}
} // namespace internal
} // namespace IO
template<typename FaceGraph, typename NamedParameters>
bool read_VTP(const char* fname, FaceGraph& g, const NamedParameters& np)
{
vtkSmartPointer<vtkPointSet> data;
vtkSmartPointer<IO::internal::ErrorObserverVtk> obs =
vtkSmartPointer<IO::internal::ErrorObserverVtk>::New();
data = IO::internal::read_vtk_file<vtkXMLPolyDataReader>(fname, obs)->GetOutput();;
return IO::internal::vtkPointSet_to_polygon_mesh(data, g, np);
}
template<typename FaceGraph>
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<typename FaceGraph, typename NamedParameters>
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 <typename FaceGraph, typename NamedParameters>
void write_polys(std::ostream& os,
const FaceGraph& g,
const NamedParameters& np)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
typedef typename CGAL::GetVertexIndexMap<FaceGraph, NamedParameters>::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<std::size_t> connectivity_table;
std::vector<std::size_t> offsets;
std::vector<unsigned char> 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<std::size_t>(os, connectivity_table);
write_vector<std::size_t>(os, offsets);
write_vector<unsigned char>(os, cell_type);
}
//todo use named params for maps
template <typename FaceGraph, typename NamedParameters>
void write_polys_tag(std::ostream& os,
const FaceGraph& g,
bool binary,
std::size_t& offset,
const NamedParameters& np)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
typedef typename CGAL::GetVertexIndexMap<FaceGraph, NamedParameters>::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 << " <Polys>\n"
<< " <DataArray Name=\"connectivity\""
<< formatattribute << typeattribute;
// if binary output, just write the xml tag
if(binary)
{
os << " offset=\"" << offset << "\"/>\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 << " </DataArray>\n";
}
// Write offsets
os << " <DataArray Name=\"offsets\""
<< formatattribute << typeattribute;
if(binary) { // if binary output, just write the xml tag
os << " offset=\"" << offset << "\"/>\n";
offset += (num_faces(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 << " </DataArray>\n";
}
// Write cell type (triangle == 5)
os << " <DataArray Name=\"types\""
<< formatattribute << " type=\"UInt8\"";
if(binary)
{
os << " offset=\"" << offset << "\"/>\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 << " </DataArray>\n";
}
os << " </Polys>\n";
}
//todo : use namedparams for points and ids
//overload for facegraph
template <typename FaceGraph, typename NamedParameters>
void write_points_tag(std::ostream& os,
const FaceGraph& g,
bool binary,
std::size_t& offset,
const NamedParameters& np)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename CGAL::GetVertexPointMap<FaceGraph, NamedParameters>::const_type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
typedef typename CGAL::Kernel_traits<Point>::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 << " <Points>\n"
<< " <DataArray type =\"" << type << "\" NumberOfComponents=\"3\" format=\""
<< format;
if(binary)
{
os << "\" offset=\"" << offset << "\"/>\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 << " </DataArray>\n";
}
os << " </Points>\n";
}
// writes the points appended data at the end of the .vtp file
template <typename FaceGraph, typename NamedParameters>
void write_polys_points(std::ostream& os,
const FaceGraph& g,
const NamedParameters& np)
{
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
typedef typename CGAL::GetVertexPointMap<FaceGraph, NamedParameters>::const_type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;
typedef typename CGAL::Kernel_traits<Point>::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<FT> 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<FT>(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<typename FaceGraph, typename NamedParameters>
void write_VTP(std::ostream& os,
const FaceGraph& g,
const NamedParameters& np)
{
using parameters::get_parameter;
using parameters::choose_parameter;
os << "<?xml version=\"1.0\"?>\n"
<< "<VTKFile type=\"PolyData\" version=\"0.1\"";
#ifdef CGAL_LITTLE_ENDIAN
os << " byte_order=\"LittleEndian\"";
#else // CGAL_BIG_ENDIAN
os << " byte_order=\"BigEndian\"";
#endif
switch(sizeof(std::size_t))
{
case 4: os << " header_type=\"UInt32\""; break;
case 8: os << " header_type=\"UInt64\""; break;
default: CGAL_error_msg("Unknown size of std::size_t");
}
os << ">\n"
<< " <PolyData>" << "\n";
os << " <Piece NumberOfPoints=\"" << num_vertices(g)
<< "\" NumberOfPolys=\"" << num_faces(g) << "\">\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 << " </Piece>\n"
<< " </PolyData>\n";
if(binary)
{
os << "<AppendedData encoding=\"raw\">\n_";
IO::internal::write_polys_points(os, g, np);
IO::internal::write_polys(os, g, np);
}
os << "</VTKFile>\n";
}
template<typename FaceGraph>
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

View File

@ -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 <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <boost/container/flat_map.hpp>
#include <fstream>
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 <typename FaceGraph, typename NamedParameters>
bool write_WRL(std::ostream& os,
const FaceGraph& g,
const NamedParameters& np)
{
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;
using parameters::get_parameter;
using parameters::choose_parameter;
typename CGAL::GetVertexPointMap<FaceGraph, NamedParameters>::const_type
vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
get_const_property_map(CGAL::vertex_point, g));
boost::container::flat_map<vertex_descriptor,vertices_size_type> 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 <typename FaceGraph, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
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 <typename FaceGraph>
bool write_WRL(std::ostream& os, const FaceGraph& g) { return write_WRL(os, g, parameters::all_default()); }
template <typename FaceGraph>
bool write_WRL(const char* fname, const FaceGraph& g) { return write_WRL(fname, g, parameters::all_default()); }
template <typename FaceGraph>
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

File diff suppressed because it is too large Load Diff

View File

@ -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 <class Points_3, class Faces>
template <class Points, class Faces>
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<mini)
mini=i;
faces.back().push_back(points.size()+i); // negative indices are relative references
if(i < mini)
mini = i;
}
else
{
@ -80,7 +81,7 @@ bool read_OBJ(std::istream& input,
}
}
if(maxi > points.size() || mini < -static_cast<int>(points.size()))
if(maxi > static_cast<int>(points.size()) || mini < -static_cast<int>(points.size()))
{
std::cerr << "a face index is invalid " << std::endl;
return false;

View File

@ -17,11 +17,6 @@
#ifndef CGAL_IO_OBJ_FILE_WRITER_WAVEFRONT_H
#define CGAL_IO_OBJ_FILE_WRITER_WAVEFRONT_H
#include <CGAL/IO/binary_file_io.h>
#include <iostream>
#include <cstddef>
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)

View File

@ -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 <class PointRange, class TriangleRange>
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<Point>::Kernel K;

View File

@ -24,7 +24,7 @@
#include <vector>
namespace CGAL {
namespace Stream_support {
namespace IO {
namespace internal {
template <class PointRange, class TriangleRange, typename IndexMap>
@ -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

View File

@ -15,6 +15,7 @@
#ifndef CGAL_IO_VTK_H
#define CGAL_IO_VTK_H
#include <CGAL/IO/VTK/write_vtk.h>
#include <CGAL/IO/VTK/VTK_reader.h>
#include <CGAL/IO/VTK/VTK_writer.h>
#endif // CGAL_IO_VTK_H

View File

@ -13,4 +13,77 @@
#ifndef CGAL_IO_VTK_READER_H
#define CGAL_IO_VTK_READER_H
#include <vtkSmartPointer.h>
#include <vtkCommand.h>
#include <string>
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<char *>(calldata);
this->Error = true;
break;
case vtkCommand::WarningEvent:
WarningMessage = static_cast<char *>(calldata);
this->Warning = true;
break;
}
}
private:
bool Error;
bool Warning;
std::string ErrorMessage;
std::string WarningMessage;
};
template <class vtkReader>
vtkSmartPointer<vtkReader> read_vtk_file(const std::string& input_filename,
vtkSmartPointer<ErrorObserverVtk> errorObserver)
{
vtkSmartPointer<vtkReader> reader = vtkSmartPointer<vtkReader>::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

View File

@ -13,8 +13,12 @@
#ifndef CGAL_IO_VTK_WRITER_H
#define CGAL_IO_VTK_WRITER_H
#include <fstream>
#include <iostream>
#include <vector>
namespace CGAL {
namespace Stream_support {
namespace IO {
namespace internal {
template <class FT>
@ -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<char *>(calldata);
this->Error = true;
break;
case vtkCommand::WarningEvent:
WarningMessage = static_cast<char *>(calldata);
this->Warning = true;
break;
}
}
private:
bool Error;
bool Warning;
std::string ErrorMessage;
std::string WarningMessage;
};
template <class vtkReader>
vtkSmartPointer<vtkReader>
read_vtk_file(const std::string& input_filename,
vtkSmartPointer<CGAL::ErrorObserverVtk> errorObserver)
{
vtkSmartPointer<vtkReader> reader = vtkSmartPointer<vtkReader>::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

View File

@ -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 <deque>
#include <iostream>
#include <string>
#include <boost/tuple/tuple.hpp>
#include <iostream>
namespace CGAL{
namespace internal {
namespace IO{
template <class Facegraph, class P, class Derived>
class Generic_facegraph_builder
{
protected:
typedef P Point_3;
typedef std::deque<Point_3> Points_3;
typedef std::vector<std::size_t> Facet;
typedef std::deque<Facet> 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<Derived*>(this)->read(this->is, this->meshPoints, this->mesh);
static_cast<Derived*>(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