From 6638d51fe84a3ecfad5f1239a3f5fc96ba86ef0f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 9 Aug 2019 13:53:33 +0200 Subject: [PATCH] - Unify the Facegraph builders (GOCAD and STL for now) - Make a BGL STL_reader - Add a test for it. --- BGL/include/CGAL/boost/graph/io.h | 125 +++++++++++++++++- BGL/test/BGL/test_bgl_read_write.cpp | 51 ++++++- .../include/CGAL/IO/GOCAD/Build_from_gocad.h | 111 ---------------- .../include/CGAL/IO/STL/STL_reader.h | 36 +++-- .../CGAL/internal/Generic_facegraph_builder.h | 69 ++++++++++ 5 files changed, 257 insertions(+), 135 deletions(-) delete mode 100644 Stream_support/include/CGAL/IO/GOCAD/Build_from_gocad.h create mode 100644 Stream_support/include/CGAL/internal/Generic_facegraph_builder.h diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index a6f28a93809..24b022ce92d 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -39,7 +39,8 @@ #include #endif #include -#include +#include +#include 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 GOCAD_builder : public Build_from_gocad > +class GOCAD_builder : public CGAL::internal::IO::Generic_facegraph_builder > { typedef GOCAD_builder Self; - typedef Build_from_gocad Base; + typedef CGAL::internal::IO::Generic_facegraph_builder 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 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 STL_builder : public CGAL::internal::IO::Generic_facegraph_builder > +{ + typedef STL_builder Self; + typedef CGAL::internal::IO::Generic_facegraph_builder 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::vertex_descriptor + vertex_descriptor; + + std::vector 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 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 +bool +read_STL(TriangleMesh& tm, std::istream& in) +{ + //typedef typename Polyhedron::HalfedgeDS HDS; + typedef typename boost::property_traits::type>::value_type Point_3; + + STL_internal::STL_builder builder(in); + builder(tm); + bool ok = in.good() || in.eof(); + ok &= tm.is_valid(); + return ok; +} + } // namespace CGAL diff --git a/BGL/test/BGL/test_bgl_read_write.cpp b/BGL/test/BGL/test_bgl_read_write.cpp index bb3811c3393..9eb69c2cc06 100644 --- a/BGL/test/BGL/test_bgl_read_write.cpp +++ b/BGL/test/BGL/test_bgl_read_write.cpp @@ -162,22 +162,65 @@ bool test_gocad() return true; } +template +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."<(filename); test_bgl_read_write(filename); test_bgl_read_write(filename); +#ifdef CGAL_USE_OPENMESH + test_bgl_read_write(filename); +#endif + //GOCAD if(!test_gocad()) return 1; if(!test_gocad()) return 1; if(!test_gocad()) return 1; -#ifdef CGAL_USE_OPENMESH - test_bgl_read_write(filename); -#endif + //STL + if(!test_STL()) + return 1; + if(!test_STL()) + return 1; + if(!test_STL()) + return 1; + //VTP #ifdef CGAL_USE_VTK if(!test_bgl_vtp()) return 1; diff --git a/Stream_support/include/CGAL/IO/GOCAD/Build_from_gocad.h b/Stream_support/include/CGAL/IO/GOCAD/Build_from_gocad.h deleted file mode 100644 index d2bb22c0821..00000000000 --- a/Stream_support/include/CGAL/IO/GOCAD/Build_from_gocad.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -namespace CGAL{ - -namespace GOCAD_internal { -template -class Build_from_gocad -{ -protected: - typedef P Point_3; - typedef std::deque Points_3; - typedef boost::tuple Facet; - typedef std::deque 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(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 - diff --git a/Stream_support/include/CGAL/IO/STL/STL_reader.h b/Stream_support/include/CGAL/IO/STL/STL_reader.h index e4056a99c0f..f5249ae6cee 100644 --- a/Stream_support/include/CGAL/IO/STL/STL_reader.h +++ b/Stream_support/include/CGAL/IO/STL/STL_reader.h @@ -34,19 +34,22 @@ namespace CGAL { -template +template bool read_ASCII_facet(std::istream& input, - std::vector& points, - std::vector& facets, + PointRange& points, + TriangleRange& facets, int& index, - std::map& 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; std::string vertex("vertex"), - endfacet("endfacet"); + endfacet("endfacet"); int count = 0; double x,y,z; @@ -113,12 +116,14 @@ bool read_ASCII_facet(std::istream& input, return false; } -template +template bool parse_ASCII_STL(std::istream& input, - std::vector& points, - std::vector& 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 +template bool parse_binary_STL(std::istream& input, - std::vector& points, - std::vector& 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 +template bool read_STL(std::istream& input, - std::vector& points, - std::vector& facets, + PointRange& points, + TriangleRange& facets, bool verbose = false) { int pos = 0; diff --git a/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h b/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h new file mode 100644 index 00000000000..fa69b3a16a9 --- /dev/null +++ b/Stream_support/include/CGAL/internal/Generic_facegraph_builder.h @@ -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 +#include +#include +#include +#include + +namespace CGAL{ + +namespace internal { +namespace IO{ +template +class Generic_facegraph_builder +{ +protected: + typedef P Point_3; + typedef std::deque Points_3; + typedef std::vector Facet; + typedef std::deque 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(this)->read(this->is, this->meshPoints, this->mesh); + static_cast(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