mirror of https://github.com/CGAL/cgal
Re-organize and improve BGL IO
This commit is contained in:
parent
6a5972cc3b
commit
423ae6ec84
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue