From c4da8690cb1f8daf88c696d46ca81518b8881eea Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 26 Apr 2018 14:00:06 +0200 Subject: [PATCH 01/84] Add NamedParameters to the off IO functions. --- BGL/include/CGAL/boost/graph/io.h | 109 ++++++++++++++---- .../Linear_cell_complex_2/surface_mesh/IO.h | 4 + .../surface_mesh/IO_off.cpp | 33 ++++-- .../include/CGAL/IO/Polyhedron_iostream.h | 54 +++++++-- .../CGAL/IO/generic_print_polyhedron.h | 23 ++-- Polyhedron_IO/include/CGAL/IO/print_OFF.h | 14 ++- .../include/CGAL/Surface_mesh/Surface_mesh.h | 34 +++++- 7 files changed, 215 insertions(+), 56 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index 52f2c046a3e..4a3e88ed66c 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -32,24 +32,36 @@ #include #include +#include +#include namespace CGAL { /*! \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`. */ -template +template bool write_off(std::ostream& os, - const FaceGraph& g) + const FaceGraph& g, + const NamedParameters& np) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::graph_traits::vertices_size_type vertices_size_type; typedef typename boost::graph_traits::faces_size_type faces_size_type; - typename boost::property_map::const_type vpm = get(CGAL::vertex_point,g); + typename Polygon_mesh_processing::GetVertexPointMap::const_type + vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); vertices_size_type nv = static_cast(std::distance(vertices(g).first, vertices(g).second)); faces_size_type nf = static_cast(std::distance(faces(g).first, faces(g).second)); @@ -78,21 +90,45 @@ bool write_off(std::ostream& os, \sa Overloads of this function for specific models of the concept `FaceGraph`. */ +template +bool write_off(const char* fname, + const FaceGraph& g, + const NamedParameters& np) +{ + std::ofstream out(fname); + if(out.good()){ + return write_off(out,g, np); + } + return false; +} + +template +bool write_off(const std::string& fname, + const FaceGraph& g, + const NamedParameters& np) +{ return write_off(fname.c_str(), g, np); } + + +template +bool write_off(std::ostream& os, + const FaceGraph& g) +{ + return write_off(os, g, + parameters::all_default()); +} template bool write_off(const char* fname, const FaceGraph& g) { - std::ofstream out(fname); - if(out.good()){ - return write_off(out,g); - } - return false; + return write_off(fname,g, + parameters::all_default()); } template bool write_off(const std::string& fname, const FaceGraph& g) -{ return write_off(fname.c_str(), g); } +{ return write_off(fname, g, + parameters::all_default()); } namespace internal { namespace read_off_tools { @@ -122,14 +158,21 @@ inline std::string next_non_comment(std::istream& is) /*! \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. */ -template +template bool read_off(std::istream& is, - FaceGraph& g) + FaceGraph& g, + NamedParameters np) { using namespace internal::read_off_tools; @@ -137,9 +180,11 @@ bool read_off(std::istream& is, typedef typename boost::graph_traits::vertices_size_type vertices_size_type; typedef typename boost::graph_traits::faces_size_type faces_size_type; - typedef typename boost::property_map::type Vpm; + typedef typename Polygon_mesh_processing::GetVertexPointMap::type Vpm; typedef typename boost::property_traits::value_type Point_3; - Vpm vpm = get(CGAL::vertex_point,g); + + Vpm vpm = choose_param(get_param(np, internal_np::vertex_point), + get_property_map(CGAL::vertex_point, g)); vertices_size_type nv, nvf; faces_size_type nf; int ignore; @@ -182,6 +227,12 @@ bool read_off(std::istream& is, return true; } +template +bool read_off(std::istream& is, + FaceGraph& g) +{ + return read_off(is, g, parameters::all_default()); +} /*! \ingroup PkgBGLIOFct @@ -191,36 +242,52 @@ bool read_off(std::istream& is, \attention The graph `g` is not cleared, and the data from the stream are added. */ -template +template bool read_off(const char* fname, - FaceGraph& g) + FaceGraph& g, + NamedParameters np) { std::ifstream in(fname); if(in.good()){ - return read_off(in, g); + return read_off(in, g, np); } return false; } template -bool read_off(const std::string& fname, +bool read_off(const char* fname, FaceGraph& g) -{ return read_off(fname.c_str(), g); } +{ + return read_off(fname, g, parameters::all_default()); +} + +template +bool read_off(const std::string& fname, + FaceGraph& g, + NamedParameters np) +{ return read_off(fname.c_str(), g, np); } template +bool read_off(const std::string& fname, + FaceGraph& g) +{ return read_off(fname, g, parameters::all_default()); } + +template bool write_inp(std::ostream& os, const FaceGraph& g, std::string name, - std::string type) + std::string type, + const NamedParameters& np) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - typedef typename boost::property_map::const_type VPM; + typedef typename Polygon_mesh_processing::GetVertexPointMap::const_type VPM; typedef typename boost::property_traits::value_type Point_3; - VPM vpm = get(CGAL::vertex_point,g); + VPM vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, g)); os << "*Part, name=" << name << "\n*Node\n"; boost::container::flat_map reindex; diff --git a/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO.h b/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO.h index ad841bce7d0..d91ed0a23be 100644 --- a/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO.h +++ b/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO.h @@ -33,9 +33,13 @@ bool read_mesh(Surface_mesh& mesh, const std::string& filename); +template +bool read_off(Surface_mesh& mesh, const std::string& filename, NamedParameters& np); bool read_off(Surface_mesh& mesh, const std::string& filename); bool write_mesh(const Surface_mesh& mesh, const std::string& filename); +template +bool write_off(const Surface_mesh& mesh, const std::string& filename, const NamedParameters& np); bool write_off(const Surface_mesh& mesh, const std::string& filename); diff --git a/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO_off.cpp b/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO_off.cpp index fbcd3bd1042..9642d452a04 100644 --- a/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO_off.cpp +++ b/Linear_cell_complex/benchmark/Linear_cell_complex_2/surface_mesh/IO_off.cpp @@ -24,7 +24,8 @@ #include "IO.h" #include - +#include +#include //== IMPLEMENTATION =========================================================== @@ -39,12 +40,13 @@ template void read(FILE* in, T& t) //----------------------------------------------------------------------------- - +template bool read_off_ascii(Surface_mesh& mesh, FILE* in, const bool has_normals, const bool has_texcoords, - const bool has_colors) + const bool has_colors, + NamedParameters& np) { char line[100], *lp; unsigned int i, j, items, idx, nc; @@ -52,6 +54,9 @@ bool read_off_ascii(Surface_mesh& mesh, Vec3f p, n, c; Vec2f t; Surface_mesh::Vertex v; + typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type + vpm = choose_param(get_param(np, CGAL::boost::internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); // properties @@ -78,7 +83,8 @@ bool read_off_ascii(Surface_mesh& mesh, // position items = sscanf(lp, "%f %f %f%n", &p[0], &p[1], &p[2], &nc); assert(items==3); - v = mesh.add_vertex((Point)p); + Surface_mesh::Vertex v = mesh.add_vertex(); + put(vpm, v, (Point)p); lp += nc; // normal @@ -146,12 +152,13 @@ bool read_off_ascii(Surface_mesh& mesh, //----------------------------------------------------------------------------- - +template bool read_off_binary(Surface_mesh& mesh, FILE* in, const bool has_normals, const bool has_texcoords, - const bool has_colors) + const bool has_colors, + NamedParameters& np) { unsigned int i, j, idx; unsigned int nV, nF, nE; @@ -169,6 +176,9 @@ bool read_off_binary(Surface_mesh& mesh, Surface_mesh::Vertex_property texcoords; if (has_normals) normals = mesh.vertex_property("v:normal"); if (has_texcoords) texcoords = mesh.vertex_property("v:texcoord"); + typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type + vpm = choose_param(get_param(np, CGAL::boost::internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); // #Vertice, #Faces, #Edges @@ -184,7 +194,8 @@ bool read_off_binary(Surface_mesh& mesh, { // position read(in, p); - v = mesh.add_vertex((Point)p); + Surface_mesh::Vertex v = mesh.add_vertex(); + put(vpm, v, (Point)p); // normal if (has_normals) @@ -224,8 +235,8 @@ bool read_off_binary(Surface_mesh& mesh, //----------------------------------------------------------------------------- - -bool read_off(Surface_mesh& mesh, const std::string& filename) +template +bool read_off(Surface_mesh& mesh, const std::string& filename, NamedParameters& np) { char line[100]; bool has_texcoords = false; @@ -274,8 +285,8 @@ bool read_off(Surface_mesh& mesh, const std::string& filename) // read as ASCII or binary bool ok = (is_binary ? - read_off_binary(mesh, in, has_normals, has_texcoords, has_colors) : - read_off_ascii(mesh, in, has_normals, has_texcoords, has_colors)); + read_off_binary(mesh, in, has_normals, has_texcoords, has_colors, np) : + read_off_ascii(mesh, in, has_normals, has_texcoords, has_colors, np)); fclose(in); diff --git a/Polyhedron_IO/include/CGAL/IO/Polyhedron_iostream.h b/Polyhedron_IO/include/CGAL/IO/Polyhedron_iostream.h index c334668c635..e8173637eda 100644 --- a/Polyhedron_IO/include/CGAL/IO/Polyhedron_iostream.h +++ b/Polyhedron_IO/include/CGAL/IO/Polyhedron_iostream.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include namespace CGAL { @@ -36,16 +38,54 @@ namespace CGAL { template < class Traits, class Items, template < class T, class I, class A> - class HDS, class Alloc> + class HDS, class Alloc, class NamedParameters> bool -write_off( std::ostream& out, const Polyhedron_3& P){ +write_off( std::ostream& out, const Polyhedron_3& P, const NamedParameters& np){ // writes P to `out' in PRETTY, ASCII or BINARY format // as the stream indicates. File_header_OFF header( is_binary( out), ! is_pretty( out), false); - CGAL::print_polyhedron_with_header_OFF( out, P, header); + typename CGAL::Polygon_mesh_processing::GetVertexPointMap, NamedParameters>::const_type + vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, P)); + CGAL::print_polyhedron_with_header_OFF( out, P, header, vpm); return out.good(); } +template < class Traits, + class Items, + template < class T, class I, class A> + class HDS, class Alloc> +bool +write_off( std::ostream& out, const Polyhedron_3& P){ + return write_off(out, P, parameters::all_default()); +} + +template < class Traits, + class Items, + template < class T, class I, class A> + class HDS, class Alloc, + class NamedParameters> +bool +read_off(std::istream& in, + Polyhedron_3& P, + NamedParameters np) { + // reads a polyhedron from `in' and appends it to P. + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap, NamedParameters>::type Vpm; + Vpm vpm = choose_param(get_param(np, internal_np::vertex_point), + get_property_map(CGAL::vertex_point, P)); + CGAL::scan_OFF( in, P); + if(!boost::is_default_param(get_param(np, internal_np::vertex_point))) + { + typedef typename boost::graph_traits >::vertex_descriptor Vertex; + typename property_map_selector, boost::vertex_point_t>::type + def_vpm = get_property_map(CGAL::vertex_point, P); + BOOST_FOREACH(Vertex v, vertices(P)) + { + put(vpm, v, get(def_vpm, v)); + } + } + return in.good(); +} template < class Traits, class Items, @@ -53,13 +93,11 @@ template < class Traits, class HDS, class Alloc> bool read_off(std::istream& in, - Polyhedron_3& P) { - // reads a polyhedron from `in' and appends it to P. - CGAL::scan_OFF( in, P); - return in.good(); + Polyhedron_3& P) +{ + return read_off(in, P, parameters::all_default()); } - template < class Traits, class Items, template < class T, class I, class A> diff --git a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h index ca27656cf7e..2e93e929782 100644 --- a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h +++ b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h @@ -24,18 +24,18 @@ #include - #include #include #include namespace CGAL { -template +template void generic_print_polyhedron( std::ostream& out, const Polyhedron& P, - Writer& writer) { + Writer& writer, + const Vpm& vpm ) { // writes P to `out' in the format provided by `writer'. typedef typename Polyhedron::Vertex_const_iterator VCI; typedef typename Polyhedron::Facet_const_iterator FCI; @@ -45,10 +45,10 @@ generic_print_polyhedron( std::ostream& out, P.size_of_vertices(), P.size_of_halfedges(), P.size_of_facets()); - for( VCI vi = P.vertices_begin(); vi != P.vertices_end(); ++vi) { - writer.write_vertex( ::CGAL::to_double( vi->point().x()), - ::CGAL::to_double( vi->point().y()), - ::CGAL::to_double( vi->point().z())); + BOOST_FOREACH(typename boost::graph_traits::vertex_descriptor vi, vertices(P)) { + writer.write_vertex( ::CGAL::to_double( get(vpm, vi).x()), + ::CGAL::to_double( get(vpm, vi).y()), + ::CGAL::to_double( get(vpm, vi).z())); } typedef Inverse_index< VCI> Index; Index index( P.vertices_begin(), P.vertices_end()); @@ -69,6 +69,15 @@ generic_print_polyhedron( std::ostream& out, writer.write_footer(); } +template +void +generic_print_polyhedron( std::ostream& out, + const Polyhedron& P, + Writer& writer) +{ + generic_print_polyhedron(out, P, writer, + get_property_map(CGAL::vertex_point, P)); +} } //namespace CGAL #endif // CGAL_IO_GENERIC_PRINT_POLYHEDRON_H // // EOF // diff --git a/Polyhedron_IO/include/CGAL/IO/print_OFF.h b/Polyhedron_IO/include/CGAL/IO/print_OFF.h index b96caaead2a..493117a60eb 100644 --- a/Polyhedron_IO/include/CGAL/IO/print_OFF.h +++ b/Polyhedron_IO/include/CGAL/IO/print_OFF.h @@ -33,16 +33,24 @@ namespace CGAL { -template +template void print_polyhedron_with_header_OFF( std::ostream& out, const Polyhedron& P, - const File_header_OFF& header) { + const File_header_OFF& header, + const Vpm& vpm) { File_writer_OFF writer( header); writer.header().set_polyhedral_surface( true); writer.header().set_halfedges( P.size_of_halfedges()); - generic_print_polyhedron( out, P, writer); + generic_print_polyhedron( out, P, writer, vpm); } +template +void print_polyhedron_with_header_OFF( std::ostream& out, + const Polyhedron& P, + const File_header_OFF& header) +{ + print_polyhedron_with_header_OFF(out, P, header); +} template void print_polyhedron_OFF( std::ostream& out, diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index aa410a18afb..d362415371d 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -55,6 +55,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -1977,9 +1979,11 @@ private: //------------------------------------------------------- private data /// \relates Surface_mesh /// Inserts the surface mesh in an output stream in Ascii OFF format. /// Only the \em point property is inserted in the stream. + /// If an alternative vertex_point map is given through `np`, + /// then it will be used instead of the default one. /// \pre `operator<<(std::ostream&,const P&)` must be defined. - template - bool write_off(std::ostream& os, const Surface_mesh

& sm) { + template + bool write_off(std::ostream& os, const Surface_mesh

& sm, const NamedParameters& np) { typedef Surface_mesh

Mesh; typedef typename Mesh::Vertex_index Vertex_index; typedef typename Mesh::Face_index Face_index; @@ -1996,10 +2000,14 @@ private: //------------------------------------------------------- private data else os << "COFF\n" << sm.number_of_vertices() << " " << sm.number_of_faces() << " 0\n"; std::vector reindex; + typename Polygon_mesh_processing::GetVertexPointMap, NamedParameters>::const_type + vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, sm)); reindex.resize(sm.num_vertices()); int n = 0; BOOST_FOREACH(Vertex_index v, sm.vertices()){ - os << sm.point(v); + + os << get(vpm, v); if(has_vcolors) { CGAL::Color color = vcolors[v]; @@ -2058,12 +2066,14 @@ private: //------------------------------------------------------- private data /// format and appends it to the surface mesh `sm`. /// The operator reads the point property as well as "v:normal", "v:color", and "f:color". /// Vertex texture coordinates are ignored. + /// If an alternative vertex_point map is given through `np`, + /// then it will be used instead of the default one. /// \pre `operator>>(std::istream&,const P&)` must be defined. /// \pre The data in the stream must represent a two-manifold. If this is not the case /// the `failbit` of `is` is set and the mesh cleared. - template - bool read_off(std::istream& is, Surface_mesh

& sm) + template + bool read_off(std::istream& is, Surface_mesh

& sm, NamedParameters np) { typedef Surface_mesh

Mesh; typedef typename Kernel_traits

::Kernel K; @@ -2071,6 +2081,9 @@ private: //------------------------------------------------------- private data typedef typename Mesh::Face_index Face_index; typedef typename Mesh::Vertex_index Vertex_index; typedef typename Mesh::size_type size_type; + typename CGAL::Polygon_mesh_processing::GetVertexPointMap, NamedParameters>::type + vpm = choose_param(get_param(np, CGAL::internal_np::vertex_point), + get_property_map(CGAL::vertex_point, sm)); int n, f, e; std::string off; is >> sm_skip_comments; @@ -2097,7 +2110,11 @@ private: //------------------------------------------------------- private data for(int i=0; i < n; i++){ is >> sm_skip_comments; is >> p; - Vertex_index vi= sm.add_vertex(p); + + Vertex_index vi = sm.add_vertex(); + put(vpm, vi, p); + + vertexmap[i] = vi; if(v_has_normals){ is >> v; @@ -2167,6 +2184,11 @@ private: //------------------------------------------------------- private data } + template + bool read_off(std::istream& is, Surface_mesh

& sm) + { + return read_off(is, sm, parameters::all_default()); + } /// \relates Surface_mesh /// This operator calls `read_off(std::istream& is, CGAL::Surface_mesh& sm)`. From 7a5e8211838eb7ccae7db90a1f297b4a7c6ce52a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 27 Apr 2018 11:01:23 +0200 Subject: [PATCH 02/84] fixes --- Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h | 4 ++++ Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h index 2e93e929782..35726c19313 100644 --- a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h +++ b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h @@ -24,6 +24,10 @@ #include +#include +#include +#include +#include #include #include #include diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index d362415371d..e41b3da6d39 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -2032,13 +2032,17 @@ private: //------------------------------------------------------- private data return os.good(); } + template + bool write_off(std::ostream& os, const Surface_mesh

& sm) { + return write_off(os, sm, CGAL::parameters::all_default()); + } /// \relates Surface_mesh /// /// This operator calls `write_off(std::ostream& os, const CGAL::Surface_mesh& sm)`. template std::ostream& operator<<(std::ostream& os, const Surface_mesh

