- Unify the Facegraph builders (GOCAD and STL for now)

- Make a BGL STL_reader
- Add a test for it.
This commit is contained in:
Maxime Gimeno 2019-08-09 13:53:33 +02:00
parent 6dbf2d3d78
commit 6638d51fe8
5 changed files with 257 additions and 135 deletions

View File

@ -39,7 +39,8 @@
#include <CGAL/IO/VTK/vtk_internals.h>
#endif
#include <CGAL/IO/write_vtk.h>
#include <CGAL/IO/GOCAD/Build_from_gocad.h>
#include <CGAL/internal/Generic_facegraph_builder.h>
#include <CGAL/IO/STL/STL_reader.h>
namespace CGAL {
/*!
@ -411,10 +412,10 @@ bool write_inp(std::ostream& os,
namespace GOCAD_internal{
//Use CRTP to gain access to the protected members without getters/setters.
template <class Facegraph, class P>
class GOCAD_builder : public Build_from_gocad<Facegraph, P, GOCAD_builder<Facegraph, P> >
class GOCAD_builder : public CGAL::internal::IO::Generic_facegraph_builder<Facegraph, P, GOCAD_builder<Facegraph, P> >
{
typedef GOCAD_builder<Facegraph, P> Self;
typedef Build_from_gocad<Facegraph, P, Self> Base;
typedef CGAL::internal::IO::Generic_facegraph_builder<Facegraph, P, Self> Base;
typedef typename Base::Point_3 Point_3;
typedef typename Base::Points_3 Points_3;
typedef typename Base::Facet Facet;
@ -437,13 +438,64 @@ public:
for(size_type i=0; i < this->mesh.size(); i++){
std::array<vertex_descriptor, 3> face;
face[0] = vertices[this->mesh[i].template get<0>()];
face[1] = vertices[this->mesh[i].template get<1>()];
face[2] = vertices[this->mesh[i].template get<2>()];
face[0] = vertices[this->mesh[i][0]];
face[1] = vertices[this->mesh[i][1]];
face[2] = vertices[this->mesh[i][2]];
CGAL::Euler::add_face(face, graph);
}
}
void
read(std::istream& input, Points_3& points, Surface& surface)
{
int offset = 0;
char c;
std::string s, tface("TFACE");
int i,j,k;
Point_3 p;
bool vertices_read = false;
while(input >> s){
if(s == tface){
break;
}
std::string::size_type idx;
if((idx = s.find("name")) != std::string::npos){
std::istringstream str(s.substr(idx+5));
str >> this->name;
}
if((idx = s.find("color")) != std::string::npos){
std::istringstream str(s.substr(idx+6));
str >> this->color;
}
}
std::getline(input, s);
while(input.get(c)){
if((c == 'V')||(c == 'P')){
input >> s >> i >> p;
if(! vertices_read){
vertices_read = true;
offset -= i; // Some files start with index 0 others with 1
}
points.push_back(p);
} else if(vertices_read && (c == 'T')){
input >> c >> c >> c >> i >> j >> k;
typename Base::Facet new_face(3);
new_face[0] = offset+i;
new_face[1] = offset+j;
new_face[2] = offset+k;
surface.push_back(new_face);
} else if(c == 'E'){
break;
}
std::getline(input, s);
}
}
};
}//end GOCAD_internal
@ -912,6 +964,67 @@ write_STL(const TriangleMesh& tm, std::ostream& out)
return out;
}
namespace STL_internal
{
//Use CRTP to gain access to the protected members without getters/setters.
template <class Facegraph, class P>
class STL_builder : public CGAL::internal::IO::Generic_facegraph_builder<Facegraph, P, STL_builder<Facegraph, P> >
{
typedef STL_builder<Facegraph, P> Self;
typedef CGAL::internal::IO::Generic_facegraph_builder<Facegraph, P, Self> Base;
typedef typename Base::Point_3 Point_3;
typedef typename Base::Points_3 Points_3;
typedef typename Base::Facet Facet;
typedef typename Base::Surface Surface;
public:
STL_builder(std::istream& is_)
:Base(is_){}
void do_construct(Facegraph& graph)
{
typedef typename boost::graph_traits<Facegraph>::vertex_descriptor
vertex_descriptor;
std::vector<vertex_descriptor> vertices(this->meshPoints.size());
for(std::size_t id = 0; id < this->meshPoints.size(); ++id)
{
vertices[id] = add_vertex( this->meshPoints[id], graph);
}
// graph.begin_surface( meshPoints.size(), mesh.size());
typedef typename Points_3::size_type size_type;
for(size_type i=0; i < this->mesh.size(); i++){
std::array<vertex_descriptor, 3> face;
face[0] = vertices[this->mesh[i][0]];
face[1] = vertices[this->mesh[i][1]];
face[2] = vertices[this->mesh[i][2]];
CGAL::Euler::add_face(face, graph);
}
}
void
read(std::istream& input, Points_3& points, Surface& surface)
{
read_STL(input, points, surface);
}
};
} // end STL_internal
template <class TriangleMesh>
bool
read_STL(TriangleMesh& tm, std::istream& in)
{
//typedef typename Polyhedron::HalfedgeDS HDS;
typedef typename boost::property_traits<typename boost::property_map<TriangleMesh, CGAL::vertex_point_t>::type>::value_type Point_3;
STL_internal::STL_builder<TriangleMesh, Point_3> builder(in);
builder(tm);
bool ok = in.good() || in.eof();
ok &= tm.is_valid();
return ok;
}
} // namespace CGAL

View File

@ -162,22 +162,65 @@ bool test_gocad()
return true;
}
template<class FaceGraph>
bool test_STL()
{
FaceGraph fg;
CGAL::make_tetrahedron(Point(0, 0, 0), Point(1, 1, 0),
Point(2, 0, 1), Point(3, 0, 0), fg);
std::ostringstream out;
CGAL::write_STL(fg, out);
if(out.fail())
{
std::cerr<<"Tetrahedron writing failed."<<std::endl;
return false;
}
FaceGraph fg2;
std::istringstream in( out.str());
if(!CGAL::read_STL(fg2, in)){
std::cerr<<"Tetrahedron reading failed."<<std::endl;
return false;
}
if(num_vertices(fg2) != 4){
std::cerr<<"Wrong number of vertices: 4 != "<<num_vertices(fg2)<<std::endl;
return false;
}
if(num_faces(fg2) != 4)
{
std::cerr<<"Wrong number of faces: 4 != "<<num_faces(fg2)<<std::endl;
return false;
}
return true;
}
int main(int argc, char** argv)
{
const char* filename=(argc>1)?argv[1]:"data/prim.off";
//OFF
test_bgl_read_write<Polyhedron>(filename);
test_bgl_read_write<SM>(filename);
test_bgl_read_write<LCC>(filename);
#ifdef CGAL_USE_OPENMESH
test_bgl_read_write<OMesh>(filename);
#endif
//GOCAD
if(!test_gocad<Polyhedron>())
return 1;
if(!test_gocad<SM>())
return 1;
if(!test_gocad<LCC>())
return 1;
#ifdef CGAL_USE_OPENMESH
test_bgl_read_write<OMesh>(filename);
#endif
//STL
if(!test_STL<Polyhedron>())
return 1;
if(!test_STL<SM>())
return 1;
if(!test_STL<LCC>())
return 1;
//VTP
#ifdef CGAL_USE_VTK
if(!test_bgl_vtp<Polyhedron>())
return 1;

View File

@ -1,111 +0,0 @@
// Copyright (c) 2019 GeometryFactory
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_IO_GOCAD_BUILD_FROM_GOCAD_H
#define CGAL_IO_GOCAD_BUILD_FROM_GOCAD_H
#include <deque>
#include <iostream>
#include <string>
#include <boost/tuple/tuple.hpp>
#include <iostream>
namespace CGAL{
namespace GOCAD_internal {
template <class Facegraph, class P, class Derived>
class Build_from_gocad
{
protected:
typedef P Point_3;
typedef std::deque<Point_3> Points_3;
typedef boost::tuple<int,int,int> Facet;
typedef std::deque<Facet> Surface;
public:
std::string name, color;
Build_from_gocad(std::istream& is_)
: is(is_), counter(0)
{}
void do_construct(){} //specific to Facegraph (declared in BGL)
void
read(std::istream& input, Points_3& points, Surface& surface, int offset = 0)
{
char c;
std::string s, tface("TFACE");
int i,j,k;
Point_3 p;
bool vertices_read = false;
while(input >> s){
if(s == tface){
break;
}
std::string::size_type idx;
if((idx = s.find("name")) != std::string::npos){
std::istringstream str(s.substr(idx+5));
str >> name;
}
if((idx = s.find("color")) != std::string::npos){
std::istringstream str(s.substr(idx+6));
str >> color;
}
}
std::getline(input, s);
while(input.get(c)){
if((c == 'V')||(c == 'P')){
input >> s >> i >> p;
if(! vertices_read){
vertices_read = true;
offset -= i; // Some files start with index 0 others with 1
}
points.push_back(p);
} else if(vertices_read && (c == 'T')){
input >> c >> c >> c >> i >> j >> k;
surface.push_back(boost::make_tuple(offset+i, offset+j, offset+k));
} else if(c == 'E'){
break;
}
std::getline(input, s);
}
}
void operator()( Facegraph& graph)
{
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 GOCAD_internal
}//end CGAL
#endif // CGAL_IO_GOCAD_BUILD_FROM_GOCAD_H

View File

@ -34,14 +34,17 @@
namespace CGAL {
template <class Point, class Triangle>
template <class PointRange, class TriangleRange, typename IndexMap>
bool read_ASCII_facet(std::istream& input,
std::vector<Point>& points,
std::vector<Triangle>& facets,
PointRange& points,
TriangleRange& facets,
int& index,
std::map<Point, int >& index_map,
IndexMap& index_map,
bool verbose = false)
{
typedef typename PointRange::value_type Point;
typedef typename TriangleRange::value_type Triangle;
// Here, we have already read the word 'facet' and are looking to read till 'endfacet'
std::string s;
@ -113,12 +116,14 @@ bool read_ASCII_facet(std::istream& input,
return false;
}
template <class Point, class Triangle>
template <class PointRange, class TriangleRange>
bool parse_ASCII_STL(std::istream& input,
std::vector<Point>& points,
std::vector<Triangle>& facets,
PointRange& points,
TriangleRange& facets,
bool verbose = false)
{
typedef typename PointRange::value_type Point;
typedef typename TriangleRange::value_type Triangle;
if(verbose)
std::cout << "Parsing ASCII file..." << std::endl;
@ -162,12 +167,15 @@ bool parse_ASCII_STL(std::istream& input,
return true;
}
template <typename Point, typename Triangle>
template <class PointRange, class TriangleRange>
bool parse_binary_STL(std::istream& input,
std::vector<Point>& points,
std::vector<Triangle>& facets,
PointRange& points,
TriangleRange& facets,
bool verbose = false)
{
typedef typename PointRange::value_type Point;
typedef typename TriangleRange::value_type Triangle;
if(verbose)
std::cout << "Parsing binary file..." << std::endl;
@ -301,10 +309,10 @@ bool parse_binary_STL(std::istream& input,
// Although the STL file format uses triangles, it is convenient to be able to use vectors
// and other models of the `SequenceContainer` (instead of arrays) for the face type,
// to avoid having to convert the to apply polygon soup reparation algorithms.
template <class Point, class Triangle>
template <class PointRange, class TriangleRange>
bool read_STL(std::istream& input,
std::vector<Point>& points,
std::vector<Triangle>& facets,
PointRange& points,
TriangleRange& facets,
bool verbose = false)
{
int pos = 0;

View File

@ -0,0 +1,69 @@
// Copyright (c) 2019 GeometryFactory
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
// 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<int> 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