& sm) { - write_off(os, sm); + write_off(os, sm, CGAL::parameters::all_default()); return os; } From 7aa9c940e7755487107e0a0c4e3f752bcc3ac90c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 23 Apr 2018 11:59:33 +0200 Subject: [PATCH 03/84] Add action for stitching by CC to stitching_plugin --- .../PMP/Polyhedron_stitching_plugin.cpp | 94 ++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp index 6fff603f995..2b8ca4cb4ac 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -46,17 +47,23 @@ class Polyhedron_demo_polyhedron_stitching_plugin : QAction* actionDetectBorders; QAction* actionStitchBorders; + QAction* actionStitchByCC; public: - QList actions() const { return QList() << actionDetectBorders << actionStitchBorders; } + QList actions() const { return QList() << actionDetectBorders << actionStitchBorders << actionStitchByCC; } void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* /* m */) { scene = scene_interface; actionDetectBorders= new QAction(tr("Detect Boundaries"), mainWindow); - actionStitchBorders= new QAction(tr("Stitch Duplicated Boundaries"), mainWindow); actionDetectBorders->setObjectName("actionDetectBorders"); + actionDetectBorders->setProperty("subMenuName", "Polygon Mesh Processing"); + actionStitchBorders= new QAction(tr("Stitch Duplicated Boundaries"), mainWindow); actionStitchBorders->setObjectName("actionStitchBorders"); actionStitchBorders->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); - actionDetectBorders->setProperty("subMenuName", "Polygon Mesh Processing"); + + actionStitchByCC= new QAction(tr("Stitch Following Connected Components"), mainWindow); + actionStitchByCC->setObjectName("actionStitchByCC"); + actionStitchByCC->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); + autoConnectActions(); } @@ -75,10 +82,14 @@ public: template void on_actionStitchBorders_triggered(Scene_interface::Item_id index); + + template + void on_actionStitchByCC_triggered(Scene_interface::Item_id index); public Q_SLOTS: void on_actionDetectBorders_triggered(); void on_actionStitchBorders_triggered(); + void on_actionStitchByCC_triggered(); }; // end Polyhedron_demo_polyhedron_stitching_plugin @@ -176,4 +187,81 @@ void Polyhedron_demo_polyhedron_stitching_plugin::on_actionStitchBorders_trigger on_actionStitchBorders_triggered(index); } } + +template +void Polyhedron_demo_polyhedron_stitching_plugin::on_actionStitchByCC_triggered(Scene_interface::Item_id index) +{ + Item* item = + qobject_cast(scene->item(index)); + + if(!item) + return; + typedef typename Item::Face_graph Face_graph; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + //typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typename Item::Face_graph* pMesh = item->polyhedron(); + //detect CCs + boost::unordered_map::face_descriptor,int> cc(num_faces(*pMesh)); + std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(*pMesh, boost::make_assoc_property_map(cc)); + + //if only one cc just stitch and stop + if(num_component < 2) + { + CGAL::Polygon_mesh_processing::stitch_borders(*pMesh); + item->invalidateOpenGLBuffers(); + scene->itemChanged(item); + return; + } + //else add each border edge in map with cc + normalize_border(*pMesh); + std::vector > border_edges_per_cc; + border_edges_per_cc.resize(num_component); + BOOST_FOREACH(face_descriptor fd, faces(*pMesh)) + { + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd,*pMesh), *pMesh)) + { + halfedge_descriptor ohd = opposite(hd, *pMesh); + if(is_border(ohd, *pMesh)) + { + border_edges_per_cc[cc[fd]].push_back(ohd); + } + } + } + // foreach cc make pair of corresponding edges. + std::vector > hedges; + typename boost::property_map< Face_graph,CGAL::vertex_point_t>::type vpmap + = get(CGAL::vertex_point, *pMesh); + for(std::size_t i = 0; i < num_component; ++i) + { + for(int j = 0; j < static_cast(border_edges_per_cc[i].size())-1; ++j) + { + halfedge_descriptor h1 = border_edges_per_cc[i].back(); + border_edges_per_cc[i].pop_back(); + Point_3 src1(get(vpmap, source(h1, *pMesh))), tgt1(get(vpmap, target(h1, *pMesh))); + BOOST_FOREACH(halfedge_descriptor h2, border_edges_per_cc[i]) + { + Point_3 src2(get(vpmap, source(h2, *pMesh))), tgt2(get(vpmap, target(h2, *pMesh))); + if(src1 == tgt2 && src2 == tgt1) + { + hedges.push_back(std::make_pair(h1,h2)); + } + } + } + } + + //finally feed the pairs to the stitch_function + CGAL::Polygon_mesh_processing::stitch_borders(*pMesh, hedges); + item->invalidateOpenGLBuffers(); + scene->itemChanged(item); +} + + +void Polyhedron_demo_polyhedron_stitching_plugin::on_actionStitchByCC_triggered() +{ + Q_FOREACH(int index, scene->selectionIndices()){ + on_actionStitchByCC_triggered(index); + on_actionStitchByCC_triggered(index); + } +} #include "Polyhedron_stitching_plugin.moc" From 68de1819cfeaaafe484ea96a648fab33aafba248 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 23 Apr 2018 12:25:33 +0200 Subject: [PATCH 04/84] Move the code to the PMP functio nand document. --- .../CGAL/boost/graph/parameters_interface.h | 1 + .../NamedParameters.txt | 8 +++ .../Polygon_mesh_processing/stitch_borders.h | 65 +++++++++++++++++-- .../PMP/Polyhedron_stitching_plugin.cpp | 58 +---------------- 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index fd75acf47d3..d8de75fb41e 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -64,6 +64,7 @@ CGAL_add_named_parameter(nb_points_per_distance_unit_t, nb_points_per_distance_u CGAL_add_named_parameter(outward_orientation_t, outward_orientation, outward_orientation) CGAL_add_named_parameter(overlap_test_t, overlap_test, do_overlap_test_of_bounded_sides) CGAL_add_named_parameter(preserve_genus_t, preserve_genus, preserve_genus) +CGAL_add_named_parameter(do_stitch_per_cc_t, do_stitch_per_cc, do_stitch_per_cc) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt index d9b8e95c9ac..208a89b28e7 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt @@ -310,6 +310,14 @@ of close meshes should be done in addition to surface intersection tests. \b Default value is `false` \cgalNPEnd +\cgalNPBegin{do_stitch_per_cc} \anchor PMP_do_stitch_per_cc +Parameter used in `stitch_borders()` to indicate whether the automatic borders detection should take the +connected components of the mesh into account. In this case, only the stitchable borders inside a same +connected component will be stictched. +\n +\b Type : `bool` \n +\b Default value is `false` +\cgalNPEnd \cgalNPTableEnd */ diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 8ef15a95303..e86fd8b3309 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -504,6 +505,8 @@ void stitch_borders(PolygonMesh& pmesh, /// \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. /// If this parameter is omitted, an internal property map for /// `CGAL::vertex_point_t` should be available in `PolygonMesh`\cgalParamEnd +/// `CGAL::do_stitch_per_cc_t` specifies if the borders should only be stitched inside their own connected component. +/// Default value is `false`.\cgalParamEnd /// \cgalNamedParamsEnd /// template @@ -517,15 +520,65 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) std::vector< std::pair > hedge_pairs_to_stitch; typedef typename GetVertexPointMap::const_type VPMap; + typedef typename VPMap::value_type Point_3; VPMap vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); + bool stitch_along_ccs = choose_param(get_param(np, internal_np::do_stitch_per_cc), + false); - internal::collect_duplicated_stitchable_boundary_edges(pmesh, - std::back_inserter(hedge_pairs_to_stitch), - internal::Less_for_halfedge(pmesh, vpm), vpm); - - stitch_borders(pmesh, hedge_pairs_to_stitch); - internal::stitch_boundary_cycle_2(pmesh); + if(!stitch_along_ccs) + { + internal::collect_duplicated_stitchable_boundary_edges(pmesh, + std::back_inserter(hedge_pairs_to_stitch), + internal::Less_for_halfedge(pmesh, vpm), vpm); + + stitch_borders(pmesh, hedge_pairs_to_stitch); + internal::stitch_boundary_cycle_2(pmesh); + } + else + { + typedef typename boost::graph_traits::face_descriptor face_descriptor; + boost::unordered_map::face_descriptor,int> cc(num_faces(pmesh)); + std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, boost::make_assoc_property_map(cc)); + + //add each border edge in map with cc + std::vector > border_edges_per_cc; + border_edges_per_cc.resize(num_component); + BOOST_FOREACH(face_descriptor fd, faces(pmesh)) + { + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd,pmesh), pmesh)) + { + halfedge_descriptor ohd = opposite(hd, pmesh); + if(is_border(ohd, pmesh)) + { + border_edges_per_cc[cc[fd]].push_back(ohd); + } + } + } + // foreach cc make pair of corresponding edges. + typename boost::property_map< PolygonMesh,CGAL::vertex_point_t>::type vpmap + = get(CGAL::vertex_point, pmesh); + for(std::size_t i = 0; i < num_component; ++i) + { + for(int j = 0; j < static_cast(border_edges_per_cc[i].size())-1; ++j) + { + halfedge_descriptor h1 = border_edges_per_cc[i].back(); + border_edges_per_cc[i].pop_back(); + Point_3 src1(get(vpmap, source(h1, pmesh))), tgt1(get(vpmap, target(h1, pmesh))); + BOOST_FOREACH(halfedge_descriptor h2, border_edges_per_cc[i]) + { + Point_3 src2(get(vpmap, source(h2, pmesh))), tgt2(get(vpmap, target(h2, pmesh))); + if(src1 == tgt2 && src2 == tgt1) + { + hedge_pairs_to_stitch.push_back(std::make_pair(h1,h2)); + } + } + } + } + + //finally feed the pairs to the stitch_function + CGAL::Polygon_mesh_processing::stitch_borders(pmesh, hedge_pairs_to_stitch); + } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp index 2b8ca4cb4ac..b4ff029da0f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp @@ -196,62 +196,8 @@ void Polyhedron_demo_polyhedron_stitching_plugin::on_actionStitchByCC_triggered( if(!item) return; - typedef typename Item::Face_graph Face_graph; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - //typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typename Item::Face_graph* pMesh = item->polyhedron(); - //detect CCs - boost::unordered_map::face_descriptor,int> cc(num_faces(*pMesh)); - std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(*pMesh, boost::make_assoc_property_map(cc)); - - //if only one cc just stitch and stop - if(num_component < 2) - { - CGAL::Polygon_mesh_processing::stitch_borders(*pMesh); - item->invalidateOpenGLBuffers(); - scene->itemChanged(item); - return; - } - //else add each border edge in map with cc - normalize_border(*pMesh); - std::vector > border_edges_per_cc; - border_edges_per_cc.resize(num_component); - BOOST_FOREACH(face_descriptor fd, faces(*pMesh)) - { - BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd,*pMesh), *pMesh)) - { - halfedge_descriptor ohd = opposite(hd, *pMesh); - if(is_border(ohd, *pMesh)) - { - border_edges_per_cc[cc[fd]].push_back(ohd); - } - } - } - // foreach cc make pair of corresponding edges. - std::vector > hedges; - typename boost::property_map< Face_graph,CGAL::vertex_point_t>::type vpmap - = get(CGAL::vertex_point, *pMesh); - for(std::size_t i = 0; i < num_component; ++i) - { - for(int j = 0; j < static_cast(border_edges_per_cc[i].size())-1; ++j) - { - halfedge_descriptor h1 = border_edges_per_cc[i].back(); - border_edges_per_cc[i].pop_back(); - Point_3 src1(get(vpmap, source(h1, *pMesh))), tgt1(get(vpmap, target(h1, *pMesh))); - BOOST_FOREACH(halfedge_descriptor h2, border_edges_per_cc[i]) - { - Point_3 src2(get(vpmap, source(h2, *pMesh))), tgt2(get(vpmap, target(h2, *pMesh))); - if(src1 == tgt2 && src2 == tgt1) - { - hedges.push_back(std::make_pair(h1,h2)); - } - } - } - } - - //finally feed the pairs to the stitch_function - CGAL::Polygon_mesh_processing::stitch_borders(*pMesh, hedges); + CGAL::Polygon_mesh_processing::stitch_borders(*item->polyhedron(), + CGAL::Polygon_mesh_processing::parameters::do_stitch_per_cc(true)); item->invalidateOpenGLBuffers(); scene->itemChanged(item); } From 4a8375ce853b30bebe3b8c0d7be099fa3e895cd3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 23 Apr 2018 13:57:54 +0200 Subject: [PATCH 05/84] Optimize --- .../CGAL/Polygon_mesh_processing/stitch_borders.h | 13 +++++-------- .../Plugins/PMP/Polyhedron_stitching_plugin.cpp | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index e86fd8b3309..6a8b642d33d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -537,22 +537,19 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) } else { - typedef typename boost::graph_traits::face_descriptor face_descriptor; boost::unordered_map::face_descriptor,int> cc(num_faces(pmesh)); std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, boost::make_assoc_property_map(cc)); //add each border edge in map with cc std::vector > border_edges_per_cc; border_edges_per_cc.resize(num_component); - BOOST_FOREACH(face_descriptor fd, faces(pmesh)) + + BOOST_FOREACH(halfedge_descriptor hd, halfedges(pmesh)) { - BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(halfedge(fd,pmesh), pmesh)) + halfedge_descriptor ohd = opposite(hd, pmesh); + if(is_border(ohd, pmesh)) { - halfedge_descriptor ohd = opposite(hd, pmesh); - if(is_border(ohd, pmesh)) - { - border_edges_per_cc[cc[fd]].push_back(ohd); - } + border_edges_per_cc[cc[face(hd, pmesh)]].push_back(ohd); } } // foreach cc make pair of corresponding edges. diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp index b4ff029da0f..4760ec0335a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp @@ -60,7 +60,7 @@ public: actionStitchBorders->setObjectName("actionStitchBorders"); actionStitchBorders->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); - actionStitchByCC= new QAction(tr("Stitch Following Connected Components"), mainWindow); + actionStitchByCC= new QAction(tr("Stitch Borders Per Connected Components"), mainWindow); actionStitchByCC->setObjectName("actionStitchByCC"); actionStitchByCC->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); From 861a6a16c566c6df25e7e3f29a45986744622a50 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 23 Apr 2018 16:53:09 +0200 Subject: [PATCH 06/84] Fixes --- .../CGAL/boost/graph/parameters_interface.h | 2 +- .../NamedParameters.txt | 8 +++----- .../Polygon_mesh_processing/stitch_borders.h | 18 +++++++++--------- .../PMP/Polyhedron_stitching_plugin.cpp | 3 +-- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index d8de75fb41e..dc40ceeb421 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -64,7 +64,7 @@ CGAL_add_named_parameter(nb_points_per_distance_unit_t, nb_points_per_distance_u CGAL_add_named_parameter(outward_orientation_t, outward_orientation, outward_orientation) CGAL_add_named_parameter(overlap_test_t, overlap_test, do_overlap_test_of_bounded_sides) CGAL_add_named_parameter(preserve_genus_t, preserve_genus, preserve_genus) -CGAL_add_named_parameter(do_stitch_per_cc_t, do_stitch_per_cc, do_stitch_per_cc) +CGAL_add_named_parameter(apply_per_connected_component_t, apply_per_connected_component, apply_per_connected_component) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt index 208a89b28e7..134f0cd11f5 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt @@ -310,11 +310,9 @@ of close meshes should be done in addition to surface intersection tests. \b Default value is `false` \cgalNPEnd -\cgalNPBegin{do_stitch_per_cc} \anchor PMP_do_stitch_per_cc -Parameter used in `stitch_borders()` to indicate whether the automatic borders detection should take the -connected components of the mesh into account. In this case, only the stitchable borders inside a same -connected component will be stictched. -\n +\cgalNPBegin{apply_per_connected_component} \anchor PMP_apply_per_connected_component +Parameter used to indicate whether an algorithm should consider each connected component +of a mesh independently.\n \b Type : `bool` \n \b Default value is `false` \cgalNPEnd diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 6a8b642d33d..b9f9c3f91db 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -520,10 +520,10 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) std::vector< std::pair > hedge_pairs_to_stitch; typedef typename GetVertexPointMap::const_type VPMap; - typedef typename VPMap::value_type Point_3; + typedef typename boost::property_traits::value_type Point_3; VPMap vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); - bool stitch_along_ccs = choose_param(get_param(np, internal_np::do_stitch_per_cc), + bool stitch_along_ccs = choose_param(get_param(np, internal_np::apply_per_connected_component), false); if(!stitch_along_ccs) @@ -537,8 +537,10 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) } else { - boost::unordered_map::face_descriptor,int> cc(num_faces(pmesh)); - std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, boost::make_assoc_property_map(cc)); + typedef CGAL::dynamic_face_property_t Face_property_tag; + typedef typename boost::property_map::type Face_cc_map; + Face_cc_map cc = get(Face_property_tag(), pmesh); + std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, cc); //add each border edge in map with cc std::vector > border_edges_per_cc; @@ -549,22 +551,20 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) halfedge_descriptor ohd = opposite(hd, pmesh); if(is_border(ohd, pmesh)) { - border_edges_per_cc[cc[face(hd, pmesh)]].push_back(ohd); + border_edges_per_cc[get(cc, face(hd, pmesh))].push_back(ohd); } } // foreach cc make pair of corresponding edges. - typename boost::property_map< PolygonMesh,CGAL::vertex_point_t>::type vpmap - = get(CGAL::vertex_point, pmesh); for(std::size_t i = 0; i < num_component; ++i) { for(int j = 0; j < static_cast(border_edges_per_cc[i].size())-1; ++j) { halfedge_descriptor h1 = border_edges_per_cc[i].back(); border_edges_per_cc[i].pop_back(); - Point_3 src1(get(vpmap, source(h1, pmesh))), tgt1(get(vpmap, target(h1, pmesh))); + Point_3 src1(get(vpm, source(h1, pmesh))), tgt1(get(vpm, target(h1, pmesh))); BOOST_FOREACH(halfedge_descriptor h2, border_edges_per_cc[i]) { - Point_3 src2(get(vpmap, source(h2, pmesh))), tgt2(get(vpmap, target(h2, pmesh))); + Point_3 src2(get(vpm, source(h2, pmesh))), tgt2(get(vpm, target(h2, pmesh))); if(src1 == tgt2 && src2 == tgt1) { hedge_pairs_to_stitch.push_back(std::make_pair(h1,h2)); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp index 4760ec0335a..6ee8cf73da5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_stitching_plugin.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -197,7 +196,7 @@ void Polyhedron_demo_polyhedron_stitching_plugin::on_actionStitchByCC_triggered( if(!item) return; CGAL::Polygon_mesh_processing::stitch_borders(*item->polyhedron(), - CGAL::Polygon_mesh_processing::parameters::do_stitch_per_cc(true)); + CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true)); item->invalidateOpenGLBuffers(); scene->itemChanged(item); } From 29e909b87b3dea265031458b9c2e65519c2dfc18 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Apr 2018 10:26:29 +0200 Subject: [PATCH 07/84] Treat nm edges --- .../Polygon_mesh_processing/stitch_borders.h | 189 ++++++++++-------- 1 file changed, 106 insertions(+), 83 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index b9f9c3f91db..a103cf94d5d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -85,54 +85,119 @@ struct Less_for_halfedge const VertexPointMap& vpmap; }; +template +void fill_pairs(const Halfedge& he, + Border_halfedge_map& border_halfedge_map, + Halfedge_pair& halfedge_pairs, + Manifold_halfedge_pair& manifold_halfedge_pairs, + VPMAP vpmap, + const Mesh& pmesh) +{ + typename Border_halfedge_map::iterator set_it; + bool insertion_ok; + CGAL::cpp11::tie(set_it, insertion_ok) + = border_halfedge_map.insert(std::make_pair(he,std::make_pair(1,0))); + + if ( !insertion_ok ){ // we found already a halfedge with the points + ++set_it->second.first; // increase the multiplicity + if(set_it->second.first == 2) + { + if ( get(vpmap, source(he,pmesh))==get(vpmap, target(set_it->first,pmesh)) && + get(vpmap, target(he,pmesh))==get(vpmap, source(set_it->first,pmesh)) ) + { + set_it->second.second = halfedge_pairs.size(); // set the id of the pair in the vector + halfedge_pairs.push_back( std::make_pair(set_it->first, he) ); + manifold_halfedge_pairs.push_back(true); + } + } + else + if ( set_it->second.first > 2 ) + { + manifold_halfedge_pairs[ set_it->second.second ] = false; + } + } +} template OutputIterator collect_duplicated_stitchable_boundary_edges -(PM& pmesh, OutputIterator out, LessHedge less_hedge, const VertexPointMap& vpmap) +(PM& pmesh, OutputIterator out, LessHedge less_hedge, const VertexPointMap& vpmap, + bool per_cc=false) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef std::map, LessHedge> Border_halfedge_map; Border_halfedge_map border_halfedge_map(less_hedge); - std::vector< std::pair > halfedge_pairs; std::vector< bool > manifold_halfedge_pairs; + + typedef CGAL::dynamic_face_property_t Face_property_tag; + typedef typename boost::property_map::type Face_cc_map; + Face_cc_map cc; + std::size_t num_component; + std::vector > border_edges_per_cc; + if(per_cc) + { + cc = get(Face_property_tag(), pmesh); + num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, cc); + border_edges_per_cc.resize(num_component); + } + BOOST_FOREACH(halfedge_descriptor he, halfedges(pmesh)) { if ( !CGAL::is_border(he, pmesh) ) continue; - - typename Border_halfedge_map::iterator set_it; - bool insertion_ok; - CGAL::cpp11::tie(set_it, insertion_ok) - = border_halfedge_map.insert(std::make_pair(he,std::make_pair(1,0))); - - if ( !insertion_ok ){ // we found already a halfedge with the points - ++set_it->second.first; // increase the multiplicity - if(set_it->second.first == 2) - { - if ( get(vpmap, source(he,pmesh))==get(vpmap, target(set_it->first,pmesh)) && - get(vpmap, target(he,pmesh))==get(vpmap, source(set_it->first,pmesh)) ) - { - set_it->second.second = halfedge_pairs.size(); // set the id of the pair in the vector - halfedge_pairs.push_back( std::make_pair(set_it->first, he) ); - manifold_halfedge_pairs.push_back(true); - } - } - else - if ( set_it->second.first > 2 ) - manifold_halfedge_pairs[ set_it->second.second ] = false; + if(per_cc) + { + border_edges_per_cc[get(cc, face(opposite(he, pmesh), pmesh))].push_back(he); + } + else + { + fill_pairs(he, border_halfedge_map, halfedge_pairs, + manifold_halfedge_pairs, vpmap, pmesh); } } - + if(per_cc) + { + for(std::size_t i = 0; i < num_component; ++i) + { + Border_halfedge_map border_halfedge_map_in_cc(less_hedge); + halfedge_pairs.clear(); + manifold_halfedge_pairs.clear(); + for(int j = 0; j < static_cast(border_edges_per_cc[i].size()); ++j) + { + halfedge_descriptor he = border_edges_per_cc[i][j]; + fill_pairs(he, border_halfedge_map_in_cc, halfedge_pairs, + manifold_halfedge_pairs, vpmap, pmesh); + } + // put in `out` only manifold edges from the set of edges to stitch. + // We choose not to allow only a pair out of the whole set to be stitched + // as we can produce inconsistent stitching along a sequence of non-manifold edges + std::size_t nb_pairs=halfedge_pairs.size(); + for (std::size_t k=0; k > hedge_pairs_to_stitch; typedef typename GetVertexPointMap::const_type VPMap; - typedef typename boost::property_traits::value_type Point_3; VPMap vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); bool stitch_along_ccs = choose_param(get_param(np, internal_np::apply_per_connected_component), - false); - - if(!stitch_along_ccs) - { - internal::collect_duplicated_stitchable_boundary_edges(pmesh, - std::back_inserter(hedge_pairs_to_stitch), - internal::Less_for_halfedge(pmesh, vpm), vpm); - - stitch_borders(pmesh, hedge_pairs_to_stitch); - internal::stitch_boundary_cycle_2(pmesh); - } - else - { - typedef CGAL::dynamic_face_property_t Face_property_tag; - typedef typename boost::property_map::type Face_cc_map; - Face_cc_map cc = get(Face_property_tag(), pmesh); - std::size_t num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, cc); - - //add each border edge in map with cc - std::vector > border_edges_per_cc; - border_edges_per_cc.resize(num_component); - - BOOST_FOREACH(halfedge_descriptor hd, halfedges(pmesh)) - { - halfedge_descriptor ohd = opposite(hd, pmesh); - if(is_border(ohd, pmesh)) - { - border_edges_per_cc[get(cc, face(hd, pmesh))].push_back(ohd); - } - } - // foreach cc make pair of corresponding edges. - for(std::size_t i = 0; i < num_component; ++i) - { - for(int j = 0; j < static_cast(border_edges_per_cc[i].size())-1; ++j) - { - halfedge_descriptor h1 = border_edges_per_cc[i].back(); - border_edges_per_cc[i].pop_back(); - Point_3 src1(get(vpm, source(h1, pmesh))), tgt1(get(vpm, target(h1, pmesh))); - BOOST_FOREACH(halfedge_descriptor h2, border_edges_per_cc[i]) - { - Point_3 src2(get(vpm, source(h2, pmesh))), tgt2(get(vpm, target(h2, pmesh))); - if(src1 == tgt2 && src2 == tgt1) - { - hedge_pairs_to_stitch.push_back(std::make_pair(h1,h2)); - } - } - } - } - - //finally feed the pairs to the stitch_function - CGAL::Polygon_mesh_processing::stitch_borders(pmesh, hedge_pairs_to_stitch); - } + false); + + internal::collect_duplicated_stitchable_boundary_edges(pmesh, + std::back_inserter(hedge_pairs_to_stitch), + internal::Less_for_halfedge(pmesh, vpm), + vpm, + stitch_along_ccs); + + stitch_borders(pmesh, hedge_pairs_to_stitch); + internal::stitch_boundary_cycle_2(pmesh); } From d6b67584158a72cbd06c886abc99a662e0b18eb5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 26 Apr 2018 14:24:42 +0200 Subject: [PATCH 08/84] test new NP --- BGL/test/BGL/test_cgal_bgl_named_params.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index 91cd3c5ff4a..34e34e95f1f 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -86,6 +86,7 @@ void test(const NamedParameters& np) assert(get_param(np, CGAL::internal_np::weight_calculator).v == 39); assert(get_param(np, CGAL::internal_np::preserve_genus).v == 40); assert(get_param(np, CGAL::internal_np::verbosity_level).v == 41); + assert(get_param(np, CGAL::internal_np::apply_per_connected_component).v == 42); // Test types @@ -150,6 +151,7 @@ void test(const NamedParameters& np) check_same_type<39>(get_param(np, CGAL::internal_np::weight_calculator)); check_same_type<40>(get_param(np, CGAL::internal_np::preserve_genus)); check_same_type<41>(get_param(np, CGAL::internal_np::verbosity_level)); + check_same_type<42>(get_param(np, CGAL::internal_np::apply_per_connected_component)); } int main() @@ -199,6 +201,7 @@ int main() .weight_calculator(A<39>(39)) .preserve_genus(A<40>(40)) .verbosity_level(A<41>(41)) + .apply_per_connected_component(A<42>(42)) ); return EXIT_SUCCESS; From 0885a2a2984117a61b239240aee78082326db0d2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 27 Apr 2018 15:54:52 +0200 Subject: [PATCH 09/84] Update CHANGES.md --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 00ab2430064..ec0b7ccdcc5 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -152,6 +152,10 @@ Release date: April 2018 - `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` - `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` +- Added a new named parameter for stitching that allows to perform + this operation per connected component instead of globally + + ### Point Set Shape Detection - **Breaking change**: From 608365d80bff8d7dc2376bcf3a9f18fb7e99f859 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 3 May 2018 12:08:11 +0200 Subject: [PATCH 10/84] restore CHANGES.md --- Installation/CHANGES.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index ec0b7ccdcc5..bfd48b2efbc 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -24,8 +24,7 @@ Release date: April 2018 to `Release` manually, to avoid using CGAL libraries without any compile-time optimization. -### Header-only Mode - +### Header-only mode - Since CGAL-4.9, it has been possible to use CGAL by configuring it using CMake, but without compiling the CGAL libraries. With CGAL-4.12, it is now possible to use CGAL header-only, without even configuring From 9a77ece72f37e4eb8c98e3371ae13905dbf6c090 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 3 May 2018 12:49:19 +0200 Subject: [PATCH 11/84] Add a test --- .../test_stitching.cpp | 92 ++++++++++++++----- 1 file changed, 69 insertions(+), 23 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp index 14fc54b703e..cabec69c4fd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -36,6 +36,28 @@ void test_polyhedron(const char* fname) std::cout << "OK\n"; } +template +void test_polyhedron_cc(const char* fname) +{ + typedef CGAL::Polyhedron_3 Polyhedron; + + std::cout << "Testing Polyhedron_3 " << fname << "..." << std::flush; + std::ifstream input(fname); + Polyhedron poly; + if (!input || !(input >> poly)){ + std::cerr << "Error: can not read file."; + return; + } + + assert(poly.size_of_vertices() > 0); + + CGAL::Polygon_mesh_processing::stitch_borders(poly, + CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true)); + poly.normalize_border(); + + assert(poly.is_valid(false, 5)); + std::cout << "OK\n"; +} void test_surface_mesh(const char* fname) { @@ -59,34 +81,58 @@ void test_surface_mesh(const char* fname) std::cout << "OK\n"; } +void test_surface_mesh_cc(const char* fname) +{ + typedef Epic K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + std::cout << "Testing Surface_mesh " << fname << "..." << std::flush; + std::ifstream input(fname); + Mesh m; + if (!input || !(input >> m)){ + std::cerr << "Error: can not read file."; + return; + } + + CGAL::Polygon_mesh_processing::stitch_borders(m, + CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true)); + //todo : add a validity test + + assert(is_valid(m)); + + std::cout << "OK\n"; +} + int main() { test_polyhedron("data_stitching/full_border.off"); - + // test_polyhedron("data_stitching/full_border.off"); - test_polyhedron("data_stitching/full_border_quads.off"); - test_polyhedron("data_stitching/half_border.off"); - test_polyhedron("data_stitching/mid_border.off"); - test_polyhedron("data_stitching/multiple_incidence.off"); - test_polyhedron("data_stitching/incidence_3.off"); - test_polyhedron("data_stitching/incoherent_patch_orientation.off"); - test_polyhedron("data_stitching/non_stitchable.off"); - test_polyhedron("data_stitching/deg_border.off"); - test_polyhedron("data_stitching/two_patches.off"); - test_polyhedron("data_stitching/non_manifold.off"); - test_polyhedron("data_stitching/non_manifold2.off"); + //test_polyhedron("data_stitching/full_border_quads.off"); + //test_polyhedron("data_stitching/half_border.off"); + //test_polyhedron("data_stitching/mid_border.off"); + //test_polyhedron("data_stitching/multiple_incidence.off"); + //test_polyhedron("data_stitching/incidence_3.off"); + //test_polyhedron("data_stitching/incoherent_patch_orientation.off"); + //test_polyhedron("data_stitching/non_stitchable.off"); + //test_polyhedron("data_stitching/deg_border.off"); + //test_polyhedron("data_stitching/two_patches.off"); + //test_polyhedron("data_stitching/non_manifold.off"); + //test_polyhedron("data_stitching/non_manifold2.off"); + //test_polyhedron_cc("data_stitching/nm_cubes.off"); - test_surface_mesh("data_stitching/full_border.off"); - test_surface_mesh("data_stitching/full_border_quads.off"); - test_surface_mesh("data_stitching/half_border.off"); - test_surface_mesh("data_stitching/mid_border.off"); - test_surface_mesh("data_stitching/multiple_incidence.off"); - test_surface_mesh("data_stitching/incidence_3.off"); - test_surface_mesh("data_stitching/incoherent_patch_orientation.off"); - test_surface_mesh("data_stitching/non_stitchable.off"); - test_surface_mesh("data_stitching/deg_border.off"); - test_surface_mesh("data_stitching/non_manifold.off"); - test_surface_mesh("data_stitching/non_manifold2.off"); + //test_surface_mesh("data_stitching/full_border.off"); + //test_surface_mesh("data_stitching/full_border_quads.off"); + //test_surface_mesh("data_stitching/half_border.off"); + //test_surface_mesh("data_stitching/mid_border.off"); + //test_surface_mesh("data_stitching/multiple_incidence.off"); + //test_surface_mesh("data_stitching/incidence_3.off"); + //test_surface_mesh("data_stitching/incoherent_patch_orientation.off"); + //test_surface_mesh("data_stitching/non_stitchable.off"); + //test_surface_mesh("data_stitching/deg_border.off"); + //test_surface_mesh("data_stitching/non_manifold.off"); + test_surface_mesh_cc("data_stitching/nm_cubes.off"); return 0; } From 47635f11febbed25d3b6db815b058a642a3d4729 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 3 May 2018 14:55:49 +0200 Subject: [PATCH 12/84] Take fimap into account and add a test. --- .../Polygon_mesh_processing/stitch_borders.h | 46 ++++++++++++--- .../test_stitching.cpp | 59 +++++++++++-------- 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index a103cf94d5d..f0ecdb8b213 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -122,11 +122,34 @@ void fill_pairs(const Halfedge& he, } } } -template + +template +std::size_t num_component_wrapper(const Mesh& pmesh, + CCMap cc, + FIMap fim) +{ + return CGAL::Polygon_mesh_processing::connected_components(pmesh, cc, + CGAL::Polygon_mesh_processing::parameters::face_index_map(fim)); +} + +//specialization if there is no FIMap +template +std::size_t num_component_wrapper(const Mesh&, + CCMap, + bool) +{ + return 0; +} + +template OutputIterator collect_duplicated_stitchable_boundary_edges -(PM& pmesh, OutputIterator out, LessHedge less_hedge, const VertexPointMap& vpmap, - bool per_cc=false) +(PM& pmesh, OutputIterator out, LessHedge less_hedge, + const VertexPointMap& vpmap, const CGAL_PMP_NP_CLASS& np) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef std::map, LessHedge> Border_halfedge_map; @@ -140,10 +163,15 @@ collect_duplicated_stitchable_boundary_edges Face_cc_map cc; std::size_t num_component; std::vector > border_edges_per_cc; + bool per_cc = boost::choose_param(get_param(np, internal_np::apply_per_connected_component), + false); if(per_cc) { cc = get(Face_property_tag(), pmesh); - num_component = CGAL::Polygon_mesh_processing::connected_components(pmesh, cc); + typedef typename GetFaceIndexMap::const_type FIMap; + FIMap fim = choose_param(get_param(np, internal_np::face_index), + get_const_property_map(face_index, pmesh)); + num_component = num_component_wrapper(pmesh, cc, fim); border_edges_per_cc.resize(num_component); } @@ -573,8 +601,13 @@ void stitch_borders(PolygonMesh& pmesh, /// \cgalParamBegin{apply_per_connected_component} /// specifies if the borders should only be stitched inside their own connected component. /// Default value is `false`.\cgalParamEnd +/// \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd /// \cgalNamedParamsEnd /// +/// @attention A property map for `CGAL::face_index_t` should be either available as an internal property map +/// to `pmesh` or provided as one of the \ref pmp_namedparameters "Named Parameters" if `apply_per_connected_component` +/// is `true`. + template void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) { @@ -588,14 +621,11 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) typedef typename GetVertexPointMap::const_type VPMap; VPMap vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); - bool stitch_along_ccs = choose_param(get_param(np, internal_np::apply_per_connected_component), - false); internal::collect_duplicated_stitchable_boundary_edges(pmesh, std::back_inserter(hedge_pairs_to_stitch), internal::Less_for_halfedge(pmesh, vpm), - vpm, - stitch_along_ccs); + vpm, np); stitch_borders(pmesh, hedge_pairs_to_stitch); internal::stitch_boundary_cycle_2(pmesh); diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp index cabec69c4fd..873b7d428c7 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -4,9 +4,9 @@ #include #include #include - #include + #include #include #include @@ -51,8 +51,15 @@ void test_polyhedron_cc(const char* fname) assert(poly.size_of_vertices() > 0); - CGAL::Polygon_mesh_processing::stitch_borders(poly, - CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true)); + std::map::face_descriptor, std::size_t> fim; + int i=0; + BOOST_FOREACH(typename boost::graph_traits::face_descriptor fd, faces(poly)){ + fim[fd] = i++; + } + CGAL::Polygon_mesh_processing:: + stitch_borders(poly, + CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true) + .face_index_map(boost::make_assoc_property_map(fim))); poly.normalize_border(); assert(poly.is_valid(false, 5)); @@ -107,31 +114,31 @@ void test_surface_mesh_cc(const char* fname) int main() { test_polyhedron("data_stitching/full_border.off"); - // + test_polyhedron("data_stitching/full_border.off"); - //test_polyhedron("data_stitching/full_border_quads.off"); - //test_polyhedron("data_stitching/half_border.off"); - //test_polyhedron("data_stitching/mid_border.off"); - //test_polyhedron("data_stitching/multiple_incidence.off"); - //test_polyhedron("data_stitching/incidence_3.off"); - //test_polyhedron("data_stitching/incoherent_patch_orientation.off"); - //test_polyhedron("data_stitching/non_stitchable.off"); - //test_polyhedron("data_stitching/deg_border.off"); - //test_polyhedron("data_stitching/two_patches.off"); - //test_polyhedron("data_stitching/non_manifold.off"); - //test_polyhedron("data_stitching/non_manifold2.off"); - //test_polyhedron_cc("data_stitching/nm_cubes.off"); + test_polyhedron("data_stitching/full_border_quads.off"); + test_polyhedron("data_stitching/half_border.off"); + test_polyhedron("data_stitching/mid_border.off"); + test_polyhedron("data_stitching/multiple_incidence.off"); + test_polyhedron("data_stitching/incidence_3.off"); + test_polyhedron("data_stitching/incoherent_patch_orientation.off"); + test_polyhedron("data_stitching/non_stitchable.off"); + test_polyhedron("data_stitching/deg_border.off"); + test_polyhedron("data_stitching/two_patches.off"); + test_polyhedron("data_stitching/non_manifold.off"); + test_polyhedron("data_stitching/non_manifold2.off"); + test_polyhedron_cc("data_stitching/nm_cubes.off"); - //test_surface_mesh("data_stitching/full_border.off"); - //test_surface_mesh("data_stitching/full_border_quads.off"); - //test_surface_mesh("data_stitching/half_border.off"); - //test_surface_mesh("data_stitching/mid_border.off"); - //test_surface_mesh("data_stitching/multiple_incidence.off"); - //test_surface_mesh("data_stitching/incidence_3.off"); - //test_surface_mesh("data_stitching/incoherent_patch_orientation.off"); - //test_surface_mesh("data_stitching/non_stitchable.off"); - //test_surface_mesh("data_stitching/deg_border.off"); - //test_surface_mesh("data_stitching/non_manifold.off"); + test_surface_mesh("data_stitching/full_border.off"); + test_surface_mesh("data_stitching/full_border_quads.off"); + test_surface_mesh("data_stitching/half_border.off"); + test_surface_mesh("data_stitching/mid_border.off"); + test_surface_mesh("data_stitching/multiple_incidence.off"); + test_surface_mesh("data_stitching/incidence_3.off"); + test_surface_mesh("data_stitching/incoherent_patch_orientation.off"); + test_surface_mesh("data_stitching/non_stitchable.off"); + test_surface_mesh("data_stitching/deg_border.off"); + test_surface_mesh("data_stitching/non_manifold.off"); test_surface_mesh_cc("data_stitching/nm_cubes.off"); return 0; From 9327e470c1a42266abdbcd9a7c43cfb43c4c50fa Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 4 May 2018 16:05:05 +0200 Subject: [PATCH 13/84] Fix doc --- Installation/CHANGES.md | 10 ++++++++-- .../CGAL/Polygon_mesh_processing/stitch_borders.h | 6 ++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index bfd48b2efbc..dc5e48dd1d7 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,14 @@ Release History =============== +Release 4.13 +------------ + +### Polygon Mesh Processing + +- Added a new named parameter for stitching that allows to perform + this operation per connected component instead of globally + Release 4.12 ------------ @@ -151,8 +159,6 @@ Release date: April 2018 - `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` - `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` -- Added a new named parameter for stitching that allows to perform - this operation per connected component instead of globally ### Point Set Shape Detection diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index f0ecdb8b213..e09d4d4eb3a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -600,13 +600,11 @@ void stitch_borders(PolygonMesh& pmesh, /// `CGAL::vertex_point_t` should be available in `PolygonMesh`\cgalParamEnd /// \cgalParamBegin{apply_per_connected_component} /// specifies if the borders should only be stitched inside their own connected component. +/// In that case, a property map for `CGAL::face_index_t` should be either available as an internal property map +/// to `pmesh` or provided as the \ref pmp_namedparameters "Named Parameter" `face_index_map`. /// Default value is `false`.\cgalParamEnd /// \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd /// \cgalNamedParamsEnd -/// -/// @attention A property map for `CGAL::face_index_t` should be either available as an internal property map -/// to `pmesh` or provided as one of the \ref pmp_namedparameters "Named Parameters" if `apply_per_connected_component` -/// is `true`. template void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) From 719033ad68f17d53d7152de5602ebabe4dbb1973 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 24 May 2018 12:41:37 +0200 Subject: [PATCH 14/84] Create id-map on the fly if needed --- .../Polygon_mesh_processing/stitch_borders.h | 28 ++++++++--- .../data_stitching/nm_cubes.off | 50 +++++++++++++++++++ .../test_stitching.cpp | 10 +--- 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data_stitching/nm_cubes.off diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index e09d4d4eb3a..b645d97137c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -85,6 +85,8 @@ struct Less_for_halfedge const VertexPointMap& vpmap; }; +//add a pair of border halfedges to be stitched. +//Specifies if they are manifold or not in the map. template -std::size_t num_component_wrapper(const Mesh&, - CCMap, +std::size_t num_component_wrapper(Mesh& pmesh, + CCMap cc, bool) { - return 0; + + boost::unordered_map::face_descriptor, std::size_t> fim; + + //init the map + std::size_t i=-1; + BOOST_FOREACH(typename boost::graph_traits::face_descriptor f, faces(pmesh)) + fim[f]=++i; + + return CGAL::Polygon_mesh_processing::connected_components(pmesh, + cc, + parameters::face_index_map(boost::make_assoc_property_map(fim))); } template (border_edges_per_cc[i].size()); ++j) { halfedge_descriptor he = border_edges_per_cc[i][j]; @@ -213,6 +225,8 @@ collect_duplicated_stitchable_boundary_edges *out++=halfedge_pairs[k]; } } + halfedge_pairs.clear(); + manifold_halfedge_pairs.clear(); } } else @@ -619,7 +633,7 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) typedef typename GetVertexPointMap::const_type VPMap; VPMap vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); - + internal::collect_duplicated_stitchable_boundary_edges(pmesh, std::back_inserter(hedge_pairs_to_stitch), internal::Less_for_halfedge(pmesh, vpm), diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data_stitching/nm_cubes.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_stitching/nm_cubes.off new file mode 100644 index 00000000000..6c9341f1e18 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_stitching/nm_cubes.off @@ -0,0 +1,50 @@ +OFF +20 28 0 +-1 -1 -1 +-1 1 -1 +1 1 -1 +1 -1 -1 +-1 -1 1 +-1 1 1 +1 1 1 +1 -1 1 +1 2 -1 +1 2 1 +2 1 -1 +2 2 -1 +2 2 1 +2 1 1 +1 1 0 +1 1 -1 +1 1 1 +1 1 0 +1 1 0 +1 1 0 +3 0 1 3 +3 3 1 2 +3 0 4 1 +3 1 4 5 +3 3 2 14 +3 3 14 7 +3 7 14 6 +3 4 0 3 +3 7 4 3 +3 6 4 7 +3 6 5 4 +3 1 17 2 +3 1 5 17 +3 5 6 17 +3 15 8 10 +3 10 8 11 +3 15 18 8 +3 8 18 9 +3 18 16 9 +3 10 11 13 +3 13 11 12 +3 16 19 13 +3 13 19 10 +3 10 19 15 +3 12 16 13 +3 12 9 16 +3 8 9 12 +3 11 8 12 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp index 873b7d428c7..98fec7d5045 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -51,15 +51,9 @@ void test_polyhedron_cc(const char* fname) assert(poly.size_of_vertices() > 0); - std::map::face_descriptor, std::size_t> fim; - int i=0; - BOOST_FOREACH(typename boost::graph_traits::face_descriptor fd, faces(poly)){ - fim[fd] = i++; - } CGAL::Polygon_mesh_processing:: stitch_borders(poly, - CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true) - .face_index_map(boost::make_assoc_property_map(fim))); + CGAL::Polygon_mesh_processing::parameters::apply_per_connected_component(true)); poly.normalize_border(); assert(poly.is_valid(false, 5)); @@ -114,7 +108,7 @@ void test_surface_mesh_cc(const char* fname) int main() { test_polyhedron("data_stitching/full_border.off"); - + test_polyhedron("data_stitching/full_border.off"); test_polyhedron("data_stitching/full_border_quads.off"); test_polyhedron("data_stitching/half_border.off"); From 57296468b135d78b5a53f92b80689e10169db0ae Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 24 May 2018 12:46:16 +0200 Subject: [PATCH 15/84] Update doc for fimap --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index b645d97137c..c04d2c532df 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -611,11 +611,12 @@ void stitch_borders(PolygonMesh& pmesh, /// \cgalNamedParamsBegin /// \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. /// If this parameter is omitted, an internal property map for -/// `CGAL::vertex_point_t` should be available in `PolygonMesh`\cgalParamEnd +/// `CGAL::vertex_point_t` should be available in `PolygonMesh`.\cgalParamEnd /// \cgalParamBegin{apply_per_connected_component} /// specifies if the borders should only be stitched inside their own connected component. /// In that case, a property map for `CGAL::face_index_t` should be either available as an internal property map -/// to `pmesh` or provided as the \ref pmp_namedparameters "Named Parameter" `face_index_map`. +/// to `pmesh` or provided as the \ref pmp_namedparameters "Named Parameter" `face_index_map`. If this is not the case, +/// a default map will be created on the fly. /// Default value is `false`.\cgalParamEnd /// \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd /// \cgalNamedParamsEnd From 2adbfe0888f65fd39aeb87c2c3dd32c9c49bff76 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 24 May 2018 14:08:57 +0200 Subject: [PATCH 16/84] replace bool by cgal_no_property_::type in wrapper --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index c04d2c532df..350ff214d3a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -141,7 +141,7 @@ template std::size_t num_component_wrapper(Mesh& pmesh, CCMap cc, - bool) + boost::cgal_no_property::type) { boost::unordered_map::face_descriptor, std::size_t> fim; From 9407dac5967d1a310dd2fc6b7f9251de777e0b35 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Mar 2018 17:07:45 +0100 Subject: [PATCH 17/84] First version of a callback in compute_average_spacing() --- .../include/CGAL/compute_average_spacing.h | 96 ++++++++++++++++--- 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 6488d1ba986..26cbfb221de 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -41,7 +41,9 @@ #ifdef CGAL_LINKED_WITH_TBB #include #include -#include +#include +#define TBB_IMPLEMENT_CPP0X 1 +#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -109,20 +111,69 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who const unsigned int k; const std::vector& input; std::vector& output; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Compute_average_spacings(Tree& tree, unsigned int k, std::vector& points, - std::vector& output) + std::vector& output, + tbb::atomic& advancement, + tbb::atomic& interrupted) : tree(tree), k (k), input (points), output (output) + , advancement (advancement) + , interrupted (interrupted) { } void operator()(const tbb::blocked_range& r) const { for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (interrupted) + break; + output[i] = CGAL::internal::compute_average_spacing(input[i], tree, k); + ++ advancement; + } } }; + + template + class Callback_caller + { + const Callback& callback; + tbb::atomic& advancement; + tbb::atomic& interrupted; + std::size_t size; + + public: + Callback_caller (const Callback& callback, + tbb::atomic& interrupted, + tbb::atomic& advancement, + std::size_t size) + : callback (callback) + , interrupted (interrupted) + , advancement (advancement) + , size (size) + { } + + void operator()() + { + tbb::tick_count::interval_t sleeping_time(0.00001); + + while (advancement != size) + { + if (!callback (advancement / double(size))) + { + interrupted = true; + return; + } + std::this_thread::sleep_for(sleeping_time); + } + callback (1.); + } + }; + #endif // CGAL_LINKED_WITH_TBB } /* namespace internal */ @@ -180,10 +231,12 @@ compute_average_spacing( // basic geometric types typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; + typedef typename Point_set_processing_3::GetCallback::type Callback; typedef typename Kernel::Point_3 Point; PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); + const Callback& callback = choose_param(get_param(np, internal_np::callback), Callback()); // types for K nearest neighbors search structure typedef typename Kernel::FT FT; @@ -209,6 +262,7 @@ compute_average_spacing( // iterate over input points, compute and output normal // vectors (already normalized) FT sum_spacings = (FT)0.0; + std::size_t nb = 0; #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), @@ -216,26 +270,44 @@ compute_average_spacing( #else if (boost::is_convertible::value) { - std::vector spacings (kd_tree_points.size ()); + tbb::atomic advancement = 0; + tbb::atomic interrupted = false; + + internal::Callback_caller callback_caller (callback, interrupted, advancement, kd_tree_points.size()); + std::thread callback_thread (callback_caller); + + std::vector spacings (kd_tree_points.size (), -1); CGAL::internal::Compute_average_spacings - f (tree, k, kd_tree_points, spacings); + f (tree, k, kd_tree_points, spacings, advancement, interrupted); tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); + for (unsigned int i = 0; i < spacings.size (); ++ i) - sum_spacings += spacings[i]; + if (spacings[i] >= 0.) + { + sum_spacings += spacings[i]; + ++ nb; + } + + callback_thread.join(); } else #endif { - for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++) - { - sum_spacings += internal::compute_average_spacing( - get(point_map,*it), - tree,k); - } + for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++) + { + sum_spacings += internal::compute_average_spacing( + get(point_map,*it), + tree,k); + if (!callback ((nb+1) / double(kd_tree_points.size()))) + { + ++ nb; + break; + } + } } // return average spacing - return sum_spacings / (FT)(kd_tree_points.size ()); + return sum_spacings / (FT)(nb); } /// \cond SKIP_IN_MANUAL From 651b9d3e850fef3b71b62f3c92bdf0ca2de98ec3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Mar 2018 17:38:16 +0100 Subject: [PATCH 18/84] Move Progress_bar_callback out of plugin --- .../Point_set_shape_detection_plugin.cpp | 89 +-------------- .../include/Progress_bar_callback.h | 106 ++++++++++++++++++ 2 files changed, 108 insertions(+), 87 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index 0ae33010333..5d07fe14d1b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -28,6 +28,8 @@ #include +#include "Progress_bar_callback.h" + #include #include #include @@ -55,93 +57,6 @@ struct build_from_pair }; -struct Progress_bar_callback -{ - mutable int nb; - CGAL::Real_timer timer; - double t_start; - mutable double t_latest; - int bar_size; - mutable std::size_t string_size; - - Progress_bar_callback() : nb(0), bar_size (30), string_size(0) - { - timer.start(); - t_start = timer.time(); - t_latest = t_start; - } - - bool operator()(double advancement) const - { - // Avoid calling time() at every single iteration, which could - // impact performances very badly - ++ nb; - if (advancement != 1 && nb % 1000 != 0) - return true; - - // If the limit is reach, interrupt the algorithm - double t = timer.time(); - if (advancement == 1 || (t - t_latest) > 1.) - { - std::ostringstream oss; - oss << "["; - int adv = int(advancement * bar_size); - for (int i = 0; i < adv; ++ i) - oss << "="; - if (adv != bar_size) - oss << ">"; - for (int i = adv; i < bar_size; ++ i) - oss << " "; - - oss << "] " << int(advancement * 100) << "% ("; - - display_time (oss, t); - - oss << " elapsed, "; - - display_time (oss, estimate_remaining(t, advancement)); - - oss << " remaining)"; - - std::string bar_string = oss.str(); - std::cerr << "\r" << bar_string; - for (std::size_t i = bar_string.size(); i < string_size; ++ i) - std::cerr << " "; - string_size = (std::max) (string_size, bar_string.size()); - - if (advancement == 1) - std::cerr << std::endl; - - t_latest = t; - } - - return true; - } - - void display_time (std::ostringstream& oss, double seconds) const - { - if (seconds > 3600.) - { - int hours = int(seconds / 3600.); - oss << hours << "h"; - seconds -= hours * 3600.; - } - if (seconds > 60.) - { - int minutes = (int)(seconds / 60.); - oss << minutes << "min"; - seconds -= minutes * 60.; - } - oss << int(seconds) << "sec"; - } - - double estimate_remaining (double seconds, double advancement) const - { - return ((1. - advancement) * (seconds - t_start) / advancement); - } -}; - - class Point_set_demo_point_set_shape_detection_dialog : public QDialog, private Ui::PointSetShapeDetectionDialog { Q_OBJECT diff --git a/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h b/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h new file mode 100644 index 00000000000..4fb060910aa --- /dev/null +++ b/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h @@ -0,0 +1,106 @@ +#ifndef PROGRESS_BAR_CALLBACK_H +#define PROGRESS_BAR_CALLBACK_H + +#include + +struct Progress_bar_callback +{ + mutable std::size_t nb; + CGAL::Real_timer timer; + double t_start; + mutable double t_start_estimate; + mutable double t_latest; + int bar_size; + mutable std::size_t string_size; + + Progress_bar_callback() : nb(0), bar_size (30), string_size(0) + { + timer.start(); + t_start = timer.time(); + t_start_estimate = 0.; + t_latest = t_start; + } + + bool operator()(double advancement) const + { + // Avoid calling time() at every single iteration, which could + // impact performances very badly + ++ nb; + if (advancement != 1 && nb % 1000 != 0) + return true; + + // If the limit is reach, interrupt the algorithm + double t = timer.time(); + if (advancement == 1 || (t - t_latest) > 1.) + { + if (advancement != 0. && t_start_estimate == 0.) + t_start_estimate = t_latest; + + std::ostringstream oss; + oss << "["; + int adv = int(advancement * bar_size); + for (int i = 0; i < adv; ++ i) + oss << "="; + if (adv != bar_size) + oss << ">"; + for (int i = adv; i < bar_size; ++ i) + oss << " "; + + oss << "] " << int(advancement * 100) << "% ("; + + display_time (oss, t); + + oss << " elapsed, "; + + display_time (oss, estimate_remaining(t, advancement)); + + oss << " remaining)"; + + std::string bar_string = oss.str(); + std::cerr << "\r" << bar_string; + for (std::size_t i = bar_string.size(); i < string_size; ++ i) + std::cerr << " "; + string_size = (std::max) (string_size, bar_string.size()); + + t_latest = t; + + if (advancement == 1) + std::cerr << std::endl; + } + + return true; + } + + void display_time (std::ostringstream& oss, double seconds) const + { + if (seconds == std::numeric_limits::infinity()) + { + oss << "unknown"; + return; + } + if (seconds > 3600.) + { + int hours = int(seconds / 3600.); + oss << hours << "h"; + seconds -= hours * 3600.; + } + if (seconds > 60.) + { + int minutes = (int)(seconds / 60.); + oss << minutes << "min"; + seconds -= minutes * 60.; + } + oss << int(seconds) << "sec"; + } + + double estimate_remaining (double seconds, double advancement) const + { + if (advancement == 0.) + return std::numeric_limits::infinity(); + + return ((1. - advancement) * (seconds - t_start_estimate) / advancement); + } +}; + + +#endif // PROGRESS_BAR_CALLBACK_H From 979d74a723b895866f53b2f1ecdfbb7a7d269d6a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 12:57:58 +0100 Subject: [PATCH 19/84] Better version of callback in compute_average_spacing() --- .../include/CGAL/compute_average_spacing.h | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 26cbfb221de..a96f8e0ef09 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #define TBB_IMPLEMENT_CPP0X 1 #include #endif // CGAL_LINKED_WITH_TBB @@ -138,22 +140,21 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who }; - template class Callback_caller { - const Callback& callback; + const cpp11::function& callback; tbb::atomic& advancement; tbb::atomic& interrupted; std::size_t size; public: - Callback_caller (const Callback& callback, + Callback_caller (const cpp11::function& callback, tbb::atomic& interrupted, tbb::atomic& advancement, std::size_t size) : callback (callback) - , interrupted (interrupted) , advancement (advancement) + , interrupted (interrupted) , size (size) { } @@ -204,6 +205,7 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who \cgalNamedParamsBegin \cgalParamBegin{point_map} a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of `cpp11::function`\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd @@ -231,12 +233,12 @@ compute_average_spacing( // basic geometric types typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; - typedef typename Point_set_processing_3::GetCallback::type Callback; typedef typename Kernel::Point_3 Point; PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); - const Callback& callback = choose_param(get_param(np, internal_np::callback), Callback()); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); // types for K nearest neighbors search structure typedef typename Kernel::FT FT; @@ -270,11 +272,17 @@ compute_average_spacing( #else if (boost::is_convertible::value) { - tbb::atomic advancement = 0; - tbb::atomic interrupted = false; + // tbb::atomic only has default constructor, initialization done in two steps + tbb::atomic advancement; + advancement = 0; + tbb::atomic interrupted; + interrupted = false; - internal::Callback_caller callback_caller (callback, interrupted, advancement, kd_tree_points.size()); - std::thread callback_thread (callback_caller); + internal::Callback_caller callback_caller (callback, interrupted, advancement, kd_tree_points.size()); + std::thread* callback_thread; + + if (callback) + callback_thread = new std::thread (callback_caller); std::vector spacings (kd_tree_points.size (), -1); CGAL::internal::Compute_average_spacings @@ -287,8 +295,12 @@ compute_average_spacing( sum_spacings += spacings[i]; ++ nb; } - - callback_thread.join(); + + if (callback) + { + callback_thread->join(); + delete callback_thread; + } } else #endif @@ -298,7 +310,7 @@ compute_average_spacing( sum_spacings += internal::compute_average_spacing( get(point_map,*it), tree,k); - if (!callback ((nb+1) / double(kd_tree_points.size()))) + if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) { ++ nb; break; From 5ddb92da9872d84970aebec706fffe5ca8d0b43f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 13:13:44 +0100 Subject: [PATCH 20/84] Add a Qt progress bar (modal, no multithread mode) --- .../include/Qt_progress_bar_callback.h | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h diff --git a/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h b/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h new file mode 100644 index 00000000000..18f5960d02b --- /dev/null +++ b/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h @@ -0,0 +1,68 @@ +#ifndef PROGRESS_BAR_CALLBACK_H +#define PROGRESS_BAR_CALLBACK_H + +#include + +#include +#include + +class Qt_progress_bar_callback +{ + +private: + + CGAL::Real_timer timer; + double t_start; + mutable double t_latest; + + mutable std::size_t nb; + + QProgressDialog* dialog; + +public: + + Qt_progress_bar_callback() + { + } + + Qt_progress_bar_callback(const char* title, QWidget* parent) + : dialog (new QProgressDialog (QString(title), + QString("Cancel"), + 0, 100, + parent)) + { + dialog->setMinimumDuration(0); + dialog->setWindowModality(Qt::WindowModal); + timer.start(); + t_start = timer.time(); + t_latest = t_start; + } + ~Qt_progress_bar_callback() + { + } + + bool operator() (double advancement) const + { + // Avoid calling time() at every single iteration, which could + // impact performances very badly + ++ nb; + if (advancement != 1 && nb % 1000 != 0) + return true; + + // If the limit is reach, interrupt the algorithm + double t = timer.time(); + if (advancement == 1 || (t - t_latest) > 0.25) + { + dialog->setValue (int (100. * advancement)); + t_latest = t; + + if (dialog->wasCanceled()) + return false; + } + + return true; + } +}; + + +#endif // PROGRESS_BAR_CALLBACK_H From a01ee0c2a5ad9bec176dbc22dda02d4c1516c193 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 13:14:01 +0100 Subject: [PATCH 21/84] Use Qt progress bar in shape detection plugin --- .../Plugins/Point_set/Point_set_shape_detection_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index 5d07fe14d1b..a3833b8c7bf 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -28,7 +28,7 @@ #include -#include "Progress_bar_callback.h" +#include "Qt_progress_bar_callback.h" #include #include @@ -255,7 +255,7 @@ private: // The actual shape detection. CGAL::Real_timer t; t.start(); - Progress_bar_callback callback; + Qt_progress_bar_callback callback ("Detecting shapes...", mw); shape_detection.detect(op, callback); t.stop(); From e1dac37b74882c6ba021041a315df33e6c1bd1be Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 13:19:36 +0100 Subject: [PATCH 22/84] Average spacing plugin: use Qt progress bar in sequential, ASCII in parallel --- .../Point_set_average_spacing_plugin.cpp | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp index 33e0cccdd0f..98cdaf3a82b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -14,11 +14,16 @@ #include #include #include + // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; +# include "Qt_progress_bar_callback.h" + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif using namespace CGAL::Three; @@ -85,27 +90,34 @@ void Polyhedron_demo_point_set_average_spacing_plugin::on_actionAverageSpacing_t &ok); if(!ok) return; - + QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::processEvents(); - CGAL::Timer task_timer; task_timer.start(); + CGAL::Real_timer task_timer; task_timer.start(); std::cerr << "Average spacing (k=" << nb_neighbors <<")...\n"; +#ifdef CGAL_LINKED_WITH_TBB + Callback callback; +#else + Callback callback("Computing average spacing...", mw); +#endif + // Computes average spacing +// double average_spacing = CGAL::compute_average_spacing( double average_spacing = CGAL::compute_average_spacing( points->all_or_selection_if_not_empty(), nb_neighbors, - points->parameters()); + points->parameters().callback (callback)); // Print result Kernel::Sphere_3 bsphere = points->bounding_sphere(); double radius = std::sqrt(bsphere.squared_radius()); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Average spacing = " << average_spacing - << " = " << average_spacing/radius << " * point set radius (" - << task_timer.time() << " seconds, " - << (memory>>20) << " Mb allocated)" - << std::endl; + << " = " << average_spacing/radius << " * point set radius (" + << task_timer.time() << " seconds, " + << (memory>>20) << " Mb allocated)" + << std::endl; QApplication::restoreOverrideCursor(); QMessageBox::information(NULL, @@ -113,6 +125,7 @@ void Polyhedron_demo_point_set_average_spacing_plugin::on_actionAverageSpacing_t tr("Average Spacing = %1 = %2 * point set radius") .arg(average_spacing) .arg(average_spacing/radius)); + } } From 6daa40c4aad26676586620b1763b2c1f1df7708a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 13:50:59 +0100 Subject: [PATCH 23/84] Add callback named parameter --- BGL/include/CGAL/boost/graph/parameters_interface.h | 1 + 1 file changed, 1 insertion(+) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index fd75acf47d3..b595eebecf7 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -83,6 +83,7 @@ CGAL_add_named_parameter(query_point_t, query_point_map, query_point_map) CGAL_add_named_parameter(normal_t, normal_map, normal_map) CGAL_add_named_parameter(diagonalize_traits_t, diagonalize_traits, diagonalize_traits) CGAL_add_named_parameter(svd_traits_t, svd_traits, svd_traits) +CGAL_add_named_parameter(callback_t, callback, callback) CGAL_add_named_parameter(sharpness_angle_t, sharpness_angle, sharpness_angle) CGAL_add_named_parameter(edge_sensitivity_t, edge_sensitivity, edge_sensitivity) CGAL_add_named_parameter(neighbor_radius_t, neighbor_radius, neighbor_radius) From 7fba36b8ddfd0f8d769ff566c8bda8ec1fb6f365 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 13:56:43 +0100 Subject: [PATCH 24/84] Move Parallel_callback out of function + documentation --- .../include/CGAL/compute_average_spacing.h | 53 +++----------- .../include/CGAL/internal/Parallel_callback.h | 73 +++++++++++++++++++ 2 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 Point_set_processing_3/include/CGAL/internal/Parallel_callback.h diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index a96f8e0ef09..647af926dbb 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -40,6 +40,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include #include @@ -139,42 +140,6 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who } }; - - class Callback_caller - { - const cpp11::function& callback; - tbb::atomic& advancement; - tbb::atomic& interrupted; - std::size_t size; - - public: - Callback_caller (const cpp11::function& callback, - tbb::atomic& interrupted, - tbb::atomic& advancement, - std::size_t size) - : callback (callback) - , advancement (advancement) - , interrupted (interrupted) - , size (size) - { } - - void operator()() - { - tbb::tick_count::interval_t sleeping_time(0.00001); - - while (advancement != size) - { - if (!callback (advancement / double(size))) - { - interrupted = true; - return; - } - std::this_thread::sleep_for(sleeping_time); - } - callback (1.); - } - }; - #endif // CGAL_LINKED_WITH_TBB } /* namespace internal */ @@ -205,7 +170,13 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who \cgalNamedParamsBegin \cgalParamBegin{point_map} a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd - \cgalParamBegin{callback} an instance of `cpp11::function`\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the average spacing value + estimated on the processed subset is returned.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd @@ -278,11 +249,9 @@ compute_average_spacing( tbb::atomic interrupted; interrupted = false; - internal::Callback_caller callback_caller (callback, interrupted, advancement, kd_tree_points.size()); - std::thread* callback_thread; - - if (callback) - callback_thread = new std::thread (callback_caller); + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, interrupted, advancement, kd_tree_points.size()); + std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); std::vector spacings (kd_tree_points.size (), -1); CGAL::internal::Compute_average_spacings diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h new file mode 100644 index 00000000000..b6185059b23 --- /dev/null +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -0,0 +1,73 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// 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: GPL-3.0+ +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_INTERNAL_PSP_PARALLEL_CALLBACK_H +#define CGAL_INTERNAL_PSP_PARALLEL_CALLBACK_H + +#include + +#include +#define TBB_IMPLEMENT_CPP0X 1 +#include + +namespace CGAL { +namespace internal { +namespace Point_set_processing_3 { + +class Parallel_callback +{ + const cpp11::function& callback; + tbb::atomic& advancement; + tbb::atomic& interrupted; + std::size_t size; + +public: + Parallel_callback (const cpp11::function& callback, + tbb::atomic& interrupted, + tbb::atomic& advancement, + std::size_t size) + : callback (callback) + , advancement (advancement) + , interrupted (interrupted) + , size (size) + { } + + void operator()() + { + tbb::tick_count::interval_t sleeping_time(0.00001); + + while (advancement != size) + { + if (!callback (advancement / double(size))) + { + interrupted = true; + return; + } + std::this_thread::sleep_for(sleeping_time); + } + callback (1.); + } +}; + +} // namespace Point_set_processing_3 +} // namespace internal +} // namespace CGAL + +#endif // CGAL_INTERNAL_PSP_PARALLEL_CALLBACK_H From 45bad1258e07dffd59f956469d7dd18b7045acab Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 14:13:17 +0100 Subject: [PATCH 25/84] Move atomic variables into Parallel_callback --- .../include/CGAL/compute_average_spacing.h | 12 ++-- .../include/CGAL/internal/Parallel_callback.h | 68 ++++++++++++++----- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 647af926dbb..82b2b03272b 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -243,19 +243,15 @@ compute_average_spacing( #else if (boost::is_convertible::value) { - // tbb::atomic only has default constructor, initialization done in two steps - tbb::atomic advancement; - advancement = 0; - tbb::atomic interrupted; - interrupted = false; - internal::Point_set_processing_3::Parallel_callback - parallel_callback (callback, interrupted, advancement, kd_tree_points.size()); + parallel_callback (callback, kd_tree_points.size()); std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); std::vector spacings (kd_tree_points.size (), -1); CGAL::internal::Compute_average_spacings - f (tree, k, kd_tree_points, spacings, advancement, interrupted); + f (tree, k, kd_tree_points, spacings, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); for (unsigned int i = 0; i < spacings.size (); ++ i) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index b6185059b23..282e3e69d57 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -33,36 +33,70 @@ namespace Point_set_processing_3 { class Parallel_callback { - const cpp11::function& callback; - tbb::atomic& advancement; - tbb::atomic& interrupted; - std::size_t size; - + const cpp11::function& m_callback; + tbb::atomic* m_advancement; + tbb::atomic* m_interrupted; + std::size_t m_size; + bool m_creator; + public: Parallel_callback (const cpp11::function& callback, - tbb::atomic& interrupted, - tbb::atomic& advancement, - std::size_t size) - : callback (callback) - , advancement (advancement) - , interrupted (interrupted) - , size (size) - { } + std::size_t size, + std::size_t advancement = 0, + bool interrupted = false) + : m_callback (callback) + , m_advancement (new tbb::atomic()) + , m_interrupted (new tbb::atomic()) + , m_size (size) + , m_creator (true) + { + // tbb::atomic only has default constructor, initialization done in two steps + *m_advancement = advancement; + *m_interrupted = interrupted; + } + + Parallel_callback (const Parallel_callback& other) + : m_callback (other.m_callback) + , m_advancement (other.m_advancement) + , m_interrupted (other.m_interrupted) + , m_size (other.m_size) + , m_creator (false) + { + + } + + Parallel_callback& operator= (const Parallel_callback& other) + { + Parallel_callback out (other); + return out; + } + + ~Parallel_callback () + { + if (m_creator) + { + delete m_advancement; + delete m_interrupted; + } + } + + tbb::atomic& advancement() { return *m_advancement; } + tbb::atomic& interrupted() { return *m_interrupted; } void operator()() { tbb::tick_count::interval_t sleeping_time(0.00001); - while (advancement != size) + while (*m_advancement != m_size) { - if (!callback (advancement / double(size))) + if (!m_callback (*m_advancement / double(m_size))) { - interrupted = true; + *m_interrupted = true; return; } std::this_thread::sleep_for(sleeping_time); } - callback (1.); + m_callback (1.); } }; From 92f88cecbbb60c1783b34a7003b6d2b550c513d9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 15:10:06 +0100 Subject: [PATCH 26/84] Fix interruption --- .../include/CGAL/internal/Parallel_callback.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index 282e3e69d57..bde8bc384fa 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -23,6 +23,8 @@ #include +#include + #include #define TBB_IMPLEMENT_CPP0X 1 #include @@ -37,7 +39,7 @@ class Parallel_callback tbb::atomic* m_advancement; tbb::atomic* m_interrupted; std::size_t m_size; - bool m_creator; + bool m_creator; public: Parallel_callback (const cpp11::function& callback, @@ -90,10 +92,9 @@ public: while (*m_advancement != m_size) { if (!m_callback (*m_advancement / double(m_size))) - { *m_interrupted = true; + if (*m_interrupted) return; - } std::this_thread::sleep_for(sleeping_time); } m_callback (1.); From a2fd0c7630cd5461699ef7253660e1c464bcd672 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 15:15:45 +0100 Subject: [PATCH 27/84] Callback for bilateral smoothing --- .../include/CGAL/bilateral_smooth_point_set.h | 88 ++++++++++++++++--- .../Point_set_bilateral_smoothing_plugin.cpp | 29 ++++-- 2 files changed, 101 insertions(+), 16 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index 817216de0d6..9f791c9561d 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -45,9 +46,13 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include #include +#include +#define TBB_IMPLEMENT_CPP0X 1 +#include #endif // CGAL_LINKED_WITH_TBB // Default allocator: use TBB allocators if available @@ -300,18 +305,27 @@ class Compute_pwns_neighbors const Tree & m_tree; const Pwns & m_pwns; Pwns_neighbors & m_pwns_neighbors; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Compute_pwns_neighbors(unsigned int k, const Tree &tree, - const Pwns &pwns, Pwns_neighbors &neighbors) - : m_k(k), m_tree(tree), m_pwns(pwns), m_pwns_neighbors(neighbors) {} + const Pwns &pwns, Pwns_neighbors &neighbors, + tbb::atomic& advancement, + tbb::atomic& interrupted) + : m_k(k), m_tree(tree), m_pwns(pwns), m_pwns_neighbors(neighbors) + , advancement (advancement), interrupted (interrupted) {} void operator() ( const tbb::blocked_range& r ) const { for (size_t i = r.begin(); i!=r.end(); i++) { + if (interrupted) + break; + m_pwns_neighbors[i] = bilateral_smooth_point_set_internal:: compute_kdtree_neighbors(m_pwns[i], m_tree, m_k); + ++ advancement; } } }; @@ -331,30 +345,37 @@ class Pwn_updater Pwns* pwns; Pwns* update_pwns; std::vector >* pwns_neighbors; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Pwn_updater(FT sharpness, FT r, Pwns *in, Pwns *out, - std::vector >* neighbors): + std::vector >* neighbors, + tbb::atomic& advancement, + tbb::atomic& interrupted): sharpness_angle(sharpness), radius(r), pwns(in), update_pwns(out), - pwns_neighbors(neighbors){} - + pwns_neighbors(neighbors), + advancement (advancement), + interrupted (interrupted) {} void operator() ( const tbb::blocked_range& r ) const { for (size_t i = r.begin(); i != r.end(); ++i) { + if (interrupted) + break; (*update_pwns)[i] = bilateral_smooth_point_set_internal:: compute_denoise_projection((*pwns)[i], (*pwns_neighbors)[i], radius, sharpness_angle); - + ++ advancement; } } }; @@ -434,6 +455,8 @@ bilateral_smooth_point_set( typedef typename Kernel::FT FT; double sharpness_angle = choose_param(get_param(np, internal_np::sharpness_angle), 30.); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); CGAL_point_set_processing_precondition(points.begin() != points.end()); CGAL_point_set_processing_precondition(k > 1); @@ -513,8 +536,30 @@ bilateral_smooth_point_set( #else if (boost::is_convertible::value) { - Compute_pwns_neighbors f(k, tree, pwns, pwns_neighbors); + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, 2 * nb_points); + std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); + + Compute_pwns_neighbors f(k, tree, pwns, pwns_neighbors, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, nb_points), f); + + if (callback) + { + bool interrupted = parallel_callback.interrupted(); + + // We interrupt by hand as counter only goes halfway and won't terminate by itself + parallel_callback.interrupted() = true; + + callback_thread->join(); + delete callback_thread; + + // If interrupted during this step, nothing is computed, we return NaN + if (interrupted) + return std::numeric_limits::quiet_NaN(); + } + } else #endif @@ -522,10 +567,13 @@ bilateral_smooth_point_set( typename std::vector >::iterator pwns_iter = pwns_neighbors.begin(); - for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter, ++pwns_iter) + std::size_t nb = 0; + for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter, ++pwns_iter, ++ nb) { *pwns_iter = bilateral_smooth_point_set_internal:: compute_kdtree_neighbors(*pwn_iter, tree, k); + if (callback && !callback ((nb+1) / double(2. * nb_points))) + return std::numeric_limits::quiet_NaN(); } } @@ -545,24 +593,42 @@ bilateral_smooth_point_set( #ifdef CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) { + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, 2 * nb_points, nb_points); + std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); + //tbb::task_scheduler_init init(4); tbb::blocked_range block(0, nb_points); Pwn_updater pwn_updater(sharpness_angle, guess_neighbor_radius, &pwns, &update_pwns, - &pwns_neighbors); + &pwns_neighbors, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(block, pwn_updater); + + if (callback) + { + callback_thread->join(); + delete callback_thread; + + // If interrupted during this step, nothing is computed, we return NaN + if (parallel_callback.interrupted()) + return std::numeric_limits::quiet_NaN(); + } } else #endif // CGAL_LINKED_WITH_TBB { + std::size_t nb = nb_points; + typename std::vector >::iterator update_iter = update_pwns.begin(); typename std::vector >::iterator neighbor_iter = pwns_neighbors.begin(); for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); - ++pwn_iter, ++update_iter, ++neighbor_iter) + ++pwn_iter, ++update_iter, ++neighbor_iter, ++ nb) { *update_iter = bilateral_smooth_point_set_internal:: compute_denoise_projection @@ -570,6 +636,8 @@ bilateral_smooth_point_set( *neighbor_iter, guess_neighbor_radius, sharpness_angle); + if (callback && !callback ((nb+1) / double(2. * nb_points))) + return std::numeric_limits::quiet_NaN(); } } #ifdef CGAL_PSP3_VERBOSE diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp index 4e0e5020fd0..333cc9b2daf 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp @@ -14,16 +14,21 @@ #include #include +#include + #include "ui_Point_set_bilateral_smoothing_plugin.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; +# include "Qt_progress_bar_callback.h" + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif - using namespace CGAL::Three; class Polyhedron_demo_point_set_bilateral_smoothing_plugin : public QObject, @@ -109,12 +114,24 @@ void Polyhedron_demo_point_set_bilateral_smoothing_plugin::on_actionBilateralSmo for (unsigned int i = 0; i < dialog.iterations (); ++i) { - /* double error = */ - CGAL::bilateral_smooth_point_set +#ifdef CGAL_LINKED_WITH_TBB + Callback callback; +#else + std::ostringstream oss; + oss << "Bilateral smoothing (iteration " << i+1 << "/" << dialog.iterations() << ")"; + Callback callback(oss.str().c_str(), mw); +#endif + + double error = + CGAL::bilateral_smooth_point_set (points->all_or_selection_if_not_empty(), dialog.neighborhood_size (), points->parameters(). - sharpness_angle(dialog.sharpness_angle ())); + sharpness_angle(dialog.sharpness_angle ()). + callback (callback)); + + if (std::isnan(error)) // NaN return means algorithm was interrupted + break; } From 23f7b130c3f59482509a1a8d3ec468882a8e01f9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 15:40:30 +0100 Subject: [PATCH 28/84] Integrate thread management to Parallel_callback --- .../include/CGAL/bilateral_smooth_point_set.h | 11 ++--------- .../include/CGAL/compute_average_spacing.h | 9 +-------- .../include/CGAL/internal/Parallel_callback.h | 8 ++++++++ 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index 9f791c9561d..9c9de75cb3b 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -51,8 +51,6 @@ #include #include #include -#define TBB_IMPLEMENT_CPP0X 1 -#include #endif // CGAL_LINKED_WITH_TBB // Default allocator: use TBB allocators if available @@ -538,7 +536,6 @@ bilateral_smooth_point_set( { internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, 2 * nb_points); - std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); Compute_pwns_neighbors f(k, tree, pwns, pwns_neighbors, parallel_callback.advancement(), @@ -551,9 +548,7 @@ bilateral_smooth_point_set( // We interrupt by hand as counter only goes halfway and won't terminate by itself parallel_callback.interrupted() = true; - - callback_thread->join(); - delete callback_thread; + parallel_callback.join(); // If interrupted during this step, nothing is computed, we return NaN if (interrupted) @@ -595,7 +590,6 @@ bilateral_smooth_point_set( { internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, 2 * nb_points, nb_points); - std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); //tbb::task_scheduler_init init(4); tbb::blocked_range block(0, nb_points); @@ -610,8 +604,7 @@ bilateral_smooth_point_set( if (callback) { - callback_thread->join(); - delete callback_thread; + parallel_callback.join(); // If interrupted during this step, nothing is computed, we return NaN if (parallel_callback.interrupted()) diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 82b2b03272b..0fa54c5c7b6 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -45,8 +45,6 @@ #include #include #include -#define TBB_IMPLEMENT_CPP0X 1 -#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -245,7 +243,6 @@ compute_average_spacing( { internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, kd_tree_points.size()); - std::thread* callback_thread = (callback ? new std::thread (parallel_callback) : NULL); std::vector spacings (kd_tree_points.size (), -1); CGAL::internal::Compute_average_spacings @@ -261,11 +258,7 @@ compute_average_spacing( ++ nb; } - if (callback) - { - callback_thread->join(); - delete callback_thread; - } + parallel_callback.join(); } else #endif diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index bde8bc384fa..e50f2a7ff08 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -40,6 +40,7 @@ class Parallel_callback tbb::atomic* m_interrupted; std::size_t m_size; bool m_creator; + std::thread* m_thread; public: Parallel_callback (const cpp11::function& callback, @@ -51,10 +52,13 @@ public: , m_interrupted (new tbb::atomic()) , m_size (size) , m_creator (true) + , m_thread (NULL) { // tbb::atomic only has default constructor, initialization done in two steps *m_advancement = advancement; *m_interrupted = interrupted; + if (m_callback) + m_thread = new std::thread (*this); } Parallel_callback (const Parallel_callback& other) @@ -63,6 +67,7 @@ public: , m_interrupted (other.m_interrupted) , m_size (other.m_size) , m_creator (false) + , m_thread (NULL) { } @@ -80,10 +85,13 @@ public: delete m_advancement; delete m_interrupted; } + if (m_thread != NULL) + delete m_thread; } tbb::atomic& advancement() { return *m_advancement; } tbb::atomic& interrupted() { return *m_interrupted; } + void join() { m_thread->join(); } void operator()() { From 31acf93a1d7d555a940cd3d6a970dddda925a45b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 9 Mar 2018 15:50:35 +0100 Subject: [PATCH 29/84] Fix include guard --- .../demo/Polyhedron/include/Qt_progress_bar_callback.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h b/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h index 18f5960d02b..d074bacdaa4 100644 --- a/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h +++ b/Polyhedron/demo/Polyhedron/include/Qt_progress_bar_callback.h @@ -1,5 +1,5 @@ -#ifndef PROGRESS_BAR_CALLBACK_H -#define PROGRESS_BAR_CALLBACK_H +#ifndef QT_PROGRESS_BAR_CALLBACK_H +#define QT_PROGRESS_BAR_CALLBACK_H #include @@ -65,4 +65,4 @@ public: }; -#endif // PROGRESS_BAR_CALLBACK_H +#endif // QT_PROGRESS_BAR_CALLBACK_H From dd1b072fa6c74126389be964774c03369f8a6806 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 12 Mar 2018 11:51:02 +0100 Subject: [PATCH 30/84] Fix indentation --- Point_set_processing_3/include/CGAL/compute_average_spacing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 0fa54c5c7b6..5a21c1d5f41 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -263,7 +263,7 @@ compute_average_spacing( else #endif { - for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++) + for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++) { sum_spacings += internal::compute_average_spacing( get(point_map,*it), From 0f66525c2d7055edab00e9f7a207faabe61c4616 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 12 Mar 2018 11:51:20 +0100 Subject: [PATCH 31/84] Simplify code --- .../include/CGAL/bilateral_smooth_point_set.h | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index 9c9de75cb3b..ab396fdfa18 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -542,19 +542,15 @@ bilateral_smooth_point_set( parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, nb_points), f); - if (callback) - { - bool interrupted = parallel_callback.interrupted(); + bool interrupted = parallel_callback.interrupted(); - // We interrupt by hand as counter only goes halfway and won't terminate by itself - parallel_callback.interrupted() = true; - parallel_callback.join(); - - // If interrupted during this step, nothing is computed, we return NaN - if (interrupted) - return std::numeric_limits::quiet_NaN(); - } + // We interrupt by hand as counter only goes halfway and won't terminate by itself + parallel_callback.interrupted() = true; + parallel_callback.join(); + // If interrupted during this step, nothing is computed, we return NaN + if (interrupted) + return std::numeric_limits::quiet_NaN(); } else #endif @@ -602,14 +598,11 @@ bilateral_smooth_point_set( parallel_callback.interrupted()); tbb::parallel_for(block, pwn_updater); - if (callback) - { - parallel_callback.join(); + parallel_callback.join(); - // If interrupted during this step, nothing is computed, we return NaN - if (parallel_callback.interrupted()) - return std::numeric_limits::quiet_NaN(); - } + // If interrupted during this step, nothing is computed, we return NaN + if (parallel_callback.interrupted()) + return std::numeric_limits::quiet_NaN(); } else #endif // CGAL_LINKED_WITH_TBB From 08f4afd00eb0cb2b0bf556226463ddd84d19c063 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 12 Mar 2018 11:51:37 +0100 Subject: [PATCH 32/84] Bugfix: check that thread is non null --- .../include/CGAL/internal/Parallel_callback.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index e50f2a7ff08..f1893da8a3c 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -91,7 +91,11 @@ public: tbb::atomic& advancement() { return *m_advancement; } tbb::atomic& interrupted() { return *m_interrupted; } - void join() { m_thread->join(); } + void join() + { + if (m_thread != NULL) + m_thread->join(); + } void operator()() { From 770323602507f9f40b824b004fe54f1cb1d84956 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 12 Mar 2018 11:52:08 +0100 Subject: [PATCH 33/84] Callbacks in most Point Set Processing functions --- .../include/CGAL/grid_simplify_point_set.h | 8 +++- .../CGAL/hierarchy_simplify_point_set.h | 16 ++++++++ .../include/CGAL/jet_estimate_normals.h | 40 ++++++++++++++---- .../include/CGAL/jet_smooth_point_set.h | 35 +++++++++++++--- .../include/CGAL/pca_estimate_normals.h | 35 +++++++++++++--- .../include/CGAL/remove_outliers.h | 8 +++- .../wlop_simplify_and_regularize_point_set.h | 41 ++++++++++++++++--- 7 files changed, 155 insertions(+), 28 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h index fb488710b73..851f48cf6fc 100644 --- a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -204,6 +205,8 @@ grid_simplify_point_set( typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); // actual type of input points typedef typename std::iterator_traits::value_type Enriched_point; @@ -214,12 +217,15 @@ grid_simplify_point_set( // points_to_keep[] will contain 1 point per cell; the others will be in points_to_remove[]. Epsilon_point_set_3 points_to_keep(epsilon, point_map); std::deque points_to_remove; - for (typename PointRange::iterator it = points.begin(); it != points.end(); it++) + std::size_t nb = 0, nb_points = points.size(); + for (typename PointRange::iterator it = points.begin(); it != points.end(); it++, ++ nb) { std::pair::iterator,bool> result; result = points_to_keep.insert(*it); if (!result.second) // if not inserted points_to_remove.push_back(*it); + if (callback && !callback ((nb+1) / double(nb_points))) + break; } // Replaces `[first, beyond)` range by the content of points_to_keep, then points_to_remove. diff --git a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h index bbb94e0d81e..18f0cf25da3 100644 --- a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -167,6 +168,8 @@ namespace CGAL { PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); unsigned int size = choose_param(get_param(np, internal_np::size), 10); double var_max = choose_param(get_param(np, internal_np::maximum_variation), 1./3.); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename std::iterator_traits::value_type Input_type; @@ -191,6 +194,8 @@ namespace CGAL { std::list points_to_keep; std::list points_to_remove; + + std::size_t nb_done = 0; while (!(clusters_stack.empty ())) { @@ -203,6 +208,7 @@ namespace CGAL { points_to_keep.splice (points_to_keep.end (), current_cluster->first, current_cluster->first.begin ()); clusters_stack.pop_front (); + ++ nb_done; continue; } @@ -268,6 +274,7 @@ namespace CGAL { cluster_iterator nonempty = (current_cluster->first.empty () ? negative_side : current_cluster); + nb_done += nonempty->first.size(); // Compute the centroid nonempty->second = internal::hsps_centroid (nonempty->first.begin (), nonempty->first.end (), @@ -279,6 +286,7 @@ namespace CGAL { point_map, nonempty->second, Kernel ()); + clusters_stack.pop_front (); clusters_stack.pop_front (); } @@ -311,6 +319,7 @@ namespace CGAL { // and output point else { + nb_done += current_cluster->first.size(); internal::hsc_terminate_cluster (current_cluster->first, points_to_keep, points_to_remove, @@ -319,7 +328,14 @@ namespace CGAL { Kernel ()); clusters_stack.pop_front (); } + + if (callback && !callback (nb_done / double (points.size()))) + break; } + + if (callback) + callback (1.); + typename PointRange::iterator first_point_to_remove = std::copy (points_to_keep.begin(), points_to_keep.end(), points.begin()); std::copy (points_to_remove.begin(), points_to_remove.end(), first_point_to_remove); diff --git a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h index edc1cc6ee6a..bbd97d98e3e 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -40,9 +40,11 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include #include +#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -125,17 +127,28 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute const unsigned int degree_fitting; const std::vector& input; std::vector& output; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Jet_estimate_normals(Tree& tree, unsigned int k, std::vector& points, - unsigned int degree_fitting, std::vector& output) + unsigned int degree_fitting, std::vector& output, + tbb::atomic& advancement, + tbb::atomic& interrupted) : tree(tree), k (k), degree_fitting (degree_fitting), input (points), output (output) + , advancement (advancement) + , interrupted (interrupted) { } void operator()(const tbb::blocked_range& r) const { for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (interrupted) + break; output[i] = CGAL::internal::jet_estimate_normal(input[i], tree, k, degree_fitting); + ++ advancement; + } } }; @@ -212,6 +225,8 @@ jet_estimate_normals( PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); NormalMap normal_map = choose_param(get_param(np, internal_np::normal_map), NormalMap()); unsigned int degree_fitting = choose_param(get_param(np, internal_np::degree_fitting), 2); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename Kernel::Point_3 Point; @@ -254,28 +269,35 @@ jet_estimate_normals( #else if (boost::is_convertible::value) { + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, kd_tree_points.size()); + std::vector normals (kd_tree_points.size ()); CGAL::internal::Jet_estimate_normals - f (tree, k, kd_tree_points, degree_fitting, normals); + f (tree, k, kd_tree_points, degree_fitting, normals, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); - unsigned int i = 0; + std::size_t i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - { - put (normal_map, *it, normals[i]); - } + put (normal_map, *it, normals[i]); + + parallel_callback.join(); } else #endif { - for(it = points.begin(); it != points.end(); it++) + std::size_t nb = 0; + for(it = points.begin(); it != points.end(); it++, ++ nb) { Vector normal = internal::jet_estimate_normal( get(point_map,*it), tree, k, degree_fitting); put(normal_map, *it, normal); // normal_map[it] = normal - - } + if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + break; + } } diff --git a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h index 83edb6dd1c0..c03062c64d9 100644 --- a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h @@ -39,9 +39,11 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include #include +#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -125,20 +127,31 @@ jet_smooth_point( unsigned int degree_monge; const std::vector& input; std::vector& output; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Jet_smooth_pwns (Tree& tree, unsigned int k, std::vector& points, - unsigned int degree_fitting, unsigned int degree_monge, std::vector& output) + unsigned int degree_fitting, unsigned int degree_monge, std::vector& output, + tbb::atomic& advancement, + tbb::atomic& interrupted) : tree(tree), k (k), degree_fitting (degree_fitting), degree_monge (degree_monge), input (points), output (output) + , advancement (advancement) + , interrupted (interrupted) { } void operator()(const tbb::blocked_range& r) const { for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (interrupted) + break; output[i] = CGAL::internal::jet_smooth_point(input[i], tree, k, degree_fitting, degree_monge); + ++ advancement; + } } }; @@ -210,6 +223,8 @@ jet_smooth_point_set( PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); unsigned int degree_fitting = choose_param(get_param(np, internal_np::degree_fitting), 2); unsigned int degree_monge = choose_param(get_param(np, internal_np::degree_monge), 2); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename Kernel::Point_3 Point; @@ -244,27 +259,35 @@ jet_smooth_point_set( #else if (boost::is_convertible::value) { + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, kd_tree_points.size()); + std::vector mutated_points (kd_tree_points.size ()); CGAL::internal::Jet_smooth_pwns f (tree, k, kd_tree_points, degree_fitting, degree_monge, - mutated_points); + mutated_points, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); unsigned int i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - { - put(point_map, *it, mutated_points[i]); + put(point_map, *it, mutated_points[i]); + + parallel_callback.join(); - } } else #endif { - for(it = points.begin(); it != points.end(); it++) + std::size_t nb = 0; + for(it = points.begin(); it != points.end(); it++, ++ nb) { const typename boost::property_traits::reference p = get(point_map, *it); put(point_map, *it , internal::jet_smooth_point( p,tree,k,degree_fitting,degree_monge) ); + if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + break; } } } diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 6011e1428cb..022837fc5d8 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -41,9 +41,11 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include #include +#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -117,17 +119,28 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute const unsigned int k; const std::vector& input; std::vector& output; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: PCA_estimate_normals(Tree& tree, unsigned int k, std::vector& points, - std::vector& output) + std::vector& output, + tbb::atomic& advancement, + tbb::atomic& interrupted) : tree(tree), k (k), input (points), output (output) + , advancement (advancement) + , interrupted (interrupted) { } void operator()(const tbb::blocked_range& r) const { for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (interrupted) + break; output[i] = CGAL::internal::pca_estimate_normal(input[i], tree, k); + ++ advancement; + } } }; @@ -193,6 +206,8 @@ pca_estimate_normals( PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); NormalMap normal_map = choose_param(get_param(np, internal_np::normal_map), NormalMap()); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename Kernel::Point_3 Point; @@ -235,20 +250,26 @@ pca_estimate_normals( #else if (boost::is_convertible::value) { + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, kd_tree_points.size()); + std::vector normals (kd_tree_points.size ()); CGAL::internal::PCA_estimate_normals - f (tree, k, kd_tree_points, normals); + f (tree, k, kd_tree_points, normals, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); unsigned int i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - { - put (normal_map, *it, normals[i]); - } + put (normal_map, *it, normals[i]); + + parallel_callback.join(); } else #endif { - for(it = points.begin(); it != points.end(); it++) + std::size_t nb = 0; + for(it = points.begin(); it != points.end(); it++, ++ nb) { Vector normal = internal::pca_estimate_normal( get(point_map,*it), @@ -256,6 +277,8 @@ pca_estimate_normals( k); put(normal_map, *it, normal); // normal_map[it] = normal + if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + break; } } diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index d268a26adf4..9980ec462b2 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -163,6 +164,8 @@ remove_outliers( PointMap point_map = choose_param(get_param(np, internal_np::point_map), PointMap()); double threshold_percent = choose_param(get_param(np, internal_np::threshold_percent), 10.); double threshold_distance = choose_param(get_param(np, internal_np::threshold_distance), 0.); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename Kernel::FT FT; @@ -198,12 +201,15 @@ remove_outliers( // iterate over input points and add them to multimap sorted by distance to k std::multimap sorted_points; - for(it = points.begin(); it != points.end(); it++) + std::size_t nb = 0; + for(it = points.begin(); it != points.end(); it++, ++ nb) { FT sq_distance = internal::compute_avg_knn_sq_distance_3( get(point_map,*it), tree, k); sorted_points.insert( std::make_pair(sq_distance, *it) ); + if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + break; } // Replaces [points.begin(), points.end()) range by the multimap content. diff --git a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h index c47bb214eff..d9ecad56d7e 100644 --- a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h +++ b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h @@ -42,8 +42,11 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#include #include #include +#include +#include #endif // CGAL_LINKED_WITH_TBB #include @@ -354,6 +357,8 @@ class Sample_point_updater const typename Kernel::FT radius; const std::vector &original_densities; const std::vector &sample_densities; + tbb::atomic& advancement; + tbb::atomic& interrupted; public: Sample_point_updater( @@ -363,20 +368,25 @@ public: const Tree &_sample_kd_tree, const typename Kernel::FT _radius, const std::vector &_original_densities, - const std::vector &_sample_densities): + const std::vector &_sample_densities, + tbb::atomic& advancement, + tbb::atomic& interrupted): update_sample_points(out), sample_points(in), original_kd_tree(_original_kd_tree), sample_kd_tree(_sample_kd_tree), radius(_radius), original_densities(_original_densities), - sample_densities(_sample_densities){} - + sample_densities(_sample_densities), + advancement (advancement), + interrupted (interrupted) {} void operator() ( const tbb::blocked_range& r ) const { for (size_t i = r.begin(); i != r.end(); ++i) { + if (interrupted) + break; update_sample_points[i] = simplify_and_regularize_internal:: compute_update_sample_point( sample_points[i], @@ -385,6 +395,7 @@ public: radius, original_densities, sample_densities); + ++ advancement; } } }; @@ -466,6 +477,8 @@ wlop_simplify_and_regularize_point_set( double radius = choose_param(get_param(np, internal_np::neighbor_radius), -1); unsigned int iter_number = choose_param(get_param(np, internal_np::number_of_iterations), 35); bool require_uniform_sampling = choose_param(get_param(np, internal_np::require_uniform_sampling), false); + const cpp11::function& callback = choose_param(get_param(np, internal_np::callback), + cpp11::function()); typedef typename Kernel::Point_3 Point; typedef typename Kernel::FT FT; @@ -589,6 +602,9 @@ wlop_simplify_and_regularize_point_set( //parallel if (boost::is_convertible::value) { + internal::Point_set_processing_3::Parallel_callback + parallel_callback (callback, iter_number * number_of_sample, iter_n * number_of_sample); + tbb::blocked_range block(0, number_of_sample); Sample_point_updater sample_updater( update_sample_points, @@ -597,15 +613,28 @@ wlop_simplify_and_regularize_point_set( sample_kd_tree, radius2, original_density_weights, - sample_density_weights); + sample_density_weights, + parallel_callback.advancement(), + parallel_callback.interrupted()); tbb::parallel_for(block, sample_updater); + + bool interrupted = parallel_callback.interrupted(); + + // We interrupt by hand as counter only goes halfway and won't terminate by itself + parallel_callback.interrupted() = true; + parallel_callback.join(); + + // If interrupted during this step, nothing is computed, we return NaN + if (interrupted) + return output; }else #endif { //sequential + std::size_t nb = iter_n * number_of_sample; for (sample_iter = sample_points.begin(); - sample_iter != sample_points.end(); ++sample_iter, ++update_iter) + sample_iter != sample_points.end(); ++sample_iter, ++update_iter, ++ nb) { *update_iter = simplify_and_regularize_internal:: compute_update_sample_point Date: Mon, 12 Mar 2018 11:52:32 +0100 Subject: [PATCH 34/84] Make ASCII callback have the same constructor as Qt one --- Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h b/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h index 4fb060910aa..9a0eb468ec2 100644 --- a/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h +++ b/Polyhedron/demo/Polyhedron/include/Progress_bar_callback.h @@ -13,8 +13,13 @@ struct Progress_bar_callback int bar_size; mutable std::size_t string_size; - Progress_bar_callback() : nb(0), bar_size (30), string_size(0) + Progress_bar_callback(const char* title = NULL, + void* = NULL) // Hack to have same constructor as Qt_progress_bar_callback + : nb(0), bar_size (30), string_size(0) { + if (title != NULL) + std::cerr << title << std::endl; + timer.start(); t_start = timer.time(); t_start_estimate = 0.; From ee0579d6e07f631090a4a201364cf62a17353b67 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 12 Mar 2018 11:52:42 +0100 Subject: [PATCH 35/84] Callbacks in PSP plugins --- .../Point_set_average_spacing_plugin.cpp | 4 --- .../Point_set_bilateral_smoothing_plugin.cpp | 6 ---- .../Point_set_normal_estimation_plugin.cpp | 20 ++++++++++--- .../Point_set_outliers_removal_plugin.cpp | 16 +++++++---- .../Point_set_simplification_plugin.cpp | 28 ++++++++++++++----- .../Point_set/Point_set_smoothing_plugin.cpp | 14 ++++++++-- .../Point_set/Point_set_wlop_plugin.cpp | 13 +++++++-- 7 files changed, 69 insertions(+), 32 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp index 98cdaf3a82b..4d20a5ff728 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp @@ -96,11 +96,7 @@ void Polyhedron_demo_point_set_average_spacing_plugin::on_actionAverageSpacing_t CGAL::Real_timer task_timer; task_timer.start(); std::cerr << "Average spacing (k=" << nb_neighbors <<")...\n"; -#ifdef CGAL_LINKED_WITH_TBB - Callback callback; -#else Callback callback("Computing average spacing...", mw); -#endif // Computes average spacing // double average_spacing = CGAL::compute_average_spacing( diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp index 333cc9b2daf..8a0660462d0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp @@ -114,13 +114,9 @@ void Polyhedron_demo_point_set_bilateral_smoothing_plugin::on_actionBilateralSmo for (unsigned int i = 0; i < dialog.iterations (); ++i) { -#ifdef CGAL_LINKED_WITH_TBB - Callback callback; -#else std::ostringstream oss; oss << "Bilateral smoothing (iteration " << i+1 << "/" << dialog.iterations() << ")"; Callback callback(oss.str().c_str(), mw); -#endif double error = CGAL::bilateral_smooth_point_set @@ -133,8 +129,6 @@ void Polyhedron_demo_point_set_bilateral_smoothing_plugin::on_actionBilateralSmo if (std::isnan(error)) // NaN return means algorithm was interrupted break; } - - std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << task_timer.time() << " seconds, " diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp index c5698c8094e..969d37fdeac 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp @@ -28,10 +28,15 @@ // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; +# include "Qt_progress_bar_callback.h" + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif + using namespace CGAL::Three; class Polyhedron_demo_point_set_normal_estimation_plugin : @@ -174,10 +179,14 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati CGAL::Timer task_timer; task_timer.start(); std::cerr << "Estimates normal direction by PCA (k=" << dialog.pca_neighbors() <<")...\n"; + Callback callback("Estimating normals by PCA...", NULL); + // Estimates normals direction. CGAL::pca_estimate_normals(points->all_or_selection_if_not_empty(), dialog.pca_neighbors(), - points->parameters()); + points->parameters(). + callback (callback)); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Estimates normal direction: " << task_timer.time() << " seconds, " @@ -189,10 +198,13 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati CGAL::Timer task_timer; task_timer.start(); std::cerr << "Estimates normal direction by Jet Fitting (k=" << dialog.jet_neighbors() <<")...\n"; + Callback callback("Estimating normals by jet fitting...", NULL); + // Estimates normals direction. CGAL::jet_estimate_normals(points->all_or_selection_if_not_empty(), dialog.jet_neighbors(), - points->parameters()); + points->parameters(). + callback (callback)); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Estimates normal direction: " << task_timer.time() << " seconds, " diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp index cce263b6174..fb57a95e917 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp @@ -15,6 +15,9 @@ #include #include +#include "Qt_progress_bar_callback.h" +typedef Qt_progress_bar_callback Callback; + #include "ui_Point_set_outliers_removal_plugin.h" using namespace CGAL::Three; class Polyhedron_demo_point_set_outliers_removal_plugin : @@ -93,21 +96,24 @@ void Polyhedron_demo_point_set_outliers_removal_plugin::on_actionOutlierRemoval_ std::cerr << "Select outliers (" << removed_percentage <<"% with distance threshold " << distance_threshold << ")...\n"; + Callback callback("Selecting outliers...", NULL); + // Computes outliers Point_set::iterator first_point_to_remove = CGAL::remove_outliers(*points, nb_neighbors, points->parameters(). threshold_percent(removed_percentage). - threshold_distance(distance_threshold)); + threshold_distance(distance_threshold). + callback (callback)); std::size_t nb_points_to_remove = std::distance(first_point_to_remove, points->end()); std::size_t memory = CGAL::Memory_sizer().virtual_size(); - std::cerr << "Simplification: " << nb_points_to_remove << " point(s) are selected (" - << task_timer.time() << " seconds, " - << (memory>>20) << " Mb allocated)" - << std::endl; + std::cerr << "Outliers: " << nb_points_to_remove << " point(s) are selected (" + << task_timer.time() << " seconds, " + << (memory>>20) << " Mb allocated)" + << std::endl; // Selects points to delete points->set_first_selected (first_point_to_remove); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp index 3711bb10053..cb38c76f193 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp @@ -17,16 +17,20 @@ #include #include +#include "Qt_progress_bar_callback.h" + #include "ui_Point_set_simplification_plugin.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif - using namespace CGAL::Three; class Polyhedron_demo_point_set_simplification_plugin : public QObject, @@ -151,25 +155,35 @@ void Polyhedron_demo_point_set_simplification_plugin::on_actionSimplify_triggere { std::cerr << "Point set grid simplification (cell size = " << dialog.gridCellSize() <<" * average spacing)...\n"; + Callback as_callback("Computing average spacing...", NULL); + // Computes average spacing - double average_spacing = CGAL::compute_average_spacing(*points, 6 /* knn = 1 ring */); + double average_spacing = CGAL::compute_average_spacing(*points, 6, /* knn = 1 ring */ + points->parameters(). + callback (as_callback)); + Qt_progress_bar_callback callback("Grid simplyfing...", NULL); + // Computes points to remove by Grid Clustering first_point_to_remove = CGAL::grid_simplify_point_set(*points, - dialog.gridCellSize()*average_spacing); + dialog.gridCellSize()*average_spacing, + points->parameters(). + callback (callback)); } else { std::cerr << "Point set hierarchy simplification (cluster size = " << dialog.maximumClusterSize() << ", maximum variation = " << dialog.maximumSurfaceVariation() << ")...\n"; - // Computes points to remove by Grid Clustering + Qt_progress_bar_callback callback("Hierarchy simplyfing...", NULL); + // Computes points to remove by Hierarchy first_point_to_remove = CGAL::hierarchy_simplify_point_set(*points, points->parameters(). size(dialog.maximumClusterSize()). - maximum_variation(dialog.maximumSurfaceVariation())); + maximum_variation(dialog.maximumSurfaceVariation()). + callback(callback)); } std::size_t nb_points_to_remove = std::distance(first_point_to_remove, points->end()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp index adf56f72e8e..5e72b164a48 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp @@ -14,9 +14,13 @@ // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; +# include "Qt_progress_bar_callback.h" + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif using namespace CGAL::Three; @@ -81,9 +85,13 @@ void Polyhedron_demo_point_set_smoothing_plugin::on_actionJetSmoothing_triggered QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::processEvents(); + + Callback callback("Smoothing point set...", NULL); + CGAL::jet_smooth_point_set(points->all_or_selection_if_not_empty(), nb_neighbors, - points->parameters()); + points->parameters(). + callback (callback)); points->invalidate_bounds(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp index 2c340be75e3..ccd354c9b97 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp @@ -19,9 +19,13 @@ // Concurrency #ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; +# include "Progress_bar_callback.h" + typedef Progress_bar_callback Callback; + typedef CGAL::Parallel_tag Concurrency_tag; #else -typedef CGAL::Sequential_tag Concurrency_tag; +# include "Qt_progress_bar_callback.h" + typedef Qt_progress_bar_callback Callback; + typedef CGAL::Sequential_tag Concurrency_tag; #endif using namespace CGAL::Three; @@ -108,13 +112,16 @@ void Polyhedron_demo_point_set_wlop_plugin::on_actionSimplifyAndRegularize_trigg new_item->setVisible(true); item->setVisible(false); scene->addItem(new_item); + + Callback callback ("WLOP simplification and regularization...", NULL); CGAL::wlop_simplify_and_regularize_point_set (points->all_or_selection_if_not_empty(), new_item->point_set()->point_back_inserter(), points->parameters(). select_percentage (dialog.retainedPercentage()). - neighbor_radius (dialog.neighborhoodRadius()*average_spacing)); + neighbor_radius (dialog.neighborhoodRadius()*average_spacing). + callback (callback)); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Simplification and regularization: " From e649d77dde13103df91036ffbb8357a81f387031 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 07:59:04 +0100 Subject: [PATCH 36/84] Undef first by safety --- Point_set_processing_3/include/CGAL/internal/Parallel_callback.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index f1893da8a3c..fa992d459ce 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -26,6 +26,7 @@ #include #include +#undef TBB_IMPLEMENT_CPP0X #define TBB_IMPLEMENT_CPP0X 1 #include From 9851cd7856fa101872b2e83010b2055d0c3418f3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 07:59:25 +0100 Subject: [PATCH 37/84] Mechanism to lauch QProgressDialog either in thread or modal --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 3 + .../demo/Polyhedron/Callback_signaler.cpp | 11 ++ .../demo/Polyhedron/Callback_signaler.h | 39 ++++++ .../Plugins/Point_set/CMakeLists.txt | 2 +- .../Point_set_average_spacing_plugin.cpp | 44 ++++-- .../include/run_with_qprogressdialog.h | 130 ++++++++++++++++++ 6 files changed, 215 insertions(+), 14 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Callback_signaler.cpp create mode 100644 Polyhedron/demo/Polyhedron/Callback_signaler.h create mode 100644 Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 47b9048b765..7825ddec9d9 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -200,6 +200,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) add_library(scene_color_ramp SHARED Color_ramp.cpp) target_link_libraries(scene_color_ramp PRIVATE Qt5::Core) + add_library(scene_callback_signaler SHARED Callback_signaler.cpp) + target_link_libraries(scene_callback_signaler PRIVATE Qt5::Core) + add_library(point_dialog SHARED Show_point_dialog.cpp Show_point_dialog.ui ${Show_point_dialogUI_FILES}) target_link_libraries(point_dialog PUBLIC Qt5::OpenGL Qt5::Gui Qt5::Script Qt5::Widgets) diff --git a/Polyhedron/demo/Polyhedron/Callback_signaler.cpp b/Polyhedron/demo/Polyhedron/Callback_signaler.cpp new file mode 100644 index 00000000000..8dc0f6fe8e4 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Callback_signaler.cpp @@ -0,0 +1,11 @@ +#include "Callback_signaler.h" + +Callback_signaler::Callback_signaler() + : is_canceled(false) +{ +} + +void Callback_signaler::emit_signal (int value) const +{ + Q_EMIT progressChanged(value); +} diff --git a/Polyhedron/demo/Polyhedron/Callback_signaler.h b/Polyhedron/demo/Polyhedron/Callback_signaler.h new file mode 100644 index 00000000000..4ebcb170107 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Callback_signaler.h @@ -0,0 +1,39 @@ +#ifndef CALLBACK_SIGNALER_H +#define CALLBACK_SIGNALER_H + +#include + +#include +#ifdef scene_color_ramp_EXPORTS +# define SCENE_CALLBACK_SIGNALER_EXPORT Q_DECL_EXPORT +#else +# define SCENE_CALLBACK_SIGNALER_EXPORT Q_DECL_IMPORT +#endif + +class SCENE_CALLBACK_SIGNALER_EXPORT Callback_signaler + : public QObject +{ + Q_OBJECT + +public: + + bool is_canceled; + + Callback_signaler(); + + void emit_signal (int value) const; + +public Q_SLOTS: + + void cancel() + { + is_canceled = true; + } + +Q_SIGNALS: + + void progressChanged(int) const; +}; + + +#endif // CALLBACK_SIGNALER_H diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index d538c96e658..1e8cbb0e258 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -16,7 +16,7 @@ if(EIGEN3_FOUND) target_link_libraries(point_set_smoothing_plugin PUBLIC scene_points_with_normal_item) polyhedron_demo_plugin(point_set_average_spacing_plugin Point_set_average_spacing_plugin) - target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) else(EIGEN3_FOUND) message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Surface reconstruction plugin will not be available.") diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp index 4d20a5ff728..5b3f9f73f96 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp @@ -1,3 +1,5 @@ +//#undef CGAL_LINKED_WITH_TBB + #include "config.h" #include "Scene_points_with_normal_item.h" #include @@ -14,18 +16,37 @@ #include #include #include +#include + +#include "run_with_qprogressdialog.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else -# include "Qt_progress_bar_callback.h" - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct Compute_average_spacing_functor + : public Functor_with_signal_callback +{ + Point_set* points; + const int nb_neighbors; + boost::shared_ptr result; + + Compute_average_spacing_functor (Point_set* points, const int nb_neighbors) + : points (points), nb_neighbors (nb_neighbors), result (new double(0)) { } + + void operator()() + { + *result = CGAL::compute_average_spacing( + points->all_or_selection_if_not_empty(), + nb_neighbors, + points->parameters(). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_average_spacing_plugin : public QObject, @@ -96,14 +117,11 @@ void Polyhedron_demo_point_set_average_spacing_plugin::on_actionAverageSpacing_t CGAL::Real_timer task_timer; task_timer.start(); std::cerr << "Average spacing (k=" << nb_neighbors <<")...\n"; - Callback callback("Computing average spacing...", mw); - // Computes average spacing -// double average_spacing = CGAL::compute_average_spacing( - double average_spacing = CGAL::compute_average_spacing( - points->all_or_selection_if_not_empty(), - nb_neighbors, - points->parameters().callback (callback)); + Compute_average_spacing_functor functor (points, nb_neighbors); + run_with_qprogressdialog (functor, "Computing average spacing...", mw); + + double average_spacing = *functor.result; // Print result Kernel::Sphere_3 bsphere = points->bounding_sphere(); diff --git a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h new file mode 100644 index 00000000000..801f52fc3f1 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h @@ -0,0 +1,130 @@ +#ifndef RUN_WITH_QPROGRESSDIALOG_H +#define RUN_WITH_QPROGRESSDIALOG_H + +#include + +#include "Callback_signaler.h" + +#ifdef CGAL_LINKED_WITH_TBB +#ifndef TBB_IMPLEMENT_CPP0X +#define TBB_IMPLEMENT_CPP0X 1 +#endif +#include +#endif + +class Signal_callback +{ +public: + + +private: + + CGAL::Real_timer timer; + double t_start; + mutable double t_latest; + mutable std::size_t nb; + +public: + boost::shared_ptr latest_adv; + boost::shared_ptr state; + boost::shared_ptr signaler; + + Signal_callback(bool) + : latest_adv (new double(0)) + , state (new bool(true)) + , signaler (new Callback_signaler()) + { + timer.start(); + t_start = timer.time(); + t_latest = t_start; + } + ~Signal_callback() + { + } + + bool operator() (double advancement) const + { + if (!state) + return false; + + *latest_adv = advancement; + + // Avoid calling time() at every single iteration, which could + // impact performances very badly + ++ nb; + if (advancement != 1 && nb % 1000 != 0) + return *state; + + // If the limit is reach, interrupt the algorithm + double t = timer.time(); + if (advancement == 1 || (t - t_latest) > 0.25) + { + signaler->emit_signal (int (100. * advancement)); + + t_latest = t; + + if (signaler->is_canceled) + *state = false; + } + + return *state; + } + +}; + + +class Functor_with_signal_callback +{ +protected: + boost::shared_ptr m_callback; +public: + + Signal_callback* callback() { return m_callback.get(); } + + Functor_with_signal_callback() + : m_callback (new Signal_callback(true)) { } + + virtual void operator()() = 0; +}; + + +template +void run_with_qprogressdialog (Functor& functor, + const char* title, + QWidget* mainWindow) +{ + mainWindow->setEnabled(false); + QProgressDialog progress (QString(title), + QString("Cancel"), + 0, 100, + mainWindow); + progress.setMinimumDuration(0); + + Signal_callback* signal_callback = functor.callback(); + + QEventLoop::connect (signal_callback->signaler.get(), SIGNAL(progressChanged(int)), + &progress, SLOT(setValue(int))); + QEventLoop::connect (&progress, SIGNAL(canceled()), + signal_callback->signaler.get(), SLOT(cancel())); + +#ifdef CGAL_LINKED_WITH_TBB + std::thread thread (functor); + + while (*signal_callback->latest_adv != 1. && + *signal_callback->state) + { + QThread::msleep(10); + QApplication::processEvents (); + } + + thread.join(); +#else // Sequential version + progress.setWindowModality(Qt::WindowModal); + functor(); +#endif + + mainWindow->setEnabled(true); +} + + +#endif // RUN_WITH_QPROGRESSDIALOG_H From 9dbdc6c826d981748ced5534983ba7863be08cff Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 12:32:50 +0100 Subject: [PATCH 38/84] Fix assignment operator --- .../include/CGAL/internal/Parallel_callback.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index fa992d459ce..ba40612b5dd 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -43,6 +43,12 @@ class Parallel_callback bool m_creator; std::thread* m_thread; + // assignment operator shouldn't be used (m_callback is const ref) + Parallel_callback& operator= (const Parallel_callback&) + { + return *this; + } + public: Parallel_callback (const cpp11::function& callback, std::size_t size, @@ -73,11 +79,6 @@ public: } - Parallel_callback& operator= (const Parallel_callback& other) - { - Parallel_callback out (other); - return out; - } ~Parallel_callback () { From cea723cbffbddc8dcfa7a5f8ec1c785fdb434a92 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 12:57:39 +0100 Subject: [PATCH 39/84] Add sequential qprogressdialog --- .../include/run_with_qprogressdialog.h | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h index 801f52fc3f1..9c43f6db14c 100644 --- a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h +++ b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h @@ -2,16 +2,22 @@ #define RUN_WITH_QPROGRESSDIALOG_H #include +#include + +#include #include "Callback_signaler.h" #ifdef CGAL_LINKED_WITH_TBB -#ifndef TBB_IMPLEMENT_CPP0X -#define TBB_IMPLEMENT_CPP0X 1 -#endif -#include + typedef CGAL::Parallel_tag Concurrency_tag; +# undef TBB_IMPLEMENT_CPP0X +# define TBB_IMPLEMENT_CPP0X 1 +# include +#else + typedef CGAL::Sequential_tag Concurrency_tag; #endif + class Signal_callback { public: @@ -89,6 +95,14 @@ public: template +void run_with_qprogressdialog (Functor& functor, + const char* title, + QWidget* mainWindow) +{ + return run_with_qprogressdialog (functor, title, mainWindow); +} + +template void run_with_qprogressdialog (Functor& functor, const char* title, QWidget* mainWindow) @@ -108,20 +122,25 @@ void run_with_qprogressdialog (Functor& functor, signal_callback->signaler.get(), SLOT(cancel())); #ifdef CGAL_LINKED_WITH_TBB - std::thread thread (functor); - - while (*signal_callback->latest_adv != 1. && - *signal_callback->state) + if (boost::is_convertible::value) { - QThread::msleep(10); - QApplication::processEvents (); - } + std::thread thread (functor); + + while (*signal_callback->latest_adv != 1. && + *signal_callback->state) + { + QThread::msleep(10); + QApplication::processEvents (); + } - thread.join(); -#else // Sequential version - progress.setWindowModality(Qt::WindowModal); - functor(); -#endif + thread.join(); + } + else +#endif // Sequential version + { + progress.setWindowModality(Qt::WindowModal); + functor(); + } mainWindow->setEnabled(true); } From 4b7f5bccc44b5e5171afd9ba191bf09d90b10f10 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 15:39:56 +0100 Subject: [PATCH 40/84] Only include needed TBB headers --- STL_Extension/include/CGAL/Concurrent_compact_container.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index e0ad2fb5333..a7d9862d890 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -37,7 +37,8 @@ #include #include -#include +#include +#include #include From 6480cf2205f73c75850fb0c7785ff47d2c48afb8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 13 Mar 2018 15:41:12 +0100 Subject: [PATCH 41/84] Define a CGAL::cpp11::thread wrapper for TBB or STD --- Installation/include/CGAL/config.h | 4 ++ STL_Extension/include/CGAL/thread.h | 105 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 STL_Extension/include/CGAL/thread.h diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index 70cb2a2281f..c7fcad9736f 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -187,6 +187,10 @@ defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) #define CGAL_CFG_NO_CPP0X_UNORDERED 1 #endif +#if defined( BOOST_NO_0X_HDR_THREAD) || \ + defined( BOOST_NO_CXX11_HDR_THREAD) +#define CGAL_CFG_NO_STD_THREAD 1 +#endif #if defined(BOOST_NO_DECLTYPE) || \ defined(BOOST_NO_CXX11_DECLTYPE) || (BOOST_VERSION < 103600) #define CGAL_CFG_NO_CPP0X_DECLTYPE 1 diff --git a/STL_Extension/include/CGAL/thread.h b/STL_Extension/include/CGAL/thread.h new file mode 100644 index 00000000000..770c74bad02 --- /dev/null +++ b/STL_Extension/include/CGAL/thread.h @@ -0,0 +1,105 @@ +// Copyright (c) 2018 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_THREAD_H +#define CGAL_THREAD_H + +#include + +/* + This file defines the following: + - CGAL::cpp11::thread + - CGAL::cpp11::this_thread::sleep_for + - CGAL::cpp11::atomic + - CGAL::cpp11::chrono::seconds + + It uses either TBB or STD depending on what's available: as TBB can + quite often override `std::thread`, it is possible that TBB will be + used instead of STD even if the real CXX11 `std::thread` is + available. +*/ + +#if defined(CGAL_LINKED_WITH_TBB) +# include +# if TBB_IMPLEMENT_CPP0X +# include +# include +# include +# define CGAL_USE_TBB_THREADS 1 +# else +# define CGAL_USE_TBB_THREADS 0 +# endif +#else +# define CGAL_USE_TBB_THREADS 0 +#endif + +#if !CGAL_USE_TBB_THREADS +# if !defined(CGAL_CFG_NO_STD_THREAD) +# include +# include +# include +# define CGAL_USE_STD_THREADS 1 +# else +# define CGAL_USE_STD_THREADS 0 +# endif +#else +# define CGAL_USE_STD_THREADS 0 +#endif + +#if CGAL_USE_STD_THREADS || CGAL_USE_TBB_THREADS +# define CGAL_HAS_STD_THREADS // Useful define +#endif + +namespace CGAL { + +namespace cpp11 { + +#if CGAL_USE_TBB_THREADS + using std::thread; // std::thread is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 + namespace this_thread + { + using std::this_thread::sleep_for; // std::this_thread::sleep_for is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 + } + using tbb::atomic; + namespace chrono + { + typedef tbb::tick_count::interval_t seconds; + } +#elif CGAL_USE_STD_THREADS + using std::thread; + namespace this_thread + { + using std::this_thread::sleep_for; + } + using std::atomic; + namespace chrono + { + typedef std::chrono::duration > seconds; + } +#endif + +} // cpp11 + +} //namespace CGAL + +#undef CGAL_USE_STD_THREADS +#undef CGAL_USE_TBB_THREADS + +#endif // CGAL_THREAD_H From d11654d2f2dd8760a734320b0f64a3fff8bf600f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 15 Mar 2018 08:30:43 +0100 Subject: [PATCH 42/84] Use cpp11::thread --- .../include/CGAL/bilateral_smooth_point_set.h | 16 +++++------ .../include/CGAL/compute_average_spacing.h | 9 +++---- .../include/CGAL/internal/Parallel_callback.h | 27 +++++++++---------- .../include/CGAL/jet_estimate_normals.h | 9 +++---- .../include/CGAL/jet_smooth_point_set.h | 9 +++---- .../include/CGAL/pca_estimate_normals.h | 9 +++---- .../wlop_simplify_and_regularize_point_set.h | 9 +++---- 7 files changed, 40 insertions(+), 48 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index ab396fdfa18..166c429e43e 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -303,14 +303,14 @@ class Compute_pwns_neighbors const Tree & m_tree; const Pwns & m_pwns; Pwns_neighbors & m_pwns_neighbors; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Compute_pwns_neighbors(unsigned int k, const Tree &tree, const Pwns &pwns, Pwns_neighbors &neighbors, - tbb::atomic& advancement, - tbb::atomic& interrupted) + cpp11::atomic& advancement, + cpp11::atomic& interrupted) : m_k(k), m_tree(tree), m_pwns(pwns), m_pwns_neighbors(neighbors) , advancement (advancement), interrupted (interrupted) {} @@ -343,8 +343,8 @@ class Pwn_updater Pwns* pwns; Pwns* update_pwns; std::vector >* pwns_neighbors; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Pwn_updater(FT sharpness, @@ -352,8 +352,8 @@ public: Pwns *in, Pwns *out, std::vector >* neighbors, - tbb::atomic& advancement, - tbb::atomic& interrupted): + cpp11::atomic& advancement, + cpp11::atomic& interrupted): sharpness_angle(sharpness), radius(r), pwns(in), diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 5a21c1d5f41..b557ac389d4 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -44,7 +44,6 @@ #include #include #include -#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -112,14 +111,14 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who const unsigned int k; const std::vector& input; std::vector& output; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Compute_average_spacings(Tree& tree, unsigned int k, std::vector& points, std::vector& output, - tbb::atomic& advancement, - tbb::atomic& interrupted) + cpp11::atomic& advancement, + cpp11::atomic& interrupted) : tree(tree), k (k), input (points), output (output) , advancement (advancement) , interrupted (interrupted) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index ba40612b5dd..f5d783a7b25 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -25,10 +25,7 @@ #include -#include -#undef TBB_IMPLEMENT_CPP0X -#define TBB_IMPLEMENT_CPP0X 1 -#include +#include namespace CGAL { namespace internal { @@ -37,11 +34,11 @@ namespace Point_set_processing_3 { class Parallel_callback { const cpp11::function& m_callback; - tbb::atomic* m_advancement; - tbb::atomic* m_interrupted; + cpp11::atomic* m_advancement; + cpp11::atomic* m_interrupted; std::size_t m_size; bool m_creator; - std::thread* m_thread; + cpp11::thread* m_thread; // assignment operator shouldn't be used (m_callback is const ref) Parallel_callback& operator= (const Parallel_callback&) @@ -55,17 +52,17 @@ public: std::size_t advancement = 0, bool interrupted = false) : m_callback (callback) - , m_advancement (new tbb::atomic()) - , m_interrupted (new tbb::atomic()) + , m_advancement (new cpp11::atomic()) + , m_interrupted (new cpp11::atomic()) , m_size (size) , m_creator (true) , m_thread (NULL) { - // tbb::atomic only has default constructor, initialization done in two steps + // cpp11::atomic only has default constructor, initialization done in two steps *m_advancement = advancement; *m_interrupted = interrupted; if (m_callback) - m_thread = new std::thread (*this); + m_thread = new cpp11::thread (*this); } Parallel_callback (const Parallel_callback& other) @@ -91,8 +88,8 @@ public: delete m_thread; } - tbb::atomic& advancement() { return *m_advancement; } - tbb::atomic& interrupted() { return *m_interrupted; } + cpp11::atomic& advancement() { return *m_advancement; } + cpp11::atomic& interrupted() { return *m_interrupted; } void join() { if (m_thread != NULL) @@ -101,7 +98,7 @@ public: void operator()() { - tbb::tick_count::interval_t sleeping_time(0.00001); + cpp11::chrono::seconds sleeping_time(0.00001); while (*m_advancement != m_size) { @@ -109,7 +106,7 @@ public: *m_interrupted = true; if (*m_interrupted) return; - std::this_thread::sleep_for(sleeping_time); + cpp11::this_thread::sleep_for(sleeping_time); } m_callback (1.); } diff --git a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h index bbd97d98e3e..0fa2dc3cf38 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -44,7 +44,6 @@ #include #include #include -#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -127,14 +126,14 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute const unsigned int degree_fitting; const std::vector& input; std::vector& output; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Jet_estimate_normals(Tree& tree, unsigned int k, std::vector& points, unsigned int degree_fitting, std::vector& output, - tbb::atomic& advancement, - tbb::atomic& interrupted) + cpp11::atomic& advancement, + cpp11::atomic& interrupted) : tree(tree), k (k), degree_fitting (degree_fitting), input (points), output (output) , advancement (advancement) , interrupted (interrupted) diff --git a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h index c03062c64d9..8e87b74e42b 100644 --- a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h @@ -43,7 +43,6 @@ #include #include #include -#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -127,14 +126,14 @@ jet_smooth_point( unsigned int degree_monge; const std::vector& input; std::vector& output; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Jet_smooth_pwns (Tree& tree, unsigned int k, std::vector& points, unsigned int degree_fitting, unsigned int degree_monge, std::vector& output, - tbb::atomic& advancement, - tbb::atomic& interrupted) + cpp11::atomic& advancement, + cpp11::atomic& interrupted) : tree(tree), k (k), degree_fitting (degree_fitting), degree_monge (degree_monge), input (points), output (output) , advancement (advancement) diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 022837fc5d8..4c0abdbd778 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -45,7 +45,6 @@ #include #include #include -#include #endif // CGAL_LINKED_WITH_TBB namespace CGAL { @@ -119,14 +118,14 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute const unsigned int k; const std::vector& input; std::vector& output; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: PCA_estimate_normals(Tree& tree, unsigned int k, std::vector& points, std::vector& output, - tbb::atomic& advancement, - tbb::atomic& interrupted) + cpp11::atomic& advancement, + cpp11::atomic& interrupted) : tree(tree), k (k), input (points), output (output) , advancement (advancement) , interrupted (interrupted) diff --git a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h index d9ecad56d7e..1fc3fafc1c7 100644 --- a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h +++ b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h @@ -46,7 +46,6 @@ #include #include #include -#include #endif // CGAL_LINKED_WITH_TBB #include @@ -357,8 +356,8 @@ class Sample_point_updater const typename Kernel::FT radius; const std::vector &original_densities; const std::vector &sample_densities; - tbb::atomic& advancement; - tbb::atomic& interrupted; + cpp11::atomic& advancement; + cpp11::atomic& interrupted; public: Sample_point_updater( @@ -369,8 +368,8 @@ public: const typename Kernel::FT _radius, const std::vector &_original_densities, const std::vector &_sample_densities, - tbb::atomic& advancement, - tbb::atomic& interrupted): + cpp11::atomic& advancement, + cpp11::atomic& interrupted): update_sample_points(out), sample_points(in), original_kd_tree(_original_kd_tree), From f34d09eee965a113874dfac345aaf4b01a2853e3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 15 Mar 2018 08:51:25 +0100 Subject: [PATCH 43/84] Use function run_with_qprogressdialog() in plugins --- .../Plugins/Point_set/CMakeLists.txt | 15 ++- .../Point_set_average_spacing_plugin.cpp | 3 +- .../Point_set_bilateral_smoothing_plugin.cpp | 50 +++++--- .../Point_set_normal_estimation_plugin.cpp | 72 ++++++++---- .../Point_set_outliers_removal_plugin.cpp | 52 ++++++--- .../Point_set_shape_detection_plugin.cpp | 27 ++++- .../Point_set_simplification_plugin.cpp | 107 ++++++++++++++---- .../Point_set/Point_set_smoothing_plugin.cpp | 41 ++++--- .../Point_set/Point_set_wlop_plugin.cpp | 78 +++++++++---- .../include/run_with_qprogressdialog.h | 19 +--- 10 files changed, 327 insertions(+), 137 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 1e8cbb0e258..3725e4b61f8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -6,14 +6,14 @@ if(EIGEN3_FOUND) qt5_wrap_ui( point_set_normal_estimationUI_FILES Point_set_normal_estimation_plugin.ui) polyhedron_demo_plugin(point_set_normal_estimation_plugin Point_set_normal_estimation_plugin ${point_set_normal_estimationUI_FILES}) - target_link_libraries(point_set_normal_estimation_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_normal_estimation_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) qt5_wrap_ui( features_detection_pluginUI_FILES Features_detection_plugin.ui) polyhedron_demo_plugin(features_detection_plugin Features_detection_plugin ${features_detection_pluginUI_FILES}) target_link_libraries(features_detection_plugin PUBLIC scene_points_with_normal_item) polyhedron_demo_plugin(point_set_smoothing_plugin Point_set_smoothing_plugin) - target_link_libraries(point_set_smoothing_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_smoothing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) polyhedron_demo_plugin(point_set_average_spacing_plugin Point_set_average_spacing_plugin) target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) @@ -29,11 +29,11 @@ endif() qt5_wrap_ui(point_set_bilateral_smoothingUI_FILES Point_set_bilateral_smoothing_plugin.ui) polyhedron_demo_plugin(point_set_bilateral_smoothing_plugin Point_set_bilateral_smoothing_plugin ${point_set_bilateral_smoothingUI_FILES}) - target_link_libraries(point_set_bilateral_smoothing_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_bilateral_smoothing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) qt5_wrap_ui( ps_outliers_removal_UI_FILES Point_set_outliers_removal_plugin.ui) polyhedron_demo_plugin(point_set_outliers_removal_plugin Point_set_outliers_removal_plugin ${ps_outliers_removal_UI_FILES}) - target_link_libraries(point_set_outliers_removal_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_outliers_removal_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) qt5_wrap_ui( point_set_selectionUI_FILES Point_set_selection_widget.ui) polyhedron_demo_plugin(point_set_selection_plugin Point_set_selection_plugin ${point_set_selectionUI_FILES}) @@ -41,12 +41,11 @@ endif() qt5_wrap_ui(point_set_shape_detectionUI_FILES Point_set_shape_detection_plugin.ui) polyhedron_demo_plugin(point_set_shape_detection_plugin Point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES}) - target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_points_with_normal_item scene_polygon_soup_item) + target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_points_with_normal_item scene_polygon_soup_item scene_callback_signaler) qt5_wrap_ui(point_set_simplificationUI_FILES Point_set_simplification_plugin.ui) polyhedron_demo_plugin(point_set_simplification_plugin Point_set_simplification_plugin ${point_set_simplificationUI_FILES}) - target_link_libraries(point_set_simplification_plugin PUBLIC scene_points_with_normal_item) - + target_link_libraries(point_set_simplification_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) qt5_wrap_ui(point_set_upsamplingUI_FILES Point_set_upsampling_plugin.ui) polyhedron_demo_plugin(point_set_upsampling_plugin Point_set_upsampling_plugin ${point_set_upsamplingUI_FILES}) @@ -54,7 +53,7 @@ endif() qt5_wrap_ui(point_set_wlopFILES Point_set_wlop_plugin.ui) polyhedron_demo_plugin(point_set_wlop_plugin Point_set_wlop_plugin ${point_set_wlopFILES}) - target_link_libraries(point_set_wlop_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(point_set_wlop_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin) target_link_libraries(merge_point_sets_plugin PUBLIC scene_points_with_normal_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp index 5b3f9f73f96..13e9e0fa7db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include "run_with_qprogressdialog.h" @@ -112,7 +111,7 @@ void Polyhedron_demo_point_set_average_spacing_plugin::on_actionAverageSpacing_t if(!ok) return; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); QApplication::processEvents(); CGAL::Real_timer task_timer; task_timer.start(); std::cerr << "Average spacing (k=" << nb_neighbors <<")...\n"; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp index 8a0660462d0..14c45d7391b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp @@ -16,19 +16,42 @@ #include +#include "run_with_qprogressdialog.h" + #include "ui_Point_set_bilateral_smoothing_plugin.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else -# include "Qt_progress_bar_callback.h" - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct Bilateral_smoothing_functor + : public Functor_with_signal_callback +{ + Point_set* points; + unsigned int neighborhood_size; + unsigned int sharpness_angle; + boost::shared_ptr result; + + Bilateral_smoothing_functor (Point_set* points, + unsigned int neighborhood_size, + unsigned int sharpness_angle) + : points (points), neighborhood_size (neighborhood_size) + , sharpness_angle (sharpness_angle), result (new double(0)) { } + + void operator()() + { + *result = CGAL::bilateral_smooth_point_set + (points->all_or_selection_if_not_empty(), + neighborhood_size, + points->parameters(). + sharpness_angle(sharpness_angle). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_bilateral_smoothing_plugin : public QObject, @@ -108,7 +131,7 @@ void Polyhedron_demo_point_set_bilateral_smoothing_plugin::on_actionBilateralSmo << dialog.iterations () << " iteration(s), neighborhood size of " << dialog.neighborhood_size () << " and sharpness angle of " << dialog.sharpness_angle () << "... "; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); CGAL::Timer task_timer; task_timer.start(); @@ -116,15 +139,12 @@ void Polyhedron_demo_point_set_bilateral_smoothing_plugin::on_actionBilateralSmo { std::ostringstream oss; oss << "Bilateral smoothing (iteration " << i+1 << "/" << dialog.iterations() << ")"; - Callback callback(oss.str().c_str(), mw); - double error = - CGAL::bilateral_smooth_point_set - (points->all_or_selection_if_not_empty(), - dialog.neighborhood_size (), - points->parameters(). - sharpness_angle(dialog.sharpness_angle ()). - callback (callback)); + Bilateral_smoothing_functor functor (points, + dialog.neighborhood_size (), + dialog.sharpness_angle ()); + run_with_qprogressdialog (functor, oss.str().c_str(), mw); + double error = *functor.result; if (std::isnan(error)) // NaN return means algorithm was interrupted break; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp index 969d37fdeac..398f08f707d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp @@ -18,6 +18,8 @@ #include #include +#include "run_with_qprogressdialog.h" + #include "ui_Point_set_normal_estimation_plugin.h" #if BOOST_VERSION == 105700 @@ -28,15 +30,53 @@ // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else -# include "Qt_progress_bar_callback.h" - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct PCA_estimate_normals_functor + : public Functor_with_signal_callback +{ + Point_set* points; + int neighborhood_size; + unsigned int sharpness_angle; + + PCA_estimate_normals_functor (Point_set* points, + int neighborhood_size) + : points (points), neighborhood_size (neighborhood_size) + { } + + void operator()() + { + CGAL::pca_estimate_normals(points->all_or_selection_if_not_empty(), + neighborhood_size, + points->parameters(). + callback (*(this->callback()))); + } +}; + +struct Jet_estimate_normals_functor + : public Functor_with_signal_callback +{ + Point_set* points; + int neighborhood_size; + unsigned int sharpness_angle; + + Jet_estimate_normals_functor (Point_set* points, + int neighborhood_size) + : points (points), neighborhood_size (neighborhood_size) + { } + + void operator()() + { + CGAL::jet_estimate_normals(points->all_or_selection_if_not_empty(), + neighborhood_size, + points->parameters(). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_normal_estimation_plugin : @@ -54,6 +94,7 @@ public: void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { scene = scene_interface; + mw = mainWindow; actionNormalEstimation = new QAction(tr("Normal Estimation"), mainWindow); actionNormalEstimation->setObjectName("actionNormalEstimation"); actionNormalEstimation->setProperty("subMenuName","Point Set Processing"); @@ -165,7 +206,7 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati if(!dialog.exec()) return; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); QApplication::processEvents(); // First point to delete @@ -179,14 +220,9 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati CGAL::Timer task_timer; task_timer.start(); std::cerr << "Estimates normal direction by PCA (k=" << dialog.pca_neighbors() <<")...\n"; - Callback callback("Estimating normals by PCA...", NULL); - // Estimates normals direction. - CGAL::pca_estimate_normals(points->all_or_selection_if_not_empty(), - dialog.pca_neighbors(), - points->parameters(). - callback (callback)); - + PCA_estimate_normals_functor functor (points, dialog.pca_neighbors()); + run_with_qprogressdialog (functor, "Estimating normals by PCA...", mw); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Estimates normal direction: " << task_timer.time() << " seconds, " @@ -198,13 +234,9 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati CGAL::Timer task_timer; task_timer.start(); std::cerr << "Estimates normal direction by Jet Fitting (k=" << dialog.jet_neighbors() <<")...\n"; - Callback callback("Estimating normals by jet fitting...", NULL); - // Estimates normals direction. - CGAL::jet_estimate_normals(points->all_or_selection_if_not_empty(), - dialog.jet_neighbors(), - points->parameters(). - callback (callback)); + Jet_estimate_normals_functor functor (points, dialog.pca_neighbors()); + run_with_qprogressdialog (functor, "Estimating normals by jet fitting...", mw); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Estimates normal direction: " << task_timer.time() << " seconds, " diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp index fb57a95e917..db4b46da4eb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp @@ -15,10 +15,40 @@ #include #include -#include "Qt_progress_bar_callback.h" -typedef Qt_progress_bar_callback Callback; - #include "ui_Point_set_outliers_removal_plugin.h" + +#include "run_with_qprogressdialog.h" + +struct Outlier_removal_functor + : public Functor_with_signal_callback +{ + Point_set* points; + int nb_neighbors; + double removed_percentage; + double distance_threshold; + boost::shared_ptr result; + + Outlier_removal_functor (Point_set* points, + int nb_neighbors, + double removed_percentage, + double distance_threshold) + : points (points), nb_neighbors (nb_neighbors) + , removed_percentage (removed_percentage), distance_threshold (distance_threshold) + , result (new Point_set::iterator) { } + + void operator()() + { + // Computes outliers + *result = + CGAL::remove_outliers(*points, + nb_neighbors, + points->parameters(). + threshold_percent(removed_percentage). + threshold_distance(distance_threshold). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_outliers_removal_plugin : public QObject, @@ -34,6 +64,7 @@ private: public: void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { scene = scene_interface; + mw = mainWindow; actionOutlierRemoval = new QAction(tr("Outliers Selection"), mainWindow); actionOutlierRemoval->setProperty("subMenuName","Point Set Processing"); actionOutlierRemoval->setObjectName("actionOutlierRemoval"); @@ -90,23 +121,16 @@ void Polyhedron_demo_point_set_outliers_removal_plugin::on_actionOutlierRemoval_ const double distance_threshold = dialog.distance(); const int nb_neighbors = dialog.nbNeighbors(); - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); CGAL::Timer task_timer; task_timer.start(); std::cerr << "Select outliers (" << removed_percentage <<"% with distance threshold " << distance_threshold << ")...\n"; - Callback callback("Selecting outliers...", NULL); - // Computes outliers - Point_set::iterator first_point_to_remove = - CGAL::remove_outliers(*points, - nb_neighbors, - points->parameters(). - threshold_percent(removed_percentage). - threshold_distance(distance_threshold). - callback (callback)); - + Outlier_removal_functor functor (points, nb_neighbors, removed_percentage, distance_threshold); + run_with_qprogressdialog (functor, "Selecting outliers...", mw); + Point_set::iterator first_point_to_remove = *functor.result; std::size_t nb_points_to_remove = std::distance(first_point_to_remove, points->end()); std::size_t memory = CGAL::Memory_sizer().virtual_size(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index a3833b8c7bf..eef452a345c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -28,8 +28,6 @@ #include -#include "Qt_progress_bar_callback.h" - #include #include #include @@ -40,8 +38,27 @@ #include #include +#include "run_with_qprogressdialog.h" + #include "ui_Point_set_shape_detection_plugin.h" +template +struct Detect_shapes_functor + : public Functor_with_signal_callback +{ + Shape_detection& shape_detection; + typename Shape_detection::Parameters& op; + + Detect_shapes_functor (Shape_detection& shape_detection, + typename Shape_detection::Parameters& op) + : shape_detection (shape_detection), op (op) + { } + + void operator()() + { + shape_detection.detect(op, *(this->callback())); + } +}; struct build_from_pair { @@ -218,7 +235,7 @@ private: comments += "shape -1 no assigned shape\n"; } - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); Shape_detection shape_detection; shape_detection.set_input(*points, points->point_map(), points->normal_map()); @@ -255,8 +272,8 @@ private: // The actual shape detection. CGAL::Real_timer t; t.start(); - Qt_progress_bar_callback callback ("Detecting shapes...", mw); - shape_detection.detect(op, callback); + Detect_shapes_functor functor (shape_detection, op); + run_with_qprogressdialog (functor, "Detecting shapes...", mw); t.stop(); std::cout << shape_detection.shapes().size() << " shapes found in " diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp index cb38c76f193..9d838794b69 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp @@ -17,20 +17,80 @@ #include #include -#include "Qt_progress_bar_callback.h" +#include "run_with_qprogressdialog.h" #include "ui_Point_set_simplification_plugin.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct Compute_average_spacing_functor + : public Functor_with_signal_callback +{ + Point_set* points; + const int nb_neighbors; + boost::shared_ptr result; + + Compute_average_spacing_functor (Point_set* points, const int nb_neighbors) + : points (points), nb_neighbors (nb_neighbors), result (new double(0)) { } + + void operator()() + { + *result = CGAL::compute_average_spacing( + points->all_or_selection_if_not_empty(), + nb_neighbors, + points->parameters(). + callback (*(this->callback()))); + } +}; + +struct Grid_simplify_functor + : public Functor_with_signal_callback +{ + Point_set* points; + double grid_size; + boost::shared_ptr result; + + Grid_simplify_functor (Point_set* points, double grid_size) + : points (points), grid_size (grid_size), result (new Point_set::iterator) { } + + void operator()() + { + *result = CGAL::grid_simplify_point_set(*points, + grid_size, + points->parameters(). + callback (*(this->callback()))); + } +}; + +struct Hierarchy_simplify_functor + : public Functor_with_signal_callback +{ + Point_set* points; + unsigned int max_cluster_size; + double max_surface_variation; + boost::shared_ptr result; + + Hierarchy_simplify_functor (Point_set* points, + double max_cluster_size, + double max_surface_variation) + : points (points), max_cluster_size (max_cluster_size) + , max_surface_variation (max_surface_variation), result (new Point_set::iterator) { } + + void operator()() + { + *result = CGAL::hierarchy_simplify_point_set(*points, + points->parameters(). + size(max_cluster_size). + maximum_variation(max_surface_variation). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_simplification_plugin : public QObject, @@ -45,6 +105,7 @@ class Polyhedron_demo_point_set_simplification_plugin : public: void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface,Messages_interface*) { scene = scene_interface; + mw = mainWindow; actionSimplify = new QAction(tr("Simplification Selection"), mainWindow); actionSimplify->setProperty("subMenuName","Point Set Processing"); @@ -134,7 +195,7 @@ void Polyhedron_demo_point_set_simplification_plugin::on_actionSimplify_triggere if(!dialog.exec()) return; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); CGAL::Timer task_timer; task_timer.start(); @@ -155,35 +216,31 @@ void Polyhedron_demo_point_set_simplification_plugin::on_actionSimplify_triggere { std::cerr << "Point set grid simplification (cell size = " << dialog.gridCellSize() <<" * average spacing)...\n"; - Callback as_callback("Computing average spacing...", NULL); - // Computes average spacing - double average_spacing = CGAL::compute_average_spacing(*points, 6, /* knn = 1 ring */ - points->parameters(). - callback (as_callback)); + Compute_average_spacing_functor functor_as (points, 6); + run_with_qprogressdialog (functor_as, "Simplification: computing average spacing...", mw); - Qt_progress_bar_callback callback("Grid simplyfing...", NULL); + double average_spacing = *functor_as.result; + + Grid_simplify_functor functor (points, dialog.gridCellSize() * average_spacing); + run_with_qprogressdialog (functor, "Grid simplyfing...", mw); // Computes points to remove by Grid Clustering - first_point_to_remove = - CGAL::grid_simplify_point_set(*points, - dialog.gridCellSize()*average_spacing, - points->parameters(). - callback (callback)); + first_point_to_remove = *functor.result; + } else { std::cerr << "Point set hierarchy simplification (cluster size = " << dialog.maximumClusterSize() << ", maximum variation = " << dialog.maximumSurfaceVariation() << ")...\n"; - Qt_progress_bar_callback callback("Hierarchy simplyfing...", NULL); // Computes points to remove by Hierarchy - first_point_to_remove = - CGAL::hierarchy_simplify_point_set(*points, - points->parameters(). - size(dialog.maximumClusterSize()). - maximum_variation(dialog.maximumSurfaceVariation()). - callback(callback)); + Hierarchy_simplify_functor functor (points, dialog.maximumClusterSize(), + dialog.maximumSurfaceVariation()); + run_with_qprogressdialog (functor, "Hierarchy simplyfing...", mw); + + first_point_to_remove = *functor.result; + } std::size_t nb_points_to_remove = std::distance(first_point_to_remove, points->end()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp index 5e72b164a48..1436a2b4ae5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp @@ -12,17 +12,33 @@ #include +#include "run_with_qprogressdialog.h" + // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else -# include "Qt_progress_bar_callback.h" - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct Jet_smoothing_functor + : public Functor_with_signal_callback +{ + Point_set* points; + const int nb_neighbors; + + Jet_smoothing_functor (Point_set* points, const int nb_neighbors) + : points (points), nb_neighbors (nb_neighbors) { } + + void operator()() + { + CGAL::jet_smooth_point_set(points->all_or_selection_if_not_empty(), + nb_neighbors, + points->parameters(). + callback (*(this->callback()))); + } +}; + using namespace CGAL::Three; class Polyhedron_demo_point_set_smoothing_plugin : public QObject, @@ -83,21 +99,14 @@ void Polyhedron_demo_point_set_smoothing_plugin::on_actionJetSmoothing_triggered &ok); if(!ok) return; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); QApplication::processEvents(); - Callback callback("Smoothing point set...", NULL); - - CGAL::jet_smooth_point_set(points->all_or_selection_if_not_empty(), - nb_neighbors, - points->parameters(). - callback (callback)); + Jet_smoothing_functor functor (points, nb_neighbors); + run_with_qprogressdialog (functor, "Smoothing point set...", mw); points->invalidate_bounds(); - // calling jet_smooth_point_set breaks the normals - points->remove_normal_map(); - // update scene item->invalidateOpenGLBuffers(); scene->itemChanged(index); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp index ccd354c9b97..561b849c4f0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp @@ -15,19 +15,64 @@ #include #include +#include "run_with_qprogressdialog.h" + #include "ui_Point_set_wlop_plugin.h" // Concurrency #ifdef CGAL_LINKED_WITH_TBB -# include "Progress_bar_callback.h" - typedef Progress_bar_callback Callback; - typedef CGAL::Parallel_tag Concurrency_tag; +typedef CGAL::Parallel_tag Concurrency_tag; #else -# include "Qt_progress_bar_callback.h" - typedef Qt_progress_bar_callback Callback; - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif +struct Compute_average_spacing_functor + : public Functor_with_signal_callback +{ + Point_set* points; + const int nb_neighbors; + boost::shared_ptr result; + + Compute_average_spacing_functor (Point_set* points, const int nb_neighbors) + : points (points), nb_neighbors (nb_neighbors), result (new double(0)) { } + + void operator()() + { + *result = CGAL::compute_average_spacing( + points->all_or_selection_if_not_empty(), + nb_neighbors, + points->parameters(). + callback (*(this->callback()))); + } +}; + +struct Wlop_functor + : public Functor_with_signal_callback +{ + Point_set* points; + double select_percentage; + double neighbor_radius; + Scene_points_with_normal_item* new_item; + + Wlop_functor (Point_set* points, double select_percentage, double neighbor_radius, + Scene_points_with_normal_item* new_item) + : points (points), select_percentage (select_percentage) + , neighbor_radius (neighbor_radius), new_item (new_item) + { } + + void operator()() + { + CGAL::wlop_simplify_and_regularize_point_set + (points->all_or_selection_if_not_empty(), + new_item->point_set()->point_back_inserter(), + points->parameters(). + select_percentage (select_percentage). + neighbor_radius (neighbor_radius). + callback (*(this->callback()))); + } +}; + + using namespace CGAL::Three; class Polyhedron_demo_point_set_wlop_plugin : public QObject, @@ -42,6 +87,7 @@ class Polyhedron_demo_point_set_wlop_plugin : public: void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { scene = scene_interface; + mw = mainWindow; actionSimplifyAndRegularize = new QAction(tr("WLOP Simplification and Regularization Selection"), mainWindow); actionSimplifyAndRegularize->setProperty("subMenuName","Point Set Processing"); actionSimplifyAndRegularize->setObjectName("actionSimplifyAndRegularize"); @@ -93,7 +139,7 @@ void Polyhedron_demo_point_set_wlop_plugin::on_actionSimplifyAndRegularize_trigg if(!dialog.exec()) return; - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor(Qt::BusyCursor); CGAL::Timer task_timer; task_timer.start(); @@ -102,9 +148,9 @@ void Polyhedron_demo_point_set_wlop_plugin::on_actionSimplifyAndRegularize_trigg << dialog.neighborhoodRadius() <<" * average spacing)...\n"; // Computes average spacing - double average_spacing = CGAL::compute_average_spacing(points->all_or_selection_if_not_empty(), - 6 /* knn = 1 ring */, - points->parameters()); + Compute_average_spacing_functor functor_as (points, 6); + run_with_qprogressdialog (functor_as, "WLOP: computing average spacing...", mw); + double average_spacing = *functor_as.result; Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item(); @@ -113,15 +159,9 @@ void Polyhedron_demo_point_set_wlop_plugin::on_actionSimplifyAndRegularize_trigg item->setVisible(false); scene->addItem(new_item); - Callback callback ("WLOP simplification and regularization...", NULL); - - CGAL::wlop_simplify_and_regularize_point_set - (points->all_or_selection_if_not_empty(), - new_item->point_set()->point_back_inserter(), - points->parameters(). - select_percentage (dialog.retainedPercentage()). - neighbor_radius (dialog.neighborhoodRadius()*average_spacing). - callback (callback)); + Wlop_functor functor (points, dialog.retainedPercentage(), + dialog.neighborhoodRadius() * average_spacing, new_item); + run_with_qprogressdialog (functor, "WLOP simplification and regularization...", mw); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Simplification and regularization: " diff --git a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h index 9c43f6db14c..ff2820d363a 100644 --- a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h +++ b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h @@ -2,27 +2,20 @@ #define RUN_WITH_QPROGRESSDIALOG_H #include -#include - #include +#include #include "Callback_signaler.h" #ifdef CGAL_LINKED_WITH_TBB - typedef CGAL::Parallel_tag Concurrency_tag; -# undef TBB_IMPLEMENT_CPP0X -# define TBB_IMPLEMENT_CPP0X 1 -# include +typedef CGAL::Parallel_tag Concurrency_tag; #else - typedef CGAL::Sequential_tag Concurrency_tag; +typedef CGAL::Sequential_tag Concurrency_tag; #endif class Signal_callback { -public: - - private: CGAL::Real_timer timer; @@ -121,15 +114,15 @@ void run_with_qprogressdialog (Functor& functor, QEventLoop::connect (&progress, SIGNAL(canceled()), signal_callback->signaler.get(), SLOT(cancel())); -#ifdef CGAL_LINKED_WITH_TBB +#ifdef CGAL_HAS_STD_THREADS if (boost::is_convertible::value) { - std::thread thread (functor); + CGAL::cpp11::thread thread (functor); while (*signal_callback->latest_adv != 1. && *signal_callback->state) { - QThread::msleep(10); + CGAL::cpp11::this_thread::sleep_for(CGAL::cpp11::chrono::seconds(0.1)); QApplication::processEvents (); } From 67c830879ce7a7aacdd0a581210d097d8fe056ec Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 15 Mar 2018 14:35:36 +0100 Subject: [PATCH 44/84] Document callbacks in all functions + in PSP named parameters --- .../doc/Point_set_processing_3/NamedParameters.txt | 6 ++++++ .../include/CGAL/bilateral_smooth_point_set.h | 7 +++++++ .../include/CGAL/grid_simplify_point_set.h | 7 +++++++ .../include/CGAL/hierarchy_simplify_point_set.h | 7 +++++++ .../include/CGAL/jet_estimate_normals.h | 13 +++++++++++-- .../include/CGAL/jet_smooth_point_set.h | 12 ++++++++++-- .../include/CGAL/pca_estimate_normals.h | 13 +++++++++++-- .../include/CGAL/remove_outliers.h | 9 ++++++++- .../CGAL/wlop_simplify_and_regularize_point_set.h | 7 +++++++ 9 files changed, 74 insertions(+), 7 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index ee2acdba8f2..16522c3acfd 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -58,6 +58,12 @@ No default value. \b Default: if \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined, then `CGAL::Eigen_svd` is used.\n \cgalNPEnd +\cgalNPBegin{callback} \anchor PSP_callback +is a mechanism to get feedback on the advancement of the algorithm while it's running and to interrupt it if needed. It is called regularly when the algorithm is running: the current advancement (between 0. and 1.) is passed as parameter. If it returns `true`, then the algorithm continues its execution normally; if it returns `false`, the algorithm is stopped.\n +\b Type: `CGAL::cpp11::function`.\n +\b Default: empty function.\n +\cgalNPEnd + \cgalNPBegin{query_point_map} \anchor PSP_query_point_map is the property map containing the points associated to the iterators of the point range `queries`.\n \b Type: a class model of `ReadablePropertyMap` with diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index 166c429e43e..4c0d896f1fb 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -421,6 +421,13 @@ public: \cgalParamBegin{normal_map} a model of `ReadWritePropertyMap` with value type `geom_traits::Vector_3`.\cgalParamEnd \cgalParamBegin{sharpness_angle} controls the sharpness of the result.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped, all points are left unchanged + and the function return `NaN`.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd diff --git a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h index 851f48cf6fc..8bd23ec3c29 100644 --- a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h @@ -189,6 +189,13 @@ public: \cgalNamedParamsBegin \cgalParamBegin{point_map} a model of `ReadWritePropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and simplification stops with + no guarantee on the outut.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd diff --git a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h index 18f0cf25da3..04c044cb25a 100644 --- a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h @@ -143,6 +143,13 @@ namespace CGAL { if Eigen 3 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined then an overload using `Eigen_diagonalize_traits` is provided. Otherwise, the internal implementation `CGAL::Diagonalize_traits` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and simplification stops with + no guarantee on the outut.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd diff --git a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h index 0fa2dc3cf38..cbeaa348917 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -191,6 +191,13 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute \cgalParamBegin{svd_traits} template parameter for the class `Monge_via_jet_fitting`. If \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined, then `CGAL::Eigen_svd` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the remaining normals are + left unchanged.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd */ @@ -271,7 +278,8 @@ jet_estimate_normals( internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, kd_tree_points.size()); - std::vector normals (kd_tree_points.size ()); + std::vector normals (kd_tree_points.size (), + CGAL::NULL_VECTOR); CGAL::internal::Jet_estimate_normals f (tree, k, kd_tree_points, degree_fitting, normals, parallel_callback.advancement(), @@ -279,7 +287,8 @@ jet_estimate_normals( tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); std::size_t i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - put (normal_map, *it, normals[i]); + if (normals[i] != CGAL::NULL_VECTOR) + put (normal_map, *it, normals[i]); parallel_callback.join(); } diff --git a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h index 8e87b74e42b..bb2135be03c 100644 --- a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h @@ -194,6 +194,13 @@ jet_smooth_point( \cgalParamBegin{svd_traits} template parameter for the class `Monge_via_jet_fitting`. If \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined, then `CGAL::Eigen_svd` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the remaining points are + left unchanged.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd @@ -261,7 +268,7 @@ jet_smooth_point_set( internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, kd_tree_points.size()); - std::vector mutated_points (kd_tree_points.size ()); + std::vector mutated_points (kd_tree_points.size (), CGAL::ORIGIN); CGAL::internal::Jet_smooth_pwns f (tree, k, kd_tree_points, degree_fitting, degree_monge, mutated_points, @@ -270,7 +277,8 @@ jet_smooth_point_set( tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); unsigned int i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - put(point_map, *it, mutated_points[i]); + if (mutated_points[i] != CGAL::ORIGIN) + put(point_map, *it, mutated_points[i]); parallel_callback.join(); diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 4c0abdbd778..46b62a68758 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -178,6 +178,13 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd \cgalParamBegin{normal_map} a model of `WritablePropertyMap` with value type `geom_traits::Vector_3`.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the remaining normals are + left unchanged.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd */ @@ -252,7 +259,8 @@ pca_estimate_normals( internal::Point_set_processing_3::Parallel_callback parallel_callback (callback, kd_tree_points.size()); - std::vector normals (kd_tree_points.size ()); + std::vector normals (kd_tree_points.size (), + CGAL::NULL_VECTOR); CGAL::internal::PCA_estimate_normals f (tree, k, kd_tree_points, normals, parallel_callback.advancement(), @@ -260,7 +268,8 @@ pca_estimate_normals( tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); unsigned int i = 0; for(it = points.begin(); it != points.end(); ++ it, ++ i) - put (normal_map, *it, normals[i]); + if (normals[i] != CGAL::NULL_VECTOR) + put (normal_map, *it, normals[i]); parallel_callback.join(); } diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 9980ec462b2..3300d2c6696 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -133,6 +133,13 @@ compute_avg_knn_sq_distance_3( \cgalParamBegin{threshold_percent} maximum percentage of points to remove.\cgalParamEnd \cgalParamBegin{threshold_distance} minimum distance for a point to be considered as outlier (distance here is the square root of the average squared distance to K nearest neighbors).\cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped, all points are left unchanged + and the function return `points.end()`.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd @@ -209,7 +216,7 @@ remove_outliers( tree, k); sorted_points.insert( std::make_pair(sq_distance, *it) ); if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) - break; + return points.end(); } // Replaces [points.begin(), points.end()) range by the multimap content. diff --git a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h index 1fc3fafc1c7..3d9c0f43c52 100644 --- a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h +++ b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h @@ -450,6 +450,13 @@ public: value is 35. More iterations give a more regular result but increase the runtime.\cgalParamEnd \cgalParamBegin{require_uniform_sampling} an optional preprocessing, which will give better result if the distribution of the input points is highly non-uniform. The default value is `false`. \cgalParamEnd + \cgalParamBegin{callback} an instance of + `cpp11::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped, no output points are + generated.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd From ac391e0fb2cd4d4b496b3033b7397235baf8f39a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 15 Mar 2018 15:47:14 +0100 Subject: [PATCH 45/84] Add example for callbacks --- .../Point_set_processing_3.txt | 12 +++ .../doc/Point_set_processing_3/examples.txt | 1 + .../Point_set_processing_3/CMakeLists.txt | 1 + .../callback_example.cpp | 94 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 82b37b231c2..66c96bca219 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -632,6 +632,18 @@ point set: \cgalExample{Point_set_processing_3/structuring_example.cpp} +\section Point_set_processing_3Callbacks Callbacks + +Several functions of this package provide a callback mechanism that enables the user to track the progress of the algorithms and to interrupt them if needed. A callback, in this package, is an instance of `CGAL::cpp11::function` that takes the advancement as a parameter (between 0. when the algorithm begins to 1. when the algorithm is completed) and that returns `true` if the algorithm should carry on, `false` otherwise. It is passed as a named parameter with an empty function as default. + +Algorithms that support this mechanism are detailed in the [Reference Manual](@ref PkgPointSetProcessing), along with the effect that an early interruption has on the output. + +\subsection Point_set_processing_3Example_callbacks Example + +The following example defines a callback that displays the name of the current algorithm along with the progress (as a percentage) updated every \f$1/10th\f$ of a second. + +\cgalExample{Point_set_processing_3/callback_example.cpp} + \section Point_set_processing_3ImplementationHistory Implementation History diff --git a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt index 7c9c599da36..43849ae022c 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt @@ -17,4 +17,5 @@ \example Point_set_processing_3/edge_aware_upsample_point_set_example.cpp \example Point_set_processing_3/edges_example.cpp \example Point_set_processing_3/structuring_example.cpp +\example Point_set_processing_3/callback_example.cpp */ diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index 2712f080b1c..87697e6325a 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -57,6 +57,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "wlop_simplify_and_regularize_point_set_example.cpp" ) create_single_source_cgal_program( "edge_aware_upsample_point_set_example.cpp" ) create_single_source_cgal_program( "structuring_example.cpp" ) + create_single_source_cgal_program( "callback_example.cpp" ) set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) create_single_source_cgal_program( "read_ply_points_with_colors_example.cpp" CXX_FEATURES ${needed_cxx_features} ) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp new file mode 100644 index 00000000000..d393f20f090 --- /dev/null +++ b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp @@ -0,0 +1,94 @@ +#include +#include +#include + +#include +#include +#include + +#include +#include + +// Types +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel::FT FT; +typedef Kernel::Point_3 Point; +typedef CGAL::Random_points_on_sphere_3 Generator; + +// Concurrency +#ifdef CGAL_LINKED_WITH_TBB +typedef CGAL::Parallel_tag Concurrency_tag; +#else +typedef CGAL::Sequential_tag Concurrency_tag; +#endif + +// instance of CGAL::cpp11::function +struct Progress_to_std_cerr_callback +{ + mutable std::size_t nb; + CGAL::Real_timer timer; + double t_start; + mutable double t_latest; + const std::string name; + + Progress_to_std_cerr_callback (const char* name) + : name (name) + { + timer.start(); + t_start = timer.time(); + t_latest = t_start; + } + + bool operator()(double advancement) const + { + // Avoid calling time() at every single iteration, which could + // impact performances very badly + ++ nb; + if (advancement != 1 && nb % 1000 != 0) + return true; + + double t = timer.time(); + if (advancement == 1 || (t - t_latest) > 0.1) // Update every 1/10th of second + { + std::cerr << "\r" // Return at the beginning of same line and overwrite + << name << ": " << int(advancement * 100) << "%"; + + if (advancement == 1) + std::cerr << std::endl; + } + + return true; + } +}; + + +int main () +{ + // Generate 1000000 points on a sphere of radius 100. + std::vector points; + points.reserve (1000000); + Generator generator(100.); + CGAL::cpp11::copy_n (generator, 1000000, std::back_inserter(points)); + + // Compute average spacing + FT average_spacing = CGAL::compute_average_spacing + (points, 6, + CGAL::parameters::callback + (Progress_to_std_cerr_callback("Computing average spacing"))); + + // Simplify on a grid with a size of twice the average spacing + points.erase(CGAL::grid_simplify_point_set + (points, 2. * average_spacing, + CGAL::parameters::callback + (Progress_to_std_cerr_callback("Grid simplification"))), + points.end()); + + // Smooth simplified point set + CGAL::jet_smooth_point_set + (points, 6, + CGAL::parameters::callback + (Progress_to_std_cerr_callback("Jet smoothing"))); + + return EXIT_SUCCESS; +} + From 941e376ce6ab5055d1fe2cd4dccdde87b07fc11c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 16 Mar 2018 09:18:09 +0100 Subject: [PATCH 46/84] Include remarks from review --- .../doc/Point_set_processing_3/NamedParameters.txt | 2 ++ .../Point_set_processing_3/Point_set_processing_3.txt | 10 +++++++++- .../include/CGAL/grid_simplify_point_set.h | 2 +- .../include/CGAL/hierarchy_simplify_point_set.h | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index 16522c3acfd..6b3226af96f 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -60,6 +60,8 @@ No default value. \cgalNPBegin{callback} \anchor PSP_callback is a mechanism to get feedback on the advancement of the algorithm while it's running and to interrupt it if needed. It is called regularly when the algorithm is running: the current advancement (between 0. and 1.) is passed as parameter. If it returns `true`, then the algorithm continues its execution normally; if it returns `false`, the algorithm is stopped.\n +The callback will be copied and therefore needs to be lightweight.\n +Note that when a callback is run on a parallelized algorithm with `CGAL::Parallel_tag`, it is called asynchronously on a separate thread and should then be thread-safe.\n \b Type: `CGAL::cpp11::function`.\n \b Default: empty function.\n \cgalNPEnd diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 66c96bca219..ccd0c750df0 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -640,7 +640,15 @@ Algorithms that support this mechanism are detailed in the [Reference Manual](@r \subsection Point_set_processing_3Example_callbacks Example -The following example defines a callback that displays the name of the current algorithm along with the progress (as a percentage) updated every \f$1/10th\f$ of a second. +The following example defines a callback that displays the name of the current algorithm along with the progress (as a percentage) updated every \f$1/10th\f$ of a second. While the algorithm is running, the console output will typically look like this: + +\code{.sh} +Computing average spacing: 100% +Grid simplification: 100% +Jet smoothing: 54% +\endcode + +Thanks to the carriage return character `\r`, the lines are overwritten and the user sees the percentage increasing on each line. \cgalExample{Point_set_processing_3/callback_example.cpp} diff --git a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h index 8bd23ec3c29..2dcb7ab6c7e 100644 --- a/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/grid_simplify_point_set.h @@ -195,7 +195,7 @@ public: 1.) is passed as parameter. If it returns `true`, then the algorithm continues its execution normally; if it returns `false`, the algorithm is stopped and simplification stops with - no guarantee on the outut.\cgalParamEnd + no guarantee on the output.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd diff --git a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h index 04c044cb25a..15580c55cdb 100644 --- a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h @@ -149,7 +149,7 @@ namespace CGAL { 1.) is passed as parameter. If it returns `true`, then the algorithm continues its execution normally; if it returns `false`, the algorithm is stopped and simplification stops with - no guarantee on the outut.\cgalParamEnd + no guarantee on the output.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd From 16c0ae5f453487c5634dcb4647c79315183fd17d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 16 Mar 2018 15:04:48 +0100 Subject: [PATCH 47/84] Fix TBB includes in Mesh_3 --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 1 + Mesh_3/include/CGAL/Mesh_3/Mesher_3.h | 6 +----- Mesh_3/include/CGAL/Mesh_3/Mesher_level.h | 1 - Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h | 4 +++- Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h | 3 ++- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index c0ce67121ee..e4844d82a13 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -56,6 +56,7 @@ #ifdef CGAL_LINKED_WITH_TBB # include +# include #endif #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index d0ee40fb0d7..f277be4e6b9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -57,11 +57,7 @@ #endif #ifdef CGAL_LINKED_WITH_TBB -# if TBB_IMPLEMENT_CPP0X -# include -# else -# include -# endif +# include #endif #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h index dc629bd5b20..06170f3d91a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h @@ -43,7 +43,6 @@ #ifdef CGAL_LINKED_WITH_TBB # include -# include #endif #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h index 3c0a50c9620..10aac5954f7 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h @@ -31,7 +31,9 @@ #include #include #ifdef CGAL_LINKED_WITH_TBB - #include + #include + #include + #include #endif #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h index 35cd8ac92be..6c1318f2f57 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h @@ -34,7 +34,8 @@ #include #include #ifdef CGAL_LINKED_WITH_TBB - #include + #include + #include #endif #include From 7576160cf853a6ca096f6879b12f228c20c08201 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 29 May 2018 11:34:02 +0200 Subject: [PATCH 48/84] Improve doc of NP callback --- .../doc/Point_set_processing_3/NamedParameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index 6b3226af96f..d6341e19f03 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -61,7 +61,7 @@ No default value. \cgalNPBegin{callback} \anchor PSP_callback is a mechanism to get feedback on the advancement of the algorithm while it's running and to interrupt it if needed. It is called regularly when the algorithm is running: the current advancement (between 0. and 1.) is passed as parameter. If it returns `true`, then the algorithm continues its execution normally; if it returns `false`, the algorithm is stopped.\n The callback will be copied and therefore needs to be lightweight.\n -Note that when a callback is run on a parallelized algorithm with `CGAL::Parallel_tag`, it is called asynchronously on a separate thread and should then be thread-safe.\n +Note that when a callback is run on a parallelized algorithm with `CGAL::Parallel_tag`, it is called asynchronously on a separate thread and shouldn't access or modify the variables that are parameters of the algorithm.\n \b Type: `CGAL::cpp11::function`.\n \b Default: empty function.\n \cgalNPEnd From f722955b45c1833fa9125639c00c9f41c1cbf9d1 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 29 May 2018 12:22:46 +0200 Subject: [PATCH 49/84] Add missing includes --- Point_set_processing_3/include/CGAL/jet_estimate_normals.h | 1 + Point_set_processing_3/include/CGAL/jet_smooth_point_set.h | 1 + Point_set_processing_3/include/CGAL/pca_estimate_normals.h | 1 + 3 files changed, 3 insertions(+) diff --git a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h index cbeaa348917..362bf0abf19 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h index bb2135be03c..e9054ba2147 100644 --- a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 46b62a68758..68da25df8d8 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include From a76d289ef723f429d04d6c1f0c66288b3d450e22 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 30 May 2018 11:24:04 +0200 Subject: [PATCH 50/84] Update CHANGES.md --- Installation/CHANGES.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 78fc891eea6..5bf98c3eb63 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -32,6 +32,18 @@ Release date: September 2018 to reflect the real needs of the code (some types and operators were used in the code but did not appear in the concepts). +### Point Set Processing + +- Added a callback mechanism for functions + `CGAL::bilateral_smooth_point_set()`, + `CGAL::compute_average_spacing()`, + `CGAL::grid_simplify_point_set()`, + `CGAL::hierarchy_simplify_point_set()`, + `CGAL::jet_estimate_normals()`, `CGAL::jet_smooth_point_set()`, + `CGAL::pca_estimate_normals()`, `CGAL::remove_outliers()` and + `CGAL::wlop_simplify_and_regularize_point_set()`. + + ### Polygon Mesh Processing - Added a function to apply a transformation to a mesh : - `CGAL::Polygon_mesh_processing::transform()` From 6d60cd99babfcb0174de423860ce0e157d4a065b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 4 Jun 2018 12:27:22 +0200 Subject: [PATCH 51/84] Add static functions to gain access to the mainwindow and the scene. Use it to automatically decide which selection_io_plugin should be used. --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 1 + Polyhedron/demo/Polyhedron/MainWindow.cpp | 4 + Polyhedron/demo/Polyhedron/MainWindow.h | 3 + .../Plugins/IO/Selection_io_plugin.cpp | 9 +- Polyhedron/demo/Polyhedron/Three.cpp | 132 ++++++++++++++++++ Three/include/CGAL/Three/Three.h | 55 ++++++++ 6 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 Polyhedron/demo/Polyhedron/Three.cpp create mode 100644 Three/include/CGAL/Three/Three.h diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 47b9048b765..e4145a9359d 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -171,6 +171,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) add_library(demo_framework SHARED Scene.cpp Viewer.cpp + Three.cpp ${ViewerUI_FILES} ${CGAL_Qt5_RESOURCE_FILES} ${CGAL_Qt5_MOC_FILES} Viewer_interface_moc.cpp diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 9fcb2ffb6c9..38609ce3b01 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -44,6 +44,7 @@ # endif #endif +#include #include #include #include @@ -131,6 +132,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) ui = new Ui::MainWindow; ui->setupUi(this); menuBar()->setNativeMenuBar(false); + CGAL::Three::Three::s_mainwindow = this; menu_map[ui->menuOperations->title()] = ui->menuOperations; this->verbose = verbose; // remove the Load Script menu entry, when the demo has not been compiled with QT_SCRIPT_LIB @@ -147,6 +149,8 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) scene = new Scene(this); viewer->textRenderer()->setScene(scene); viewer->setScene(scene); + CGAL::Three::Three::s_scene = scene; + CGAL::Three::Three::s_connectable_scene = scene; ui->actionMaxTextItemsDisplayed->setText(QString("Set Maximum Text Items Displayed : %1").arg(viewer->textRenderer()->getMax_textItems())); { QShortcut* shortcut = new QShortcut(QKeySequence(Qt::ALT+Qt::Key_Q), this); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 0f15e8e2112..c1eb1079623 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -48,6 +49,7 @@ namespace Ui { class MAINWINDOW_EXPORT MainWindow : public CGAL::Qt::DemosMainWindow, public Messages_interface, + public CGAL::Three::Three, protected QScriptable { Q_OBJECT @@ -410,6 +412,7 @@ private: //!Called when "Add new group" in the file menu is triggered. QAction* actionAddToGroup; QAction* actionResetDefaultLoaders; + CGAL::Three::Three* three; void print_message(QString message) { messages->information(message); } Messages_interface* messages; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Selection_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Selection_io_plugin.cpp index c125a01656e..9405afa1e03 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Selection_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Selection_io_plugin.cpp @@ -1,5 +1,6 @@ #include "Scene_polyhedron_selection_item.h" #include +#include #include using namespace CGAL::Three; class Polyhedron_demo_selection_io_plugin : @@ -19,7 +20,13 @@ public: #endif - bool canLoad() const { return true; } + bool canLoad() const { + Scene_facegraph_item* sel_item = qobject_cast(CGAL::Three::Three::scene()->item( + CGAL::Three::Three::scene()->mainSelectionIndex())); + if(sel_item) + return true; + return false; + } CGAL::Three::Scene_item* load(QFileInfo fileinfo) { if(fileinfo.suffix().toLower() != "txt") return 0; // There will be no actual loading at this step. diff --git a/Polyhedron/demo/Polyhedron/Three.cpp b/Polyhedron/demo/Polyhedron/Three.cpp new file mode 100644 index 00000000000..ae5b0f0dc2e --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Three.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +using namespace CGAL::Three; + +QMainWindow* Three::s_mainwindow = NULL; +Scene_interface* Three::s_scene = NULL; +QObject* Three::s_connectable_scene = NULL; +Three* Three::s_three = NULL; + +QMainWindow* Three::mainWindow() +{ + return s_mainwindow; +} + +Scene_interface* Three::scene() +{ + return s_scene; +} + +QObject* Three::connectableScene() +{ + return s_connectable_scene; +} + +Three* Three::messages() +{ + return s_three; +} + +Three::Three() +{ + Three::s_three = this; +} + +template +SceneType* Three::getSelectedItem(){ + Q_FOREACH(int item_id , scene()->selectionIndices()) + { + SceneType* scene_item = qobject_cast(scene()->item(item_id)); + if(scene_item) + return scene_item; + } + return NULL; +} + +void Three::addDockWidget(QDockWidget* dock_widget) +{ + mainWindow()->addDockWidget(::Qt::LeftDockWidgetArea, dock_widget); + dock_widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); + + QList dockWidgets = mainWindow()->findChildren(); + int counter = 0; + Q_FOREACH(QDockWidget* dock, dockWidgets) { + if( mainWindow()->dockWidgetArea(dock) != ::Qt::LeftDockWidgetArea || + dock == dock_widget ) + { continue; } + + if(++counter > 1) { + mainWindow()->tabifyDockWidget(dock, dock_widget); + return; + } + } +} + + +void Three::autoConnectActions(Polyhedron_demo_plugin_interface *plugin) +{ + QObject* thisObject = dynamic_cast(plugin); + if(!thisObject) + return; + + const QMetaObject* metaObject = thisObject->metaObject(); + QVector methods; + QVector methodsNames; + QSet connected; + for(int i = metaObject->methodOffset(); + i < metaObject->methodCount(); + ++i) + { + const int pos = QString(metaObject->method(i).methodSignature()).indexOf('('); + methodsNames << QString(metaObject->method(i).methodSignature()).left(pos); + + methods << metaObject->method(i); + } + + Q_FOREACH(QAction* action, plugin->actions()) + { + bool success = false; + const QMetaObject* action_metaObject = action->metaObject(); + for(int i = action_metaObject->methodOffset(); + i < action_metaObject->methodCount(); ++i) + { + QMetaMethod action_method = action_metaObject->method(i); + + if(action_method.methodType() == QMetaMethod::Signal) + { + const int pos = QString(action_method.methodSignature()).indexOf('('); + QString methodName = QString(action_method.methodSignature()).left(pos); + + QString slotName = + QString("on_%1_%2").arg(action->objectName()).arg(methodName); +// qDebug() << thisObject->tr("Slot %1 (%2)...").arg(slotName).arg(i); + int index = methodsNames.indexOf(slotName); + if(index>=0 && !connected.contains(slotName)) + { + const bool ok = QObject::connect(action, + qPrintable(QString("2%1").arg(QString(action_method.methodSignature()))), + thisObject, + qPrintable(QString("1%1").arg(QString(methods[index].methodSignature())))); + + if(!ok) + { + qDebug() << thisObject->tr("Cannot connect method %1.%2 to slot %3!") + .arg(action->objectName()) + .arg(QString(action_method.methodSignature())) + .arg(QString(methods[index].methodSignature())); + } + else { + success = true; + connected << slotName; + } + } + } + } // end for each method of action + if(!success) + qDebug("ERROR: Failed to autoconnect the action \"%s\"!", + action->objectName().toUtf8().data()); + } // end foreach action of actions() +} diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h new file mode 100644 index 00000000000..db4779f5d66 --- /dev/null +++ b/Three/include/CGAL/Three/Three.h @@ -0,0 +1,55 @@ +#ifndef THREE_H +#define THREE_H +#include +#include +#include +#include + +#ifdef three_EXPORTS +# define THREE_EXPORT Q_DECL_EXPORT +#else +# define THREE_EXPORT Q_DECL_IMPORT +#endif + +namespace CGAL{ +namespace Three{ +class Polyhedron_demo_plugin_interface; +class THREE_EXPORT Three{ +public: + + Three(); + virtual ~Three(){} + static QMainWindow* mainWindow(); + static Scene_interface* scene(); + static QObject* connectableScene(); + static Three* messages(); + /*! \brief Adds a dock widget to the interface + * + * Adds a dock widget in the left section of the MainWindow. If the slot is already taken, the dock widgets will be tabified. + */ + void addDockWidget(QDockWidget* dock_widget); + + /*! \brief Gets an item of the templated type. + * \returns the first `SceneType` item found in the scene's list of currently selected items; + * \returns NULL if there is no `SceneType` in the list. + */ + template + static SceneType* getSelectedItem(); + + /*! \brief Automatically connects each action of `plugin` to the corresponding slot. + * + * \attention Each action named `ActionName` in the plugin's `actions()` list must have a corresponding slot named `on_ActionsName_triggered()` + * in the plugin. + */ + static void autoConnectActions(CGAL::Three::Polyhedron_demo_plugin_interface* plugin); +protected: + static QMainWindow* s_mainwindow; + static Scene_interface* s_scene; + static QObject* s_connectable_scene; + static Three* s_three; + +}; +} +} + +#endif // THREE_H From c9c3fbc7028214d44609bc44df9144f443bdbf57 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Jun 2018 09:28:00 +0200 Subject: [PATCH 52/84] Add license to the new file --- Three/include/CGAL/Three/Three.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index db4779f5d66..53ea8dfcd73 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -1,5 +1,8 @@ #ifndef THREE_H #define THREE_H + +#include + #include #include #include From beb3408663997780e8bc72bcebf7c11c5c140ea9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 5 Jun 2018 14:26:59 +0200 Subject: [PATCH 53/84] Add forward declarations and remove dependency to Solver_interface --- .../CGAL/boost/graph/named_params_helper.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index 027982c9015..166736e8616 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -23,14 +23,6 @@ #include #include -#include - -#if defined(CGAL_EIGEN3_ENABLED) -#include -#elif defined(CGAL_LAPACK_ENABLED) -#include -#endif - #include #include @@ -41,6 +33,15 @@ #include namespace CGAL { + + // forward declarations to avoid dependency to Solver_interface + template + class Default_diagonalize_traits; + class Eigen_svd; + class Lapack_svd; + // + + //helper classes template class property_map_selector From 911b6eb4c1f80b339c65a666d8063156b5a53673 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 6 Jun 2018 16:44:39 +0200 Subject: [PATCH 54/84] Fix error in print_polyhedron --- Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h index 35726c19313..eae9c811ca0 100644 --- a/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h +++ b/Polyhedron_IO/include/CGAL/IO/generic_print_polyhedron.h @@ -28,6 +28,7 @@ #include #include #include + #include #include #include @@ -80,7 +81,7 @@ generic_print_polyhedron( std::ostream& out, Writer& writer) { generic_print_polyhedron(out, P, writer, - get_property_map(CGAL::vertex_point, P)); + get(CGAL::vertex_point, P)); } } //namespace CGAL #endif // CGAL_IO_GENERIC_PRINT_POLYHEDRON_H // From 1c7ab0d3aac7ae2c9f832fe2dc94f6ad50c7d71c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 8 Jun 2018 09:04:34 +0200 Subject: [PATCH 55/84] Fix dependencies files. --- BGL/package_info/BGL/dependencies | 1 - Point_set_3/package_info/Point_set_3/dependencies | 1 - .../package_info/Subdivision_method_3/dependencies | 1 - 3 files changed, 3 deletions(-) diff --git a/BGL/package_info/BGL/dependencies b/BGL/package_info/BGL/dependencies index 73de807750e..4a55ee6163f 100644 --- a/BGL/package_info/BGL/dependencies +++ b/BGL/package_info/BGL/dependencies @@ -19,5 +19,4 @@ Number_types Profiling_tools Property_map STL_Extension -Solver_interface Stream_support diff --git a/Point_set_3/package_info/Point_set_3/dependencies b/Point_set_3/package_info/Point_set_3/dependencies index 372b476bbed..d5ec00a4fea 100644 --- a/Point_set_3/package_info/Point_set_3/dependencies +++ b/Point_set_3/package_info/Point_set_3/dependencies @@ -10,6 +10,5 @@ Point_set_processing_3 Profiling_tools Property_map STL_Extension -Solver_interface Stream_support Surface_mesh diff --git a/Subdivision_method_3/package_info/Subdivision_method_3/dependencies b/Subdivision_method_3/package_info/Subdivision_method_3/dependencies index e85d728f1f7..95d535dc571 100644 --- a/Subdivision_method_3/package_info/Subdivision_method_3/dependencies +++ b/Subdivision_method_3/package_info/Subdivision_method_3/dependencies @@ -10,6 +10,5 @@ Number_types Profiling_tools Property_map STL_Extension -Solver_interface Stream_support Subdivision_method_3 From 0a14aec59e24d528d1f12f78832c23ab08ccfb0c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 8 Jun 2018 09:11:29 +0200 Subject: [PATCH 56/84] Add misisng license header --- Three/include/CGAL/Three/Three.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 53ea8dfcd73..d962ac4d4b2 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -1,3 +1,24 @@ +// Copyright (c) 2018 GeometryFactory Sarl (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// 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: GPL-3.0+ +// +// +// Author(s) : Maxime GIMENO + #ifndef THREE_H #define THREE_H From abfeaf39cd995fd5bf9c9eb98d4b629ecc389bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 11 Jun 2018 14:02:39 +0200 Subject: [PATCH 57/84] Improved STL reader --- Polyhedron_IO/include/CGAL/IO/STL_reader.h | 504 +++++++++++++-------- 1 file changed, 309 insertions(+), 195 deletions(-) diff --git a/Polyhedron_IO/include/CGAL/IO/STL_reader.h b/Polyhedron_IO/include/CGAL/IO/STL_reader.h index 049b0f4b04b..5bf8cde0059 100644 --- a/Polyhedron_IO/include/CGAL/IO/STL_reader.h +++ b/Polyhedron_IO/include/CGAL/IO/STL_reader.h @@ -15,221 +15,335 @@ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // -// Author(s) : Andreas Fabri +// Author(s) : Andreas Fabri, +// Mael Rouxel-Labbé #ifndef CGAL_IO_STL_READER_H #define CGAL_IO_STL_READER_H #include +#include + #include -#include -#include -#include -#include + #include +#include +#include +#include +#include -namespace CGAL{ +namespace CGAL { - bool - read_STL( std::istream& input, - std::vector< cpp11::array >& points, - std::vector< cpp11::array >& facets, - bool verbose = false) +bool read_ASCII_facet(std::istream& input, + std::vector >& points, + std::vector >& facets, + int& index, + std::map, int >& index_map, + bool verbose = false) +{ + // Here, we have already read the word 'facet' and are looking to read till 'endfacet' + + std::string s; + std::string vertex("vertex"), + endfacet("endfacet"); + + int count = 0; + cpp11::array p; + cpp11::array ijk; + + while(input >> s) { - bool is_binary_file = false; - - std::string s, solid("solid"), facet("facet"); - std::map, int> pmap; - int index = 0; - cpp11::array ijk; - cpp11::array p; + if(s == endfacet) + { + if(count != 3) + { + if(verbose) + std::cerr << "Error: only triangulated surfaces are supported" << std::endl; - char line[80]; - int i = 0, ni = 0; - - // read the 5 first characters to check if the first word is "solid" - boost::uint8_t c; - for(; i < 5; i++){ - input.read(reinterpret_cast(&c), sizeof(c)); - line[i]=c; + return false; } - s = std::string(line,5); - if(s == solid){ - // we found the keyword "solid" which is supposed to indicate the file is Ascii - // But it might still be binary, so we have to find out if it is followed - // by an (optional) name and then the keyword "facet" - // When we find "facet" we conclude that it is really Ascii - - // first skip whitespaces after solid - do { - input.read(reinterpret_cast(&c), sizeof(c)); - line[i++]=c; - }while(isspace(c) && ( i < 80)); - if(i==80){ - is_binary_file = true; - goto done; - } - // now c is not whitespace - ni = i-1; // here starts either the name or the keyword "facet" - do { - input.read(reinterpret_cast(&c), sizeof(c)); - line[i++]=c; - }while(! isspace(c) && ( i < 80)); - s = std::string(line+ni, (i-1) - ni); -# ifdef CGAL_DEBUG_BINARY_HEADER - std::cout << "|" << s << "|" << std::endl; -# endif - if(s == facet){ - goto done; - } else if(i == 80){ - // the entire header is a name - is_binary_file = true; - goto done; - } - - // we continue to read what comes after the name - - // now c is whitespace, skip other whitespaces - do { - input.read(reinterpret_cast(&c), sizeof(c)); - line[i++]=c; - }while(isspace(c) && ( i < 80)); - if(i==80){ - is_binary_file = true; - goto done; - } - - // now c is not whitespace - ni = i-1; // here starts either "facet", or it is really binary - do { - input.read(reinterpret_cast(&c), sizeof(c)); - line[i++]=c; - }while(! isspace(c) && ( i < 80)); - s = std::string(line+ni, (i-1) - ni); -# ifdef CGAL_DEBUG_BINARY_HEADER - std::cout << "|" << s << "|" << std::endl; -# endif - if(s == facet){ - goto done; - } else { - for(; i < 80; i++){ - input.read(reinterpret_cast(&c), sizeof(c)); - } - is_binary_file = true; - goto done; - } - }else{ - // we read the other 75 characters of the header - for(; i < 80; i++){ - input.read(reinterpret_cast(&c), sizeof(c)); - } - is_binary_file = true; - } - - done: - - if(is_binary_file){ - boost::uint32_t N32; - input.read(reinterpret_cast(&N32), sizeof(N32)); - unsigned int N = N32; - - for(unsigned int i=0; i < N; i++){ - float normal[3]; - input.read(reinterpret_cast(&normal[0]), sizeof(normal[0])); - input.read(reinterpret_cast(&normal[1]), sizeof(normal[1])); - input.read(reinterpret_cast(&normal[2]), sizeof(normal[2])); - - for(int j=0; j < 3; j++){ - float x,y,z; - input.read(reinterpret_cast(&x), sizeof(x)); - input.read(reinterpret_cast(&y), sizeof(y)); - input.read(reinterpret_cast(&z), sizeof(z)); - p[0]=x; p[1]=y; p[2]=z; - std::map, int>::iterator iti= - pmap.insert(std::make_pair(p,-1)).first; - if(iti->second==-1){ - ijk[j] = index; - iti->second = index++; - points.push_back(p); - } else { - ijk[j] = iti->second; - } - } - if((ijk[0] != ijk[1]) && - (ijk[0] != ijk[2]) && - (ijk[1] != ijk[2])){ - facets.push_back(ijk); - }else{ - if(verbose){ - std::cerr << "ignore degenerate face" << std::endl; - } - } - char c; - input.read(reinterpret_cast(&c), sizeof(c)); - input.read(reinterpret_cast(&c), sizeof(c)); - } + facets.push_back(ijk); return true; - } else { + } + else if(s == vertex) + { + if(count >= 3) + { + if(verbose) + std::cerr << "Error: only triangulated surfaces are supported" << std::endl; - // It is an Ascii file but the first occurence of "facet" has already be parsed - bool first_facet = true; - std::string outer("outer"), - loop("loop"), - vertex("vertex"), - endloop("endloop"), - endsolid("endsolid"); - s = facet; - while(first_facet || (input >> s)){ - first_facet = false; - if(s == endsolid){ - //std::cerr << "found endsolid" << std::endl; - } else if(s == facet){ - //std::cerr << "found facet" << std::endl; - std::getline(input, s); // ignore the normal - input >> s; - if(s != outer){ - if (verbose) - std::cerr << "Expect 'outer' and got " << s << std::endl; - return false; - } - input >> s; - if(s != loop){ - if (verbose) - std::cerr << "Expect 'loop' and got " << s << std::endl; - return false; - } - int count = 0; - do { - input >> s; - if(s == vertex){ - // std::cerr << "found vertex" << std::endl; - if(count < 3){ - input >> p[0] >> p[1] >> p[2]; - std::map, int>::iterator iti= - pmap.insert(std::make_pair(p,-1)).first; - if(iti->second==-1){ - ijk[count] = index; - iti->second = index++; - points.push_back(p); - } else { - ijk[count] = iti->second; - } - ++count; - } else { - if (verbose) - std::cerr << "We can only read triangulated surfaces" << std::endl; - return false; - } - } - }while(s != endloop); - - facets.push_back(ijk); + return false; + } + + if(!(input >> iformat(p[0]) >> iformat(p[1]) >> iformat(p[2]))) + { + if(verbose) + std::cerr << "Error while reading point coordinates (premature end of file)" << std::endl; + + return false; + } + else + { + std::map, int>::iterator iti= + index_map.insert(std::make_pair(p, -1)).first; + + if(iti->second == -1) + { + ijk[count] = index; + iti->second = index++; + points.push_back(p); + } + else + { + ijk[count] = iti->second; } } + + ++count; + } + } + + if(verbose) + std::cerr << "Error while reading facet (premature end of file)" << std::endl; + + return false; +} + +bool parse_ASCII_STL(std::istream& input, + std::vector >& points, + std::vector >& facets, + bool verbose = false) +{ + if(verbose) + std::cout << "Parsing ASCII file..." << std::endl; + + if(!input.good()) + return true; + + // Here, we have already read the word 'solid' + + int index = 0; + std::map, int> index_map; + + std::string s; + std::string facet("facet"), + endsolid("endsolid"); + + while(input >> s) + { + if(s == facet) + { + if(!read_ASCII_facet(input, points, facets, index, index_map, verbose)) + return false; + } + else if(s == endsolid) + { return true; } } + + if(verbose) + std::cerr << "Error while parsing ASCII file" << std::endl; + + return false; +} + +bool parse_binary_STL(std::istream& input, + std::vector >& points, + std::vector >& facets, + bool verbose = false) +{ + if(verbose) + std::cout << "Parsing binary file..." << std::endl; + + // Start from the beginning again to simplify things + input.clear(); + input.seekg(0, std::ios::beg); + + if(!input.good()) + return true; + + // Discard the first 80 chars (unused header) + int pos = 0; + char c; + + if(verbose) + std::cout << "header: "; + + while(pos < 80) + { + input.read(reinterpret_cast(&c), sizeof(c)); + if(!input.good()) + break; + + if(verbose) + std::cout << c; + + ++pos; + } + + if(verbose) + std::cout << std::endl; + + if(pos != 80) + return true; // empty file + + int index = 0; + std::map, int> index_map; + + boost::uint32_t N32; + if(!(input.read(reinterpret_cast(&N32), sizeof(N32)))) + { + if(verbose) + std::cerr << "Error while reading number of facets" << std::endl; + + return false; + } + + unsigned int N = N32; + if(verbose) + std::cout << N << " facets to read" << std::endl; + + for(unsigned int i=0; i(&normal[0]), sizeof(normal[0]))) || + !(input.read(reinterpret_cast(&normal[1]), sizeof(normal[1]))) || + !(input.read(reinterpret_cast(&normal[2]), sizeof(normal[2])))) + { + if(verbose) + std::cerr << "Error while reading normal coordinates (premature end of file)" << std::endl; + + return false; + } + + cpp11::array ijk; + + for(int j=0; j<3; ++j) + { + float x,y,z; + if(!(input.read(reinterpret_cast(&x), sizeof(x))) || + !(input.read(reinterpret_cast(&y), sizeof(y))) || + !(input.read(reinterpret_cast(&z), sizeof(z)))) + { + if(verbose) + std::cerr << "Error while reading vertex coordinates (premature end of file)" << std::endl; + + return false; + } + + cpp11::array p; + p[0] = x; p[1] = y; p[2] = z; + + std::map, int>::iterator iti = + index_map.insert(std::make_pair(p, -1)).first; + + if(iti->second == -1) + { + ijk[j] = index; + iti->second = index++; + points.push_back(p); + } + else + { + ijk[j] = iti->second; + } + } + + facets.push_back(ijk); + + // Read so-called attribute byte count and ignore it + char c; + if(!(input.read(reinterpret_cast(&c), sizeof(c))) || + !(input.read(reinterpret_cast(&c), sizeof(c)))) + { + if(verbose) + std::cerr << "Error while reading attribute byte count (premature end of file)" << std::endl; + + return false; + } + } + + return true; +} + +bool read_STL(std::istream& input, + std::vector >& points, + std::vector >& facets, + bool verbose = false) +{ + int pos = 0; + + // Ignore all initial whitespace + char c; + + while(input.read(reinterpret_cast(&c), sizeof(c))) + { + if(!isspace(c)) + { + input.unget(); // move back to the first interesting char + break; + } + ++pos; + } + + if(!input.good()) // reached the end + return true; + + // 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); + + // We are within the first 80 characters, both ASCII and binary are possible + + // Read the 5 first characters to check if the first word is "solid" + std::string s, solid("solid"); + + char word[5]; + if(input.read(reinterpret_cast(&word[0]), sizeof(c)) && + input.read(reinterpret_cast(&word[1]), sizeof(c)) && + input.read(reinterpret_cast(&word[2]), sizeof(c)) && + input.read(reinterpret_cast(&word[3]), sizeof(c)) && + input.read(reinterpret_cast(&word[4]), sizeof(c))) + { + s = std::string(word, 5); + pos += 5; + } + else + return true; // empty file + + // If the first word is not 'solid', the file must be binary + if(s != solid) + { + if(parse_binary_STL(input, points, facets, verbose)) + { + return true; + } + else + { + // If we failed to read it as a binary, try as ASCII just in case... + // 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); + } + } + + // Now, we have found the keyword "solid" which is supposed to indicate that the file is ASCII + if(parse_ASCII_STL(input, points, facets, verbose)) + { + // correctly read the input as an ASCII file + return true; + } + else // Failed to read the ASCII file + { + // It might have actually have been a binary file... ? + return parse_binary_STL(input, points, facets, verbose); + } +} + } // namespace CGAL #endif // CGAL_IO_STL_READER_H From da95ade46e414ffde6a4992c1b9289f34a3c50b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 11 Jun 2018 14:03:31 +0200 Subject: [PATCH 58/84] Added a few more difficulties to the tests --- .../Polyhedron_IO/data/ascii-tetrahedron.stl | 7 ++++--- ...binary-tetrahedron-non-standard-header-2.stl | Bin 284 -> 284 bytes 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl b/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl index ef48cbaea36..ead0eb394b2 100644 --- a/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl +++ b/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl @@ -1,12 +1,14 @@ -solid cube_corner + + solid cube_corner facet normal 0.0 -1.0 0.0 outer loop - vertex 0.0 0.0 0.0 + vertex 0.0 0.0 0.0 vertex 1.0 0.0 0.0 vertex 0.0 0.0 1.0 endloop endfacet facet normal 0.0 0.0 -1.0 + outer loop vertex 0.0 0.0 0.0 vertex 0.0 1.0 0.0 @@ -28,4 +30,3 @@ solid cube_corner endloop endfacet endsolid - \ No newline at end of file diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-2.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-2.stl index 2f2b3eb59cadd3685b1025e7e80d7f4ae1c53879..626338681dc4a144f6f36e31d2be09346c83a393 100644 GIT binary patch delta 34 pcmbQkG>1vNI6o&dMIkLQIkiNgI3qPLF)uScF|T-{pykAXGXT<549Nfh delta 25 gcmbQkG>3`1I6o&dML{7iF*kLhqW(k!v55g^0BS%8sQ>@~ From f738319cdce1689b5623308a046cce63ddc81a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 11 Jun 2018 14:07:44 +0200 Subject: [PATCH 59/84] Fixed whitespace (no real changes) --- Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp b/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp index 878eeff6d25..f12ad5fd6d6 100644 --- a/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp +++ b/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp @@ -20,8 +20,8 @@ void read(const char* fname, std::size_t v, std::size_t f) true); assert(points.size() == v); - assert(faces.size() == f); - + assert(faces.size() == f); + std::cout << "OFF version of file " << fname << std::endl; std::cout.precision(17); @@ -33,8 +33,6 @@ void read(const char* fname, std::size_t v, std::size_t f) for(std::size_t i=0; i < faces.size(); i++){ std::cout << "3 " << faces[i][0] << " " << faces[i][1] << " " << faces[i][2] << std::endl; } - - } @@ -43,7 +41,6 @@ int main() read("data/cube.stl", 8, 12); read("data/triangle.stl", 3, 1); - read("data/ascii-tetrahedron.stl", 4, 4); read("data/binary-tetrahedron-nice-header.stl", 4, 4); read("data/binary-tetrahedron-non-standard-header-1.stl", 4, 4); @@ -51,5 +48,6 @@ int main() read("data/binary-tetrahedron-non-standard-header-3.stl", 4, 4); read("data/binary-tetrahedron-non-standard-header-4.stl", 4, 4); read("data/binary-tetrahedron-non-standard-header-5.stl", 4, 4); + return 0; } From 158d2924355415cd395b08e43e9c3a4c81ab1a7f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 13 Jun 2018 10:22:11 +0200 Subject: [PATCH 60/84] Add missing overload --- BGL/include/CGAL/boost/graph/io.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index 4a3e88ed66c..2ad04ff8fe8 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -309,8 +309,15 @@ bool write_inp(std::ostream& os, os << "*End Part"<< std::endl; return os.good(); } - - +// conveniance overload +template +bool write_inp(std::ostream& os, + const FaceGraph& g, + std::string name, + std::string type) +{ + return write_inp(os, g, name, type, parameters::all_default()); +} } // namespace CGAL #endif // CGAL_BOOST_GRAPH_IO_H From 13f68633975c34365f034bacedfe79a5e870e9eb Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 13 Jun 2018 10:45:00 +0200 Subject: [PATCH 61/84] Fix the indentation --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 38609ce3b01..5ca2e1cb5ee 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -150,7 +150,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) viewer->textRenderer()->setScene(scene); viewer->setScene(scene); CGAL::Three::Three::s_scene = scene; - CGAL::Three::Three::s_connectable_scene = scene; + CGAL::Three::Three::s_connectable_scene = scene; ui->actionMaxTextItemsDisplayed->setText(QString("Set Maximum Text Items Displayed : %1").arg(viewer->textRenderer()->getMax_textItems())); { QShortcut* shortcut = new QShortcut(QKeySequence(Qt::ALT+Qt::Key_Q), this); From ffd78e296e47b87c13746aeddc6c3cf5a87aca49 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 13 Jun 2018 10:45:33 +0200 Subject: [PATCH 62/84] Workaround a strange error from g++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was a warning: ``` [100%] Building CXX object demo/Polyhedron/CMakeFiles/polyhedron_demo.dir/MainWindow.cpp.o /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.cpp: In constructor ‘MainWindow::MainWindow(bool, QWidget*)’: /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.cpp:312:11: error: request for member ‘addDockWidget’ is ambiguous this->addDockWidget(Qt::BottomDockWidgetArea, dock); ^~~~~~~~~~~~~ In file included from /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.h:8:0, from /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.cpp:4: /home/lrineau/Git/cgal/Three/include/CGAL/Three/Three.h:54:8: note: candidates are: void CGAL::Three::Three::addDockWidget(QDockWidget*) void addDockWidget(QDockWidget* dock_widget); ^~~~~~~~~~~~~ In file included from /usr/include/qt5/QtWidgets/QMainWindow:1:0, from /home/lrineau/Git/cgal/GraphicsView/include/CGAL/Qt/DemosMainWindow.h:31, from /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.h:7, from /home/lrineau/Git/cgal/Polyhedron/demo/Polyhedron/MainWindow.cpp:4: /usr/include/qt5/QtWidgets/qmainwindow.h:166:10: note: void QMainWindow::addDockWidget(Qt::DockWidgetArea, QDockWidget*, Qt::Orientation) void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget, ^~~~~~~~~~~~~ /usr/include/qt5/QtWidgets/qmainwindow.h:165:10: note: void QMainWindow::addDockWidget(Qt::DockWidgetArea, QDockWidget*) void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget); ^~~~~~~~~~~~~ ``` That is strange, because the call is not ambiguous at all: all three candidates have different numbers of parameters! Anyway, the workaround is an explicit qualified call to `QMainWindow::addDockWidget`. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 3 ++- Three/include/CGAL/Three/Three.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 5ca2e1cb5ee..607d5654eb0 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef QT_SCRIPT_LIB # include @@ -309,7 +310,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) QDockWidget* dock = new QDockWidget(debug_widgets_names[i], this); dock->setObjectName(debug_widgets_names[i]); dock->setWidget(debugger->widget(debug_widgets[i])); - this->addDockWidget(Qt::BottomDockWidgetArea, dock); + this->QMainWindow::addDockWidget(Qt::BottomDockWidgetArea, dock); dock->hide(); } debugger->setAutoShowStandardWindow(false); diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index d962ac4d4b2..307034838d0 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -26,6 +26,7 @@ #include #include +#include #include #include From 0984402c3d915e2ea34ee0f721ec394bd8e2e92c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 14 Jun 2018 11:11:19 +0200 Subject: [PATCH 63/84] Fix dllimport/-export issue on Windows --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index e4145a9359d..0a6e6eb875b 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -185,6 +185,11 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) target_link_libraries(demo_framework PUBLIC Qt5::OpenGL Qt5::Widgets Qt5::Gui Qt5::Script ) + # Let's define `three_EXPORT` during the compilation of `demo_framework`, + # in addition of `demo_framework_EXPORT` (defined automatically by + # CMake). That is to deal with the visibility of symbols of + # `Three.h`/`Three.cpp`. + target_compile_definitions(demo_framework PRIVATE three_EXPORTS=1) if(CGAL_HEADER_ONLY) target_compile_definitions(demo_framework PRIVATE -DCGAL_USE_Qt5_RESOURCES) endif() From b993dcfc291a3a5dd8672c4836cdb3c8b3af3d27 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 18 Jun 2018 16:04:34 +0200 Subject: [PATCH 64/84] Test callbacks with parallel version too --- .../examples/Point_set_processing_3/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index 87697e6325a..54f9aadf9e7 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -104,7 +104,8 @@ if ( CGAL_FOUND ) average_spacing_example normals_example jet_smoothing_example - normal_estimation) + normal_estimation + callback_example) if(TBB_FOUND AND TARGET ${target}) CGAL_target_use_TBB(${target}) endif() From c0e79003fc31e2bf25386ef5ee6ddc6b8230a119 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 18 Jun 2018 16:05:18 +0200 Subject: [PATCH 65/84] Provide a more generic cpp11::sleep_for() function that handles TBB/STD/MSVC2013 specificities --- .../include/CGAL/internal/Parallel_callback.h | 4 +-- .../include/run_with_qprogressdialog.h | 2 +- STL_Extension/include/CGAL/thread.h | 36 +++++++++++-------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h index f5d783a7b25..fd9a3335794 100644 --- a/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h +++ b/Point_set_processing_3/include/CGAL/internal/Parallel_callback.h @@ -98,15 +98,13 @@ public: void operator()() { - cpp11::chrono::seconds sleeping_time(0.00001); - while (*m_advancement != m_size) { if (!m_callback (*m_advancement / double(m_size))) *m_interrupted = true; if (*m_interrupted) return; - cpp11::this_thread::sleep_for(sleeping_time); + cpp11::sleep_for (0.00001); } m_callback (1.); } diff --git a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h index ff2820d363a..f1bef8fb5fd 100644 --- a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h +++ b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h @@ -122,7 +122,7 @@ void run_with_qprogressdialog (Functor& functor, while (*signal_callback->latest_adv != 1. && *signal_callback->state) { - CGAL::cpp11::this_thread::sleep_for(CGAL::cpp11::chrono::seconds(0.1)); + CGAL::cpp11::sleep_for (0.1); QApplication::processEvents (); } diff --git a/STL_Extension/include/CGAL/thread.h b/STL_Extension/include/CGAL/thread.h index 770c74bad02..aeab901a27b 100644 --- a/STL_Extension/include/CGAL/thread.h +++ b/STL_Extension/include/CGAL/thread.h @@ -26,14 +26,17 @@ /* This file defines the following: - CGAL::cpp11::thread - - CGAL::cpp11::this_thread::sleep_for - CGAL::cpp11::atomic - - CGAL::cpp11::chrono::seconds + - CGAL::cpp11::sleep_for It uses either TBB or STD depending on what's available: as TBB can quite often override `std::thread`, it is possible that TBB will be used instead of STD even if the real CXX11 `std::thread` is available. + + As the conflicting API between TBB and STD can be quite complicated, + we offer a more generic `sleep_for()` function that takes + double-typed seconds as argument and deals with it. */ #if defined(CGAL_LINKED_WITH_TBB) @@ -72,31 +75,36 @@ namespace CGAL { namespace cpp11 { #if CGAL_USE_TBB_THREADS + using std::thread; // std::thread is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 - namespace this_thread - { - using std::this_thread::sleep_for; // std::this_thread::sleep_for is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 - } using tbb::atomic; - namespace chrono + + void sleep_for (double seconds) { - typedef tbb::tick_count::interval_t seconds; + // std::this_thread::sleep_for is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 + // It takes interval_t types as argument (!= from the std norm) + std::this_thread::sleep_for(tbb::tick_count::interval_t(seconds)); } + #elif CGAL_USE_STD_THREADS + using std::thread; - namespace this_thread - { - using std::this_thread::sleep_for; - } using std::atomic; - namespace chrono + + void sleep_for (double seconds) { - typedef std::chrono::duration > seconds; + // MSVC2013 cannot call `sleep_for()` with other types than + // std::chrono::nanoseconds (bug in the implementation of the norm). + typedef std::chrono::nanoseconds nanoseconds; + nanoseconds ns (nanoseconds::rep (1000000000.0 * seconds)); + std::this_thread::sleep_for(ns); } + #endif } // cpp11 + } //namespace CGAL #undef CGAL_USE_STD_THREADS From 41a7c25942d06e7e14e18d5d79d704dc7e94e7eb Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 19 Jun 2018 10:06:37 +0200 Subject: [PATCH 66/84] Force inclusion of if TBB does not define it --- STL_Extension/include/CGAL/thread.h | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/STL_Extension/include/CGAL/thread.h b/STL_Extension/include/CGAL/thread.h index aeab901a27b..9800f4ab678 100644 --- a/STL_Extension/include/CGAL/thread.h +++ b/STL_Extension/include/CGAL/thread.h @@ -54,20 +54,9 @@ #endif #if !CGAL_USE_TBB_THREADS -# if !defined(CGAL_CFG_NO_STD_THREAD) -# include -# include -# include -# define CGAL_USE_STD_THREADS 1 -# else -# define CGAL_USE_STD_THREADS 0 -# endif -#else -# define CGAL_USE_STD_THREADS 0 -#endif - -#if CGAL_USE_STD_THREADS || CGAL_USE_TBB_THREADS -# define CGAL_HAS_STD_THREADS // Useful define +# include +# include +# include #endif namespace CGAL { @@ -86,8 +75,8 @@ namespace cpp11 { std::this_thread::sleep_for(tbb::tick_count::interval_t(seconds)); } -#elif CGAL_USE_STD_THREADS - +#else + using std::thread; using std::atomic; @@ -99,7 +88,7 @@ namespace cpp11 { nanoseconds ns (nanoseconds::rep (1000000000.0 * seconds)); std::this_thread::sleep_for(ns); } - + #endif } // cpp11 @@ -107,7 +96,6 @@ namespace cpp11 { } //namespace CGAL -#undef CGAL_USE_STD_THREADS #undef CGAL_USE_TBB_THREADS #endif // CGAL_THREAD_H From 678333a272cdad59f54ceab83d3584eb50482cba Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Apr 2018 12:36:21 +0200 Subject: [PATCH 67/84] More precisions about Eigen_diagonalize_traits --- Solver_interface/doc/Solver_interface/Solver_interface.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Solver_interface/doc/Solver_interface/Solver_interface.txt b/Solver_interface/doc/Solver_interface/Solver_interface.txt index d9ab9162b80..f613ce32e74 100644 --- a/Solver_interface/doc/Solver_interface/Solver_interface.txt +++ b/Solver_interface/doc/Solver_interface/Solver_interface.txt @@ -34,9 +34,10 @@ for this concept: depend on another library. Although both models achieve the same computation, -`Eigen_diagonalize_traits` is faster and should thus be used if the -\ref thirdpartyEigen library is available. The eigenvalues are stored -in ascending order and eigenvectors are stored in accordance. +`Eigen_diagonalize_traits` is more precise and faster: it +should thus be used if the \ref thirdpartyEigen library is +available. The eigenvalues are stored in ascending order and +eigenvectors are stored in accordance. This is an example of an eigen decomposition of a matrix using this class: From c0da4fcef568acc8af4f40a9520ed379da348bb3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Apr 2018 12:37:04 +0200 Subject: [PATCH 68/84] Warn against using CGAL diagonalize traits --- .../include/CGAL/Diagonalize_traits.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Solver_interface/include/CGAL/Diagonalize_traits.h b/Solver_interface/include/CGAL/Diagonalize_traits.h index 5fec86d2ab6..547e7e2bcae 100644 --- a/Solver_interface/include/CGAL/Diagonalize_traits.h +++ b/Solver_interface/include/CGAL/Diagonalize_traits.h @@ -26,6 +26,14 @@ #include #include +#ifdef CGAL_TEST_SUITE +#define CGAL_WARNING_DIAGONALIZE_TRAITS +#else +#define CGAL_WARNING_DIAGONALIZE_TRAITS \ + CGAL_DEPRECATED_MSG("CGAL::Diagonalize_traits is an outdated class that can \ +lead to precision issues, using CGAL::Eigen_diagonalize_traits is strongly advised") +#endif + namespace CGAL { /// \ingroup PkgSolver @@ -34,6 +42,10 @@ namespace CGAL { /// implementation for the diagonalization of Variance-Covariance /// Matrices. /// +/// \warning This class is outdated: it can lead to precision issues +/// and should only be used if \ref thirdpartyEigen "Eigen" is not +/// available. Otherwise, `Eigen_diagonalize_traits` should be used. +/// /// \tparam FT Number type /// \tparam dim Dimension of the matrices and vectors /// @@ -49,6 +61,7 @@ public: /// Fill `eigenvalues` with the eigenvalues of the covariance matrix represented by `cov`. /// Eigenvalues are sorted by increasing order. /// \return `true` if the operation was successful and `false` otherwise. + CGAL_WARNING_DIAGONALIZE_TRAITS static bool diagonalize_selfadjoint_covariance_matrix(const Covariance_matrix& cov, Vector& eigenvalues) { @@ -59,6 +72,7 @@ public: /// Extract the eigenvector associated to the largest eigenvalue /// of the covariance matrix represented by `cov`. /// \return `true` if the operation was successful and `false` otherwise. + CGAL_WARNING_DIAGONALIZE_TRAITS static bool extract_largest_eigenvector_of_covariance_matrix(const Covariance_matrix& cov, Vector& normal) { @@ -77,6 +91,7 @@ public: /// the eigenvectors of the covariance matrix represented by `cov`. /// Eigenvalues are sorted by increasing order. /// \return `true` if the operation was successful and `false` otherwise. + CGAL_WARNING_DIAGONALIZE_TRAITS static bool diagonalize_selfadjoint_covariance_matrix(const Covariance_matrix& mat, Vector& eigen_values, Matrix& eigen_vectors) From 4599787d671c69f438faad94294e48508a5edc1e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Apr 2018 14:58:01 +0200 Subject: [PATCH 69/84] Improve deprecated message --- Solver_interface/include/CGAL/Diagonalize_traits.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Solver_interface/include/CGAL/Diagonalize_traits.h b/Solver_interface/include/CGAL/Diagonalize_traits.h index 547e7e2bcae..f1c29fa74db 100644 --- a/Solver_interface/include/CGAL/Diagonalize_traits.h +++ b/Solver_interface/include/CGAL/Diagonalize_traits.h @@ -26,13 +26,9 @@ #include #include -#ifdef CGAL_TEST_SUITE -#define CGAL_WARNING_DIAGONALIZE_TRAITS -#else #define CGAL_WARNING_DIAGONALIZE_TRAITS \ - CGAL_DEPRECATED_MSG("CGAL::Diagonalize_traits is an outdated class that can \ -lead to precision issues, using CGAL::Eigen_diagonalize_traits is strongly advised") -#endif + CGAL_DEPRECATED_MSG("CGAL::Diagonalize_traits is a deprecated class that can \ +lead to precision issues, please use CGAL::Eigen_diagonalize_traits") namespace CGAL { From 41d554fe585c8442f6a765c24d5d6a9060b9d2e9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Apr 2018 15:33:36 +0200 Subject: [PATCH 70/84] Deprecating Diagonalize_traits: document dependency to Eigen --- .../CGAL/Approximate_min_ellipsoid_d.h | 2 ++ .../CGAL/Classification/Local_eigen_analysis.h | 7 +++---- .../Classification/Point_set_feature_generator.h | 6 ++---- .../CGAL/Classification/Point_set_neighborhood.h | 1 - .../Jet_fitting_3/CGAL/Monge_via_jet_fitting.h | 1 + Mesh_3/doc/Mesh_3/CGAL/lloyd_optimize_mesh_3.h | 1 + .../Point_set_processing_3/NamedParameters.txt | 2 +- .../CGAL/linear_least_squares_fitting_2.h | 2 +- .../CGAL/linear_least_squares_fitting_3.h | 7 +++---- .../Weighted_PCA_smoother.h | 9 ++++----- .../Solver_interface/Concepts/DiagonalizeTraits.h | 2 -- .../doc/Solver_interface/Solver_interface.txt | 15 ++------------- .../include/CGAL/Default_diagonalize_traits.h | 4 ++++ .../include/CGAL/Diagonalize_traits.h | 4 ++++ 14 files changed, 28 insertions(+), 35 deletions(-) diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h index c162a00c5aa..8fbe5d25734 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h @@ -137,6 +137,8 @@ for display in Maplesoft's Maple. \cgalExample{Approximate_min_ellipsoid_d/ellipsoid_for_maple.cpp} +\note This class requires the \ref thirdpartyEigen library. + */ template< typename Traits > class Approximate_min_ellipsoid_d { diff --git a/Classification/include/CGAL/Classification/Local_eigen_analysis.h b/Classification/include/CGAL/Classification/Local_eigen_analysis.h index 7fcdb9d2ba1..f8ca6bf1903 100644 --- a/Classification/include/CGAL/Classification/Local_eigen_analysis.h +++ b/Classification/include/CGAL/Classification/Local_eigen_analysis.h @@ -184,10 +184,9 @@ public: algorithm. Possible values are `Parallel_tag` (default value is %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for - matrix diagonalization. It can be omitted: if Eigen 3 (or greater) - is available and `CGAL_EIGEN3_ENABLED` is defined then an overload - using `Eigen_diagonalize_traits` is provided. Otherwise, the - internal implementation `Diagonalize_traits` is used. + matrix diagonalization. It can be omitted if Eigen 3 (or greater) + is available and `CGAL_EIGEN3_ENABLED` is defined. In that case, + an overload using `Eigen_diagonalize_traits` is provided. \param input point range. \param point_map property map to access the input points. diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index b74ef1d16f6..8108c671422 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -87,10 +87,8 @@ namespace Classification { is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for matrix diagonalization. It can be omitted: if Eigen 3 (or greater) - is available and `CGAL_EIGEN3_ENABLED` is defined then an overload - using `Eigen_diagonalize_traits` is provided. Otherwise, the - internal implementation `Diagonalize_traits` is used. - + is available and `CGAL_EIGEN3_ENABLED` is defined: in that case, an + overload using `Eigen_diagonalize_traits` is provided. */ template #include #include -#include #include #include #include diff --git a/Jet_fitting_3/doc/Jet_fitting_3/CGAL/Monge_via_jet_fitting.h b/Jet_fitting_3/doc/Jet_fitting_3/CGAL/Monge_via_jet_fitting.h index f9df0ee5b65..7f31a429a16 100644 --- a/Jet_fitting_3/doc/Jet_fitting_3/CGAL/Monge_via_jet_fitting.h +++ b/Jet_fitting_3/doc/Jet_fitting_3/CGAL/Monge_via_jet_fitting.h @@ -29,6 +29,7 @@ algebra algorithm required by the fitting method. The scalar type, `SvdTraits:: \sa `Eigen_svd` \sa `Monge_form` +\note This class requires the \ref thirdpartyEigen library. */ template< typename DataKernel, typename LocalKernel, typename SvdTraits > class Monge_via_jet_fitting { diff --git a/Mesh_3/doc/Mesh_3/CGAL/lloyd_optimize_mesh_3.h b/Mesh_3/doc/Mesh_3/CGAL/lloyd_optimize_mesh_3.h index 498e582d500..c6d3e76f4ea 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/lloyd_optimize_mesh_3.h +++ b/Mesh_3/doc/Mesh_3/CGAL/lloyd_optimize_mesh_3.h @@ -100,6 +100,7 @@ lloyd_optimize_mesh_3(c3t3, \sa `CGAL::perturb_mesh_3()` \sa `CGAL::odt_optimize_mesh_3()` +\note This function requires the \ref thirdpartyEigen library. */ template diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index ee2acdba8f2..ee5322600c1 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -49,7 +49,7 @@ No default value. \cgalNPBegin{diagonalize_traits} \anchor PSP_diagonalize_traits is the solver used for diagonalizing covariance matrices.\n \b Type: a class model of `DiagonalizeTraits`.\n -\b Default: if \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined, then `CGAL::Eigen_diagonalize_traits` is used. Otherwise, the fallback `CGAL::Diagonalize_traits` is used (note that it is significantly slower, so using Eigen is strongly advised).\n +\b Default: `CGAL::Eigen_diagonalize_traits` if \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined.\n \cgalNPEnd \cgalNPBegin{svd_traits} \anchor PSP_svd_traits diff --git a/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_2.h b/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_2.h index 1668552b251..16c458413a7 100644 --- a/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_2.h +++ b/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_2.h @@ -13,7 +13,7 @@ The tag `tag` identifies the dimension to be considered from the objects. For po The class `K` is the kernel in which the value type of the `InputIterator` is defined. It can be omitted and deduced automatically from the value type. -The class `DiagonalizeTraits_` is a model of `DiagonalizeTraits`. It can be omitted: if Eigen 3 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined then an overload using `Eigen_diagonalize_traits` is provided. Otherwise, the internal implementation `Diagonalize_traits` is used. +The class `DiagonalizeTraits_` is a model of `DiagonalizeTraits`. It can be omitted if Eigen 3 (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined: in that case, an overload using `Eigen_diagonalize_traits` is provided. \cgalHeading{Requirements} diff --git a/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_3.h b/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_3.h index 9a6812e1e27..4a01d3bc784 100644 --- a/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_3.h +++ b/Principal_component_analysis/doc/Principal_component_analysis/CGAL/linear_least_squares_fitting_3.h @@ -65,10 +65,9 @@ value type of `InputIterator` is defined. It can be omitted and deduced automatically from the value type. The class `DiagonalizeTraits_` is a model of `DiagonalizeTraits`. It -can be omitted: if Eigen 3 (or greater) is available and -`CGAL_EIGEN3_ENABLED` is defined then an overload using -`Eigen_diagonalize_traits` is provided. Otherwise, the internal -implementation `Diagonalize_traits` is used. +can be omitted if Eigen 3 (or greater) is available and +`CGAL_EIGEN3_ENABLED` is defined: in that case, an overload using +`Eigen_diagonalize_traits` is provided. \note This function is significantly faster when using `Eigen_diagonalize_traits` and it is strongly advised to use this diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h index 6f991ed6d74..f2f1fb39555 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h @@ -61,11 +61,10 @@ namespace Scale_space_reconstruction_3 * \tparam DiagonalizeTraits model of `DiagonalizeTraits` that * determines how to diagonalize a weighted covariance matrix to - * approximate a weighted point set. It can be omitted: if Eigen 3 - * (or greater) is available and `CGAL_EIGEN3_ENABLED` is defined - * then an overload using `Eigen_diagonalize_traits` is - * provided. Otherwise, the internal implementation - * `Diagonalize_traits` is used. + * approximate a weighted point set. It can be omitted if Eigen 3 (or + * greater) is available and `CGAL_EIGEN3_ENABLED` is defined: in + * that case, an overload using `Eigen_diagonalize_traits` is + * provided. * \tparam ConcurrencyTag indicates whether to use concurrent * processing. It can be omitted: if TBB (or greater) is available * and `CGAL_LINKED_WITH_TBB` is defined then `Parallel_tag` is diff --git a/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h b/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h index 345bd48dd39..1badaed4564 100644 --- a/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h +++ b/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h @@ -17,8 +17,6 @@ follows: \tparam FT Number type \tparam dim Dimension of the matrices and vectors -\cgalHasModel `CGAL::Default_diagonalize_traits` -\cgalHasModel `CGAL::Diagonalize_traits` \cgalHasModel `CGAL::Eigen_diagonalize_traits` */ diff --git a/Solver_interface/doc/Solver_interface/Solver_interface.txt b/Solver_interface/doc/Solver_interface/Solver_interface.txt index f613ce32e74..8025bd5cafd 100644 --- a/Solver_interface/doc/Solver_interface/Solver_interface.txt +++ b/Solver_interface/doc/Solver_interface/Solver_interface.txt @@ -26,23 +26,12 @@ Library (MKL). The concept `DiagonalizeTraits` defines an interface for the diagonalization and computation of eigenvectors and eigenvalues of a symmetric matrix. `T` is the number type and `dim` is the dimension of -the matrices and vector (set to 3 by default). We provide two models -for this concept: - -- `Eigen_diagonalize_traits` uses the \ref thirdpartyEigen library. -- `Diagonalize_traits` is an internal implementation that does not -depend on another library. - -Although both models achieve the same computation, -`Eigen_diagonalize_traits` is more precise and faster: it -should thus be used if the \ref thirdpartyEigen library is -available. The eigenvalues are stored in ascending order and -eigenvectors are stored in accordance. +the matrices and vector (set to 3 by default). We provide the model +`Eigen_diagonalize_traits` that uses the \ref thirdpartyEigen library. This is an example of an eigen decomposition of a matrix using this class: - \cgalExample{Solver_interface/diagonalize_matrix.cpp} diff --git a/Solver_interface/include/CGAL/Default_diagonalize_traits.h b/Solver_interface/include/CGAL/Default_diagonalize_traits.h index 6dc31b4aa35..7dd97adf522 100644 --- a/Solver_interface/include/CGAL/Default_diagonalize_traits.h +++ b/Solver_interface/include/CGAL/Default_diagonalize_traits.h @@ -26,6 +26,8 @@ #include #endif +/// \cond SKIP_IN_MANUAL + namespace CGAL { /// \ingroup PkgSolver @@ -84,4 +86,6 @@ public: } // namespace CGAL +/// \endcond + #endif // CGAL_DEFAULT_DIAGONALIZE_TRAITS_H diff --git a/Solver_interface/include/CGAL/Diagonalize_traits.h b/Solver_interface/include/CGAL/Diagonalize_traits.h index f1c29fa74db..57c086ef6b2 100644 --- a/Solver_interface/include/CGAL/Diagonalize_traits.h +++ b/Solver_interface/include/CGAL/Diagonalize_traits.h @@ -30,6 +30,8 @@ CGAL_DEPRECATED_MSG("CGAL::Diagonalize_traits is a deprecated class that can \ lead to precision issues, please use CGAL::Eigen_diagonalize_traits") +/// \cond SKIP_IN_MANUAL + namespace CGAL { /// \ingroup PkgSolver @@ -299,4 +301,6 @@ public: } // namespace CGAL +/// \endcond + #endif // CGAL_DIAGONALIZE_TRAITS_H From 7048b5cb17ee7cd563e0ef95026de5282b3911b5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Apr 2018 16:10:24 +0200 Subject: [PATCH 71/84] Update diagonalize traits inclusions + deprecation warnings --- .../Plugins/Point_set/Surface_reconstruction_plugin.cpp | 1 - .../test_linear_least_squares_fitting_circles_2.cpp | 2 ++ .../test_linear_least_squares_fitting_cuboids_3.cpp | 2 ++ .../test_linear_least_squares_fitting_points_2.cpp | 2 ++ .../test_linear_least_squares_fitting_points_3.cpp | 2 ++ .../test_linear_least_squares_fitting_rectangles_2.cpp | 2 ++ .../test_linear_least_squares_fitting_segments_2.cpp | 2 ++ .../test_linear_least_squares_fitting_segments_3.cpp | 2 ++ .../test_linear_least_squares_fitting_spheres_3.cpp | 2 ++ .../test_linear_least_squares_fitting_tetrahedra_3.cpp | 2 ++ .../test_linear_least_squares_fitting_triangles_2.cpp | 2 ++ .../test_linear_least_squares_fitting_triangles_3.cpp | 2 ++ .../doc/Solver_interface/PackageDescription.txt | 2 -- .../examples/Solver_interface/diagonalize_matrix.cpp | 9 --------- 14 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.cpp index 63003bb8cdb..6b0d61b56ec 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp index b2f2c69575f..baa560c2f3f 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // Example program for the linear_least_square_fitting function on a set of circles in 2D #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp index caad6d8dbc9..eb3c32e8a9f 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // Example program for the linear_least_square_fitting function on set of cuboids in 3D #include #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp index b8aa1207cc3..d5a243c9e62 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. #include #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp index bd94792cf91..55dbb420c6b 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp index 5b7d67f01ce..c735e6b658c 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp index 9a4d6fe8a90..292018f05eb 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp index 260eae89b21..f3e58e21d7e 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp index 044de1a2c91..9037ba236a9 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp @@ -1,5 +1,7 @@ // Example program for the linear_least_square_fitting function +#define CGAL_NO_DEPRECATION_WARNINGS + #include #include #ifdef CGAL_EIGEN3_ENABLED diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp index 560be170c05..a2150baf22d 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // Example program for the linear_least_square_fitting function // on a set of tetrahedra in 3D diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp index 37d3b15a89a..e45305b1a99 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // test for the linear_least_square_fitting() functions. #include #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp index a075a75699f..d210dce1f08 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp @@ -1,3 +1,5 @@ +#define CGAL_NO_DEPRECATION_WARNINGS + // Example program for the linear_least_square_fitting function on set of triangles in 3D #include #include diff --git a/Solver_interface/doc/Solver_interface/PackageDescription.txt b/Solver_interface/doc/Solver_interface/PackageDescription.txt index 663a5c99f33..c8cb3e86a2d 100644 --- a/Solver_interface/doc/Solver_interface/PackageDescription.txt +++ b/Solver_interface/doc/Solver_interface/PackageDescription.txt @@ -31,10 +31,8 @@ ## Classes ## -- `CGAL::Diagonalize_traits` - `CGAL::Eigen_solver_traits` - `CGAL::Eigen_diagonalize_traits` -- `CGAL::Default_diagonalize_traits` - `CGAL::Eigen_vector` - `CGAL::Eigen_matrix` - `CGAL::Eigen_sparse_matrix` diff --git a/Solver_interface/examples/Solver_interface/diagonalize_matrix.cpp b/Solver_interface/examples/Solver_interface/diagonalize_matrix.cpp index 21d6a4925f4..1fbada87dc0 100644 --- a/Solver_interface/examples/Solver_interface/diagonalize_matrix.cpp +++ b/Solver_interface/examples/Solver_interface/diagonalize_matrix.cpp @@ -1,22 +1,13 @@ #include -#ifdef CGAL_EIGEN3_ENABLED #include -#else -#include -#endif typedef double FT; typedef CGAL::cpp11::array Eigen_matrix; typedef CGAL::cpp11::array Eigen_vector; typedef CGAL::cpp11::array Eigen_three_vectors; -// If Eigen is enabled, use it, otherwise fallback to the internal model -#ifdef CGAL_EIGEN3_ENABLED typedef CGAL::Eigen_diagonalize_traits Diagonalize_traits; -#else -typedef CGAL::Diagonalize_traits Diagonalize_traits; -#endif int main(void) { From 95e6d089fa9758a798bd3bc3f5ea0dde5deed4e4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Apr 2018 14:16:35 +0200 Subject: [PATCH 72/84] Include Eigen in CMakeLists.txt where needed --- .../Approximate_min_ellipsoid_d/CMakeLists.txt | 10 +++++++++- .../test/Bounding_volumes/CMakeLists.txt | 10 +++++++++- .../examples/Classification/CMakeLists.txt | 10 ++++++++++ Generator/examples/Generator/CMakeLists.txt | 12 +++++++++++- Generator/test/Generator/CMakeLists.txt | 10 +++++++++- Mesh_3/examples/Mesh_3/CMakeLists.txt | 9 +++++++++ Mesh_3/test/Mesh_3/CMakeLists.txt | 9 +++++++++ .../Point_set_shape_detection_3/CMakeLists.txt | 12 +++++++++--- 8 files changed, 75 insertions(+), 7 deletions(-) diff --git a/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt b/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt index 90f3a7f6622..00764d546fc 100644 --- a/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt +++ b/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt @@ -12,10 +12,18 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") + # Use Eigen + find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + endif() + # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) + if(NOT (${cppfile} STREQUAL "ellipsoid.cpp") OR EIGEN3_FOUND) + create_single_source_cgal_program( "${cppfile}" ) + endif() endforeach() else() diff --git a/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt b/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt index da560c664e8..30daac07fc0 100644 --- a/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt +++ b/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt @@ -16,10 +16,18 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") + # Use Eigen + find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + endif() + # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) + if(NOT (${cppfile} STREQUAL "Approximate_min_ellipsoid_d.cpp") OR EIGEN3_FOUND) + create_single_source_cgal_program( "${cppfile}" ) + endif() endforeach() else() diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index b991947625a..d6f2df8c92a 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -39,6 +39,16 @@ find_package(TBB QUIET) find_package(OpenCV QUIET) +# Use Eigen +find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) +if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() +else() + include( ${EIGEN3_USE_FILE} ) +endif() + + # include for local directory include_directories( BEFORE include ) diff --git a/Generator/examples/Generator/CMakeLists.txt b/Generator/examples/Generator/CMakeLists.txt index ab607583d10..a2a9ce98fbb 100644 --- a/Generator/examples/Generator/CMakeLists.txt +++ b/Generator/examples/Generator/CMakeLists.txt @@ -16,10 +16,20 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") + # Use Eigen + find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + endif() + # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) + if(NOT (${cppfile} STREQUAL "random_points_in_tetrahedral_mesh_3.cpp") + OR NOT (${cppfile} STREQUAL "random_points_on_tetrahedral_mesh_3.cpp") + OR EIGEN3_FOUND) + create_single_source_cgal_program( "${cppfile}" ) + endif() endforeach() else() diff --git a/Generator/test/Generator/CMakeLists.txt b/Generator/test/Generator/CMakeLists.txt index ada6b13c2da..8e8c59d2504 100644 --- a/Generator/test/Generator/CMakeLists.txt +++ b/Generator/test/Generator/CMakeLists.txt @@ -16,10 +16,18 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") + # Use Eigen + find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + endif() + # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) + if(NOT (${cppfile} STREQUAL "generic_random_test.cpp") OR EIGEN3_FOUND) + create_single_source_cgal_program( "${cppfile}" ) + endif() endforeach() else() diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index 480956dbaf0..40232023833 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -39,6 +39,15 @@ if ( CGAL_FOUND ) endif( LINK_WITH_TBB ) endif() + # Use Eigen + find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) + if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() + else() + include( ${EIGEN3_USE_FILE} ) + endif() + set(VTK_LIBS "") find_package(VTK QUIET COMPONENTS vtkImagingGeneral vtkIOImage NO_MODULE) if(VTK_FOUND) diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index 3a3302cc942..87503909cf4 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -19,6 +19,15 @@ if ( CGAL_FOUND ) include_directories (BEFORE ../../include) include_directories (BEFORE ../../../AABB_tree/include) + # Use Eigen + find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) + if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() + else() + include( ${EIGEN3_USE_FILE} ) + endif() + create_single_source_cgal_program( "test_backward_compatibility.cpp" ) create_single_source_cgal_program( "test_boost_has_xxx.cpp" ) create_single_source_cgal_program( "test_c3t3.cpp" ) diff --git a/Point_set_shape_detection_3/examples/Point_set_shape_detection_3/CMakeLists.txt b/Point_set_shape_detection_3/examples/Point_set_shape_detection_3/CMakeLists.txt index 032db9a7f9a..380426c2f72 100644 --- a/Point_set_shape_detection_3/examples/Point_set_shape_detection_3/CMakeLists.txt +++ b/Point_set_shape_detection_3/examples/Point_set_shape_detection_3/CMakeLists.txt @@ -23,12 +23,18 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") - create_single_source_cgal_program( "shape_detection_basic.cpp" ) - create_single_source_cgal_program( "shape_detection_with_callback.cpp" ) + # Use Eigen + find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + create_single_source_cgal_program( "shape_detection_basic.cpp" ) + create_single_source_cgal_program( "shape_detection_with_callback.cpp" ) + create_single_source_cgal_program( "plane_regularization.cpp" ) + endif() + create_single_source_cgal_program( "efficient_RANSAC_custom_shape.cpp" ) create_single_source_cgal_program( "efficient_RANSAC_parameters.cpp" ) create_single_source_cgal_program( "efficient_RANSAC_point_access.cpp" ) - create_single_source_cgal_program( "plane_regularization.cpp" ) else() From 429e4657612a989aca571c2252f8c254bd0436ea Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 29 May 2018 10:37:50 +0200 Subject: [PATCH 73/84] Update CHANGES.md --- Installation/CHANGES.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index adc36f63d8f..acb4d786f36 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -81,6 +81,19 @@ Release date: September 2018 ``, that were deprecated since CGAL 4.5, are now removed. +- **Breaking change**: `CGAL::lloyd_optimize_mesh_3` now depends on + the _Eigen_ library. + +### Estimation of Local Differential Properties of Point-Sampled Surfaces Reference + +- **Breaking change**: `CGAL::Monge_via_jet_fitting` now depends on + the _Eigen_ library. + +### Bounding Volumes + +- **Breaking change**: `CGAL::Approximate_min_ellipsoid_d` now + depends on the _Eigen_ library. + ### CGAL and the Boost Graph Library (BGL) - Add helper function `CGAL::is_valid_polygon_mesh` that checks the @@ -89,6 +102,13 @@ Release date: September 2018 - Improve the function `CGAL::Euler::collapse_edge` so that the target vertex of the collapsed edge is always kept after the collapse. +### CGAL and Solvers + +- **Breaking change**: `CGAL::Diagonalize_traits` is now deprecated + and shouldn't be used, `CGAL::Eigen_diagonalize_traits` (along + with the _Eigen_ library) should be used instead. + + Release 4.12 ------------ From 80142e0569aae2780ef79ff7853098c9171baeee Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 29 May 2018 12:46:04 +0200 Subject: [PATCH 74/84] Fix test of deprecated code --- .../test_linear_least_squares_fitting_circles_2.cpp | 2 +- .../test_linear_least_squares_fitting_cuboids_3.cpp | 2 +- .../test_linear_least_squares_fitting_points_2.cpp | 2 +- .../test_linear_least_squares_fitting_points_3.cpp | 2 +- .../test_linear_least_squares_fitting_rectangles_2.cpp | 2 +- .../test_linear_least_squares_fitting_segments_2.cpp | 2 +- .../test_linear_least_squares_fitting_segments_3.cpp | 2 +- .../test_linear_least_squares_fitting_spheres_3.cpp | 2 +- .../test_linear_least_squares_fitting_tetrahedra_3.cpp | 2 +- .../test_linear_least_squares_fitting_triangles_2.cpp | 2 +- .../test_linear_least_squares_fitting_triangles_3.cpp | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp index baa560c2f3f..4f5bac3277d 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_circles_2.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // Example program for the linear_least_square_fitting function on a set of circles in 2D diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp index eb3c32e8a9f..da09885b0f0 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_cuboids_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // Example program for the linear_least_square_fitting function on set of cuboids in 3D #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp index d5a243c9e62..bd063d67ed5 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_2.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp index 55dbb420c6b..6308207c8b9 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_points_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp index c735e6b658c..22fbdc53fa0 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_rectangles_2.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp index 292018f05eb..bee7a607098 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_2.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp index f3e58e21d7e..6f148de7cd2 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_segments_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp index 9037ba236a9..4a8a8b4251d 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_spheres_3.cpp @@ -1,6 +1,6 @@ // Example program for the linear_least_square_fitting function -#define CGAL_NO_DEPRECATION_WARNINGS +#include #include #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp index a2150baf22d..cc56701293a 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_tetrahedra_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // Example program for the linear_least_square_fitting function // on a set of tetrahedra in 3D diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp index e45305b1a99..83941382425 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_2.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // test for the linear_least_square_fitting() functions. #include diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp index d210dce1f08..20fba3fb597 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp +++ b/Principal_component_analysis/test/Principal_component_analysis/test_linear_least_squares_fitting_triangles_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_NO_DEPRECATION_WARNINGS +#include // Example program for the linear_least_square_fitting function on set of triangles in 3D #include From 06c0835a3bca07284f89660f64416113e05bc328 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 19 Jun 2018 10:54:34 +0200 Subject: [PATCH 75/84] Add Eigen dependency in CMakeLists of demos that need it --- CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt | 8 ++++++++ GraphicsView/demo/Polygon/CMakeLists.txt | 8 ++++++++ .../demo/Principal_component_analysis/CMakeLists.txt | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt b/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt index cad2c3889dc..83f66e52253 100644 --- a/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt +++ b/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt @@ -25,6 +25,14 @@ find_package(CGAL QUIET COMPONENTS Core) if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) + find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + else() + message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") + return() + endif() + find_package(IPE 6) if ( IPE_FOUND ) diff --git a/GraphicsView/demo/Polygon/CMakeLists.txt b/GraphicsView/demo/Polygon/CMakeLists.txt index ed26300f92c..f84197f4cc1 100644 --- a/GraphicsView/demo/Polygon/CMakeLists.txt +++ b/GraphicsView/demo/Polygon/CMakeLists.txt @@ -13,6 +13,14 @@ find_package(CGAL COMPONENTS Qt5 Core) include(${CGAL_USE_FILE}) +find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) +if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) +else() + message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") + return() +endif() + find_package(Qt5 QUIET COMPONENTS Xml Script OpenGL Svg) include_directories (BEFORE ../../include) diff --git a/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt b/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt index c7f68b6629c..478cc49ca88 100644 --- a/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt +++ b/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt @@ -20,6 +20,14 @@ include_directories( ./ ) find_package(CGAL COMPONENTS Qt5) include( ${CGAL_USE_FILE} ) +find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) +if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) +else() + message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") + return() +endif() + # Find Qt5 itself find_package(Qt5 QUIET COMPONENTS Xml Script OpenGL) From ae193e5af35f3603900ffd45a0cab471c46149bc Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 19 Jun 2018 10:57:43 +0200 Subject: [PATCH 76/84] Document Eigen dependency in PackageDescription.txt of packages --- Bounding_volumes/doc/Bounding_volumes/PackageDescription.txt | 1 + Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt | 2 +- Mesh_3/doc/Mesh_3/PackageDescription.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Bounding_volumes/doc/Bounding_volumes/PackageDescription.txt b/Bounding_volumes/doc/Bounding_volumes/PackageDescription.txt index 37299cae1fe..30b90996b35 100644 --- a/Bounding_volumes/doc/Bounding_volumes/PackageDescription.txt +++ b/Bounding_volumes/doc/Bounding_volumes/PackageDescription.txt @@ -13,6 +13,7 @@ \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{1.1} +\cgalPkgDependsOn{\ref thirdpartyEigen} \cgalPkgBib{cgal:fghhs-bv} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{2D Bounding Volumes,bounding_volumes_2.zip} diff --git a/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt b/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt index a21429417ed..ff80e0f65c4 100644 --- a/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt +++ b/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt @@ -13,7 +13,7 @@ \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{3.3} -\cgalPkgDependsOn{\ref PkgSolverSummary} +\cgalPkgDependsOn{\ref PkgSolverSummary and \ref thirdpartyEigen} \cgalPkgBib{cgal:pc-eldp} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index a823b21cffc..c75c8a7acd9 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -42,7 +42,7 @@ \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{3.5} -\cgalPkgDependsOn{\ref PkgTriangulation3Summary} +\cgalPkgDependsOn{\ref PkgTriangulation3Summary and \ref thirdpartyEigen} \cgalPkgBib{cgal:rty-m3} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} From 96dcfc070dbf2f8c33c5f86c557f144eed791559 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 20 Jun 2018 08:34:18 +0200 Subject: [PATCH 77/84] Fix multiple definitions by making sleep_for() inline --- STL_Extension/include/CGAL/thread.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STL_Extension/include/CGAL/thread.h b/STL_Extension/include/CGAL/thread.h index 9800f4ab678..a777d7e7286 100644 --- a/STL_Extension/include/CGAL/thread.h +++ b/STL_Extension/include/CGAL/thread.h @@ -68,7 +68,7 @@ namespace cpp11 { using std::thread; // std::thread is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 using tbb::atomic; - void sleep_for (double seconds) + inline void sleep_for (double seconds) { // std::this_thread::sleep_for is declared by TBB if TBB_IMPLEMENT_CPP0X == 1 // It takes interval_t types as argument (!= from the std norm) @@ -80,7 +80,7 @@ namespace cpp11 { using std::thread; using std::atomic; - void sleep_for (double seconds) + inline void sleep_for (double seconds) { // MSVC2013 cannot call `sleep_for()` with other types than // std::chrono::nanoseconds (bug in the implementation of the norm). From 1cba5df6b61ed270769f5f0b96f613248d637a73 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 20 Jun 2018 08:38:04 +0200 Subject: [PATCH 78/84] Fix looping overload --- Polyhedron_IO/include/CGAL/IO/print_OFF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron_IO/include/CGAL/IO/print_OFF.h b/Polyhedron_IO/include/CGAL/IO/print_OFF.h index 493117a60eb..0126c5e9b12 100644 --- a/Polyhedron_IO/include/CGAL/IO/print_OFF.h +++ b/Polyhedron_IO/include/CGAL/IO/print_OFF.h @@ -49,7 +49,7 @@ void print_polyhedron_with_header_OFF( std::ostream& out, const Polyhedron& P, const File_header_OFF& header) { - print_polyhedron_with_header_OFF(out, P, header); + print_polyhedron_with_header_OFF(out, P, header, get(CGAL::vertex_point, P)); } template From f7807b3d5c76054f91a19f58418c27aa8e679f32 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 20 Jun 2018 08:25:25 +0200 Subject: [PATCH 79/84] fix warning --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 303ea538c32..3457081de5e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -173,7 +173,7 @@ collect_duplicated_stitchable_boundary_edges typedef CGAL::dynamic_face_property_t Face_property_tag; typedef typename boost::property_map::type Face_cc_map; Face_cc_map cc; - std::size_t num_component; + std::size_t num_component = 0; std::vector > border_edges_per_cc; bool per_cc = boost::choose_param(get_param(np, internal_np::apply_per_connected_component), false); From a043df3619d36448c487232d085dbec86e513a78 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 20 Jun 2018 11:02:57 +0200 Subject: [PATCH 80/84] Fix scene_callback_signaler_EXPORTS variable --- Polyhedron/demo/Polyhedron/Callback_signaler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Callback_signaler.h b/Polyhedron/demo/Polyhedron/Callback_signaler.h index 4ebcb170107..0691d257641 100644 --- a/Polyhedron/demo/Polyhedron/Callback_signaler.h +++ b/Polyhedron/demo/Polyhedron/Callback_signaler.h @@ -4,7 +4,7 @@ #include #include -#ifdef scene_color_ramp_EXPORTS +#ifdef scene_callback_signaler_EXPORTS # define SCENE_CALLBACK_SIGNALER_EXPORT Q_DECL_EXPORT #else # define SCENE_CALLBACK_SIGNALER_EXPORT Q_DECL_IMPORT From 784ea33b2da0d875579f34f3a58eda9ab7d5b3e2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 21 Jun 2018 10:46:18 +0000 Subject: [PATCH 81/84] Do not modify the CHANGES in the section CGAL 4.12 --- Installation/CHANGES.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 4cd9614a34d..8ec94a744a4 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -116,7 +116,8 @@ Release date: April 2018 to `Release` manually, to avoid using CGAL libraries without any compile-time optimization. -### Header-only mode +### Header-only Mode + - Since CGAL-4.9, it has been possible to use CGAL by configuring it using CMake, but without compiling the CGAL libraries. With CGAL-4.12, it is now possible to use CGAL header-only, without even configuring @@ -243,8 +244,6 @@ Release date: April 2018 - `CGAL::Polygon_mesh_processing::detect_vertex_incident_patches()` - `CGAL::Polygon_mesh_processing::sharp_edges_segmentation()` - - ### Point Set Shape Detection - **Breaking change**: From 70859adb20e2bfac2f8e229c424168210ed11bba Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 20 Jun 2018 11:13:59 +0200 Subject: [PATCH 82/84] Fix callback and avoid making too many syscalls --- .../examples/Point_set_processing_3/callback_example.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp index d393f20f090..3117627e022 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp @@ -44,7 +44,7 @@ struct Progress_to_std_cerr_callback // Avoid calling time() at every single iteration, which could // impact performances very badly ++ nb; - if (advancement != 1 && nb % 1000 != 0) + if (advancement != 1 && nb % 10000 != 0) return true; double t = timer.time(); @@ -55,6 +55,7 @@ struct Progress_to_std_cerr_callback if (advancement == 1) std::cerr << std::endl; + t_latest = t; } return true; From 24ac59a01cdc073fe4bfcf70c366740ea7a60c28 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Jun 2018 16:03:57 +0200 Subject: [PATCH 83/84] Avoid using std::unordered_set for MSVC2013 as performances can be very bad See: https://medium.com/plaxis/embarrassingly-poor-performance-of-regular-point-sets-with-std-unordered-set-418cb413974b --- Installation/include/CGAL/config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index c7fcad9736f..dbfe6fcccb0 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -184,7 +184,8 @@ #if defined(BOOST_NO_0X_HDR_UNORDERED_SET) || \ defined(BOOST_NO_0X_HDR_UNORDERED_MAP) || \ defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) || \ - defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) + defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) || \ + (defined(_MSC_VER) && (_MSC_VER == 1800)) // std::unordered_set is very bad in MSVC2013 #define CGAL_CFG_NO_CPP0X_UNORDERED 1 #endif #if defined( BOOST_NO_0X_HDR_THREAD) || \ From 803e5e67179522d07f46b2e5114ecf920f4a1266 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 22 Jun 2018 10:32:23 +0200 Subject: [PATCH 84/84] add missing boost:: --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 3457081de5e..30a859cc1c0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -181,7 +181,7 @@ collect_duplicated_stitchable_boundary_edges { cc = get(Face_property_tag(), pmesh); typedef typename GetFaceIndexMap::const_type FIMap; - FIMap fim = choose_param(get_param(np, internal_np::face_index), + FIMap fim = boost::choose_param(get_param(np, internal_np::face_index), get_const_property_map(face_index, pmesh)); num_component = num_component_wrapper(pmesh, cc, fim); border_edges_per_cc.resize(num_component);