From 9b776fa516967c183f84d7314d81729cd0846dda Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 16 Jul 2018 14:10:55 +0200 Subject: [PATCH 001/186] Fix behaviour when loading an empty file. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 6 ------ Polyhedron/demo/Polyhedron/MainWindow.h | 6 +++--- .../Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp | 11 +++++++++++ .../demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp | 6 ++++++ .../demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp | 10 ++++++++++ .../Plugins/IO/OFF_to_nef_io_plugin.cpp | 8 +++++++- .../demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp | 7 +++++++ .../Polyhedron/Plugins/IO/Polylines_io_plugin.cpp | 9 +++++++++ .../demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp | 9 ++++++++- .../demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp | 8 ++++++++ .../Plugins/IO/Surface_mesh_io_plugin.cpp | 11 ++++++++++- .../demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 10 ++++++++++ .../demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp | 10 ++++++++++ .../Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp | 8 ++++++++ Three/include/CGAL/Three/Three.h | 15 +++++++++++++++ 15 files changed, 122 insertions(+), 12 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index b60cbd764ab..4bdd1d01907 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1113,12 +1113,6 @@ CGAL::Three::Scene_item* MainWindow::loadItem(QFileInfo fileinfo, CGAL::Three::P throw std::invalid_argument(QString("File %1 is not a readable file.") .arg(fileinfo.absoluteFilePath()).toStdString()); } - //test if the file is empty. - if(fileinfo.size() == 0) { - QMessageBox::warning(this, tr("Error"), - tr("The file you are trying to load is empty.\n")); - return 0; - } QApplication::setOverrideCursor(Qt::WaitCursor); item = loader->load(fileinfo); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index c1eb1079623..2d84c336bd2 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -213,15 +213,15 @@ public Q_SLOTS: /*! * Displays a text preceded by the mention "INFO :". */ - void information(QString); + void information(QString) Q_DECL_OVERRIDE; /*! * Displays a blue text preceded by the mention "WARNING :". */ - void warning(QString); + void warning(QString) Q_DECL_OVERRIDE; /*! * Displays a red text preceded by the mention "ERROR :". */ - void error(QString); + void error(QString) Q_DECL_OVERRIDE; //!Displays a text in the chosen html color with the chosen html font. diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp index 4b526e26a07..5409475d32a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,11 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) { // Try to read GOCAD file in a polyhedron Scene_polyhedron_item* item = new Scene_polyhedron_item(Polyhedron()); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + return item; + } Polyhedron& P = * const_cast(item->polyhedron()); std::string name, color; @@ -103,6 +109,11 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) { // Try to read GOCAD file in a surface_mesh Scene_surface_mesh_item* item = new Scene_surface_mesh_item(new SMesh()); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + return item; + } SMesh& P = * const_cast(item->polyhedron()); std::string name, color; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp index 9a18386d813..947a4a88ac0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp @@ -1,6 +1,7 @@ #include "Scene_nef_polyhedron_item.h" #include +#include #include #include @@ -47,6 +48,11 @@ Polyhedron_demo_io_nef_plugin::load(QFileInfo fileinfo) { // Try to read .nef3 in a polyhedron Scene_nef_polyhedron_item* item = new Scene_nef_polyhedron_item(); item->setName(fileinfo.baseName()); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + return item; + } if(!item->load(in)) { delete item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp index cfe9f558948..4ab711cfeab 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -48,6 +49,15 @@ bool Polyhedron_demo_off_plugin::canLoad() const { CGAL::Three::Scene_item* Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) { + + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_polyhedron_item* item = + new Scene_polyhedron_item(Polyhedron()); + item->setName(fileinfo.completeBaseName()); + return item; + } if(fileinfo.suffix().toLower() == "off"){ return load_off(fileinfo); } else if(fileinfo.suffix().toLower() == "obj"){ diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp index 0ac3e1f8b0e..eebae8a7393 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp @@ -2,6 +2,7 @@ #include "Nef_type.h" #include +#include #include using namespace CGAL::Three; class Polyhedron_demo_off_to_nef_plugin : @@ -33,7 +34,12 @@ Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) { if(!in) std::cerr << "Error!\n"; Scene_nef_polyhedron_item* item = new Scene_nef_polyhedron_item(); - + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + item->setName(fileinfo.completeBaseName()); + return item; + } if(!item->load_from_off(in)) { delete item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp index 19f788c1bb8..b2ae3f10905 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp @@ -4,6 +4,7 @@ #include "Scene_points_with_normal_item.h" #include +#include #include #include #include @@ -79,6 +80,12 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) { QApplication::setOverrideCursor(Qt::WaitCursor); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + return 0; + } + // Test if input is mesh or point set bool input_is_mesh = false; std::string line; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp index e4997939f80..ad67e838c42 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,14 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) { return NULL; } + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_polylines_item* item = new Scene_polylines_item; + item->setName(fileinfo.completeBaseName()); + return item; + } + std::list > polylines; QStringList polylines_metadata; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp index 9eada718ae9..7f87f3ee48f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -72,7 +73,13 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) { std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl; return NULL; } - + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_surface_mesh_item* item = new Scene_surface_mesh_item(); + item->setName(fileinfo.completeBaseName()); + return item; + } std::vector > points; std::vector > triangles; if (!CGAL::read_STL(in, points, triangles)) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp index 43f44a90613..31d6482febd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -74,6 +75,13 @@ CGAL::Three::Scene_item* Surf_io_plugin::actual_load(QFileInfo fileinfo) return NULL; } + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_group_item* item = + new Scene_group_item(fileinfo.completeBaseName()); + return item; + } std::vector patches; std::vector material_data; CGAL::Bbox_3 grid_box; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp index 8de6c704d56..9fc66819ac1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -59,8 +60,16 @@ public: } SMesh *surface_mesh = new SMesh(); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_surface_mesh_item* item = new Scene_surface_mesh_item(surface_mesh); + item->setName(fileinfo.completeBaseName()); + return item; + } + in >> *surface_mesh; - if(!in || surface_mesh->is_empty()) + if(!in) { delete surface_mesh; in.close(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index a73e7b3f62e..8d5f8ed72df 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -363,6 +364,15 @@ public: FaceGraph* poly = new FaceGraph(); // Try to read .vtk in a facegraph + + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_facegraph_item* item = + new Scene_facegraph_item(poly); + item->setName(fileinfo.completeBaseName()); + return item; + } vtkSmartPointer data; vtkSmartPointer obs = vtkSmartPointer::New(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp index 9f95025a27f..88aca74fafb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,15 @@ Polyhedron_demo_xyz_plugin::load(QFileInfo fileinfo) return NULL; } + + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + Scene_points_with_normal_item* item = + new Scene_points_with_normal_item(); + item->setName(fileinfo.completeBaseName()); + return item; + } // Read .xyz in a point set Scene_points_with_normal_item* point_set_item = new Scene_points_with_normal_item; point_set_item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 9a788dc87b4..de5e9bcb245 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,13 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) { return NULL; } Scene_c3t3_item* item = new Scene_c3t3_item(); + + if(fileinfo.size() == 0) + { + CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + item->setName(fileinfo.completeBaseName()); + return item; + } if(fileinfo.suffix().toLower() == "cgal") { item->setName(fileinfo.baseName()); diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 307034838d0..6abe97dbb85 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -48,6 +48,21 @@ public: static Scene_interface* scene(); static QObject* connectableScene(); static Three* messages(); + + /*! + * Displays a text preceded by the mention "INFO :". + */ + virtual void information(QString) = 0; + /*! + * Displays a blue text preceded by the mention "WARNING :". + */ + virtual void warning(QString) = 0; + /*! + * Displays a red text preceded by the mention "ERROR :". + */ + virtual void error(QString) = 0; + + /*! \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. From 2570c21b7017f8a73c940f60954a971c999a7eae Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 23 Aug 2018 15:24:32 +0200 Subject: [PATCH 002/186] WIP tests with c3t3 and meshdomain ID --- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 283 +++++++++++++++++- 1 file changed, 277 insertions(+), 6 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index a73e7b3f62e..dc9c79214ba 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -83,6 +83,236 @@ typedef Scene_polyhedron_item Scene_facegraph_item; #endif typedef Scene_facegraph_item::Face_graph FaceGraph; typedef boost::property_traits::type>::value_type Point; + + + +// writes the appended data into the .vtu file +template +void +write_vector(std::ostream& os, + const std::vector& vect) +{ + const char* buffer = reinterpret_cast(&(vect[0])); + std::size_t size = vect.size()*sizeof(FT); + + os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded + os.write(buffer, vect.size()*sizeof(FT)); // encoded data +} + +// writes the cells tags before binary data is appended +template +void +write_cells_tag(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + bool binary, + std::size_t& offset) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 4 indices (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + for (int i=0; i<4; i++) + os << V[cit->vertex(i)] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 1 offset (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t cells_offset = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + cells_offset += 4; + os << cells_offset << " "; + } + os << " \n"; + } + + // Write cell type (tetrahedra == 10) + os << " \n"; + offset += c3t3.number_of_cells() + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + os << "10 "; + os << " \n"; + } + os << " \n"; +} + +// writes the cells appended data at the end of the .vtu file +template +void +write_cells(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + std::vector& mids) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 + + std::size_t off = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + off += 4; + offsets.push_back(off); + for (int i=0; i<4; i++) + connectivity_table.push_back(V[cit->vertex(i)]); + mids.push_back(cit->subdomain_index()); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} + + +// writes the points tags before binary data is appended +template +void +write_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) +{ + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; + os << vit->point().x() << " " << vit->point().y() << " " << vit->point().z() << " "; + } + os << " \n"; + } + os << " \n"; +} + +// writes the points appended data at the end of the .vtu file +template +void +write_points(std::ostream& os, + const Tr & tr, + std::map & V) +{ + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::vector coordinates; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; // binary output => the map has not been filled yet + coordinates.push_back(vit->point().x()); + coordinates.push_back(vit->point().y()); + coordinates.push_back(vit->point().z()); + } + write_vector(os,coordinates); +} + +// writes the attribute tags before binary data is appended +template +void +write_attribute_tag(std::ostream& os, + const std::string& attr_name, + const std::vector& attribute, + bool binary, + std::size_t& offset) +{ + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; + os << " \n"; + offset += attribute.size() * sizeof(T) + sizeof(std::size_t); + } + else { + typedef typename std::vector::const_iterator Iterator; + os << "\">\n"; + for (Iterator it = attribute.begin(); + it != attribute.end(); + ++it ) + os << *it << " "; + os << " \n"; + } +} + +// writes the attributes appended data at the end of the .vtu file +template +void +write_attributes(std::ostream& os, + const std::vector& att) +{ + write_vector(os,att); +} namespace CGAL{ class ErrorObserverVtk : public vtkCommand @@ -300,6 +530,8 @@ public: return (qobject_cast(item) || qobject_cast(item)); } + + bool save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo) { std::string extension = fileinfo.suffix().toLower().toStdString(); @@ -328,12 +560,51 @@ public: qobject_cast(item); if(!c3t3_item || extension != "vtu") return false; - - vtkSmartPointer writer = - vtkSmartPointer::New(); - writer->SetFileName( output_filename.data()); - writer->SetInputData(CGAL::output_c3t3_to_vtk_unstructured_grid(c3t3_item->c3t3())); - writer->Write(); + + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + const C3t3& c3t3 = c3t3_item->c3t3(); + const Tr& tr = c3t3.triangulation(); + std::map V; + std::ofstream os(output_filename.data()); + os << std::setprecision(16); + //write header + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + bool binary = true; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset); + write_cells_tag(os,c3t3,V,binary,offset); + os << " \n"; + std::vector mids; + write_attribute_tag(os,"MeshDomain",mids,binary,offset); + os << " \n"; + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V); // write points before cells to fill the std::map V + write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag + write_attributes(os,mids); + } + os << "\n"; } return true; } From b29534c73d7b0caf1ee6356a146bde55fd13c079 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 27 Aug 2018 10:21:52 +0200 Subject: [PATCH 003/186] vtp in plugin --- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 302 +++++++++++++++++- 1 file changed, 288 insertions(+), 14 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index dc9c79214ba..eece21fd26b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -76,6 +76,9 @@ #include #include +#include +#include + #ifdef USE_SURFACE_MESH typedef Scene_surface_mesh_item Scene_facegraph_item; #else @@ -90,7 +93,7 @@ typedef boost::property_traits void write_vector(std::ostream& os, - const std::vector& vect) + const std::vector& vect) { const char* buffer = reinterpret_cast(&(vect[0])); std::size_t size = vect.size()*sizeof(FT); @@ -103,10 +106,10 @@ write_vector(std::ostream& os, template void write_cells_tag(std::ostream& os, - const C3T3 & c3t3, - std::map & V, - bool binary, - std::size_t& offset) + const C3T3 & c3t3, + std::map & V, + bool binary, + std::size_t& offset) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::string formatattribute = @@ -187,8 +190,8 @@ write_cells_tag(std::ostream& os, template void write_cells(std::ostream& os, - const C3T3 & c3t3, - std::map & V, + const C3T3 & c3t3, + std::map & V, std::vector& mids) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; @@ -212,15 +215,165 @@ write_cells(std::ostream& os, write_vector(os,cell_type); } +// writes the polys appended data at the end of the .vtp file +template +void +write_polys(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(mesh),5); // triangle == 5 + + std::size_t off = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} +//overload +template +void +write_polys(std::ostream& os, + const Mesh & mesh) +{ + write_polys(os, mesh, CGAL::parameters::all_default()); +} +//todo use named params for maps +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(mesh) + 1) * sizeof(std::size_t); + // 1 offset (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t polys_offset = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(mesh) + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(std::size_t i = 0; i< num_faces(mesh); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} +//overload +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset) +{ + write_polys_tag(os, + mesh, + binary, + offset, + CGAL::parameters::all_default()); +} // writes the points tags before binary data is appended template void write_points_tag(std::ostream& os, - const Tr & tr, - std::map & V, - bool binary, - std::size_t& offset) + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) { typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Geom_traits Gt; @@ -252,6 +405,58 @@ write_points_tag(std::ostream& os, os << " \n"; } +//todo : use namedparams for points and ids +//overload for facegraph +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " << get(vpm, *vit).z() << " "; + } + os << " \n"; + } + os << " \n"; +} +//overload +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset) +{ + write_points_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); +} // writes the points appended data at the end of the .vtu file template void @@ -277,6 +482,40 @@ write_points(std::ostream& os, write_vector(os,coordinates); } +// writes the points appended data at the end of the .vtp file +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector coordinates; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + coordinates.push_back(get(vpm, *vit).x()); + coordinates.push_back(get(vpm, *vit).y()); + coordinates.push_back(get(vpm, *vit).z()); + } + write_vector(os,coordinates); +} +//overload +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh) +{ + write_polys_points(os, mesh, CGAL::parameters::all_default()); +} // writes the attribute tags before binary data is appended template void @@ -550,9 +789,44 @@ public: *poly_item->polyhedron(), output_filename.data()); else - CGAL::polygon_mesh_to_vtkUnstructured( - *poly_item->polyhedron(), - output_filename.data()); + { + const FaceGraph* mesh = poly_item->face_graph(); + std::ofstream os(output_filename.data()); + os << std::setprecision(16); + //write header + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + bool binary = true; + std::size_t offset = 0; + write_points_tag(os,*mesh,binary,offset); + write_polys_tag(os,*mesh,binary,offset); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_polys_points(os,*mesh); // write points before cells to fill the std::map V + write_polys(os,*mesh); + } + os << "\n"; + } + // CGAL::polygon_mesh_to_vtkUnstructured( + // *poly_item->polyhedron(), + // output_filename.data()); } else { From 06db5dafbcf5180993a4a19f6d60d5997fa737ac Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 27 Aug 2018 14:56:18 +0200 Subject: [PATCH 004/186] WIP integrate functions. --- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 542 +------------- Stream_support/include/CGAL/IO/vtk_io.h | 668 ++++++++++++++++++ 2 files changed, 674 insertions(+), 536 deletions(-) create mode 100644 Stream_support/include/CGAL/IO/vtk_io.h diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index eece21fd26b..656869b2847 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -85,473 +86,12 @@ typedef Scene_surface_mesh_item Scene_facegraph_item; typedef Scene_polyhedron_item Scene_facegraph_item; #endif typedef Scene_facegraph_item::Face_graph FaceGraph; -typedef boost::property_traits::type>::value_type Point; +typedef boost::property_traits::type>::value_type Point; -// writes the appended data into the .vtu file -template -void -write_vector(std::ostream& os, - const std::vector& vect) -{ - const char* buffer = reinterpret_cast(&(vect[0])); - std::size_t size = vect.size()*sizeof(FT); - - os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded - os.write(buffer, vect.size()*sizeof(FT)); // encoded data -} -// writes the cells tags before binary data is appended -template -void -write_cells_tag(std::ostream& os, - const C3T3 & c3t3, - std::map & V, - bool binary, - std::size_t& offset) -{ - typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); - // 4 indices (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - for (int i=0; i<4; i++) - os << V[cit->vertex(i)] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); - // 1 offset (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t cells_offset = 0; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - cells_offset += 4; - os << cells_offset << " "; - } - os << " \n"; - } - - // Write cell type (tetrahedra == 10) - os << " \n"; - offset += c3t3.number_of_cells() + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - os << "10 "; - os << " \n"; - } - os << " \n"; -} - -// writes the cells appended data at the end of the .vtu file -template -void -write_cells(std::ostream& os, - const C3T3 & c3t3, - std::map & V, - std::vector& mids) -{ - typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 - - std::size_t off = 0; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - off += 4; - offsets.push_back(off); - for (int i=0; i<4; i++) - connectivity_table.push_back(V[cit->vertex(i)]); - mids.push_back(cit->subdomain_index()); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} - -// writes the polys appended data at the end of the .vtp file -template -void -write_polys(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(num_faces(mesh),5); // triangle == 5 - - std::size_t off = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - off += 3; - offsets.push_back(off); - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(V[v]); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} -//overload -template -void -write_polys(std::ostream& os, - const Mesh & mesh) -{ - write_polys(os, mesh, CGAL::parameters::all_default()); -} -//todo use named params for maps -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); - // 3 indices (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << V[v] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (num_faces(mesh) + 1) * sizeof(std::size_t); - // 1 offset (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t polys_offset = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - polys_offset += 3; - os << polys_offset << " "; - } - os << " \n"; - } - - // Write cell type (triangle == 5) - os << " \n"; - offset += num_faces(mesh) + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(std::size_t i = 0; i< num_faces(mesh); ++i) - os << "5 "; - os << " \n"; - } - os << " \n"; -} -//overload -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset) -{ - write_polys_tag(os, - mesh, - binary, - offset, - CGAL::parameters::all_default()); -} -// writes the points tags before binary data is appended -template -void -write_points_tag(std::ostream& os, - const Tr & tr, - std::map & V, - bool binary, - std::size_t& offset) -{ - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - std::size_t inum = 0; - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); - // 3 coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - V[vit] = inum++; - os << vit->point().x() << " " << vit->point().y() << " " << vit->point().z() << " "; - } - os << " \n"; - } - os << " \n"; -} - -//todo : use namedparams for points and ids -//overload for facegraph -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); - // 3 coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " << get(vpm, *vit).z() << " "; - } - os << " \n"; - } - os << " \n"; -} -//overload -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset) -{ - write_points_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); -} -// writes the points appended data at the end of the .vtu file -template -void -write_points(std::ostream& os, - const Tr & tr, - std::map & V) -{ - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - std::size_t inum = 0; - std::vector coordinates; - for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - V[vit] = inum++; // binary output => the map has not been filled yet - coordinates.push_back(vit->point().x()); - coordinates.push_back(vit->point().y()); - coordinates.push_back(vit->point().z()); - } - write_vector(os,coordinates); -} - -// writes the points appended data at the end of the .vtp file -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector coordinates; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - coordinates.push_back(get(vpm, *vit).x()); - coordinates.push_back(get(vpm, *vit).y()); - coordinates.push_back(get(vpm, *vit).z()); - } - write_vector(os,coordinates); -} -//overload -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh) -{ - write_polys_points(os, mesh, CGAL::parameters::all_default()); -} -// writes the attribute tags before binary data is appended -template -void -write_attribute_tag(std::ostream& os, - const std::string& attr_name, - const std::vector& attribute, - bool binary, - std::size_t& offset) -{ - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; - os << " \n"; - offset += attribute.size() * sizeof(T) + sizeof(std::size_t); - } - else { - typedef typename std::vector::const_iterator Iterator; - os << "\">\n"; - for (Iterator it = attribute.begin(); - it != attribute.end(); - ++it ) - os << *it << " "; - os << " \n"; - } -} - -// writes the attributes appended data at the end of the .vtu file -template -void -write_attributes(std::ostream& os, - const std::vector& att) -{ - write_vector(os,att); -} namespace CGAL{ class ErrorObserverVtk : public vtkCommand @@ -794,39 +334,8 @@ public: std::ofstream os(output_filename.data()); os << std::setprecision(16); //write header - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - bool binary = true; - std::size_t offset = 0; - write_points_tag(os,*mesh,binary,offset); - write_polys_tag(os,*mesh,binary,offset); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_polys_points(os,*mesh); // write points before cells to fill the std::map V - write_polys(os,*mesh); - } - os << "\n"; + CGAL::write_polydata(os, *mesh); } - // CGAL::polygon_mesh_to_vtkUnstructured( - // *poly_item->polyhedron(), - // output_filename.data()); } else { @@ -835,50 +344,11 @@ public: if(!c3t3_item || extension != "vtu") return false; - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Vertex_handle Vertex_handle; - const C3t3& c3t3 = c3t3_item->c3t3(); - const Tr& tr = c3t3.triangulation(); - std::map V; std::ofstream os(output_filename.data()); os << std::setprecision(16); - //write header - os << "\n" - << "c3t3(); - switch(sizeof(std::size_t)) { - case 4: os << " header_type=\"UInt32\""; break; - case 8: os << " header_type=\"UInt64\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - os << ">\n" - << " " << "\n"; - - os << " \n"; - bool binary = true; - std::size_t offset = 0; - write_points_tag(os,tr,V,binary,offset); - write_cells_tag(os,c3t3,V,binary,offset); - os << " \n"; - std::vector mids; - write_attribute_tag(os,"MeshDomain",mids,binary,offset); - os << " \n"; - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_points(os,tr,V); // write points before cells to fill the std::map V - write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag - write_attributes(os,mids); - } - os << "\n"; + CGAL::write_unstructured_grid_3(os, c3t3); } return true; } diff --git a/Stream_support/include/CGAL/IO/vtk_io.h b/Stream_support/include/CGAL/IO/vtk_io.h new file mode 100644 index 00000000000..660afbd7d91 --- /dev/null +++ b/Stream_support/include/CGAL/IO/vtk_io.h @@ -0,0 +1,668 @@ +// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). +// Copyright (c) 2009 INRIA Sophia-Antipolis (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$ +// +// +// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno + +#ifndef CGAL_VTK_IO_H +#define CGAL_VTK_IO_H + +#include +#include + +#include +#include + + + +namespace CGAL{ +// writes the appended data into the .vtu file +template +void +write_vector(std::ostream& os, + const std::vector& vect) +{ + const char* buffer = reinterpret_cast(&(vect[0])); + std::size_t size = vect.size()*sizeof(FT); + + os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded + os.write(buffer, vect.size()*sizeof(FT)); // encoded data +} + +// writes the cells tags before binary data is appended +template +void +write_cells_tag(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + bool binary, + std::size_t& offset) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 4 indices (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + for (int i=0; i<4; i++) + os << V[cit->vertex(i)] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 1 offset (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t cells_offset = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + cells_offset += 4; + os << cells_offset << " "; + } + os << " \n"; + } + + // Write cell type (tetrahedra == 10) + os << " \n"; + offset += c3t3.number_of_cells() + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + os << "10 "; + os << " \n"; + } + os << " \n"; +} + +// writes the cells appended data at the end of the .vtu file +template +void +write_cells(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + std::vector& mids) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 + + std::size_t off = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + off += 4; + offsets.push_back(off); + for (int i=0; i<4; i++) + connectivity_table.push_back(V[cit->vertex(i)]); + mids.push_back(cit->subdomain_index()); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} + +// writes the polys appended data at the end of the .vtp file +template +void +write_polys(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(mesh),5); // triangle == 5 + + std::size_t off = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} +//overload +template +void +write_polys(std::ostream& os, + const Mesh & mesh) +{ + write_polys(os, mesh, CGAL::parameters::all_default()); +} +//todo use named params for maps +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(mesh) + 1) * sizeof(std::size_t); + // 1 offset (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t polys_offset = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(mesh) + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(std::size_t i = 0; i< num_faces(mesh); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} +//overload +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset) +{ + write_polys_tag(os, + mesh, + binary, + offset, + CGAL::parameters::all_default()); +} +// writes the points tags before binary data is appended +template +void +write_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset, + std::size_t dim) +{ + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += dim * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + // dim coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; + os << vit->point().x() << " " << vit->point().y()<< " " ; + if(dim == 3) + os << vit->point().z() << " "; + } + os << " \n"; + } + os << " \n"; +} + +//todo : use namedparams for points and ids +//overload for facegraph +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " + << get(vpm, *vit).z() << " "; + } + os << " \n"; + } + os << " \n"; +} +//overload +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset) +{ + write_points_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); +} +// writes the points appended data at the end of the .vtu file +template +void +write_points(std::ostream& os, + const Tr & tr, + std::map & V, + std::size_t dim) +{ + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::vector coordinates; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; // binary output => the map has not been filled yet + coordinates.push_back(vit->point().x()); + coordinates.push_back(vit->point().y()); + if(dim == 3) + coordinates.push_back(vit->point().z()); + } + write_vector(os,coordinates); +} + +// writes the points appended data at the end of the .vtp file +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector coordinates; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + coordinates.push_back(get(vpm, *vit).x()); + coordinates.push_back(get(vpm, *vit).y()); + coordinates.push_back(get(vpm, *vit).z()); + } + write_vector(os,coordinates); +} +//overload +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh) +{ + write_polys_points(os, mesh, CGAL::parameters::all_default()); +} +// writes the attribute tags before binary data is appended +template +void +write_attribute_tag(std::ostream& os, + const std::string& attr_name, + const std::vector& attribute, + bool binary, + std::size_t& offset) +{ + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; + os << " \n"; + offset += attribute.size() * sizeof(T) + sizeof(std::size_t); + } + else { + typedef typename std::vector::const_iterator Iterator; + os << "\">\n"; + for (Iterator it = attribute.begin(); + it != attribute.end(); + ++it ) + os << *it << " "; + os << " \n"; + } +} + +// writes the attributes appended data at the end of the .vtu file +template +void +write_attributes(std::ostream& os, + const std::vector& att) +{ + write_vector(os,att); +} + +template +void write_unstructured_grid(std::ostream& os, + const C3t3& c3t3, + std::size_t dim) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + const Tr& tr = c3t3.triangulation(); + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + bool binary = true; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset, dim); + write_cells_tag(os,c3t3,V,binary,offset); + if(dim==3) + { + os << " \n"; + std::vector mids; + write_attribute_tag(os,"MeshDomain",mids,binary,offset); + os << " \n"; + } + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V, dim); // write points before cells to fill the std::map V + write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag + if(dim==3) + write_attributes(os,mids); + } + os << "\n"; +} + +//public API + +//! +//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp +//! XML format. +//! +//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. +//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +//! +//! \param os a `std::ostream`. +//! \param mesh an instance of `TriangleMesh` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the +//! ones listed below +//! +//! \cgalNamedParamsBegin +//! \cgalParamBegin{vertex_point_map} the property map with the points associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalNamedParamsEnd +template +void write_polydata(std::ostream& os, + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np) +{ + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + std::size_t offset = 0; + write_points_tag(os,mesh,binary,offset, np); + write_polys_tag(os,mesh,binary,offset, np); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_polys_points(os,mesh, np); + write_polys(os,mesh, np); + } + os << "\n"; +} + +template +void write_polydata(std::ostream& os, + const TriangleMesh& mesh, + bool binary = true) +{ + write_polydata(os, mesh, binary, CGAL::parameters::all_default()); +} + +//! +//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu +//! XML format. +//! +//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. +//! +//! \param os a `std::ostream`. +//! \param c3t3 an instance of `C3T3` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! +template +void write_unstructured_grid_3(std::ostream& os, + const C3T3& c3t3) +{ + write_unstructured_grid(os, c3t3, 3); +} + +//! +//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu +//! XML format. +//! +//! \tparam CDT must be 2D constrained Delaunay triangulation +//! +//! \param os a `std::ostream`. +//! \param tr ????????? +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! +//! +template +void write_unstructured_grid_2(std::ostream& os, + const CDT& tr) +{ + write_unstructured_grid(os, tr, 2); +} +} //end CGAL +#endif // CGAL_VTK_IO_H From 223fa687c238e116d2b66a553ed847533bf0519d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 27 Aug 2018 16:29:07 +0200 Subject: [PATCH 005/186] Add function for CDT. and use it in Triangulation_2 demo. Missing Doc --- .../Constrained_Delaunay_triangulation_2.cpp | 14 +- Stream_support/include/CGAL/IO/vtk_io.h | 367 ++++++++++++------ 2 files changed, 250 insertions(+), 131 deletions(-) diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 818d9f04c69..e505233e119 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -22,6 +22,7 @@ #include #include #include +#include // Qt headers #include @@ -658,9 +659,10 @@ MainWindow::on_actionSaveConstraints_triggered() tr("Save Constraints"), ".", tr("Poly files (*.poly)\n" - "Edge files (*.edg)")); + "Edge files (*.edg)\n" + "VTU files (*.vtu)")); if(! fileName.isEmpty()){ - saveConstraints(fileName); + saveConstraints(fileName); } } @@ -669,7 +671,13 @@ void MainWindow::saveConstraints(QString fileName) { std::ofstream output(qPrintable(fileName)); - if (output) output << cdt; + + if(!fileName.endsWith("vtu") && output) + output << cdt; + else if (output) + { + CGAL::write_unstructured_grid_2(output, cdt); + } } diff --git a/Stream_support/include/CGAL/IO/vtk_io.h b/Stream_support/include/CGAL/IO/vtk_io.h index 660afbd7d91..13382735c42 100644 --- a/Stream_support/include/CGAL/IO/vtk_io.h +++ b/Stream_support/include/CGAL/IO/vtk_io.h @@ -30,7 +30,7 @@ #include - +//todo try to factorize with functors namespace CGAL{ // writes the appended data into the .vtu file template @@ -46,6 +46,105 @@ write_vector(std::ostream& os, } // writes the cells tags before binary data is appended + +template +void +write_cells_tag_2(std::ostream& os, + const CDT & tr, + std::size_t number_of_triangles, + std::map & V, + bool binary, + std::size_t& offset) +{ + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * number_of_triangles + 1) * sizeof(std::size_t); + // 3 indices (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) + { + os << V[fit->vertex(0)] << " "; + os << V[fit->vertex(2)] << " "; + os << V[fit->vertex(1)] << " "; + } + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (number_of_triangles + 1) * sizeof(std::size_t); + // 1 offset (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t cells_offset = 0; + for(typename CDT::Finite_faces_iterator fit = + tr.finite_faces_begin() ; + fit != tr.finite_faces_end() ; + ++fit ) + { + if(fit->is_in_domain()) + { + cells_offset += 3; + os << cells_offset << " "; + } + } + os << " \n"; + } + + // Write cell type (triangles == 5) + os << " \n"; + offset += number_of_triangles + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(typename CDT::Finite_faces_iterator fit = + tr.finite_faces_begin() ; + fit != tr.finite_faces_end() ; + ++fit ) + { + if(fit->is_in_domain()) + { + os << "5 "; + } + } + os << " \n"; + } + os << " \n"; +} + template void write_cells_tag(std::ostream& os, @@ -130,6 +229,38 @@ write_cells_tag(std::ostream& os, } // writes the cells appended data at the end of the .vtu file +template +void +write_cells_2(std::ostream& os, + const CDT & tr, + std::size_t number_of_triangles, + std::map & V) +{ + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(number_of_triangles,5); // triangles == 5 + + std::size_t off = 0; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) + { + off += 3; + offsets.push_back(off); + connectivity_table.push_back(V[fit->vertex(0)]); + connectivity_table.push_back(V[fit->vertex(2)]); + connectivity_table.push_back(V[fit->vertex(1)]); + } + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} + + template void write_cells(std::ostream& os, @@ -166,6 +297,7 @@ write_polys(std::ostream& os, const Mesh & mesh, const NamedParameters& np) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; @@ -174,7 +306,6 @@ write_polys(std::ostream& os, typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; std::vector connectivity_table; std::vector offsets; std::vector cell_type(num_faces(mesh),5); // triangle == 5 @@ -194,14 +325,6 @@ write_polys(std::ostream& os, write_vector(os,offsets); write_vector(os,cell_type); } -//overload -template -void -write_polys(std::ostream& os, - const Mesh & mesh) -{ - write_polys(os, mesh, CGAL::parameters::all_default()); -} //todo use named params for maps template @@ -212,6 +335,7 @@ write_polys_tag(std::ostream& os, std::size_t& offset, const NamedParameters& np) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; @@ -221,7 +345,6 @@ write_polys_tag(std::ostream& os, typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; std::string formatattribute = binary ? " format=\"appended\"" : " format=\"ascii\""; @@ -295,20 +418,6 @@ write_polys_tag(std::ostream& os, } os << " \n"; } -//overload -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset) -{ - write_polys_tag(os, - mesh, - binary, - offset, - CGAL::parameters::all_default()); -} // writes the points tags before binary data is appended template void @@ -317,7 +426,7 @@ write_points_tag(std::ostream& os, std::map & V, bool binary, std::size_t& offset, - std::size_t dim) + std::size_t dim = 3) { typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Geom_traits Gt; @@ -328,25 +437,27 @@ write_points_tag(std::ostream& os, std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; os << " \n" - << " \n"; - offset += dim * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); // dim coords per points + length of the encoded data (size_t) } else { os << "\">\n"; for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - V[vit] = inum++; - os << vit->point().x() << " " << vit->point().y()<< " " ; - if(dim == 3) - os << vit->point().z() << " "; + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; + os << vit->point()[0] << " "; + os << vit->point()[1] << " "; + if(dim == 3) + os << vit->point()[2] << " "; + else + os << 0.0 << " "; } os << " \n"; } @@ -397,23 +508,15 @@ write_points_tag(std::ostream& os, } os << " \n"; } -//overload -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset) -{ - write_points_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); -} + // writes the points appended data at the end of the .vtu file template void write_points(std::ostream& os, const Tr & tr, - std::map & V, - std::size_t dim) + std::map & V, + std::size_t dim = 3) { typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Geom_traits Gt; @@ -426,10 +529,9 @@ write_points(std::ostream& os, ++vit) { V[vit] = inum++; // binary output => the map has not been filled yet - coordinates.push_back(vit->point().x()); - coordinates.push_back(vit->point().y()); - if(dim == 3) - coordinates.push_back(vit->point().z()); + coordinates.push_back(vit->point()[0]); + coordinates.push_back(vit->point()[1]); + coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0); } write_vector(os,coordinates); } @@ -460,14 +562,6 @@ write_polys_points(std::ostream& os, } write_vector(os,coordinates); } -//overload -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh) -{ - write_polys_points(os, mesh, CGAL::parameters::all_default()); -} // writes the attribute tags before binary data is appended template void @@ -505,58 +599,6 @@ write_attributes(std::ostream& os, write_vector(os,att); } -template -void write_unstructured_grid(std::ostream& os, - const C3t3& c3t3, - std::size_t dim) -{ - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Vertex_handle Vertex_handle; - const Tr& tr = c3t3.triangulation(); - std::map V; - //write header - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - bool binary = true; - std::size_t offset = 0; - write_points_tag(os,tr,V,binary,offset, dim); - write_cells_tag(os,c3t3,V,binary,offset); - if(dim==3) - { - os << " \n"; - std::vector mids; - write_attribute_tag(os,"MeshDomain",mids,binary,offset); - os << " \n"; - } - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_points(os,tr,V, dim); // write points before cells to fill the std::map V - write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag - if(dim==3) - write_attributes(os,mids); - } - os << "\n"; -} - //public API //! @@ -643,26 +685,95 @@ template void write_unstructured_grid_3(std::ostream& os, const C3T3& c3t3) { - write_unstructured_grid(os, c3t3, 3); + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + const Tr& tr = c3t3.triangulation(); + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + bool binary = true; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset); + write_cells_tag(os,c3t3,V,binary,offset); + std::vector mids; + os << " \n"; + write_attribute_tag(os,"MeshDomain",mids,binary,offset); + os << " \n"; + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V); // write points before cells to fill the std::map V + write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag + write_attributes(os,mids); + } + os << "\n"; } -//! -//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu -//! XML format. -//! -//! \tparam CDT must be 2D constrained Delaunay triangulation -//! -//! \param os a `std::ostream`. -//! \param tr ????????? -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! -//! template void write_unstructured_grid_2(std::ostream& os, - const CDT& tr) + const CDT& tr, + bool binary = true) { - write_unstructured_grid(os, tr, 2); + typedef typename CDT::Vertex_handle Vertex_handle; + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + int number_of_triangles = 0; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) ++number_of_triangles; + } + os << " \n"; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset, 2); + write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V, 2); // write points before cells to fill the std::map V + write_cells_2(os,tr, number_of_triangles, V); + } + os << "\n"; } + } //end CGAL #endif // CGAL_VTK_IO_H From 4fb1fe60798b19c5cc35c8c65aad4ca6fd827999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 1 Oct 2018 19:00:18 +0200 Subject: [PATCH 006/186] fix when not using Gmp --- ...nt_Delaunay_graph_Linf_filtered_traits_2.h | 2 +- .../include/CGAL/Side_of_bounded_square_2.h | 8 +++--- .../test_sdg_linf_2_et.cpp | 25 ++++++------------- .../test_sdg_linf_2_ft.cpp | 15 ++++------- .../test_sdg_linf_hierarchy_2_et.cpp | 25 ++++++------------- .../test_sdg_linf_hierarchy_2_ft.cpp | 15 ++++------- .../test_sdg_linf_new_range_api.cpp | 6 +++-- 7 files changed, 35 insertions(+), 61 deletions(-) diff --git a/Segment_Delaunay_graph_Linf_2/include/CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h b/Segment_Delaunay_graph_Linf_2/include/CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h index 4f9c4a31648..5335a26b209 100644 --- a/Segment_Delaunay_graph_Linf_2/include/CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h +++ b/Segment_Delaunay_graph_Linf_2/include/CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h @@ -221,7 +221,7 @@ template, #else - class EK = Simple_cartesian< MP_Float >, + class EK = Simple_cartesian< CGAL::Quotient >, #endif class EK_MTag = Integral_domain_without_division_tag, class FK = Simple_cartesian< Interval_nt >, diff --git a/Segment_Delaunay_graph_Linf_2/include/CGAL/Side_of_bounded_square_2.h b/Segment_Delaunay_graph_Linf_2/include/CGAL/Side_of_bounded_square_2.h index 17cfb236743..37f205cf6c4 100644 --- a/Segment_Delaunay_graph_Linf_2/include/CGAL/Side_of_bounded_square_2.h +++ b/Segment_Delaunay_graph_Linf_2/include/CGAL/Side_of_bounded_square_2.h @@ -70,7 +70,7 @@ namespace CGAL { bool samepq = false; bool samepr = false; bool sameqr = false; - const Comparison_result cmppq = compare(p, q); + const Comparison_result cmppq = CGAL::compare(p, q); switch(cmppq) { case SMALLER: min_p = &p; @@ -86,7 +86,7 @@ namespace CGAL { samepq = true; break; } - const Comparison_result cmppr = compare(p, r); + const Comparison_result cmppr = CGAL::compare(p, r); Comparison_result cmpqr; if (samepq) { cmpqr = cmppr; @@ -105,7 +105,7 @@ namespace CGAL { if (min_p == &p) { switch(cmppr) { case SMALLER: - cmpqr = compare(q, r); + cmpqr = CGAL::compare(q, r); switch(cmpqr) { case SMALLER: max_p = &r; @@ -135,7 +135,7 @@ namespace CGAL { max_p = &r; break; case LARGER: - cmpqr = compare(q, r); + cmpqr = CGAL::compare(q, r); switch(cmpqr) { case SMALLER: break; diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp index eca8eee9727..a53b491851c 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp @@ -10,28 +10,19 @@ #include #include -// choose number type -#ifdef CGAL_USE_GMP +#include +#include -# include -typedef CGAL::Gmpq exact_ring_t; -typedef CGAL::Gmpq exact_field_t; +// choose number type +typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_field_t; namespace CGAL { // needed for the drawing methods -Gmpq sqrt(const Gmpq& x) { - return Gmpq( CGAL::sqrt( CGAL::to_double(x) ) ); +exact_ring_t sqrt(const exact_ring_t& x) { + return exact_ring_t( sqrt( to_double(x) ) ); +} } - -} //namespace CGAL -#else - -# include -# include -typedef CGAL::MP_Float exact_ring_t; -typedef CGAL::Quotient exact_field_t; - -#endif typedef exact_ring_t ring_number_t; typedef exact_field_t field_number_t; diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp index 91e5edbe13c..1030d7a135b 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp @@ -10,17 +10,12 @@ #include #include +#include +#include + // choose number type -#ifdef CGAL_USE_GMP -# include -typedef CGAL::Gmpq exact_ring_t; -typedef CGAL::Gmpq exact_field_t; -#else -# include -# include -typedef CGAL::MP_Float exact_ring_t; -typedef CGAL::Quotient exact_field_t; -#endif +typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_field_t; #include diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp index 2f05e01dac2..50a1bdd0e34 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp @@ -10,28 +10,19 @@ #include #include -// choose number type -#ifdef CGAL_USE_GMP +#include +#include -# include -typedef CGAL::Gmpq exact_ring_t; -typedef CGAL::Gmpq exact_field_t; +// choose number type +typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_field_t; namespace CGAL { // needed for the drawing methods -Gmpq sqrt(const Gmpq& x) { - return Gmpq( sqrt( to_double(x) ) ); +exact_ring_t sqrt(const exact_ring_t& x) { + return exact_ring_t( sqrt( to_double(x) ) ); +} } - -} //namespace CGAL -#else - -# include -# include -typedef CGAL::MP_Float exact_ring_t; -typedef CGAL::Quotient exact_field_t; - -#endif typedef exact_ring_t ring_number_t; typedef exact_field_t field_number_t; diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp index 458a3a81c31..3e16425979c 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp @@ -10,17 +10,12 @@ #include #include +#include +#include + // choose number type -#ifdef CGAL_USE_GMP -# include -typedef CGAL::Gmpq exact_ring_t; -typedef CGAL::Gmpq exact_field_t; -#else -# include -# include -typedef CGAL::MP_Float exact_ring_t; -typedef CGAL::Quotient exact_field_t; -#endif +typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_field_t; #include diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_new_range_api.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_new_range_api.cpp index 791a866fb99..8b5124e1c6c 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_new_range_api.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_new_range_api.cpp @@ -7,12 +7,14 @@ #include #include #include -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Field_with_sqrt_tag MTag; typedef CGAL::Integral_domain_without_division_tag EMTag; -typedef CGAL::Simple_cartesian EK; +typedef CGAL::Exact_rational Number_type; + +typedef CGAL::Simple_cartesian EK; typedef CGAL::Segment_Delaunay_graph_Linf_filtered_traits_without_intersections_2 Gt; typedef CGAL::Segment_Delaunay_graph_Linf_2 SDG; From 49b88e533fb0c61e038f6f1e78d5c15395bba46b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Oct 2018 11:15:37 +0200 Subject: [PATCH 007/186] Move and split vtk_io.h to Mesh_2 and Mesh_3 to avoid license and dependencies problems. Also fix vtu writer of VTK_io_plugin for polygon meshes. --- .../Constrained_Delaunay_triangulation_2.cpp | 2 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 23 +- Stream_support/include/CGAL/IO/vtk_io.h | 779 ------------------ 3 files changed, 18 insertions(+), 786 deletions(-) delete mode 100644 Stream_support/include/CGAL/IO/vtk_io.h diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index e505233e119..352151640fd 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include // Qt headers #include diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 656869b2847..7d797ba0079 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -172,6 +173,7 @@ namespace CGAL{ vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); + std::cout< vr(nb_vertices); @@ -254,13 +256,13 @@ namespace CGAL{ cell->Delete(); } - vtkSmartPointer polydata = - vtkSmartPointer::New(); + vtkSmartPointer usg = + vtkSmartPointer::New(); - polydata->SetPoints(vtk_points); + usg->SetPoints(vtk_points); vtk_points->Delete(); - polydata->SetPolys(vtk_cells); + usg->SetCells(5,vtk_cells); vtk_cells->Delete(); // Combine the two data sets @@ -277,7 +279,7 @@ namespace CGAL{ vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetFileName(filename); - writer->SetInputData(polydata); + writer->SetInputData(usg); writer->Write(); } }//end namespace CGAL @@ -325,9 +327,18 @@ public: if (poly_item) { if (extension != "vtp") - CGAL::polygon_mesh_to_vtkUnstructured( + { + if(!CGAL::is_triangle_mesh(*poly_item->polyhedron())) + { + QMessageBox::warning(0, "Error", + "Cannot save a mesh in vtu format if " + "it is not pure triangle."); + return false; + } + CGAL::polygon_mesh_to_vtkUnstructured( *poly_item->polyhedron(), output_filename.data()); + } else { const FaceGraph* mesh = poly_item->face_graph(); diff --git a/Stream_support/include/CGAL/IO/vtk_io.h b/Stream_support/include/CGAL/IO/vtk_io.h deleted file mode 100644 index 13382735c42..00000000000 --- a/Stream_support/include/CGAL/IO/vtk_io.h +++ /dev/null @@ -1,779 +0,0 @@ -// Copyright (c) 2018 GeometryFactory (France). -// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). -// Copyright (c) 2009 INRIA Sophia-Antipolis (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$ -// -// -// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno - -#ifndef CGAL_VTK_IO_H -#define CGAL_VTK_IO_H - -#include -#include - -#include -#include - - -//todo try to factorize with functors -namespace CGAL{ -// writes the appended data into the .vtu file -template -void -write_vector(std::ostream& os, - const std::vector& vect) -{ - const char* buffer = reinterpret_cast(&(vect[0])); - std::size_t size = vect.size()*sizeof(FT); - - os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded - os.write(buffer, vect.size()*sizeof(FT)); // encoded data -} - -// writes the cells tags before binary data is appended - -template -void -write_cells_tag_2(std::ostream& os, - const CDT & tr, - std::size_t number_of_triangles, - std::map & V, - bool binary, - std::size_t& offset) -{ - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (3 * number_of_triangles + 1) * sizeof(std::size_t); - // 3 indices (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(typename CDT::Finite_faces_iterator - fit = tr.finite_faces_begin(), - end = tr.finite_faces_end(); - fit != end; ++fit) - { - if(fit->is_in_domain()) - { - os << V[fit->vertex(0)] << " "; - os << V[fit->vertex(2)] << " "; - os << V[fit->vertex(1)] << " "; - } - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (number_of_triangles + 1) * sizeof(std::size_t); - // 1 offset (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t cells_offset = 0; - for(typename CDT::Finite_faces_iterator fit = - tr.finite_faces_begin() ; - fit != tr.finite_faces_end() ; - ++fit ) - { - if(fit->is_in_domain()) - { - cells_offset += 3; - os << cells_offset << " "; - } - } - os << " \n"; - } - - // Write cell type (triangles == 5) - os << " \n"; - offset += number_of_triangles + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(typename CDT::Finite_faces_iterator fit = - tr.finite_faces_begin() ; - fit != tr.finite_faces_end() ; - ++fit ) - { - if(fit->is_in_domain()) - { - os << "5 "; - } - } - os << " \n"; - } - os << " \n"; -} - -template -void -write_cells_tag(std::ostream& os, - const C3T3 & c3t3, - std::map & V, - bool binary, - std::size_t& offset) -{ - typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); - // 4 indices (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - for (int i=0; i<4; i++) - os << V[cit->vertex(i)] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); - // 1 offset (size_t) per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t cells_offset = 0; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - cells_offset += 4; - os << cells_offset << " "; - } - os << " \n"; - } - - // Write cell type (tetrahedra == 10) - os << " \n"; - offset += c3t3.number_of_cells() + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - os << "10 "; - os << " \n"; - } - os << " \n"; -} - -// writes the cells appended data at the end of the .vtu file -template -void -write_cells_2(std::ostream& os, - const CDT & tr, - std::size_t number_of_triangles, - std::map & V) -{ - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(number_of_triangles,5); // triangles == 5 - - std::size_t off = 0; - for(typename CDT::Finite_faces_iterator - fit = tr.finite_faces_begin(), - end = tr.finite_faces_end(); - fit != end; ++fit) - { - if(fit->is_in_domain()) - { - off += 3; - offsets.push_back(off); - connectivity_table.push_back(V[fit->vertex(0)]); - connectivity_table.push_back(V[fit->vertex(2)]); - connectivity_table.push_back(V[fit->vertex(1)]); - } - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} - - -template -void -write_cells(std::ostream& os, - const C3T3 & c3t3, - std::map & V, - std::vector& mids) -{ - typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 - - std::size_t off = 0; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - off += 4; - offsets.push_back(off); - for (int i=0; i<4; i++) - connectivity_table.push_back(V[cit->vertex(i)]); - mids.push_back(cit->subdomain_index()); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} - -// writes the polys appended data at the end of the .vtp file -template -void -write_polys(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(num_faces(mesh),5); // triangle == 5 - - std::size_t off = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - off += 3; - offsets.push_back(off); - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(V[v]); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} -//todo use named params for maps -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); - // 3 indices (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << V[v] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (num_faces(mesh) + 1) * sizeof(std::size_t); - // 1 offset (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t polys_offset = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - polys_offset += 3; - os << polys_offset << " "; - } - os << " \n"; - } - - // Write cell type (triangle == 5) - os << " \n"; - offset += num_faces(mesh) + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(std::size_t i = 0; i< num_faces(mesh); ++i) - os << "5 "; - os << " \n"; - } - os << " \n"; -} -// writes the points tags before binary data is appended -template -void -write_points_tag(std::ostream& os, - const Tr & tr, - std::map & V, - bool binary, - std::size_t& offset, - std::size_t dim = 3) -{ - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - std::size_t inum = 0; - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); - // dim coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - V[vit] = inum++; - os << vit->point()[0] << " "; - os << vit->point()[1] << " "; - if(dim == 3) - os << vit->point()[2] << " "; - else - os << 0.0 << " "; - } - os << " \n"; - } - os << " \n"; -} - -//todo : use namedparams for points and ids -//overload for facegraph -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); - // 3 coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " - << get(vpm, *vit).z() << " "; - } - os << " \n"; - } - os << " \n"; -} - -// writes the points appended data at the end of the .vtu file -template -void -write_points(std::ostream& os, - const Tr & tr, - std::map & V, - std::size_t dim = 3) -{ - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - std::size_t inum = 0; - std::vector coordinates; - for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - V[vit] = inum++; // binary output => the map has not been filled yet - coordinates.push_back(vit->point()[0]); - coordinates.push_back(vit->point()[1]); - coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0); - } - write_vector(os,coordinates); -} - -// writes the points appended data at the end of the .vtp file -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector coordinates; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - coordinates.push_back(get(vpm, *vit).x()); - coordinates.push_back(get(vpm, *vit).y()); - coordinates.push_back(get(vpm, *vit).z()); - } - write_vector(os,coordinates); -} -// writes the attribute tags before binary data is appended -template -void -write_attribute_tag(std::ostream& os, - const std::string& attr_name, - const std::vector& attribute, - bool binary, - std::size_t& offset) -{ - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; - os << " \n"; - offset += attribute.size() * sizeof(T) + sizeof(std::size_t); - } - else { - typedef typename std::vector::const_iterator Iterator; - os << "\">\n"; - for (Iterator it = attribute.begin(); - it != attribute.end(); - ++it ) - os << *it << " "; - os << " \n"; - } -} - -// writes the attributes appended data at the end of the .vtu file -template -void -write_attributes(std::ostream& os, - const std::vector& att) -{ - write_vector(os,att); -} - -//public API - -//! -//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp -//! XML format. -//! -//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. -//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" -//! -//! \param os a `std::ostream`. -//! \param mesh an instance of `TriangleMesh` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the -//! ones listed below -//! -//! \cgalNamedParamsBegin -//! \cgalParamBegin{vertex_point_map} the property map with the points associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalNamedParamsEnd -template -void write_polydata(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np) -{ - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - std::size_t offset = 0; - write_points_tag(os,mesh,binary,offset, np); - write_polys_tag(os,mesh,binary,offset, np); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_polys_points(os,mesh, np); - write_polys(os,mesh, np); - } - os << "\n"; -} - -template -void write_polydata(std::ostream& os, - const TriangleMesh& mesh, - bool binary = true) -{ - write_polydata(os, mesh, binary, CGAL::parameters::all_default()); -} - -//! -//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu -//! XML format. -//! -//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. -//! -//! \param os a `std::ostream`. -//! \param c3t3 an instance of `C3T3` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! -template -void write_unstructured_grid_3(std::ostream& os, - const C3T3& c3t3) -{ - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Vertex_handle Vertex_handle; - const Tr& tr = c3t3.triangulation(); - std::map V; - //write header - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - bool binary = true; - std::size_t offset = 0; - write_points_tag(os,tr,V,binary,offset); - write_cells_tag(os,c3t3,V,binary,offset); - std::vector mids; - os << " \n"; - write_attribute_tag(os,"MeshDomain",mids,binary,offset); - os << " \n"; - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_points(os,tr,V); // write points before cells to fill the std::map V - write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag - write_attributes(os,mids); - } - os << "\n"; -} - -template -void write_unstructured_grid_2(std::ostream& os, - const CDT& tr, - bool binary = true) -{ - typedef typename CDT::Vertex_handle Vertex_handle; - std::map V; - //write header - os << "\n" - << "\n" - << " " << "\n"; - - int number_of_triangles = 0; - for(typename CDT::Finite_faces_iterator - fit = tr.finite_faces_begin(), - end = tr.finite_faces_end(); - fit != end; ++fit) - { - if(fit->is_in_domain()) ++number_of_triangles; - } - os << " \n"; - std::size_t offset = 0; - write_points_tag(os,tr,V,binary,offset, 2); - write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_points(os,tr,V, 2); // write points before cells to fill the std::map V - write_cells_2(os,tr, number_of_triangles, V); - } - os << "\n"; -} - -} //end CGAL -#endif // CGAL_VTK_IO_H From 99832879edf0d3f8aa29c515f599aea2f39109e9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 4 Oct 2018 14:08:52 +0200 Subject: [PATCH 008/186] Add missing files --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 298 +++++++++++++++ Mesh_3/include/CGAL/IO/vtk_io.h | 600 ++++++++++++++++++++++++++++++ 2 files changed, 898 insertions(+) create mode 100644 Mesh_2/include/CGAL/IO/vtk_io_2.h create mode 100644 Mesh_3/include/CGAL/IO/vtk_io.h diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h new file mode 100644 index 00000000000..2b4f38b1ade --- /dev/null +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -0,0 +1,298 @@ +// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). +// Copyright (c) 2009 INRIA Sophia-Antipolis (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$ +// +// +// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno + +#ifndef CGAL_VTK_IO_H +#define CGAL_VTK_IO_H + +#include +#include + +//todo try to factorize with functors +namespace CGAL{ +// writes the appended data into the .vtu file +template +void +write_vector(std::ostream& os, + const std::vector& vect) +{ + const char* buffer = reinterpret_cast(&(vect[0])); + std::size_t size = vect.size()*sizeof(FT); + + os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded + os.write(buffer, vect.size()*sizeof(FT)); // encoded data +} + +// writes the cells tags before binary data is appended + +template +void +write_cells_tag_2(std::ostream& os, + const CDT & tr, + std::size_t number_of_triangles, + std::map & V, + bool binary, + std::size_t& offset) +{ + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * number_of_triangles + 1) * sizeof(std::size_t); + // 3 indices (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) + { + os << V[fit->vertex(0)] << " "; + os << V[fit->vertex(2)] << " "; + os << V[fit->vertex(1)] << " "; + } + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (number_of_triangles + 1) * sizeof(std::size_t); + // 1 offset (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t cells_offset = 0; + for(typename CDT::Finite_faces_iterator fit = + tr.finite_faces_begin() ; + fit != tr.finite_faces_end() ; + ++fit ) + { + if(fit->is_in_domain()) + { + cells_offset += 3; + os << cells_offset << " "; + } + } + os << " \n"; + } + + // Write cell type (triangles == 5) + os << " \n"; + offset += number_of_triangles + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(typename CDT::Finite_faces_iterator fit = + tr.finite_faces_begin() ; + fit != tr.finite_faces_end() ; + ++fit ) + { + if(fit->is_in_domain()) + { + os << "5 "; + } + } + os << " \n"; + } + os << " \n"; +} + +// writes the cells appended data at the end of the .vtu file +template +void +write_cells_2(std::ostream& os, + const CDT & tr, + std::size_t number_of_triangles, + std::map & V) +{ + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(number_of_triangles,5); // triangles == 5 + + std::size_t off = 0; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) + { + off += 3; + offsets.push_back(off); + connectivity_table.push_back(V[fit->vertex(0)]); + connectivity_table.push_back(V[fit->vertex(2)]); + connectivity_table.push_back(V[fit->vertex(1)]); + } + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} + +// writes the points tags before binary data is appended +template +void +write_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) +{ + std::size_t dim = 2; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + // dim coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; + os << vit->point()[0] << " "; + os << vit->point()[1] << " "; + if(dim == 3) + os << vit->point()[2] << " "; + else + os << 0.0 << " "; + } + os << " \n"; + } + os << " \n"; +} + +// writes the points appended data at the end of the .vtu file +template +void +write_points(std::ostream& os, + const Tr & tr, + std::map & V) +{ + std::size_t dim = 2; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::vector coordinates; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; // binary output => the map has not been filled yet + coordinates.push_back(vit->point()[0]); + coordinates.push_back(vit->point()[1]); + coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0); + } + write_vector(os,coordinates); +} + + +template +void write_unstructured_grid_2(std::ostream& os, + const CDT& tr, + bool binary = true) +{ + typedef typename CDT::Vertex_handle Vertex_handle; + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + int number_of_triangles = 0; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) ++number_of_triangles; + } + os << " \n"; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset); + write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V); // write points before cells to fill the std::map V + write_cells_2(os,tr, number_of_triangles, V); + } + os << "\n"; +} + +} //end CGAL +#endif // CGAL_VTK_IO_H diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h new file mode 100644 index 00000000000..012e85d4096 --- /dev/null +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -0,0 +1,600 @@ +// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). +// Copyright (c) 2009 INRIA Sophia-Antipolis (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$ +// +// +// Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno + +#ifndef CGAL_VTK_IO_H +#define CGAL_VTK_IO_H + +#include +#include + +#include +#include + + +//todo try to factorize with functors +namespace CGAL{ +// writes the appended data into the .vtu file +template +void +write_vector(std::ostream& os, + const std::vector& vect) +{ + const char* buffer = reinterpret_cast(&(vect[0])); + std::size_t size = vect.size()*sizeof(FT); + + os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded + os.write(buffer, vect.size()*sizeof(FT)); // encoded data +} + +template +void +write_cells_tag(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + bool binary, + std::size_t& offset) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 4 indices (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + for (int i=0; i<4; i++) + os << V[cit->vertex(i)] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); + // 1 offset (size_t) per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t cells_offset = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + cells_offset += 4; + os << cells_offset << " "; + } + os << " \n"; + } + + // Write cell type (tetrahedra == 10) + os << " \n"; + offset += c3t3.number_of_cells() + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + os << "10 "; + os << " \n"; + } + os << " \n"; +} + + +template +void +write_cells(std::ostream& os, + const C3T3 & c3t3, + std::map & V, + std::vector& mids) +{ + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 + + std::size_t off = 0; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + off += 4; + offsets.push_back(off); + for (int i=0; i<4; i++) + connectivity_table.push_back(V[cit->vertex(i)]); + mids.push_back(cit->subdomain_index()); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} + +// writes the polys appended data at the end of the .vtp file +template +void +write_polys(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(mesh),5); // triangle == 5 + + std::size_t off = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} +//todo use named params for maps +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(mesh) + 1) * sizeof(std::size_t); + // 1 offset (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t polys_offset = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(mesh) + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(std::size_t i = 0; i< num_faces(mesh); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} +// writes the points tags before binary data is appended +template +void +write_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) +{ + std::size_t dim = 3; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + // dim coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; + os << vit->point()[0] << " "; + os << vit->point()[1] << " "; + if(dim == 3) + os << vit->point()[2] << " "; + else + os << 0.0 << " "; + } + os << " \n"; + } + os << " \n"; +} + +//todo : use namedparams for points and ids +//overload for facegraph +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " + << get(vpm, *vit).z() << " "; + } + os << " \n"; + } + os << " \n"; +} + +// writes the points appended data at the end of the .vtu file +template +void +write_points(std::ostream& os, + const Tr & tr, + std::map & V) +{ + std::size_t dim = 3; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + std::size_t inum = 0; + std::vector coordinates; + for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + V[vit] = inum++; // binary output => the map has not been filled yet + coordinates.push_back(vit->point()[0]); + coordinates.push_back(vit->point()[1]); + coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0); + } + write_vector(os,coordinates); +} + +// writes the points appended data at the end of the .vtp file +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector coordinates; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + coordinates.push_back(get(vpm, *vit).x()); + coordinates.push_back(get(vpm, *vit).y()); + coordinates.push_back(get(vpm, *vit).z()); + } + write_vector(os,coordinates); +} +// writes the attribute tags before binary data is appended +template +void +write_attribute_tag(std::ostream& os, + const std::string& attr_name, + const std::vector& attribute, + bool binary, + std::size_t& offset) +{ + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; + os << " \n"; + offset += attribute.size() * sizeof(T) + sizeof(std::size_t); + } + else { + typedef typename std::vector::const_iterator Iterator; + os << "\">\n"; + for (Iterator it = attribute.begin(); + it != attribute.end(); + ++it ) + os << *it << " "; + os << " \n"; + } +} + +// writes the attributes appended data at the end of the .vtu file +template +void +write_attributes(std::ostream& os, + const std::vector& att) +{ + write_vector(os,att); +} + +//public API + +//! +//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp +//! XML format. +//! +//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. +//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +//! +//! \param os a `std::ostream`. +//! \param mesh an instance of `TriangleMesh` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the +//! ones listed below +//! +//! \cgalNamedParamsBegin +//! \cgalParamBegin{vertex_point_map} the property map with the points associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalNamedParamsEnd +template +void write_polydata(std::ostream& os, + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np) +{ + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + std::size_t offset = 0; + write_points_tag(os,mesh,binary,offset, np); + write_polys_tag(os,mesh,binary,offset, np); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_polys_points(os,mesh, np); + write_polys(os,mesh, np); + } + os << "\n"; +} + +template +void write_polydata(std::ostream& os, + const TriangleMesh& mesh, + bool binary = true) +{ + write_polydata(os, mesh, binary, CGAL::parameters::all_default()); +} + +//! +//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu +//! XML format. +//! +//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. +//! +//! \param os a `std::ostream`. +//! \param c3t3 an instance of `C3T3` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! +template +void write_unstructured_grid_3(std::ostream& os, + const C3T3& c3t3) +{ + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + const Tr& tr = c3t3.triangulation(); + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + bool binary = true; + std::size_t offset = 0; + write_points_tag(os,tr,V,binary,offset); + write_cells_tag(os,c3t3,V,binary,offset); + std::vector mids; + os << " \n"; + write_attribute_tag(os,"MeshDomain",mids,binary,offset); + os << " \n"; + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_points(os,tr,V); // write points before cells to fill the std::map V + write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag + write_attributes(os,mids); + } + os << "\n"; +} + +} //end CGAL +#endif // CGAL_VTK_IO_H From 0c800d58308b017aa83140c41a4de33083e3602b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 5 Oct 2018 11:48:46 +0200 Subject: [PATCH 009/186] Add SPDX stuff --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 1 + Mesh_3/include/CGAL/IO/vtk_io.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 2b4f38b1ade..3544142f13f 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -16,6 +16,7 @@ // // $URL$ // $Id$ +// SPDX-License-Identifier: GPL-3.0+ // // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index 012e85d4096..969a9a20be2 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -16,7 +16,7 @@ // // $URL$ // $Id$ -// +// SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno From e8cf3f319283f683f3fa682183d18ef5ff719ce2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 5 Oct 2018 17:09:43 +0200 Subject: [PATCH 010/186] add license includes --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 3 +++ Mesh_3/include/CGAL/IO/vtk_io.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 3544142f13f..59b2d5f1ee9 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -27,6 +27,9 @@ #include #include +#include + + //todo try to factorize with functors namespace CGAL{ // writes the appended data into the .vtu file diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index 969a9a20be2..c062294419c 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -23,6 +23,9 @@ #ifndef CGAL_VTK_IO_H #define CGAL_VTK_IO_H +#include + + #include #include From b380bd8b319d030aaadbaff699dace5ea29e5df8 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 8 Oct 2018 16:25:51 +0200 Subject: [PATCH 011/186] Doc for write_unstructured_grid_2 --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 59b2d5f1ee9..f2551ad9d4d 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -250,7 +250,17 @@ write_points(std::ostream& os, write_vector(os,coordinates); } - +//! +//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu +//! XML format. +//! +//! \tparam CDT a `Constrained_Delaunay_triangulation_2`. +//! +//! \param os a `std::ostream`. +//! \param cdt an instance of `CDT` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! template void write_unstructured_grid_2(std::ostream& os, const CDT& tr, From 9c1ecd1a43d8cd394f74efae8d95191dd87de811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 9 Oct 2018 14:30:30 +0200 Subject: [PATCH 012/186] use exact rational everywhere --- .../test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp | 3 +-- .../test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp | 3 +-- .../test_sdg_linf_hierarchy_2_et.cpp | 3 +-- .../test_sdg_linf_hierarchy_2_ft.cpp | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp index a53b491851c..43c4de102d9 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_et.cpp @@ -11,10 +11,9 @@ #include #include -#include // choose number type -typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_ring_t; typedef CGAL::Exact_rational exact_field_t; namespace CGAL { diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp index 1030d7a135b..961eaa43605 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_2_ft.cpp @@ -11,10 +11,9 @@ #include #include -#include // choose number type -typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_ring_t; typedef CGAL::Exact_rational exact_field_t; #include diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp index 50a1bdd0e34..8b9733164a2 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_et.cpp @@ -11,10 +11,9 @@ #include #include -#include // choose number type -typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_ring_t; typedef CGAL::Exact_rational exact_field_t; namespace CGAL { diff --git a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp index 3e16425979c..ed6565c1997 100644 --- a/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp +++ b/Segment_Delaunay_graph_Linf_2/test/Segment_Delaunay_graph_Linf_2/test_sdg_linf_hierarchy_2_ft.cpp @@ -11,10 +11,9 @@ #include #include -#include // choose number type -typedef CGAL::Exact_integer exact_ring_t; +typedef CGAL::Exact_rational exact_ring_t; typedef CGAL::Exact_rational exact_field_t; #include From 14c526a37815adb4254904cd8b4779614bc783e6 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 9 Oct 2018 14:42:42 +0200 Subject: [PATCH 013/186] Add constrained edges to vtu output for cdt --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 31 +++++++++++++++++++++++++++---- Mesh_3/include/CGAL/IO/vtk_io.h | 12 ++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index f2551ad9d4d..22e34aed107 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -73,8 +73,11 @@ write_cells_tag_2(std::ostream& os, if (binary) { // if binary output, just write the xml tag os << " offset=\"" << offset << "\"/>\n"; + // 3 indices (size_t) per triangle + length of the encoded data (size_t) offset += (3 * number_of_triangles + 1) * sizeof(std::size_t); - // 3 indices (size_t) per cell + length of the encoded data (size_t) + // 2 indices (size_t) per edge (size_t) + offset += (2 * std::distance(tr.constrained_edges_begin(), + tr.constrained_edges_end())) * sizeof(std::size_t); } else { os << "\">\n"; @@ -99,7 +102,9 @@ write_cells_tag_2(std::ostream& os, if (binary) { // if binary output, just write the xml tag os << " offset=\"" << offset << "\"/>\n"; - offset += (number_of_triangles + 1) * sizeof(std::size_t); + offset += (number_of_triangles +std::distance(tr.constrained_edges_begin(), + tr.constrained_edges_end()) + 1) + * sizeof(std::size_t); // 1 offset (size_t) per cell + length of the encoded data (size_t) } else { @@ -125,7 +130,10 @@ write_cells_tag_2(std::ostream& os, if (binary) { os << " offset=\"" << offset << "\"/>\n"; - offset += number_of_triangles + sizeof(std::size_t); + offset += number_of_triangles + + std::distance(tr.constrained_edges_begin(), + tr.constrained_edges_end()) + + sizeof(std::size_t); // 1 unsigned char per cell + length of the encoded data (size_t) } else { @@ -156,6 +164,8 @@ write_cells_2(std::ostream& os, std::vector connectivity_table; std::vector offsets; std::vector cell_type(number_of_triangles,5); // triangles == 5 + cell_type.resize(cell_type.size() + std::distance(tr.constrained_edges_begin(), + tr.constrained_edges_end()), 3); // line == 3 std::size_t off = 0; for(typename CDT::Finite_faces_iterator @@ -172,6 +182,19 @@ write_cells_2(std::ostream& os, connectivity_table.push_back(V[fit->vertex(1)]); } } + for(typename CDT::Constrained_edges_iterator + cei = tr.constrained_edges_begin(), + end = tr.constrained_edges_end(); + cei != end; ++cei) + { + off += 2; + offsets.push_back(off); + for(int i=0; i<3; ++i) + { + if(i != cei->second) + connectivity_table.push_back(V[cei->first->vertex(i)]); + } + } write_vector(os,connectivity_table); write_vector(os,offsets); write_vector(os,cell_type); @@ -294,7 +317,7 @@ void write_unstructured_grid_2(std::ostream& os, if(fit->is_in_domain()) ++number_of_triangles; } os << " \n"; + << "\" NumberOfCells=\"" << number_of_triangles + std::distance(tr.constrained_edges_begin(), tr.constrained_edges_end()) << "\">\n"; std::size_t offset = 0; write_points_tag(os,tr,V,binary,offset); write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index c062294419c..9029f304e53 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -80,12 +80,12 @@ write_cells_tag(std::ostream& os, else { os << "\">\n"; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) - { - for (int i=0; i<4; i++) - os << V[cit->vertex(i)] << " "; - } + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + for (int i=0; i<4; i++) + os << V[cit->vertex(i)] << " "; + } os << " \n"; } From 9e929e39a01e335c64e2470cda64a692640344b4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 9 Oct 2018 14:49:08 +0200 Subject: [PATCH 014/186] Clarifies the doc --- Mesh_2/include/CGAL/IO/vtk_io_2.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 22e34aed107..962b7b9ee26 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -275,7 +275,9 @@ write_points(std::ostream& os, //! //! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu -//! XML format. +//! XML format. +//! +//! The triangles inside the domain and the constrained edges will be outputted. //! //! \tparam CDT a `Constrained_Delaunay_triangulation_2`. //! From 63488d81d1c793ad6c30d00ed44ad51f320067ef Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 29 Oct 2018 12:59:44 +0100 Subject: [PATCH 015/186] Update Changes and doc --- Installation/CHANGES.md | 7 ++++ Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h | 19 ++++++++++ Mesh_2/doc/Mesh_2/PackageDescription.txt | 1 + Mesh_2/include/CGAL/IO/vtk_io_2.h | 14 +------ Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 47 ++++++++++++++++++++++++ Mesh_3/doc/Mesh_3/Doxyfile.in | 14 +++++++ Mesh_3/doc/Mesh_3/PackageDescription.txt | 2 + Mesh_3/include/CGAL/IO/vtk_io.h | 36 +----------------- 8 files changed, 92 insertions(+), 48 deletions(-) create mode 100644 Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h create mode 100644 Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fcd898c453f..7e65f197641 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -20,6 +20,13 @@ Release date: March 2019 - `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycle()` - `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles()` +### 2D and 3D Mesh Generation +- Added 3 functions for writing in modern VTK formats: + -`CGAL::write_unstructured_grid_3(std::ostream& os, const C3T3& c3t3)` + -`CGAL::write_unstructured_grid_2(std::ostream& os, const CDT& tr, bool binary = true)` + -`CGAL::write_polydata(std::ostream& os, const TriangleMesh& mesh, bool binary, const NamedParameters& np)` + + Release 4.13 ------------ diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h new file mode 100644 index 00000000000..1ca341b743e --- /dev/null +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h @@ -0,0 +1,19 @@ +namespace CGAL{ +//!\ingroup PkgMesh2 +//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu +//! XML format. +//! +//! The triangles inside the domain and the constrained edges will be outputted. +//! +//! \tparam CDT a `Constrained_Delaunay_triangulation_2`. +//! +//! \param os a `std::ostream`. +//! \param tr an instance of `CDT` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! +template +void write_unstructured_grid_2(std::ostream& os, + const CDT& tr, + bool binary = true); +} diff --git a/Mesh_2/doc/Mesh_2/PackageDescription.txt b/Mesh_2/doc/Mesh_2/PackageDescription.txt index 79733d285b8..dd5e859cbfd 100644 --- a/Mesh_2/doc/Mesh_2/PackageDescription.txt +++ b/Mesh_2/doc/Mesh_2/PackageDescription.txt @@ -57,6 +57,7 @@ The package can handle intersecting input constraints and set no restriction on - `CGAL::make_conforming_Gabriel_2` - `CGAL::refine_Delaunay_mesh_2` - `CGAL::lloyd_optimize_mesh_2` +- `CGAL::write_unstructured_grid_2()` ## Enumerations ## - `CGAL::Mesh_optimization_return_code` diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 962b7b9ee26..1ad09ee3aad 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -273,19 +273,7 @@ write_points(std::ostream& os, write_vector(os,coordinates); } -//! -//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu -//! XML format. -//! -//! The triangles inside the domain and the constrained edges will be outputted. -//! -//! \tparam CDT a `Constrained_Delaunay_triangulation_2`. -//! -//! \param os a `std::ostream`. -//! \param cdt an instance of `CDT` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! + template void write_unstructured_grid_2(std::ostream& os, const CDT& tr, diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h new file mode 100644 index 00000000000..6c10de585c8 --- /dev/null +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -0,0 +1,47 @@ +namespace CGAL{ +//! \ingroup PkgMesh_3IOFunctions +//! +//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp +//! XML format. +//! +//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. +//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +//! +//! \param os a `std::ostream`. +//! \param mesh an instance of `TriangleMesh` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the +//! ones listed below +//! +//! \cgalNamedParamsBegin +//! \cgalParamBegin{vertex_point_map} the property map with the points associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalNamedParamsEnd +template +void write_polydata(std::ostream& os, + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np); + +//! \ingroup PkgMesh_3IOFunctions +//! +//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu +//! XML format. +//! +//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. +//! +//! \param os a `std::ostream`. +//! \param c3t3 an instance of `C3T3` to be written. +//! +template +void write_unstructured_grid_3(std::ostream& os, + const C3T3& c3t3); +} diff --git a/Mesh_3/doc/Mesh_3/Doxyfile.in b/Mesh_3/doc/Mesh_3/Doxyfile.in index 0a6229c8c69..eafd3c94e7a 100644 --- a/Mesh_3/doc/Mesh_3/Doxyfile.in +++ b/Mesh_3/doc/Mesh_3/Doxyfile.in @@ -1,5 +1,19 @@ @INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} +# macros to be used inside the code +ALIASES += "cgalNamedParamsBegin=
Named Parameters
" +ALIASES += "cgalNamedParamsEnd=
" +ALIASES += "cgalParamBegin{1}=\ref PMP_\1 \"\1\"" +ALIASES += "cgalParamEnd=" +ALIASES += "cgalDescribePolylineType=A polyline is defined as a sequence of points, each pair of contiguous points defines a segment of the polyline. If the first and last points of the polyline are identical, the polyline is closed." + +#macros for NamedParameters.txt +ALIASES += "cgalNPTableBegin=
" +ALIASES += "cgalNPTableEnd=
" +ALIASES += "cgalNPBegin{1}=\1 " +ALIASES += "cgalNPEnd=" + + INPUT += \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Polyhedral_complex_mesh_domain_3.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Mesh_domain_with_polyline_features_3.h diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index 791b9c7894b..c5eda2eac45 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -139,6 +139,8 @@ and their associated classes: ## Input/Output Functions ## - `CGAL::output_to_medit()` +- `CGAL::write_polydata()` +- `CGAL::write_unstructured_grid_3()` */ diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index 9029f304e53..cbba82268bc 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -472,30 +472,6 @@ write_attributes(std::ostream& os, //public API -//! -//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp -//! XML format. -//! -//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. -//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" -//! -//! \param os a `std::ostream`. -//! \param mesh an instance of `TriangleMesh` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the -//! ones listed below -//! -//! \cgalNamedParamsBegin -//! \cgalParamBegin{vertex_point_map} the property map with the points associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalNamedParamsEnd template void write_polydata(std::ostream& os, @@ -541,17 +517,7 @@ void write_polydata(std::ostream& os, write_polydata(os, mesh, binary, CGAL::parameters::all_default()); } -//! -//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu -//! XML format. -//! -//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. -//! -//! \param os a `std::ostream`. -//! \param c3t3 an instance of `C3T3` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! + template void write_unstructured_grid_3(std::ostream& os, const C3T3& c3t3) From 33a3996fa1d72557462142b19c51112c49158838 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 29 Oct 2018 15:02:20 +0100 Subject: [PATCH 016/186] Rename write_VTU and write_VTP --- .../Constrained_Delaunay_triangulation_2.cpp | 2 +- Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h | 4 ++-- Mesh_2/include/CGAL/IO/vtk_io_2.h | 2 +- Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 8 ++++---- Mesh_3/include/CGAL/IO/vtk_io.h | 8 ++++---- Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 352151640fd..9aafc882385 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -676,7 +676,7 @@ MainWindow::saveConstraints(QString fileName) output << cdt; else if (output) { - CGAL::write_unstructured_grid_2(output, cdt); + CGAL::write_VTU(output, cdt); } } diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h index 1ca341b743e..103157509d0 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h @@ -1,6 +1,6 @@ namespace CGAL{ //!\ingroup PkgMesh2 -//! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu +//! \brief writes the content of a `CDT` in the .vtu //! XML format. //! //! The triangles inside the domain and the constrained edges will be outputted. @@ -13,7 +13,7 @@ namespace CGAL{ //! or in ASCII(`false`). //! template -void write_unstructured_grid_2(std::ostream& os, +void write_VTU(std::ostream& os, const CDT& tr, bool binary = true); } diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/vtk_io_2.h index 1ad09ee3aad..160e383bcf6 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/vtk_io_2.h @@ -275,7 +275,7 @@ write_points(std::ostream& os, template -void write_unstructured_grid_2(std::ostream& os, +void write_VTU(std::ostream& os, const CDT& tr, bool binary = true) { diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index 6c10de585c8..e58dca6acc5 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -1,7 +1,7 @@ namespace CGAL{ //! \ingroup PkgMesh_3IOFunctions //! -//! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp +//! \brief writes the content of a triangulated surface mesh in the .vtp //! XML format. //! //! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. @@ -26,14 +26,14 @@ namespace CGAL{ //! \cgalNamedParamsEnd template -void write_polydata(std::ostream& os, +void write_VTP(std::ostream& os, const TriangleMesh& mesh, bool binary, const NamedParameters& np); //! \ingroup PkgMesh_3IOFunctions //! -//! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu +//! \brief writes the content of a `C3t3` in the .vtu //! XML format. //! //! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. @@ -42,6 +42,6 @@ void write_polydata(std::ostream& os, //! \param c3t3 an instance of `C3T3` to be written. //! template -void write_unstructured_grid_3(std::ostream& os, +void write_VTU(std::ostream& os, const C3T3& c3t3); } diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index cbba82268bc..ce13b4e404a 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -474,7 +474,7 @@ write_attributes(std::ostream& os, template -void write_polydata(std::ostream& os, +void write_VTP(std::ostream& os, const TriangleMesh& mesh, bool binary, const NamedParameters& np) @@ -510,16 +510,16 @@ void write_polydata(std::ostream& os, } template -void write_polydata(std::ostream& os, +void write_VTP(std::ostream& os, const TriangleMesh& mesh, bool binary = true) { - write_polydata(os, mesh, binary, CGAL::parameters::all_default()); + write_VTP(os, mesh, binary, CGAL::parameters::all_default()); } template -void write_unstructured_grid_3(std::ostream& os, +void write_VTU(std::ostream& os, const C3T3& c3t3) { typedef typename C3T3::Triangulation Tr; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 7d797ba0079..db810b5ae02 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -345,7 +345,7 @@ public: std::ofstream os(output_filename.data()); os << std::setprecision(16); //write header - CGAL::write_polydata(os, *mesh); + CGAL::write_VTP(os, *mesh); } } else @@ -359,7 +359,7 @@ public: os << std::setprecision(16); const C3t3& c3t3 = c3t3_item->c3t3(); - CGAL::write_unstructured_grid_3(os, c3t3); + CGAL::write_VTU(os, c3t3); } return true; } From 08a98a5603652df0f7c4136e315c5319def81989 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 30 Oct 2018 11:51:34 +0100 Subject: [PATCH 017/186] Update Changes.md --- Installation/CHANGES.md | 7 +++---- Mesh_2/doc/Mesh_2/PackageDescription.txt | 2 +- Mesh_3/doc/Mesh_3/PackageDescription.txt | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 7e65f197641..85e87b22d17 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,10 +21,9 @@ Release date: March 2019 - `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles()` ### 2D and 3D Mesh Generation -- Added 3 functions for writing in modern VTK formats: - -`CGAL::write_unstructured_grid_3(std::ostream& os, const C3T3& c3t3)` - -`CGAL::write_unstructured_grid_2(std::ostream& os, const CDT& tr, bool binary = true)` - -`CGAL::write_polydata(std::ostream& os, const TriangleMesh& mesh, bool binary, const NamedParameters& np)` +- Added 2 functions for writing in modern VTK formats: + -`CGAL::write_VTU()` + -`CGAL::write_VTP()` Release 4.13 diff --git a/Mesh_2/doc/Mesh_2/PackageDescription.txt b/Mesh_2/doc/Mesh_2/PackageDescription.txt index dd5e859cbfd..d76b4a3b3c4 100644 --- a/Mesh_2/doc/Mesh_2/PackageDescription.txt +++ b/Mesh_2/doc/Mesh_2/PackageDescription.txt @@ -57,7 +57,7 @@ The package can handle intersecting input constraints and set no restriction on - `CGAL::make_conforming_Gabriel_2` - `CGAL::refine_Delaunay_mesh_2` - `CGAL::lloyd_optimize_mesh_2` -- `CGAL::write_unstructured_grid_2()` +- `CGAL::write_VTU()` ## Enumerations ## - `CGAL::Mesh_optimization_return_code` diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index c5eda2eac45..060ddb44d1b 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -139,8 +139,8 @@ and their associated classes: ## Input/Output Functions ## - `CGAL::output_to_medit()` -- `CGAL::write_polydata()` -- `CGAL::write_unstructured_grid_3()` +- `CGAL::write_VTP()` +- `CGAL::write_VTU()` */ From 45b19c81349810c57bb9e114b84aa949faf5661b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 15 Nov 2018 09:28:26 +0100 Subject: [PATCH 018/186] Remove debug code --- Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index db810b5ae02..0563ee80944 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -173,7 +173,6 @@ namespace CGAL{ vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); - std::cout< vr(nb_vertices); From 6e4ab58edc23c76a99ff28d12f7c521cba2d40de Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 20 Nov 2018 15:15:53 +0100 Subject: [PATCH 019/186] Put write_vtk in Polyhedron_IO --- BGL/doc/BGL/CGAL/boost/graph/vtp_io.h | 31 ++ Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 32 -- Mesh_3/include/CGAL/IO/vtk_io.h | 265 +---------------- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 1 + Polyhedron_IO/include/CGAL/IO/vtp_io.h | 279 ++++++++++++++++++ Stream_support/include/CGAL/IO/write_vtk.h | 16 + 6 files changed, 328 insertions(+), 296 deletions(-) create mode 100644 BGL/doc/BGL/CGAL/boost/graph/vtp_io.h create mode 100644 Polyhedron_IO/include/CGAL/IO/vtp_io.h create mode 100644 Stream_support/include/CGAL/IO/write_vtk.h diff --git a/BGL/doc/BGL/CGAL/boost/graph/vtp_io.h b/BGL/doc/BGL/CGAL/boost/graph/vtp_io.h new file mode 100644 index 00000000000..6604cdc7db3 --- /dev/null +++ b/BGL/doc/BGL/CGAL/boost/graph/vtp_io.h @@ -0,0 +1,31 @@ +//!\ingroup PkgBGLIOFct +//! +//! \brief writes the content of a triangulated surface mesh in the .vtp +//! XML format. +//! +//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. +//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +//! +//! \param os a `std::ostream`. +//! \param mesh an instance of `TriangleMesh` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). +//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the +//! ones listed below +//! +//! \cgalNamedParamsBegin +//! \cgalParamBegin{vertex_point_map} the property map with the points associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to +//! the vertices of `mesh`. If this parameter is omitted, an internal property map for +//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. +//! \cgalParamEnd +//! \cgalNamedParamsEnd +template +void write_VTP(std::ostream& os, + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np); diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index e58dca6acc5..4fa0d878bcf 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -1,36 +1,4 @@ namespace CGAL{ -//! \ingroup PkgMesh_3IOFunctions -//! -//! \brief writes the content of a triangulated surface mesh in the .vtp -//! XML format. -//! -//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. -//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" -//! -//! \param os a `std::ostream`. -//! \param mesh an instance of `TriangleMesh` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the -//! ones listed below -//! -//! \cgalNamedParamsBegin -//! \cgalParamBegin{vertex_point_map} the property map with the points associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalNamedParamsEnd -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np); - //! \ingroup PkgMesh_3IOFunctions //! //! \brief writes the content of a `C3t3` in the .vtu diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index ce13b4e404a..934d494b57f 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -28,25 +28,10 @@ #include #include - -#include -#include - +#include //todo try to factorize with functors namespace CGAL{ -// writes the appended data into the .vtu file -template -void -write_vector(std::ostream& os, - const std::vector& vect) -{ - const char* buffer = reinterpret_cast(&(vect[0])); - std::size_t size = vect.size()*sizeof(FT); - - os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded - os.write(buffer, vect.size()*sizeof(FT)); // encoded data -} template void @@ -143,7 +128,6 @@ write_cells(std::ostream& os, std::vector connectivity_table; std::vector offsets; std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 - std::size_t off = 0; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; @@ -160,136 +144,7 @@ write_cells(std::ostream& os, write_vector(os,cell_type); } -// writes the polys appended data at the end of the .vtp file -template -void -write_polys(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(num_faces(mesh),5); // triangle == 5 - - std::size_t off = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - off += 3; - offsets.push_back(off); - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(V[v]); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} -//todo use named params for maps -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); - // 3 indices (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << V[v] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (num_faces(mesh) + 1) * sizeof(std::size_t); - // 1 offset (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t polys_offset = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - polys_offset += 3; - os << polys_offset << " "; - } - os << " \n"; - } - - // Write cell type (triangle == 5) - os << " \n"; - offset += num_faces(mesh) + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(std::size_t i = 0; i< num_faces(mesh); ++i) - os << "5 "; - os << " \n"; - } - os << " \n"; -} -// writes the points tags before binary data is appended template void write_points_tag(std::ostream& os, @@ -335,51 +190,6 @@ write_points_tag(std::ostream& os, os << " \n"; } -//todo : use namedparams for points and ids -//overload for facegraph -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); - // 3 coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " - << get(vpm, *vit).z() << " "; - } - os << " \n"; - } - os << " \n"; -} - // writes the points appended data at the end of the .vtu file template void @@ -407,32 +217,6 @@ write_points(std::ostream& os, write_vector(os,coordinates); } -// writes the points appended data at the end of the .vtp file -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector coordinates; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - coordinates.push_back(get(vpm, *vit).x()); - coordinates.push_back(get(vpm, *vit).y()); - coordinates.push_back(get(vpm, *vit).z()); - } - write_vector(os,coordinates); -} // writes the attribute tags before binary data is appended template void @@ -471,53 +255,6 @@ write_attributes(std::ostream& os, } //public API - -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np) -{ - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - std::size_t offset = 0; - write_points_tag(os,mesh,binary,offset, np); - write_polys_tag(os,mesh,binary,offset, np); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_polys_points(os,mesh, np); - write_polys(os,mesh, np); - } - os << "\n"; -} - -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary = true) -{ - write_VTP(os, mesh, binary, CGAL::parameters::all_default()); -} - - template void write_VTU(std::ostream& os, const C3T3& c3t3) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 0563ee80944..d74599bd2ad 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include diff --git a/Polyhedron_IO/include/CGAL/IO/vtp_io.h b/Polyhedron_IO/include/CGAL/IO/vtp_io.h new file mode 100644 index 00000000000..2c0ec6bf152 --- /dev/null +++ b/Polyhedron_IO/include/CGAL/IO/vtp_io.h @@ -0,0 +1,279 @@ +// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). +// Copyright (c) 2009 INRIA Sophia-Antipolis (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) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno + +#ifndef CGAL_VTP_IO_H +#define CGAL_VTP_IO_H + +#include + + +#include +#include +#include + + +//todo try to factorize with functors +namespace CGAL{ +// writes the polys appended data at the end of the .vtp file +template +void +write_polys(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(mesh),5); // triangle == 5 + + std::size_t off = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} +//todo use named params for maps +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(mesh) + 1) * sizeof(std::size_t); + // 1 offset (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t polys_offset = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(mesh) + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(std::size_t i = 0; i< num_faces(mesh); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} + +//todo : use namedparams for points and ids +//overload for facegraph +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " + << get(vpm, *vit).z() << " "; + } + os << " \n"; + } + os << " \n"; +} + + +// writes the points appended data at the end of the .vtp file +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector coordinates; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + coordinates.push_back(get(vpm, *vit).x()); + coordinates.push_back(get(vpm, *vit).y()); + coordinates.push_back(get(vpm, *vit).z()); + } + write_vector(os,coordinates); +} + +//public API + +template +void write_VTP(std::ostream& os, + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np) +{ + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + std::size_t offset = 0; + write_points_tag(os,mesh,binary,offset, np); + write_polys_tag(os,mesh,binary,offset, np); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_polys_points(os,mesh, np); + write_polys(os,mesh, np); + } + os << "\n"; +} + +template +void write_VTP(std::ostream& os, + const TriangleMesh& mesh, + bool binary = true) +{ + write_VTP(os, mesh, binary, CGAL::parameters::all_default()); +} + +} //end CGAL +#endif // CGAL_VTP_IO_H diff --git a/Stream_support/include/CGAL/IO/write_vtk.h b/Stream_support/include/CGAL/IO/write_vtk.h new file mode 100644 index 00000000000..38a5c21e288 --- /dev/null +++ b/Stream_support/include/CGAL/IO/write_vtk.h @@ -0,0 +1,16 @@ +#ifndef CGAL_WRITE_VTK_IO_H +#define CGAL_WRITE_VTK_IO_H +#include +#include +template +void +write_vector(std::ostream& os, + const std::vector& vect) +{ + const char* buffer = reinterpret_cast(&(vect[0])); + std::size_t size = vect.size()*sizeof(FT); + + os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded + os.write(buffer, vect.size()*sizeof(FT)); // encoded data +} +#endif From 51808762906fa39a59b4482e1a6a614ac565d5aa Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 21 Nov 2018 10:48:16 +0100 Subject: [PATCH 020/186] Fix ambiguity between 2D and 3D write_VTU and restore gone bool binary in write_VTU 3D --- .../Triangulation_2/Constrained_Delaunay_triangulation_2.cpp | 2 +- Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h | 2 +- Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 5 ++++- Mesh_3/include/CGAL/IO/vtk_io.h | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 9aafc882385..28d30aee065 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -676,7 +676,7 @@ MainWindow::saveConstraints(QString fileName) output << cdt; else if (output) { - CGAL::write_VTU(output, cdt); + CGAL::write_VTU_2D(output, cdt); } } diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h index 103157509d0..d2e4f2baa54 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h @@ -13,7 +13,7 @@ namespace CGAL{ //! or in ASCII(`false`). //! template -void write_VTU(std::ostream& os, +void write_VTU_2D(std::ostream& os, const CDT& tr, bool binary = true); } diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index 4fa0d878bcf..42e2d301617 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -8,8 +8,11 @@ namespace CGAL{ //! //! \param os a `std::ostream`. //! \param c3t3 an instance of `C3T3` to be written. +//! \param binary decides if the data should be written in binary(`true`) +//! or in ASCII(`false`). //! template void write_VTU(std::ostream& os, - const C3T3& c3t3); + const C3T3& c3t3, + bool binary = true); } diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index 934d494b57f..59668f0a2aa 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -257,7 +257,8 @@ write_attributes(std::ostream& os, //public API template void write_VTU(std::ostream& os, - const C3T3& c3t3) + const C3T3& c3t3, + bool binary = true) { typedef typename C3T3::Triangulation Tr; typedef typename Tr::Vertex_handle Vertex_handle; @@ -282,7 +283,6 @@ void write_VTU(std::ostream& os, os << " \n"; - bool binary = true; std::size_t offset = 0; write_points_tag(os,tr,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); From 7b13f4a969fac3a0f583520108d5a9ad04ad8848 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 23 Nov 2018 10:11:23 +0100 Subject: [PATCH 021/186] Add misisng license header, rename vtu functions and update change.md --- BGL/doc/BGL/PackageDescription.txt | 1 + .../Constrained_Delaunay_triangulation_2.cpp | 2 +- Installation/CHANGES.md | 3 ++- Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h | 6 +++--- Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 2 +- Mesh_3/doc/Mesh_3/PackageDescription.txt | 4 +--- Mesh_3/include/CGAL/IO/vtk_io.h | 2 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 2 +- Stream_support/include/CGAL/IO/write_vtk.h | 21 +++++++++++++++++++ 9 files changed, 32 insertions(+), 11 deletions(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 6ba2f1ba2d6..9191c619c58 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -708,6 +708,7 @@ user might encounter. ## I/O Functions ## - \link PkgBGLIOFct CGAL::read_off() \endlink - \link PkgBGLIOFct CGAL::write_off() \endlink +- `CGAL::write_VTP()` */ diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 28d30aee065..9aafc882385 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -676,7 +676,7 @@ MainWindow::saveConstraints(QString fileName) output << cdt; else if (output) { - CGAL::write_VTU_2D(output, cdt); + CGAL::write_VTU(output, cdt); } } diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 444b6b73fe0..20b61b4128d 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -55,7 +55,8 @@ Release date: March 2019 `Arr_polycurve_basic_traits_2`. ### 2D and 3D Mesh Generation -- Added 2 functions for writing in modern VTK formats: +- Added 3 functions for writing in modern VTK formats: + -`CGAL::output_to_vtu()` -`CGAL::write_VTU()` -`CGAL::write_VTP()` diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h index d2e4f2baa54..27c2dce50c4 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h @@ -13,7 +13,7 @@ namespace CGAL{ //! or in ASCII(`false`). //! template -void write_VTU_2D(std::ostream& os, - const CDT& tr, - bool binary = true); +void write_VTU(std::ostream& os, + const CDT& tr, + bool binary = true); } diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index 42e2d301617..a1727dec86d 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -12,7 +12,7 @@ namespace CGAL{ //! or in ASCII(`false`). //! template -void write_VTU(std::ostream& os, +void output_to_vtu(std::ostream& os, const C3T3& c3t3, bool binary = true); } diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index e38a5da4d56..d67297572cd 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -139,8 +139,6 @@ and their associated classes: ## Input/Output Functions ## - `CGAL::output_to_medit()` -- `CGAL::write_VTP()` -- `CGAL::write_VTU()` - +- `CGAL::output_to_vtu()` */ diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/vtk_io.h index 59668f0a2aa..182a8b2cb7d 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/vtk_io.h @@ -256,7 +256,7 @@ write_attributes(std::ostream& os, //public API template -void write_VTU(std::ostream& os, +void output_to_vtu(std::ostream& os, const C3T3& c3t3, bool binary = true) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 01434d774f5..79ea93e2da2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -343,7 +343,7 @@ public: os << std::setprecision(16); const C3t3& c3t3 = c3t3_item->c3t3(); - CGAL::write_VTU(os, c3t3); + CGAL::output_to_vtu(os, c3t3); } return true; } diff --git a/Stream_support/include/CGAL/IO/write_vtk.h b/Stream_support/include/CGAL/IO/write_vtk.h index 38a5c21e288..5d702e27d92 100644 --- a/Stream_support/include/CGAL/IO/write_vtk.h +++ b/Stream_support/include/CGAL/IO/write_vtk.h @@ -1,3 +1,24 @@ +// 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 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) : Stephane Tayeb + #ifndef CGAL_WRITE_VTK_IO_H #define CGAL_WRITE_VTK_IO_H #include From e05feea350baea0c379d71922d0f9f8916827598 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 23 Nov 2018 10:42:47 +0100 Subject: [PATCH 022/186] Fix doc --- BGL/doc/BGL/PackageDescription.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 9191c619c58..b76ff169a8f 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -708,7 +708,7 @@ user might encounter. ## I/O Functions ## - \link PkgBGLIOFct CGAL::read_off() \endlink - \link PkgBGLIOFct CGAL::write_off() \endlink -- `CGAL::write_VTP()` +- \link PkgBGLIOFct `CGAL::write_VTP()` \endlink */ From 756eeb7cdef053a660728c5cee23a26504709f08 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 29 Nov 2018 12:23:52 +0100 Subject: [PATCH 023/186] move vtp_io.h in BGL --- BGL/doc/BGL/CGAL/{boost/graph => IO}/vtp_io.h | 0 BGL/doc/BGL/Doxyfile.in | 2 ++ {Polyhedron_IO => BGL}/include/CGAL/IO/vtp_io.h | 0 3 files changed, 2 insertions(+) rename BGL/doc/BGL/CGAL/{boost/graph => IO}/vtp_io.h (100%) rename {Polyhedron_IO => BGL}/include/CGAL/IO/vtp_io.h (100%) diff --git a/BGL/doc/BGL/CGAL/boost/graph/vtp_io.h b/BGL/doc/BGL/CGAL/IO/vtp_io.h similarity index 100% rename from BGL/doc/BGL/CGAL/boost/graph/vtp_io.h rename to BGL/doc/BGL/CGAL/IO/vtp_io.h diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index 6948a31cf43..2ce62be128d 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -15,6 +15,8 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/IO/vtp_io.h + EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \ ${CGAL_Surface_mesh_segmentation_EXAMPLE_DIR} \ diff --git a/Polyhedron_IO/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h similarity index 100% rename from Polyhedron_IO/include/CGAL/IO/vtp_io.h rename to BGL/include/CGAL/IO/vtp_io.h From 642aea115aa0b3944f06291c0103c29fc589f87f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 31 May 2018 14:05:53 +0200 Subject: [PATCH 024/186] Add variant of classify() to get detailed output --- .../include/CGAL/Classification/classify.h | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Classification/include/CGAL/Classification/classify.h b/Classification/include/CGAL/Classification/classify.h index bf491b89c71..59bd19cfe2f 100644 --- a/Classification/include/CGAL/Classification/classify.h +++ b/Classification/include/CGAL/Classification/classify.h @@ -87,6 +87,53 @@ namespace internal { }; + template + class Classify_detailed_output_functor + { + const Label_set& m_labels; + const Classifier& m_classifier; + LabelIndexRange& m_out; + ProbabilitiesRanges& m_prob; + + public: + + Classify_detailed_output_functor (const Label_set& labels, + const Classifier& classifier, + LabelIndexRange& out, + ProbabilitiesRanges& prob) + : m_labels (labels), m_classifier (classifier), m_out (out), m_prob (prob) + { } + +#ifdef CGAL_LINKED_WITH_TBB + void operator()(const tbb::blocked_range& r) const + { + for (std::size_t s = r.begin(); s != r.end(); ++ s) + apply(s); + } +#endif // CGAL_LINKED_WITH_TBB + + inline void apply (std::size_t s) const + { + std::size_t nb_class_best=0; + std::vector values; + m_classifier (s, values); + + float val_class_best = 0.f; + for(std::size_t k = 0; k < m_labels.size(); ++ k) + { + m_prob[k][s] = values[k]; + if(val_class_best < values[k]) + { + val_class_best = values[k]; + nb_class_best = k; + } + } + + m_out[s] = static_cast(nb_class_best); + } + + }; + template class Classify_functor_local_smoothing_preprocessing { @@ -344,6 +391,44 @@ namespace internal { } } + /// \cond SKIP_IN_MANUAL + // variant to get a detailed output (not documented yet) + template + void classify (const ItemRange& input, + const Label_set& labels, + const Classifier& classifier, + LabelIndexRange& output, + ProbabilitiesRanges& probabilities) + { + output.resize (input.size()); + probabilities.resize (labels.size()); + for (std::size_t i = 0; i < probabilities.size(); ++ i) + probabilities[i].resize (input.size()); + + internal::Classify_detailed_output_functor + f (labels, classifier, output, probabilities); + +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(0, input.size ()), f); + } + else +#endif + { + for (std::size_t i = 0; i < input.size(); ++ i) + f.apply(i); + } + } + /// \endcond + /*! \ingroup PkgClassificationMain From 14a2269206311fb51d862f37d96256e15635274b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 31 May 2018 14:06:02 +0200 Subject: [PATCH 025/186] Plugin: show detailed output --- .../Classification/Classification_plugin.cpp | 3 +- .../Classification/Item_classification_base.h | 7 ++ .../Point_set_item_classification.cpp | 96 +++++++++++++++---- .../Point_set_item_classification.h | 2 + 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 45e5fdfaf87..0e7ce721566 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -845,6 +845,7 @@ public Q_SLOTS: add_new_label (classif, n); add_label_button(); + update_plugin_from_item(classif); } void on_use_config_building_clicked() @@ -1244,7 +1245,7 @@ public Q_SLOTS: label_buttons.erase (label_buttons.begin() + position); add_label_button(); } - + update_plugin_from_item(classif); item_changed(classif->item()); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 111b75a3f9e..6198fb56b29 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -124,6 +124,13 @@ public: virtual void fill_display_combo_box (QComboBox* cb, QComboBox* cb1) const { + for (std::size_t i = 0; i < m_labels.size(); ++ i) + { + std::ostringstream oss; + oss << "Label " << m_labels[i]->name(); + cb->addItem (oss.str().c_str()); + cb1->addItem (oss.str().c_str()); + } for (std::size_t i = 0; i < m_features.size(); ++ i) { std::ostringstream oss; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index 1096fe5d067..c981e2459db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -17,8 +17,8 @@ #include Point_set_item_classification::Point_set_item_classification(Scene_points_with_normal_item* points) - : m_points (points), - m_generator (NULL) + : m_points (points) + , m_generator (NULL) { m_index_color = 1; @@ -216,9 +216,9 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n update_comments_of_point_set_item(); m_sowf = new Sum_of_weighted_features (m_labels, m_features); - m_ethz = new ETHZ_random_forest (m_labels, m_features); + m_ethz = NULL; #ifdef CGAL_LINKED_WITH_OPENCV - m_random_forest = new Random_forest (m_labels, m_features); + m_random_forest = NULL; #endif } @@ -381,24 +381,54 @@ void Point_set_item_classification::change_color (int index) } else { - Feature_handle feature = m_features[index_color - 3]; + std::size_t corrected_index = index_color - 3; + if (corrected_index < m_labels.size()) // Display label probabilities + { + if (m_label_probabilities.size() <= corrected_index || + m_label_probabilities[corrected_index].size() != m_points->point_set()->size()) + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + m_red[*it] = 0; + m_green[*it] = 0; + m_blue[*it] = 0; + } + } + else + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][*it])); + m_red[*it] = (unsigned char)(ramp.r(v) * 255); + m_green[*it] = (unsigned char)(ramp.g(v) * 255); + m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + } + } + } + else + { + corrected_index -= m_labels.size(); + Feature_handle feature = m_features[corrected_index]; - float max = 0.; - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - if (feature->value(*it) > max) - max = feature->value(*it); + float max = 0.; + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + if (feature->value(*it) > max) + max = feature->value(*it); - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) { float v = std::max (0.f, feature->value(*it) / max); m_red[*it] = (unsigned char)(ramp.r(v) * 255); m_green[*it] = (unsigned char)(ramp.g(v) * 255); m_blue[*it] = (unsigned char)(ramp.b(v) * 255); } + } } - + for (Point_set::const_iterator it = m_points->point_set()->first_selected(); it != m_points->point_set()->end(); ++ it) { @@ -480,12 +510,17 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); - delete m_ethz; - m_ethz = new ETHZ_random_forest (m_labels, m_features); - + if (m_ethz != NULL) + { + delete m_ethz; + m_ethz = NULL; + } #ifdef CGAL_LINKED_WITH_OPENCV - delete m_random_forest; - m_random_forest = new Random_forest (m_labels, m_features); + if (m_random_forest != NULL) + { + delete m_random_forest; + m_random_forest = NULL; + } #endif t.stop(); @@ -608,6 +643,8 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials } reset_indices(); + m_label_probabilities.clear(); + std::vector training (m_points->point_set()->size(), -1); std::vector indices (m_points->point_set()->size(), -1); @@ -635,14 +672,17 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials m_sowf->train(training, nb_trials); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_sowf, - indices); + indices, m_label_probabilities); } else if (classifier == 1) { + if (m_ethz != NULL) + delete m_ethz; + m_ethz = new ETHZ_random_forest (m_labels, m_features); m_ethz->train(training, true, num_trees, max_depth); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_ethz, - indices); + indices, m_label_probabilities); } else { @@ -655,7 +695,7 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials m_random_forest->train (training); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_random_forest, - indices); + indices, m_label_probabilities); #endif } for (Point_set::const_iterator it = m_points->point_set()->begin(); @@ -680,10 +720,24 @@ bool Point_set_item_classification::run (int method, int classifier, if (classifier == 0) run (method, *m_sowf, subdivisions, smoothing); else if (classifier == 1) + { + if (m_ethz == NULL) + { + std::cerr << "Error: ETHZ Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_ethz, subdivisions, smoothing); + } #ifdef CGAL_LINKED_WITH_OPENCV else + { + if (m_random_forest == NULL) + { + std::cerr << "Error: OpenCV Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_random_forest, subdivisions, smoothing); + } #endif return true; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 7390bd3a8e3..373c3e308df 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -367,6 +367,8 @@ class Point_set_item_classification : public Item_classification_base std::vector m_clusters; + std::vector > m_label_probabilities; + Point_set::Property_map m_red; Point_set::Property_map m_green; Point_set::Property_map m_blue; From f520f9eb11f249c094bf30791e1add2e722515c6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 4 Jun 2018 15:58:17 +0200 Subject: [PATCH 026/186] First version of NN with TensorFlow --- Classification/include/CGAL/Classification.h | 4 + .../TensorFlow_neural_network_classifier.h | 436 ++++++++++++++++++ .../cmake/modules/FindTensorFlow.cmake | 25 + .../Plugins/Classification/CMakeLists.txt | 12 + .../Classification/Classification_plugin.cpp | 6 +- .../Classification/Item_classification_base.h | 25 + .../Point_set_item_classification.cpp | 66 ++- .../Point_set_item_classification.h | 1 + 8 files changed, 560 insertions(+), 15 deletions(-) create mode 100644 Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h create mode 100644 Installation/cmake/modules/FindTensorFlow.cmake diff --git a/Classification/include/CGAL/Classification.h b/Classification/include/CGAL/Classification.h index 654aa185cd3..7800d10794d 100644 --- a/Classification/include/CGAL/Classification.h +++ b/Classification/include/CGAL/Classification.h @@ -31,6 +31,10 @@ #include #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW +#include +#endif + #include #include #include diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h new file mode 100644 index 00000000000..6df293517b3 --- /dev/null +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -0,0 +1,436 @@ +// 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) : Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_TENSORFLOW_NEURAL_NETWORK_CLASSIFIER_H +#define CGAL_CLASSIFICATION_TENSORFLOW_NEURAL_NETWORK_CLASSIFIER_H + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +namespace CGAL { + +namespace Classification { + +namespace TF = tensorflow; +namespace TFops = tensorflow::ops; + +/*! + \ingroup PkgClassificationClassifiers + + \cgalModels `CGAL::Classification::Classifier` +*/ +class TensorFlow_neural_network_classifier +{ + typedef TFops::Tanh Activation_function; +// typedef TFops::Relu Activation_function; + + const Label_set& m_labels; + const Feature_set& m_features; + std::vector m_feature_means; + std::vector m_feature_sd; + + TF::Scope* m_root; + TFops::Placeholder* m_ph_ft; + std::vector m_layers; + TF::ClientSession* m_session; + +public: + + /// \name Constructor + /// @{ + + /*! + \brief Instantiate the classifier using the sets of `labels` and `features`. + + */ + TensorFlow_neural_network_classifier (const Label_set& labels, + const Feature_set& features) + : m_labels (labels), m_features (features) + , m_root (NULL), m_ph_ft (NULL), m_session (NULL) + { } + + /// \cond SKIP_IN_MANUAL + ~TensorFlow_neural_network_classifier () + { + } + + void compute_normalization_coefficients (const std::vector& indices) + { + m_feature_means.clear(); + m_feature_means.resize (m_features.size(), 0.f); + + for (std::size_t i = 0; i < indices.size(); ++ i) + for (std::size_t f = 0; f < m_features.size(); ++ f) + m_feature_means[f] += m_features[f]->value(indices[i]); + for (std::size_t f = 0; f < m_features.size(); ++ f) + m_feature_means[f] /= indices.size(); + + m_feature_sd.clear(); + m_feature_sd.resize (m_features.size(), 0.f); + + for (std::size_t i = 0; i < indices.size(); ++ i) + for (std::size_t f = 0; f < m_features.size(); ++ f) + m_feature_sd[f] += + (m_features[f]->value(indices[i]) - m_feature_means[f]) * + (m_features[f]->value(indices[i]) - m_feature_means[f]); + for (std::size_t f = 0; f < m_features.size(); ++ f) + { + m_feature_sd[f] = std::sqrt (m_feature_sd[f] / indices.size()); + if (m_feature_sd[f] == 0.f) + m_feature_sd[f] = 1.f; + } + } + /// \endcond + + /// @} + + /// \name Training + + /// @{ + /*! + \brief Runs the training algorithm. + + */ + template + void train (const LabelIndexRange& ground_truth, + std::size_t number_of_iterations = 5000, + float learning_rate = 0.5, + const std::vector& hidden_layers + = std::vector()) + { + m_root = new TF::Scope (TF::Scope::NewRootScope()); + + // Get input + std::vector indices; + std::vector raw_gt; + for (std::size_t i = 0; i < ground_truth.size(); ++ i) + { + int gc = int(ground_truth[i]); + if (gc != -1) + { + indices.push_back (i); + raw_gt.push_back (gc); + } + } + + CGAL_CLASSTRAINING_CERR << "I - BUILDING NEURAL NETWORK ARCHITECTURE" << std::endl; + + // Get layers and sizes or init with default values + std::vector hl = hidden_layers; + if (hl.empty()) + { + hl.push_back (m_features.size()); + hl.push_back ((m_features.size() + m_labels.size()) / 2); + } + + CGAL_CLASSTRAINING_CERR << " 1) Initializing architecture:" << std::endl + << " * Layer 0: " << m_features.size() << " neuron(s) (input features)" << std::endl; + + if (!CGAL_CLASSTRAINING_SILENT) + for (std::size_t i = 0; i < hl.size(); ++ i) + std::cerr << " * Layer " << i+1 << ": " << hl[i] << " neuron(s)" << std::endl; + + CGAL_CLASSTRAINING_CERR << " * Layer " << hl.size() + 1 << ": " + << m_labels.size() << " neuron(s) (output labels)" << std::endl; + + m_ph_ft = new TFops::Placeholder (*m_root, TF::DT_FLOAT); + TFops::Placeholder ph_gt (*m_root, TF::DT_FLOAT); + + + + CGAL_CLASSTRAINING_CERR << " 2) Creating weight matrices and bias" << std::endl; + + // create weight matrices and bias for each layer transition + std::vector weights; + std::vector assign_weights; + std::vector bias; + std::vector assign_bias; + + for (std::size_t i = 0; i <= hl.size(); ++ i) + { + long long size_from = 0; + long long size_to = 0; + if (i == 0) + { + size_from = m_features.size(); + size_to = hl[0]; + } + else if (i == hl.size()) + { + size_from = hl.back(); + size_to = m_labels.size(); + } + else + { + size_from = hl[i-1]; + size_to = hl[i]; + } + + CGAL_CLASSTRAINING_CERR << " * Weight matrix " << i << " [" << size_from << ";" << size_to << "]" << std::endl; + weights.push_back (TFops::Variable (*m_root, { size_from, size_to }, TF::DT_FLOAT)); + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT))); + + CGAL_CLASSTRAINING_CERR << " * Bias " << i << " [" << size_to << "]" << std::endl; + bias.push_back (TFops::Variable (*m_root, { (long long)(1), size_to }, TF::DT_FLOAT)); + + TF::Tensor init_bias + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(1), (long long)(size_to)}); + float* init_bias_data = init_bias.flat().data(); + for (std::size_t s = 0; s < size_to; ++ s) + init_bias_data[s] = 0.f; + + assign_bias.push_back (TFops::Assign (*m_root, bias.back(), init_bias)); + } + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 3) Creating layers" << std::endl; + + for (std::size_t i = 0; i < weights.size(); ++ i) + { + if (i == 0) + m_layers.push_back (Activation_function (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, *m_ph_ft, weights[0]), + bias[0]))); + else if (i == weights.size() - 1) + m_layers.push_back (TFops::Softmax (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), + bias[i]))); + else + m_layers.push_back (Activation_function (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), + bias[i]))); + } + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 4) Setting up loss calculation" << std::endl; + + // loss calculation + TFops::ReduceMean loss + = TFops::ReduceMean (*m_root, + TFops::Mul (*m_root, TFops::Const(*m_root, -1.f), + TFops::ReduceSum(*m_root, + TFops::Mul (*m_root, ph_gt, + TFops::Log (*m_root, m_layers.back())), {1})), + {0}); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 5) Setting up gradient descent" << std::endl; + + std::vector weights_and_bias; + for (std::size_t i = 0; i < weights.size(); ++ i) + weights_and_bias.push_back (TF::Output(weights[i])); + for (std::size_t i = 0; i < bias.size(); ++ i) + weights_and_bias.push_back (TF::Output(bias[i])); + + std::vector gradients; + + TF_CHECK_OK(TF::AddSymbolicGradients(*m_root, {loss}, + weights_and_bias, + &gradients)); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + std::vector gradient_descent; + for (std::size_t i = 0; i < weights.size(); ++ i) + gradient_descent.push_back (TFops::ApplyGradientDescent + (*m_root, weights[i], + TFops::Cast(*m_root, learning_rate, TF::DT_FLOAT), {gradients[i]})); + for (std::size_t i = 0; i < bias.size(); ++ i) + gradient_descent.push_back (TFops::ApplyGradientDescent + (*m_root, bias[i], + TFops::Cast(*m_root, learning_rate, TF::DT_FLOAT), {gradients[weights.size() + i]})); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 6) Starting session" << std::endl; + + m_session = new TF::ClientSession (*m_root); + std::vector outputs; + + std::vector assign_weights_and_bias; + for (std::size_t i = 0; i < assign_weights.size(); ++ i) + assign_weights_and_bias.push_back (TF::Output(assign_weights[i])); + for (std::size_t i = 0; i < assign_bias.size(); ++ i) + assign_weights_and_bias.push_back (TF::Output(assign_bias[i])); + TF_CHECK_OK (m_session->Run(assign_weights_and_bias, nullptr)); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 7. Normalizing features" << std::endl; + + compute_normalization_coefficients (indices); + + CGAL_CLASSTRAINING_CERR << " 8. Constructing feature tensor and ground truth tensor" << std::endl; + + TF::Tensor ft + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(raw_gt.size()), (long long)(m_features.size())}); + TF::Tensor gt + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(raw_gt.size()), (long long)(m_labels.size())}); + + float* ft_data = ft.flat().data(); + float* gt_data = gt.flat().data(); + + // Fill input tensors + for (std::size_t i = 0; i < indices.size(); ++ i) + { + std::size_t idx = indices[i]; + int g = raw_gt[i]; + + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft_data[i * m_features.size() + f] + = (m_features[f]->value(idx) - m_feature_means[f]) / m_feature_sd[f]; + + for (std::size_t l = 0; l < m_labels.size(); ++ l) + if (std::size_t(g) == l) + gt_data[i * m_labels.size() + l] = 1.f; + else + gt_data[i * m_labels.size() + l] = 0.f; + } + + CGAL_CLASSTRAINING_CERR << "II - TRAINING NEURAL NETWORK" << std::endl; + + std::vector operations; + for (std::size_t i = 0; i < gradient_descent.size(); ++ i) + operations.push_back (gradient_descent[i]); + operations.push_back (m_layers.back()); + + for (std::size_t i = 0; i < number_of_iterations; ++ i) + { + TF_CHECK_OK (m_session->Run ({{*m_ph_ft, ft}, {ph_gt, gt}}, {loss}, &outputs)); + + if ((i+1) % (number_of_iterations / 20) == 0) + { + CGAL_CLASSTRAINING_CERR << " * Step " << i+1 << "/" << number_of_iterations << ": loss = " + << outputs[0].scalar() << std::endl; + } + if (!std::isfinite(*outputs[0].scalar().data())) + { + std::cerr << "Loss is " << outputs[0].scalar() << ", aborting" << std::endl; + return; + } + + TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}, {ph_gt, gt}}, operations, nullptr)); + } + + } + + /// \cond SKIP_IN_MANUAL + void operator() (std::size_t item_index, std::vector& out) const + { + out.resize (m_labels.size(), 0.); + + TF::Tensor ft + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(1), (long long)(m_features.size())}); + + float* ft_data = ft.flat().data(); + + // Fill input tensor + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft_data[f] = (m_features[f]->value(item_index) - m_feature_means[f]) / m_feature_sd[f]; + + std::vector outputs; + TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}}, {m_layers.back()}, &outputs)); + + float* output_data = outputs[0].flat().data(); + + for (std::size_t i = 0; i < m_labels.size(); ++ i) + out[i] = output_data[i]; + } + /// \endcond + + /// @} + + /// \name Input/Output + /// @{ + + /*! + \brief Saves the current configuration in the stream `output`. + + This allows to easily save and recover a specific classification + configuration. + + The output file is written in an GZIP container that is readable + by the `load_configuration()` method. + */ + void save_configuration (std::ostream& ) + { + } + + /*! + \brief Loads a configuration from the stream `input`. + + The input file should be a GZIP container written by the + `save_configuration()` method. The feature set of the classifier + should contain the exact same features in the exact same order as + the ones present when the file was generated using + `save_configuration()`. + */ + void load_configuration (std::istream& ) + { + } + +}; + +} + +} + +#endif // CGAL_CLASSIFICATION_TENSORFLOW_NEURAL_NETWORK_CLASSIFIER_H diff --git a/Installation/cmake/modules/FindTensorFlow.cmake b/Installation/cmake/modules/FindTensorFlow.cmake new file mode 100644 index 00000000000..2d63a0ea237 --- /dev/null +++ b/Installation/cmake/modules/FindTensorFlow.cmake @@ -0,0 +1,25 @@ +include(FindPackageHandleStandardArgs) + +unset(TENSORFLOW_FOUND) + +find_path(TensorFlow_INCLUDE_DIR + NAMES + tensorflow/core + tensorflow/cc + third_party + HINTS + /usr/include/ + /usr/local/include/) + +find_library(TensorFlow_LIBRARY NAMES tensorflow_all + HINTS + /usr/lib + /usr/local/lib) + +find_package_handle_standard_args(TensorFlow DEFAULT_MSG TensorFlow_INCLUDE_DIR TensorFlow_LIBRARY) + +if(TENSORFLOW_FOUND) + set(TensorFlow_LIBRARIES ${TensorFlow_LIBRARY}) + set(TensorFlow_INCLUDE_DIRS ${TensorFlow_INCLUDE_DIR}) +endif() + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 48ce9e655d1..436e3727108 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -37,6 +37,18 @@ if(EIGEN3_FOUND) else() message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") endif() + + find_package(TensorFlow QUIET) + if (TensorFlow_FOUND) + message(STATUS "Found TensorFlow") + set(classification_linked_libraries ${classification_linked_libraries} + ${TensorFlow_LIBRARY}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_TENSORFLOW") + include_directories( ${TensorFlow_INCLUDE_DIR} ) + else() + message(STATUS "NOTICE: TensorFlow not found, Neural Network predicate for classification won't be available.") + endif() target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp ${classification_linked_libraries}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 0e7ce721566..bbebfb8c4e5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -191,6 +191,10 @@ public: .arg(CV_MINOR_VERSION)); #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + ui_widget.classifier->addItem (tr("Neural Network (TensorFlow)")); +#endif + color_att = QColor (75, 75, 77); ui_widget.menu->setMenu (new QMenu("Classification Menu", ui_widget.menu)); @@ -1080,7 +1084,7 @@ public Q_SLOTS: int num_trees = 0; int max_depth = 0; - if (ui_widget.classifier->currentIndex() == 0) + if (ui_widget.classifier->currentIndex() == 0 || ui_widget.classifier->currentIndex() == 3) { bool ok = false; nb_trials = QInputDialog::getInt((QWidget*)mw, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 6198fb56b29..a061f48be54 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -13,6 +13,9 @@ #ifdef CGAL_LINKED_WITH_OPENCV #include #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW +#include +#endif class Item_classification_base { @@ -27,6 +30,9 @@ public: #ifdef CGAL_LINKED_WITH_OPENCV typedef CGAL::Classification::OpenCV_random_forest_classifier Random_forest; #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + typedef CGAL::Classification::TensorFlow_neural_network_classifier Neural_network; +#endif public: @@ -84,6 +90,11 @@ public: delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features); #endif + +#ifdef CGAL_LINKED_WITH_TENSORFLOW + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); +#endif return m_label_colors.back(); } @@ -102,7 +113,13 @@ public: delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features); #endif + +#ifdef CGAL_LINKED_WITH_TENSORFLOW + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); +#endif } + virtual void clear_labels () { m_labels.clear(); @@ -118,6 +135,11 @@ public: delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features); #endif + +#ifdef CGAL_LINKED_WITH_TENSORFLOW + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); +#endif } std::size_t number_of_labels() const { return m_labels.size(); } Label_handle label(std::size_t i) { return m_labels[i]; } @@ -255,6 +277,9 @@ protected: #ifdef CGAL_LINKED_WITH_OPENCV Random_forest* m_random_forest; #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + Neural_network* m_neural_network; +#endif }; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index c981e2459db..1fe42545224 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -220,6 +220,9 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n #ifdef CGAL_LINKED_WITH_OPENCV m_random_forest = NULL; #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + m_neural_network = NULL; +#endif } @@ -232,6 +235,10 @@ Point_set_item_classification::~Point_set_item_classification() #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) delete m_random_forest; +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + delete m_neural_network; #endif if (m_generator != NULL) delete m_generator; @@ -522,6 +529,13 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) m_random_forest = NULL; } #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + { + delete m_neural_network; + m_neural_network = NULL; + } +#endif t.stop(); std::cerr << m_features.size() << " feature(s) computed in " << t.time() << " second(s)" << std::endl; @@ -684,20 +698,33 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials m_labels, *m_ethz, indices, m_label_probabilities); } - else - { + else if (classifier == 2) + { #ifdef CGAL_LINKED_WITH_OPENCV - if (m_random_forest != NULL) - delete m_random_forest; - m_random_forest = new Random_forest (m_labels, m_features, - int(max_depth), 5, 15, - int(num_trees)); - m_random_forest->train (training); - CGAL::Classification::classify (*(m_points->point_set()), - m_labels, *m_random_forest, - indices, m_label_probabilities); + if (m_random_forest != NULL) + delete m_random_forest; + m_random_forest = new Random_forest (m_labels, m_features, + int(max_depth), 5, 15, + int(num_trees)); + m_random_forest->train (training); + CGAL::Classification::classify (*(m_points->point_set()), + m_labels, *m_random_forest, + indices, m_label_probabilities); + } + else + { #endif - } +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + m_neural_network->train (training, nb_trials); + CGAL::Classification::classify (*(m_points->point_set()), + m_labels, *m_neural_network, + indices, m_label_probabilities); +#endif + } + for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) m_classif[*it] = indices[*it]; @@ -728,9 +755,9 @@ bool Point_set_item_classification::run (int method, int classifier, } run (method, *m_ethz, subdivisions, smoothing); } -#ifdef CGAL_LINKED_WITH_OPENCV - else + else if (classifier == 2) { +#ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest == NULL) { std::cerr << "Error: OpenCV Random Forest must be trained or have a configuration loaded first" << std::endl; @@ -738,7 +765,18 @@ bool Point_set_item_classification::run (int method, int classifier, } run (method, *m_random_forest, subdivisions, smoothing); } + else + { #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network == NULL) + { + std::cerr << "Error: TensorFlow Neural Network must be trained or have a configuration loaded first" << std::endl; + return false; + } + run (method, *m_neural_network, subdivisions, smoothing); +#endif + } return true; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 373c3e308df..742f0a0a7ef 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -3,6 +3,7 @@ //#define CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE #define CGAL_CLASSIFICATION_VERBOSE +#define CGAL_CLASSTRAINING_VERBOSE #include From 21b0b0ee816cd265a1fbfba696aa70e15c8688b8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 6 Jun 2018 11:57:43 +0200 Subject: [PATCH 027/186] Much better version of NN with IO functions --- .../TensorFlow_neural_network_classifier.h | 836 +++++++++++++----- 1 file changed, 623 insertions(+), 213 deletions(-) diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index 6df293517b3..4160d082462 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -32,6 +32,16 @@ #include #include +#include +#include +#include +#include +#include +#include + +#include + +#define CGAL_NEURAL_NETWORKS_VERSION "0.1" namespace CGAL { @@ -47,8 +57,20 @@ namespace TFops = tensorflow::ops; */ class TensorFlow_neural_network_classifier { +#define USE_RELU +#if defined(USE_TANH) typedef TFops::Tanh Activation_function; -// typedef TFops::Relu Activation_function; +#elif defined(USE_RELU) + typedef TFops::Relu Activation_function; +#elif defined(USE_RELU6) + typedef TFops::Relu6 Activation_function; +#elif defined(USE_ELU) + typedef TFops::Elu Activation_function; +#elif defined(USE_SELU) + typedef TFops::Selu Activation_function; +#elif defined(USE_SIGMOID) + typedef TFops::Sigmoid Activation_function; +#endif const Label_set& m_labels; const Feature_set& m_features; @@ -57,8 +79,15 @@ class TensorFlow_neural_network_classifier TF::Scope* m_root; TFops::Placeholder* m_ph_ft; + TFops::Placeholder* m_ph_gt; + TFops::ReduceMean* m_loss; + std::vector > m_weights; + std::vector > m_bias; + float m_learning_rate; std::vector m_layers; + std::vector m_gradient_descent; TF::ClientSession* m_session; + public: @@ -72,16 +101,48 @@ public: TensorFlow_neural_network_classifier (const Label_set& labels, const Feature_set& features) : m_labels (labels), m_features (features) - , m_root (NULL), m_ph_ft (NULL), m_session (NULL) + , m_root (NULL), m_ph_ft (NULL), m_ph_gt (NULL), m_loss(NULL), m_session (NULL) { } /// \cond SKIP_IN_MANUAL ~TensorFlow_neural_network_classifier () { + clear(); + } + + bool initialized() const { return (m_root != NULL); } + + void clear() + { + CGAL_CLASSTRAINING_CERR << "(Clearing Neural Network classifier)" << std::endl; + clear (m_ph_gt); + clear (m_ph_ft); + clear (m_loss); + clear (m_session); + clear (m_root); + m_weights.clear(); + m_bias.clear(); + m_gradient_descent.clear(); + m_layers.clear(); + } + + template + void clear (T* t) + { + if (t != NULL) + delete t; + t = NULL; } void compute_normalization_coefficients (const std::vector& indices) { +//#define DO_NOT_NORMALIZE_FEATURES +#ifdef DO_NOT_NORMALIZE_FEATURES + m_feature_means.clear(); + m_feature_means.resize (m_features.size(), 0.f); + m_feature_sd.clear(); + m_feature_sd.resize (m_features.size(), 1.f); +#else m_feature_means.clear(); m_feature_means.resize (m_features.size(), 0.f); @@ -104,7 +165,13 @@ public: m_feature_sd[f] = std::sqrt (m_feature_sd[f] / indices.size()); if (m_feature_sd[f] == 0.f) m_feature_sd[f] = 1.f; + + if (std::isnan(m_feature_means[f])) + m_feature_means[f] = 0.f; + if (std::isnan(m_feature_sd[f])) + m_feature_sd[f] = 1.f; } +#endif } /// \endcond @@ -119,14 +186,23 @@ public: */ template void train (const LabelIndexRange& ground_truth, + bool restart_from_scratch = false, std::size_t number_of_iterations = 5000, - float learning_rate = 0.5, + float learning_rate = 0.1, + std::size_t batch_size = 1000, const std::vector& hidden_layers = std::vector()) { - m_root = new TF::Scope (TF::Scope::NewRootScope()); + CGAL_CLASSTRAINING_CERR << "[Training Neural Network]" << std::endl; + if (restart_from_scratch) + clear(); - // Get input +#define EQUAL_DISTRIBUTION + +#ifdef EQUAL_DISTRIBUTION + std::vector > random_indices (m_labels.size()); +#endif + std::vector indices; std::vector raw_gt; for (std::size_t i = 0; i < ground_truth.size(); ++ i) @@ -136,224 +212,126 @@ public: { indices.push_back (i); raw_gt.push_back (gc); +#ifdef EQUAL_DISTRIBUTION + random_indices[std::size_t(gc)].push_back (i); +#endif } } - CGAL_CLASSTRAINING_CERR << "I - BUILDING NEURAL NETWORK ARCHITECTURE" << std::endl; - - // Get layers and sizes or init with default values - std::vector hl = hidden_layers; - if (hl.empty()) + if (!initialized()) { - hl.push_back (m_features.size()); - hl.push_back ((m_features.size() + m_labels.size()) / 2); + m_learning_rate = learning_rate; + build_architecture (hidden_layers); + CGAL_CLASSTRAINING_CERR << "II - NORMALIZING FEATURES" << std::endl; + compute_normalization_coefficients (indices); } - CGAL_CLASSTRAINING_CERR << " 1) Initializing architecture:" << std::endl - << " * Layer 0: " << m_features.size() << " neuron(s) (input features)" << std::endl; - - if (!CGAL_CLASSTRAINING_SILENT) - for (std::size_t i = 0; i < hl.size(); ++ i) - std::cerr << " * Layer " << i+1 << ": " << hl[i] << " neuron(s)" << std::endl; + CGAL_CLASSTRAINING_CERR << "III - TRAINING NEURAL NETWORK" << std::endl; - CGAL_CLASSTRAINING_CERR << " * Layer " << hl.size() + 1 << ": " - << m_labels.size() << " neuron(s) (output labels)" << std::endl; - - m_ph_ft = new TFops::Placeholder (*m_root, TF::DT_FLOAT); - TFops::Placeholder ph_gt (*m_root, TF::DT_FLOAT); - - - - CGAL_CLASSTRAINING_CERR << " 2) Creating weight matrices and bias" << std::endl; - - // create weight matrices and bias for each layer transition - std::vector weights; - std::vector assign_weights; - std::vector bias; - std::vector assign_bias; - - for (std::size_t i = 0; i <= hl.size(); ++ i) - { - long long size_from = 0; - long long size_to = 0; - if (i == 0) - { - size_from = m_features.size(); - size_to = hl[0]; - } - else if (i == hl.size()) - { - size_from = hl.back(); - size_to = m_labels.size(); - } - else - { - size_from = hl[i-1]; - size_to = hl[i]; - } - - CGAL_CLASSTRAINING_CERR << " * Weight matrix " << i << " [" << size_from << ";" << size_to << "]" << std::endl; - weights.push_back (TFops::Variable (*m_root, { size_from, size_to }, TF::DT_FLOAT)); - assign_weights.push_back (TFops::Assign (*m_root, weights.back(), - TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT))); - - CGAL_CLASSTRAINING_CERR << " * Bias " << i << " [" << size_to << "]" << std::endl; - bias.push_back (TFops::Variable (*m_root, { (long long)(1), size_to }, TF::DT_FLOAT)); - - TF::Tensor init_bias - (TF::DataTypeToEnum::v(), - TF::TensorShape {(long long)(1), (long long)(size_to)}); - float* init_bias_data = init_bias.flat().data(); - for (std::size_t s = 0; s < size_to; ++ s) - init_bias_data[s] = 0.f; - - assign_bias.push_back (TFops::Assign (*m_root, bias.back(), init_bias)); - } - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - CGAL_CLASSTRAINING_CERR << " 3) Creating layers" << std::endl; - - for (std::size_t i = 0; i < weights.size(); ++ i) - { - if (i == 0) - m_layers.push_back (Activation_function (*m_root, TFops::Add - (*m_root, TFops::MatMul (*m_root, *m_ph_ft, weights[0]), - bias[0]))); - else if (i == weights.size() - 1) - m_layers.push_back (TFops::Softmax (*m_root, TFops::Add - (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), - bias[i]))); - else - m_layers.push_back (Activation_function (*m_root, TFops::Add - (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), - bias[i]))); - } - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - CGAL_CLASSTRAINING_CERR << " 4) Setting up loss calculation" << std::endl; - - // loss calculation - TFops::ReduceMean loss - = TFops::ReduceMean (*m_root, - TFops::Mul (*m_root, TFops::Const(*m_root, -1.f), - TFops::ReduceSum(*m_root, - TFops::Mul (*m_root, ph_gt, - TFops::Log (*m_root, m_layers.back())), {1})), - {0}); - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - CGAL_CLASSTRAINING_CERR << " 5) Setting up gradient descent" << std::endl; - - std::vector weights_and_bias; - for (std::size_t i = 0; i < weights.size(); ++ i) - weights_and_bias.push_back (TF::Output(weights[i])); - for (std::size_t i = 0; i < bias.size(); ++ i) - weights_and_bias.push_back (TF::Output(bias[i])); - - std::vector gradients; - - TF_CHECK_OK(TF::AddSymbolicGradients(*m_root, {loss}, - weights_and_bias, - &gradients)); - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - std::vector gradient_descent; - for (std::size_t i = 0; i < weights.size(); ++ i) - gradient_descent.push_back (TFops::ApplyGradientDescent - (*m_root, weights[i], - TFops::Cast(*m_root, learning_rate, TF::DT_FLOAT), {gradients[i]})); - for (std::size_t i = 0; i < bias.size(); ++ i) - gradient_descent.push_back (TFops::ApplyGradientDescent - (*m_root, bias[i], - TFops::Cast(*m_root, learning_rate, TF::DT_FLOAT), {gradients[weights.size() + i]})); - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - CGAL_CLASSTRAINING_CERR << " 6) Starting session" << std::endl; - - m_session = new TF::ClientSession (*m_root); - std::vector outputs; - - std::vector assign_weights_and_bias; - for (std::size_t i = 0; i < assign_weights.size(); ++ i) - assign_weights_and_bias.push_back (TF::Output(assign_weights[i])); - for (std::size_t i = 0; i < assign_bias.size(); ++ i) - assign_weights_and_bias.push_back (TF::Output(assign_bias[i])); - TF_CHECK_OK (m_session->Run(assign_weights_and_bias, nullptr)); - - if (!m_root->status().ok()) - { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; - return; - } - - CGAL_CLASSTRAINING_CERR << " 7. Normalizing features" << std::endl; - - compute_normalization_coefficients (indices); - - CGAL_CLASSTRAINING_CERR << " 8. Constructing feature tensor and ground truth tensor" << std::endl; - - TF::Tensor ft - (TF::DataTypeToEnum::v(), - TF::TensorShape {(long long)(raw_gt.size()), (long long)(m_features.size())}); - TF::Tensor gt - (TF::DataTypeToEnum::v(), - TF::TensorShape {(long long)(raw_gt.size()), (long long)(m_labels.size())}); - - float* ft_data = ft.flat().data(); - float* gt_data = gt.flat().data(); - - // Fill input tensors - for (std::size_t i = 0; i < indices.size(); ++ i) - { - std::size_t idx = indices[i]; - int g = raw_gt[i]; - - for (std::size_t f = 0; f < m_features.size(); ++ f) - ft_data[i * m_features.size() + f] - = (m_features[f]->value(idx) - m_feature_means[f]) / m_feature_sd[f]; - - for (std::size_t l = 0; l < m_labels.size(); ++ l) - if (std::size_t(g) == l) - gt_data[i * m_labels.size() + l] = 1.f; - else - gt_data[i * m_labels.size() + l] = 0.f; - } - - CGAL_CLASSTRAINING_CERR << "II - TRAINING NEURAL NETWORK" << std::endl; +#ifndef EQUAL_DISTRIBUTION + batch_size = std::min (std::size_t(batch_size), indices.size()); + std::vector random_indices + (boost::make_counting_iterator(0), + boost::make_counting_iterator(indices.size())); +#endif std::vector operations; - for (std::size_t i = 0; i < gradient_descent.size(); ++ i) - operations.push_back (gradient_descent[i]); + for (std::size_t i = 0; i < m_gradient_descent.size(); ++ i) + operations.push_back (m_gradient_descent[i]); operations.push_back (m_layers.back()); + std::vector outputs; + + m_weights.clear(); + m_bias.clear(); for (std::size_t i = 0; i < number_of_iterations; ++ i) { - TF_CHECK_OK (m_session->Run ({{*m_ph_ft, ft}, {ph_gt, gt}}, {loss}, &outputs)); +#ifdef EQUAL_DISTRIBUTION + std::size_t total_batch_size = 0; + for (std::size_t j = 0; j < random_indices.size(); ++ j) + { + if (random_indices[j].empty()) + continue; + std::size_t local_batch_size = std::min (std::size_t(batch_size / m_labels.size()), + random_indices[j].size()); + random_unique (random_indices[j].begin(), random_indices[j].end(), local_batch_size); + total_batch_size += local_batch_size; + + if (i == 0) + { + CGAL_CLASSTRAINING_CERR << " * Size of batch for " << m_labels[j]->name() << ": " + << local_batch_size << std::endl; + } + } + + TF::Tensor ft + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(total_batch_size), (long long)(m_features.size())}); + TF::Tensor gt + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(total_batch_size), (long long)(m_labels.size())}); + + float* ft_data = ft.flat().data(); + float* gt_data = gt.flat().data(); + + // Fill input tensors + std::size_t current_i = 0; + for (std::size_t j = 0; j < random_indices.size(); ++ j) + { + if (random_indices[j].empty()) + continue; + std::size_t local_batch_size = std::min (std::size_t(batch_size / m_labels.size()), + random_indices[j].size()); + for (std::size_t k = 0; k < local_batch_size; ++ k) + { + std::size_t idx = indices[random_indices[j][k]]; + int g = raw_gt[random_indices[j][k]]; + + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft_data[current_i * m_features.size() + f] + = (m_features[f]->value(idx) - m_feature_means[f]) / m_feature_sd[f]; + + for (std::size_t l = 0; l < m_labels.size(); ++ l) + if (std::size_t(g) == l) + gt_data[current_i * m_labels.size() + l] = 1.f; + else + gt_data[current_i * m_labels.size() + l] = 0.f; + + ++ current_i; + } + } +#else + random_unique (random_indices.begin(), random_indices.end(), batch_size); + + TF::Tensor ft + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(batch_size), (long long)(m_features.size())}); + TF::Tensor gt + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(batch_size), (long long)(m_labels.size())}); + + float* ft_data = ft.flat().data(); + float* gt_data = gt.flat().data(); + + // Fill input tensors + for (std::size_t i = 0; i < batch_size; ++ i) + { + std::size_t idx = indices[random_indices[i]]; + int g = raw_gt[random_indices[i]]; + + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft_data[i * m_features.size() + f] + = (m_features[f]->value(idx) - m_feature_means[f]) / m_feature_sd[f]; + + for (std::size_t l = 0; l < m_labels.size(); ++ l) + if (std::size_t(g) == l) + gt_data[i * m_labels.size() + l] = 1.f; + else + gt_data[i * m_labels.size() + l] = 0.f; + } +#endif + + TF_CHECK_OK (m_session->Run ({{*m_ph_ft, ft}, {*m_ph_gt, gt}}, {*m_loss}, &outputs)); if ((i+1) % (number_of_iterations / 20) == 0) { @@ -366,7 +344,28 @@ public: return; } - TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}, {ph_gt, gt}}, operations, nullptr)); + if (i == number_of_iterations - 1) + { + TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}, {*m_ph_gt, gt}}, operations, &outputs)); + for (std::size_t o = 0; o < outputs.size() - 1; ++ o) + { + std::size_t size = outputs[o].dim_size(0) * outputs[o].dim_size(1); + if (o < outputs.size() / 2) + { + m_weights.push_back (std::vector(size)); + float* weights_data = outputs[o].flat().data(); + std::copy_n (weights_data, size, m_weights.back().begin()); + } + else + { + m_bias.push_back (std::vector(size)); + float* bias_data = outputs[o].flat().data(); + std::copy_n (bias_data, size, m_bias.back().begin()); + } + } + } + else + TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}, {*m_ph_gt, gt}}, operations, nullptr)); } } @@ -410,8 +409,74 @@ public: The output file is written in an GZIP container that is readable by the `load_configuration()` method. */ - void save_configuration (std::ostream& ) + void save_configuration (std::ostream& output) { + boost::property_tree::ptree tree; + + { + boost::property_tree::ptree ptr; + ptr.put("classifier_version", CGAL_NEURAL_NETWORKS_VERSION); + ptr.put("number_of_features", m_features.size()); + ptr.put("number_of_labels", m_labels.size()); + ptr.put("number_of_hidden_layers", m_layers.size() - 1); + ptr.put("learning_rate", m_learning_rate); + tree.add_child("classification.metadata", ptr); + } + + for (std::size_t i = 0; i < m_features.size(); ++ i) + { + boost::property_tree::ptree ptr; + ptr.put("name", m_features[i]->name()); + ptr.put("mean", m_feature_means[i]); + ptr.put("standard_deviation", m_feature_sd[i]); + tree.add_child("classification.features.feature", ptr); + } + + for (std::size_t i = 0; i < m_labels.size(); ++ i) + { + boost::property_tree::ptree ptr; + ptr.put("name", m_labels[i]->name()); + tree.add_child("classification.labels.label", ptr); + } + + for (std::size_t i = 0; i < m_weights.size(); ++ i) + { + boost::property_tree::ptree ptr; + ptr.put("height", (m_weights[i].size() / m_bias[i].size())); + ptr.put("width", m_bias[i].size()); + + std::ostringstream oss; + oss.precision(std::numeric_limits::digits10 + 2); + for (std::size_t j = 0; j < m_weights[i].size(); ++ j) + { + oss << m_weights[i][j]; + if (j != m_weights[i].size() - 1) + oss << " "; + } + ptr.put("weights", oss.str()); + + oss = std::ostringstream(); + oss.precision(std::numeric_limits::digits10 + 2); + for (std::size_t j = 0; j < m_bias[i].size(); ++ j) + { + oss << m_bias[i][j]; + if (j != m_bias[i].size() - 1) + oss << " "; + } + ptr.put("bias", oss.str()); + + tree.add_child("classification.layers.layer", ptr); + } + + + + // Write property tree to XML file + boost::property_tree::write_xml(output, tree, +#if BOOST_VERSION >= 105600 + boost::property_tree::xml_writer_make_settings(' ', 3)); +#else + boost::property_tree::xml_writer_make_settings(' ', 3)); +#endif } /*! @@ -423,10 +488,355 @@ public: the ones present when the file was generated using `save_configuration()`. */ - void load_configuration (std::istream& ) + bool load_configuration (std::istream& input, bool verbose = false) { + clear(); + + bool out = true; + + boost::property_tree::ptree tree; + boost::property_tree::read_xml(input, tree); + + std::string version = tree.get("classification.metadata.classifier_version"); + if (version != CGAL_NEURAL_NETWORKS_VERSION) + { + if (verbose) + std::cerr << "Error: CGAL Neural Network version mismatch " << version << "/" << CGAL_NEURAL_NETWORKS_VERSION << std::endl; + return false; + } + std::size_t nb_features = std::size_t(tree.get("classification.metadata.number_of_features")); + if (nb_features != m_features.size()) + { + if (verbose) + std::cerr << "Error: number of features mismatch " << nb_features << "/" << m_features.size() << std::endl; + return false; + } + + std::size_t nb_labels = std::size_t(tree.get("classification.metadata.number_of_labels")); + if (nb_labels != m_labels.size()) + { + if (verbose) + std::cerr << "Error: number of labels mismatch " << nb_labels << "/" << m_labels.size() << std::endl; + return false; + } + + std::size_t nb_layers = std::size_t(tree.get("classification.metadata.number_of_hidden_layers")) + 1; + m_learning_rate = tree.get("classification.metadata.learning_rate"); + + std::size_t idx = 0; + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("classification.features")) + { + std::string name = v.second.get("name"); + + if (name != m_features[idx]->name()) + { + if (verbose) + std::cerr << "Warning: feature mismatch " << name << "/" << m_features[idx]->name() << std::endl; + out = false; + } + + m_feature_means.push_back(v.second.get("mean")); + m_feature_sd.push_back(v.second.get("standard_deviation")); + + ++ idx; + } + + if (idx != nb_features) + { + if (verbose) + std::cerr << "Error: number of features mismatch " << nb_features << "/" << idx << std::endl; + return false; + } + + idx = 0; + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("classification.labels")) + { + std::string name = v.second.get("name"); + if (name != m_labels[idx]->name()) + { + if (verbose) + std::cerr << "Warning: label mismatch " << name << "/" << m_labels[idx]->name() << std::endl; + out = false; + } + ++ idx; + } + + if (idx != nb_labels) + { + if (verbose) + std::cerr << "Error: number of labels mismatch " << nb_labels << "/" << idx << std::endl; + return false; + } + + idx = 0; + m_weights.resize (nb_layers); + m_bias.resize (nb_layers); + + std::vector hidden_layers; + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("classification.layers")) + { + if (idx >= nb_layers) + { + if (verbose) + std::cerr << "Error: number of layers mismatch " << nb_layers << "/" << idx << std::endl; + return false; + } + std::size_t height = std::size_t(v.second.get("height")); + std::size_t width = std::size_t(v.second.get("width")); + std::size_t size = height * width; + m_weights[idx].reserve (size); + m_bias[idx].reserve (width); + + std::string weights = v.second.get("weights"); + std::istringstream iss (weights); + float f; + while (iss >> f) + m_weights[idx].push_back (f); + + std::string bias = v.second.get("bias"); + iss = std::istringstream (bias); + while (iss >> f) + m_bias[idx].push_back (f); + + if (idx != nb_layers - 1) + hidden_layers.push_back (width); + + ++ idx; + } + + if (idx != nb_layers) + { + if (verbose) + std::cerr << "Error: number of layers mismatch " << nb_layers << "/" << idx << std::endl; + return false; + } + + build_architecture(hidden_layers); + + return out; } + +private: + + template + BidiIter random_unique(BidiIter begin, BidiIter end, size_t num_random) { + size_t left = std::distance(begin, end); + while (num_random--) { + BidiIter r = begin; + std::advance(r, rand()%left); + std::swap(*begin, *r); + ++begin; + --left; + } + return begin; + } + + void build_architecture (const std::vector& hidden_layers) + { + m_root = new TF::Scope (TF::Scope::NewRootScope()); + + CGAL_CLASSTRAINING_CERR << "I - BUILDING NEURAL NETWORK ARCHITECTURE" << std::endl; + + // Get layers and sizes or init with default values + std::vector hl = hidden_layers; + if (hl.empty()) + { + hl.push_back (m_features.size()); + hl.push_back ((m_features.size() + m_labels.size()) / 2); + } + + CGAL_CLASSTRAINING_CERR << " 1) Initializing architecture:" << std::endl + << " * Layer 0: " << m_features.size() << " neuron(s) (input features)" << std::endl; + + if (!CGAL_CLASSTRAINING_SILENT) + for (std::size_t i = 0; i < hl.size(); ++ i) + std::cerr << " * Layer " << i+1 << ": " << hl[i] << " neuron(s)" << std::endl; + + CGAL_CLASSTRAINING_CERR << " * Layer " << hl.size() + 1 << ": " + << m_labels.size() << " neuron(s) (output labels)" << std::endl; + + m_ph_ft = new TFops::Placeholder (*m_root, TF::DT_FLOAT); + m_ph_gt = new TFops::Placeholder (*m_root, TF::DT_FLOAT); + + CGAL_CLASSTRAINING_CERR << " 2) Creating weight matrices and bias" << std::endl; + + // create weight matrices and bias for each layer transition + std::vector weights; + std::vector bias; + std::vector assign_weights; + std::vector assign_bias; + + for (std::size_t i = 0; i <= hl.size(); ++ i) + { + long long size_from = 0; + long long size_to = 0; + if (i == 0) + { + size_from = m_features.size(); + size_to = hl[0]; + } + else if (i == hl.size()) + { + size_from = hl.back(); + size_to = m_labels.size(); + } + else + { + size_from = hl[i-1]; + size_to = hl[i]; + } + + CGAL_CLASSTRAINING_CERR << " * Weight matrix " << i << " [" << size_from << ";" << size_to << "]" << std::endl; + weights.push_back (TFops::Variable (*m_root, { size_from, size_to }, TF::DT_FLOAT)); + + if (m_weights.empty()) + { +#ifdef USE_TANH // Weights initialized by Xavier method + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::Mul (*m_root, TFops::Const(*m_root, + std::sqrt (1.f / (float)(size_from))), + TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); +#elif defined(USE_RELU) || defined(USE_RELU6) // Weights initialized by He method + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::Mul (*m_root, TFops::Const(*m_root, + std::sqrt (2.f / (float)(size_from))), + TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); +#else // Default: weights truncated normal + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::TruncatedNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT))); +#endif + } + else + { + TF::Tensor init_weight + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(size_from), (long long)(size_to)}); + float* init_weight_data = init_weight.flat().data(); + std::copy_n (m_weights[i].begin(), size_from * size_to, init_weight_data); + + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), init_weight)); + } + + CGAL_CLASSTRAINING_CERR << " * Bias " << i << " [" << size_to << "]" << std::endl; + bias.push_back (TFops::Variable (*m_root, { (long long)(1), size_to }, TF::DT_FLOAT)); + + TF::Tensor init_bias + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(1), (long long)(size_to)}); + float* init_bias_data = init_bias.flat().data(); + if (m_bias.empty()) + for (std::size_t s = 0; s < size_to; ++ s) + init_bias_data[s] = 0.f; + else + std::copy_n (m_bias[i].begin(), size_to, init_bias_data); + + assign_bias.push_back (TFops::Assign (*m_root, bias.back(), init_bias)); + } + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 3) Creating layers" << std::endl; + + for (std::size_t i = 0; i < weights.size(); ++ i) + { + if (i == 0) + m_layers.push_back (Activation_function (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, *m_ph_ft, weights[0]), + bias[0]))); + else if (i == weights.size() - 1) + m_layers.push_back (TFops::Softmax (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), + bias[i]))); + else + m_layers.push_back (Activation_function (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), + bias[i]))); + } + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 4) Setting up loss calculation" << std::endl; + + // loss calculation based on cross-entropy + +// TFops::Log log_ypred = TFops::Log (*m_root, m_layers.back()); + + TFops::Maximum truncated_ypred = TFops::Maximum (*m_root, TFops::Const(*m_root, 0.0001f), m_layers.back()); + TFops::Log log_ypred = TFops::Log (*m_root, truncated_ypred); + TFops::Mul ygt_times_log_ypred = TFops::Mul (*m_root, *m_ph_gt, log_ypred); + TFops::ReduceSum sum_ygt_times_log_ypred = TFops::ReduceSum(*m_root, ygt_times_log_ypred, {1}); + TFops::Mul minus_sum_ygt_times_log_ypred = TFops::Mul (*m_root, TFops::Const(*m_root, -1.f), sum_ygt_times_log_ypred); + + m_loss = new TFops::ReduceMean (*m_root, minus_sum_ygt_times_log_ypred, {0}); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 5) Setting up gradient descent" << std::endl; + + std::vector weights_and_bias; + for (std::size_t i = 0; i < weights.size(); ++ i) + weights_and_bias.push_back (TF::Output(weights[i])); + for (std::size_t i = 0; i < bias.size(); ++ i) + weights_and_bias.push_back (TF::Output(bias[i])); + + std::vector gradients; + + TF_CHECK_OK(TF::AddSymbolicGradients(*m_root, {*m_loss}, + weights_and_bias, + &gradients)); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + for (std::size_t i = 0; i < weights.size(); ++ i) + m_gradient_descent.push_back (TFops::ApplyGradientDescent + (*m_root, weights[i], + TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), {gradients[i]})); + for (std::size_t i = 0; i < bias.size(); ++ i) + m_gradient_descent.push_back (TFops::ApplyGradientDescent + (*m_root, bias[i], + TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), {gradients[weights.size() + i]})); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + + CGAL_CLASSTRAINING_CERR << " 6) Starting session" << std::endl; + + m_session = new TF::ClientSession (*m_root); + std::vector outputs; + + std::vector assign_weights_and_bias; + for (std::size_t i = 0; i < assign_weights.size(); ++ i) + assign_weights_and_bias.push_back (TF::Output(assign_weights[i])); + for (std::size_t i = 0; i < assign_bias.size(); ++ i) + assign_weights_and_bias.push_back (TF::Output(assign_bias[i])); + TF_CHECK_OK (m_session->Run(assign_weights_and_bias, nullptr)); + + if (!m_root->status().ok()) + { + CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + return; + } + } }; } From ec520f57d55c819b3a57dc9eabe29ee70b678579 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 15 Jun 2018 15:22:46 +0200 Subject: [PATCH 028/186] More improvements using better optimizer --- .../TensorFlow_neural_network_classifier.h | 210 +++++++++++++++--- .../Classification/Classification_plugin.cpp | 111 ++++++--- .../Classification/Classification_widget.ui | 12 +- .../Classification/Cluster_classification.cpp | 13 +- .../Classification/Cluster_classification.h | 3 +- .../Classification/Item_classification_base.h | 24 +- .../Point_set_item_classification.cpp | 82 +++++-- .../Point_set_item_classification.h | 7 +- .../Surface_mesh_item_classification.cpp | 14 +- .../Surface_mesh_item_classification.h | 3 +- .../Polyhedron/include/QMultipleInputDialog.h | 19 +- 11 files changed, 382 insertions(+), 116 deletions(-) diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index 4160d082462..f8ac8d48f28 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -71,6 +71,8 @@ class TensorFlow_neural_network_classifier #elif defined(USE_SIGMOID) typedef TFops::Sigmoid Activation_function; #endif + + bool m_verbose; const Label_set& m_labels; const Feature_set& m_features; @@ -80,12 +82,26 @@ class TensorFlow_neural_network_classifier TF::Scope* m_root; TFops::Placeholder* m_ph_ft; TFops::Placeholder* m_ph_gt; + +//#define USE_IOU +#ifdef USE_IOU TFops::ReduceMean* m_loss; +#else + TFops::ReduceMean* m_loss; +#endif + std::vector > m_weights; std::vector > m_bias; float m_learning_rate; std::vector m_layers; + +#define USE_ADAM +#ifdef USE_ADAM + std::vector m_gradient_descent; +#else std::vector m_gradient_descent; +#endif + TF::ClientSession* m_session; @@ -100,7 +116,7 @@ public: */ TensorFlow_neural_network_classifier (const Label_set& labels, const Feature_set& features) - : m_labels (labels), m_features (features) + : m_verbose (true), m_labels (labels), m_features (features) , m_root (NULL), m_ph_ft (NULL), m_ph_gt (NULL), m_loss(NULL), m_session (NULL) { } @@ -114,7 +130,7 @@ public: void clear() { - CGAL_CLASSTRAINING_CERR << "(Clearing Neural Network classifier)" << std::endl; + if (m_verbose) std::cerr << "(Clearing Neural Network classifier)" << std::endl; clear (m_ph_gt); clear (m_ph_ft); clear (m_loss); @@ -170,6 +186,9 @@ public: m_feature_means[f] = 0.f; if (std::isnan(m_feature_sd[f])) m_feature_sd[f] = 1.f; + + std::cerr << "#" << f << ": " << m_features[f]->name() << " = " + << m_feature_means[f] << " +/- " << m_feature_sd[f] << std::endl; } #endif } @@ -193,7 +212,7 @@ public: const std::vector& hidden_layers = std::vector()) { - CGAL_CLASSTRAINING_CERR << "[Training Neural Network]" << std::endl; + if (m_verbose) std::cerr << "[Training Neural Network]" << std::endl; if (restart_from_scratch) clear(); @@ -213,7 +232,7 @@ public: indices.push_back (i); raw_gt.push_back (gc); #ifdef EQUAL_DISTRIBUTION - random_indices[std::size_t(gc)].push_back (i); + random_indices[std::size_t(gc)].push_back (indices.size() - 1); #endif } } @@ -222,11 +241,11 @@ public: { m_learning_rate = learning_rate; build_architecture (hidden_layers); - CGAL_CLASSTRAINING_CERR << "II - NORMALIZING FEATURES" << std::endl; + if (m_verbose) std::cerr << "II - NORMALIZING FEATURES" << std::endl; compute_normalization_coefficients (indices); } - CGAL_CLASSTRAINING_CERR << "III - TRAINING NEURAL NETWORK" << std::endl; + if (m_verbose) std::cerr << "III - TRAINING NEURAL NETWORK" << std::endl; #ifndef EQUAL_DISTRIBUTION batch_size = std::min (std::size_t(batch_size), indices.size()); @@ -244,6 +263,9 @@ public: m_weights.clear(); m_bias.clear(); + // std::ofstream log ("loss.log"); + // log.precision(18); + for (std::size_t i = 0; i < number_of_iterations; ++ i) { #ifdef EQUAL_DISTRIBUTION @@ -259,7 +281,7 @@ public: if (i == 0) { - CGAL_CLASSTRAINING_CERR << " * Size of batch for " << m_labels[j]->name() << ": " + if (m_verbose) std::cerr << " * Size of batch for " << m_labels[j]->name() << ": " << local_batch_size << std::endl; } } @@ -333,9 +355,10 @@ public: TF_CHECK_OK (m_session->Run ({{*m_ph_ft, ft}, {*m_ph_gt, gt}}, {*m_loss}, &outputs)); +// log << outputs[0].scalar() << std::endl; if ((i+1) % (number_of_iterations / 20) == 0) { - CGAL_CLASSTRAINING_CERR << " * Step " << i+1 << "/" << number_of_iterations << ": loss = " + if (m_verbose) std::cerr << " * Step " << i+1 << "/" << number_of_iterations << ": loss = " << outputs[0].scalar() << std::endl; } if (!std::isfinite(*outputs[0].scalar().data())) @@ -636,7 +659,8 @@ private: { m_root = new TF::Scope (TF::Scope::NewRootScope()); - CGAL_CLASSTRAINING_CERR << "I - BUILDING NEURAL NETWORK ARCHITECTURE" << std::endl; + + if (m_verbose) std::cerr << "I - BUILDING NEURAL NETWORK ARCHITECTURE" << std::endl; // Get layers and sizes or init with default values std::vector hl = hidden_layers; @@ -646,20 +670,20 @@ private: hl.push_back ((m_features.size() + m_labels.size()) / 2); } - CGAL_CLASSTRAINING_CERR << " 1) Initializing architecture:" << std::endl + if (m_verbose) std::cerr << " 1) Initializing architecture:" << std::endl << " * Layer 0: " << m_features.size() << " neuron(s) (input features)" << std::endl; if (!CGAL_CLASSTRAINING_SILENT) for (std::size_t i = 0; i < hl.size(); ++ i) std::cerr << " * Layer " << i+1 << ": " << hl[i] << " neuron(s)" << std::endl; - CGAL_CLASSTRAINING_CERR << " * Layer " << hl.size() + 1 << ": " + if (m_verbose) std::cerr << " * Layer " << hl.size() + 1 << ": " << m_labels.size() << " neuron(s) (output labels)" << std::endl; m_ph_ft = new TFops::Placeholder (*m_root, TF::DT_FLOAT); m_ph_gt = new TFops::Placeholder (*m_root, TF::DT_FLOAT); - CGAL_CLASSTRAINING_CERR << " 2) Creating weight matrices and bias" << std::endl; + if (m_verbose) std::cerr << " 2) Creating weight matrices and bias" << std::endl; // create weight matrices and bias for each layer transition std::vector weights; @@ -687,7 +711,7 @@ private: size_to = hl[i]; } - CGAL_CLASSTRAINING_CERR << " * Weight matrix " << i << " [" << size_from << ";" << size_to << "]" << std::endl; + if (m_verbose) std::cerr << " * Weight matrix " << i << " [" << size_from << ";" << size_to << "]" << std::endl; weights.push_back (TFops::Variable (*m_root, { size_from, size_to }, TF::DT_FLOAT)); if (m_weights.empty()) @@ -718,7 +742,7 @@ private: assign_weights.push_back (TFops::Assign (*m_root, weights.back(), init_weight)); } - CGAL_CLASSTRAINING_CERR << " * Bias " << i << " [" << size_to << "]" << std::endl; + if (m_verbose) std::cerr << " * Bias " << i << " [" << size_to << "]" << std::endl; bias.push_back (TFops::Variable (*m_root, { (long long)(1), size_to }, TF::DT_FLOAT)); TF::Tensor init_bias @@ -736,11 +760,11 @@ private: if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } - CGAL_CLASSTRAINING_CERR << " 3) Creating layers" << std::endl; + if (m_verbose) std::cerr << " 3) Creating layers" << std::endl; for (std::size_t i = 0; i < weights.size(); ++ i) { @@ -760,31 +784,50 @@ private: if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } - CGAL_CLASSTRAINING_CERR << " 4) Setting up loss calculation" << std::endl; + if (m_verbose) std::cerr << " 4) Setting up loss calculation" << std::endl; // loss calculation based on cross-entropy // TFops::Log log_ypred = TFops::Log (*m_root, m_layers.back()); +#ifdef USE_IOU + + TFops::Mul ygt_times_ypred = TFops::Mul (*m_root, *m_ph_gt, m_layers.back()); + TFops::ReduceSum intersection = TFops::ReduceSum(*m_root, ygt_times_ypred, {1}); + + TFops::Add ygt_plus_ypred = TFops::Add (*m_root, *m_ph_gt, m_layers.back()); + TFops::Mul ygt_times_ypred_2 = TFops::Mul (*m_root, *m_ph_gt, m_layers.back()); + TFops::Sub sum_minus_product = TFops::Sub (*m_root, ygt_plus_ypred, ygt_times_ypred_2); + TFops::ReduceSum my_union = TFops::ReduceSum(*m_root, sum_minus_product, {1}); + + TFops::Div IoU = TFops::Div(*m_root, intersection, my_union); + TFops::Sub one_minus_IoU = TFops::Sub (*m_root, TFops::Const(*m_root, 1.f), IoU); + m_loss = new TFops::ReduceMean (*m_root, one_minus_IoU, {0}); + + // TFops::ReduceMean mean_IoU = TFops::ReduceMean (*m_root, IoU, {0}); + // m_loss = new TFops::Sub (*m_root, TFops::Const(*m_root, 1.f), mean_IoU); + +#else TFops::Maximum truncated_ypred = TFops::Maximum (*m_root, TFops::Const(*m_root, 0.0001f), m_layers.back()); TFops::Log log_ypred = TFops::Log (*m_root, truncated_ypred); TFops::Mul ygt_times_log_ypred = TFops::Mul (*m_root, *m_ph_gt, log_ypred); TFops::ReduceSum sum_ygt_times_log_ypred = TFops::ReduceSum(*m_root, ygt_times_log_ypred, {1}); TFops::Mul minus_sum_ygt_times_log_ypred = TFops::Mul (*m_root, TFops::Const(*m_root, -1.f), sum_ygt_times_log_ypred); - + m_loss = new TFops::ReduceMean (*m_root, minus_sum_ygt_times_log_ypred, {0}); +#endif if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } - CGAL_CLASSTRAINING_CERR << " 5) Setting up gradient descent" << std::endl; + if (m_verbose) std::cerr << " 5) Setting up gradient descent" << std::endl; std::vector weights_and_bias; for (std::size_t i = 0; i < weights.size(); ++ i) @@ -797,13 +840,114 @@ private: TF_CHECK_OK(TF::AddSymbolicGradients(*m_root, {*m_loss}, weights_and_bias, &gradients)); - + if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } + + std::vector assigners; + +#ifdef USE_ADAM + for (std::size_t i = 0; i < weights.size(); ++ i) + { + long long size_from = 0; + long long size_to = 0; + if (i == 0) + { + size_from = m_features.size(); + size_to = hl[0]; + } + else if (i == weights.size() - 1) + { + size_from = hl.back(); + size_to = m_labels.size(); + } + else + { + size_from = hl[i-1]; + size_to = hl[i]; + } + TFops::Variable m (*m_root, { size_from, size_to}, TF::DT_FLOAT); + TF::Tensor init_m + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(size_from), (long long)(size_to)}); + float* init_m_data = init_m.flat().data(); + for (std::size_t s = 0; s < size_from; ++ s) + for (std::size_t ss = 0; ss < size_to; ++ ss) + init_m_data[ss * size_from + s] = 0.f; + assigners.push_back (TFops::Assign (*m_root, m, init_m)); + + TFops::Variable v (*m_root, { size_from, size_to}, TF::DT_FLOAT); + TF::Tensor init_v + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(size_from), (long long)(size_to)}); + float* init_v_data = init_v.flat().data(); + for (std::size_t s = 0; s < size_from; ++ s) + for (std::size_t ss = 0; ss < size_to; ++ ss) + init_v_data[ss * size_from + s] = 0.f; + assigners.push_back (TFops::Assign (*m_root, v, init_v)); + + m_gradient_descent.push_back (TFops::ApplyAdam + (*m_root, + weights[i], + m, + v, + TFops::Cast(*m_root, 0.9, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.999, TF::DT_FLOAT), + TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.9, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.999, TF::DT_FLOAT), + TFops::Cast(*m_root, 1e-8, TF::DT_FLOAT), + {gradients[i]})); + } + + for (std::size_t i = 0; i < bias.size(); ++ i) + { + long long size_from = 0; + long long size_to = 0; + if (i == 0) + size_to = hl[0]; + else if (i == bias.size() - 1) + size_to = m_labels.size(); + else + size_to = hl[i]; + + TFops::Variable m (*m_root, { 1, size_to}, TF::DT_FLOAT); + TF::Tensor init_m + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(1), (long long)(size_to)}); + float* init_m_data = init_m.flat().data(); + for (std::size_t s = 0; s < size_to; ++ s) + init_m_data[s] = 0.f; + assigners.push_back (TFops::Assign (*m_root, m, init_m)); + + TFops::Variable v (*m_root, { 1, size_to}, TF::DT_FLOAT); + TF::Tensor init_v + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(1), (long long)(size_to)}); + float* init_v_data = init_v.flat().data(); + for (std::size_t s = 0; s < size_to; ++ s) + init_v_data[s] = 0.f; + assigners.push_back (TFops::Assign (*m_root, v, init_v)); + + m_gradient_descent.push_back (TFops::ApplyAdam + (*m_root, + bias[i], + m, + v, + TFops::Cast(*m_root, 0.9, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.999, TF::DT_FLOAT), + TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.9, TF::DT_FLOAT), + TFops::Cast(*m_root, 0.999, TF::DT_FLOAT), + TFops::Cast(*m_root, 1e-8, TF::DT_FLOAT), + {gradients[weights.size() + i]})); + } + +#else for (std::size_t i = 0; i < weights.size(); ++ i) m_gradient_descent.push_back (TFops::ApplyGradientDescent (*m_root, weights[i], @@ -812,28 +956,32 @@ private: m_gradient_descent.push_back (TFops::ApplyGradientDescent (*m_root, bias[i], TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), {gradients[weights.size() + i]})); - +#endif if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } - CGAL_CLASSTRAINING_CERR << " 6) Starting session" << std::endl; + if (m_verbose) std::cerr << " 6) Starting session" << std::endl; m_session = new TF::ClientSession (*m_root); + if (!m_root->status().ok()) + { + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; + return; + } std::vector outputs; - std::vector assign_weights_and_bias; for (std::size_t i = 0; i < assign_weights.size(); ++ i) - assign_weights_and_bias.push_back (TF::Output(assign_weights[i])); + assigners.push_back (TF::Output(assign_weights[i])); for (std::size_t i = 0; i < assign_bias.size(); ++ i) - assign_weights_and_bias.push_back (TF::Output(assign_bias[i])); - TF_CHECK_OK (m_session->Run(assign_weights_and_bias, nullptr)); + assigners.push_back (TF::Output(assign_bias[i])); + TF_CHECK_OK (m_session->Run(assigners, nullptr)); if (!m_root->status().ok()) { - CGAL_CLASSTRAINING_CERR << "Error: " << m_root->status().ToString() << std::endl; + if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index bbebfb8c4e5..67a2ffe1e35 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -185,15 +185,19 @@ public: addDockWidget(dock_widget); addDockWidget(dock_widget_adv); + ui_widget.classifier->addItem (tr("Random Forest (ETHZ)")); + +#ifdef CGAL_LINKED_WITH_TENSORFLOW + ui_widget.classifier->addItem (tr("Neural Network (TensorFlow)")); +#endif + #ifdef CGAL_LINKED_WITH_OPENCV ui_widget.classifier->addItem (tr("Random Forest (OpenCV %1.%2)") .arg(CV_MAJOR_VERSION) .arg(CV_MINOR_VERSION)); #endif + ui_widget.classifier->addItem (tr("Sum of Weighted Features")); -#ifdef CGAL_LINKED_WITH_TENSORFLOW - ui_widget.classifier->addItem (tr("Neural Network (TensorFlow)")); -#endif color_att = QColor (75, 75, 77); @@ -508,12 +512,27 @@ public Q_SLOTS: update_plugin_from_item(classif); return classif; } + + int get_classifier () + { + if (ui_widget.classifier->currentText() == QString("Random Forest (ETHZ)")) + return 1; + if (ui_widget.classifier->currentText() == QString("Neural Network (TensorFlow)")) + return 3; + if (ui_widget.classifier->currentText() == QString("Random Forest (OpenCV")) + return 2; + if (ui_widget.classifier->currentText() == QString("Sum of Weighted Features")) + return 0; + + std::cerr << "Error: unknown classifier" << std::endl; + return -1; + } void run (Item_classification_base* classif, int method, std::size_t subdivisions = 1, double smoothing = 0.5) { - classif->run (method, ui_widget.classifier->currentIndex(), subdivisions, smoothing); + classif->run (method, get_classifier(), subdivisions, smoothing); } void on_classifier_changed (int index) @@ -566,18 +585,19 @@ public Q_SLOTS: QString filename; - if (ui_widget.classifier->currentIndex() == 0) + int classifier = get_classifier(); + if (classifier == 0) // Sum of Weighted Featuers filename = QFileDialog::getSaveFileName(mw, tr("Save classification configuration"), tr("%1 (CGAL classif config).xml").arg(classif->item()->name()), "CGAL classification configuration (*.xml);;"); - else if (ui_widget.classifier->currentIndex() == 1) + else if (classifier == 1) // Random Forest (ETHZ) filename = QFileDialog::getSaveFileName(mw, tr("Save classification configuration"), tr("%1 (ETHZ random forest config).gz").arg(classif->item()->name()), "Compressed ETHZ random forest configuration (*.gz);;"); #ifdef CGAL_LINKED_WITH_OPENCV - else if (ui_widget.classifier->currentIndex() == 2) + else if (classifier == 2) // Random Forest (OpenCV) filename = QFileDialog::getSaveFileName(mw, tr("Save classification configuration"), tr("%1 (OpenCV %2.%3 random forest config).xml") @@ -588,6 +608,13 @@ public Q_SLOTS: .arg(CV_MAJOR_VERSION) .arg(CV_MINOR_VERSION)); #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + else if (classifier == 3) // Neural Network (TensorFlow) + filename = QFileDialog::getSaveFileName(mw, + tr("Save classification configuration"), + tr("%1 (CGAL Neural Network config).xml").arg(classif->item()->name()), + "CGAL TensorFlow Neural Network classification configuration (*.xml);;"); +#endif if (filename == QString()) return; @@ -595,8 +622,7 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); - classif->save_config (filename.toStdString().c_str(), - ui_widget.classifier->currentIndex()); + classif->save_config (filename.toStdString().c_str(), classifier); QApplication::restoreOverrideCursor(); @@ -613,18 +639,19 @@ public Q_SLOTS: } QString filename; - if (ui_widget.classifier->currentIndex() == 0) + int classifier = get_classifier(); + if (classifier == 0) // SOWF filename = QFileDialog::getOpenFileName(mw, tr("Open CGAL classification configuration"), ".", "CGAL classification configuration (*.xml);;All Files (*)"); - else if (ui_widget.classifier->currentIndex() == 1) + else if (classifier == 1) // ETHZ filename = QFileDialog::getOpenFileName(mw, tr("Open ETHZ random forest configuration"), ".", "Compressed ETHZ random forest configuration (*.gz);;All Files (*)"); #ifdef CGAL_LINKED_WITH_OPENCV - else if (ui_widget.classifier->currentIndex() == 2) + else if (classifier == 2) // OpenCV filename = QFileDialog::getOpenFileName(mw, tr("Open OpenCV %2.%3 random forest configuration") .arg(CV_MAJOR_VERSION) @@ -634,14 +661,21 @@ public Q_SLOTS: .arg(CV_MAJOR_VERSION) .arg(CV_MINOR_VERSION)); #endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + else if (classifier == 3) // TensorFlow + filename = QFileDialog::getOpenFileName(mw, + tr("Open CGAL Neural Network classification configuration"), + ".", + tr("CGAL Neural Network classification configuration (*.xml);;All Files (*)")); +#endif if (filename == QString()) return; QApplication::setOverrideCursor(Qt::WaitCursor); - classif->load_config (filename.toStdString().c_str(), - ui_widget.classifier->currentIndex()); + classif->load_config (filename.toStdString().c_str(), classifier); + update_plugin_from_item(classif); run (classif, 0); @@ -1084,37 +1118,48 @@ public Q_SLOTS: int num_trees = 0; int max_depth = 0; - if (ui_widget.classifier->currentIndex() == 0 || ui_widget.classifier->currentIndex() == 3) + QMultipleInputDialog dialog ("Train Classifier", mw); + + int classifier = get_classifier(); + if (classifier == 0) // SOWF { - bool ok = false; - nb_trials = QInputDialog::getInt((QWidget*)mw, - tr("Train Classifier"), // dialog title - tr("Number of trials:"), // field label - 800, 1, 99999, 50, &ok); - if (!ok) - return; + QSpinBox* trials = dialog.add ("Number of trials: ", "trials"); + trials->setRange (1, 99999); + trials->setValue (800); } - else + else if (classifier == 1 || classifier == 2) // random forest { - QMultipleInputDialog dialog ("Train Random Forest Classifier", mw); - QSpinBox* trees = dialog.add ("Number of trees: "); + QSpinBox* trees = dialog.add ("Number of trees: ", "num_trees"); trees->setRange (1, 9999); trees->setValue (25); - QSpinBox* depth = dialog.add ("Maximum depth of tree: "); + QSpinBox* depth = dialog.add ("Maximum depth of tree: ", "max_depth"); depth->setRange (1, 9999); depth->setValue (20); - - if (dialog.exec() != QDialog::Accepted) - return; - num_trees = trees->value(); - max_depth = depth->value(); } + else if (classifier == 3) // neural network + { + QSpinBox* trials = dialog.add ("Number of trials: ", "trials"); + trials->setRange (1, 99999); + trials->setValue (5000); + QDoubleSpinBox* rate = dialog.add ("Learning rate: ", "learning_rate"); + rate->setRange (0.00001, 10000.0); + rate->setValue (0.1); + rate->setDecimals (5); + QSpinBox* batch = dialog.add ("Batch size: ", "batch_size"); + batch->setRange (1, 2000000000); + batch->setValue (1000); + QLineEdit* layers = dialog.add ("Hidden layer size(s): ", "hidden_layers"); + QCheckBox* restart = dialog.add ("Restart from scratch: ", "restart"); + restart->setChecked (false); + } + + if (dialog.exec() != QDialog::Accepted) + return; QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Real_timer t; t.start(); - classif->train(ui_widget.classifier->currentIndex(), nb_trials, - num_trees, max_depth); + classif->train(classifier, dialog); t.stop(); std::cerr << "Done in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index 486e4a6d516..e0f452b086b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -98,18 +98,8 @@ - 1 + -1 - - - Sum of Weighted Features - - - - - Random Forest (ETHZ) - - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index d8e20fd778f..970234b174b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -696,8 +696,7 @@ void Cluster_classification::add_remaining_point_set_properties_as_features(Feat } } -void Cluster_classification::train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth) +void Cluster_classification::train(int classifier, const QMultipleInputDialog& dialog) { if (m_features.size() == 0) { @@ -730,14 +729,16 @@ void Cluster_classification::train(int classifier, unsigned int nb_trials, if (classifier == 0) { - m_sowf->train(training, nb_trials); + m_sowf->train(training, dialog.get("trials")->value()); CGAL::Classification::classify (m_clusters, m_labels, *m_sowf, indices); } else if (classifier == 1) { - m_ethz->train(training, true, num_trees, max_depth); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (m_clusters, m_labels, *m_ethz, indices); @@ -748,8 +749,8 @@ void Cluster_classification::train(int classifier, unsigned int nb_trials, if (m_random_forest != NULL) delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features, - int(max_depth), 5, 15, - int(num_trees)); + dialog.get("max_depth")->value(), 5, 15, + dialog.get("num_trees")->value()); m_random_forest->train (training); CGAL::Classification::classify (m_clusters, m_labels, *m_random_forest, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index 190692f07c4..eff9c99cba7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -202,8 +202,7 @@ class Cluster_classification : public Item_classification_base if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } - void train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth); + void train(int classifier, const QMultipleInputDialog& dialog); bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color () { change_color (m_index_color); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index a061f48be54..45030506c3b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -53,8 +54,7 @@ public: virtual void select_random_region() = 0; virtual void validate_selection () = 0; - virtual void train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth) = 0; + virtual void train(int classifier, const QMultipleInputDialog&) = 0; virtual bool run (int method, int classifier, std::size_t subdivisions, double smoothing) = 0; virtual void update_color () = 0; @@ -180,10 +180,17 @@ public: std::ofstream f (filename, std::ios_base::out | std::ios_base::binary); m_ethz->save_configuration (f); } - else + else if (classifier == 2) { #ifdef CGAL_LINKED_WITH_OPENCV m_random_forest->save_configuration (filename); +#endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + std::ofstream f (filename); + m_neural_network->save_configuration (f); #endif } } @@ -205,10 +212,19 @@ public: std::ifstream f (filename, std::ios_base::in | std::ios_base::binary); m_ethz->load_configuration (f); } - else + else if (classifier == 2) { #ifdef CGAL_LINKED_WITH_OPENCV m_random_forest->load_configuration (filename); +#endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network == NULL) + m_neural_network = new Neural_network (m_labels, m_features); + std::ifstream f (filename); + m_neural_network->load_configuration (f, true); #endif } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index 1fe42545224..b981ea06287 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include @@ -417,18 +419,30 @@ void Point_set_item_classification::change_color (int index) else { corrected_index -= m_labels.size(); + if (corrected_index >= m_features.size()) + { + std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl; + return; + } Feature_handle feature = m_features[corrected_index]; - float max = 0.; + float min = std::numeric_limits::max(); + float max = -std::numeric_limits::max(); + for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) + { if (feature->value(*it) > max) max = feature->value(*it); + if (feature->value(*it) < min) + min = feature->value(*it); + } + std::cerr << "[Feature " << feature->name() << "] between " << min << " and " << max << std::endl; for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { - float v = std::max (0.f, feature->value(*it) / max); + float v = (feature->value(*it) - min) / (max - min); m_red[*it] = (unsigned char)(ramp.r(v) * 255); m_green[*it] = (unsigned char)(ramp.g(v) * 255); m_blue[*it] = (unsigned char)(ramp.b(v) * 255); @@ -647,8 +661,7 @@ void Point_set_item_classification::add_remaining_point_set_properties_as_featur } } -void Point_set_item_classification::train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth) +void Point_set_item_classification::train(int classifier, const QMultipleInputDialog& dialog) { if (m_features.size() == 0) { @@ -683,7 +696,7 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials if (classifier == 0) { - m_sowf->train(training, nb_trials); + m_sowf->train(training, dialog.get("trials")->value()); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_sowf, indices, m_label_probabilities); @@ -693,7 +706,9 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials if (m_ethz != NULL) delete m_ethz; m_ethz = new ETHZ_random_forest (m_labels, m_features); - m_ethz->train(training, true, num_trees, max_depth); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_ethz, indices, m_label_probabilities); @@ -704,21 +719,54 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials if (m_random_forest != NULL) delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features, - int(max_depth), 5, 15, - int(num_trees)); + dialog.get("max_depth")->value(), 5, 15, + dialog.get("num_trees")->value()); m_random_forest->train (training); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_random_forest, indices, m_label_probabilities); - } - else - { #endif + } + else if (classifier == 3) + { #ifdef CGAL_LINKED_WITH_TENSORFLOW if (m_neural_network != NULL) - delete m_neural_network; - m_neural_network = new Neural_network (m_labels, m_features); - m_neural_network->train (training, nb_trials); + { + if (m_neural_network->initialized()) + { + if (dialog.get("restart")->isChecked()) + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + m_neural_network = new Neural_network (m_labels, m_features); + + std::vector hidden_layers; + + std::string hl_input = dialog.get("hidden_layers")->text().toStdString(); + if (hl_input != "") + { + std::istringstream iss(hl_input); + int s; + while (iss >> s) + hidden_layers.push_back (std::size_t(s)); + } + + m_neural_network->train (training, + dialog.get("restart")->isChecked(), + dialog.get("trials")->value(), + dialog.get("learning_rate")->value(), + dialog.get("batch_size")->value(), + hidden_layers); + CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_neural_network, indices, m_label_probabilities); @@ -764,10 +812,10 @@ bool Point_set_item_classification::run (int method, int classifier, return false; } run (method, *m_random_forest, subdivisions, smoothing); - } - else - { #endif + } + else if (classifier == 3) + { #ifdef CGAL_LINKED_WITH_TENSORFLOW if (m_neural_network == NULL) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 742f0a0a7ef..a5d2b6636ac 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -130,8 +130,12 @@ class Point_set_item_classification : public Item_classification_base Pmap pmap; boost::tie (pmap, okay) = m_points->point_set()->template property_map(name.c_str()); if (okay) + { + std::cerr << "Adding property<" << CGAL::demangle(typeid(Type).name()) << ">(" + << name << ") as feature" << std::endl; m_features.template add > (*(m_points->point_set()), pmap, name.c_str()); + } return okay; } @@ -187,8 +191,7 @@ class Point_set_item_classification : public Item_classification_base if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } - void train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth); + void train(int classifier, const QMultipleInputDialog& dialog); bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color () { change_color (m_index_color); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 8c778bc3c58..885e418f09c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -183,9 +183,7 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales) std::cerr << "Features = " << m_features.size() << std::endl; } -void Surface_mesh_item_classification::train -(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth) +void Surface_mesh_item_classification::train (int classifier, const QMultipleInputDialog& dialog) { if (m_features.size() == 0) { @@ -216,14 +214,16 @@ void Surface_mesh_item_classification::train if (classifier == 0) { - m_sowf->train(training, nb_trials); + m_sowf->train(training, dialog.get("trials")->value()); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_sowf, indices); } else if (classifier == 1) { - m_ethz->train(training, true, num_trees, max_depth); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_ethz, indices); @@ -234,8 +234,8 @@ void Surface_mesh_item_classification::train if (m_random_forest != NULL) delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features, - int(max_depth), 5, 15, - int(num_trees)); + dialog.get("max_depth")->value(), 5, 15, + dialog.get("num_trees")->value()); m_random_forest->train (training); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h index 238d160c2eb..5c9cd4f9fff 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h @@ -116,8 +116,7 @@ public: if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } - void train(int classifier, unsigned int nb_trials, - std::size_t num_trees, std::size_t max_depth); + void train(int classifier, const QMultipleInputDialog& dialog); bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color() { change_color (m_index_color); } diff --git a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h index 17147651f29..cf6ae9db3a0 100644 --- a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h +++ b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h @@ -14,6 +14,9 @@ class QMultipleInputDialog { QDialog* dialog; QFormLayout* form; + std::map map_widgets; + + public: QMultipleInputDialog (const char* name, QWidget* parent) { @@ -27,13 +30,27 @@ public: } template - QObjectType* add (const char* name) + QObjectType* add (const char* name, const char* key = NULL) { QObjectType* out = new QObjectType (dialog); form->addRow (QString(name), out); + if (key != NULL) + map_widgets.insert (std::make_pair (key, out)); return out; } + template + const QObjectType* get (const char* key) const + { + typename std::map::const_iterator + found = map_widgets.find (key); + if (found == map_widgets.end()) + return NULL; + + QWidget* widget_out = found->second; + return qobject_cast(widget_out); + } + int exec() { QDialogButtonBox* oknotok = new QDialogButtonBox From 4df1d0a966d738e39e8d9a50145ad877f46694c1 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 22 Jun 2018 09:35:18 +0200 Subject: [PATCH 029/186] Fix advanced plugin display --- .../Plugins/Classification/Classification_plugin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 67a2ffe1e35..1c560a1f8b3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -203,8 +203,8 @@ public: ui_widget.menu->setMenu (new QMenu("Classification Menu", ui_widget.menu)); - connect(ui_widget.classifier, SIGNAL(currentIndexChanged(int)), this, - SLOT(on_classifier_changed(int))); + connect(ui_widget.classifier, SIGNAL(currentTextChanged(QString)), this, + SLOT(on_classifier_changed(QString))); QAction* compute_features = ui_widget.menu->menu()->addAction ("Compute features"); connect(compute_features, SIGNAL(triggered()), this, @@ -535,9 +535,9 @@ public Q_SLOTS: classif->run (method, get_classifier(), subdivisions, smoothing); } - void on_classifier_changed (int index) + void on_classifier_changed (const QString& name) { - if (index == 0) + if (name == QString("Sum of Weighted Features")) { dock_widget_adv->show(); dock_widget_adv->raise(); From 8af631874d62ff30e4bd3e946081ca063ad2f79b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 22 Jun 2018 14:12:58 +0200 Subject: [PATCH 030/186] Update plugin with latest changes --- .../Classification/Classification_plugin.cpp | 4 +- .../Classification/Cluster_classification.cpp | 212 +++++++++++++++--- .../Classification/Cluster_classification.h | 10 +- .../Surface_mesh_item_classification.cpp | 176 +++++++++++++-- .../Surface_mesh_item_classification.h | 2 + 5 files changed, 337 insertions(+), 67 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 1c560a1f8b3..92b45162a3d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -1140,10 +1140,10 @@ public Q_SLOTS: { QSpinBox* trials = dialog.add ("Number of trials: ", "trials"); trials->setRange (1, 99999); - trials->setValue (5000); + trials->setValue (500); QDoubleSpinBox* rate = dialog.add ("Learning rate: ", "learning_rate"); rate->setRange (0.00001, 10000.0); - rate->setValue (0.1); + rate->setValue (0.001); rate->setDecimals (5); QSpinBox* batch = dialog.add ("Batch size: ", "batch_size"); batch->setRange (1, 2000000000); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 970234b174b..a53e825ac04 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include #include @@ -221,9 +223,12 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po update_comments_of_point_set_item(); m_sowf = new Sum_of_weighted_features (m_labels, m_features); - m_ethz = new ETHZ_random_forest (m_labels, m_features); + m_ethz = NULL; #ifdef CGAL_LINKED_WITH_OPENCV - m_random_forest = new Random_forest (m_labels, m_features); + m_random_forest = NULL; +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + m_neural_network = NULL; #endif // Compute neighborhood @@ -290,6 +295,10 @@ Cluster_classification::~Cluster_classification() #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) delete m_random_forest; +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + delete m_neural_network; #endif if (m_points != NULL) { @@ -467,40 +476,84 @@ void Cluster_classification::change_color (int index) } else { - Feature_handle feature = m_features[index_color - 4]; - - float max = 0.; - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) + std::size_t corrected_index = index_color - 4; + if (corrected_index < m_labels.size()) // Display label probabilities { - int cid = m_cluster_id[*it]; - if (cid != -1) + if (m_label_probabilities.size() <= corrected_index || + m_label_probabilities[corrected_index].size() != m_clusters.size()) { - if (feature->value(cid) > max) - max = feature->value(cid); - } - } - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - int cid = m_cluster_id[*it]; - if (cid != -1) - { - float v = std::max (0.f, feature->value(cid) / max); - m_red[*it] = (unsigned char)(ramp.r(v) * 255); - m_green[*it] = (unsigned char)(ramp.g(v) * 255); - m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + m_red[*it] = 0; + m_green[*it] = 0; + m_blue[*it] = 0; + } } else { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + if (cid != -1) + { + float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][cid])); + m_red[*it] = (unsigned char)(ramp.r(v) * 255); + m_green[*it] = (unsigned char)(ramp.g(v) * 255); + m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + } + else + { + m_red[*it] = 0; + m_green[*it] = 0; + m_blue[*it] = 0; + } + } + } + } + else + { + corrected_index -= m_labels.size(); + Feature_handle feature = m_features[corrected_index]; + + float min = std::numeric_limits::max(); + float max = -std::numeric_limits::max(); + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + if (cid != -1) + { + if (feature->value(cid) > max) + max = feature->value(cid); + if (feature->value(*it) < min) + min = feature->value(cid); + } + } + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + if (cid != -1) + { + float v = (feature->value(cid) - min) / (max - min); + m_red[*it] = (unsigned char)(ramp.r(v) * 255); + m_green[*it] = (unsigned char)(ramp.g(v) * 255); + m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + } + else + { + m_red[*it] = 0; + m_green[*it] = 0; + m_blue[*it] = 0; + } } } } - + for (Point_set::const_iterator it = m_points->point_set()->first_selected(); it != m_points->point_set()->end(); ++ it) { @@ -620,11 +673,24 @@ void Cluster_classification::compute_features (std::size_t nb_scales) delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); - delete m_ethz; - m_ethz = new ETHZ_random_forest (m_labels, m_features); + if (m_ethz != NULL) + { + delete m_ethz; + m_ethz = NULL; + } #ifdef CGAL_LINKED_WITH_OPENCV - delete m_random_forest; - m_random_forest = new Random_forest (m_labels, m_features); + if (m_random_forest != NULL) + { + delete m_random_forest; + m_random_forest = NULL; + } +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + { + delete m_neural_network; + m_neural_network = NULL; + } #endif std::cerr << "Features = " << m_features.size() << std::endl; @@ -705,6 +771,8 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d } reset_indices(); + m_label_probabilities.clear(); + std::vector nb_label (m_labels.size(), 0); std::size_t nb_total = 0; @@ -732,7 +800,7 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d m_sowf->train(training, dialog.get("trials")->value()); CGAL::Classification::classify (m_clusters, m_labels, *m_sowf, - indices); + indices, m_label_probabilities); } else if (classifier == 1) { @@ -741,9 +809,9 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d dialog.get("max_depth")->value()); CGAL::Classification::classify (m_clusters, m_labels, *m_ethz, - indices); + indices, m_label_probabilities); } - else + else if (classifier == 2) { #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) @@ -754,7 +822,52 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d m_random_forest->train (training); CGAL::Classification::classify (m_clusters, m_labels, *m_random_forest, - indices); + indices, m_label_probabilities); +#endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + { + if (m_neural_network->initialized()) + { + if (dialog.get("restart")->isChecked()) + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + m_neural_network = new Neural_network (m_labels, m_features); + + std::vector hidden_layers; + + std::string hl_input = dialog.get("hidden_layers")->text().toStdString(); + if (hl_input != "") + { + std::istringstream iss(hl_input); + int s; + while (iss >> s) + hidden_layers.push_back (std::size_t(s)); + } + + m_neural_network->train (training, + dialog.get("restart")->isChecked(), + dialog.get("trials")->value(), + dialog.get("learning_rate")->value(), + dialog.get("batch_size")->value(), + hidden_layers); + + CGAL::Classification::classify (m_clusters, + m_labels, *m_neural_network, + indices, m_label_probabilities); #endif } @@ -779,11 +892,36 @@ bool Cluster_classification::run (int method, int classifier, if (classifier == 0) run (method, *m_sowf, subdivisions, smoothing); else if (classifier == 1) + { + if (m_ethz == NULL) + { + std::cerr << "Error: ETHZ Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_ethz, subdivisions, smoothing); + } + else if (classifier == 2) + { #ifdef CGAL_LINKED_WITH_OPENCV - else + if (m_random_forest == NULL) + { + std::cerr << "Error: OpenCV Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_random_forest, subdivisions, smoothing); #endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network == NULL) + { + std::cerr << "Error: TensorFlow Neural Network must be trained or have a configuration loaded first" << std::endl; + return false; + } + run (method, *m_neural_network, subdivisions, smoothing); +#endif + } return true; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index eff9c99cba7..cfea6dbf015 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -286,13 +286,7 @@ class Cluster_classification : public Item_classification_base void fill_display_combo_box (QComboBox* cb, QComboBox* cb1) const { cb->addItem ("Clusters"); - for (std::size_t i = 0; i < m_features.size(); ++ i) - { - std::ostringstream oss; - oss << "Feature " << m_features[i]->name(); - cb->addItem (oss.str().c_str()); - cb1->addItem (oss.str().c_str()); - } + Item_classification_base::fill_display_combo_box(cb, cb1); } int real_index_color() const; @@ -398,6 +392,8 @@ class Cluster_classification : public Item_classification_base Point_set::Property_map m_training; Point_set::Property_map m_classif; + std::vector > m_label_probabilities; + int m_index_color; boost::shared_ptr m_eigen; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 885e418f09c..aff3f4ea0ab 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -6,6 +6,8 @@ #include +#include + #include #include #include @@ -31,9 +33,12 @@ Surface_mesh_item_classification::Surface_mesh_item_classification(Scene_surface m_label_colors.push_back (this->get_new_label_color (m_labels[i]->name())); m_sowf = new Sum_of_weighted_features (m_labels, m_features); - m_ethz = new ETHZ_random_forest (m_labels, m_features); + m_ethz = NULL; #ifdef CGAL_LINKED_WITH_OPENCV - m_random_forest = new Random_forest (m_labels, m_features); + m_random_forest = NULL; +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + m_neural_network = NULL; #endif } @@ -47,6 +52,10 @@ Surface_mesh_item_classification::~Surface_mesh_item_classification() #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) delete m_random_forest; +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + delete m_neural_network; #endif if (m_generator != NULL) delete m_generator; @@ -132,21 +141,59 @@ void Surface_mesh_item_classification::change_color (int index) } else { - Feature_handle feature = m_features[index_color - 3]; - - float max = 0.; - BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + std::size_t corrected_index = index_color - 3; + if (corrected_index < m_labels.size()) // Display label probabilities { - if (feature->value(fd) > max) - max = feature->value(fd); + if (m_label_probabilities.size() <= corrected_index || + m_label_probabilities[corrected_index].size() != num_faces(*(m_mesh->polyhedron()))) + { + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + { + m_color[fd] = CGAL::Color((unsigned char)(128), + (unsigned char)(128), + (unsigned char)(128)); + } + } + else + { + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + { + float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][fd])); + m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), + (unsigned char)(ramp.g(v) * 255), + (unsigned char)(ramp.b(v) * 255)); + } + } } - - BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + else { - float v = std::max (0.f, feature->value(fd) / max); - m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), - (unsigned char)(ramp.g(v) * 255), - (unsigned char)(ramp.b(v) * 255)); + corrected_index -= m_labels.size(); + if (corrected_index >= m_features.size()) + { + std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl; + return; + } + + Feature_handle feature = m_features[corrected_index]; + + float min = std::numeric_limits::max(); + float max = -std::numeric_limits::max(); + + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + { + if (feature->value(fd) > max) + max = feature->value(fd); + if (feature->value(fd) < min) + min = feature->value(fd); + } + + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + { + float v = (feature->value(fd) - min) / (max - min); + m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), + (unsigned char)(ramp.g(v) * 255), + (unsigned char)(ramp.b(v) * 255)); + } } } } @@ -176,9 +223,24 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales) delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); + if (m_ethz != NULL) + { + delete m_ethz; + m_ethz = NULL; + } #ifdef CGAL_LINKED_WITH_OPENCV - delete m_random_forest; - m_random_forest = new Random_forest (m_labels, m_features); + if (m_random_forest != NULL) + { + delete m_random_forest; + m_random_forest = NULL; + } +#endif +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + { + delete m_neural_network; + m_neural_network = NULL; + } #endif std::cerr << "Features = " << m_features.size() << std::endl; } @@ -191,6 +253,8 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp return; } + m_label_probabilities.clear(); + std::vector training (num_faces(*(m_mesh->polyhedron())), std::size_t(-1)); std::vector indices (num_faces(*(m_mesh->polyhedron())), std::size_t(-1)); @@ -217,7 +281,7 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp m_sowf->train(training, dialog.get("trials")->value()); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_sowf, - indices); + indices, m_label_probabilities); } else if (classifier == 1) { @@ -226,9 +290,9 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp dialog.get("max_depth")->value()); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_ethz, - indices); + indices, m_label_probabilities); } - else + else if (classifier == 2) { #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) @@ -240,7 +304,52 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_random_forest, - indices); + indices, m_label_probabilities); +#endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network != NULL) + { + if (m_neural_network->initialized()) + { + if (dialog.get("restart")->isChecked()) + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + { + delete m_neural_network; + m_neural_network = new Neural_network (m_labels, m_features); + } + } + else + m_neural_network = new Neural_network (m_labels, m_features); + + std::vector hidden_layers; + + std::string hl_input = dialog.get("hidden_layers")->text().toStdString(); + if (hl_input != "") + { + std::istringstream iss(hl_input); + int s; + while (iss >> s) + hidden_layers.push_back (std::size_t(s)); + } + + m_neural_network->train (training, + dialog.get("restart")->isChecked(), + dialog.get("trials")->value(), + dialog.get("learning_rate")->value(), + dialog.get("batch_size")->value(), + hidden_layers); + + CGAL::Classification::classify (m_mesh->polyhedron()->faces(), + m_labels, *m_neural_network, + indices, m_label_probabilities); #endif } @@ -263,11 +372,36 @@ bool Surface_mesh_item_classification::run (int method, int classifier, if (classifier == 0) run (method, *m_sowf, subdivisions, smoothing); else if (classifier == 1) + { + if (m_ethz == NULL) + { + std::cerr << "Error: ETHZ Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_ethz, subdivisions, smoothing); + } + else if (classifier == 2) + { #ifdef CGAL_LINKED_WITH_OPENCV - else + if (m_random_forest == NULL) + { + std::cerr << "Error: OpenCV Random Forest must be trained or have a configuration loaded first" << std::endl; + return false; + } run (method, *m_random_forest, subdivisions, smoothing); #endif + } + else if (classifier == 3) + { +#ifdef CGAL_LINKED_WITH_TENSORFLOW + if (m_neural_network == NULL) + { + std::cerr << "Error: TensorFlow Neural Network must be trained or have a configuration loaded first" << std::endl; + return false; + } + run (method, *m_neural_network, subdivisions, smoothing); +#endif + } return true; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h index 5c9cd4f9fff..b3a40b78fe5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h @@ -209,6 +209,8 @@ protected: Mesh::Property_map m_color; Mesh::Property_map m_real_color; + std::vector > m_label_probabilities; + Generator* m_generator; int m_index_color; }; From 61e853c22401e674e8677f8c77c665ae9c4930e8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 22 Jun 2018 22:52:42 +0200 Subject: [PATCH 031/186] Fix segfault --- .../Plugins/Classification/Cluster_classification.cpp | 3 +++ .../Classification/Surface_mesh_item_classification.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index a53e825ac04..916e3423971 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -804,6 +804,9 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d } else if (classifier == 1) { + if (m_ethz != NULL) + delete m_ethz; + m_ethz = new ETHZ_random_forest (m_labels, m_features); m_ethz->train(training, true, dialog.get("num_trees")->value(), dialog.get("max_depth")->value()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index aff3f4ea0ab..003c132e916 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -285,6 +285,9 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp } else if (classifier == 1) { + if (m_ethz != NULL) + delete m_ethz; + m_ethz = new ETHZ_random_forest (m_labels, m_features); m_ethz->train(training, true, dialog.get("num_trees")->value(), dialog.get("max_depth")->value()); From 9a234d260a0aaa799db78232f1fbe6c79a088876 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 27 Jun 2018 10:22:24 +0200 Subject: [PATCH 032/186] Fix some bugs --- .../Plugins/Classification/Cluster_classification.cpp | 8 +++++++- .../Plugins/Classification/Item_classification_base.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 916e3423971..bda87452066 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -515,6 +515,12 @@ void Cluster_classification::change_color (int index) else { corrected_index -= m_labels.size(); + if (corrected_index >= m_features.size()) + { + std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl; + return; + } + Feature_handle feature = m_features[corrected_index]; float min = std::numeric_limits::max(); @@ -528,7 +534,7 @@ void Cluster_classification::change_color (int index) { if (feature->value(cid) > max) max = feature->value(cid); - if (feature->value(*it) < min) + if (feature->value(cid) < min) min = feature->value(cid); } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 45030506c3b..1c9226b263a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -209,6 +209,8 @@ public: } else if (classifier == 1) { + if (m_ethz == NULL) + m_ethz = new ETHZ_random_forest (m_labels, m_features); std::ifstream f (filename, std::ios_base::in | std::ios_base::binary); m_ethz->load_configuration (f); } From 826fb15b37fbb9902b68b05cc9562c5780dd23be Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 27 Jun 2018 10:22:41 +0200 Subject: [PATCH 033/186] Add possibility to do 3D image instead of 2D --- .../include/CGAL/Classification/Image.h | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/Classification/include/CGAL/Classification/Image.h b/Classification/include/CGAL/Classification/Image.h index 6f2f0ed297a..ffaf0796081 100644 --- a/Classification/include/CGAL/Classification/Image.h +++ b/Classification/include/CGAL/Classification/Image.h @@ -41,6 +41,8 @@ class Image std::size_t m_width; std::size_t m_height; + std::size_t m_depth; + boost::shared_ptr m_raw; boost::shared_ptr m_sparse; Type m_default; @@ -52,18 +54,19 @@ class Image public: - Image () : m_width(0), m_height(0), m_raw (NULL) + Image () : m_width(0), m_height(0), m_depth(0), m_raw (NULL) { } - Image (std::size_t width, std::size_t height) - : m_width (width), - m_height (height) + Image (std::size_t width, std::size_t height, std::size_t depth = 1) + : m_width (width) + , m_height (height) + , m_depth (depth) { - if (m_width * m_height > 0) + if (m_width * m_height * m_depth > 0) { - if (m_width * m_height < CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT) - m_raw = boost::shared_ptr (new Vector(m_width * m_height)); + if (m_width * m_height * m_depth < CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT) + m_raw = boost::shared_ptr (new Vector(m_width * m_height * m_depth)); else m_sparse = boost::shared_ptr (new Map()); } @@ -85,33 +88,41 @@ public: m_sparse = other.m_sparse; m_width = other.width(); m_height = other.height(); + m_depth = other.depth(); return *this; } std::size_t width() const { return m_width; } std::size_t height() const { return m_height; } + std::size_t depth() const { return m_depth; } - Type& operator() (const std::size_t& x, const std::size_t& y) + inline std::size_t coord (const std::size_t& x, const std::size_t& y, const std::size_t& z) const + { + return z + (m_depth * y) + (m_depth * m_height * x); + } + + Type& operator() (const std::size_t& x, const std::size_t& y, const std::size_t& z = 0) { if (m_raw == boost::shared_ptr()) // sparse case { - typename Map::iterator inserted = m_sparse->insert (std::make_pair (x * m_height + y, Type())).first; + typename Map::iterator inserted = m_sparse->insert + (std::make_pair (coord(x,y,z), Type())).first; return inserted->second; } - return (*m_raw)[x * m_height + y]; + return (*m_raw)[coord(x,y,z)]; } - const Type& operator() (const std::size_t& x, const std::size_t& y) const + const Type& operator() (const std::size_t& x, const std::size_t& y, const std::size_t& z = 0) const { if (m_raw == boost::shared_ptr()) // sparse case { - typename Map::iterator found = m_sparse->find (x * m_height + y); + typename Map::iterator found = m_sparse->find (coord(x,y,z)); if (found != m_sparse->end()) return found->second; return m_default; } - return (*m_raw)[x * m_height + y]; + return (*m_raw)[coord(x,y,z)]; } From 335375dbba738f2b0f4265cad279472f670220c3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 27 Jun 2018 10:24:40 +0200 Subject: [PATCH 034/186] Fix verbosity --- .../TensorFlow_neural_network_classifier.h | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index f8ac8d48f28..d539c9e5e49 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -128,9 +128,10 @@ public: bool initialized() const { return (m_root != NULL); } + bool& verbose() { return m_verbose; } + void clear() { - if (m_verbose) std::cerr << "(Clearing Neural Network classifier)" << std::endl; clear (m_ph_gt); clear (m_ph_ft); clear (m_loss); @@ -187,8 +188,9 @@ public: if (std::isnan(m_feature_sd[f])) m_feature_sd[f] = 1.f; - std::cerr << "#" << f << ": " << m_features[f]->name() << " = " - << m_feature_means[f] << " +/- " << m_feature_sd[f] << std::endl; + // if (m_verbose) + // std::cerr << "#" << f << ": " << m_features[f]->name() << " = " + // << m_feature_means[f] << " +/- " << m_feature_sd[f] << std::endl; } #endif } @@ -212,7 +214,6 @@ public: const std::vector& hidden_layers = std::vector()) { - if (m_verbose) std::cerr << "[Training Neural Network]" << std::endl; if (restart_from_scratch) clear(); @@ -363,7 +364,8 @@ public: } if (!std::isfinite(*outputs[0].scalar().data())) { - std::cerr << "Loss is " << outputs[0].scalar() << ", aborting" << std::endl; + if (m_verbose) + std::cerr << "Loss is " << outputs[0].scalar() << ", aborting" << std::endl; return; } @@ -673,12 +675,14 @@ private: if (m_verbose) std::cerr << " 1) Initializing architecture:" << std::endl << " * Layer 0: " << m_features.size() << " neuron(s) (input features)" << std::endl; - if (!CGAL_CLASSTRAINING_SILENT) + if (m_verbose) for (std::size_t i = 0; i < hl.size(); ++ i) std::cerr << " * Layer " << i+1 << ": " << hl[i] << " neuron(s)" << std::endl; if (m_verbose) std::cerr << " * Layer " << hl.size() + 1 << ": " << m_labels.size() << " neuron(s) (output labels)" << std::endl; + + m_ph_ft = new TFops::Placeholder (*m_root, TF::DT_FLOAT); m_ph_gt = new TFops::Placeholder (*m_root, TF::DT_FLOAT); @@ -965,12 +969,24 @@ private: if (m_verbose) std::cerr << " 6) Starting session" << std::endl; - m_session = new TF::ClientSession (*m_root); + TF::SessionOptions options = TF::SessionOptions(); + + // options.config.mutable_gpu_options()->set_visible_device_list("0"); + // options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.3); + // options.config.mutable_gpu_options()->set_operation_timeout_in_ms(15000); + +// options.config.mutable_gpu_options()->set_visible_device_list(""); + options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.3); + options.config.mutable_gpu_options()->set_allow_growth(true); + options.config.mutable_gpu_options()->set_force_gpu_compatible(true); + + m_session = new TF::ClientSession (*m_root, options); if (!m_root->status().ok()) { if (m_verbose) std::cerr << "Error: " << m_root->status().ToString() << std::endl; return; } + std::vector outputs; for (std::size_t i = 0; i < assign_weights.size(); ++ i) @@ -985,6 +1001,7 @@ private: return; } } + }; } From 4bebcae4f2cdf00a97250259afc0ac1791d4fa5c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 9 Aug 2018 10:11:05 +0200 Subject: [PATCH 035/186] Many improvements for plugin, statistics on features, etc. --- .../Classification/Classification_plugin.cpp | 169 +++++++++++++++- .../Classification/Classification_widget.ui | 188 +++++++++++------- .../Classification/Cluster_classification.cpp | 13 +- .../Classification/Cluster_classification.h | 4 +- .../Classification/Item_classification_base.h | 6 +- .../Point_set_item_classification.cpp | 47 +++-- .../Point_set_item_classification.h | 32 ++- .../Surface_mesh_item_classification.cpp | 13 +- .../Surface_mesh_item_classification.h | 4 +- .../Polyhedron/include/QMultipleInputDialog.h | 10 + 10 files changed, 381 insertions(+), 105 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 92b45162a3d..9cb50727333 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -210,6 +210,10 @@ public: connect(compute_features, SIGNAL(triggered()), this, SLOT(on_compute_features_button_clicked())); + action_statistics = ui_widget.menu->menu()->addAction ("Show feature statistics"); + connect(action_statistics, SIGNAL(triggered()), this, + SLOT(on_statistics_clicked())); + ui_widget.menu->menu()->addSection ("Training"); action_train = ui_widget.menu->menu()->addAction ("Train classifier"); @@ -264,6 +268,11 @@ public: connect(ui_widget.display, SIGNAL(currentIndexChanged(int)), this, SLOT(on_display_button_clicked(int))); + connect(ui_widget.minDisplay, SIGNAL(released()), this, + SLOT(on_min_display_button_clicked())); + connect(ui_widget.maxDisplay, SIGNAL(released()), this, + SLOT(on_max_display_button_clicked())); + connect(ui_widget_adv.selected_feature, SIGNAL(currentIndexChanged(int)), this, SLOT(on_selected_feature_changed(int))); connect(ui_widget_adv.feature_weight, SIGNAL(valueChanged(int)), this, @@ -278,6 +287,7 @@ public: connect(scene_obj, SIGNAL(itemIndexSelected(int)), this, SLOT(update_plugin(int))); } + } virtual void closure() { @@ -359,6 +369,7 @@ public Q_SLOTS: void enable_computation() { ui_widget.menu->setEnabled(true); + action_statistics->setEnabled(false); action_train->setEnabled(false); action_reset_local->setEnabled(false); action_reset->setEnabled(false); @@ -375,6 +386,7 @@ public Q_SLOTS: void enable_classif() { + action_statistics->setEnabled(true); action_train->setEnabled(true); action_reset_local->setEnabled(true); action_reset->setEnabled(true); @@ -428,9 +440,15 @@ public Q_SLOTS: ui_widget_adv.selected_feature->clear(); classif->fill_display_combo_box(ui_widget.display, ui_widget_adv.selected_feature); if (index >= ui_widget.display->count()) + { ui_widget.display->setCurrentIndex(1); + change_color (classif, 1); + } else + { ui_widget.display->setCurrentIndex(index); + change_color (classif, index); + } ui_widget_adv.selected_feature->setCurrentIndex(0); } } @@ -556,17 +574,26 @@ public Q_SLOTS: return; } - bool ok = false; - int nb_scales = QInputDialog::getInt((QWidget*)mw, - tr("Compute Features"), // dialog title - tr("Number of scales:"), // field label - 5, 1, 99, 1, &ok); - if (!ok) + QMultipleInputDialog dialog ("Compute Features", mw); + QSpinBox* scales = dialog.add ("Number of scales:"); + scales->setRange (1, 99); + scales->setValue (5); + + QDoubleSpinBox* voxel_size = dialog.add ("Voxel size (0 for automatic):"); + voxel_size->setRange (0.0, 10000.0); + voxel_size->setValue (0.0); + voxel_size->setSingleStep (0.01); + + if (dialog.exec() != QDialog::Accepted) return; QApplication::setOverrideCursor(Qt::WaitCursor); - classif->compute_features (std::size_t(nb_scales)); + float vsize = float(voxel_size->value()); + if (vsize == 0.f) + vsize = -1.f; // auto value + + classif->compute_features (std::size_t(scales->value()), vsize); update_plugin_from_item(classif); QApplication::restoreOverrideCursor(); @@ -683,7 +710,32 @@ public Q_SLOTS: item_changed(classif->item()); } + void change_color (Item_classification_base* classif, int index) + { + float vmin = std::numeric_limits::infinity(); + float vmax = std::numeric_limits::infinity(); + + classif->change_color (index, &vmin, &vmax); + if (vmin == std::numeric_limits::infinity() || vmax == std::numeric_limits::infinity()) + { + ui_widget.minDisplay->setEnabled(false); + ui_widget.minDisplay->setText("Min"); + ui_widget.maxDisplay->setEnabled(false); + ui_widget.maxDisplay->setText("Max"); + } + else + { + ui_widget.minDisplay->setEnabled(true); + ui_widget.minDisplay->setText(tr("Min (%1)").arg(vmin)); + ui_widget.maxDisplay->setEnabled(true); + ui_widget.maxDisplay->setText(tr("Max (%1)").arg(vmax)); + } + + item_changed(classif->item()); + } + + void on_display_button_clicked(int index) { Item_classification_base* classif @@ -691,7 +743,87 @@ public Q_SLOTS: if(!classif) return; - classif->change_color (index); + change_color (classif, index); + } + + float display_button_value (QPushButton* button) + { + std::string text = button->text().toStdString(); + + std::size_t pos1 = text.find('('); + if (pos1 == std::string::npos) + return std::numeric_limits::infinity(); + std::size_t pos2 = text.find(')'); + if (pos2 == std::string::npos) + return std::numeric_limits::infinity(); + + std::string fstring (text.begin() + pos1 + 1, + text.begin() + pos2); + + return float (std::atof(fstring.c_str())); + } + + void on_min_display_button_clicked() + { + Item_classification_base* classif + = get_classification(); + if(!classif) + return; + + float vmin = display_button_value (ui_widget.minDisplay); + float vmax = display_button_value (ui_widget.maxDisplay); + + if (vmin == std::numeric_limits::infinity() + || vmax == std::numeric_limits::infinity()) + return; + + bool ok = false; + vmin = float(QInputDialog::getDouble((QWidget*)mw, + tr("Set display ramp minimum value (saturate under):"), + tr("Minimum value (pale blue):"), + double(vmin), + -10000000.0, + double(vmax), 5, &ok)); + if (!ok) + return; + + int index = ui_widget.display->currentIndex(); + + classif->change_color (index, &vmin, &vmax); + ui_widget.minDisplay->setText(tr("Min* (%1)").arg(vmin)); + + item_changed(classif->item()); + } + + void on_max_display_button_clicked() + { + Item_classification_base* classif + = get_classification(); + if(!classif) + return; + + float vmin = display_button_value (ui_widget.minDisplay); + float vmax = display_button_value (ui_widget.maxDisplay); + + if (vmin == std::numeric_limits::infinity() + || vmax == std::numeric_limits::infinity()) + return; + + bool ok = false; + vmax = float(QInputDialog::getDouble((QWidget*)mw, + tr("Set display ramp maximum value (saturate over):"), + tr("Maximum value (dark red):"), + double(vmax), + double(vmin), + 10000000.0, 5, &ok)); + if (!ok) + return; + + int index = ui_widget.display->currentIndex(); + + classif->change_color (index, &vmin, &vmax); + ui_widget.maxDisplay->setText(tr("Max* (%1)").arg(vmax)); + item_changed(classif->item()); } @@ -1104,6 +1236,26 @@ public Q_SLOTS: (bbox.zmin() + bbox.zmax()) / 2.) + offset); } + void on_statistics_clicked() + { + Item_classification_base* classif + = get_classification(); + if(!classif) + { + print_message("Error: there is no point set classification item!"); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + std::string str = classif->feature_statistics(); + QApplication::restoreOverrideCursor(); + + QMultipleInputDialog dialog ("Feature Statistics", mw); + QLabel* text = dialog.add (""); + text->setText(str.c_str()); + dialog.exec_no_cancel(); + } + void on_train_clicked() { Item_classification_base* classif @@ -1457,6 +1609,7 @@ private: QDockWidget* dock_widget; QDockWidget* dock_widget_adv; + QAction* action_statistics; QAction* action_train; QAction* action_reset_local; QAction* action_reset; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index e0f452b086b..99a49be0487 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -6,8 +6,8 @@ 0 0 - 289 - 154 + 368 + 143 @@ -20,21 +20,49 @@ Classification - + - + - - - - 75 - true - - - - Classification - - + + + + + + 75 + true + + + + Classification + + + + + + + + + + 0 + 0 + + + + Classifier: + + + + + + + -1 + + + + + + @@ -44,63 +72,87 @@ - - - - 0 - 0 - - - - View: - - - - - - - 0 - + - - Real colors - + + + + + + 0 + 0 + + + + View: + + + + + + + 0 + + + + Real colors + + + + + Classification + + + + + Training sets + + + + + - - Classification - + + + + + false + + + Min + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Max + + + + - - - Training sets - - - - - - - - - - - - - 0 - 0 - - - - Classifier: - - - - - - - -1 - - + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index bda87452066..94bbef928e2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -376,7 +376,7 @@ bool Cluster_classification::write_output(std::ostream& stream) } -void Cluster_classification::change_color (int index) +void Cluster_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; @@ -591,13 +591,18 @@ void Cluster_classification::reset_indices () *(indices.begin() + i) = idx ++; } -void Cluster_classification::compute_features (std::size_t nb_scales) +void Cluster_classification::compute_features (std::size_t nb_scales, float voxel_size) { CGAL_assertion (!(m_points->point_set()->empty())); reset_indices(); - std::cerr << "Computing pointwise features with " << nb_scales << " scale(s)" << std::endl; + std::cerr << "Computing pointwise features with " << nb_scales << " scale(s) and "; + if (voxel_size == -1) + std::cerr << "automatic voxel size" << std::endl; + else + std::cerr << "voxel size = " << voxel_size << std::endl; + m_features.clear(); Point_set::Vector_map normal_map; @@ -615,7 +620,7 @@ void Cluster_classification::compute_features (std::size_t nb_scales) Feature_set pointwise_features; - Generator generator (*(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); + Generator generator (*(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, voxel_size); CGAL::Real_timer t; t.start(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index cfea6dbf015..5c71e2c05ec 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -97,7 +97,7 @@ class Cluster_classification : public Item_classification_base xcenter + dx, ycenter + dy, zcenter + dz); } - void compute_features (std::size_t nb_scales); + void compute_features (std::size_t nb_scales, float voxel_size); void add_remaining_point_set_properties_as_features(Feature_set& feature_set); void select_random_region(); @@ -206,7 +206,7 @@ class Cluster_classification : public Item_classification_base bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color () { change_color (m_index_color); } - void change_color (int index); + void change_color (int index, float* vmin = NULL, float* vmax = NULL); CGAL::Three::Scene_item* generate_one_item (const char* name, int label) const { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 1c9226b263a..3142c32695a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -45,8 +45,10 @@ public: virtual CGAL::Bbox_3 bbox() { return item()->bbox(); } - virtual void compute_features (std::size_t nb_scales) = 0; + virtual void compute_features (std::size_t nb_scales, float voxel_size) = 0; + virtual std::string feature_statistics () const { return std::string(); } + virtual void add_selection_to_training_set (std::size_t label) = 0; virtual void reset_training_set (std::size_t label) = 0; virtual void reset_training_set_of_selection() = 0; @@ -58,7 +60,7 @@ public: virtual bool run (int method, int classifier, std::size_t subdivisions, double smoothing) = 0; virtual void update_color () = 0; - virtual void change_color (int index) = 0; + virtual void change_color (int index, float* vmin = NULL, float* vmax = NULL) = 0; virtual CGAL::Three::Scene_item* generate_one_item (const char* name, int label) const = 0; virtual void generate_one_item_per_label(std::vector& items, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index b981ea06287..44a58ef4236 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -320,7 +320,7 @@ bool Point_set_item_classification::write_output(std::ostream& stream) } -void Point_set_item_classification::change_color (int index) +void Point_set_item_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; @@ -425,28 +425,44 @@ void Point_set_item_classification::change_color (int index) return; } Feature_handle feature = m_features[corrected_index]; - + float min = std::numeric_limits::max(); float max = -std::numeric_limits::max(); - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) + + if (vmin != NULL && vmax != NULL + && *vmin != std::numeric_limits::infinity() + && *vmax != std::numeric_limits::infinity()) { - if (feature->value(*it) > max) - max = feature->value(*it); - if (feature->value(*it) < min) - min = feature->value(*it); + min = *vmin; + max = *vmax; + } + else + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + { + float v = feature->value(*it); + min = (std::min) (min, v); + max = (std::max) (max, v); + } } - std::cerr << "[Feature " << feature->name() << "] between " << min << " and " << max << std::endl; for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { float v = (feature->value(*it) - min) / (max - min); + if (v < 0.f) v = 0.f; + if (v > 1.f) v = 1.f; m_red[*it] = (unsigned char)(ramp.r(v) * 255); m_green[*it] = (unsigned char)(ramp.g(v) * 255); m_blue[*it] = (unsigned char)(ramp.b(v) * 255); } + + if (vmin != NULL && vmax != NULL) + { + *vmin = min; + *vmax = max; + } } } @@ -481,7 +497,7 @@ void Point_set_item_classification::reset_indices () *(indices.begin() + i) = idx ++; } -void Point_set_item_classification::compute_features (std::size_t nb_scales) +void Point_set_item_classification::compute_features (std::size_t nb_scales, float voxel_size) { CGAL_assertion (!(m_points->point_set()->empty())); @@ -490,7 +506,12 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) reset_indices(); - std::cerr << "Computing features with " << nb_scales << " scale(s)" << std::endl; + std::cerr << "Computing features with " << nb_scales << " scale(s) and "; + if (voxel_size == -1) + std::cerr << "automatic voxel size" << std::endl; + else + std::cerr << "voxel size = " << voxel_size << std::endl; + m_features.clear(); Point_set::Vector_map normal_map; @@ -506,7 +527,7 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) if (!echo) boost::tie (echo_map, echo) = m_points->point_set()->template property_map("number_of_returns"); - m_generator = new Generator (*(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); + m_generator = new Generator (*(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, voxel_size); CGAL::Real_timer t; t.start(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index a5d2b6636ac..3a428b523ef 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -117,7 +117,35 @@ class Point_set_item_classification : public Item_classification_base xcenter + dx, ycenter + dy, zcenter + dz); } - void compute_features (std::size_t nb_scales); + void compute_features (std::size_t nb_scales, float voxel_size); + + std::string feature_statistics() const + { + std::ostringstream oss; + + for (std::size_t i = 0; i < m_features.size(); ++ i) + { + float vmin = std::numeric_limits::max(); + float vmax = -std::numeric_limits::max(); + float vmean = 0.f; + std::size_t nb = 0; + + for (Point_set::const_iterator it = m_points->point_set()->begin_or_selection_begin(); + it != m_points->point_set()->end(); ++ it) + { + float v = m_features[i]->value(std::size_t(it - m_points->point_set()->begin())); + vmin = (std::min) (vmin, v); + vmax = (std::max) (vmax, v); + vmean += v; + ++ nb; + } + + oss << m_features[i]->name() << " in [ " << vmin << " ; " << vmax << " ], mean = " << vmean / nb << std::endl; + } + + return oss.str(); + } + void add_remaining_point_set_properties_as_features(); void select_random_region(); @@ -195,7 +223,7 @@ class Point_set_item_classification : public Item_classification_base bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color () { change_color (m_index_color); } - void change_color (int index); + void change_color (int index, float* vmin = NULL, float* vmax = NULL); CGAL::Three::Scene_item* generate_one_item (const char* name, int label) const { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 003c132e916..39e9d5cbb68 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -87,7 +87,7 @@ bool Surface_mesh_item_classification::write_output(std::ostream& ) } -void Surface_mesh_item_classification::change_color (int index) +void Surface_mesh_item_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; int index_color = index; @@ -198,9 +198,14 @@ void Surface_mesh_item_classification::change_color (int index) } } -void Surface_mesh_item_classification::compute_features (std::size_t nb_scales) +void Surface_mesh_item_classification::compute_features (std::size_t nb_scales, float voxel_size) { - std::cerr << "Computing features with " << nb_scales << " scale(s)" << std::endl; + std::cerr << "Computing features with " << nb_scales << " scale(s) and "; + if (voxel_size == -1) + std::cerr << "automatic voxel size" << std::endl; + else + std::cerr << "voxel size = " << voxel_size << std::endl; + m_features.clear(); if (m_generator != NULL) @@ -208,7 +213,7 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales) Face_center_map fc_map (m_mesh->polyhedron()); - m_generator = new Generator (*(m_mesh->polyhedron()), fc_map, nb_scales); + m_generator = new Generator (*(m_mesh->polyhedron()), fc_map, nb_scales, voxel_size); #ifdef CGAL_LINKED_WITH_TBB m_features.begin_parallel_additions(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h index b3a40b78fe5..a9983109bc1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h @@ -50,7 +50,7 @@ public: CGAL::Three::Scene_item* item() { return m_mesh; } void erase_item() { m_mesh = NULL; } - void compute_features (std::size_t nb_scales); + void compute_features (std::size_t nb_scales, float voxel_size); void add_selection_to_training_set (std::size_t label) { @@ -120,7 +120,7 @@ public: bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color() { change_color (m_index_color); } - void change_color (int index); + void change_color (int index, float* vmin = NULL, float* vmax = NULL); CGAL::Three::Scene_item* generate_one_item (const char* /* name */, int /* label */) const { diff --git a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h index cf6ae9db3a0..d36717bfb0a 100644 --- a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h +++ b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h @@ -63,6 +63,16 @@ public: return dialog->exec(); } + + void exec_no_cancel() + { + QDialogButtonBox* ok = new QDialogButtonBox + (QDialogButtonBox::Ok, Qt::Horizontal, dialog); + + form->addRow (ok); + QObject::connect (ok, SIGNAL(accepted()), dialog, SLOT(accept())); + dialog->exec(); + } }; From 58a6c4cc2f463fa23913f07bbd074e2a6d170e01 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 11 Oct 2018 13:11:44 +0200 Subject: [PATCH 036/186] Specialize TensorFlow classifier for GPU processing --- .../TensorFlow_neural_network_classifier.h | 138 +++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index d539c9e5e49..a6b457990ef 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -106,6 +106,10 @@ class TensorFlow_neural_network_classifier public: + + /// \cond SKIP_IN_MANUAL + const Feature_set& features() const { return m_features; } + /// \endcond /// \name Constructor /// @{ @@ -418,6 +422,34 @@ public: for (std::size_t i = 0; i < m_labels.size(); ++ i) out[i] = output_data[i]; } + + + void operator() (const std::vector& item_indices, + std::vector >& out) const + { + out.resize (item_indices.size(), std::vector(m_labels.size(), 0.)); + + TF::Tensor ft + (TF::DataTypeToEnum::v(), + TF::TensorShape {(long long)(item_indices.size()), (long long)(m_features.size())}); + + float* ft_data = ft.flat().data(); + + // Fill input tensor + for (std::size_t i = 0; i < item_indices.size(); ++ i) + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft_data[i * m_features.size() + f] + = (m_features[f]->value(item_indices[i]) - m_feature_means[f]) / m_feature_sd[f]; + + std::vector outputs; + TF_CHECK_OK(m_session->Run({{*m_ph_ft, ft}}, {m_layers.back()}, &outputs)); + + float* output_data = outputs[0].flat().data(); + + for (std::size_t i = 0; i < item_indices.size(); ++ i) + for (std::size_t l = 0; l < m_labels.size(); ++ l) + out[i][l] = output_data[i * m_labels.size() + l]; + } /// \endcond /// @} @@ -976,8 +1008,8 @@ private: // options.config.mutable_gpu_options()->set_operation_timeout_in_ms(15000); // options.config.mutable_gpu_options()->set_visible_device_list(""); - options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.3); options.config.mutable_gpu_options()->set_allow_growth(true); + options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.8); options.config.mutable_gpu_options()->set_force_gpu_compatible(true); m_session = new TF::ClientSession (*m_root, options); @@ -1004,6 +1036,110 @@ private: }; + +#if 1 +// Specialization to use GPU parallelization +template +void classify (const ItemRange& input, + const Label_set& labels, + const TensorFlow_neural_network_classifier& classifier, + LabelIndexRange& output, + ProbabilitiesRanges& probabilities) +{ + std::cerr << "Classify with TensorFlow classifier" << std::endl; + + output.resize(input.size()); + probabilities.resize (labels.size()); + for (std::size_t i = 0; i < probabilities.size(); ++ i) + probabilities[i].resize (input.size()); + + const std::size_t mem_allocated = sizeof(float) * input.size() * (labels.size() + classifier.features().size()); + const std::size_t size_max = 1024 * 1024 * 1024; + const std::size_t nb_subdivisions = (mem_allocated / size_max) + 1; + std::cerr << nb_subdivisions << " subdivision(s) for GPU processing" << std::endl; + + std::size_t idx = 0; + for (std::size_t n = 0; n < nb_subdivisions; ++ n) + { + std::vector indices; + indices.reserve (input.size() / nb_subdivisions); + for (std::size_t i = 0; i < input.size() / nb_subdivisions && idx < input.size(); ++ i) + indices.push_back(idx ++); + + std::vector > values; + classifier (indices, values); + for(std::size_t i = 0; i < indices.size(); ++ i) + { + std::size_t nb_class_best = 0; + float val_class_best = 0.f; + + for (std::size_t j = 0; j < labels.size(); ++ j) + { + probabilities[j][indices[i]] = values[i][j]; + + if(val_class_best < values[i][j]) + { + val_class_best = values[i][j]; + nb_class_best = j; + } + } + + output[indices[i]] = nb_class_best; + } + } +} + +// Specialization to use GPU parallelization +template +void classify (const ItemRange& input, + const Label_set& labels, + const TensorFlow_neural_network_classifier& classifier, + LabelIndexRange& output) +{ + std::cerr << "Classify with TensorFlow classifier" << std::endl; + + output.resize(input.size()); + + const std::size_t mem_allocated = sizeof(float) * input.size() * (labels.size() + classifier.features().size()); + const std::size_t size_max = 1024 * 1024 * 1024; + const std::size_t nb_subdivisions = (mem_allocated / size_max) + 1; + std::cerr << nb_subdivisions << " subdivision(s) for GPU processing" << std::endl; + + std::size_t idx = 0; + for (std::size_t n = 0; n < nb_subdivisions; ++ n) + { + std::vector indices; + indices.reserve (input.size() / nb_subdivisions); + for (std::size_t i = 0; i < input.size() / nb_subdivisions && idx < input.size(); ++ i) + indices.push_back(idx ++); + + std::vector > values; + classifier (indices, values); + + for(std::size_t i = 0; i < indices.size(); ++ i) + { + std::size_t nb_class_best = 0; + float val_class_best = 0.f; + + for (std::size_t j = 0; j < labels.size(); ++ j) + { + if(val_class_best < values[i][j]) + { + val_class_best = values[i][j]; + nb_class_best = j; + } + } + + output[indices[i]] = nb_class_best; + } + } +} +#endif } } From ebac82765880470768a07bb4575ec77ec5ee36b3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 19 Oct 2018 11:39:28 +0200 Subject: [PATCH 037/186] Improve bagging algorithm (30% gain on training timing) --- .../random-forest/common-libraries.hpp | 2 +- .../auxiliary/random-forest/forest.hpp | 21 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 3d9b9a60553..466e28ea339 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -97,7 +97,7 @@ struct ForestParams { max_depth(42), n_trees(100), min_samples_per_node(5), - sample_reduction(0) + sample_reduction(0.368f) {} template void serialize(Archive& ar, unsigned /*version*/) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index 4d22c2bb36b..ee9b03e3c6f 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -93,9 +93,6 @@ public: size_t n_idxes = sample_idxes.size(); params.n_in_bag_samples = n_idxes * (1 - params.sample_reduction); - // Random distribution over indexes - UniformIntDist dist(0, n_idxes - 1); - // Store for each sample and each tree if sample was used for tree if (register_oob) { was_oob_data.assign(n_idxes*params.n_trees, 1); @@ -103,6 +100,8 @@ public: } std::size_t nb_trees = trees.size(); + std::vector in_bag_samples = sample_idxes; + for (size_t i_tree = nb_trees; i_tree < nb_trees + params.n_trees; ++i_tree) { #if VERBOSE_TREE_PROGRESS std::printf("Training tree %zu/%zu, max depth %zu\n", i_tree+1, nb_trees + params.n_trees, params.max_depth); @@ -112,20 +111,18 @@ public: // initialize random generator with sequential seeds (one for each // tree) RandomGen gen(seed_start + i_tree); + // Bagging: draw random sample indexes used for this tree - std::vector in_bag_samples(params.n_in_bag_samples); - for (size_t i_sample = 0; i_sample < in_bag_samples.size(); ++i_sample) { - int random_idx = dist(gen); - in_bag_samples[i_sample] = sample_idxes[random_idx]; - if (register_oob && was_oob(random_idx, i_tree)) { - was_oob(random_idx, i_tree) = 0; - } - } + std::random_shuffle (in_bag_samples.begin(),in_bag_samples.end()); + if (register_oob) + for (std::size_t i = 0; i < params.n_in_bag_samples; ++ i) + was_oob(in_bag_samples[i], i_tree) = 0; + #ifdef TREE_GRAPHVIZ_STREAM TREE_GRAPHVIZ_STREAM << "digraph Tree {" << std::endl; #endif // Train the tree - trees.back().train(samples, labels, &in_bag_samples[0], in_bag_samples.size(), split_generator, gen); + trees.back().train(samples, labels, &in_bag_samples[0], params.n_in_bag_samples, split_generator, gen); #ifdef TREE_GRAPHVIZ_STREAM TREE_GRAPHVIZ_STREAM << "}" << std::endl << std::endl; #endif From 0108fa4436a0cf281897c26d0808c41a09d3c66a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 29 Oct 2018 11:13:00 +0100 Subject: [PATCH 038/186] Parallelize random forest training algorithm --- .../ETHZ_random_forest_classifier.h | 5 +- .../auxiliary/random-forest/forest.hpp | 130 +++++++++++++----- 2 files changed, 98 insertions(+), 37 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index cf3ae810df9..0ea67e0013e 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -134,7 +134,7 @@ public: will underfit the test data and conversely an overly high value will likely overfit. */ - template + template void train (const LabelIndexRange& ground_truth, bool reset_trees = true, std::size_t num_trees = 25, @@ -174,7 +174,8 @@ public: CGAL::internal::liblearning::RandomForest::AxisAlignedRandomSplitGenerator generator; - m_rfc->train(feature_vector, label_vector, CGAL::internal::liblearning::DataView2D(), generator, 0, false, reset_trees); + m_rfc->train + (feature_vector, label_vector, CGAL::internal::liblearning::DataView2D(), generator, 0, reset_trees, m_labels.size()); } /// \cond SKIP_IN_MANUAL diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index ee9b03e3c6f..c0323a4abac 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -39,11 +39,78 @@ #include #endif +#ifdef CGAL_LINKED_WITH_TBB +#include +#include +#include +#include +#endif // CGAL_LINKED_WITH_TBB + + namespace CGAL { namespace internal { + + namespace liblearning { namespace RandomForest { +template +class Tree_training_functor +{ + typedef typename NodeT::ParamType ParamType; + typedef typename NodeT::FeatureType FeatureType; + typedef Tree TreeType; + + std::size_t seed_start; + const std::vector& sample_idxes; + boost::ptr_vector >& trees; + DataView2D samples; + DataView2D labels; + std::size_t n_in_bag_samples; + const SplitGenerator& split_generator; + +public: + + Tree_training_functor(std::size_t seed_start, + const std::vector& sample_idxes, + boost::ptr_vector >& trees, + DataView2D samples, + DataView2D labels, + std::size_t n_in_bag_samples, + const SplitGenerator& split_generator) + : seed_start (seed_start) + , sample_idxes (sample_idxes) + , trees (trees) + , samples (samples) + , labels (labels) + , n_in_bag_samples(n_in_bag_samples) + , split_generator(split_generator) + { } + +#ifdef CGAL_LINKED_WITH_TBB + void operator()(const tbb::blocked_range& r) const + { + for (std::size_t s = r.begin(); s != r.end(); ++ s) + apply(s); + } +#endif // CGAL_LINKED_WITH_TBB + + inline void apply (std::size_t i_tree) const + { + // initialize random generator with sequential seeds (one for each + // tree) + RandomGen gen(seed_start + i_tree); + std::vector in_bag_samples = sample_idxes; + + // Bagging: draw random sample indexes used for this tree + std::random_shuffle (in_bag_samples.begin(),in_bag_samples.end()); + + // Train the tree + trees[i_tree].train(samples, labels, &in_bag_samples[0], n_in_bag_samples, split_generator, gen); + } + +}; + template class RandomForest { public: @@ -52,28 +119,29 @@ public: typedef Tree TreeType; ParamType params; - std::vector was_oob_data; - DataView2D was_oob; - boost::ptr_vector< Tree > trees; RandomForest() {} RandomForest(ParamType const& params) : params(params) {} - template + template void train(DataView2D samples, DataView2D labels, DataView2D train_sample_idxes, SplitGenerator const& split_generator, size_t seed_start = 1, - bool register_oob = true, - bool reset_trees = true + bool reset_trees = true, + std::size_t n_classes = std::size_t(-1) ) { if (reset_trees) trees.clear(); - params.n_classes = *std::max_element(&labels(0,0), &labels(0,0)+labels.num_elements()) + 1; + if (n_classes == std::size_t(-1)) + params.n_classes = *std::max_element(&labels(0,0), &labels(0,0)+labels.num_elements()) + 1; + else + params.n_classes = n_classes; + params.n_features = samples.cols; params.n_samples = samples.rows; @@ -93,39 +161,31 @@ public: size_t n_idxes = sample_idxes.size(); params.n_in_bag_samples = n_idxes * (1 - params.sample_reduction); - // Store for each sample and each tree if sample was used for tree - if (register_oob) { - was_oob_data.assign(n_idxes*params.n_trees, 1); - was_oob = DataView2D(&was_oob_data[0], n_idxes, params.n_trees); - } - std::size_t nb_trees = trees.size(); - std::vector in_bag_samples = sample_idxes; + for (std::size_t i_tree = nb_trees; i_tree < nb_trees + params.n_trees; ++ i_tree) + trees.push_back (new TreeType(¶ms)); - for (size_t i_tree = nb_trees; i_tree < nb_trees + params.n_trees; ++i_tree) { + Tree_training_functor + f (seed_start, sample_idxes, trees, samples, labels, params.n_in_bag_samples, split_generator); + +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(nb_trees, nb_trees + params.n_trees), f); + } + else +#endif + { + for (size_t i_tree = nb_trees; i_tree < nb_trees + params.n_trees; ++i_tree) + { #if VERBOSE_TREE_PROGRESS std::printf("Training tree %zu/%zu, max depth %zu\n", i_tree+1, nb_trees + params.n_trees, params.max_depth); #endif - // new tree - trees.push_back(new TreeType(¶ms)); - // initialize random generator with sequential seeds (one for each - // tree) - RandomGen gen(seed_start + i_tree); - - // Bagging: draw random sample indexes used for this tree - std::random_shuffle (in_bag_samples.begin(),in_bag_samples.end()); - if (register_oob) - for (std::size_t i = 0; i < params.n_in_bag_samples; ++ i) - was_oob(in_bag_samples[i], i_tree) = 0; - -#ifdef TREE_GRAPHVIZ_STREAM - TREE_GRAPHVIZ_STREAM << "digraph Tree {" << std::endl; -#endif - // Train the tree - trees.back().train(samples, labels, &in_bag_samples[0], params.n_in_bag_samples, split_generator, gen); -#ifdef TREE_GRAPHVIZ_STREAM - TREE_GRAPHVIZ_STREAM << "}" << std::endl << std::endl; -#endif + f.apply(i_tree); + } } } int evaluate(FeatureType const* sample, float* results) { From fd1c923f6fadadfc88f2f548e320ca8c36571778 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 29 Oct 2018 11:28:19 +0100 Subject: [PATCH 039/186] Add method to get feature usage --- .../Classification/ETHZ_random_forest_classifier.h | 7 ++++++- .../internal/auxiliary/random-forest/forest.hpp | 6 ++++++ .../internal/auxiliary/random-forest/node.hpp | 10 ++++++++++ .../internal/auxiliary/random-forest/tree.hpp | 4 ++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 0ea67e0013e..0cba0824b9e 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -158,7 +158,7 @@ public: } } - std::cerr << "Using " << gt.size() << " inliers" << std::endl; + CGAL_CLASSIFICATION_CERR << "Using " << gt.size() << " inliers" << std::endl; CGAL::internal::liblearning::DataView2D label_vector (&(gt[0]), gt.size(), 1); CGAL::internal::liblearning::DataView2D feature_vector(&(ft[0]), gt.size(), ft.size() / gt.size()); @@ -195,6 +195,11 @@ public: for (std::size_t i = 0; i < out.size(); ++ i) out[i] = (std::min) (1.f, (std::max) (0.f, prob[i])); } + + void get_feature_usage (std::vector& count) const + { + return m_rfc->get_feature_usage(count); + } /// \endcond /// @} diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index c0323a4abac..05b57c765a4 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -234,6 +234,12 @@ public: ar & BOOST_SERIALIZATION_NVP(params); ar & BOOST_SERIALIZATION_NVP(trees); } + + void get_feature_usage (std::vector& count) const + { + for (std::size_t i_tree = 0; i_tree < trees.size(); ++i_tree) + trees[i_tree].get_feature_usage(count); + } }; } diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index 9e02ed11400..f448ba98064 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -257,6 +257,16 @@ public: ar & BOOST_SERIALIZATION_NVP(right); } } + + void get_feature_usage (std::vector& count) const + { + if (!is_leaf) + { + count[std::size_t(splitter.feature)] ++; + left->get_feature_usage(count); + right->get_feature_usage(count); + } + } }; } diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp index 6c426f75141..476ebf56f80 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp @@ -135,6 +135,10 @@ public: ar & BOOST_SERIALIZATION_NVP(params); ar & BOOST_SERIALIZATION_NVP(root_node); } + void get_feature_usage (std::vector& count) const + { + root_node->get_feature_usage(count); + } }; } From 2145a29297123e7eaf5c72d2ede416c6b1dbe318 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 29 Oct 2018 11:29:52 +0100 Subject: [PATCH 040/186] Optimizations for random forest training algorithm --- .../random-forest/common-libraries.hpp | 28 +++++++++++-------- .../auxiliary/random-forest/node-gini.hpp | 10 ++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 466e28ea339..8e951287ba4 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -62,9 +62,9 @@ namespace liblearning { namespace RandomForest { typedef std::vector< std::pair > FeatureClassDataFloat; -inline void init_feature_class_data(FeatureClassDataFloat& data, int /*n_classes*/, int n_samples) +inline void init_feature_class_data(FeatureClassDataFloat& data, int /*n_classes*/, int /* n_samples */) { - data.resize(n_samples); +// data.resize(n_samples); } typedef boost::unordered_set FeatureSet; @@ -222,15 +222,21 @@ struct AxisAlignedSplitter { int n_samples, FeatureClassData& data_points) const { - for (int i_sample = 0; i_sample < n_samples; ++i_sample) { - // determine index of this sample ... - int sample_idx = sample_idxes[i_sample]; - // determine class ... - int sample_class = labels(sample_idx, 0); - // determine value of the selected feature for this sample - FeatureType sample_fval = samples(sample_idx, feature); - data_points[i_sample] = std::make_pair(sample_fval, sample_class); - } + std::size_t size = (std::min)(std::size_t(5000), std::size_t(n_samples)); + data_points.clear(); + data_points.reserve(size); + + std::size_t step = n_samples / size; + + for (int i_sample = 0; i_sample < n_samples; i_sample += step) { + // determine index of this sample ... + int sample_idx = sample_idxes[i_sample]; + // determine class ... + int sample_class = labels(sample_idx, 0); + // determine value of the selected feature for this sample + FeatureType sample_fval = samples(sample_idx, feature); + data_points.push_back(std::make_pair(sample_fval, sample_class)); + } } template void serialize(Archive& ar, unsigned /*version*/) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp index 1b3c6ec89c8..d9c62d4add4 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp @@ -79,7 +79,13 @@ public: n_r += 1; } // sort data so thresholding is easy based on position in array - std::sort(data_points.begin(), data_points.end()); + std::sort(data_points.begin(), data_points.end(), + [&](const std::pair& a, + const std::pair& b) -> bool + { + return a.first < b.first; + }); + // loop over data, update class distributions left&right for (size_t i_point = 1; i_point < data_points.size(); ++i_point) { int cls = data_points[i_point-1].second; @@ -92,6 +98,7 @@ public: continue; // weighted average double gini = n_l - gini_square_term(classes_l) * 1.0 / n_l + n_r - gini_square_term(classes_r) * 1.0 / n_r; + if (gini < best_loss) { best_loss = gini; double fraction = fraction_dist(gen); @@ -106,6 +113,7 @@ public: { ar & boost::serialization::make_nvp("base", boost::serialization::base_object< Node< NodeGini, ForestParams, Splitter > >(*this)); } + }; } From 291982ee6764eb68d06c3cd81f1b6b36c8698f98 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 6 Dec 2018 14:58:26 +0100 Subject: [PATCH 041/186] Parallelized RF in plugin --- .../Plugins/Classification/Cluster_classification.cpp | 6 +++--- .../Classification/Point_set_item_classification.cpp | 6 +++--- .../Plugins/Classification/Point_set_item_classification.h | 3 ++- .../Classification/Surface_mesh_item_classification.cpp | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 94bbef928e2..5c5fedfafb5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -818,9 +818,9 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d if (m_ethz != NULL) delete m_ethz; m_ethz = new ETHZ_random_forest (m_labels, m_features); - m_ethz->train(training, true, - dialog.get("num_trees")->value(), - dialog.get("max_depth")->value()); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (m_clusters, m_labels, *m_ethz, indices, m_label_probabilities); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index 44a58ef4236..e2146d9343a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -727,9 +727,9 @@ void Point_set_item_classification::train(int classifier, const QMultipleInputDi if (m_ethz != NULL) delete m_ethz; m_ethz = new ETHZ_random_forest (m_labels, m_features); - m_ethz->train(training, true, - dialog.get("num_trees")->value(), - dialog.get("max_depth")->value()); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_ethz, indices, m_label_probabilities); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 3a428b523ef..af9412c6a73 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -333,10 +333,11 @@ class Point_set_item_classification : public Item_classification_base { std::vector indices (m_points->point_set()->size(), -1); + m_label_probabilities.clear(); if (method == 0) CGAL::Classification::classify (*(m_points->point_set()), m_labels, classifier, - indices); + indices, m_label_probabilities); else if (method == 1) { if (m_clusters.empty()) // Use real local smoothing diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 39e9d5cbb68..6f4d47b0704 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -293,9 +293,9 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp if (m_ethz != NULL) delete m_ethz; m_ethz = new ETHZ_random_forest (m_labels, m_features); - m_ethz->train(training, true, - dialog.get("num_trees")->value(), - dialog.get("max_depth")->value()); + m_ethz->train(training, true, + dialog.get("num_trees")->value(), + dialog.get("max_depth")->value()); CGAL::Classification::classify (m_mesh->polyhedron()->faces(), m_labels, *m_ethz, indices, m_label_probabilities); From e86777c8dc4a94c2ea3b781ccf6324b6670c2f8e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 6 Dec 2018 14:59:26 +0100 Subject: [PATCH 042/186] Reduce max memory used --- .../Classification/TensorFlow_neural_network_classifier.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index a6b457990ef..307289bd7c2 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -1057,7 +1057,7 @@ void classify (const ItemRange& input, probabilities[i].resize (input.size()); const std::size_t mem_allocated = sizeof(float) * input.size() * (labels.size() + classifier.features().size()); - const std::size_t size_max = 1024 * 1024 * 1024; + const std::size_t size_max = 512 * 1024 * 1024; const std::size_t nb_subdivisions = (mem_allocated / size_max) + 1; std::cerr << nb_subdivisions << " subdivision(s) for GPU processing" << std::endl; @@ -1106,7 +1106,7 @@ void classify (const ItemRange& input, output.resize(input.size()); const std::size_t mem_allocated = sizeof(float) * input.size() * (labels.size() + classifier.features().size()); - const std::size_t size_max = 1024 * 1024 * 1024; + const std::size_t size_max = 512 * 1024 * 1024; const std::size_t nb_subdivisions = (mem_allocated / size_max) + 1; std::cerr << nb_subdivisions << " subdivision(s) for GPU processing" << std::endl; From 7f17f352d982bfe26c5b0a6d743b16034087d39d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 7 Dec 2018 10:42:08 +0100 Subject: [PATCH 043/186] Fix bug + improve radius values --- .../CGAL/Classification/Point_set_feature_generator.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index 9063d094afb..2e10f364e0f 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -166,7 +166,7 @@ private: neighborhood = new Neighborhood (input, point_map, voxel_size); t.stop(); - if (voxel_size < 0.) + if (lower_grid == NULL) CGAL_CLASSIFICATION_CERR << "Neighborhood computed in " << t.time() << " second(s)" << std::endl; else CGAL_CLASSIFICATION_CERR << "Neighborhood with voxel size " << voxel_size @@ -216,8 +216,8 @@ private: } float grid_resolution() const { return voxel_size; } - float radius_neighbors() const { return voxel_size * 5; } - float radius_dtm() const { return voxel_size * 100; } + float radius_neighbors() const { return voxel_size * 3; } + float radius_dtm() const { return voxel_size * 10; } }; From c26df8b989f7b1944ec19480d288ded829cbcd9d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 7 Dec 2018 10:42:18 +0100 Subject: [PATCH 044/186] Fix reading labels in cluster classification --- .../Classification/Cluster_classification.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 5c5fedfafb5..0aaa7828cd5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -128,20 +128,26 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po if (training_found) { - if (las_found && (m_training[*it] == 0 || m_training[*it] == 1)) // Unclassified class in LAS - m_training[*it] = -1; - else if (m_training[*it] != -1) - m_training[*it] = used_indices[std::size_t(m_training[*it])]; - if (c != -1) + if (std::size_t(current_idx) != used_indices.size()) // Empty indices -> reorder indices in point set + { + if (las_found && (m_training[*it] == 0 || m_training[*it] == 1)) // Unclassified class in LAS + m_training[*it] = -1; + else if (m_training[*it] != -1) + m_training[*it] = used_indices[std::size_t(m_training[*it])]; + } + if (c != -1 && m_training[*it] != -1) m_clusters[c].training() = m_training[*it]; } if (classif_found) { - if (las_found && (m_classif[*it] == 0 || m_classif[*it] == 1)) // Unclassified class in LAS - m_classif[*it] = -1; - else if (m_classif[*it] != -1) - m_classif[*it] = used_indices[std::size_t(m_classif[*it])]; - if (c != -1) + if (std::size_t(current_idx) != used_indices.size()) // Empty indices -> reorder indices in point set + { + if (las_found && (m_classif[*it] == 0 || m_classif[*it] == 1)) // Unclassified class in LAS + m_classif[*it] = -1; + else if (m_classif[*it] != -1) + m_classif[*it] = used_indices[std::size_t(m_classif[*it])]; + } + if (c != -1 && m_classif[*it] != -1) m_clusters[c].label() = m_classif[*it]; } } From f8f53ba70491525862f1fb9a126c143bdd790b17 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 15:05:14 +0100 Subject: [PATCH 045/186] Fix license in vtp_io.h --- BGL/include/CGAL/IO/vtp_io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h index 2c0ec6bf152..a616dd6b99c 100644 --- a/BGL/include/CGAL/IO/vtp_io.h +++ b/BGL/include/CGAL/IO/vtp_io.h @@ -16,7 +16,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0+ // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno From 967ada6cfd3e3c5a9b5fe735d42f1d34dfc85bb3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 10 Dec 2018 11:06:01 +0100 Subject: [PATCH 046/186] Convert classification back to LAS format when closing a LAS file --- .../Classification/Cluster_classification.cpp | 100 ++++++++++++++++-- .../Classification/Cluster_classification.h | 2 + .../Point_set_item_classification.cpp | 77 +++++++++++++- .../Point_set_item_classification.h | 2 + 4 files changed, 168 insertions(+), 13 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 0aaa7828cd5..24610806714 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -23,6 +23,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* points) : m_points (points) + , m_input_is_las (false) { m_index_color = 1; @@ -61,6 +62,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po boost::tie (las_classif, las_found) = m_points->point_set()->property_map("classification"); if (las_found) { + m_input_is_las = true; for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { @@ -283,17 +285,6 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po Cluster_classification::~Cluster_classification() { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - int c = m_cluster_id[*it]; - if (c != -1) - { - m_training[*it] = m_clusters[c].training(); - m_classif[*it] = m_clusters[c].label(); - } - } - if (m_sowf != NULL) delete m_sowf; if (m_ethz != NULL) @@ -308,6 +299,93 @@ Cluster_classification::~Cluster_classification() #endif if (m_points != NULL) { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int c = m_cluster_id[*it]; + if (c != -1) + { + m_training[*it] = m_clusters[c].training(); + m_classif[*it] = m_clusters[c].label(); + } + else + { + m_training[*it] = -1; + m_classif[*it] = -1; + } + } + + // For LAS saving, convert classification info in the LAS standard +// if (m_input_is_las) + { + Point_set::Property_map las_classif + = m_points->point_set()->add_property_map("classification", 0).first; + + std::vector label_indices; + + unsigned char custom = 19; + for (std::size_t i = 0; i < m_labels.size(); ++ i) + { + if (m_labels[i]->name() == "ground") + label_indices.push_back (2); + else if (m_labels[i]->name() == "low_veget") + label_indices.push_back (3); + else if (m_labels[i]->name() == "med_veget" || m_labels[i]->name() == "vegetation") + label_indices.push_back (4); + else if (m_labels[i]->name() == "high_veget") + label_indices.push_back (5); + else if (m_labels[i]->name() == "building" || m_labels[i]->name() == "roof") + label_indices.push_back (6); + else if (m_labels[i]->name() == "noise") + label_indices.push_back (7); + else if (m_labels[i]->name() == "reserved" || m_labels[i]->name() == "facade") + label_indices.push_back (8); + else if (m_labels[i]->name() == "water") + label_indices.push_back (9); + else if (m_labels[i]->name() == "rail") + label_indices.push_back (10); + else if (m_labels[i]->name() == "road_surface") + label_indices.push_back (11); + else if (m_labels[i]->name() == "reserved_2") + label_indices.push_back (12); + else if (m_labels[i]->name() == "wire_guard") + label_indices.push_back (13); + else if (m_labels[i]->name() == "wire_conduct") + label_indices.push_back (14); + else if (m_labels[i]->name() == "trans_tower") + label_indices.push_back (15); + else if (m_labels[i]->name() == "wire_connect") + label_indices.push_back (16); + else if (m_labels[i]->name() == "bridge_deck") + label_indices.push_back (17); + else if (m_labels[i]->name() == "high_noise") + label_indices.push_back (18); + else + label_indices.push_back (custom ++); + } + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + { + int c = m_classif[*it]; + unsigned char lc = 1; // unclassified in LAS standard + if (c != -1) + lc = label_indices[std::size_t(c)]; + + las_classif[*it] = lc; + + int t = m_training[*it]; + unsigned char lt = 1; // unclassified in LAS standard + if (t != -1) + lt = label_indices[std::size_t(t)]; + + m_training[*it] = int(lt); + } + + m_points->point_set()->remove_property_map (m_classif); + } + + reset_colors(); erase_item(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index 5c71e2c05ec..8a0f69f2ced 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -397,6 +397,8 @@ class Cluster_classification : public Item_classification_base int m_index_color; boost::shared_ptr m_eigen; + + bool m_input_is_las; }; // end class Cluster_classification diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index e2146d9343a..e201748b84d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -21,6 +21,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_normal_item* points) : m_points (points) , m_generator (NULL) + , m_input_is_las (false) { m_index_color = 1; @@ -60,6 +61,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n boost::tie (las_classif, las_found) = m_points->point_set()->property_map("classification"); if (las_found) { + m_input_is_las = true; for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { @@ -245,10 +247,81 @@ Point_set_item_classification::~Point_set_item_classification() if (m_generator != NULL) delete m_generator; if (m_points != NULL) + { + // For LAS saving, convert classification info in the LAS standard + if (m_input_is_las) { - reset_colors(); - erase_item(); + Point_set::Property_map las_classif + = m_points->point_set()->add_property_map("classification", 0).first; + + std::vector label_indices; + + unsigned char custom = 19; + for (std::size_t i = 0; i < m_labels.size(); ++ i) + { + if (m_labels[i]->name() == "ground") + label_indices.push_back (2); + else if (m_labels[i]->name() == "low_veget") + label_indices.push_back (3); + else if (m_labels[i]->name() == "med_veget" || m_labels[i]->name() == "vegetation") + label_indices.push_back (4); + else if (m_labels[i]->name() == "high_veget") + label_indices.push_back (5); + else if (m_labels[i]->name() == "building" || m_labels[i]->name() == "roof") + label_indices.push_back (6); + else if (m_labels[i]->name() == "noise") + label_indices.push_back (7); + else if (m_labels[i]->name() == "reserved" || m_labels[i]->name() == "facade") + label_indices.push_back (8); + else if (m_labels[i]->name() == "water") + label_indices.push_back (9); + else if (m_labels[i]->name() == "rail") + label_indices.push_back (10); + else if (m_labels[i]->name() == "road_surface") + label_indices.push_back (11); + else if (m_labels[i]->name() == "reserved_2") + label_indices.push_back (12); + else if (m_labels[i]->name() == "wire_guard") + label_indices.push_back (13); + else if (m_labels[i]->name() == "wire_conduct") + label_indices.push_back (14); + else if (m_labels[i]->name() == "trans_tower") + label_indices.push_back (15); + else if (m_labels[i]->name() == "wire_connect") + label_indices.push_back (16); + else if (m_labels[i]->name() == "bridge_deck") + label_indices.push_back (17); + else if (m_labels[i]->name() == "high_noise") + label_indices.push_back (18); + else + label_indices.push_back (custom ++); + } + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + { + int c = m_classif[*it]; + unsigned char lc = 1; // unclassified in LAS standard + if (c != -1) + lc = label_indices[std::size_t(c)]; + + las_classif[*it] = lc; + + int t = m_training[*it]; + unsigned char lt = 1; // unclassified in LAS standard + if (t != -1) + lt = label_indices[std::size_t(t)]; + + m_training[*it] = int(lt); + } + + m_points->point_set()->remove_property_map (m_classif); } + + reset_colors(); + erase_item(); + } + } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index af9412c6a73..a6138fe4c07 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -412,6 +412,8 @@ class Point_set_item_classification : public Item_classification_base Generator* m_generator; int m_index_color; + + bool m_input_is_las; }; // end class Point_set_item_classification From 1f8c581f332654df2931c492727fcc7a164a5239 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 10 Dec 2018 15:24:05 +0100 Subject: [PATCH 047/186] Improve plugin with help menu + more unlocked buttons before computing features --- .../Classification/Classification_plugin.cpp | 200 ++++++++++++------ .../Classification/Classification_widget.ui | 35 ++- 2 files changed, 143 insertions(+), 92 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 9cb50727333..a882df85469 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,11 @@ #include #include +#define CGAL_CLASSIFICATION_ETHZ_ID "Random Forest (ETHZ)" +#define CGAL_CLASSIFICATION_TENSORFLOW_ID "Neural Network (TensorFlow)" +#define CGAL_CLASSIFICATION_OPENCV_ID "Random Forest (OpenCV)" +#define CGAL_CLASSIFICATION_SOWF_ID "Sum of Weighted Features" + using namespace CGAL::Three; class Polyhedron_demo_classification_plugin : @@ -185,28 +191,15 @@ public: addDockWidget(dock_widget); addDockWidget(dock_widget_adv); - ui_widget.classifier->addItem (tr("Random Forest (ETHZ)")); - -#ifdef CGAL_LINKED_WITH_TENSORFLOW - ui_widget.classifier->addItem (tr("Neural Network (TensorFlow)")); -#endif - -#ifdef CGAL_LINKED_WITH_OPENCV - ui_widget.classifier->addItem (tr("Random Forest (OpenCV %1.%2)") - .arg(CV_MAJOR_VERSION) - .arg(CV_MINOR_VERSION)); -#endif - ui_widget.classifier->addItem (tr("Sum of Weighted Features")); - - color_att = QColor (75, 75, 77); ui_widget.menu->setMenu (new QMenu("Classification Menu", ui_widget.menu)); - connect(ui_widget.classifier, SIGNAL(currentTextChanged(QString)), this, - SLOT(on_classifier_changed(QString))); - - QAction* compute_features = ui_widget.menu->menu()->addAction ("Compute features"); + QAction* help = ui_widget.menu->menu()->addAction ("Help"); + connect(help, SIGNAL(triggered()), this, + SLOT(on_help_clicked())); + + QAction* compute_features = ui_widget.menu->menu()->addAction ("Compute features..."); connect(compute_features, SIGNAL(triggered()), this, SLOT(on_compute_features_button_clicked())); @@ -214,13 +207,8 @@ public: connect(action_statistics, SIGNAL(triggered()), this, SLOT(on_statistics_clicked())); - ui_widget.menu->menu()->addSection ("Training"); + ui_widget.menu->menu()->addSection ("Training Set"); - action_train = ui_widget.menu->menu()->addAction ("Train classifier"); - action_train->setShortcut(Qt::SHIFT | Qt::Key_T); - connect(action_train, SIGNAL(triggered()), this, - SLOT(on_train_clicked())); - action_reset_local = ui_widget.menu->menu()->addAction ("Reset training set of selection"); connect(action_reset_local, SIGNAL(triggered()), this, SLOT(on_reset_training_set_of_selection_clicked())); @@ -238,27 +226,36 @@ public: connect(action_validate, SIGNAL(triggered()), this, SLOT(on_validate_selection_clicked())); - action_save_config = ui_widget.menu->menu()->addAction ("Save classifier's current configuration"); - action_load_config = ui_widget.menu->menu()->addAction ("Load configuration for classifier"); + classifier = ui_widget.menu->menu()->addSection (CGAL_CLASSIFICATION_ETHZ_ID); + + QAction* switch_classifier = ui_widget.menu->menu()->addAction ("Switch to another classifier..."); + connect(switch_classifier, SIGNAL(triggered()), this, + SLOT(on_switch_classifier_clicked())); + + action_train = ui_widget.menu->menu()->addAction ("Train..."); + action_train->setShortcut(Qt::SHIFT | Qt::Key_T); + connect(action_train, SIGNAL(triggered()), this, + SLOT(on_train_clicked())); + + action_run = ui_widget.menu->menu()->addAction ("Classify"); + connect(action_run, SIGNAL(triggered()), this, + SLOT(on_run_button_clicked())); + + action_run_smoothed = ui_widget.menu->menu()->addAction ("Classify with local smoothing..."); + connect(action_run_smoothed, SIGNAL(triggered()), this, + SLOT(on_run_smoothed_button_clicked())); + + action_run_graphcut = ui_widget.menu->menu()->addAction ("Classify with Graph Cut..."); + connect(action_run_graphcut, SIGNAL(triggered()), this, + SLOT(on_run_graphcut_button_clicked())); + + action_save_config = ui_widget.menu->menu()->addAction ("Save current configuration..."); + action_load_config = ui_widget.menu->menu()->addAction ("Load configuration..."); connect(action_save_config, SIGNAL(triggered()), this, SLOT(on_save_config_button_clicked())); connect(action_load_config, SIGNAL(triggered()), this, SLOT(on_load_config_button_clicked())); - ui_widget.menu->menu()->addSection ("Algorithms"); - - action_run = ui_widget.menu->menu()->addAction ("Classification"); - connect(action_run, SIGNAL(triggered()), this, - SLOT(on_run_button_clicked())); - - action_run_smoothed = ui_widget.menu->menu()->addAction ("Classification with local smoothing"); - connect(action_run_smoothed, SIGNAL(triggered()), this, - SLOT(on_run_smoothed_button_clicked())); - - action_run_graphcut = ui_widget.menu->menu()->addAction ("Classification with Graph Cut"); - connect(action_run_graphcut, SIGNAL(triggered()), this, - SLOT(on_run_graphcut_button_clicked())); - ui_widget.menu->menu()->addSeparator(); QAction* close = ui_widget.menu->menu()->addAction ("Close"); @@ -287,7 +284,6 @@ public: connect(scene_obj, SIGNAL(itemIndexSelected(int)), this, SLOT(update_plugin(int))); } - } virtual void closure() { @@ -318,6 +314,7 @@ public Q_SLOTS: else if (Scene_surface_mesh_item* mesh_item = qobject_cast(scene->item(scene->mainSelectionIndex()))) create_from_item(mesh_item); + on_help_clicked(); } @@ -362,7 +359,6 @@ public Q_SLOTS: { ui_widget.menu->setEnabled(false); ui_widget.display->setEnabled(false); - ui_widget.classifier->setEnabled(false); ui_widget.frame->setEnabled(false); } @@ -371,17 +367,17 @@ public Q_SLOTS: ui_widget.menu->setEnabled(true); action_statistics->setEnabled(false); action_train->setEnabled(false); - action_reset_local->setEnabled(false); - action_reset->setEnabled(false); - action_random_region->setEnabled(false); - action_validate->setEnabled(false); + action_reset_local->setEnabled(true); + action_reset->setEnabled(true); + action_random_region->setEnabled(true); + action_validate->setEnabled(true); action_save_config->setEnabled(false); action_load_config->setEnabled(false); action_run->setEnabled(false); action_run_smoothed->setEnabled(false); action_run_graphcut->setEnabled(false); ui_widget.display->setEnabled(true); - ui_widget.classifier->setEnabled(true); + ui_widget.frame->setEnabled(true); } void enable_classif() @@ -474,12 +470,6 @@ public Q_SLOTS: dynamic_cast(it->second)->set_selection_item(selection_item); return it->second; } - else if (Scene_points_with_normal_item* points_item - = qobject_cast(item)) - return create_from_item(points_item); - else if (Scene_surface_mesh_item* mesh_item - = qobject_cast(item)) - return create_from_item(mesh_item); return NULL; } @@ -533,13 +523,13 @@ public Q_SLOTS: int get_classifier () { - if (ui_widget.classifier->currentText() == QString("Random Forest (ETHZ)")) + if (classifier->text() == QString(CGAL_CLASSIFICATION_ETHZ_ID)) return 1; - if (ui_widget.classifier->currentText() == QString("Neural Network (TensorFlow)")) + if (classifier->text() == QString(CGAL_CLASSIFICATION_TENSORFLOW_ID)) return 3; - if (ui_widget.classifier->currentText() == QString("Random Forest (OpenCV")) + if (classifier->text() == QString(CGAL_CLASSIFICATION_OPENCV_ID)) return 2; - if (ui_widget.classifier->currentText() == QString("Sum of Weighted Features")) + if (classifier->text() == QString(CGAL_CLASSIFICATION_SOWF_ID)) return 0; std::cerr << "Error: unknown classifier" << std::endl; @@ -553,17 +543,45 @@ public Q_SLOTS: classif->run (method, get_classifier(), subdivisions, smoothing); } - void on_classifier_changed (const QString& name) + void on_help_clicked() { - if (name == QString("Sum of Weighted Features")) - { - dock_widget_adv->show(); - dock_widget_adv->raise(); - } - else - dock_widget_adv->hide(); + QMessageBox::information(dock_widget, QString("Classification"), + QString("Classification\n" + "\n" + "Welcome to CGAL Classification! Please read carefully this notice\n" + "before using the plugin.\n" + "\n" + "[QUICK INTRODUCTION]\n" + "\n" + "In order to classify, you need to perform the following steps:\n" + "\n" + "1. Compute the features\n" + "2. Set up the labels (ground, vegetation, etc.) that you need\n" + "3. Select a training set for each of these labels\n" + "4. Train the classifier\n" + "\n" + "You can then either select more inliers for training and train again\n" + "to improve the results, classify with or without regularization or\n" + "save the classifier's configuration.\n" + "\n" + "When loading a classifier's configuration, the computed features\n" + "should be the same (same number of scales, etc.) and the labels should\n" + "be the same as when the classifier's configuration was saved.\n" + "\n" + "For more information, please refer to the CGAL manual.\n" + "\n" + "[IMPORTANT NOTICE ON SAVING CLASSIFIED ITEMS]\n" + "\n" + "If you intend to save the file after classifying, PLEASE CLOSE THE\n" + "CLASSIFICATION PLUGIN FIRST: for visualization, colors are saved in\n" + "the point set. If you do not close the classification plugin, colors\n" + "will be saved and might overwrite existing colors of the point cloud.\n" + "\n" + "Classification results will be saved if you use the PLY or LAS\n" + "formats. Training will be saved if you use the PLY format.\n")); + } - + void on_compute_features_button_clicked() { Item_classification_base* classif @@ -1255,6 +1273,48 @@ public Q_SLOTS: text->setText(str.c_str()); dialog.exec_no_cancel(); } + + void on_switch_classifier_clicked() + { + QMultipleInputDialog dialog ("Which classifier do you want to use?", mw); + + QRadioButton* ethz = dialog.add (CGAL_CLASSIFICATION_ETHZ_ID); + ethz->setChecked(true); + + QRadioButton* sowf = dialog.add (CGAL_CLASSIFICATION_SOWF_ID); + +#ifdef CGAL_LINKED_WITH_TENSORFLOW + QRadioButton* tensorflow = dialog.add (CGAL_CLASSIFICATION_TENSORFLOW_ID); +#endif + +#ifdef CGAL_LINKED_WITH_OPENCV + QRadioButton* opencv = dialog.add (CGAL_CLASSIFICATION_OPENCV_ID); +#endif + + if (dialog.exec() != QDialog::Accepted) + return; + + if (ethz->isChecked()) + classifier->setText(CGAL_CLASSIFICATION_ETHZ_ID); + else if (sowf->isChecked()) + classifier->setText(CGAL_CLASSIFICATION_SOWF_ID); +#ifdef CGAL_LINKED_WITH_TENSORFLOW + else if (tensorflow->isChecked()) + classifier->setText(CGAL_CLASSIFICATION_TENSORFLOW_ID); +#endif +#ifdef CGAL_LINKED_WITH_OPENCV + else if (opencv->isChecked()) + classifier->setText(CGAL_CLASSIFICATION_OPENCV_ID); +#endif + + if (sowf->isChecked()) + { + dock_widget_adv->show(); + dock_widget_adv->raise(); + } + else + dock_widget_adv->hide(); + } void on_train_clicked() { @@ -1610,16 +1670,18 @@ private: QDockWidget* dock_widget; QDockWidget* dock_widget_adv; QAction* action_statistics; - QAction* action_train; QAction* action_reset_local; QAction* action_reset; QAction* action_random_region; QAction* action_validate; - QAction* action_save_config; - QAction* action_load_config; + + QAction* classifier; + QAction* action_train; QAction* action_run; QAction* action_run_smoothed; QAction* action_run_graphcut; + QAction* action_save_config; + QAction* action_load_config; std::vector label_buttons; QPushButton* label_button; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index 99a49be0487..0361bfd4311 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -7,7 +7,7 @@ 0 0 368 - 143 + 157 @@ -39,28 +39,17 @@ - - - - - - 0 - 0 - - - - Classifier: - - - - - - - -1 - - - - + + + Qt::Vertical + + + + 20 + 40 + + + From 646ca523a0c15e27e01d7cad8075348f6d8381b8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 19 Sep 2018 12:36:02 +0200 Subject: [PATCH 048/186] Specialize QMultiInputDialog to handle correctly radio buttons --- .../Polyhedron/include/QMultipleInputDialog.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h index d36717bfb0a..f2b13bc84b2 100644 --- a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h +++ b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h @@ -9,6 +9,7 @@ #include #include #include +#include class QMultipleInputDialog { @@ -32,10 +33,22 @@ public: template QObjectType* add (const char* name, const char* key = NULL) { - QObjectType* out = new QObjectType (dialog); - form->addRow (QString(name), out); + QObjectType* out = NULL; + + if (boost::is_same::value) + { + out = dynamic_cast(new QRadioButton (QString(name), dialog)); + form->addRow (out); + } + else + { + out = new QObjectType (dialog); + form->addRow (QString(name), out); + } + if (key != NULL) map_widgets.insert (std::make_pair (key, out)); + return out; } From 5bb7e5d1d32da5655f1ed6dee30e4bd1ec350e14 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 08:55:49 +0100 Subject: [PATCH 049/186] Improve plugin with a menu bar and a better way to select classifier --- .../Classification/Classification_plugin.cpp | 70 ++--- .../Classification/Classification_widget.ui | 254 +++++++++--------- 2 files changed, 169 insertions(+), 155 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index a882df85469..b7664c7afe6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -193,75 +193,67 @@ public: color_att = QColor (75, 75, 77); - ui_widget.menu->setMenu (new QMenu("Classification Menu", ui_widget.menu)); - - QAction* help = ui_widget.menu->menu()->addAction ("Help"); - connect(help, SIGNAL(triggered()), this, - SLOT(on_help_clicked())); - - QAction* compute_features = ui_widget.menu->menu()->addAction ("Compute features..."); + QAction* compute_features = ui_widget.features_menu->addAction ("Compute features..."); connect(compute_features, SIGNAL(triggered()), this, SLOT(on_compute_features_button_clicked())); - action_statistics = ui_widget.menu->menu()->addAction ("Show feature statistics"); + action_statistics = ui_widget.features_menu->addAction ("Show feature statistics"); connect(action_statistics, SIGNAL(triggered()), this, SLOT(on_statistics_clicked())); - ui_widget.menu->menu()->addSection ("Training Set"); - - action_reset_local = ui_widget.menu->menu()->addAction ("Reset training set of selection"); + action_reset_local = ui_widget.training_menu->addAction ("Reset training set of selection"); connect(action_reset_local, SIGNAL(triggered()), this, SLOT(on_reset_training_set_of_selection_clicked())); - action_reset = ui_widget.menu->menu()->addAction ("Reset all training sets"); + action_reset = ui_widget.training_menu->addAction ("Reset all training sets"); connect(action_reset, SIGNAL(triggered()), this, SLOT(on_reset_training_sets_clicked())); - action_random_region = ui_widget.menu->menu()->addAction ("Select random region"); + action_random_region = ui_widget.training_menu->addAction ("Select random region"); action_random_region->setShortcut(Qt::SHIFT | Qt::Key_S); connect(action_random_region, SIGNAL(triggered()), this, SLOT(on_select_random_region_clicked())); - action_validate = ui_widget.menu->menu()->addAction ("Validate labels of current selection as training sets"); + action_validate = ui_widget.training_menu->addAction ("Validate labels of current selection as training sets"); connect(action_validate, SIGNAL(triggered()), this, SLOT(on_validate_selection_clicked())); - classifier = ui_widget.menu->menu()->addSection (CGAL_CLASSIFICATION_ETHZ_ID); + classifier = ui_widget.classifier_menu->addSection (CGAL_CLASSIFICATION_ETHZ_ID); - QAction* switch_classifier = ui_widget.menu->menu()->addAction ("Switch to another classifier..."); - connect(switch_classifier, SIGNAL(triggered()), this, - SLOT(on_switch_classifier_clicked())); - - action_train = ui_widget.menu->menu()->addAction ("Train..."); + action_train = ui_widget.classifier_menu->addAction ("Train..."); action_train->setShortcut(Qt::SHIFT | Qt::Key_T); connect(action_train, SIGNAL(triggered()), this, SLOT(on_train_clicked())); - action_run = ui_widget.menu->menu()->addAction ("Classify"); + ui_widget.classifier_menu->addSeparator(); + + action_run = ui_widget.classifier_menu->addAction ("Classify"); connect(action_run, SIGNAL(triggered()), this, SLOT(on_run_button_clicked())); - action_run_smoothed = ui_widget.menu->menu()->addAction ("Classify with local smoothing..."); + action_run_smoothed = ui_widget.classifier_menu->addAction ("Classify with local smoothing..."); connect(action_run_smoothed, SIGNAL(triggered()), this, SLOT(on_run_smoothed_button_clicked())); - action_run_graphcut = ui_widget.menu->menu()->addAction ("Classify with Graph Cut..."); + action_run_graphcut = ui_widget.classifier_menu->addAction ("Classify with Graph Cut..."); connect(action_run_graphcut, SIGNAL(triggered()), this, SLOT(on_run_graphcut_button_clicked())); - action_save_config = ui_widget.menu->menu()->addAction ("Save current configuration..."); - action_load_config = ui_widget.menu->menu()->addAction ("Load configuration..."); + ui_widget.classifier_menu->addSeparator(); + + action_save_config = ui_widget.classifier_menu->addAction ("Save current configuration..."); + action_load_config = ui_widget.classifier_menu->addAction ("Load configuration..."); connect(action_save_config, SIGNAL(triggered()), this, SLOT(on_save_config_button_clicked())); connect(action_load_config, SIGNAL(triggered()), this, SLOT(on_load_config_button_clicked())); - ui_widget.menu->menu()->addSeparator(); - - QAction* close = ui_widget.menu->menu()->addAction ("Close"); - connect(close, SIGNAL(triggered()), this, - SLOT(ask_for_closing())); - + ui_widget.classifier_menu->addSeparator(); + + QAction* switch_classifier = ui_widget.classifier_menu->addAction ("Switch to another classifier..."); + connect(switch_classifier, SIGNAL(triggered()), this, + SLOT(on_switch_classifier_clicked())); + connect(ui_widget.display, SIGNAL(currentIndexChanged(int)), this, SLOT(on_display_button_clicked(int))); @@ -275,6 +267,11 @@ public: connect(ui_widget_adv.feature_weight, SIGNAL(valueChanged(int)), this, SLOT(on_feature_weight_changed(int))); + connect(ui_widget.help, SIGNAL(clicked()), this, + SLOT(on_help_clicked())); + connect(ui_widget.close, SIGNAL(clicked()), this, + SLOT(ask_for_closing())); + QObject* scene_obj = dynamic_cast(scene_interface); if(scene_obj) { @@ -357,14 +354,18 @@ public Q_SLOTS: void disable_everything () { - ui_widget.menu->setEnabled(false); + ui_widget.features_menu->setEnabled(false); + ui_widget.training_menu->setEnabled(false); + ui_widget.classifier_menu->setEnabled(false); ui_widget.display->setEnabled(false); ui_widget.frame->setEnabled(false); } void enable_computation() { - ui_widget.menu->setEnabled(true); + ui_widget.features_menu->setEnabled(true); + ui_widget.training_menu->setEnabled(true); + ui_widget.classifier_menu->setEnabled(false); action_statistics->setEnabled(false); action_train->setEnabled(false); action_reset_local->setEnabled(true); @@ -382,6 +383,9 @@ public Q_SLOTS: void enable_classif() { + ui_widget.features_menu->setEnabled(true); + ui_widget.training_menu->setEnabled(true); + ui_widget.classifier_menu->setEnabled(true); action_statistics->setEnabled(true); action_train->setEnabled(true); action_reset_local->setEnabled(true); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index 0361bfd4311..0c9e307b129 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -6,8 +6,8 @@ 0 0 - 368 - 157 + 411 + 194 @@ -20,144 +20,152 @@ Classification - + - + - - - - - - 75 - true - - - - Classification - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + Features + + + + + Training Sets + + + + + Classifier + + + + + + - + - Qt::Vertical + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + :/cgal/icons/resources/help_button.png:/cgal/icons/resources/help_button.png - - - - - - - - 0 - 0 - - - - View: - - - - - - - 0 - - - - Real colors - - - - - Classification - - - - - Training sets - - - - - - - - - - - - false - - - Min - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Max - - - - - - + + + + + + + :/cgal/icons/check-off.png:/cgal/icons/check-off.png + + - + + + View + + + + + + 0 + + + + Real colors + + + + + Classification + + + + + Training sets + + + + + + + + Qt::Vertical + + + + + + + false + + + Min + + + false + + + + + + + Qt::Horizontal + + + + 65 + 20 + + + + + + + + false + + + Max + + + + + + + + 0 0 - - QFrame::StyledPanel - - - QFrame::Raised + + Labels @@ -186,6 +194,8 @@ - + + + From b4b6acfeca98299cc7f397895439271d5f9de786 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 10:19:17 +0100 Subject: [PATCH 050/186] Clean up plugin --- .../Classification/Classification_plugin.cpp | 7 +- .../Classification/Classification_widget.ui | 2 +- .../Classification/Cluster_classification.cpp | 323 +++++++----------- .../Classification/Cluster_classification.h | 5 - .../Classification/Item_classification_base.h | 2 - .../Point_set_item_classification.cpp | 172 ++++------ .../Point_set_item_classification.h | 5 - .../Surface_mesh_item_classification.cpp | 7 - .../Surface_mesh_item_classification.h | 2 - .../demo/Polyhedron/include/Point_set_3.h | 31 +- 10 files changed, 215 insertions(+), 341 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index b7664c7afe6..6a843c4f264 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -357,7 +357,7 @@ public Q_SLOTS: ui_widget.features_menu->setEnabled(false); ui_widget.training_menu->setEnabled(false); ui_widget.classifier_menu->setEnabled(false); - ui_widget.display->setEnabled(false); + ui_widget.view->setEnabled(false); ui_widget.frame->setEnabled(false); } @@ -377,7 +377,7 @@ public Q_SLOTS: action_run->setEnabled(false); action_run_smoothed->setEnabled(false); action_run_graphcut->setEnabled(false); - ui_widget.display->setEnabled(true); + ui_widget.view->setEnabled(true); ui_widget.frame->setEnabled(true); } @@ -1577,10 +1577,7 @@ public Q_SLOTS: Item_classification_base* classif = get_classification(); if(!classif) - { - print_message("Error: there is no point set classification item!"); return; - } if (classif->number_of_features() <= (std::size_t)v) return; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index 0c9e307b129..e96efa5c7d3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -83,7 +83,7 @@ - + View diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 24610806714..b9e01c89204 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -406,17 +406,7 @@ void Cluster_classification::backup_existing_colors_and_add_new() m_points->point_set()->remove_colors(); } - m_red = m_points->point_set()->add_property_map("red").first; - m_green = m_points->point_set()->add_property_map("green").first; - m_blue = m_points->point_set()->add_property_map("blue").first; - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - m_points->point_set()->check_colors(); + m_points->point_set()->add_colors(); } void Cluster_classification::reset_colors() @@ -427,39 +417,12 @@ void Cluster_classification::reset_colors() { for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = m_color[*it][0]; - m_green[*it] = m_color[*it][1]; - m_blue[*it] = m_color[*it][2]; - } + m_points->point_set()->set_color(*it, m_color[*it]); + m_points->point_set()->remove_property_map(m_color); } } -// Write point set to .PLY file -bool Cluster_classification::write_output(std::ostream& stream) -{ - if (m_features.size() == 0) - return false; - - reset_indices(); - - stream.precision (std::numeric_limits::digits10 + 2); - - // std::vector colors; - // for (std::size_t i = 0; i < m_labels.size(); ++ i) - // { - // Color c = {{ (unsigned char)(m_labels[i].second.red()), - // (unsigned char)(m_labels[i].second.green()), - // (unsigned char)(m_labels[i].second.blue()) }}; - // colors.push_back (c); - // } - - // m_psc->write_classification_to_ply (stream); - return true; -} - - void Cluster_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; @@ -470,175 +433,146 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) static Color_ramp ramp; ramp.build_rainbow(); reset_indices(); + if (index_color == -1) // item color - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - } - else if (index_color == 0) // real colors - { - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = m_color[*it][0]; - m_green[*it] = m_color[*it][1]; - m_blue[*it] = m_color[*it][2]; - } - } - else if (index_color == 1) // classif - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - QColor color (0, 0, 0); - int cid = m_cluster_id[*it]; - if (cid != -1) - { - std::size_t c = m_clusters[cid].label(); - - if (c != std::size_t(-1)) - color = m_label_colors[c]; - } - - m_red[*it] = color.red(); - m_green[*it] = color.green(); - m_blue[*it] = color.blue(); - } - } - else if (index_color == 2) // training - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - QColor color (0, 0, 0); - int cid = m_cluster_id[*it]; - float div = 1; - - if (cid != -1) - { - int c = m_clusters[cid].training(); - int c2 = m_clusters[cid].label(); - - if (c != -1) - color = m_label_colors[std::size_t(c)]; - - if (c != c2) - div = 2; - } - m_red[*it] = (color.red() / div); - m_green[*it] = (color.green() / div); - m_blue[*it] = (color.blue() / div); - } - } - else if (index_color == 3) // clusters - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - int cid = m_cluster_id[*it]; - - if (cid != -1) - { - srand(cid); - m_red[*it] = 64 + rand() % 192; - m_green[*it] = 64 + rand() % 192; - m_blue[*it] = 64 + rand() % 192; - } - else - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - } - } + m_points->point_set()->remove_colors(); else { - std::size_t corrected_index = index_color - 4; - if (corrected_index < m_labels.size()) // Display label probabilities + if (!m_points->point_set()->has_colors()) + m_points->point_set()->add_colors(); + + if (index_color == 0) // real colors { - if (m_label_probabilities.size() <= corrected_index || - m_label_probabilities[corrected_index].size() != m_clusters.size()) + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + m_points->point_set()->set_color(*it, m_color[*it]); + } + else if (index_color == 1) // classif + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) + QColor color (0, 0, 0); + int cid = m_cluster_id[*it]; + if (cid != -1) { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; + std::size_t c = m_clusters[cid].label(); + + if (c != std::size_t(-1)) + color = m_label_colors[c]; + } + + m_points->point_set()->set_color(*it, color); + } + } + else if (index_color == 2) // training + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + QColor color (0, 0, 0); + int cid = m_cluster_id[*it]; + float div = 1; + + if (cid != -1) + { + int c = m_clusters[cid].training(); + int c2 = m_clusters[cid].label(); + + if (c != -1) + color = m_label_colors[std::size_t(c)]; + + if (c != c2) + div = 2; + } + m_points->point_set()->set_color(*it, color.red() / div, color.green() / div, color.blue() / div); + } + } + else if (index_color == 3) // clusters + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + + if (cid != -1) + { + srand(cid); + m_points->point_set()->set_color(*it, 64 + rand() % 192, 64 + rand() % 192, 64 + rand() % 192); + } + else + { + m_points->point_set()->set_color(*it); + } + } + } + else + { + std::size_t corrected_index = index_color - 4; + if (corrected_index < m_labels.size()) // Display label probabilities + { + if (m_label_probabilities.size() <= corrected_index || + m_label_probabilities[corrected_index].size() != m_clusters.size()) + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + m_points->point_set()->set_color(*it); + } + else + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + if (cid != -1) + { + float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][cid])); + m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); + } + else + m_points->point_set()->set_color(*it); + } } } else { + corrected_index -= m_labels.size(); + if (corrected_index >= m_features.size()) + { + std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl; + return; + } + + Feature_handle feature = m_features[corrected_index]; + + float min = std::numeric_limits::max(); + float max = -std::numeric_limits::max(); + for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { int cid = m_cluster_id[*it]; if (cid != -1) { - float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][cid])); - m_red[*it] = (unsigned char)(ramp.r(v) * 255); - m_green[*it] = (unsigned char)(ramp.g(v) * 255); - m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + if (feature->value(cid) > max) + max = feature->value(cid); + if (feature->value(cid) < min) + min = feature->value(cid); + } + } + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + int cid = m_cluster_id[*it]; + if (cid != -1) + { + float v = (feature->value(cid) - min) / (max - min); + m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } else - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - } - } - } - else - { - corrected_index -= m_labels.size(); - if (corrected_index >= m_features.size()) - { - std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl; - return; - } - - Feature_handle feature = m_features[corrected_index]; - - float min = std::numeric_limits::max(); - float max = -std::numeric_limits::max(); - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - int cid = m_cluster_id[*it]; - if (cid != -1) - { - if (feature->value(cid) > max) - max = feature->value(cid); - if (feature->value(cid) < min) - min = feature->value(cid); - } - } - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - int cid = m_cluster_id[*it]; - if (cid != -1) - { - float v = (feature->value(cid) - min) / (max - min); - m_red[*it] = (unsigned char)(ramp.r(v) * 255); - m_green[*it] = (unsigned char)(ramp.g(v) * 255); - m_blue[*it] = (unsigned char)(ramp.b(v) * 255); - } - else - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; + m_points->point_set()->set_color(*it); } } } @@ -646,12 +580,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) for (Point_set::const_iterator it = m_points->point_set()->first_selected(); it != m_points->point_set()->end(); ++ it) - { - m_red[*it] = 255; - m_green[*it] = 0; - m_blue[*it] = 0; - } - + m_points->point_set()->set_color(*it, 255, 0, 0); } int Cluster_classification::real_index_color() const diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index 8a0f69f2ced..53753e7cbbb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -254,8 +254,6 @@ class Cluster_classification : public Item_classification_base } - bool write_output(std::ostream& out); - QColor add_new_label (const char* name) { QColor out = Item_classification_base::add_new_label (name); @@ -384,9 +382,6 @@ class Cluster_classification : public Item_classification_base std::vector m_clusters; - Point_set::Property_map m_red; - Point_set::Property_map m_green; - Point_set::Property_map m_blue; Point_set::Property_map m_color; Point_set::Property_map m_cluster_id; Point_set::Property_map m_training; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 3142c32695a..7dc0517071d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -66,8 +66,6 @@ public: virtual void generate_one_item_per_label(std::vector& items, const char* name) const = 0; - virtual bool write_output(std::ostream& out) = 0; - bool features_computed() const { return (m_features.size() != 0); } std::size_t number_of_features() const { return m_features.size(); } Feature_handle feature(std::size_t i) { return m_features[i]; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index e201748b84d..ee308ac5e11 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -338,18 +338,8 @@ void Point_set_item_classification::backup_existing_colors_and_add_new() m_points->point_set()->remove_colors(); } - - m_red = m_points->point_set()->add_property_map("red").first; - m_green = m_points->point_set()->add_property_map("green").first; - m_blue = m_points->point_set()->add_property_map("blue").first; - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - m_points->point_set()->check_colors(); + + m_points->point_set()->add_colors(); } void Point_set_item_classification::reset_colors() @@ -360,39 +350,12 @@ void Point_set_item_classification::reset_colors() { for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = m_color[*it][0]; - m_green[*it] = m_color[*it][1]; - m_blue[*it] = m_color[*it][2]; - } + m_points->point_set()->set_color(*it, m_color[*it]); + m_points->point_set()->remove_property_map(m_color); } } -// Write point set to .PLY file -bool Point_set_item_classification::write_output(std::ostream& stream) -{ - if (m_features.size() == 0) - return false; - - reset_indices(); - - stream.precision (std::numeric_limits::digits10 + 2); - - // std::vector colors; - // for (std::size_t i = 0; i < m_labels.size(); ++ i) - // { - // Color c = {{ (unsigned char)(m_labels[i].second.red()), - // (unsigned char)(m_labels[i].second.green()), - // (unsigned char)(m_labels[i].second.blue()) }}; - // colors.push_back (c); - // } - - // m_psc->write_classification_to_ply (stream); - return true; -} - - void Point_set_item_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; @@ -403,65 +366,55 @@ void Point_set_item_classification::change_color (int index, float* vmin, float* static Color_ramp ramp; ramp.build_rainbow(); reset_indices(); + if (index_color == -1) // item color - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } - } - else if (index_color == 0) // real colors - { - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = m_color[*it][0]; - m_green[*it] = m_color[*it][1]; - m_blue[*it] = m_color[*it][2]; - } - } - else if (index_color == 1) // classif - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - QColor color (0, 0, 0); - std::size_t c = m_classif[*it]; - - if (c != std::size_t(-1)) - color = m_label_colors[c]; - - m_red[*it] = color.red(); - m_green[*it] = color.green(); - m_blue[*it] = color.blue(); - } - } - else if (index_color == 2) // training - { - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) - { - QColor color (0, 0, 0); - int c = m_training[*it]; - int c2 = m_classif[*it]; - - if (c != -1) - color = m_label_colors[std::size_t(c)]; - - float div = 1; - if (c != c2) - div = 2; - - m_red[*it] = (color.red() / div); - m_green[*it] = (color.green() / div); - m_blue[*it] = (color.blue() / div); - } - } + m_points->point_set()->remove_colors(); else + { + if (!m_points->point_set()->has_colors()) + m_points->point_set()->add_colors(); + + if (index_color == 0) // real colors + { + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + m_points->point_set()->set_color(*it, m_color[*it]); + } + else if (index_color == 1) // classif + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + QColor color (0, 0, 0); + std::size_t c = m_classif[*it]; + + if (c != std::size_t(-1)) + color = m_label_colors[c]; + + m_points->point_set()->set_color(*it, color); + } + } + else if (index_color == 2) // training + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + QColor color (0, 0, 0); + int c = m_training[*it]; + int c2 = m_classif[*it]; + + if (c != -1) + color = m_label_colors[std::size_t(c)]; + + float div = 1; + if (c != c2) + div = 2; + + m_points->point_set()->set_color(*it, color.red() / div, color.green() / div, color.blue() / div); + } + } + else { std::size_t corrected_index = index_color - 3; if (corrected_index < m_labels.size()) // Display label probabilities @@ -471,11 +424,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float* { for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) - { - m_red[*it] = 0; - m_green[*it] = 0; - m_blue[*it] = 0; - } + m_points->point_set()->set_color(*it); } else { @@ -483,9 +432,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float* it != m_points->point_set()->first_selected(); ++ it) { float v = std::max (0.f, std::min(1.f, m_label_probabilities[corrected_index][*it])); - m_red[*it] = (unsigned char)(ramp.r(v) * 255); - m_green[*it] = (unsigned char)(ramp.g(v) * 255); - m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } } } @@ -526,9 +473,8 @@ void Point_set_item_classification::change_color (int index, float* vmin, float* float v = (feature->value(*it) - min) / (max - min); if (v < 0.f) v = 0.f; if (v > 1.f) v = 1.f; - m_red[*it] = (unsigned char)(ramp.r(v) * 255); - m_green[*it] = (unsigned char)(ramp.g(v) * 255); - m_blue[*it] = (unsigned char)(ramp.b(v) * 255); + + m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } if (vmin != NULL && vmax != NULL) @@ -538,15 +484,11 @@ void Point_set_item_classification::change_color (int index, float* vmin, float* } } } + } for (Point_set::const_iterator it = m_points->point_set()->first_selected(); it != m_points->point_set()->end(); ++ it) - { - m_red[*it] = 255; - m_green[*it] = 0; - m_blue[*it] = 0; - } - + m_points->point_set()->set_color(*it, 255, 0, 0); } int Point_set_item_classification::real_index_color() const diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index a6138fe4c07..3dc0ba57af9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -263,8 +263,6 @@ class Point_set_item_classification : public Item_classification_base } } - bool write_output(std::ostream& out); - QColor add_new_label (const char* name) { QColor out = Item_classification_base::add_new_label (name); @@ -402,9 +400,6 @@ class Point_set_item_classification : public Item_classification_base std::vector > m_label_probabilities; - Point_set::Property_map m_red; - Point_set::Property_map m_green; - Point_set::Property_map m_blue; Point_set::Property_map m_color; Point_set::Property_map m_training; Point_set::Property_map m_classif; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 6f4d47b0704..e04bc8330c1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -80,13 +80,6 @@ void Surface_mesh_item_classification::backup_existing_colors_and_add_new() m_mesh->polyhedron()->add_property_map("f:color", CGAL::Color(128,128,128)).first; } -bool Surface_mesh_item_classification::write_output(std::ostream& ) -{ - // TODO - return true; -} - - void Surface_mesh_item_classification::change_color (int index, float* vmin, float* vmax) { m_index_color = index; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h index a9983109bc1..90d53ae3151 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h @@ -135,8 +135,6 @@ public: std::cerr << "Warning: operation not yet available for meshes." << std::endl; } - bool write_output(std::ostream& out); - void set_selection_item (Scene_polyhedron_selection_item* selection) { m_selection = selection; diff --git a/Polyhedron/demo/Polyhedron/include/Point_set_3.h b/Polyhedron/demo/Polyhedron/include/Point_set_3.h index 8697f75c2cf..c0802ee24aa 100644 --- a/Polyhedron/demo/Polyhedron/include/Point_set_3.h +++ b/Polyhedron/demo/Polyhedron/include/Point_set_3.h @@ -268,7 +268,19 @@ public: { return (m_blue != Byte_map()); } + + bool add_colors () + { + if (has_colors()) + return false; + m_red = this->template add_property_map("red", 0).first; + m_green = this->template add_property_map("green", 0).first; + m_blue = this->template add_property_map("blue", 0).first; + + return true; + } + void remove_colors() { if (m_blue != Byte_map()) @@ -284,20 +296,35 @@ public: this->template remove_property_map(m_fblue); } } - + double red (const Index& index) const { return (m_red == Byte_map()) ? m_fred[index] : double(m_red[index]) / 255.; } double green (const Index& index) const { return (m_green == Byte_map()) ? m_fgreen[index] : double(m_green[index]) / 255.; } double blue (const Index& index) const { return (m_blue == Byte_map()) ? m_fblue[index] : double(m_blue[index]) / 255.; } - void set_color (const Index& index, unsigned char r, unsigned char g, unsigned char b) + + void set_color (const Index& index, unsigned char r = 0, unsigned char g = 0, unsigned char b = 0) { m_red[index] = r; m_green[index] = g; m_blue[index] = b; } + void set_color (const Index& index, const QColor& color) + { + m_red[index] = color.red(); + m_green[index] = color.green(); + m_blue[index] = color.blue(); + } + + template + void set_color (const Index& index, const ColorRange& color) + { + m_red[index] = color[0]; + m_green[index] = color[1]; + m_blue[index] = color[2]; + } iterator first_selected() { return this->m_indices.end() - this->m_nb_removed; } From 5758fb5b708909a9632b81fe93b6ff164701823e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 11:24:20 +0100 Subject: [PATCH 051/186] Add names of QAction* for selection plugins in order to find them from outside plugin --- Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp | 1 + .../Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index 338a0f979ce..8fb88ab304b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -86,6 +86,7 @@ public: actionSelection = new QAction( QString("Surface Mesh Selection") , mw); + actionSelection->setObjectName("actionSelection"); connect(actionSelection, SIGNAL(triggered()), this, SLOT(selection_action())); last_mode = 0; dock_widget = new QDockWidget( diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp index 9b9c5853770..2ec6bccea5c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp @@ -426,6 +426,7 @@ public: rg_cluster_epsilon = -1; rg_normal_threshold = 20; actionPointSetSelection = new QAction(tr("Selection"), mw); + actionPointSetSelection->setObjectName("actionPointSetSelection"); connect(actionPointSetSelection, SIGNAL(triggered()), this, SLOT(selection_action())); dock_widget = new QDockWidget("Point Set Selection", mw); From 0e456f0b4fe960499663bb88a58f73ae8e0121b4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 11:24:38 +0100 Subject: [PATCH 052/186] Launch selection plugins along with classification if possible --- .../Classification/Classification_plugin.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 6a843c4f264..f0878969aee 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -307,10 +307,25 @@ public Q_SLOTS: dock_widget->raise(); if (Scene_points_with_normal_item* points_item = qobject_cast(scene->item(scene->mainSelectionIndex()))) + { create_from_item(points_item); + QAction* ps_selection = mw->findChild("actionPointSetSelection"); + if (ps_selection) + ps_selection->trigger(); + else + print_message("Warning: can't find Point Set Selection plugin"); + } else if (Scene_surface_mesh_item* mesh_item = qobject_cast(scene->item(scene->mainSelectionIndex()))) + { create_from_item(mesh_item); + QAction* sm_selection = mw->findChild("actionSelection"); + if (sm_selection) + sm_selection->trigger(); + else + print_message("Warning: can't find Surface Mesh Selection plugin"); + } + on_help_clicked(); } From f2f919c6bdd697cdb606d6c7c5786b87e74252ad Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 11:44:11 +0100 Subject: [PATCH 053/186] Add option to change name of label --- .../include/CGAL/Classification/Label.h | 4 ++ .../Classification/Classification_plugin.cpp | 52 ++++++++++++++++++- .../Classification/Item_classification_base.h | 4 ++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/Label.h b/Classification/include/CGAL/Classification/Label.h index 910a3498add..6c06eb96a49 100644 --- a/Classification/include/CGAL/Classification/Label.h +++ b/Classification/include/CGAL/Classification/Label.h @@ -50,6 +50,10 @@ public: Label (std::string name) : m_name (name) { } const std::string& name() const { return m_name; } + + /// \cond SKIP_IN_MANUAL + void set_name (const std::string& name) { m_name = name; } + /// \endcond }; #ifdef DOXYGEN_RUNNING diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index f0878969aee..b64356a5617 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -126,6 +126,7 @@ class Polyhedron_demo_classification_plugin : color_button->setStyleSheet(s); color_button->update(); } + }; @@ -1451,6 +1452,10 @@ public Q_SLOTS: connect(change_color, SIGNAL(triggered()), this, SLOT(on_color_changed_clicked())); + QAction* change_name = label_buttons.back().menu->addAction ("Change name"); + connect(change_name, SIGNAL(triggered()), this, + SLOT(on_name_changed_clicked())); + QAction* create = label_buttons.back().menu->addAction ("Create point set item from labeled points"); connect(create, SIGNAL(triggered()), this, SLOT(on_create_point_set_item())); @@ -1551,7 +1556,11 @@ public Q_SLOTS: int position = row_index * 3 + column_index; QColor color = label_buttons[position].color; - color = QColorDialog::getColor(color, (QWidget*)mw, "Change of color of label"); + color = QColorDialog::getColor(color, (QWidget*)mw, "Change color of label"); + + if (!color.isValid()) + return; + label_buttons[position].change_color (color); classif->change_label_color (position, color); @@ -1560,6 +1569,47 @@ public Q_SLOTS: item_changed(classif->item()); } + void on_name_changed_clicked() + { + Item_classification_base* classif + = get_classification(); + if(!classif) + { + print_message("Error: there is no point set classification item!"); + return; + } + + QPushButton* label_clicked = qobject_cast(QObject::sender()->parent()->parent()); + if (label_clicked == NULL) + std::cerr << "Error" << std::endl; + else + { + int index = ui_widget.labelGrid->indexOf(label_clicked); + int row_index, column_index, row_span, column_span; + ui_widget.labelGrid->getItemPosition(index, &row_index, &column_index, &row_span, &column_span); + + int position = row_index * 3 + column_index; + + bool ok; + QString name = + QInputDialog::getText((QWidget*)mw, + tr("Change name of label"), // dialog title + tr("New name:"), // field label + QLineEdit::Normal, + classif->label(position)->name().c_str(), + &ok); + + if (!ok) + return; + + classif->change_label_name (position, name.toStdString()); + } + + update_plugin_from_item(classif); + classif->update_color (); + item_changed(classif->item()); + } + void on_add_selection_to_training_set_clicked() { Item_classification_base* classif diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 7dc0517071d..3fdce8b2053 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -236,6 +236,10 @@ public: { m_label_colors[position] = color; } + void change_label_name (std::size_t position, const std::string& name) + { + m_labels[position]->set_name (name); + } QColor get_new_label_color (const std::string& name) { From 7d43e87716f4ae7f4035a431e9d6df00b2d33fa0 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 12:11:00 +0100 Subject: [PATCH 054/186] Add warning about scope definition of feature generators --- .../CGAL/Classification/Mesh_feature_generator.h | 11 ++++++++--- .../CGAL/Classification/Point_set_feature_generator.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index 935abc76a1e..6892f3c6b02 100644 --- a/Classification/include/CGAL/Classification/Mesh_feature_generator.h +++ b/Classification/include/CGAL/Classification/Mesh_feature_generator.h @@ -65,15 +65,20 @@ namespace Classification { \brief Generates a set of generic features for surface mesh classification. - This class takes care of computing all necessary data structures and - of generating a set of generic features at multiple scales to - increase the reliability of the classification. + This class takes care of computing and storing all necessary data + structures and of generating a set of generic features at multiple + scales to increase the reliability of the classification. A `PointMap` is required: this map should associate each face of the mesh to a representative point (for example, the center of mass of the face). It is used to generate point set features by considering the mesh as a point set. + \warning The generated features use data structures that are stored + inside the generator. For this reason, the generator should be + instantiated _within the same scope_ as the feature set and should + not be deleted before the feature set. + \tparam GeomTraits model of \cgal Kernel. \tparam FaceListGraph model of `FaceListGraph`. \tparam PointMap model of `ReadablePropertyMap` whose key type is diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index 2e10f364e0f..adaf9eb5782 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -67,9 +67,14 @@ namespace Classification { \brief Generates a set of generic features for point set classification. - This class takes care of computing all necessary data structures and - of generating a set of generic features at multiple scales to - increase the reliability of the classification. + This class takes care of computing and storing all necessary data + structures and of generating a set of generic features at multiple + scales to increase the reliability of the classification. + + \warning The generated features use data structures that are stored + inside the generator. For this reason, the generator should be + instantiated _within the same scope_ as the feature set and should + not be deleted before the feature set. \tparam GeomTraits model of \cgal Kernel. \tparam PointRange model of `ConstRange`. Its iterator type is From c0897c29bf442cc95f0670ead48a72cca2d7d08e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 12:39:05 +0100 Subject: [PATCH 055/186] Document new features of Random Forest --- .../ETHZ_random_forest_classifier.h | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 0cba0824b9e..6ea47a2a6e9 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -101,8 +101,23 @@ public: /// @} /// \name Training - /// @{ + + /// \cond SKIP_IN_MANUAL + template + void train (const LabelIndexRange& ground_truth, + bool reset_trees = true, + std::size_t num_trees = 25, + std::size_t max_depth = 20) + { +#ifdef CGAL_LINKED_WITH_TBB + train(ground_truth, reset_trees, num_trees, max_depth); +#else + train(ground_truth, reset_trees, num_trees, max_depth); +#endif + } + /// \endcond + /*! \brief Runs the training algorithm. @@ -113,6 +128,11 @@ public: \pre At least one ground truth item should be assigned to each label. + \tparam ConcurrencyTag enables sequential versus parallel + algorithm. Possible values are `Parallel_tag` (default value is + %CGAL is linked with TBB) or `Sequential_tag` (default value + otherwise). + \param ground_truth vector of label indices. It should contain for each input item, in the same order as the input set, the index of the corresponding label in the `Label_set` provided in the @@ -196,11 +216,42 @@ public: out[i] = (std::min) (1.f, (std::max) (0.f, prob[i])); } + /// \endcond + + /// @} + + /// \name Miscellaneous + /// @{ + + /*! + \brief Computes, for each feature, how many nodes in the forest + uses it as a split criterion. + + Each tree of the random forest recursively splits the training + data set using at each node one of the input features. This method + counts, for each feature, how many times it was selected by the + training algorithm as a split criterion. + + This method allows to evaluate how useful a feature was with + respect to a training set: if a feature is used a lot, that means + that it has a strong discriminative power with respect to how the + labels are represented by the feature set; on the contrary, if a + feature is not used very often, it's discriminative power is + probably low; if a feature is _never_ used, it likely has no + interest at all and is completely uncorrelated to the label + segmentation of the training set. + + \param count vector where the result is stored. After running the + method, it contains, for each feature, the number of nodes in the + foret that uses it as a split criterion, in the same order as the + feature set order. + */ void get_feature_usage (std::vector& count) const { + count.clear(); + count.resize(m_features.size(), 0); return m_rfc->get_feature_usage(count); } - /// \endcond /// @} From 7ac0eccbb9cbcdda0afe6ea051103bcedf33b7d6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 12:52:37 +0100 Subject: [PATCH 056/186] Add function to copy random forest classifier --- .../ETHZ_random_forest_classifier.h | 22 ++++++++++++++++++- .../Classification/test_classification_io.cpp | 7 +++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 6ea47a2a6e9..12db1189a0b 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -90,6 +90,26 @@ public: : m_labels (labels), m_features (features), m_rfc (NULL) { } + /*! + \brief Copies the `other` classifier's configuration using another + set of `features`. + + This constructor can be used to apply a trained random forest to + another data set. + + \warning The feature set should be composed of the same features + than the ones used by `other`, and in the same order. + + */ + ETHZ_random_forest_classifier (const ETHZ_random_forest_classifier& other, + const Feature_set& features) + : m_labels (other.m_labels), m_features (features), m_rfc (NULL) + { + std::stringstream stream; + other.save_configuration(stream); + this->load_configuration(stream); + } + /// \cond SKIP_IN_MANUAL ~ETHZ_random_forest_classifier () { @@ -267,7 +287,7 @@ public: The output file is written in an GZIP container that is readable by the `load_configuration()` method. */ - void save_configuration (std::ostream& output) + void save_configuration (std::ostream& output) const { boost::iostreams::filtering_ostream outs; outs.push(boost::iostreams::gzip_compressor()); diff --git a/Classification/test/Classification/test_classification_io.cpp b/Classification/test/Classification/test_classification_io.cpp index cc05ccfb110..bb1d770e47c 100644 --- a/Classification/test/Classification/test_classification_io.cpp +++ b/Classification/test/Classification/test_classification_io.cpp @@ -87,13 +87,18 @@ int main (int, char**) std::ifstream inf ("output_config.gz", std::ios::binary); classifier2.load_configuration(inf); + Classifier classifier3 (classifier, features); + std::vector label_indices; std::vector label_indices_2; + std::vector label_indices_3; Classification::classify (points, labels, classifier, label_indices); Classification::classify (points, labels, classifier2, label_indices_2); + Classification::classify (points, labels, classifier3, label_indices_3); assert (label_indices == label_indices_2); - + assert (label_indices == label_indices_3); + return EXIT_SUCCESS; } From 6901935aecfddf889e4c763b056af9be2dc75f4a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 13:48:54 +0100 Subject: [PATCH 057/186] Add new features based on local height --- .../doc/Classification/PackageDescription.txt | 3 + .../Classification/Feature/Height_above.h | 142 +++++++++++++++++ .../Classification/Feature/Height_below.h | 142 +++++++++++++++++ .../Classification/Feature/Vertical_range.h | 144 ++++++++++++++++++ .../Classification/Mesh_feature_generator.h | 18 +++ .../Point_set_feature_generator.h | 18 +++ 6 files changed, 467 insertions(+) create mode 100644 Classification/include/CGAL/Classification/Feature/Height_above.h create mode 100644 Classification/include/CGAL/Classification/Feature/Height_below.h create mode 100644 Classification/include/CGAL/Classification/Feature/Vertical_range.h diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index 6452aa25b39..c7fd807ce01 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -115,8 +115,11 @@ Data structures specialized to classify clusters. - `CGAL::Classification::Feature::Echo_scatter` - `CGAL::Classification::Feature::Eigenvalue` - `CGAL::Classification::Feature::Elevation` +- `CGAL::Classification::Feature::Height_above` +- `CGAL::Classification::Feature::Height_below` - `CGAL::Classification::Feature::Simple_feature` - `CGAL::Classification::Feature::Vertical_dispersion` +- `CGAL::Classification::Feature::Vertical_range` - `CGAL::Classification::Feature::Verticality` ## Point Set Classification ## diff --git a/Classification/include/CGAL/Classification/Feature/Height_above.h b/Classification/include/CGAL/Classification/Feature/Height_above.h new file mode 100644 index 00000000000..b812e76634d --- /dev/null +++ b/Classification/include/CGAL/Classification/Feature/Height_above.h @@ -0,0 +1,142 @@ +// Copyright (c) 2012 INRIA Sophia-Antipolis (France). +// Copyright (c) 2017 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) : Florent Lafarge, Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_FEATURE_HEIGHT_ABOVE_H +#define CGAL_CLASSIFICATION_FEATURE_HEIGHT_ABOVE_H + +#include + +#include + +#include +#include +#include +#include + +namespace CGAL { + +namespace Classification { + +namespace Feature { + + /*! + \ingroup PkgClassificationFeatures + + %Feature based on local height distribution This feature computes + the distance between the maxium height on the local cell of the + planimetric grid and a point's height. + + Its default name is "height_after". + + \tparam GeomTraits model of \cgal Kernel. + \tparam PointRange model of `ConstRange`. Its iterator type + is `RandomAccessIterator` and its value type is the key type of + `PointMap`. + \tparam PointMap model of `ReadablePropertyMap` whose key + type is the value type of the iterator of `PointRange` and value type + is `GeomTraits::Point_3`. + + */ +template +class Height_above : public Feature_base +{ + typedef typename GeomTraits::Iso_cuboid_3 Iso_cuboid_3; + + typedef Image Image_float; + typedef Planimetric_grid Grid; + + const PointRange& input; + PointMap point_map; + const Grid& grid; + Image_float dtm; + std::vector values; + +public: + /*! + \brief Constructs the feature. + + \param input point range. + \param point_map property map to access the input points. + \param grid precomputed `Planimetric_grid`. + */ + Height_above (const PointRange& input, + PointMap point_map, + const Grid& grid) + : input(input), point_map(point_map), grid(grid) + { + this->set_name ("height_above"); + + dtm = Image_float(grid.width(),grid.height()); + + for (std::size_t j = 0; j < grid.height(); ++ j) + for (std::size_t i = 0; i < grid.width(); ++ i) + if (grid.has_points(i,j)) + { + float z_max = -std::numeric_limits::max(); + + typename Grid::iterator end = grid.indices_end(i,j); + for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it) + { + float z = float(get(point_map, *(input.begin()+(*it))).z()); + z_max = (std::max(z_max, z)); + } + + dtm(i,j) = z_max; + } + + if (grid.width() * grid.height() > input.size()) + { + values.resize (input.size(), 0.f); + for (std::size_t i = 0; i < input.size(); ++ i) + { + std::size_t I = grid.x(i); + std::size_t J = grid.y(i); + values[i] = dtm(I,J) - get (point_map, *(input.begin() + i)).z(); + } + dtm.free(); + } + + } + + /// \cond SKIP_IN_MANUAL + virtual float value (std::size_t pt_index) + { + if (values.empty()) + { + std::size_t I = grid.x(pt_index); + std::size_t J = grid.y(pt_index); + return dtm(I,J) - get (point_map, *(input.begin() + pt_index)).z(); + } + + return values[pt_index]; + } + + /// \endcond +}; + +} // namespace Feature + +} // namespace Classification + + +} // namespace CGAL + +#endif // CGAL_CLASSIFICATION_FEATURE_HEIGHT_ABOVE_H diff --git a/Classification/include/CGAL/Classification/Feature/Height_below.h b/Classification/include/CGAL/Classification/Feature/Height_below.h new file mode 100644 index 00000000000..4d39bbd0a9c --- /dev/null +++ b/Classification/include/CGAL/Classification/Feature/Height_below.h @@ -0,0 +1,142 @@ +// Copyright (c) 2012 INRIA Sophia-Antipolis (France). +// Copyright (c) 2017 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) : Florent Lafarge, Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_FEATURE_HEIGHT_BELOW_H +#define CGAL_CLASSIFICATION_FEATURE_HEIGHT_BELOW_H + +#include + +#include + +#include +#include +#include +#include + +namespace CGAL { + +namespace Classification { + +namespace Feature { + + /*! + \ingroup PkgClassificationFeatures + + %Feature based on local height distribution This feature computes + the distance between a point's height and the minimum height on + the local cell of the planimetric grid. + + Its default name is "height_below". + + \tparam GeomTraits model of \cgal Kernel. + \tparam PointRange model of `ConstRange`. Its iterator type + is `RandomAccessIterator` and its value type is the key type of + `PointMap`. + \tparam PointMap model of `ReadablePropertyMap` whose key + type is the value type of the iterator of `PointRange` and value type + is `GeomTraits::Point_3`. + + */ +template +class Height_below : public Feature_base +{ + typedef typename GeomTraits::Iso_cuboid_3 Iso_cuboid_3; + + typedef Image Image_float; + typedef Planimetric_grid Grid; + + const PointRange& input; + PointMap point_map; + const Grid& grid; + Image_float dtm; + std::vector values; + +public: + /*! + \brief Constructs the feature. + + \param input point range. + \param point_map property map to access the input points. + \param grid precomputed `Planimetric_grid`. + */ + Height_below (const PointRange& input, + PointMap point_map, + const Grid& grid) + : input(input), point_map(point_map), grid(grid) + { + this->set_name ("height_below"); + + dtm = Image_float(grid.width(),grid.height()); + + for (std::size_t j = 0; j < grid.height(); ++ j) + for (std::size_t i = 0; i < grid.width(); ++ i) + if (grid.has_points(i,j)) + { + float z_min = std::numeric_limits::max(); + + typename Grid::iterator end = grid.indices_end(i,j); + for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it) + { + float z = float(get(point_map, *(input.begin()+(*it))).z()); + z_min = (std::min(z_min, z)); + } + + dtm(i,j) = z_min; + } + + if (grid.width() * grid.height() > input.size()) + { + values.resize (input.size(), 0.f); + for (std::size_t i = 0; i < input.size(); ++ i) + { + std::size_t I = grid.x(i); + std::size_t J = grid.y(i); + values[i] = get (point_map, *(input.begin() + i)).z() - dtm(I,J); + } + dtm.free(); + } + + } + + /// \cond SKIP_IN_MANUAL + virtual float value (std::size_t pt_index) + { + if (values.empty()) + { + std::size_t I = grid.x(pt_index); + std::size_t J = grid.y(pt_index); + return get (point_map, *(input.begin() + pt_index)).z() - dtm(I,J); + } + + return values[pt_index]; + } + + /// \endcond +}; + +} // namespace Feature + +} // namespace Classification + + +} // namespace CGAL + +#endif // CGAL_CLASSIFICATION_FEATURE_HEIGHT_BELOW_H diff --git a/Classification/include/CGAL/Classification/Feature/Vertical_range.h b/Classification/include/CGAL/Classification/Feature/Vertical_range.h new file mode 100644 index 00000000000..b5e670e0b7c --- /dev/null +++ b/Classification/include/CGAL/Classification/Feature/Vertical_range.h @@ -0,0 +1,144 @@ +// Copyright (c) 2012 INRIA Sophia-Antipolis (France). +// Copyright (c) 2017 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) : Florent Lafarge, Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_FEATURE_VERTICAL_RANGE_H +#define CGAL_CLASSIFICATION_FEATURE_VERTICAL_RANGE_H + +#include + +#include + +#include +#include +#include +#include + +namespace CGAL { + +namespace Classification { + +namespace Feature { + + /*! + \ingroup PkgClassificationFeatures + + %Feature based on local height distribution This feature computes + the distance between the maximum and the minimum height on the + local cell of the planimetric grid. + + Its default name is "vertical_range". + + \tparam GeomTraits model of \cgal Kernel. + \tparam PointRange model of `ConstRange`. Its iterator type + is `RandomAccessIterator` and its value type is the key type of + `PointMap`. + \tparam PointMap model of `ReadablePropertyMap` whose key + type is the value type of the iterator of `PointRange` and value type + is `GeomTraits::Point_3`. + + */ +template +class Vertical_range : public Feature_base +{ + typedef typename GeomTraits::Iso_cuboid_3 Iso_cuboid_3; + + typedef Image Image_float; + typedef Planimetric_grid Grid; + + const PointRange& input; + PointMap point_map; + const Grid& grid; + Image_float dtm; + std::vector values; + +public: + /*! + \brief Constructs the feature. + + \param input point range. + \param point_map property map to access the input points. + \param grid precomputed `Planimetric_grid`. + */ + Vertical_range (const PointRange& input, + PointMap point_map, + const Grid& grid) + : input(input), point_map(point_map), grid(grid) + { + this->set_name ("vertical_range"); + + dtm = Image_float(grid.width(),grid.height()); + + for (std::size_t j = 0; j < grid.height(); ++ j) + for (std::size_t i = 0; i < grid.width(); ++ i) + if (grid.has_points(i,j)) + { + float z_max = -std::numeric_limits::max(); + float z_min = std::numeric_limits::max(); + + typename Grid::iterator end = grid.indices_end(i,j); + for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it) + { + float z = float(get(point_map, *(input.begin()+(*it))).z()); + z_max = (std::max(z_max, z)); + z_min = (std::min(z_min, z)); + } + + dtm(i,j) = z_max - z_min; + } + + if (grid.width() * grid.height() > input.size()) + { + values.resize (input.size(), 0.f); + for (std::size_t i = 0; i < input.size(); ++ i) + { + std::size_t I = grid.x(i); + std::size_t J = grid.y(i); + values[i] = dtm(I,J); + } + dtm.free(); + } + + } + + /// \cond SKIP_IN_MANUAL + virtual float value (std::size_t pt_index) + { + if (values.empty()) + { + std::size_t I = grid.x(pt_index); + std::size_t J = grid.y(pt_index); + return dtm(I,J); + } + + return values[pt_index]; + } + + /// \endcond +}; + +} // namespace Feature + +} // namespace Classification + + +} // namespace CGAL + +#endif // CGAL_CLASSIFICATION_FEATURE_VERTICAL_RANGE_H diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index 6892f3c6b02..00938c2c87a 100644 --- a/Classification/include/CGAL/Classification/Mesh_feature_generator.h +++ b/Classification/include/CGAL/Classification/Mesh_feature_generator.h @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include @@ -139,6 +142,12 @@ public: Distance_to_plane; typedef Classification::Feature::Elevation Elevation; + typedef Classification::Feature::Height_below + Height_below; + typedef Classification::Feature::Height_above + Height_above; + typedef Classification::Feature::Vertical_range + Vertical_range; typedef Classification::Feature::Vertical_dispersion Dispersion; typedef Classification::Feature::Verticality @@ -332,7 +341,10 @@ public: - `CGAL::Classification::Feature::Distance_to_plane` - `CGAL::Classification::Feature::Elevation` + - `CGAL::Classification::Feature::Height_above` + - `CGAL::Classification::Feature::Height_below` - `CGAL::Classification::Feature::Vertical_dispersion` + - `CGAL::Classification::Feature::Vertical_range` \param features the feature set where the features are instantiated. */ @@ -344,6 +356,12 @@ public: features.add_with_scale_id (i, m_range, m_point_map, grid(i), radius_neighbors(i)); for (std::size_t i = 0; i < m_scales.size(); ++ i) features.add_with_scale_id (i, m_range, m_point_map, grid(i), radius_dtm(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_range, m_point_map, grid(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_range, m_point_map, grid(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_range, m_point_map, grid(i)); } /// @} diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index adaf9eb5782..b017ebe427c 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include // Experimental feature, not used officially #ifdef CGAL_CLASSIFICATION_USE_GRADIENT_OF_FEATURE @@ -133,6 +136,12 @@ public: Distance_to_plane; typedef Classification::Feature::Elevation Elevation; + typedef Classification::Feature::Height_below + Height_below; + typedef Classification::Feature::Height_above + Height_above; + typedef Classification::Feature::Vertical_range + Vertical_range; typedef Classification::Feature::Vertical_dispersion Dispersion; typedef Classification::Feature::Verticality @@ -370,7 +379,10 @@ public: - `CGAL::Classification::Feature::Eigenvalue` with indices 0, 1 and 2 - `CGAL::Classification::Feature::Distance_to_plane` - `CGAL::Classification::Feature::Elevation` + - `CGAL::Classification::Feature::Height_above` + - `CGAL::Classification::Feature::Height_below` - `CGAL::Classification::Feature::Vertical_dispersion` + - `CGAL::Classification::Feature::Vertical_range` - The version of `CGAL::Classification::Feature::Verticality` based on eigenvalues \param features the feature set where the features are instantiated. @@ -386,6 +398,12 @@ public: features.add_with_scale_id (i, m_input, m_point_map, grid(i), radius_neighbors(i)); for (std::size_t i = 0; i < m_scales.size(); ++ i) features.add_with_scale_id (i, m_input, m_point_map, grid(i), radius_dtm(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_input, m_point_map, grid(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_input, m_point_map, grid(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + features.add_with_scale_id (i, m_input, m_point_map, grid(i)); for (std::size_t i = 0; i < m_scales.size(); ++ i) features.add_with_scale_id (i, m_input, eigen(i)); } From f558ce43be34fcee2abc862c5db9ad2c432a3a58 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 15:29:33 +0100 Subject: [PATCH 058/186] Fix erase() to keep the right order in the items list. --- Polyhedron/demo/Polyhedron/Scene.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 890940606fe..2e5b5e1e9ab 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -181,9 +181,9 @@ Scene::erase(Scene::Item_id index) item->deleteLater(); selected_item = -1; //re-creates the Scene_view - Q_FOREACH(Scene_item* item, m_entries) + Q_FOREACH(Item_id id, children) { - organize_items(item, invisibleRootItem(), 0); + organize_items(this->item(id), invisibleRootItem(), 0); } QStandardItemModel::beginResetModel(); Q_EMIT updated(); @@ -233,9 +233,9 @@ Scene::erase(QList indices) continue; if(item->parentGroup()) item->parentGroup()->removeChild(item); - children.removeAll(removed_item); - indexErased(removed_item); - m_entries.removeAll(item); + children.removeAll(removed_item); + indexErased(removed_item); + m_entries.removeAll(item); Q_EMIT itemAboutToBeDestroyed(item); item->aboutToBeDestroyed(); @@ -244,9 +244,9 @@ Scene::erase(QList indices) clear(); index_map.clear(); selected_item = -1; - Q_FOREACH(Scene_item* item, m_entries) + Q_FOREACH(Item_id id, children) { - organize_items(item, invisibleRootItem(), 0); + organize_items(item(id), invisibleRootItem(), 0); } QStandardItemModel::beginResetModel(); Q_EMIT updated(); @@ -1544,7 +1544,6 @@ void Scene::redraw_model() index_map.clear(); //fills the model Q_FOREACH(Item_id id, children) - { organize_items(m_entries[id], invisibleRootItem(), 0); } From ca4a568fa7432c110b53bc133b05baac12740627 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 16:29:53 +0100 Subject: [PATCH 059/186] Fix Remove Degenerated Faces --- .../include/CGAL/Polygon_mesh_processing/repair.h | 2 +- .../Plugins/PMP/Repair_polyhedron_plugin.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h index 0005edca6ac..dff16c5ea0b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h @@ -1510,7 +1510,7 @@ bool remove_degenerate_faces( TriangleMesh& tmesh, } template -std::size_t remove_degenerate_faces(TriangleMesh& tmesh) +bool remove_degenerate_faces(TriangleMesh& tmesh) { return remove_degenerate_faces(tmesh, CGAL::Polygon_mesh_processing::parameters::all_default()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index 548cc110464..217722074aa 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -147,13 +147,14 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_tr qobject_cast(scene->item(index)); if (poly_item) { - std::size_t nbv = + std::size_t nbv = num_faces(*poly_item->polyhedron()); CGAL::Polygon_mesh_processing::remove_degenerate_faces( *poly_item->polyhedron()); - messages->information(tr(" %1 degenerate faces have been removed.") - .arg(nbv)); - poly_item->invalidateOpenGLBuffers(); - Q_EMIT poly_item->itemChanged(); + poly_item->invalidateOpenGLBuffers(); + Q_EMIT poly_item->itemChanged(); + nbv -= num_faces(*poly_item->polyhedron()); + messages->information(tr(" %1 degenerate faces have been removed.") + .arg(nbv)); } } From 9c8eea5e2d9ced0d578ff4b416752af6f195d5ab Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 17:11:27 +0100 Subject: [PATCH 060/186] Reset colors when using a PMP operation that adds (or may add) a face (or more). --- .../demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp | 2 ++ Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp | 1 + Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp | 2 ++ .../demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp | 3 ++- .../Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp | 2 +- .../demo/Polyhedron/Scene_polyhedron_selection_item.cpp | 5 +++++ 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp index ce83faa6f5b..82fc1ba8f0f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp @@ -151,6 +151,8 @@ private: QApplication::setOverrideCursor(Qt::WaitCursor); try{ PMP::corefine(*item1->face_graph(), *item2->face_graph(), params::throw_on_self_intersection(true)); + item1->resetColors(); + item2->resetColors(); item1->invalidateOpenGLBuffers(); item2->invalidateOpenGLBuffers(); scene->itemChanged(item2); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp index 8c968b5e323..0b8502b305a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp @@ -448,6 +448,7 @@ private Q_SLOTS: Kernel::Vector_3(dir.x(), dir.y(), dir.z())); scene->erase(scene->item_id(oliver_queen)); oliver_queen = NULL; + target->resetColors(); target->invalidateOpenGLBuffers(); target->itemChanged(); target = NULL; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp index 98cf548d126..88b4bbf45ee 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp @@ -102,6 +102,7 @@ public Q_SLOTS: CGAL::Polygon_mesh_processing::fair(*selection_item->polyhedron(), selection_item->selected_vertices, CGAL::Polygon_mesh_processing::parameters::fairing_continuity(continuity)); + selection_item->polyhedron_item()->resetColors(); selection_item->changed_with_poly_item(); selection_item->invalidateOpenGLBuffers(); QApplication::restoreOverrideCursor(); @@ -127,6 +128,7 @@ public Q_SLOTS: for(std::vector::face_descriptor>::iterator it = new_facets.begin(); it != new_facets.end(); ++it) { selection_item->selected_facets.insert(*it); } + selection_item->polyhedron_item()->resetColors(); selection_item->changed_with_poly_item(); selection_item->invalidateOpenGLBuffers(); QApplication::restoreOverrideCursor(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp index 88523da2286..b10474ca27a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp @@ -365,6 +365,7 @@ protected: void change_poly_item_by_blocking(Scene_face_graph_item* poly_item, Scene_hole_visualizer* collection) { if(collection) collection->block_poly_item_changed = true; + poly_item->resetColors(); poly_item->invalidateOpenGLBuffers(); poly_item->redraw(); if(collection) collection->block_poly_item_changed = false; @@ -859,7 +860,7 @@ void Polyhedron_demo_hole_filling_plugin::on_Fill_from_selection_button() { last_active_item = edge_selection->polyhedron_item(); accept_reject_toggle(true); } - + edge_selection->polyhedron_item()->resetColors(); edge_selection->polyhedron_item()->invalidateOpenGLBuffers(); edge_selection->polyhedron_item()->itemChanged(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp index acf5bf53abe..0b1ca45e872 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp @@ -59,7 +59,7 @@ public Q_SLOTS: } if(!CGAL::Polygon_mesh_processing::triangulate_faces(*pMesh)) messages->warning(tr("Some facets could not be triangulated.")); - + sm_item->resetColors(); sm_item->invalidateOpenGLBuffers(); scene->itemChanged(sm_item); } // end of the loop on the selected items diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp index 775b3daf1eb..43bfcf7ecd2 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp @@ -1117,6 +1117,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::set(1)); d->tempInstructions("Face split.", "Select a facet (1/3)."); + polyhedron_item()->resetColors(); polyhedron_item()->invalidateOpenGLBuffers(); } } @@ -1342,6 +1343,7 @@ bool Scene_polyhedron_selection_item:: treat_selection(const std::setresetColors(); invalidateOpenGLBuffers(); polyhedron_item()->invalidateOpenGLBuffers(); d->tempInstructions("Face and vertex added.", @@ -1392,6 +1394,7 @@ bool Scene_polyhedron_selection_item:: treat_selection(const std::setresetColors(); invalidateOpenGLBuffers(); polyhedron_item()->invalidateOpenGLBuffers(); d->tempInstructions("Face added.", @@ -1490,6 +1493,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::set(0)); + poly_item->resetColors(); poly_item->invalidateOpenGLBuffers(); d->tempInstructions("Vertex splitted.", "Select the vertex you want splitted. (1/3)"); } @@ -1545,6 +1549,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::setresetColors(); poly_item->invalidateOpenGLBuffers(); } From 0ca82ed5e5cbc3d769c8532b06736dc786a21c05 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 17:13:07 +0100 Subject: [PATCH 061/186] Fix text at some places. --- Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_widget.ui | 2 +- Polyhedron/demo/Polyhedron/Preferences.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_widget.ui index 6cb5504b0c3..22d3ed83b49 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_widget.ui @@ -551,7 +551,7 @@ - Split edges + Split edge diff --git a/Polyhedron/demo/Polyhedron/Preferences.ui b/Polyhedron/demo/Polyhedron/Preferences.ui index 596e8cf2513..fec5b31c5a5 100644 --- a/Polyhedron/demo/Polyhedron/Preferences.ui +++ b/Polyhedron/demo/Polyhedron/Preferences.ui @@ -60,7 +60,7 @@ 0 0 278 - 432 + 499 @@ -311,7 +311,7 @@ - Tick plugins you don't want to load at start up + Tick plugins you want to load at start up From 45e95eb3f82db862dc47450de653f0c82fd09d1d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 7 Dec 2018 17:38:18 +0100 Subject: [PATCH 062/186] Fix segfault when reloading a selection item. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index b45aca5ac1b..9fb8afc7eed 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -968,6 +968,8 @@ void MainWindow::reloadItem() { Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) { item = scene->item(id); + if(!item)//secure items like selection items that get deleted when their "parent" item is reloaded. + continue; QString filename = item->property("source filename").toString(); QString loader_name = item->property("loader_name").toString(); if(filename.isEmpty() || loader_name.isEmpty()) { From e40cb2461fe03f63f78f405835732d4f0ce528b0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 10 Dec 2018 15:28:58 +0100 Subject: [PATCH 063/186] Filter for operations: also parse submenu names --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 88 +++++++++++++++-------- Polyhedron/demo/Polyhedron/MainWindow.h | 3 + 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 9fb8afc7eed..da16ed67801 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -402,45 +402,70 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren } //Recursive function that do a pass over a menu and its sub-menus(etc.) and hide them when they are empty -void filterMenuOperations(QMenu* menu, bool showFullMenu) +void filterMenuOperations(QMenu* menu, QString filter, bool keep_from_here) { - Q_FOREACH(QAction* action, menu->actions()) { - if(QMenu* menu = action->menu()) - { - filterMenuOperations(menu, showFullMenu); - action->setVisible(showFullMenu && !(menu->isEmpty())); + QList buffer; + Q_FOREACH(QAction* action, menu->actions()) + buffer.append(action); + while(!buffer.isEmpty()){ + + Q_FOREACH(QAction* action, buffer) { + if(QMenu* submenu = action->menu()) + { + bool keep = true; + if(!keep_from_here){ + keep = submenu->menuAction()->text().contains(filter, Qt::CaseInsensitive); + if(!keep) + { + Q_FOREACH(QAction* subaction, submenu->actions()) + { + submenu->removeAction(subaction); + buffer.append(subaction); + } + } + else + { + menu->addAction(submenu->menuAction()); + } + } + filterMenuOperations(submenu, filter, keep); + action->setVisible(!(submenu->isEmpty())); + } + else if(action->text().contains(filter, Qt::CaseInsensitive)){ + menu->addAction(action); + } + buffer.removeAll(action); } } - } void MainWindow::filterOperations() { - static QVector to_remove; - Q_FOREACH(QAction* action, to_remove) - ui->menuOperations->removeAction(action); - QString filter=operationSearchBar.text(); - if(!filter.isEmpty()) - Q_FOREACH(const PluginNamePair& p, plugins) { - Q_FOREACH(QAction* action, p.first->actions()) { - action->setVisible( p.first->applicable(action) - && action->text().contains(filter, Qt::CaseInsensitive)); - if(action->menu() != ui->menuOperations){ - ui->menuOperations->addAction(action); - to_remove.push_back(action); - } - } + //return actions to their true menu + Q_FOREACH(QMenu* menu, action_menu_map.values()) + { + Q_FOREACH(QAction* action, menu->actions()) + { + if(action != searchAction) + menu->removeAction(action); } - else{ - Q_FOREACH(const PluginNamePair& p, plugins) { - Q_FOREACH(QAction* action, p.first->actions()) { - action->setVisible( p.first->applicable(action) - && action->text().contains(filter, Qt::CaseInsensitive)); - } - } - // do a pass over all menus in Operations and their sub-menus(etc.) and hide them when they are empty } - filterMenuOperations(ui->menuOperations, filter.isEmpty()); + Q_FOREACH(QAction* action, action_menu_map.keys()) + { + action_menu_map[action]->addAction(action); + } + QString filter=operationSearchBar.text(); + Q_FOREACH(const PluginNamePair& p, plugins) { + Q_FOREACH(QAction* action, p.first->actions()) { + action->setVisible( p.first->applicable(action) + && (action->text().contains(filter, Qt::CaseInsensitive) + || action->property("subMenuName") + .toString().contains(filter, Qt::CaseInsensitive))); + } + } + // do a pass over all menus in Operations and their sub-menus(etc.) and hide them when they are empty + filterMenuOperations(ui->menuOperations, filter, false); + operationSearchBar.setFocus(); } #include @@ -549,12 +574,14 @@ void MainWindow::setMenus(QString name, QString parentName, QAction* a ) menu_map[parentName] = new QMenu(parentName, this); // add the submenu in the menu menu_map[parentName]->addMenu(menu_map[menuName]); + action_menu_map[menu_map[menuName]->menuAction()] = menu_map[parentName]; // only add the action in the last submenu if(slash_index==-1) { ui->menuOperations->removeAction(a); menu_map[menuName]->addAction(a); + action_menu_map[a] = menu_map[menuName]; } } @@ -765,6 +792,7 @@ bool MainWindow::initPlugin(QObject* obj) // If action does not belong to the menus, add it to "Operations" menu if(!childs.contains(action)) { ui->menuOperations->addAction(action); + action_menu_map[action] = ui->menuOperations; } // Show and enable menu item addAction(action); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 7a23e664b61..122263f0033 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -453,6 +453,9 @@ private: QMap >plugin_metadata_map; QMap ignored_map; const QStringList& accepted_keywords; + +private: + QMap action_menu_map; }; #endif // ifndef MAINWINDOW_H From 90f975b4d09771355a2460414eae591d100ac377 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 11 Dec 2018 11:04:41 +0100 Subject: [PATCH 064/186] Fix transparency total pass minimum to 4 --- Polyhedron/demo/Polyhedron/Preferences.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Preferences.ui b/Polyhedron/demo/Polyhedron/Preferences.ui index fec5b31c5a5..34613871e8d 100644 --- a/Polyhedron/demo/Polyhedron/Preferences.ui +++ b/Polyhedron/demo/Polyhedron/Preferences.ui @@ -118,6 +118,9 @@ Transparency Pass Number: + + 4 + 4 From adc36c5b38c98152751c000c6e4c7f56f13b1116 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 11 Dec 2018 11:23:28 +0100 Subject: [PATCH 065/186] Fix reload action behavior for multi selection. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index da16ed67801..191c75906fd 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1439,6 +1439,15 @@ void MainWindow::showSceneContextMenu(const QPoint& p) { QMap menu_actions; QVector slider_menus; bool has_stats = false; + bool has_reload = false; + Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) + { + if(!scene->item(id)->property("source filename").toString().isEmpty()) + { + has_reload = true; + break; + } + } Q_FOREACH(QAction* action, scene->item(main_index)->contextMenu()->actions()) { if(action->property("is_groupable").toBool()) @@ -1601,10 +1610,13 @@ void MainWindow::showSceneContextMenu(const QPoint& p) { connect(actionStatistics, SIGNAL(triggered()), this, SLOT(statisticsOnItem())); } + if(has_reload) + { QAction* reload = menu.addAction(tr("&Reload Item from File")); reload->setProperty("is_groupable", true); connect(reload, SIGNAL(triggered()), this, SLOT(reloadItem())); + } QAction* saveas = menu.addAction(tr("&Save as...")); connect(saveas, SIGNAL(triggered()), this, SLOT(on_actionSaveAs_triggered())); From 82dfb1f552cc7dbf96207f04fca4666dad450ee1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 11 Dec 2018 11:55:23 +0100 Subject: [PATCH 066/186] Restore classic selection mode on widget closure to stop highlighting --- Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index baf70e4deed..d973524109e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -138,6 +138,11 @@ public: dock_widget->setWindowTitle(tr( "Surface Mesh Selection" )); + connect(dock_widget, &QDockWidget::visibilityChanged, + this, [this](bool b){ + if(!b) + this->set_operation_mode(-1); + }); addDockWidget(dock_widget); From 3740f1eb4c0ab00a5bc0ed61ecc58a9b1890d252 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 11 Dec 2018 14:52:57 +0100 Subject: [PATCH 067/186] Stop the camera spinning before lookat() --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 191c75906fd..c14c61da403 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2244,6 +2244,8 @@ void MainWindow::on_actionLookAt_triggered() if( i == QDialog::Accepted && dialog.has_correct_coordinates() ) { + if(viewer->camera()->frame()->isSpinning()) + viewer->camera()->frame()->stopSpinning(); viewerShow((float)dialog.get_x()+viewer->offset().x, (float)dialog.get_y()+viewer->offset().y, (float)dialog.get_z()+viewer->offset().z); From 2940102bdcd4e601742d4e044aafab0942e521fa Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 11 Dec 2018 15:37:08 +0100 Subject: [PATCH 068/186] Fix picking with alpha Fix picking with alpha --- Polyhedron/demo/Polyhedron/Scene.cpp | 28 +++++++++++++++++++++++++++ Polyhedron/demo/Polyhedron/Viewer.cpp | 25 +++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 2e5b5e1e9ab..5de23995153 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -683,6 +683,34 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) transparent_items.push_back(id); } renderScene(children, viewer, picked_item_IDs, with_names, -1, false, NULL); + if(with_names) + { + //here we get the selected point, before erasing the depth buffer. We store it + //in a dynamic property as a QList. If there is some alpha, the + //depth buffer is altered, and the picking will return true even when it is + // performed in the background, when it should return false. To avoid that, + // we distinguish the case were there is no alpha, to let the viewer + //perform it, and the case where the pixel is not found. In the first case, + //we erase the property, in the latter we return an empty list. + //According ot that, in the viewer, either we perform the picking, either we do nothing. + if(has_alpha()) { + bool found = false; + CGAL::qglviewer::Vec point = viewer->camera()->pointUnderPixel(picked_pixel, found) - viewer->offset(); + if(found){ + QList picked_point; + picked_point <setProperty("picked_point", picked_point); + } + else{ + viewer->setProperty("picked_point", QList()); + } + } + else { + viewer->setProperty("picked_point", {}); + } + } if(!with_names && has_alpha()) { std::vector fbos; diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 05343dde80a..2e9fc83ac8c 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -708,12 +708,27 @@ void Viewer::drawWithNames() void Viewer::postSelection(const QPoint& pixel) { Q_EMIT selected(this->selectedName()); - bool found = false; - CGAL::qglviewer::Vec point = camera()->pointUnderPixel(pixel, found) - offset(); + CGAL::qglviewer::Vec point; + bool found = true; + if(property("picked_point").isValid()) { + if(!property("picked_point").toList().isEmpty()) + { + QList picked_point = property("picked_point").toList(); + point = CGAL::qglviewer::Vec (picked_point[0].toDouble(), + picked_point[1].toDouble(), + picked_point[2].toDouble()); + } + else{ + found = false; + } + } + else{ + point = camera()->pointUnderPixel(pixel, found) - offset(); + } if(found) { Q_EMIT selectedPoint(point.x, - point.y, - point.z); + point.y, + point.z); CGAL::qglviewer::Vec dir; CGAL::qglviewer::Vec orig; if(d->projection_is_ortho) @@ -726,7 +741,7 @@ void Viewer::postSelection(const QPoint& pixel) dir = point - orig; } Q_EMIT selectionRay(orig.x, orig.y, orig.z, - dir.x, dir.y, dir.z); + dir.x, dir.y, dir.z); } } bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame) From 34aa9a529040114a90f2fc4e1d0c6f1a051d1536 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 11 Dec 2018 16:32:04 +0100 Subject: [PATCH 069/186] Document tensorflow classifier + example --- .../doc/Classification/Classification.txt | 35 ++- .../doc/Classification/PackageDescription.txt | 3 +- .../doc/Classification/examples.txt | 1 + .../examples/Classification/CMakeLists.txt | 15 ++ .../example_tensorflow_neural_network.cpp | 164 ++++++++++++ .../TensorFlow_neural_network_classifier.h | 252 ++++++++---------- .../doc/Documentation/Installation.txt | 9 + .../Classification/Item_classification_base.h | 2 +- 8 files changed, 337 insertions(+), 144 deletions(-) create mode 100644 Classification/examples/Classification/example_tensorflow_neural_network.cpp diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index a0cd4c9650f..fbb70d858dd 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -196,9 +196,9 @@ Example of cluster classification mesh (left: input, middle: clusters computed f %Classification relies on a classifier: this classifier is an object that, from the set of values taken by the features at an input item, computes the probability that an input item belongs to one label or another. A model of the concept `CGAL::Classification::Classifier` must take the index of an input item and store the probability associated to each label in a vector. If a classifier returns the value 1 for a pair of label and input item, it means that this item belongs to this label with certainty; values close to 0 mean that this item is not likely to belong to this label. -\cgal provides three models for this concept, [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier) and [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier). +\cgal provides four models for this concept, [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier), [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier) and [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier). -To perform classification based on these classifiers, please refer to \ref Classification_classification_functions. +To perform classification based on four classifiers, please refer to \ref Classification_classification_functions. \subsection Classification_ETHZ_random_forest ETHZ Random Forest @@ -244,6 +244,31 @@ use this classifier. For more details about the algorithm, please refer to [the official documentation](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) of OpenCV. +\subsection Classification_TensorFlow_neural_network TensorFlow Neural Network + +\cgal provides [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier). + +It uses the C++ API of the \ref thirdpartyTensorFlow library. + +\warning This feature is still experimental: it may not be stable +and is likely to undergo substantial changes in future releases of +\cgal. Use at your own risk. + +The provided interface is a feature-based neural network: a set of +features is used as an input layer followed by a user-specified number +of hidden layers with a user-specified activation function. The output +layer is a softmax layer providing, for each label, the probability +that an input item belongs to it. + +This classifier cannot be set up by hand and requires a ground truth +training set. The training algorithm usually requires a higher number +of inliers than random forest. The quality of the results, so far, is +comparable to random forest. + +An [example](\ref Classification_example_tensorflow_neural_network) shows how to +use this classifier. For more details about the algorithm, please refer +to [the TensorFlow tutorials](https://www.tensorflow.org/tutorials/). + \subsection Classification_sowf Sum of Weighted Features This latest classifier defines the following attributes: @@ -488,6 +513,12 @@ The following example shows how to use the classifier [OpenCV_random_forest_clas \cgalExample{Classification/example_opencv_random_forest.cpp} +\subsection Classification_example_tensorflow_neural_network TensorFlow Neural Network + +The following example shows how to use the classifier [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier) using an input training set. + +\cgalExample{Classification/example_tensorflow_neural_network.cpp} + \subsection Classification_example_mesh Mesh Classification The following example: diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index c7fd807ce01..04c12aeb469 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -86,9 +86,10 @@ Data structures specialized to classify clusters. ## Classifiers ## -- `CGAL::Classification::Sum_of_weighted_features_classifier` - `CGAL::Classification::ETHZ_random_forest_classifier` - `CGAL::Classification::OpenCV_random_forest_classifier` +- `CGAL::Classification::TensorFlow_neural_network_classifier` +- `CGAL::Classification::Sum_of_weighted_features_classifier` ## Common Data Structures ## diff --git a/Classification/doc/Classification/examples.txt b/Classification/doc/Classification/examples.txt index f3598bb82a9..90fde632cce 100644 --- a/Classification/doc/Classification/examples.txt +++ b/Classification/doc/Classification/examples.txt @@ -4,6 +4,7 @@ \example Classification/example_generation_and_training.cpp \example Classification/example_ethz_random_forest.cpp \example Classification/example_opencv_random_forest.cpp +\example Classification/example_tensorflow_neural_network.cpp \example Classification/example_mesh_classification.cpp \example Classification/example_cluster_classification.cpp */ diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 392d1708e5c..7f5e28d1da2 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -108,6 +108,21 @@ else() message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") endif() +find_package(TensorFlow QUIET) +if (TensorFlow_FOUND) + message(STATUS "Found TensorFlow") + include_directories( ${TensorFlow_INCLUDE_DIR} ) + set(classification_linked_libraries ${classification_linked_libraries} + ${TensorFlow_LIBRARY}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_TENSORFLOW") + + set(targets ${targets} example_tensorflow_neural_network) +else() + message(STATUS "NOTICE: TensorFlow not found, Neural Network predicate for classification won't be available.") +endif() + + # Creating targets with correct libraries and flags foreach(target ${targets}) create_single_source_cgal_program( "${target}.cpp" CXX_FEATURES ${needed_cxx_features} ) diff --git a/Classification/examples/Classification/example_tensorflow_neural_network.cpp b/Classification/examples/Classification/example_tensorflow_neural_network.cpp new file mode 100644 index 00000000000..6763faf6da0 --- /dev/null +++ b/Classification/examples/Classification/example_tensorflow_neural_network.cpp @@ -0,0 +1,164 @@ +#if defined (_MSC_VER) && !defined (_WIN64) +#pragma warning(disable:4244) // boost::number_distance::distance() + // converts 64 to 32 bits integers +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Point_set_3 Point_set; +typedef Kernel::Iso_cuboid_3 Iso_cuboid_3; + +typedef Point_set::Point_map Pmap; +typedef Point_set::Property_map Imap; +typedef Point_set::Property_map UCmap; + +namespace Classification = CGAL::Classification; + +typedef Classification::Label_handle Label_handle; +typedef Classification::Feature_handle Feature_handle; +typedef Classification::Label_set Label_set; +typedef Classification::Feature_set Feature_set; + +typedef Classification::Point_set_feature_generator Feature_generator; + + +int main (int argc, char** argv) +{ + std::string filename = "data/b9_training.ply"; + + if (argc > 1) + filename = argv[1]; + + std::ifstream in (filename.c_str(), std::ios::binary); + Point_set pts; + + std::cerr << "Reading input" << std::endl; + in >> pts; + + Imap label_map; + bool lm_found = false; + boost::tie (label_map, lm_found) = pts.property_map ("label"); + if (!lm_found) + { + std::cerr << "Error: \"label\" property not found in input file." << std::endl; + return EXIT_FAILURE; + } + + std::vector ground_truth; + ground_truth.reserve (pts.size()); + std::copy (pts.range(label_map).begin(), pts.range(label_map).end(), + std::back_inserter (ground_truth)); + + Feature_set features; + + std::cerr << "Generating features" << std::endl; + CGAL::Real_timer t; + t.start(); + Feature_generator generator (pts, pts.point_map(), + 5); // using 5 scales + +#ifdef CGAL_LINKED_WITH_TBB + features.begin_parallel_additions(); +#endif + + generator.generate_point_based_features (features); + +#ifdef CGAL_LINKED_WITH_TBB + features.end_parallel_additions(); +#endif + + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + // Add types + Label_set labels; + Label_handle ground = labels.add ("ground"); + Label_handle vegetation = labels.add ("vegetation"); + Label_handle roof = labels.add ("roof"); + + std::vector label_indices(pts.size(), -1); + + std::cerr << "Using TensorFlow neural network Classifier" << std::endl; + Classification::TensorFlow_neural_network_classifier<> classifier (labels, features); + + std::cerr << "Training" << std::endl; + t.reset(); + t.start(); + classifier.train (ground_truth, + true, // restart from scratch + 100); // 100 iterations + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + t.reset(); + t.start(); + Classification::classify_with_graphcut + (pts, pts.point_map(), labels, classifier, + generator.neighborhood().k_neighbor_query(12), + 0.2f, 1, label_indices); + t.stop(); + + std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl; + + std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl; + Classification::Evaluation evaluation (labels, ground_truth, label_indices); + + for (std::size_t i = 0; i < labels.size(); ++ i) + { + std::cerr << " * " << labels[i]->name() << ": " + << evaluation.precision(labels[i]) << " ; " + << evaluation.recall(labels[i]) << " ; " + << evaluation.f1_score(labels[i]) << " ; " + << evaluation.intersection_over_union(labels[i]) << std::endl; + } + + std::cerr << "Accuracy = " << evaluation.accuracy() << std::endl + << "Mean F1 score = " << evaluation.mean_f1_score() << std::endl + << "Mean IoU = " << evaluation.mean_intersection_over_union() << std::endl; + + // Color point set according to class + UCmap red = pts.add_property_map("red", 0).first; + UCmap green = pts.add_property_map("green", 0).first; + UCmap blue = pts.add_property_map("blue", 0).first; + + for (std::size_t i = 0; i < label_indices.size(); ++ i) + { + label_map[i] = label_indices[i]; // update label map with computed classification + + Label_handle label = labels[label_indices[i]]; + + if (label == ground) + { + red[i] = 245; green[i] = 180; blue[i] = 0; + } + else if (label == vegetation) + { + red[i] = 0; green[i] = 255; blue[i] = 27; + } + else if (label == roof) + { + red[i] = 255; green[i] = 0; blue[i] = 170; + } + } + + // Write result + std::ofstream f ("classification.ply"); + f.precision(18); + f << pts; + + std::cerr << "All done" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index 307289bd7c2..11fa526dc27 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -41,7 +41,7 @@ #include -#define CGAL_NEURAL_NETWORKS_VERSION "0.1" +#define CGAL_NEURAL_NETWORK_VERSION "0.1" namespace CGAL { @@ -53,25 +53,36 @@ namespace TFops = tensorflow::ops; /*! \ingroup PkgClassificationClassifiers + \brief %Classifier based on the TensorFlow version of neural network. + + This class provides an interface to a feature-based neural network: + a set of features is used as an input layer followed by a + user-specified number of hidden layers with a user-specified + activation function. The output layer is a softmax layer providing, + for each label, the probability that an input item belongs to it. + + \warning This feature is still experimental: it may not be stable + and is likely to undergo substantial changes in future releases of + \cgal. Use at your own risk. + + \note This class requires the \ref thirdpartyTensorFlow library. + + \tparam ActivationFunction Chosen activation function for the hidden + layers. Relu is used as default. The following functions can be used + (please refer to the documentation of TensorFlow for more + information): + - `tensorflow::ops::Elu` + - `tensorflow::ops::Relu6` + - `tensorflow::ops::Relu` + - `tensorflow::ops::Selu` + - `tensorflow::ops::Sigmoid` + - `tensorflow::ops::Tanh` + \cgalModels `CGAL::Classification::Classifier` */ +template class TensorFlow_neural_network_classifier { -#define USE_RELU -#if defined(USE_TANH) - typedef TFops::Tanh Activation_function; -#elif defined(USE_RELU) - typedef TFops::Relu Activation_function; -#elif defined(USE_RELU6) - typedef TFops::Relu6 Activation_function; -#elif defined(USE_ELU) - typedef TFops::Elu Activation_function; -#elif defined(USE_SELU) - typedef TFops::Selu Activation_function; -#elif defined(USE_SIGMOID) - typedef TFops::Sigmoid Activation_function; -#endif - bool m_verbose; const Label_set& m_labels; @@ -83,27 +94,21 @@ class TensorFlow_neural_network_classifier TFops::Placeholder* m_ph_ft; TFops::Placeholder* m_ph_gt; -//#define USE_IOU -#ifdef USE_IOU TFops::ReduceMean* m_loss; -#else - TFops::ReduceMean* m_loss; -#endif std::vector > m_weights; std::vector > m_bias; float m_learning_rate; std::vector m_layers; -#define USE_ADAM -#ifdef USE_ADAM - std::vector m_gradient_descent; +#define CGAL_CLASSIFICATION_TENSORFLOW_USE_ADAM +#ifdef CGAL_CLASSIFICATION_TENSORFLOW_USE_ADAM + std::vector m_optimizer; #else - std::vector m_gradient_descent; + std::vector m_optimizer; #endif TF::ClientSession* m_session; - public: @@ -143,7 +148,7 @@ public: clear (m_root); m_weights.clear(); m_bias.clear(); - m_gradient_descent.clear(); + m_optimizer.clear(); m_layers.clear(); } @@ -208,12 +213,47 @@ public: /*! \brief Runs the training algorithm. + From the set of provided ground truth, this algorithm constructs a + neural network and applies an Adam optimizer to set up the weights + and bias that produce the most accurate result with respect to + this ground truth. + + \pre At least one ground truth item should be assigned to each + label. + + \param ground_truth vector of label indices. It should contain for + each input item, in the same order as the input set, the index of + the corresponding label in the `Label_set` provided in the + constructor. Input items that do not have a ground truth + information should be given the value `-1`. + + \param restart_from_scratch should be set to `false` if the user + wants to continue adjusting weights and bias based, and kept to + `true` if the neural network should be re-created from scratch + (discarding all previous training result). + + \param number_of_iterations number of times the optimizer is + called. + + \param learning_rate describes the rate at which the optimizer + changes the weights and bias. + + \param batch_size size of the random subset of inliers uses for + optimizing at each iteration. + + \param hidden_layers vector containing the consecutive sizes + (number of neurons) of the hidden layers of the network. If no + vector is given, the behavior used is the following: 2 hidden + layers are used. The first layer has as many neurons as the number + of features; the second layer has a number of neurons equal to the + average value between the number of features and the number of + labels. */ template void train (const LabelIndexRange& ground_truth, - bool restart_from_scratch = false, + bool restart_from_scratch = true, std::size_t number_of_iterations = 5000, - float learning_rate = 0.1, + float learning_rate = 0.01, std::size_t batch_size = 1000, const std::vector& hidden_layers = std::vector()) @@ -221,11 +261,7 @@ public: if (restart_from_scratch) clear(); -#define EQUAL_DISTRIBUTION - -#ifdef EQUAL_DISTRIBUTION std::vector > random_indices (m_labels.size()); -#endif std::vector indices; std::vector raw_gt; @@ -236,9 +272,7 @@ public: { indices.push_back (i); raw_gt.push_back (gc); -#ifdef EQUAL_DISTRIBUTION random_indices[std::size_t(gc)].push_back (indices.size() - 1); -#endif } } @@ -252,16 +286,9 @@ public: if (m_verbose) std::cerr << "III - TRAINING NEURAL NETWORK" << std::endl; -#ifndef EQUAL_DISTRIBUTION - batch_size = std::min (std::size_t(batch_size), indices.size()); - std::vector random_indices - (boost::make_counting_iterator(0), - boost::make_counting_iterator(indices.size())); -#endif - std::vector operations; - for (std::size_t i = 0; i < m_gradient_descent.size(); ++ i) - operations.push_back (m_gradient_descent[i]); + for (std::size_t i = 0; i < m_optimizer.size(); ++ i) + operations.push_back (m_optimizer[i]); operations.push_back (m_layers.back()); std::vector outputs; @@ -273,7 +300,6 @@ public: for (std::size_t i = 0; i < number_of_iterations; ++ i) { -#ifdef EQUAL_DISTRIBUTION std::size_t total_batch_size = 0; for (std::size_t j = 0; j < random_indices.size(); ++ j) { @@ -327,40 +353,9 @@ public: ++ current_i; } } -#else - random_unique (random_indices.begin(), random_indices.end(), batch_size); - - TF::Tensor ft - (TF::DataTypeToEnum::v(), - TF::TensorShape {(long long)(batch_size), (long long)(m_features.size())}); - TF::Tensor gt - (TF::DataTypeToEnum::v(), - TF::TensorShape {(long long)(batch_size), (long long)(m_labels.size())}); - - float* ft_data = ft.flat().data(); - float* gt_data = gt.flat().data(); - - // Fill input tensors - for (std::size_t i = 0; i < batch_size; ++ i) - { - std::size_t idx = indices[random_indices[i]]; - int g = raw_gt[random_indices[i]]; - - for (std::size_t f = 0; f < m_features.size(); ++ f) - ft_data[i * m_features.size() + f] - = (m_features[f]->value(idx) - m_feature_means[f]) / m_feature_sd[f]; - - for (std::size_t l = 0; l < m_labels.size(); ++ l) - if (std::size_t(g) == l) - gt_data[i * m_labels.size() + l] = 1.f; - else - gt_data[i * m_labels.size() + l] = 0.f; - } -#endif TF_CHECK_OK (m_session->Run ({{*m_ph_ft, ft}, {*m_ph_gt, gt}}, {*m_loss}, &outputs)); -// log << outputs[0].scalar() << std::endl; if ((i+1) % (number_of_iterations / 20) == 0) { if (m_verbose) std::cerr << " * Step " << i+1 << "/" << number_of_iterations << ": loss = " @@ -461,10 +456,14 @@ public: \brief Saves the current configuration in the stream `output`. This allows to easily save and recover a specific classification - configuration. + configuration, that is to say: - The output file is written in an GZIP container that is readable - by the `load_configuration()` method. + - The statistics of features (mean and standard deviation) + - The number of hiddens layers and their respectives sizes + - The weights and bias of the neurons + + The output file is written in an XML format that is readable by + the `load_configuration()` method. */ void save_configuration (std::ostream& output) { @@ -472,7 +471,7 @@ public: { boost::property_tree::ptree ptr; - ptr.put("classifier_version", CGAL_NEURAL_NETWORKS_VERSION); + ptr.put("classifier_version", CGAL_NEURAL_NETWORK_VERSION); ptr.put("number_of_features", m_features.size()); ptr.put("number_of_labels", m_labels.size()); ptr.put("number_of_hidden_layers", m_layers.size() - 1); @@ -524,8 +523,6 @@ public: tree.add_child("classification.layers.layer", ptr); } - - // Write property tree to XML file boost::property_tree::write_xml(output, tree, @@ -539,7 +536,7 @@ public: /*! \brief Loads a configuration from the stream `input`. - The input file should be a GZIP container written by the + The input file should be in the XML format written by the `save_configuration()` method. The feature set of the classifier should contain the exact same features in the exact same order as the ones present when the file was generated using @@ -555,10 +552,10 @@ public: boost::property_tree::read_xml(input, tree); std::string version = tree.get("classification.metadata.classifier_version"); - if (version != CGAL_NEURAL_NETWORKS_VERSION) + if (version != CGAL_NEURAL_NETWORK_VERSION) { if (verbose) - std::cerr << "Error: CGAL Neural Network version mismatch " << version << "/" << CGAL_NEURAL_NETWORKS_VERSION << std::endl; + std::cerr << "Error: CGAL Neural Network version mismatch " << version << "/" << CGAL_NEURAL_NETWORK_VERSION << std::endl; return false; } std::size_t nb_features = std::size_t(tree.get("classification.metadata.number_of_features")); @@ -673,7 +670,6 @@ public: return out; } - private: template @@ -752,20 +748,20 @@ private: if (m_weights.empty()) { -#ifdef USE_TANH // Weights initialized by Xavier method - assign_weights.push_back (TFops::Assign (*m_root, weights.back(), - TFops::Mul (*m_root, TFops::Const(*m_root, - std::sqrt (1.f / (float)(size_from))), - TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); -#elif defined(USE_RELU) || defined(USE_RELU6) // Weights initialized by He method - assign_weights.push_back (TFops::Assign (*m_root, weights.back(), - TFops::Mul (*m_root, TFops::Const(*m_root, - std::sqrt (2.f / (float)(size_from))), - TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); -#else // Default: weights truncated normal - assign_weights.push_back (TFops::Assign (*m_root, weights.back(), - TFops::TruncatedNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT))); -#endif + if (boost::is_same::value) // Weights initialized by Xavier method + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::Mul (*m_root, TFops::Const(*m_root, + std::sqrt (1.f / (float)(size_from))), + TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); + else if (boost::is_same::value || + boost::is_same::value) // Weights initialized by He method + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::Mul (*m_root, TFops::Const(*m_root, + std::sqrt (2.f / (float)(size_from))), + TFops::RandomNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT)))); + else // Default: weights truncated normal + assign_weights.push_back (TFops::Assign (*m_root, weights.back(), + TFops::TruncatedNormal (*m_root, { size_from, size_to}, TF::DT_FLOAT))); } else { @@ -805,17 +801,17 @@ private: for (std::size_t i = 0; i < weights.size(); ++ i) { if (i == 0) - m_layers.push_back (Activation_function (*m_root, TFops::Add - (*m_root, TFops::MatMul (*m_root, *m_ph_ft, weights[0]), - bias[0]))); + m_layers.push_back (ActivationFunction (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, *m_ph_ft, weights[0]), + bias[0]))); else if (i == weights.size() - 1) m_layers.push_back (TFops::Softmax (*m_root, TFops::Add (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), bias[i]))); else - m_layers.push_back (Activation_function (*m_root, TFops::Add - (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), - bias[i]))); + m_layers.push_back (ActivationFunction (*m_root, TFops::Add + (*m_root, TFops::MatMul (*m_root, m_layers.back(), weights[i]), + bias[i]))); } if (!m_root->status().ok()) @@ -827,27 +823,6 @@ private: if (m_verbose) std::cerr << " 4) Setting up loss calculation" << std::endl; // loss calculation based on cross-entropy - -// TFops::Log log_ypred = TFops::Log (*m_root, m_layers.back()); - -#ifdef USE_IOU - - TFops::Mul ygt_times_ypred = TFops::Mul (*m_root, *m_ph_gt, m_layers.back()); - TFops::ReduceSum intersection = TFops::ReduceSum(*m_root, ygt_times_ypred, {1}); - - TFops::Add ygt_plus_ypred = TFops::Add (*m_root, *m_ph_gt, m_layers.back()); - TFops::Mul ygt_times_ypred_2 = TFops::Mul (*m_root, *m_ph_gt, m_layers.back()); - TFops::Sub sum_minus_product = TFops::Sub (*m_root, ygt_plus_ypred, ygt_times_ypred_2); - TFops::ReduceSum my_union = TFops::ReduceSum(*m_root, sum_minus_product, {1}); - - TFops::Div IoU = TFops::Div(*m_root, intersection, my_union); - TFops::Sub one_minus_IoU = TFops::Sub (*m_root, TFops::Const(*m_root, 1.f), IoU); - m_loss = new TFops::ReduceMean (*m_root, one_minus_IoU, {0}); - - // TFops::ReduceMean mean_IoU = TFops::ReduceMean (*m_root, IoU, {0}); - // m_loss = new TFops::Sub (*m_root, TFops::Const(*m_root, 1.f), mean_IoU); - -#else TFops::Maximum truncated_ypred = TFops::Maximum (*m_root, TFops::Const(*m_root, 0.0001f), m_layers.back()); TFops::Log log_ypred = TFops::Log (*m_root, truncated_ypred); TFops::Mul ygt_times_log_ypred = TFops::Mul (*m_root, *m_ph_gt, log_ypred); @@ -855,7 +830,6 @@ private: TFops::Mul minus_sum_ygt_times_log_ypred = TFops::Mul (*m_root, TFops::Const(*m_root, -1.f), sum_ygt_times_log_ypred); m_loss = new TFops::ReduceMean (*m_root, minus_sum_ygt_times_log_ypred, {0}); -#endif if (!m_root->status().ok()) { @@ -885,7 +859,7 @@ private: std::vector assigners; -#ifdef USE_ADAM +#ifdef CGAL_CLASSIFICATION_TENSORFLOW_USE_ADAM for (std::size_t i = 0; i < weights.size(); ++ i) { long long size_from = 0; @@ -926,7 +900,7 @@ private: init_v_data[ss * size_from + s] = 0.f; assigners.push_back (TFops::Assign (*m_root, v, init_v)); - m_gradient_descent.push_back (TFops::ApplyAdam + m_optimizer.push_back (TFops::ApplyAdam (*m_root, weights[i], m, @@ -969,7 +943,7 @@ private: init_v_data[s] = 0.f; assigners.push_back (TFops::Assign (*m_root, v, init_v)); - m_gradient_descent.push_back (TFops::ApplyAdam + m_optimizer.push_back (TFops::ApplyAdam (*m_root, bias[i], m, @@ -985,11 +959,11 @@ private: #else for (std::size_t i = 0; i < weights.size(); ++ i) - m_gradient_descent.push_back (TFops::ApplyGradientDescent + m_optimizer.push_back (TFops::ApplyGradientDescent (*m_root, weights[i], TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), {gradients[i]})); for (std::size_t i = 0; i < bias.size(); ++ i) - m_gradient_descent.push_back (TFops::ApplyGradientDescent + m_optimizer.push_back (TFops::ApplyGradientDescent (*m_root, bias[i], TFops::Cast(*m_root, m_learning_rate, TF::DT_FLOAT), {gradients[weights.size() + i]})); #endif @@ -1003,11 +977,6 @@ private: TF::SessionOptions options = TF::SessionOptions(); - // options.config.mutable_gpu_options()->set_visible_device_list("0"); - // options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.3); - // options.config.mutable_gpu_options()->set_operation_timeout_in_ms(15000); - -// options.config.mutable_gpu_options()->set_visible_device_list(""); options.config.mutable_gpu_options()->set_allow_growth(true); options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.8); options.config.mutable_gpu_options()->set_force_gpu_compatible(true); @@ -1033,11 +1002,11 @@ private: return; } } - }; -#if 1 +/// \cond SKIP_IN_MANUAL +#ifdef CGAL_CLASSIFICATION_TENSORFLOW_ENABLE_GPU_SPECIALIZATION // Specialization to use GPU parallelization template `http://opencv.org/`. +\subsection thirdpartyTensorFlow TensorFlow + +\sc{TensorFlow} is a library designed for machine learning and deep learning. + +In \cgal, the C++ API of \sc{TensorFlow} is used by the \ref PkgClassificationRef +package for neural network. + +The \sc{TensorFlow} web site is `https://www.tensorflow.org/`. + \subsection thirdpartyMETIS METIS \sc{METIS} is a library developed by the Karypis Lab diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 3fdce8b2053..4f63a9957b2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -32,7 +32,7 @@ public: typedef CGAL::Classification::OpenCV_random_forest_classifier Random_forest; #endif #ifdef CGAL_LINKED_WITH_TENSORFLOW - typedef CGAL::Classification::TensorFlow_neural_network_classifier Neural_network; + typedef CGAL::Classification::TensorFlow_neural_network_classifier<> Neural_network; #endif public: From ae169b9f9a4ab9efbdea9f1f1d09296a33b6e8e5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 08:55:49 +0100 Subject: [PATCH 070/186] Update user manual --- Classification/doc/Classification/Classification.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index fbb70d858dd..e6d913579d7 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -87,7 +87,10 @@ The following code snippet shows how to instantiate such data structures from an - [Distance_to_plane](@ref CGAL::Classification::Feature::Distance_to_plane) measures how far away a point is from a locally estimated plane; - [Eigenvalue](@ref CGAL::Classification::Feature::Eigenvalue) measures one of the three local eigenvalues; - [Elevation](@ref CGAL::Classification::Feature::Elevation) computes the local distance to an estimation of the ground; +- [Height_above](@ref CGAL::Classification::Feature::Elevation) computes the distance between the local highest point and the point; +- [Height_below](@ref CGAL::Classification::Feature::Elevation) computes the distance between the point and local lowest point; - [Vertical_dispersion](@ref CGAL::Classification::Feature::Vertical_dispersion) computes how noisy the point set is on a local Z-cylinder; +- [Vertical_range](@ref CGAL::Classification::Feature::Elevation) computes the distance between the local highest and lowest points; - [Verticality](@ref CGAL::Classification::Feature::Verticality) compares the local normal vector to the vertical vector. These features are designed for point sets but can easily be used with surface meshes as well (see \ref Classification_meshes). For more details about how these different features can help to identify one label or the other, please refer to their associated reference manual pages. @@ -108,6 +111,8 @@ Multiple scales that are sequentially larger can be used to increase the quality Note that using this class in order to generate features is not mandatory, as features and data structures can all be handled by hand. It is mainly provided to make the specific case of point sets simpler to handle. Users can still add their own features within their feature set. +Some data structure instantiated by the generator will be used by feature: for this reason, the generator should be instantiated _within the same scope_ as the feature set and should not be deleted before the feature set. + The following snippet shows how to use the point set feature generator: \snippet Classification/example_generation_and_training.cpp Generator @@ -548,7 +553,7 @@ The following example: \section Classification_history History -This package is based on a research code by [Florent Lafarge](https://www-sop.inria.fr/members/Florent.Lafarge/) that was generalized, extended and packaged by [Simon Giraudot](http://geometryfactory.com/who-we-are/) in \cgal 4.12. %Classification of surface meshes and of clusters were introduced in \cgal 4.13. +This package is based on a research code by [Florent Lafarge](https://www-sop.inria.fr/members/Florent.Lafarge/) that was generalized, extended and packaged by [Simon Giraudot](http://geometryfactory.com/who-we-are/) in \cgal 4.12. %Classification of surface meshes and of clusters were introduced in \cgal 4.13. The Neural Network classifier was introduced in \cgal 4.14. From eeed92c94debd82d2db4e386213390ca8766a65a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 09:16:57 +0100 Subject: [PATCH 071/186] Fix usage of concept Range (no resize() method, size should be taken care of by the user --- .../examples/Classification/example_classification.cpp | 4 ++-- .../examples/Classification/example_feature.cpp | 2 +- Classification/include/CGAL/Classification/classify.h | 9 --------- .../test/Classification/test_classification_io.cpp | 6 +++--- .../Plugins/Classification/Cluster_classification.cpp | 3 +++ .../Classification/Point_set_item_classification.cpp | 5 ++++- .../Classification/Surface_mesh_item_classification.cpp | 3 +++ 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Classification/examples/Classification/example_classification.cpp b/Classification/examples/Classification/example_classification.cpp index 4ed9caccabd..665fb17f064 100644 --- a/Classification/examples/Classification/example_classification.cpp +++ b/Classification/examples/Classification/example_classification.cpp @@ -146,7 +146,7 @@ int main (int argc, char** argv) /////////////////////////////////////////////////////////////////// //! [Classify] - std::vector label_indices; + std::vector label_indices (pts.size(), -1); CGAL::Real_timer t; t.start(); @@ -200,7 +200,7 @@ int main (int argc, char** argv) { f << pts[i] << " "; - Label_handle label = labels[label_indices[i]]; + Label_handle label = labels[std::size_t(label_indices[i])]; if (label == ground) f << "245 180 0" << std::endl; else if (label == vegetation) diff --git a/Classification/examples/Classification/example_feature.cpp b/Classification/examples/Classification/example_feature.cpp index d1ce94e8fee..4cce763be1a 100644 --- a/Classification/examples/Classification/example_feature.cpp +++ b/Classification/examples/Classification/example_feature.cpp @@ -114,7 +114,7 @@ int main (int argc, char** argv) classifier.set_effect (b, my_feature, Classifier::PENALIZING); std::cerr << "Classifying" << std::endl; - std::vector label_indices(pts.size(), -1); + std::vector label_indices(pts.size(), -1); Classification::classify_with_graphcut (pts, Pmap(), labels, classifier, neighborhood.k_neighbor_query(12), diff --git a/Classification/include/CGAL/Classification/classify.h b/Classification/include/CGAL/Classification/classify.h index 59bd19cfe2f..492d1855237 100644 --- a/Classification/include/CGAL/Classification/classify.h +++ b/Classification/include/CGAL/Classification/classify.h @@ -370,8 +370,6 @@ namespace internal { const Classifier& classifier, LabelIndexRange& output) { - output.resize(input.size()); - internal::Classify_functor f (labels, classifier, output); @@ -404,11 +402,6 @@ namespace internal { LabelIndexRange& output, ProbabilitiesRanges& probabilities) { - output.resize (input.size()); - probabilities.resize (labels.size()); - for (std::size_t i = 0; i < probabilities.size(); ++ i) - probabilities[i].resize (input.size()); - internal::Classify_detailed_output_functor f (labels, classifier, output, probabilities); @@ -473,8 +466,6 @@ namespace internal { const NeighborQuery& neighbor_query, LabelIndexRange& output) { - output.resize(input.size()); - std::vector > values (labels.size(), std::vector (input.size(), -1.)); internal::Classify_functor_local_smoothing_preprocessing diff --git a/Classification/test/Classification/test_classification_io.cpp b/Classification/test/Classification/test_classification_io.cpp index bb1d770e47c..a9c9173d7b6 100644 --- a/Classification/test/Classification/test_classification_io.cpp +++ b/Classification/test/Classification/test_classification_io.cpp @@ -89,9 +89,9 @@ int main (int, char**) Classifier classifier3 (classifier, features); - std::vector label_indices; - std::vector label_indices_2; - std::vector label_indices_3; + std::vector label_indices (points.size()); + std::vector label_indices_2 (points.size()); + std::vector label_indices_3 (points.size()); Classification::classify (points, labels, classifier, label_indices); Classification::classify (points, labels, classifier2, label_indices_2); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index b9e01c89204..6dce115eb68 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -796,6 +796,9 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d reset_indices(); m_label_probabilities.clear(); + m_label_probabilities.resize (m_labels.size()); + for (std::size_t i = 0; i < m_label_probabilities.size(); ++ i) + m_label_probabilities[i].resize (m_clusters.size(), -1); std::vector nb_label (m_labels.size(), 0); std::size_t nb_total = 0; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index ee308ac5e11..6273425fb8e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -707,7 +707,10 @@ void Point_set_item_classification::train(int classifier, const QMultipleInputDi reset_indices(); m_label_probabilities.clear(); - + m_label_probabilities.resize (m_labels.size()); + for (std::size_t i = 0; i < m_label_probabilities.size(); ++ i) + m_label_probabilities[i].resize (m_points->point_set()->size(), -1); + std::vector training (m_points->point_set()->size(), -1); std::vector indices (m_points->point_set()->size(), -1); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index e04bc8330c1..3f6fdcec51f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -252,6 +252,9 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp } m_label_probabilities.clear(); + m_label_probabilities.resize (m_labels.size()); + for (std::size_t i = 0; i < m_label_probabilities.size(); ++ i) + m_label_probabilities[i].resize (num_faces(*(m_mesh->polyhedron()))); std::vector training (num_faces(*(m_mesh->polyhedron())), std::size_t(-1)); std::vector indices (num_faces(*(m_mesh->polyhedron())), std::size_t(-1)); From 4e1212b07d1f196e5f8fd19e0e0a21609e7c31ef Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 09:32:23 +0100 Subject: [PATCH 072/186] Unify default radius parameters values --- .../include/CGAL/Classification/Feature/Echo_scatter.h | 2 ++ .../include/CGAL/Classification/Feature/Elevation.h | 2 +- .../include/CGAL/Classification/Mesh_feature_generator.h | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Classification/include/CGAL/Classification/Feature/Echo_scatter.h b/Classification/include/CGAL/Classification/Feature/Echo_scatter.h index 85e3b9942b4..dd90d7b86f8 100644 --- a/Classification/include/CGAL/Classification/Feature/Echo_scatter.h +++ b/Classification/include/CGAL/Classification/Feature/Echo_scatter.h @@ -85,6 +85,8 @@ public: : grid (grid) { this->set_name ("echo_scatter"); + if (radius_neighbors < 0.) + radius_neighbors = 3.f * grid.resolution(); if (grid.width() * grid.height() > input.size()) echo_scatter.resize(input.size(), compressed_float(0)); diff --git a/Classification/include/CGAL/Classification/Feature/Elevation.h b/Classification/include/CGAL/Classification/Feature/Elevation.h index 14750ba905f..1af70565840 100644 --- a/Classification/include/CGAL/Classification/Feature/Elevation.h +++ b/Classification/include/CGAL/Classification/Feature/Elevation.h @@ -91,7 +91,7 @@ public: { this->set_name ("elevation"); if (radius_dtm < 0.) - radius_dtm = 100.f * grid.resolution(); + radius_dtm = 10.f * grid.resolution(); //DEM Image_float dem(grid.width(),grid.height()); diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index 00938c2c87a..d15b139cb3e 100644 --- a/Classification/include/CGAL/Classification/Mesh_feature_generator.h +++ b/Classification/include/CGAL/Classification/Mesh_feature_generator.h @@ -226,8 +226,8 @@ private: } float grid_resolution() const { return voxel_size; } - float radius_neighbors() const { return voxel_size * 5; } - float radius_dtm() const { return voxel_size * 100; } + float radius_neighbors() const { return voxel_size * 3; } + float radius_dtm() const { return voxel_size * 10; } }; From 35511bae8e5706b21bbd2403cfe0c5f46a2eed40 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 09:41:05 +0100 Subject: [PATCH 073/186] Document changes in internal ETHZ random forest library --- .../auxiliary/random-forest/common-libraries.hpp | 10 ++++++++++ .../internal/auxiliary/random-forest/forest.hpp | 6 ++++++ .../internal/auxiliary/random-forest/node-gini.hpp | 7 +++++-- .../internal/auxiliary/random-forest/node.hpp | 1 + .../internal/auxiliary/random-forest/tree.hpp | 1 + 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 8e951287ba4..3e2099844a2 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -27,6 +27,16 @@ // Modifications from original library: // * changed inclusion protection tag // * moved to namespace CGAL::internal:: +// * init_feature_class_data() does not resize anymore (it's done +// later directly in the splitter). WARNING: all splitters other +// than the default won't be working correctly (but experimentally +// they are less good and we don't use them - we keep them just in +// case) +// * sample reduction is now 36.8% (to account for the correction of +// the randomization of the input which used to implicitly ignore +// this proportion of items) +// * map_points() in axis aligned splitter now only uses a subset of +// the points for evaluation (for timing optimization= #ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H #define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index 05b57c765a4..6dd83485e76 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -29,6 +29,12 @@ // * moved to namespace CGAL::internal:: // * add parameter "reset_trees" to train() to be able to construct // forest with several iterations +// * training algorithm has been parallelized with Intel TBB +// * remove the unused feature "register_obb" +// * add option to not count labels (if it's know before) +// * fix the randomization of input (which was implicitly losing +// samples) +// * add method to get feature usage #ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_FOREST_H #define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_FOREST_H diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp index d9c62d4add4..2b42b35843b 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp @@ -28,6 +28,11 @@ // * changed inclusion protection tag // * moved to namespace CGAL::internal:: +// * improve sorting algorithm by only comparing the first of pair +// (second is useless) + + + #ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_NODE_GINI_H #define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_NODE_GINI_H #include "node.hpp" @@ -98,7 +103,6 @@ public: continue; // weighted average double gini = n_l - gini_square_term(classes_l) * 1.0 / n_l + n_r - gini_square_term(classes_r) * 1.0 / n_r; - if (gini < best_loss) { best_loss = gini; double fraction = fraction_dist(gen); @@ -113,7 +117,6 @@ public: { ar & boost::serialization::make_nvp("base", boost::serialization::base_object< Node< NodeGini, ForestParams, Splitter > >(*this)); } - }; } diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index f448ba98064..6d5ef03bafc 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -30,6 +30,7 @@ // * fix computation of node_dist[label] so that results are always <= 1.0 // * change serialization functions to avoid a bug with boost and some // compilers (that leads to dereferencing a null pointer) +// * add a method to get feature usage #ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFORESTS_NODE_H #define CGAL_INTERNAL_LIBLEARNING_RANDOMFORESTS_NODE_H diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp index 476ebf56f80..08ddb45aa5b 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp @@ -27,6 +27,7 @@ // Modifications from original library: // * changed inclusion protection tag // * moved to namespace CGAL::internal:: +// * add a method to get feature usage #ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_TREE_H #define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_TREE_H From 3b0220482a1abfbf30bdfee3868abe393af442ca Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 10:06:33 +0100 Subject: [PATCH 074/186] Update CHANGES.md --- Installation/CHANGES.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 672d71541a4..e2922f426f7 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -32,6 +32,20 @@ Release date: March 2019 - Added the class `CGAL::Rigid_triangle_mesh_collision_detection` to detect intersections between meshes and volumes undergoing affine transformations. +### Classification + +- Added a new experimental classifier + `TensorFlow_neural_network_classifier`. + +- The training algorithm of `ETHZ_random_forest_classifier` was + parallelized. + +- Added a constructor to copy a `ETHZ_random_forest_classifier` + using a different data set as input. + +- Added 3 new geometric features, `Height_above`, `Height_below` and + `Vertical_range`. + ### 3D Fast Intersection and Distance Computation - The primitives `AABB_face_graph_triangle_primitive` and From 30964250447aebe2ddec3d03d79986be9bdebd1a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 10:06:57 +0100 Subject: [PATCH 075/186] Add some indication on what to compile in TensorFlow (it's not well documented) --- Documentation/doc/Documentation/Installation.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index 0b533777b35..59923355807 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -597,8 +597,15 @@ The \sc{OpenCV} web site is `http://opencv.org/``https://www.tensorflow.org/`. From a731e942325f5ec471a5fba6eb73233ad1509775 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 12 Dec 2018 10:41:19 +0100 Subject: [PATCH 076/186] Fix currentIndex when selecting items in the sceneView. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 8 ++++++-- Polyhedron/demo/Polyhedron/Scene.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index c14c61da403..ddc8cf0668d 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1237,11 +1237,13 @@ void MainWindow::selectSceneItem(int i) } else { QItemSelection s = - proxyModel->mapSelectionFromSource(scene->createSelection(i)); - + proxyModel->mapSelectionFromSource(scene->createSelection(i)); + QModelIndex mi = proxyModel->mapFromSource(scene->getModelIndexFromId(i).first()); + sceneView->setCurrentIndex(mi); sceneView->selectionModel()->select(s, QItemSelectionModel::ClearAndSelect); sceneView->scrollTo(s.indexes().first()); + sceneView->setCurrentIndex(sceneView->selectionModel()->selectedIndexes().first()); } } @@ -1256,6 +1258,8 @@ void MainWindow::selectSceneItems(QList is) QItemSelection s = proxyModel->mapSelectionFromSource(scene->createSelection(is)); + QModelIndex i = proxyModel->mapFromSource(scene->getModelIndexFromId(is.first()).first()); + sceneView->setCurrentIndex(i); sceneView->selectionModel()->select(s, QItemSelectionModel::ClearAndSelect); sceneView->scrollTo(s.indexes().first()); diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 5de23995153..568509ef22a 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -1216,8 +1216,9 @@ void Scene::moveRowUp() } } } - if(!to_select.isEmpty()) + if(!to_select.isEmpty()){ selectionChanged(to_select); + } } void Scene::moveRowDown() { From d8ae81c69e4bf282507f2c0a84d8bb1777e4f2de Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 12 Dec 2018 11:06:51 +0100 Subject: [PATCH 077/186] Make classification plugin depend on selection plugins --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 2 +- Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 436e3727108..92f4ee95bd6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -51,7 +51,7 @@ if(EIGEN3_FOUND) endif() target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp ${classification_linked_libraries}) + scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp point_set_selection_plugin selection_plugin ${classification_linked_libraries}) target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else() message(STATUS "NOTICE: Boost Serialization or IO Streams or ZLIB not found. Classification plugin won't be available.") diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 2c3571b54c1..92baf93a289 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -36,7 +36,7 @@ endif() 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}) + add_library(point_set_selection_plugin SHARED Point_set_selection_plugin.cpp ${point_set_selectionUI_FILES}) target_link_libraries(point_set_selection_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_edit_box_item) qt5_wrap_ui(point_set_shape_detectionUI_FILES Point_set_shape_detection_plugin.ui) From c6835292d856ee3b69f70293dc47b62435686308 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 12 Dec 2018 16:50:51 +0100 Subject: [PATCH 078/186] Add include of license --- Stream_support/include/CGAL/IO/write_vtk.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Stream_support/include/CGAL/IO/write_vtk.h b/Stream_support/include/CGAL/IO/write_vtk.h index 5d702e27d92..b55df59c17e 100644 --- a/Stream_support/include/CGAL/IO/write_vtk.h +++ b/Stream_support/include/CGAL/IO/write_vtk.h @@ -21,6 +21,9 @@ #ifndef CGAL_WRITE_VTK_IO_H #define CGAL_WRITE_VTK_IO_H + +#include + #include #include template From 7e7cb6826871f1342860413f0f36ae56344b2097 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 13 Dec 2018 09:14:53 +0100 Subject: [PATCH 079/186] Fix header for vtp_io --- BGL/include/CGAL/IO/vtp_io.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h index a616dd6b99c..19de9552e61 100644 --- a/BGL/include/CGAL/IO/vtp_io.h +++ b/BGL/include/CGAL/IO/vtp_io.h @@ -3,10 +3,10 @@ // Copyright (c) 2009 INRIA Sophia-Antipolis (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. +// 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. From 7c6b907f0f90f605fddf195d33f8615ed1fe5e7d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 13 Dec 2018 09:44:09 +0100 Subject: [PATCH 080/186] Restore cursor before returning --- .../Plugins/Surface_mesh/Parameterization_plugin.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index 06a7f88598b..b5959906149 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -824,6 +824,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio if (i == QDialog::Rejected) { std::cout << "Aborting parameterization" << std::endl; + QApplication::restoreOverrideCursor(); return; } @@ -836,6 +837,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio std::cerr << "Error: incompatible orbifold type and number of cones" << std::endl; std::cerr << "Types I, II & III require 3 selected vertices" << std::endl; std::cerr << "Type IV requires 4 selected vertices" << std::endl; + QApplication::restoreOverrideCursor(); return; } @@ -847,6 +849,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio if(!SMP::locate_unordered_cones(sMesh, unordered_cones.begin(), unordered_cones.end(), cmap)) { std::cerr << "Error: invalid cone or seam selection" << std::endl; + QApplication::restoreOverrideCursor(); return; } @@ -881,6 +884,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio std::cout << "success (in " << time.elapsed() << " ms)" << std::endl; } else { std::cerr << "failure: " << SMP::get_error_message(status) << std::endl; + QApplication::restoreOverrideCursor(); return; } From 74084d1246f52b8ab015a842b5d86c819aac26b8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 13 Dec 2018 15:45:22 +0100 Subject: [PATCH 081/186] Add missing includes --- .../CGAL/Classification/ETHZ_random_forest_classifier.h | 3 +++ .../Classification/internal/auxiliary/random-forest/forest.hpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 12db1189a0b..c076b34896b 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -25,6 +25,7 @@ #include #include +#include #ifdef CGAL_CLASSIFICATION_VERBOSE #define VERBOSE_TREE_PROGRESS 1 @@ -43,6 +44,8 @@ #include #include +#include + #include #include #include diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index 6dd83485e76..02d326f8c76 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -45,6 +45,8 @@ #include #endif +#include + #ifdef CGAL_LINKED_WITH_TBB #include #include From 18eaf08cc2dbd476ec7727b5e6ed85672fa95a24 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 13 Dec 2018 17:58:24 +0100 Subject: [PATCH 082/186] replace headers --- BGL/include/CGAL/IO/vtp_io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h index 19de9552e61..6a09aa5ae82 100644 --- a/BGL/include/CGAL/IO/vtp_io.h +++ b/BGL/include/CGAL/IO/vtp_io.h @@ -26,8 +26,8 @@ #include -#include -#include +#include +#include #include From 847a6d8a8fb3edfe5ae4ba03fa84fd3f77464e6b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 14 Dec 2018 10:22:11 +0100 Subject: [PATCH 083/186] Add TensorFlow_neural_network_classifier to whitelisted headers --- Installation/cmake/modules/list_of_whitelisted_headers.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Installation/cmake/modules/list_of_whitelisted_headers.cmake b/Installation/cmake/modules/list_of_whitelisted_headers.cmake index c6bfe0e3adb..55550e4663d 100644 --- a/Installation/cmake/modules/list_of_whitelisted_headers.cmake +++ b/Installation/cmake/modules/list_of_whitelisted_headers.cmake @@ -1,4 +1,5 @@ set(list_of_whitelisted_headers_txt [=[ + CGAL/Classification/TensorFlow_neural_network_classifier.h CGAL/Linear_cell_complex_constructors.h CGAL/CGAL_Ipelet_base.h CGAL/IO/read_las_points.h From c62e00e4416ca43172ccc4c57e5bb1956c2590c4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 14 Dec 2018 11:36:40 +0100 Subject: [PATCH 084/186] Set the scene_aabb_item empty to avoid crashing with offset. This is more a workaround than reallly a fix but I really think this item is not important enough to spend too much time trying to make a proper fix. --- Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp index 71dd2874115..36eff1d74e8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp @@ -253,7 +253,7 @@ public: { } - bool isFinite() const { return true; } + bool isFinite() const { return false; } bool isEmpty() const { return is_tree_empty; } //computed in constructor void compute_bbox() const {} From 9ff64eb5dcbebab2e8b899034e3c49e7152dd28e Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 14 Dec 2018 13:58:05 +0100 Subject: [PATCH 085/186] Fix the PCA plugin --- .../Polyhedron/Plugins/PCA/Pca_plugin.cpp | 292 +++++++++--------- Three/include/CGAL/Three/Three.h | 14 + 2 files changed, 162 insertions(+), 144 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp index e56af0979ad..4f293097b88 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp @@ -13,6 +13,7 @@ #include #include "Kernel_type.h" +#include typedef Kernel::Plane_3 Plane; typedef Kernel::Iso_cuboid_3 Iso_cuboid; typedef Kernel::Triangle_3 Triangle; @@ -99,148 +100,152 @@ void Polyhedron_demo_pca_plugin::on_actionFitPlane_triggered() Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(index)); - QApplication::setOverrideCursor(Qt::WaitCursor); - - std::list triangles; - - SMesh* pMesh = sm_item->polyhedron(); - ::triangles(*pMesh,std::back_inserter(triangles)); - - if(! triangles.empty()){ - QString item_name = sm_item->name(); - // fit plane to triangles - Plane plane; - std::cout << "Fit plane..."; - CGAL::linear_least_squares_fitting_3(triangles.begin(),triangles.end(),plane,CGAL::Dimension_tag<2>()); - std::cout << "ok" << std::endl; - - // compute centroid - Point center_of_mass = CGAL::centroid(triangles.begin(),triangles.end()); - Scene_plane_item* new_item = new Scene_plane_item(this->scene); - new_item->setPosition(center_of_mass.x(), - center_of_mass.y(), - center_of_mass.z()); - const Vector& normal = plane.orthogonal_vector(); - new_item->setNormal(normal.x(), normal.y(), normal.z()); - new_item->setName(tr("%1 (plane fit)").arg(item_name)); - new_item->setColor(Qt::magenta); - new_item->setRenderingMode(sm_item->renderingMode()); - scene->addItem(new_item); - - } - else - { - Scene_points_with_normal_item* item = - qobject_cast(scene->item(index)); - - if (item) - { - Point_set* points = item->point_set(); - - // fit plane to triangles - Plane plane; - Point center_of_mass; - std::cout << "Fit plane..."; - CGAL::linear_least_squares_fitting_3 - (points->points().begin(),points->points().end(),plane, center_of_mass, - CGAL::Dimension_tag<0>()); - std::cout << "ok" << std::endl; - - // compute centroid - Scene_plane_item* new_item = new Scene_plane_item(this->scene); - new_item->setPosition(center_of_mass.x(), - center_of_mass.y(), - center_of_mass.z()); - const Vector& normal = plane.orthogonal_vector(); - new_item->setNormal(normal.x(), normal.y(), normal.z()); - new_item->setName(tr("%1 (plane fit)").arg(item->name())); - new_item->setColor(Qt::magenta); - new_item->setRenderingMode(item->renderingMode()); - scene->addItem(new_item); - - } + Three::CursorScopeGuard scope; + scope.setCursor(Qt::WaitCursor); + if(sm_item){ + std::list triangles; + + SMesh* pMesh = sm_item->polyhedron(); + ::triangles(*pMesh,std::back_inserter(triangles)); + + if(! triangles.empty()){ + QString item_name = sm_item->name(); + // fit plane to triangles + Plane plane; + std::cout << "Fit plane..."; + CGAL::linear_least_squares_fitting_3(triangles.begin(),triangles.end(),plane,CGAL::Dimension_tag<2>()); + std::cout << "ok" << std::endl; + + // compute centroid + Point center_of_mass = CGAL::centroid(triangles.begin(),triangles.end()); + Scene_plane_item* new_item = new Scene_plane_item(this->scene); + new_item->setPosition(center_of_mass.x(), + center_of_mass.y(), + center_of_mass.z()); + const Vector& normal = plane.orthogonal_vector(); + new_item->setNormal(normal.x(), normal.y(), normal.z()); + new_item->setName(tr("%1 (plane fit)").arg(item_name)); + new_item->setColor(Qt::magenta); + new_item->setRenderingMode(sm_item->renderingMode()); + scene->addItem(new_item); + return; + } + } + Scene_points_with_normal_item* item = + qobject_cast(scene->item(index)); + + if (item) + { + Point_set* points = item->point_set(); + + // fit plane to triangles + Plane plane; + Point center_of_mass; + std::cout << "Fit plane..."; + CGAL::linear_least_squares_fitting_3 + (points->points().begin(),points->points().end(),plane, center_of_mass, + CGAL::Dimension_tag<0>()); + std::cout << "ok" << std::endl; + + // compute centroid + Scene_plane_item* new_item = new Scene_plane_item(this->scene); + new_item->setPosition(center_of_mass.x(), + center_of_mass.y(), + center_of_mass.z()); + const Vector& normal = plane.orthogonal_vector(); + new_item->setNormal(normal.x(), normal.y(), normal.z()); + new_item->setName(tr("%1 (plane fit)").arg(item->name())); + new_item->setColor(Qt::magenta); + new_item->setRenderingMode(item->renderingMode()); + scene->addItem(new_item); } - QApplication::restoreOverrideCursor(); } void Polyhedron_demo_pca_plugin::on_actionFitLine_triggered() { const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); + Three::CursorScopeGuard sg; + sg.setCursor(Qt::WaitCursor); + Scene_surface_mesh_item* sm_item = - qobject_cast(scene->item(index)); - - QApplication::setOverrideCursor(Qt::WaitCursor); - - CGAL::Bbox_3 bb; + qobject_cast(scene->item(index)); - std::list triangles; - SMesh* pMesh = sm_item->polyhedron(); - bb = ::triangles(*pMesh,std::back_inserter(triangles)); - - if(! triangles.empty()){ - QString item_name = sm_item->name(); - // fit line to triangles - Line line; - std::cout << "Fit line..."; - CGAL::linear_least_squares_fitting_3(triangles.begin(),triangles.end(),line,CGAL::Dimension_tag<2>()); - std::cout << "ok" << std::endl; - - // compute centroid - Point center_of_mass = CGAL::centroid(triangles.begin(),triangles.end()); - - // compute bounding box diagonal - Iso_cuboid bbox(bb); - - // compute scale for rendering using diagonal of bbox - Point cmin = (bbox.min)(); - Point cmax = (bbox.max)(); - FT diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); - - // construct a 3D bar - Vector u = line.to_vector(); - u = u / std::sqrt(u*u); - - Point a = center_of_mass + u * diag; - Point b = center_of_mass - u * diag; - - Plane plane_a = line.perpendicular_plane(a); - - Vector u1 = plane_a.base1(); - u1 = u1 / std::sqrt(u1*u1); - u1 = u1 * 0.01 * diag; - Vector u2 = plane_a.base2(); - u2 = u2 / std::sqrt(u2*u2); - u2 = u2 * 0.01 * diag; - - Point points[8]; - - points[0] = a + u1; - points[1] = a + u2; - points[2] = a - u1; - points[3] = a - u2; - - points[4] = b + u1; - points[5] = b + u2; - points[6] = b - u1; - points[7] = b - u2; - - // add best fit line as new polyhedron bar - SMesh* pFit = new SMesh; - CGAL::make_hexahedron(points[0], - points[1], - points[2], - points[3], - points[4], - points[5], - points[6], - points[7], - *pFit); - Scene_surface_mesh_item* new_item = new Scene_surface_mesh_item(pFit); - new_item->setName(tr("%1 (line fit)").arg(item_name)); - new_item->setColor(Qt::magenta); - new_item->setRenderingMode( sm_item->renderingMode()); - scene->addItem(new_item); + if(sm_item) + { + CGAL::Bbox_3 bb; + + SMesh* pMesh = sm_item->polyhedron(); + std::list triangles; + + bb = ::triangles(*pMesh,std::back_inserter(triangles)); + + if(! triangles.empty()){ + QString item_name = sm_item->name(); + // fit line to triangles + Line line; + std::cout << "Fit line..."; + CGAL::linear_least_squares_fitting_3(triangles.begin(),triangles.end(),line,CGAL::Dimension_tag<2>()); + std::cout << "ok" << std::endl; + + // compute centroid + Point center_of_mass = CGAL::centroid(triangles.begin(),triangles.end()); + + // compute bounding box diagonal + Iso_cuboid bbox(bb); + + // compute scale for rendering using diagonal of bbox + Point cmin = (bbox.min)(); + Point cmax = (bbox.max)(); + FT diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); + + // construct a 3D bar + Vector u = line.to_vector(); + u = u / std::sqrt(u*u); + + Point a = center_of_mass + u * diag; + Point b = center_of_mass - u * diag; + + Plane plane_a = line.perpendicular_plane(a); + + Vector u1 = plane_a.base1(); + u1 = u1 / std::sqrt(u1*u1); + u1 = u1 * 0.01 * diag; + Vector u2 = plane_a.base2(); + u2 = u2 / std::sqrt(u2*u2); + u2 = u2 * 0.01 * diag; + + Point points[8]; + + points[0] = a + u1; + points[1] = a + u2; + points[2] = a - u1; + points[3] = a - u2; + + points[4] = b + u1; + points[5] = b + u2; + points[6] = b - u1; + points[7] = b - u2; + + // add best fit line as new polyhedron bar + SMesh* pFit = new SMesh; + CGAL::make_hexahedron( + points[0], + points[3], + points[2], + points[1], + points[5], + points[4], + points[7], + points[6], + *pFit); + Scene_surface_mesh_item* new_item = new Scene_surface_mesh_item(pFit); + new_item->setName(tr("%1 (line fit)").arg(item_name)); + new_item->setColor(Qt::magenta); + new_item->setRenderingMode( sm_item->renderingMode()); + scene->addItem(new_item); + } + return; } else { @@ -297,15 +302,16 @@ void Polyhedron_demo_pca_plugin::on_actionFitLine_triggered() points[7] = b - u2; SMesh* pFit = new SMesh; - CGAL::make_hexahedron(points[0], - points[1], - points[2], - points[3], - points[4], - points[5], - points[6], - points[7], - *pFit); + CGAL::make_hexahedron( + points[0], + points[3], + points[2], + points[1], + points[5], + points[4], + points[7], + points[6], + *pFit); Scene_surface_mesh_item* new_item = new Scene_surface_mesh_item(pFit); new_item->setName(tr("%1 (line fit)").arg(item->name())); new_item->setColor(Qt::magenta); @@ -313,8 +319,6 @@ void Polyhedron_demo_pca_plugin::on_actionFitLine_triggered() scene->addItem(new_item); } } - - QApplication::restoreOverrideCursor(); } #include "Pca_plugin.moc" diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 17197383a41..865ada6bc53 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef three_EXPORTS # define THREE_EXPORT Q_DECL_EXPORT @@ -88,6 +89,19 @@ protected: static int default_normal_length; static int default_lines_width; +public: + struct CursorScopeGuard + { + CursorScopeGuard(){} + void setCursor(QCursor cursor) + { + QApplication::setOverrideCursor(cursor); + } + ~CursorScopeGuard() + { + QApplication::restoreOverrideCursor(); + } + }; }; } } From ad898d1ab7fa34e3d8a5831c14c19a2ad65e06d4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 14 Dec 2018 15:21:22 +0100 Subject: [PATCH 086/186] Fix triangulate_facet() --- Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 0013b1e4313..96845a6658c 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -895,11 +895,10 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd, if(normal == CGAL::NULL_VECTOR) { boost::graph_traits::halfedge_descriptor start = prev(halfedge(fd, *smesh_), *smesh_); - boost::graph_traits::halfedge_descriptor next_; + boost::graph_traits::halfedge_descriptor hd = halfedge(fd, *smesh_); + boost::graph_traits::halfedge_descriptor next_=next(hd, *smesh_); do { - boost::graph_traits::halfedge_descriptor hd = halfedge(fd, *smesh_); - next_ =next(hd, *smesh_); const Point_3& pa = smesh_->point(target(hd, *smesh_)); const Point_3& pb = smesh_->point(target(next_, *smesh_)); const Point_3& pc = smesh_->point(target(prev(hd, *smesh_), *smesh_)); @@ -908,6 +907,7 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd, normal = CGAL::cross_product(pb-pa, pc -pa); break; } + next_ =next(next_, *smesh_); }while(next_ != start); if (normal == CGAL::NULL_VECTOR) // No normal could be computed, return From 8ce9a1ca68555f27e26c79d93cc07f1abb1e39cf Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 14 Dec 2018 15:27:17 +0100 Subject: [PATCH 087/186] Don't use extra function in scope guard class --- Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp | 6 ++---- Three/include/CGAL/Three/Three.h | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp index 4f293097b88..9f3ea5b8477 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Pca_plugin.cpp @@ -100,8 +100,7 @@ void Polyhedron_demo_pca_plugin::on_actionFitPlane_triggered() Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(index)); - Three::CursorScopeGuard scope; - scope.setCursor(Qt::WaitCursor); + Three::CursorScopeGuard scope(Qt::WaitCursor); if(sm_item){ std::list triangles; @@ -165,8 +164,7 @@ void Polyhedron_demo_pca_plugin::on_actionFitLine_triggered() { const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); - Three::CursorScopeGuard sg; - sg.setCursor(Qt::WaitCursor); + Three::CursorScopeGuard sg(Qt::WaitCursor); Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(index)); diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 865ada6bc53..9133b366783 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -92,8 +92,7 @@ protected: public: struct CursorScopeGuard { - CursorScopeGuard(){} - void setCursor(QCursor cursor) + CursorScopeGuard(QCursor cursor) { QApplication::setOverrideCursor(cursor); } From acc456f2b05ed3c785b6aad56ffbb2fdb1f4fb6c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 14 Dec 2018 15:45:42 +0100 Subject: [PATCH 088/186] normalize normals length in display. Also, make them a little bit bigger. --- Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index 1bdc1b7058e..f3d9aff906f 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -185,7 +185,8 @@ public: if(has_normals) { const Kernel::Vector_3& n = point_set->normal(*it); - Point_set_3::Point q = p + length * n; + Kernel::FT normalizer = 1.0/CGAL::sqrt(n.squared_length()); + Point_set_3::Point q = p + length * n * normalizer; positions_lines[i * size_p + 3] = q.x() + offset.x; positions_lines[i * size_p + 4] = q.y() + offset.y; positions_lines[i * size_p + 5] = q.z() + offset.z; @@ -432,7 +433,7 @@ void Scene_points_with_normal_item_priv::compute_normals_and_vertices() const // we can't afford computing real average spacing just for display, 0.5% of bbox will do average_spacing = 0.005 * item->diagonalBbox(); normal_length = (std::min)(average_spacing, std::sqrt(region_of_interest.squared_radius() / 1000.)); - length_factor = 5.0/100*normal_Slider->value(); + length_factor = 10.0/100*normal_Slider->value(); } else { From 29ce1dd40bdd4a99157602c68d864611f1ee6983 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 18 Dec 2018 10:15:14 +0100 Subject: [PATCH 089/186] Fix Qt includes in plugin --- .../Plugins/Classification/Item_classification_base.h | 2 ++ .../Plugins/Classification/Point_set_item_classification.cpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 4f63a9957b2..6622d7ab645 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index 6273425fb8e..2b64ea7349a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -11,8 +11,6 @@ #include -#include - #include #include #include From b79fef9cc8c581f5f29f5863f55b9f6e40e526d7 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 18 Dec 2018 10:47:49 +0100 Subject: [PATCH 090/186] Update number of feature generated in assertion (3 new features * 5 scales) --- .../Classification/deprecated_test_classification_point_set.cpp | 2 +- .../test/Classification/test_classification_point_set.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Classification/test/Classification/deprecated_test_classification_point_set.cpp b/Classification/test/Classification/deprecated_test_classification_point_set.cpp index 45f5a92fdc3..46dc85b46a5 100644 --- a/Classification/test/Classification/deprecated_test_classification_point_set.cpp +++ b/Classification/test/Classification/deprecated_test_classification_point_set.cpp @@ -77,7 +77,7 @@ int main (int, char**) color_map, echo_map); assert (generator.number_of_scales() == 5); - assert (features.size() == 44); + assert (features.size() == 59); Label_set labels; diff --git a/Classification/test/Classification/test_classification_point_set.cpp b/Classification/test/Classification/test_classification_point_set.cpp index f7092478a70..c60fe69b17d 100644 --- a/Classification/test/Classification/test_classification_point_set.cpp +++ b/Classification/test/Classification/test_classification_point_set.cpp @@ -91,7 +91,7 @@ int main (int, char**) #endif assert (generator.number_of_scales() == 5); - assert (features.size() == 44); + assert (features.size() == 59); Label_set labels; From 394746a75d6ddf1705e82f01a89474561dd8b4c3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 18 Dec 2018 16:18:08 +0100 Subject: [PATCH 091/186] Fix typos from review --- Classification/doc/Classification/Classification.txt | 2 +- .../CGAL/Classification/ETHZ_random_forest_classifier.h | 2 +- .../include/CGAL/Classification/Feature/Height_above.h | 4 ++-- .../include/CGAL/Classification/Feature/Vertical_range.h | 2 +- .../Classification/TensorFlow_neural_network_classifier.h | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index e6d913579d7..4c95cbeaa69 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -88,7 +88,7 @@ The following code snippet shows how to instantiate such data structures from an - [Eigenvalue](@ref CGAL::Classification::Feature::Eigenvalue) measures one of the three local eigenvalues; - [Elevation](@ref CGAL::Classification::Feature::Elevation) computes the local distance to an estimation of the ground; - [Height_above](@ref CGAL::Classification::Feature::Elevation) computes the distance between the local highest point and the point; -- [Height_below](@ref CGAL::Classification::Feature::Elevation) computes the distance between the point and local lowest point; +- [Height_below](@ref CGAL::Classification::Feature::Elevation) computes the distance between the point and the local lowest point; - [Vertical_dispersion](@ref CGAL::Classification::Feature::Vertical_dispersion) computes how noisy the point set is on a local Z-cylinder; - [Vertical_range](@ref CGAL::Classification::Feature::Elevation) computes the distance between the local highest and lowest points; - [Verticality](@ref CGAL::Classification::Feature::Verticality) compares the local normal vector to the vertical vector. diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index c076b34896b..78543d11f73 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -266,7 +266,7 @@ public: \param count vector where the result is stored. After running the method, it contains, for each feature, the number of nodes in the - foret that uses it as a split criterion, in the same order as the + forest that use it as a split criterion, in the same order as the feature set order. */ void get_feature_usage (std::vector& count) const diff --git a/Classification/include/CGAL/Classification/Feature/Height_above.h b/Classification/include/CGAL/Classification/Feature/Height_above.h index b812e76634d..f40b5c9e230 100644 --- a/Classification/include/CGAL/Classification/Feature/Height_above.h +++ b/Classification/include/CGAL/Classification/Feature/Height_above.h @@ -41,10 +41,10 @@ namespace Feature { \ingroup PkgClassificationFeatures %Feature based on local height distribution This feature computes - the distance between the maxium height on the local cell of the + the distance between the maximum height on the local cell of the planimetric grid and a point's height. - Its default name is "height_after". + Its default name is "height_above". \tparam GeomTraits model of \cgal Kernel. \tparam PointRange model of `ConstRange`. Its iterator type diff --git a/Classification/include/CGAL/Classification/Feature/Vertical_range.h b/Classification/include/CGAL/Classification/Feature/Vertical_range.h index b5e670e0b7c..6a475786eef 100644 --- a/Classification/include/CGAL/Classification/Feature/Vertical_range.h +++ b/Classification/include/CGAL/Classification/Feature/Vertical_range.h @@ -40,7 +40,7 @@ namespace Feature { /*! \ingroup PkgClassificationFeatures - %Feature based on local height distribution This feature computes + %Feature based on local height distribution. This feature computes the distance between the maximum and the minimum height on the local cell of the planimetric grid. diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h index 11fa526dc27..99870bb49d2 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h @@ -230,7 +230,7 @@ public: \param restart_from_scratch should be set to `false` if the user wants to continue adjusting weights and bias based, and kept to `true` if the neural network should be re-created from scratch - (discarding all previous training result). + (discarding all previous training results). \param number_of_iterations number of times the optimizer is called. @@ -238,7 +238,7 @@ public: \param learning_rate describes the rate at which the optimizer changes the weights and bias. - \param batch_size size of the random subset of inliers uses for + \param batch_size size of the random subset of inliers used for optimizing at each iteration. \param hidden_layers vector containing the consecutive sizes From 39560e6c461723dbba3e79a2522158792f3c19f2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 17 Dec 2018 12:45:12 +0100 Subject: [PATCH 092/186] Fix memory leaks --- Polyhedron/demo/Polyhedron/Scene.cpp | 13 +++++++------ Polyhedron/demo/Polyhedron/Viewer.cpp | 8 ++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 568509ef22a..be6748b65ed 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -276,12 +276,13 @@ void Scene::remove_item_from_groups(Scene_item* item) } Scene::~Scene() { - Q_FOREACH(CGAL::Three::Scene_item* item_ptr, m_entries) - { - item_ptr->deleteLater(); - } - m_entries.clear(); - + vao->destroy(); + delete vao; + Q_FOREACH(CGAL::Three::Scene_item* item_ptr, m_entries) + { + item_ptr->deleteLater(); + } + m_entries.clear(); } CGAL::Three::Scene_item* diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 2e9fc83ac8c..34bbe50768c 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -331,7 +331,14 @@ Viewer::~Viewer() .arg(d->specular.z())); viewer_settings.setValue("spec_power", d->spec_power); + if(d->_recentFunctions) + delete d->_recentFunctions; + if(d->painter) + delete d->painter; + if(d->textRenderer) + d->textRenderer->deleteLater(); delete d; + } void Viewer::setScene(CGAL::Three::Scene_draw_interface* scene) @@ -1002,6 +1009,7 @@ void Viewer::drawVisualHints() if (d->_displayMessage) d->textRenderer->removeText(message_text); + delete message_text; } QOpenGLShaderProgram* Viewer::declare_program(int name, From e5e0d4212084f0b45b6a0d4c2f55452ad06ccf45 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 19 Dec 2018 10:23:01 +0100 Subject: [PATCH 093/186] More memory-leaks fix --- .../demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 6 +++++- .../Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp | 5 +++++ .../Plugins/Surface_mesh/Parameterization_plugin.cpp | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 6cad4ed03c9..5097c661475 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -302,7 +302,11 @@ private: Messages_interface* messages; public : - + ~Engrave_text_plugin() + { + delete graphics_scene; + delete navigation; + } void init(QMainWindow*, CGAL::Three::Scene_interface*, Messages_interface* m) Q_DECL_OVERRIDE{ diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp index cd7f6c5fbab..e2ad0cc4d68 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp @@ -98,6 +98,11 @@ class Polyhedron_demo_mean_curvature_flow_skeleton_plugin : public: + ~Polyhedron_demo_mean_curvature_flow_skeleton_plugin() + { + delete ui; + } + void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { this->mw = mainWindow; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index b5959906149..456c578df11 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -316,6 +316,10 @@ public: return _actions; } + ~Polyhedron_demo_parameterization_plugin() + { + delete navigation; + } void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface* msg) From 777f63d0389f9f8ae4d03482becd0ddd61475dfd Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 20 Dec 2018 14:22:51 +0100 Subject: [PATCH 094/186] Fix warnings --- .../include/CGAL/Classification/Feature/Height_above.h | 4 ++-- .../include/CGAL/Classification/Feature/Height_below.h | 4 ++-- .../internal/auxiliary/random-forest/common-libraries.hpp | 2 +- .../Plugins/Classification/Classification_plugin.cpp | 6 +----- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Classification/include/CGAL/Classification/Feature/Height_above.h b/Classification/include/CGAL/Classification/Feature/Height_above.h index f40b5c9e230..0696541b610 100644 --- a/Classification/include/CGAL/Classification/Feature/Height_above.h +++ b/Classification/include/CGAL/Classification/Feature/Height_above.h @@ -109,7 +109,7 @@ public: { std::size_t I = grid.x(i); std::size_t J = grid.y(i); - values[i] = dtm(I,J) - get (point_map, *(input.begin() + i)).z(); + values[i] = float(dtm(I,J) - get (point_map, *(input.begin() + i)).z()); } dtm.free(); } @@ -123,7 +123,7 @@ public: { std::size_t I = grid.x(pt_index); std::size_t J = grid.y(pt_index); - return dtm(I,J) - get (point_map, *(input.begin() + pt_index)).z(); + return dtm(I,J) - float(get (point_map, *(input.begin() + pt_index)).z()); } return values[pt_index]; diff --git a/Classification/include/CGAL/Classification/Feature/Height_below.h b/Classification/include/CGAL/Classification/Feature/Height_below.h index 4d39bbd0a9c..c63f890f20c 100644 --- a/Classification/include/CGAL/Classification/Feature/Height_below.h +++ b/Classification/include/CGAL/Classification/Feature/Height_below.h @@ -109,7 +109,7 @@ public: { std::size_t I = grid.x(i); std::size_t J = grid.y(i); - values[i] = get (point_map, *(input.begin() + i)).z() - dtm(I,J); + values[i] = float(get (point_map, *(input.begin() + i)).z() - dtm(I,J)); } dtm.free(); } @@ -123,7 +123,7 @@ public: { std::size_t I = grid.x(pt_index); std::size_t J = grid.y(pt_index); - return get (point_map, *(input.begin() + pt_index)).z() - dtm(I,J); + return float(get (point_map, *(input.begin() + pt_index)).z() - dtm(I,J)); } return values[pt_index]; diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 3e2099844a2..ec70abfdada 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -72,7 +72,7 @@ namespace liblearning { namespace RandomForest { typedef std::vector< std::pair > FeatureClassDataFloat; -inline void init_feature_class_data(FeatureClassDataFloat& data, int /*n_classes*/, int /* n_samples */) +inline void init_feature_class_data(FeatureClassDataFloat& /*data*/, int /*n_classes*/, int /* n_samples */) { // data.resize(n_samples); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index b64356a5617..97bc40b9f19 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -1346,10 +1346,6 @@ public Q_SLOTS: return; } - int nb_trials = 0; - int num_trees = 0; - int max_depth = 0; - QMultipleInputDialog dialog ("Train Classifier", mw); int classifier = get_classifier(); @@ -1380,7 +1376,7 @@ public Q_SLOTS: QSpinBox* batch = dialog.add ("Batch size: ", "batch_size"); batch->setRange (1, 2000000000); batch->setValue (1000); - QLineEdit* layers = dialog.add ("Hidden layer size(s): ", "hidden_layers"); + dialog.add ("Hidden layer size(s): ", "hidden_layers"); QCheckBox* restart = dialog.add ("Restart from scratch: ", "restart"); restart->setChecked (false); } From 6dab35a49ce931bd5e5b8ac0be4a3859ddcd54b0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 21 Dec 2018 10:11:07 +0100 Subject: [PATCH 095/186] Restore point_set_selection_plugin as a plugin, and use add_dependencies --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 3 ++- Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 92f4ee95bd6..787fcac26e7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -51,7 +51,8 @@ if(EIGEN3_FOUND) endif() target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp point_set_selection_plugin selection_plugin ${classification_linked_libraries}) + scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp ${classification_linked_libraries}) + add_dependencies(classification_plugin point_set_selection_plugin) target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else() message(STATUS "NOTICE: Boost Serialization or IO Streams or ZLIB not found. Classification plugin won't be available.") diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 92baf93a289..2c3571b54c1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -36,7 +36,7 @@ endif() 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) - add_library(point_set_selection_plugin SHARED Point_set_selection_plugin.cpp ${point_set_selectionUI_FILES}) + polyhedron_demo_plugin(point_set_selection_plugin Point_set_selection_plugin ${point_set_selectionUI_FILES}) target_link_libraries(point_set_selection_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_edit_box_item) qt5_wrap_ui(point_set_shape_detectionUI_FILES Point_set_shape_detection_plugin.ui) From 96be87f1a72ad5e536e0fc38e9e730dea8fa11ba Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 21 Dec 2018 11:03:41 +0100 Subject: [PATCH 096/186] create Classification/CGAL_Classification targets in demo --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 5 +++++ .../Polyhedron/Plugins/Classification/CMakeLists.txt | 2 +- Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt | 8 ++++---- Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt | 4 ++-- .../demo/Polyhedron/Plugins/Point_set/CMakeLists.txt | 10 +++++----- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 857b3622def..9090f621866 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -359,6 +359,11 @@ add_executable ( CGAL_Mesh_3 Mesh_3.cpp ) add_dependencies(CGAL_Mesh_3 Mesh_3) target_link_libraries( CGAL_Mesh_3 PRIVATE polyhedron_demo ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS CGAL_Mesh_3 ) + +add_executable ( CGAL_Classification Classification.cpp ) +add_dependencies(CGAL_Classification Classification) +target_link_libraries( CGAL_Classification PRIVATE polyhedron_demo ) +add_to_cached_list( CGAL_EXECUTABLE_TARGETS CGAL_Classification ) # # Exporting # diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 787fcac26e7..9ac1cd6b734 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -20,7 +20,7 @@ if(EIGEN3_FOUND) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND AND (NOT WIN32 OR Boost_ZLIB_FOUND)) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui Classification_advanced_widget.ui ) - polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification Cluster_classification Surface_mesh_item_classification ${classificationUI_FILES}) + polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification Cluster_classification Surface_mesh_item_classification ${classificationUI_FILES} KEYWORDS Classification) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index 4a642daba09..29b1962aa2b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -10,7 +10,7 @@ target_link_libraries(io_implicit_function_plugin PUBLIC scene_implicit_function polyhedron_demo_plugin(nef_io_plugin Nef_io_plugin KEYWORDS IO) target_link_libraries(nef_io_plugin PUBLIC scene_nef_polyhedron_item) -polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS IO Mesh_3) +polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS IO Mesh_3 Classification) target_link_libraries(off_plugin PUBLIC scene_polygon_soup_item scene_points_with_normal_item scene_surface_mesh_item) polyhedron_demo_plugin(off_to_nef_plugin OFF_to_nef_io_plugin KEYWORDS IO) @@ -48,7 +48,7 @@ if (VTK_FOUND) else() message(STATUS "NOTICE : the vtk IO plugin needs VTK 6.0 or greater and will not be compiled.") endif() -polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS IO) +polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS IO Classification) target_link_libraries(xyz_plugin PUBLIC scene_points_with_normal_item) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_rvalue_references has_cxx_rvalues) @@ -59,12 +59,12 @@ if(has_cxx_rvalues LESS 0 OR has_cxx_variadic LESS 0) else() set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) - polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS IO) + polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS IO Classification) target_link_libraries(ply_plugin PUBLIC scene_points_with_normal_item scene_polygon_soup_item scene_surface_mesh_item scene_polygon_soup_item) target_compile_features(ply_plugin PRIVATE ${needed_cxx_features}) if (LASLIB_FOUND) - polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO) + polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO Classification) target_link_libraries(las_plugin PUBLIC scene_points_with_normal_item ${LASLIB_LIBRARIES}) target_compile_features(las_plugin PRIVATE ${needed_cxx_features}) else() diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index f7d3860eac6..9af3a6ebe11 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -39,7 +39,7 @@ else() endif() -polyhedron_demo_plugin(orient_soup_plugin Orient_soup_plugin) +polyhedron_demo_plugin(orient_soup_plugin Orient_soup_plugin KEYWORDS Classification) target_link_libraries(orient_soup_plugin PUBLIC scene_polygon_soup_item scene_surface_mesh_item scene_polylines_item scene_points_with_normal_item) @@ -64,7 +64,7 @@ polyhedron_demo_plugin(polyhedron_stitching_plugin Polyhedron_stitching_plugin) target_link_libraries(polyhedron_stitching_plugin PUBLIC scene_surface_mesh_item scene_polylines_item) qt5_wrap_ui( selectionUI_FILES Selection_widget.ui) -polyhedron_demo_plugin(selection_plugin Selection_plugin ${selectionUI_FILES} KEYWORDS PolygonMesh IO) +polyhedron_demo_plugin(selection_plugin Selection_plugin ${selectionUI_FILES} KEYWORDS PolygonMesh IO Classification) target_link_libraries(selection_plugin PUBLIC scene_selection_item scene_points_with_normal_item scene_polylines_item) polyhedron_demo_plugin(self_intersection_plugin Self_intersection_plugin) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 2c3571b54c1..7851aff0931 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -5,7 +5,7 @@ if(EIGEN3_FOUND) target_link_libraries(surface_reconstruction_plugin PUBLIC scene_polygon_soup_item scene_surface_mesh_item scene_points_with_normal_item) 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}) + polyhedron_demo_plugin(point_set_normal_estimation_plugin Point_set_normal_estimation_plugin ${point_set_normal_estimationUI_FILES} KEYWORDS Classification) 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) @@ -15,7 +15,7 @@ if(EIGEN3_FOUND) polyhedron_demo_plugin(point_set_smoothing_plugin Point_set_smoothing_plugin) 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) + polyhedron_demo_plugin(point_set_average_spacing_plugin Point_set_average_spacing_plugin KEYWORDS Classification) target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) else(EIGEN3_FOUND) @@ -36,11 +36,11 @@ endif() 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}) + polyhedron_demo_plugin(point_set_selection_plugin Point_set_selection_plugin ${point_set_selectionUI_FILES} KEYWORDS Classification) target_link_libraries(point_set_selection_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_edit_box_item) 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}) + polyhedron_demo_plugin(point_set_shape_detection_plugin Point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES} KEYWORDS Classification) target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_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) @@ -55,7 +55,7 @@ endif() 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 scene_callback_signaler) - polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin) + polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin KEYWORDS Classification) target_link_libraries(merge_point_sets_plugin PUBLIC scene_points_with_normal_item) polyhedron_demo_plugin(point_set_interference_plugin Point_set_interference_plugin) From e9b99cf940304ad91642bf8f9932ea693f555df4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 21 Dec 2018 11:04:30 +0100 Subject: [PATCH 097/186] Add dependency to selection plugin --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 9ac1cd6b734..c3e48ffcd9b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -52,7 +52,7 @@ if(EIGEN3_FOUND) target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp ${classification_linked_libraries}) - add_dependencies(classification_plugin point_set_selection_plugin) + add_dependencies(classification_plugin point_set_selection_plugin selection_plugin) target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else() message(STATUS "NOTICE: Boost Serialization or IO Streams or ZLIB not found. Classification plugin won't be available.") From 4075261fcdba54ff6a384441c348e2f1581d0a88 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 21 Dec 2018 11:16:17 +0100 Subject: [PATCH 098/186] Create a target PointSetProcessing for demo --- .../Plugins/Convex_hull/CMakeLists.txt | 2 +- .../demo/Polyhedron/Plugins/IO/CMakeLists.txt | 8 ++--- .../Polyhedron/Plugins/PCA/CMakeLists.txt | 6 ++-- .../Plugins/Point_set/CMakeLists.txt | 32 +++++++++---------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt index 900441b871b..61c6d9416c3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt @@ -1,7 +1,7 @@ include( polyhedron_demo_macros ) polyhedron_demo_plugin(convex_hull_plugin Convex_hull_plugin) -target_link_libraries(convex_hull_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_selection_item scene_surface_mesh_item) +target_link_libraries(convex_hull_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_selection_item scene_surface_mesh_item KEYWORDS PointSetProcessing) polyhedron_demo_plugin(kernel_plugin Kernel_plugin) target_link_libraries(kernel_plugin PUBLIC scene_surface_mesh_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index 29b1962aa2b..e5d500cc9db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -10,7 +10,7 @@ target_link_libraries(io_implicit_function_plugin PUBLIC scene_implicit_function polyhedron_demo_plugin(nef_io_plugin Nef_io_plugin KEYWORDS IO) target_link_libraries(nef_io_plugin PUBLIC scene_nef_polyhedron_item) -polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS IO Mesh_3 Classification) +polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS IO Mesh_3 PointSetProcessing Classification) target_link_libraries(off_plugin PUBLIC scene_polygon_soup_item scene_points_with_normal_item scene_surface_mesh_item) polyhedron_demo_plugin(off_to_nef_plugin OFF_to_nef_io_plugin KEYWORDS IO) @@ -48,7 +48,7 @@ if (VTK_FOUND) else() message(STATUS "NOTICE : the vtk IO plugin needs VTK 6.0 or greater and will not be compiled.") endif() -polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS IO Classification) +polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS IO PointSetProcessing Classification) target_link_libraries(xyz_plugin PUBLIC scene_points_with_normal_item) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_rvalue_references has_cxx_rvalues) @@ -59,12 +59,12 @@ if(has_cxx_rvalues LESS 0 OR has_cxx_variadic LESS 0) else() set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) - polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS IO Classification) + polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS IO PointSetProcessing Classification) target_link_libraries(ply_plugin PUBLIC scene_points_with_normal_item scene_polygon_soup_item scene_surface_mesh_item scene_polygon_soup_item) target_compile_features(ply_plugin PRIVATE ${needed_cxx_features}) if (LASLIB_FOUND) - polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO Classification) + polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO PointSetProcessing Classification) target_link_libraries(las_plugin PUBLIC scene_points_with_normal_item ${LASLIB_LIBRARIES}) target_compile_features(las_plugin PRIVATE ${needed_cxx_features}) else() diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt index ee9332ff8bd..f86989e9000 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt @@ -1,10 +1,10 @@ include( polyhedron_demo_macros ) -polyhedron_demo_plugin(pca_plugin Pca_plugin) +polyhedron_demo_plugin(pca_plugin Pca_plugin KEYWORDS PointSetProcessing) target_link_libraries(pca_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_basic_objects) qt5_wrap_ui( transformUI_FILES Transformation_widget.ui MeshOnGrid_dialog.ui) -polyhedron_demo_plugin(affine_transform_plugin Affine_transform_plugin ${transformUI_FILES}) +polyhedron_demo_plugin(affine_transform_plugin Affine_transform_plugin ${transformUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(affine_transform_plugin PUBLIC scene_surface_mesh_item scene_transform_item scene_points_with_normal_item) polyhedron_demo_plugin(edit_box_plugin Edit_box_plugin) @@ -18,5 +18,5 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin) target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item) qt5_wrap_ui( volumesUI_FILES Basic_generator_widget.ui) -polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES} KEYWORDS PolygonMesh) +polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES} KEYWORDS PolygonMesh PointSetProcessing) target_link_libraries(basic_generator_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_polylines_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 7851aff0931..9c56ba4df2a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -1,21 +1,21 @@ include( polyhedron_demo_macros ) if(EIGEN3_FOUND) qt5_wrap_ui( surface_reconstructionUI_FILES Surface_reconstruction_plugin.ui) - polyhedron_demo_plugin(surface_reconstruction_plugin Surface_reconstruction_plugin Surface_reconstruction_plugin_impl ${surface_reconstructionUI_FILES}) + polyhedron_demo_plugin(surface_reconstruction_plugin Surface_reconstruction_plugin Surface_reconstruction_plugin_impl ${surface_reconstructionUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(surface_reconstruction_plugin PUBLIC scene_polygon_soup_item scene_surface_mesh_item scene_points_with_normal_item) 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} KEYWORDS Classification) + polyhedron_demo_plugin(point_set_normal_estimation_plugin Point_set_normal_estimation_plugin ${point_set_normal_estimationUI_FILES} KEYWORDS PointSetProcessing Classification) 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}) + polyhedron_demo_plugin(features_detection_plugin Features_detection_plugin ${features_detection_pluginUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(features_detection_plugin PUBLIC scene_points_with_normal_item) - polyhedron_demo_plugin(point_set_smoothing_plugin Point_set_smoothing_plugin) + polyhedron_demo_plugin(point_set_smoothing_plugin Point_set_smoothing_plugin KEYWORDS PointSetProcessing) 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 KEYWORDS Classification) + polyhedron_demo_plugin(point_set_average_spacing_plugin Point_set_average_spacing_plugin KEYWORDS PointSetProcessing Classification) target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) else(EIGEN3_FOUND) @@ -28,45 +28,45 @@ else(EIGEN3_FOUND) 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}) + polyhedron_demo_plugin(point_set_bilateral_smoothing_plugin Point_set_bilateral_smoothing_plugin ${point_set_bilateral_smoothingUI_FILES} KEYWORDS PointSetProcessing) 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}) + polyhedron_demo_plugin(point_set_outliers_removal_plugin Point_set_outliers_removal_plugin ${ps_outliers_removal_UI_FILES} KEYWORDS PointSetProcessing) 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} KEYWORDS Classification) + polyhedron_demo_plugin(point_set_selection_plugin Point_set_selection_plugin ${point_set_selectionUI_FILES} KEYWORDS PointSetProcessing Classification) target_link_libraries(point_set_selection_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_edit_box_item) 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} KEYWORDS Classification) + polyhedron_demo_plugin(point_set_shape_detection_plugin Point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES} KEYWORDS PointSetProcessing Classification) target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_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}) + polyhedron_demo_plugin(point_set_simplification_plugin Point_set_simplification_plugin ${point_set_simplificationUI_FILES} KEYWORDS PointSetProcessing) 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}) + polyhedron_demo_plugin(point_set_upsampling_plugin Point_set_upsampling_plugin ${point_set_upsamplingUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(point_set_upsampling_plugin PUBLIC scene_points_with_normal_item) 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}) + polyhedron_demo_plugin(point_set_wlop_plugin Point_set_wlop_plugin ${point_set_wlopFILES} KEYWORDS PointSetProcessing) 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 KEYWORDS Classification) + polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin KEYWORDS PointSetProcessing Classification) target_link_libraries(merge_point_sets_plugin PUBLIC scene_points_with_normal_item) - polyhedron_demo_plugin(point_set_interference_plugin Point_set_interference_plugin) + polyhedron_demo_plugin(point_set_interference_plugin Point_set_interference_plugin KEYWORDS PointSetProcessing) target_link_libraries(point_set_interference_plugin PUBLIC scene_points_with_normal_item) qt5_wrap_ui( alpha_shapeUI_FILES Alpha_shape_widget.ui ) - polyhedron_demo_plugin(alpha_shape_plugin Alpha_shape_plugin ${alpha_shapeUI_FILES}) + polyhedron_demo_plugin(alpha_shape_plugin Alpha_shape_plugin ${alpha_shapeUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(alpha_shape_plugin PUBLIC scene_points_with_normal_item scene_c3t3_item) qt5_wrap_ui( distanceUI_FILES Point_set_to_mesh_distance_widget.ui ) - polyhedron_demo_plugin(point_set_to_mesh_distance_plugin Point_set_to_mesh_distance_plugin ${distanceUI_FILES}) + polyhedron_demo_plugin(point_set_to_mesh_distance_plugin Point_set_to_mesh_distance_plugin ${distanceUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(point_set_to_mesh_distance_plugin PUBLIC scene_points_with_normal_item scene_surface_mesh_item scene_color_ramp) if(TBB_FOUND) From 26463ab6b78e275155e3964184b4bc2dd967a771 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 2 Jan 2019 08:41:04 +0100 Subject: [PATCH 099/186] Fix wrongly defined target KEYWORDS --- Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt index 61c6d9416c3..f5c8d0c766d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/CMakeLists.txt @@ -1,7 +1,7 @@ include( polyhedron_demo_macros ) -polyhedron_demo_plugin(convex_hull_plugin Convex_hull_plugin) -target_link_libraries(convex_hull_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_selection_item scene_surface_mesh_item KEYWORDS PointSetProcessing) +polyhedron_demo_plugin(convex_hull_plugin Convex_hull_plugin KEYWORDS PointSetProcessing) +target_link_libraries(convex_hull_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_selection_item scene_surface_mesh_item) polyhedron_demo_plugin(kernel_plugin Kernel_plugin) target_link_libraries(kernel_plugin PUBLIC scene_surface_mesh_item) From 9e20888127379ed722c55fa46e24f385dc4283c4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 2 Jan 2019 08:41:47 +0100 Subject: [PATCH 100/186] Push missing file --- Polyhedron/demo/Polyhedron/Classification.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/Classification.cpp diff --git a/Polyhedron/demo/Polyhedron/Classification.cpp b/Polyhedron/demo/Polyhedron/Classification.cpp new file mode 100644 index 00000000000..acbb39eb536 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Classification.cpp @@ -0,0 +1,29 @@ +#include "Polyhedron_demo.h" +#include +#include +#include + + +/*! + * \brief Defines the entry point of the demo. + * Creates the application and sets a main window. + */ +int main(int argc, char **argv) +{ + QSurfaceFormat fmt; + + fmt.setVersion(4, 3); + fmt.setRenderableType(QSurfaceFormat::OpenGL); + fmt.setProfile(QSurfaceFormat::CoreProfile); + fmt.setOption(QSurfaceFormat::DebugContext); + QSurfaceFormat::setDefaultFormat(fmt); + QStringList keywords; + keywords << "Classification"; + Polyhedron_demo app(argc, argv, + "Classification demo", + "CGAL Classification Demo", + keywords); + //We set the locale to avoid any trouble with VTK + std::setlocale(LC_ALL, "C"); + return app.try_exec(); +} From d90b5d5259e751cb8b23fe55d735307f10fef3c9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 21 Dec 2018 12:35:22 +0100 Subject: [PATCH 101/186] Fix reload c3t3 --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 +- Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index ddc8cf0668d..9f164a121a1 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1016,9 +1016,9 @@ void MainWindow::reloadItem() { new_item->setRenderingMode(item->renderingMode()); new_item->setVisible(item->visible()); Scene_item_with_properties *property_item = dynamic_cast(new_item); + scene->replaceItem(scene->item_id(item), new_item, true); if(property_item) property_item->copyProperties(item); - scene->replaceItem(scene->item_id(item), new_item, true); new_item->invalidateOpenGLBuffers(); item->deleteLater(); } diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 8abcf815820..0e9eb038efc 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -1304,7 +1304,7 @@ QMenu* Scene_c3t3_item::contextMenu() QMenu *container = new QMenu(tr("Alpha value")); container->menuAction()->setProperty("is_groupable", true); QWidgetAction *sliderAction = new QWidgetAction(0); - sliderAction->setDefaultWidget(d->alphaSlider); + sliderAction->setDefaultWidget(alphaSlider()); connect(d->alphaSlider, &QSlider::valueChanged, [this]() { From c81fbe46888c56bd74b186db4d84b56f99f82562 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 7 Jan 2019 11:50:02 +0100 Subject: [PATCH 102/186] Move all classifiers based on other libraries to dedicated namespaces --- .../doc/Classification/Classification.txt | 20 ++++++------- .../doc/Classification/Concepts/Classifier.h | 5 ++-- .../doc/Classification/PackageDescription.txt | 21 ++++++++++++-- .../example_cluster_classification.cpp | 2 +- .../example_ethz_random_forest.cpp | 2 +- .../example_mesh_classification.cpp | 2 +- .../example_opencv_random_forest.cpp | 2 +- .../example_tensorflow_neural_network.cpp | 2 +- Classification/include/CGAL/Classification.h | 6 ++-- .../Random_forest_classifier.h} | 27 +++++++++++------ .../auxiliary => ETHZ/internal}/dataview.h | 0 .../random-forest/common-libraries.hpp | 0 .../internal}/random-forest/forest.hpp | 0 .../internal}/random-forest/node-gini.hpp | 0 .../internal}/random-forest/node.hpp | 0 .../internal}/random-forest/tree.hpp | 0 .../Random_forest_classifier.h} | 29 ++++++++++++------- .../Neural_network_classifier.h} | 17 ++++++----- .../Classification/test_classification_io.cpp | 2 +- Installation/CHANGES.md | 12 +++++--- .../Classification/Item_classification_base.h | 12 ++++---- 21 files changed, 101 insertions(+), 60 deletions(-) rename Classification/include/CGAL/Classification/{ETHZ_random_forest_classifier.h => ETHZ/Random_forest_classifier.h} (93%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/dataview.h (100%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/random-forest/common-libraries.hpp (100%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/random-forest/forest.hpp (100%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/random-forest/node-gini.hpp (100%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/random-forest/node.hpp (100%) rename Classification/include/CGAL/Classification/{internal/auxiliary => ETHZ/internal}/random-forest/tree.hpp (100%) rename Classification/include/CGAL/Classification/{OpenCV_random_forest_classifier.h => OpenCV/Random_forest_classifier.h} (93%) rename Classification/include/CGAL/Classification/{TensorFlow_neural_network_classifier.h => TensorFlow/Neural_network_classifier.h} (98%) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index 4c95cbeaa69..b107408a547 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -201,13 +201,13 @@ Example of cluster classification mesh (left: input, middle: clusters computed f %Classification relies on a classifier: this classifier is an object that, from the set of values taken by the features at an input item, computes the probability that an input item belongs to one label or another. A model of the concept `CGAL::Classification::Classifier` must take the index of an input item and store the probability associated to each label in a vector. If a classifier returns the value 1 for a pair of label and input item, it means that this item belongs to this label with certainty; values close to 0 mean that this item is not likely to belong to this label. -\cgal provides four models for this concept, [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier), [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier) and [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier). +\cgal provides four models for this concept, [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier), [OpenCV::Random_forest_classifier](@ref CGAL::Classification::OpenCV::Random_forest_classifier), [TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier) and [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier). To perform classification based on four classifiers, please refer to \ref Classification_classification_functions. \subsection Classification_ETHZ_random_forest ETHZ Random Forest -\cgal provides [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), +\cgal provides [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier), a classifier based on the Random Forest Template Library developed by Stefan Walk at ETH Zurich \cgalCite{cgal:w-erftl-14} (the library is distributed under the MIT license and is included with the \cgal release, @@ -232,13 +232,13 @@ to README provided in the [ETH Zurich's code archive](https://www.ethz.ch/conten \subsection Classification_OpenCV_random_forest OpenCV Random Forest -The second classifier is [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier). +The second classifier is [OpenCV::Random_forest_classifier](@ref CGAL::Classification::OpenCV::Random_forest_classifier). It uses the \ref thirdpartyOpenCV library, more specifically the [Random Trees](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) package. Note that this classifier usually produces results with a lower -quality than [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier). +quality than [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier). It is provided for the sake of completeness and for testing purposes, but if you are not sure what to use, we advise using the ETHZ Random @@ -251,7 +251,7 @@ of OpenCV. \subsection Classification_TensorFlow_neural_network TensorFlow Neural Network -\cgal provides [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier). +\cgal provides [TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier). It uses the C++ API of the \ref thirdpartyTensorFlow library. @@ -508,19 +508,19 @@ The following example: \subsection Classification_example_ethz_random_forest ETHZ Random Forest -The following example shows how to use the classifier [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier) using an input training set. +The following example shows how to use the classifier [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier) using an input training set. \cgalExample{Classification/example_ethz_random_forest.cpp} \subsection Classification_example_opencv_random_forest OpenCV Random Forest -The following example shows how to use the classifier [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier) using an input training set. +The following example shows how to use the classifier [OpenCV::Random_forest_classifier](@ref CGAL::Classification::OpenCV::Random_forest_classifier) using an input training set. \cgalExample{Classification/example_opencv_random_forest.cpp} \subsection Classification_example_tensorflow_neural_network TensorFlow Neural Network -The following example shows how to use the classifier [TensorFlow_neural_network_classifier](@ref CGAL::Classification::TensorFlow_neural_network_classifier) using an input training set. +The following example shows how to use the classifier [TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier) using an input training set. \cgalExample{Classification/example_tensorflow_neural_network.cpp} @@ -530,7 +530,7 @@ The following example: - reads a mesh in OFF format; - automatically generates features on 5 scales; -- loads a configuration file for classifier [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier); +- loads a configuration file for classifier [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier); - runs the algorithm using the graphcut regularization. \cgalExample{Classification/example_mesh_classification.cpp} @@ -545,7 +545,7 @@ The following example: - detects plane using the algorithm `CGAL::Shape_detection_3::Region_growing`; - creates [Cluster](@ref CGAL::Classification::Cluster) objects from these detected planes; - computes cluster features from the pointwise features; -- loads a configuration file for classifier [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier); +- loads a configuration file for classifier [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier); - runs the algorithm using the raw algorithm. \cgalExample{Classification/example_cluster_classification.cpp} diff --git a/Classification/doc/Classification/Concepts/Classifier.h b/Classification/doc/Classification/Concepts/Classifier.h index 1702fba0cb9..5f0059a7519 100644 --- a/Classification/doc/Classification/Concepts/Classifier.h +++ b/Classification/doc/Classification/Concepts/Classifier.h @@ -13,8 +13,9 @@ Concept describing a classifier used by classification functions (see `CGAL::Classification::classify_with_graphcut()`). \cgalHasModel `CGAL::Classification::Sum_of_weighted_features_classifier` -\cgalHasModel `CGAL::Classification::ETHZ_random_forest_classifier` -\cgalHasModel `CGAL::Classification::OpenCV_random_forest_classifier` +\cgalHasModel `CGAL::Classification::ETHZ::Random_forest_classifier` +\cgalHasModel `CGAL::Classification::OpenCV::Random_forest_classifier` +\cgalHasModel `CGAL::Classification::TensorFlow::Neural_network_classifier` */ class Classifier diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index 04c12aeb469..ab3ce14e173 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -14,6 +14,21 @@ Functions that perform classification based on a set of labels and a classifier, Classifiers are functors that, given a label set and an input item, associate this input item with an energy for each label. This energy measures the likelihood of the item to belong to this label. +\defgroup PkgClassificationClassifiersETHZ ETHZ +\ingroup PkgClassificationClassifiers + +Classifiers that use the ETHZ library. + +\defgroup PkgClassificationClassifiersOpenCV OpenCV +\ingroup PkgClassificationClassifiers + +Classifiers that use the \ref thirdpartyOpenCV library. + +\defgroup PkgClassificationClassifiersTensorFlow TensorFlow +\ingroup PkgClassificationClassifiers + +Classifiers that use the \ref thirdpartyTensorFlow library. + \defgroup PkgClassificationDataStructures Common Data Structures \ingroup PkgClassificationRef @@ -86,9 +101,9 @@ Data structures specialized to classify clusters. ## Classifiers ## -- `CGAL::Classification::ETHZ_random_forest_classifier` -- `CGAL::Classification::OpenCV_random_forest_classifier` -- `CGAL::Classification::TensorFlow_neural_network_classifier` +- `CGAL::Classification::ETHZ::Random_forest_classifier` +- `CGAL::Classification::OpenCV::Random_forest_classifier` +- `CGAL::Classification::TensorFlow::Neural_network_classifier` - `CGAL::Classification::Sum_of_weighted_features_classifier` ## Common Data Structures ## diff --git a/Classification/examples/Classification/example_cluster_classification.cpp b/Classification/examples/Classification/example_cluster_classification.cpp index 5774336d484..3012b5c62f0 100644 --- a/Classification/examples/Classification/example_cluster_classification.cpp +++ b/Classification/examples/Classification/example_cluster_classification.cpp @@ -191,7 +191,7 @@ int main (int argc, char** argv) std::vector label_indices(clusters.size(), -1); std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; - Classification::ETHZ_random_forest_classifier classifier (labels, features); + Classification::ETHZ::Random_forest_classifier classifier (labels, features); std::cerr << "Loading configuration" << std::endl; std::ifstream in_config (filename_config, std::ios_base::in | std::ios_base::binary); diff --git a/Classification/examples/Classification/example_ethz_random_forest.cpp b/Classification/examples/Classification/example_ethz_random_forest.cpp index 202c1b5d9fb..f4cca8960b8 100644 --- a/Classification/examples/Classification/example_ethz_random_forest.cpp +++ b/Classification/examples/Classification/example_ethz_random_forest.cpp @@ -91,7 +91,7 @@ int main (int argc, char** argv) std::vector label_indices(pts.size(), -1); std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; - Classification::ETHZ_random_forest_classifier classifier (labels, features); + Classification::ETHZ::Random_forest_classifier classifier (labels, features); std::cerr << "Training" << std::endl; t.reset(); diff --git a/Classification/examples/Classification/example_mesh_classification.cpp b/Classification/examples/Classification/example_mesh_classification.cpp index da76248ed7d..f6ac64f60c2 100644 --- a/Classification/examples/Classification/example_mesh_classification.cpp +++ b/Classification/examples/Classification/example_mesh_classification.cpp @@ -85,7 +85,7 @@ int main (int argc, char** argv) std::vector label_indices(mesh.number_of_faces(), -1); std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; - Classification::ETHZ_random_forest_classifier classifier (labels, features); + Classification::ETHZ::Random_forest_classifier classifier (labels, features); std::cerr << "Loading configuration" << std::endl; std::ifstream in_config (filename_config, std::ios_base::in | std::ios_base::binary); diff --git a/Classification/examples/Classification/example_opencv_random_forest.cpp b/Classification/examples/Classification/example_opencv_random_forest.cpp index 4b97032d65d..4ada5c5182a 100644 --- a/Classification/examples/Classification/example_opencv_random_forest.cpp +++ b/Classification/examples/Classification/example_opencv_random_forest.cpp @@ -90,7 +90,7 @@ int main (int argc, char** argv) std::vector label_indices(pts.size(), -1); std::cerr << "Using OpenCV Random Forest Classifier" << std::endl; - Classification::OpenCV_random_forest_classifier classifier (labels, features); + Classification::OpenCV::Random_forest_classifier classifier (labels, features); std::cerr << "Training" << std::endl; t.reset(); diff --git a/Classification/examples/Classification/example_tensorflow_neural_network.cpp b/Classification/examples/Classification/example_tensorflow_neural_network.cpp index 6763faf6da0..d86650de182 100644 --- a/Classification/examples/Classification/example_tensorflow_neural_network.cpp +++ b/Classification/examples/Classification/example_tensorflow_neural_network.cpp @@ -91,7 +91,7 @@ int main (int argc, char** argv) std::vector label_indices(pts.size(), -1); std::cerr << "Using TensorFlow neural network Classifier" << std::endl; - Classification::TensorFlow_neural_network_classifier<> classifier (labels, features); + Classification::TensorFlow::Neural_network_classifier<> classifier (labels, features); std::cerr << "Training" << std::endl; t.reset(); diff --git a/Classification/include/CGAL/Classification.h b/Classification/include/CGAL/Classification.h index 7800d10794d..6be192f22b8 100644 --- a/Classification/include/CGAL/Classification.h +++ b/Classification/include/CGAL/Classification.h @@ -25,14 +25,14 @@ #include #include -#include +#include #ifdef CGAL_LINKED_WITH_OPENCV -#include +#include #endif #ifdef CGAL_LINKED_WITH_TENSORFLOW -#include +#include #endif #include diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h similarity index 93% rename from Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h rename to Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h index 07d2918fc9f..3535ec20c74 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h @@ -42,8 +42,8 @@ # pragma warning(disable:4996) #endif -#include -#include +#include +#include #include @@ -61,8 +61,10 @@ namespace CGAL { namespace Classification { +namespace ETHZ { + /*! - \ingroup PkgClassificationClassifiers + \ingroup PkgClassificationClassifiersETHZ \brief %Classifier based on the ETH Zurich version of random forest algorithm \cgalCite{cgal:w-erftl-14}. @@ -70,7 +72,7 @@ namespace Classification { \cgalModels `CGAL::Classification::Classifier` */ -class ETHZ_random_forest_classifier +class Random_forest_classifier { typedef CGAL::internal::liblearning::RandomForest::RandomForest < CGAL::internal::liblearning::RandomForest::NodeGini @@ -89,8 +91,8 @@ public: \brief Instantiate the classifier using the sets of `labels` and `features`. */ - ETHZ_random_forest_classifier (const Label_set& labels, - const Feature_set& features) + Random_forest_classifier (const Label_set& labels, + const Feature_set& features) : m_labels (labels), m_features (features), m_rfc (NULL) { } @@ -105,8 +107,8 @@ public: than the ones used by `other`, and in the same order. */ - ETHZ_random_forest_classifier (const ETHZ_random_forest_classifier& other, - const Feature_set& features) + Random_forest_classifier (const Random_forest_classifier& other, + const Feature_set& features) : m_labels (other.m_labels), m_features (features), m_rfc (NULL) { std::stringstream stream; @@ -115,7 +117,7 @@ public: } /// \cond SKIP_IN_MANUAL - ~ETHZ_random_forest_classifier () + ~Random_forest_classifier () { if (m_rfc != NULL) delete m_rfc; @@ -327,6 +329,13 @@ public: } +/// \cond SKIP_IN_MANUAL +// Backward compatibility +typedef ETHZ::Random_forest_classifier ETHZ_random_forest_classifier; +/// \endcond + +} + } #endif // CGAL_CLASSIFICATION_ETHZ_RANDOM_FOREST_CLASSIFIER_H diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h b/Classification/include/CGAL/Classification/ETHZ/internal/dataview.h similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/dataview.h rename to Classification/include/CGAL/Classification/ETHZ/internal/dataview.h diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/ETHZ/internal/random-forest/common-libraries.hpp similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp rename to Classification/include/CGAL/Classification/ETHZ/internal/random-forest/common-libraries.hpp diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/ETHZ/internal/random-forest/forest.hpp similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp rename to Classification/include/CGAL/Classification/ETHZ/internal/random-forest/forest.hpp diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/ETHZ/internal/random-forest/node-gini.hpp similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp rename to Classification/include/CGAL/Classification/ETHZ/internal/random-forest/node-gini.hpp diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/ETHZ/internal/random-forest/node.hpp similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp rename to Classification/include/CGAL/Classification/ETHZ/internal/random-forest/node.hpp diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp b/Classification/include/CGAL/Classification/ETHZ/internal/random-forest/tree.hpp similarity index 100% rename from Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp rename to Classification/include/CGAL/Classification/ETHZ/internal/random-forest/tree.hpp diff --git a/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h b/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h similarity index 93% rename from Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h rename to Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h index 091396b1b14..acfa4b46e23 100644 --- a/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h @@ -37,8 +37,10 @@ namespace CGAL { namespace Classification { +namespace OpenCV { + /*! - \ingroup PkgClassificationClassifiers + \ingroup PkgClassificationClassifiersOpenCV \brief %Classifier based on the OpenCV version of random forest algorithm. @@ -46,7 +48,7 @@ namespace Classification { \cgalModels `CGAL::Classification::Classifier` */ -class OpenCV_random_forest_classifier +class Random_forest_classifier { const Label_set& m_labels; const Feature_set& m_features; @@ -80,13 +82,13 @@ public: \param max_number_of_trees_in_the_forest The maximum number of trees in the forest (surprise, surprise). Typically the more trees you have the better the accuracy. However, the improvement in accuracy generally diminishes and asymptotes pass a certain number of trees. Also to keep in mind, the number of tree increases the prediction time linearly. \param forest_accuracy Sufficient accuracy (OOB error). */ - OpenCV_random_forest_classifier (const Label_set& labels, - const Feature_set& features, - int max_depth = 20, - int min_sample_count = 5, - int max_categories = 15, - int max_number_of_trees_in_the_forest = 100, - float forest_accuracy = 0.01f) + Random_forest_classifier (const Label_set& labels, + const Feature_set& features, + int max_depth = 20, + int min_sample_count = 5, + int max_categories = 15, + int max_number_of_trees_in_the_forest = 100, + float forest_accuracy = 0.01f) : m_labels (labels), m_features (features), m_max_depth (max_depth), m_min_sample_count (min_sample_count), m_max_categories (max_categories), @@ -98,7 +100,7 @@ public: { } /// \cond SKIP_IN_MANUAL - ~OpenCV_random_forest_classifier () + ~Random_forest_classifier () { #if (CV_MAJOR_VERSION < 3) if (rtree != NULL) @@ -298,6 +300,13 @@ public: } +/// \cond SKIP_IN_MANUAL +// Backward compatibility +typedef OpenCV::Random_forest_classifier OpenCV_random_forest_classifier; +/// \endcond + +} + } #endif // CGAL_CLASSIFICATION_OPENCV_RANDOM_FOREST_CLASSIFIER_H diff --git a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h similarity index 98% rename from Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h rename to Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h index 99870bb49d2..23b0e473998 100644 --- a/Classification/include/CGAL/Classification/TensorFlow_neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h @@ -47,11 +47,13 @@ namespace CGAL { namespace Classification { +namespace TensorFlow { + namespace TF = tensorflow; namespace TFops = tensorflow::ops; /*! - \ingroup PkgClassificationClassifiers + \ingroup PkgClassificationClassifiersTensorFlow \brief %Classifier based on the TensorFlow version of neural network. @@ -81,7 +83,7 @@ namespace TFops = tensorflow::ops; \cgalModels `CGAL::Classification::Classifier` */ template -class TensorFlow_neural_network_classifier +class Neural_network_classifier { bool m_verbose; @@ -123,14 +125,14 @@ public: \brief Instantiate the classifier using the sets of `labels` and `features`. */ - TensorFlow_neural_network_classifier (const Label_set& labels, - const Feature_set& features) + Neural_network_classifier (const Label_set& labels, + const Feature_set& features) : m_verbose (true), m_labels (labels), m_features (features) , m_root (NULL), m_ph_ft (NULL), m_ph_gt (NULL), m_loss(NULL), m_session (NULL) { } /// \cond SKIP_IN_MANUAL - ~TensorFlow_neural_network_classifier () + ~Neural_network_classifier () { clear(); } @@ -1014,7 +1016,7 @@ template void classify (const ItemRange& input, const Label_set& labels, - const TensorFlow_neural_network_classifier& classifier, + const TensorFlow::Neural_network_classifier& classifier, LabelIndexRange& output, ProbabilitiesRanges& probabilities) { @@ -1067,7 +1069,7 @@ template void classify (const ItemRange& input, const Label_set& labels, - const TensorFlow_neural_network_classifier& classifier, + const TensorFlow::Neural_network_classifier& classifier, LabelIndexRange& output) { std::cerr << "Classify with TensorFlow classifier" << std::endl; @@ -1113,6 +1115,7 @@ void classify (const ItemRange& input, } +} } diff --git a/Classification/test/Classification/test_classification_io.cpp b/Classification/test/Classification/test_classification_io.cpp index a9c9173d7b6..83e782eb09d 100644 --- a/Classification/test/Classification/test_classification_io.cpp +++ b/Classification/test/Classification/test_classification_io.cpp @@ -28,7 +28,7 @@ typedef Classification::Feature_handle typedef Classification::Label_set Label_set; typedef Classification::Feature_set Feature_set; -typedef Classification::ETHZ_random_forest_classifier Classifier; +typedef Classification::ETHZ::Random_forest_classifier Classifier; typedef Classification::Planimetric_grid Planimetric_grid; typedef Classification::Point_set_neighborhood Neighborhood; diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 9c7412416b2..bd978699d16 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -35,13 +35,17 @@ Release date: March 2019 ### Classification - Added a new experimental classifier - `TensorFlow_neural_network_classifier`. + `TensorFlow::Neural_network_classifier`. -- The training algorithm of `ETHZ_random_forest_classifier` was +- For uniformity, `ETHZ_random_forest_classifier` is renamed + `ETHZ::Random_forest_classifier` and `OpenCV_random_forest_classifier` + is renamed `OpenCV::Random_forest_classifier`. + +- The training algorithm of `ETHZ::Random_forest_classifier` was parallelized. -- Added a constructor to copy a `ETHZ_random_forest_classifier` - using a different data set as input. +- Added a constructor to copy a `ETHZ::Random_forest_classifier` using a + different data set as input. - Added 3 new geometric features, `Height_above`, `Height_below` and `Vertical_range`. diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 6622d7ab645..6aa645c828a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -11,13 +11,13 @@ #include #include #include -#include +#include #ifdef CGAL_LINKED_WITH_OPENCV -#include +#include #endif #ifdef CGAL_LINKED_WITH_TENSORFLOW -#include +#include #endif class Item_classification_base @@ -28,13 +28,13 @@ public: typedef CGAL::Classification::Label_set Label_set; typedef CGAL::Classification::Feature_set Feature_set; typedef CGAL::Classification::Sum_of_weighted_features_classifier Sum_of_weighted_features; - typedef CGAL::Classification::ETHZ_random_forest_classifier ETHZ_random_forest; + typedef CGAL::Classification::ETHZ::Random_forest_classifier ETHZ_random_forest; #ifdef CGAL_LINKED_WITH_OPENCV - typedef CGAL::Classification::OpenCV_random_forest_classifier Random_forest; + typedef CGAL::Classification::OpenCV::Random_forest_classifier Random_forest; #endif #ifdef CGAL_LINKED_WITH_TENSORFLOW - typedef CGAL::Classification::TensorFlow_neural_network_classifier<> Neural_network; + typedef CGAL::Classification::TensorFlow::Neural_network_classifier<> Neural_network; #endif public: From dc9d52f4854314c9e5050e874b6c428d39ca496a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 10 Jan 2019 11:08:56 +0100 Subject: [PATCH 103/186] Update filename in whitelisted headers --- Installation/cmake/modules/list_of_whitelisted_headers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/cmake/modules/list_of_whitelisted_headers.cmake b/Installation/cmake/modules/list_of_whitelisted_headers.cmake index 55550e4663d..c9a2155e50f 100644 --- a/Installation/cmake/modules/list_of_whitelisted_headers.cmake +++ b/Installation/cmake/modules/list_of_whitelisted_headers.cmake @@ -1,5 +1,5 @@ set(list_of_whitelisted_headers_txt [=[ - CGAL/Classification/TensorFlow_neural_network_classifier.h + CGAL/Classification/TensorFlow/Neural_network_classifier.h CGAL/Linear_cell_complex_constructors.h CGAL/CGAL_Ipelet_base.h CGAL/IO/read_las_points.h From 82b935d586866ca95c56ecf5168f9f2927aa1aa4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 10 Jan 2019 11:21:01 +0100 Subject: [PATCH 104/186] Fix selection when mesh item is selected. --- .../PMP/Scene_facegraph_item_k_ring_selection.h | 6 ++++++ .../Scene_polyhedron_item_decorator.cpp | 16 +++++----------- Polyhedron/demo/Polyhedron/Viewer.cpp | 2 ++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h b/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h index 318663f2e65..86747634b0f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h @@ -134,6 +134,8 @@ public Q_SLOTS: // slots are called by signals of polyhedron_item void vertex_has_been_selected(void* void_ptr) { + if((*CGAL::QGLViewer::QGLViewerPool().begin())->property("performing_selection").toBool()) + return; is_active=true; if(active_handle_type == Active_handle::VERTEX || active_handle_type == Active_handle::PATH) { @@ -145,6 +147,8 @@ public Q_SLOTS: } void facet_has_been_selected(void* void_ptr) { + if((*CGAL::QGLViewer::QGLViewerPool().begin())->property("performing_selection").toBool()) + return; is_active=true; if (active_handle_type == Active_handle::FACET || active_handle_type == Active_handle::CONNECTED_COMPONENT) @@ -157,6 +161,8 @@ public Q_SLOTS: } void edge_has_been_selected(void* void_ptr) { + if((*CGAL::QGLViewer::QGLViewerPool().begin())->property("performing_selection").toBool()) + return; is_active=true; if(active_handle_type == Active_handle::EDGE) { diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item_decorator.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item_decorator.cpp index b756c37ea46..aec0f873302 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item_decorator.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item_decorator.cpp @@ -70,18 +70,12 @@ Scene_polyhedron_item_decorator::select(double orig_x, double dir_y, double dir_z) { - Scene_item::select(orig_x, - orig_y, - orig_z, - dir_x, - dir_y, - dir_z); poly_item->select(orig_x, - orig_y, - orig_z, - dir_x, - dir_y, - dir_z); + orig_y, + orig_z, + dir_x, + dir_y, + dir_z); } Scene_face_graph_item* Scene_polyhedron_item_decorator::polyhedron_item() const { diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 34bbe50768c..bcd056e6331 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -747,8 +747,10 @@ void Viewer::postSelection(const QPoint& pixel) orig = camera()->position() - offset(); dir = point - orig; } + this->setProperty("performing_selection", true); Q_EMIT selectionRay(orig.x, orig.y, orig.z, dir.x, dir.y, dir.z); + this->setProperty("performing_selection", false); } } bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame) From 92b87281eae816efd083d84b6e8d6135e412c37c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 10 Jan 2019 11:27:59 +0100 Subject: [PATCH 105/186] Fix selection crash for non triangle meshes --- Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index d973524109e..44a96be7bb3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -777,7 +777,8 @@ public Q_SLOTS: bool is_valid = true; BOOST_FOREACH(boost::graph_traits::face_descriptor fd, faces(*selection_item->polyhedron())) { - if (CGAL::Polygon_mesh_processing::is_degenerate_triangle_face(fd, *selection_item->polyhedron())) + if (is_triangle(halfedge(fd, *selection_item->polyhedron()), *selection_item->polyhedron()) + && CGAL::Polygon_mesh_processing::is_degenerate_triangle_face(fd, *selection_item->polyhedron())) { is_valid = false; break; From a11f6562c6ce59916e2f36802ffec934d7072a76 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 11 Jan 2019 10:47:34 +0100 Subject: [PATCH 106/186] Support Qt-5.12: qcollectiongenerator merged into qhelpgenerator --- .../Periodic_3_triangulation_3/CMakeLists.txt | 19 ++++++++++--------- .../demo/Periodic_Lloyd_3/CMakeLists.txt | 11 ++++++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/CMakeLists.txt b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/CMakeLists.txt index ed5aad38c95..ea79ae56227 100644 --- a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/CMakeLists.txt +++ b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/CMakeLists.txt @@ -22,7 +22,13 @@ if(Qt5_FOUND) add_definitions(-DQT_NO_KEYWORDS) endif(Qt5_FOUND) -if (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET Qt5::qcollectiongenerator) +if( Qt5Help_VERSION VERSION_LESS 5.12 ) + set(CGAL_QCOLLECTIONGENERATOR_TARGET Qt5::qcollectiongenerator) +else() + set(CGAL_QCOLLECTIONGENERATOR_TARGET Qt5::qhelpgenerator) +endif() + +if (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET ${CGAL_QCOLLECTIONGENERATOR_TARGET}) # UI files (Qt Designer files) qt5_wrap_ui ( UI_FILES MainWindow.ui ) @@ -35,15 +41,10 @@ if (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET Qt5::qcollectiongener qt5_generate_moc( "MainWindow.h" "${CMAKE_CURRENT_BINARY_DIR}/moc_MainWindow.cpp" ) qt5_generate_moc( "Viewer.h" "${CMAKE_CURRENT_BINARY_DIR}/moc_Viewer.cpp" ) - if(DEFINED QT_QCOLLECTIONGENERATOR_EXECUTABLE) - else() - set(QT_QCOLLECTIONGENERATOR_EXECUTABLE qcollectiongenerator) - endif() - # generate QtAssistant collection file add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Periodic_3_triangulation_3.qhc DEPENDS Periodic_3_triangulation_3.qhp Periodic_3_triangulation_3.qhcp - COMMAND Qt5::qcollectiongenerator + COMMAND ${CGAL_QCOLLECTIONGENERATOR_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/Periodic_3_triangulation_3.qhcp -o ${CMAKE_CURRENT_BINARY_DIR}/Periodic_3_triangulation_3.qhc ) @@ -80,8 +81,8 @@ else () set(PERIODIC_TRIANGULATION_MISSING_DEPS "Qt5, ${PERIODIC_TRIANGULATION_MISSING_DEPS}") endif() - if (NOT TARGET Qt5::qcollectiongenerator) - set(PERIODIC_TRIANGULATION_MISSING_DEPS "qcollectiongenerator, ${PERIODIC_TRIANGULATION_MISSING_DEPS}") + if (NOT TARGET ${CGAL_QCOLLECTIONGENERATOR_TARGET}) + set(PERIODIC_TRIANGULATION_MISSING_DEPS "${CGAL_QCOLLECTIONGENERATOR_TARGET}, ${PERIODIC_TRIANGULATION_MISSING_DEPS}") endif() message(STATUS "NOTICE: This demo requires ${PERIODIC_TRIANGULATION_MISSING_DEPS}and will not be compiled.") diff --git a/Periodic_3_triangulation_3/demo/Periodic_Lloyd_3/CMakeLists.txt b/Periodic_3_triangulation_3/demo/Periodic_Lloyd_3/CMakeLists.txt index d711a8dd6c7..540eb1bbce8 100644 --- a/Periodic_3_triangulation_3/demo/Periodic_Lloyd_3/CMakeLists.txt +++ b/Periodic_3_triangulation_3/demo/Periodic_Lloyd_3/CMakeLists.txt @@ -23,8 +23,13 @@ include(${CGAL_USE_FILE}) find_package(Qt5 QUIET COMPONENTS Xml Script Help OpenGL Svg) +if( Qt5Help_VERSION VERSION_LESS 5.12 ) + set(CGAL_QCOLLECTIONGENERATOR_TARGET Qt5::qcollectiongenerator) +else() + set(CGAL_QCOLLECTIONGENERATOR_TARGET Qt5::qhelpgenerator) +endif() -if ( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET Qt5::qcollectiongenerator ) +if ( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET ${CGAL_QCOLLECTIONGENERATOR_TARGET} ) include_directories (BEFORE ../../include ./ ) @@ -43,7 +48,7 @@ if ( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET Qt5::qcollectiongene # generate QtAssistant collection file add_custom_command ( OUTPUT Periodic_Lloyd_3.qhc DEPENDS Periodic_Lloyd_3.qhp Periodic_Lloyd_3.qhcp - COMMAND Qt5::qcollectiongenerator + COMMAND ${CGAL_QCOLLECTIONGENERATOR_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/Periodic_Lloyd_3.qhcp -o ${CMAKE_CURRENT_BINARY_DIR}/Periodic_Lloyd_3.qhc WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -71,7 +76,7 @@ else( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND QT_QCOLLECTIONGENERATOR_EX endif() if(NOT QT_QCOLLECTIONGENERATOR_EXECUTABLE) - set(PERIODIC_LLOYD_MISSING_DEPS "qcollectiongenerator, ${PERIODIC_LLOYD_MISSING_DEPS}") + set(PERIODIC_LLOYD_MISSING_DEPS "${CGAL_QCOLLECTIONGENERATOR_TARGET}, ${PERIODIC_LLOYD_MISSING_DEPS}") endif() From 0c551f93f697ae2dff08976d4b05e93e840f385c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 11 Jan 2019 10:56:59 +0100 Subject: [PATCH 107/186] Make static functions for message_interface stuff. --- .../Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp | 4 ++-- .../Polyhedron/Plugins/IO/Nef_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/OFF_io_plugin.cpp | 2 +- .../Plugins/IO/OFF_to_nef_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/PLY_io_plugin.cpp | 2 +- .../Plugins/IO/Polylines_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/STL_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/Surf_io_plugin.cpp | 2 +- .../Plugins/IO/Surface_mesh_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/XYZ_io_plugin.cpp | 2 +- .../Plugins/Mesh_3/C3t3_io_plugin.cpp | 2 +- .../Plugins/PMP/Selection_plugin.cpp | 4 ++-- Polyhedron/demo/Polyhedron/Three.cpp | 19 +++++++++++++++---- Three/include/CGAL/Three/Three.h | 10 +++++++++- 15 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp index 5409475d32a..c9ff6d6f82e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp @@ -77,7 +77,7 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) { Scene_polyhedron_item* item = new Scene_polyhedron_item(Polyhedron()); if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); return item; } Polyhedron& P = * const_cast(item->polyhedron()); @@ -111,7 +111,7 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) { Scene_surface_mesh_item* item = new Scene_surface_mesh_item(new SMesh()); if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); return item; } SMesh& P = * const_cast(item->polyhedron()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp index 947a4a88ac0..5285bcce650 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp @@ -50,7 +50,7 @@ Polyhedron_demo_io_nef_plugin::load(QFileInfo fileinfo) { item->setName(fileinfo.baseName()); if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); return item; } if(!item->load(in)) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp index 4ab711cfeab..3df1e05ef73 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp @@ -52,7 +52,7 @@ Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_polyhedron_item* item = new Scene_polyhedron_item(Polyhedron()); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp index eebae8a7393..08e8d8da4fc 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp @@ -36,7 +36,7 @@ Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) { Scene_nef_polyhedron_item* item = new Scene_nef_polyhedron_item(); if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); item->setName(fileinfo.completeBaseName()); return item; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp index b2ae3f10905..30c4fc19e20 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp @@ -82,7 +82,7 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); return 0; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp index ad67e838c42..ffdd20d5e42 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp @@ -103,7 +103,7 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_polylines_item* item = new Scene_polylines_item; item->setName(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp index 7f87f3ee48f..b7ea6653f19 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp @@ -75,7 +75,7 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) { } if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_surface_mesh_item* item = new Scene_surface_mesh_item(); item->setName(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp index 31d6482febd..2f380f0120e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp @@ -77,7 +77,7 @@ CGAL::Three::Scene_item* Surf_io_plugin::actual_load(QFileInfo fileinfo) if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_group_item* item = new Scene_group_item(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp index 3075b635862..87ededc3d3c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp @@ -64,7 +64,7 @@ public: SMesh *surface_mesh = new SMesh(); if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_surface_mesh_item* item = new Scene_surface_mesh_item(surface_mesh); item->setName(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 8d5f8ed72df..e326b9f6bea 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -367,7 +367,7 @@ public: if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_facegraph_item* item = new Scene_facegraph_item(poly); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp index 88aca74fafb..4b782baa89c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp @@ -46,7 +46,7 @@ Polyhedron_demo_xyz_plugin::load(QFileInfo fileinfo) if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); Scene_points_with_normal_item* item = new Scene_points_with_normal_item(); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 4f9161787df..b7b44fd6a46 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -70,7 +70,7 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::messages()->warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); item->setName(fileinfo.completeBaseName()); return item; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index 51290afe60e..ccc5dbf1bb9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -2,7 +2,6 @@ #include -#include "Messages_interface.h" #ifdef USE_SURFACE_MESH #include "Kernel_type.h" #include "Scene_surface_mesh_item.h" @@ -14,6 +13,7 @@ #include "Scene_polylines_item.h" #include +#include #include #include "ui_Selection_widget.h" @@ -84,7 +84,7 @@ public: return qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::s_information(message); } QList actions() const { return QList() << actionSelection; } void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m) { diff --git a/Polyhedron/demo/Polyhedron/Three.cpp b/Polyhedron/demo/Polyhedron/Three.cpp index ae5b0f0dc2e..e38d78b0422 100644 --- a/Polyhedron/demo/Polyhedron/Three.cpp +++ b/Polyhedron/demo/Polyhedron/Three.cpp @@ -3,6 +3,8 @@ #include #include #include +#include "Messages_interface.h" + using namespace CGAL::Three; QMainWindow* Three::s_mainwindow = NULL; @@ -25,10 +27,6 @@ QObject* Three::connectableScene() return s_connectable_scene; } -Three* Three::messages() -{ - return s_three; -} Three::Three() { @@ -130,3 +128,16 @@ void Three::autoConnectActions(Polyhedron_demo_plugin_interface *plugin) action->objectName().toUtf8().data()); } // end foreach action of actions() } + +void Three::s_information(QString s) +{ + qobject_cast(mainWindow())->information(s); +} +void Three::s_warning(QString s) +{ + qobject_cast(mainWindow())->warning(s); +} +void Three::s_error(QString s) +{ + qobject_cast(mainWindow())->error(s); +} diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 6abe97dbb85..5989a9037a0 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -47,7 +47,6 @@ public: static QMainWindow* mainWindow(); static Scene_interface* scene(); static QObject* connectableScene(); - static Three* messages(); /*! * Displays a text preceded by the mention "INFO :". @@ -82,6 +81,15 @@ public: * in the plugin. */ static void autoConnectActions(CGAL::Three::Polyhedron_demo_plugin_interface* plugin); + static void s_information(QString); + /*! + * Displays a blue text preceded by the mention "WARNING :". + */ + static void s_warning(QString); + /*! + * Displays a red text preceded by the mention "ERROR :". + */ + static void s_error(QString); protected: static QMainWindow* s_mainwindow; static Scene_interface* s_scene; From 830f3ce27973f1a3d3e7f53ca5a1d55b366b81d9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 11 Jan 2019 12:02:14 +0100 Subject: [PATCH 108/186] Fix segfault when item could not be read. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 9f164a121a1..36b38197167 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1199,8 +1199,9 @@ bool MainWindow::open(QString filename, QString loader_name) { CGAL::Three::Scene_item* MainWindow::loadItem(QFileInfo fileinfo, CGAL::Three::Polyhedron_demo_io_plugin_interface* loader) { CGAL::Three::Scene_item* item = NULL; if(!fileinfo.isFile() || !fileinfo.isReadable()) { - throw std::invalid_argument(QString("File %1 is not a readable file.") - .arg(fileinfo.absoluteFilePath()).toStdString()); + QMessageBox::warning(this, tr("Error"), + QString("File %1 is not a readable file.") + .arg(fileinfo.absoluteFilePath())); } //test if the file is empty. if(fileinfo.size() == 0) { @@ -1213,8 +1214,10 @@ CGAL::Three::Scene_item* MainWindow::loadItem(QFileInfo fileinfo, CGAL::Three::P item = loader->load(fileinfo); QApplication::restoreOverrideCursor(); if(!item) { - throw std::logic_error(QString("Could not load item from file %1 using plugin %2") - .arg(fileinfo.absoluteFilePath()).arg(loader->name()).toStdString()); + QMessageBox::warning(this, tr("Error"), + QString("Could not load item from file %1 using plugin %2") + .arg(fileinfo.absoluteFilePath()).arg(loader->name())); + return 0; } item->setProperty("source filename", fileinfo.absoluteFilePath()); From 28ce2a5240e432f5845a33ad9ee1dff0c29d550d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 11 Jan 2019 12:29:40 +0100 Subject: [PATCH 109/186] Fixed stack order in non recursive conflict walking Edges must be output in a CCW order, which is achieved by walking ccw-ly first. In the recursive function, we correctly call 'propagate(..., ccw(j))' first. For the non-recursive version which uses a stack, then we must add 'ccw(j)' last since the stack is a LIFO structure. --- Triangulation_2/include/CGAL/Delaunay_triangulation_2.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index bf45a49f793..ad22e75d9ca 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -503,8 +503,11 @@ private: } else { *(pit.first)++ = fn; int j = fn->index(fh); - stack.push(std::make_pair(fn,ccw(j))); + + // In the non-recursive version, we walk via 'ccw(j)' first. Here, we are filling the stack + // and the order is thus the opposite (we want the last element of the stack to be 'ccw(j)') stack.push(std::make_pair(fn,cw(j))); + stack.push(std::make_pair(fn,ccw(j))); } } return pit; From 04f3ad63fa1b453c3f6386914530ba9a14bbbec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 11 Jan 2019 12:33:16 +0100 Subject: [PATCH 110/186] Added some sanity tests for the T2 find_conflict functions --- .../CGAL/_test_cls_delaunay_triangulation_2.h | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h index 97419a8cc71..c55597c89a4 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h @@ -20,20 +20,21 @@ // coordinator : INRIA Sophia-Antipolis // ============================================================================ -#include -#include -//#include #include +#include +#include +#include +#include +#include #include -using std::rand; +using std::rand; template void _test_delaunay_duality( const Del &T ); - template void _test_cls_delaunay_triangulation_2( const Del & ) @@ -136,14 +137,58 @@ _test_cls_delaunay_triangulation_2( const Del & ) // test insertion through get_conflicts + star_hole conflicts.clear(); hole_bd.clear(); - T2.get_conflicts_and_boundary(Point(1,1,2), - std::back_inserter(conflicts), - std::back_inserter(hole_bd)); + Point query(1,1,2); + T2.get_conflicts_and_boundary(query, + std::back_inserter(conflicts), + std::back_inserter(hole_bd)); + + // check the sanity of the boundary (faces are not in conflict && edges are ccw ordered) + typename std::list::iterator curr = hole_bd.begin(), last = --(hole_bd.end()); + Vertex_handle prev_vh = last->first->vertex(T2.ccw(last->second)); + do + { + assert(curr->first->vertex(T2.cw(curr->second)) == prev_vh); + assert(!T2.test_conflict(query, curr->first)); + prev_vh = curr->first->vertex(T2.ccw(curr->second)); + ++curr; + } + while(curr != hole_bd.end()); + T2.star_hole (Point(1,1,2), hole_bd.begin(), hole_bd.end(), conflicts.begin(), conflicts.end() ); assert(T2.is_valid()); - + + // check get_conflict for a large enough point set (to use the non-recursive function) + double x, y; + std::vector layer_pts; + + std::ifstream in("data/layers.xyz"); + assert(in); + while(in >> x >> y) + layer_pts.push_back(Point(x, y)); + + Del T2b(layer_pts.begin(), layer_pts.end()); + + conflicts.clear(); + hole_bd.clear(); + + query = Point(12.25, 0.031250); + T2b.get_conflicts_and_boundary(query, + std::back_inserter(conflicts), + std::back_inserter(hole_bd)); + + // check the sanity of the boundary (faces are not in conflict && edges are ccw ordered) + curr = hole_bd.begin(), last = --(hole_bd.end()); + prev_vh = last->first->vertex(T2b.ccw(last->second)); + do + { + assert(curr->first->vertex(T2b.cw(curr->second)) == prev_vh); + assert(!T2b.test_conflict(query, curr->first)); + prev_vh = curr->first->vertex(T2b.ccw(curr->second)); + ++curr; + } + while(curr != hole_bd.end()); /********************/ /***** Duality ******/ From 502c28796d23daf199efd3936b2ad12ac5337124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 11 Jan 2019 13:56:06 +0100 Subject: [PATCH 111/186] Clarify 'last' ==> 'top' --- Triangulation_2/include/CGAL/Delaunay_triangulation_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index ad22e75d9ca..24b205a4cac 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -505,7 +505,7 @@ private: int j = fn->index(fh); // In the non-recursive version, we walk via 'ccw(j)' first. Here, we are filling the stack - // and the order is thus the opposite (we want the last element of the stack to be 'ccw(j)') + // and the order is thus the opposite (we want the top element of the stack to be 'ccw(j)') stack.push(std::make_pair(fn,cw(j))); stack.push(std::make_pair(fn,ccw(j))); } From 1e27cfba44ee22b7b88f3b870d9ad5c528ff4d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 11 Jan 2019 14:33:56 +0100 Subject: [PATCH 112/186] Add layers.xy data file for T2 tests --- .../test/Triangulation_2/data/layers.xy | 502 ++++++++++++++++++ .../CGAL/_test_cls_delaunay_triangulation_2.h | 2 +- 2 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 Triangulation_2/test/Triangulation_2/data/layers.xy diff --git a/Triangulation_2/test/Triangulation_2/data/layers.xy b/Triangulation_2/test/Triangulation_2/data/layers.xy new file mode 100644 index 00000000000..1207d7eeb95 --- /dev/null +++ b/Triangulation_2/test/Triangulation_2/data/layers.xy @@ -0,0 +1,502 @@ +10 0 +10 0.01 +10 0.02 +10 0.029999999999999999 +10 0.040000000000000001 +10 0.050000000000000003 +10 0.059999999999999998 +10 0.070000000000000007 +10 0.080000000000000002 +10 0.089999999999999997 +10 0.10000000000000001 +10 0.11 +10 0.12 +10 0.13 +10 0.14000000000000001 +10 0.14999999999999999 +10 0.16 +10 0.17000000000000001 +10 0.17999999999999999 +10 0.19 +10 0.20000000000000001 +10 0.20999999999999999 +10 0.22 +10 0.23000000000000001 +10 0.23999999999999999 +10 0.25 +10 0.26000000000000001 +10 0.27000000000000002 +10 0.28000000000000003 +10 0.28999999999999998 +10 0.29999999999999999 +10 0.31 +10 0.32000000000000001 +10 0.33000000000000002 +10 0.34000000000000002 +10 0.34999999999999998 +10 0.35999999999999999 +10 0.37 +10 0.38 +10 0.39000000000000001 +10 0.40000000000000002 +10 0.40999999999999998 +10 0.41999999999999998 +10 0.42999999999999999 +10 0.44 +10 0.45000000000000001 +10 0.46000000000000002 +10 0.46999999999999997 +10 0.47999999999999998 +10 0.48999999999999999 +10 0.5 +10 0.51000000000000001 +10 0.52000000000000002 +10 0.53000000000000003 +10 0.54000000000000004 +10 0.55000000000000004 +10 0.56000000000000005 +10 0.56999999999999995 +10 0.57999999999999996 +10 0.58999999999999997 +10 0.59999999999999998 +10 0.60999999999999999 +10 0.62 +10 0.63 +10 0.64000000000000001 +10 0.65000000000000002 +10 0.66000000000000003 +10 0.67000000000000004 +10 0.68000000000000005 +10 0.68999999999999995 +10 0.69999999999999996 +10 0.70999999999999996 +10 0.71999999999999997 +10 0.72999999999999998 +10 0.73999999999999999 +10 0.75 +10 0.76000000000000001 +10 0.77000000000000002 +10 0.78000000000000003 +10 0.79000000000000004 +10 0.80000000000000004 +10 0.81000000000000005 +10 0.81999999999999995 +10 0.82999999999999996 +10 0.83999999999999997 +10 0.84999999999999998 +10 0.85999999999999999 +10 0.87 +10 0.88 +10 0.89000000000000001 +10 0.90000000000000002 +10 0.91000000000000003 +10 0.92000000000000004 +10 0.93000000000000005 +10 0.93999999999999995 +10 0.94999999999999996 +10 0.95999999999999996 +10 0.96999999999999997 +10 0.97999999999999998 +10 0.98999999999999999 +10 1 +10 1.01 +10 1.02 +10 1.03 +10 1.04 +10 1.05 +10 1.0600000000000001 +10 1.0700000000000001 +10 1.0800000000000001 +10 1.0900000000000001 +10 1.1000000000000001 +10 1.1100000000000001 +10 1.1200000000000001 +10 1.1299999999999999 +10 1.1399999999999999 +10 1.1499999999999999 +10 1.1599999999999999 +10 1.1699999999999999 +10 1.1799999999999999 +10 1.1899999999999999 +10 1.2 +10 1.21 +10 1.22 +10 1.23 +10 1.24 +10 1.25 +10 1.26 +10 1.27 +10 1.28 +10 1.29 +10 1.3 +10 1.3100000000000001 +10 1.3200000000000001 +10 1.3300000000000001 +10 1.3400000000000001 +10 1.3500000000000001 +10 1.3600000000000001 +10 1.3700000000000001 +10 1.3799999999999999 +10 1.3899999999999999 +10 1.3999999999999999 +10 1.4099999999999999 +10 1.4199999999999999 +10 1.4299999999999999 +10 1.4399999999999999 +10 1.45 +10 1.46 +10 1.47 +10 1.48 +10 1.49 +10 1.5 +10 1.51 +10 1.52 +10 1.53 +10 1.54 +10 1.55 +10 1.5600000000000001 +10 1.5700000000000001 +10 1.5800000000000001 +10 1.5900000000000001 +10 1.6000000000000001 +10 1.6100000000000001 +10 1.6200000000000001 +10 1.6299999999999999 +10 1.6399999999999999 +10 1.6499999999999999 +10 1.6599999999999999 +10 1.6699999999999999 +10 1.6799999999999999 +10 1.6899999999999999 +10 1.7 +10 1.71 +10 1.72 +10 1.73 +10 1.74 +10 1.75 +10 1.76 +10 1.77 +10 1.78 +10 1.79 +10 1.8 +10 1.8100000000000001 +10 1.8200000000000001 +10 1.8300000000000001 +10 1.8400000000000001 +10 1.8500000000000001 +10 1.8600000000000001 +10 1.8700000000000001 +10 1.8799999999999999 +10 1.8899999999999999 +10 1.8999999999999999 +10 1.9099999999999999 +10 1.9199999999999999 +10 1.9299999999999999 +10 1.9399999999999999 +10 1.95 +10 1.96 +10 1.97 +10 1.98 +10 1.99 +10 2 +10 2.0099999999999998 +10 2.02 +10 2.0299999999999998 +10 2.04 +10 2.0499999999999998 +10 2.0600000000000001 +10 2.0699999999999998 +10 2.0800000000000001 +10 2.0899999999999999 +10 2.1000000000000001 +10 2.1099999999999999 +10 2.1200000000000001 +10 2.1299999999999999 +10 2.1400000000000001 +10 2.1499999999999999 +10 2.1600000000000001 +10 2.1699999999999999 +10 2.1800000000000002 +10 2.1899999999999999 +10 2.2000000000000002 +10 2.21 +10 2.2200000000000002 +10 2.23 +10 2.2400000000000002 +10 2.25 +10 2.2599999999999998 +10 2.27 +10 2.2799999999999998 +10 2.29 +10 2.2999999999999998 +10 2.3100000000000001 +10 2.3199999999999998 +10 2.3300000000000001 +10 2.3399999999999999 +10 2.3500000000000001 +10 2.3599999999999999 +10 2.3700000000000001 +10 2.3799999999999999 +10 2.3900000000000001 +10 2.3999999999999999 +10 2.4100000000000001 +10 2.4199999999999999 +10 2.4300000000000002 +10 2.4399999999999999 +10 2.4500000000000002 +10 2.46 +10 2.4700000000000002 +10 2.48 +10 2.4900000000000002 +10 2.5 +20 0 +20 0.01 +20 0.02 +20 0.029999999999999999 +20 0.040000000000000001 +20 0.050000000000000003 +20 0.059999999999999998 +20 0.070000000000000007 +20 0.080000000000000002 +20 0.089999999999999997 +20 0.10000000000000001 +20 0.11 +20 0.12 +20 0.13 +20 0.14000000000000001 +20 0.14999999999999999 +20 0.16 +20 0.17000000000000001 +20 0.17999999999999999 +20 0.19 +20 0.20000000000000001 +20 0.20999999999999999 +20 0.22 +20 0.23000000000000001 +20 0.23999999999999999 +20 0.25 +20 0.26000000000000001 +20 0.27000000000000002 +20 0.28000000000000003 +20 0.28999999999999998 +20 0.29999999999999999 +20 0.31 +20 0.32000000000000001 +20 0.33000000000000002 +20 0.34000000000000002 +20 0.34999999999999998 +20 0.35999999999999999 +20 0.37 +20 0.38 +20 0.39000000000000001 +20 0.40000000000000002 +20 0.40999999999999998 +20 0.41999999999999998 +20 0.42999999999999999 +20 0.44 +20 0.45000000000000001 +20 0.46000000000000002 +20 0.46999999999999997 +20 0.47999999999999998 +20 0.48999999999999999 +20 0.5 +20 0.51000000000000001 +20 0.52000000000000002 +20 0.53000000000000003 +20 0.54000000000000004 +20 0.55000000000000004 +20 0.56000000000000005 +20 0.56999999999999995 +20 0.57999999999999996 +20 0.58999999999999997 +20 0.59999999999999998 +20 0.60999999999999999 +20 0.62 +20 0.63 +20 0.64000000000000001 +20 0.65000000000000002 +20 0.66000000000000003 +20 0.67000000000000004 +20 0.68000000000000005 +20 0.68999999999999995 +20 0.69999999999999996 +20 0.70999999999999996 +20 0.71999999999999997 +20 0.72999999999999998 +20 0.73999999999999999 +20 0.75 +20 0.76000000000000001 +20 0.77000000000000002 +20 0.78000000000000003 +20 0.79000000000000004 +20 0.80000000000000004 +20 0.81000000000000005 +20 0.81999999999999995 +20 0.82999999999999996 +20 0.83999999999999997 +20 0.84999999999999998 +20 0.85999999999999999 +20 0.87 +20 0.88 +20 0.89000000000000001 +20 0.90000000000000002 +20 0.91000000000000003 +20 0.92000000000000004 +20 0.93000000000000005 +20 0.93999999999999995 +20 0.94999999999999996 +20 0.95999999999999996 +20 0.96999999999999997 +20 0.97999999999999998 +20 0.98999999999999999 +20 1 +20 1.01 +20 1.02 +20 1.03 +20 1.04 +20 1.05 +20 1.0600000000000001 +20 1.0700000000000001 +20 1.0800000000000001 +20 1.0900000000000001 +20 1.1000000000000001 +20 1.1100000000000001 +20 1.1200000000000001 +20 1.1299999999999999 +20 1.1399999999999999 +20 1.1499999999999999 +20 1.1599999999999999 +20 1.1699999999999999 +20 1.1799999999999999 +20 1.1899999999999999 +20 1.2 +20 1.21 +20 1.22 +20 1.23 +20 1.24 +20 1.25 +20 1.26 +20 1.27 +20 1.28 +20 1.29 +20 1.3 +20 1.3100000000000001 +20 1.3200000000000001 +20 1.3300000000000001 +20 1.3400000000000001 +20 1.3500000000000001 +20 1.3600000000000001 +20 1.3700000000000001 +20 1.3799999999999999 +20 1.3899999999999999 +20 1.3999999999999999 +20 1.4099999999999999 +20 1.4199999999999999 +20 1.4299999999999999 +20 1.4399999999999999 +20 1.45 +20 1.46 +20 1.47 +20 1.48 +20 1.49 +20 1.5 +20 1.51 +20 1.52 +20 1.53 +20 1.54 +20 1.55 +20 1.5600000000000001 +20 1.5700000000000001 +20 1.5800000000000001 +20 1.5900000000000001 +20 1.6000000000000001 +20 1.6100000000000001 +20 1.6200000000000001 +20 1.6299999999999999 +20 1.6399999999999999 +20 1.6499999999999999 +20 1.6599999999999999 +20 1.6699999999999999 +20 1.6799999999999999 +20 1.6899999999999999 +20 1.7 +20 1.71 +20 1.72 +20 1.73 +20 1.74 +20 1.75 +20 1.76 +20 1.77 +20 1.78 +20 1.79 +20 1.8 +20 1.8100000000000001 +20 1.8200000000000001 +20 1.8300000000000001 +20 1.8400000000000001 +20 1.8500000000000001 +20 1.8600000000000001 +20 1.8700000000000001 +20 1.8799999999999999 +20 1.8899999999999999 +20 1.8999999999999999 +20 1.9099999999999999 +20 1.9199999999999999 +20 1.9299999999999999 +20 1.9399999999999999 +20 1.95 +20 1.96 +20 1.97 +20 1.98 +20 1.99 +20 2 +20 2.0099999999999998 +20 2.02 +20 2.0299999999999998 +20 2.04 +20 2.0499999999999998 +20 2.0600000000000001 +20 2.0699999999999998 +20 2.0800000000000001 +20 2.0899999999999999 +20 2.1000000000000001 +20 2.1099999999999999 +20 2.1200000000000001 +20 2.1299999999999999 +20 2.1400000000000001 +20 2.1499999999999999 +20 2.1600000000000001 +20 2.1699999999999999 +20 2.1800000000000002 +20 2.1899999999999999 +20 2.2000000000000002 +20 2.21 +20 2.2200000000000002 +20 2.23 +20 2.2400000000000002 +20 2.25 +20 2.2599999999999998 +20 2.27 +20 2.2799999999999998 +20 2.29 +20 2.2999999999999998 +20 2.3100000000000001 +20 2.3199999999999998 +20 2.3300000000000001 +20 2.3399999999999999 +20 2.3500000000000001 +20 2.3599999999999999 +20 2.3700000000000001 +20 2.3799999999999999 +20 2.3900000000000001 +20 2.3999999999999999 +20 2.4100000000000001 +20 2.4199999999999999 +20 2.4300000000000002 +20 2.4399999999999999 +20 2.4500000000000002 +20 2.46 +20 2.4700000000000002 +20 2.48 +20 2.4900000000000002 +20 2.5 diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h index c55597c89a4..2204331cfe8 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h @@ -163,7 +163,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) double x, y; std::vector layer_pts; - std::ifstream in("data/layers.xyz"); + std::ifstream in("data/layers.xy"); assert(in); while(in >> x >> y) layer_pts.push_back(Point(x, y)); From 89a571817437c5badb11969b307898f59d997141 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 14 Jan 2019 09:43:26 +0100 Subject: [PATCH 113/186] Change names and use static functions instead of message_interface. --- .../test_minkowski_sum_with_holes.cpp | 3 ++- Polyhedron/demo/Polyhedron/MainWindow.cpp | 6 +++--- Polyhedron/demo/Polyhedron/MainWindow.h | 8 ++++---- .../demo/Polyhedron/Messages_interface.h | 6 +++--- .../Plugins/AABB_tree/Cut_plugin.cpp | 8 ++++---- .../AABB_tree/Do_trees_intersect_plugin.cpp | 2 +- .../Classification/Classification_plugin.cpp | 3 ++- .../Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/Nef_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/OFF_io_plugin.cpp | 2 +- .../Plugins/IO/OFF_to_nef_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/PLY_io_plugin.cpp | 2 +- .../Plugins/IO/Polylines_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/STL_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/Surf_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 2 +- .../Polyhedron/Plugins/IO/XYZ_io_plugin.cpp | 2 +- .../Plugins/Mesh_3/C3t3_io_plugin.cpp | 2 +- .../Plugins/Mesh_3/Io_image_plugin.cpp | 13 +++++++------ .../Plugins/Mesh_3/Mesh_3_plugin.cpp | 3 ++- .../Plugins/Mesh_3/Optimization_plugin.cpp | 3 ++- .../Clip_polyhedron_plugin.cpp | 5 +++-- .../Plugins/PMP/Corefinement_plugin.cpp | 19 ++++++++++--------- .../Plugins/PMP/Distance_plugin.cpp | 3 ++- .../Plugins/PMP/Engrave_text_plugin.cpp | 4 ++-- .../Polyhedron/Plugins/PMP/Extrude_plugin.cpp | 5 +++-- .../Polyhedron/Plugins/PMP/Fairing_plugin.cpp | 3 ++- .../Plugins/PMP/Hole_filling_plugin.cpp | 3 ++- .../PMP/Hole_filling_polyline_plugin.cpp | 3 ++- .../PMP/Join_and_split_polyhedra_plugin.cpp | 3 ++- .../Plugins/PMP/Orient_soup_plugin.cpp | 7 ++++--- .../PMP/Point_inside_polyhedron_plugin.cpp | 4 ++-- .../Plugins/PMP/Polyhedron_slicer_plugin.cpp | 3 ++- .../Plugins/PMP/Repair_polyhedron_plugin.cpp | 17 +++++++++-------- .../Plugins/PMP/Selection_plugin.cpp | 2 +- .../PMP/Surface_intersection_plugin.cpp | 5 +++-- .../Plugins/PMP/Triangulate_facets_plugin.cpp | 5 +++-- .../Point_set/Point_set_selection_plugin.cpp | 5 +++-- .../Point_set_to_mesh_distance_plugin.cpp | 3 ++- .../Point_set/Point_set_upsampling_plugin.cpp | 3 ++- .../Subdivision_methods_plugin.cpp | 17 +++++++++-------- .../Surface_mesh/Parameterization_plugin.cpp | 7 ++++--- .../Scene_polyhedron_shortest_path_item.cpp | 13 +++++++------ .../Surface_mesh/Shortest_path_plugin.cpp | 9 +++++---- Polyhedron/demo/Polyhedron/Three.cpp | 12 ++++++------ Three/include/CGAL/Three/Three.h | 6 +++--- 46 files changed, 134 insertions(+), 109 deletions(-) diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp index c887fef70e5..c4c887ab209 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp @@ -178,7 +178,8 @@ int main(int argc, char* argv[]) ++i; continue; } - + std::vector* crash = nullptr; + crash->push_back(0); std::cout << "Testing " << argv[i] << " + " << argv[i+1] << std::endl; if (!read_polygon(argv[i], p)) return -1; if (!read_polygon(argv[i+1], q)) return -1; diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 2957dca52a7..b173686af19 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -893,17 +893,17 @@ void MainWindow::message(QString message, QString colorName, QString font) { ui->consoleTextEdit->verticalScrollBar()->setValue(ui->consoleTextEdit->verticalScrollBar()->maximum()); } -void MainWindow::information(QString text) { +void MainWindow::message_information(QString text) { statusBar()->setStyleSheet("color: blue"); this->message("INFO: " + text, "blue"); } -void MainWindow::warning(QString text) { +void MainWindow::message_warning(QString text) { statusBar()->setStyleSheet("color: orange"); this->message("WARNING: " + text, "orange"); } -void MainWindow::error(QString text) { +void MainWindow::message_error(QString text) { statusBar()->setStyleSheet("color: red"); this->message("ERROR: " + text, "red"); } diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 4446b926bf3..394d75546cf 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -220,15 +220,15 @@ public Q_SLOTS: /*! * Displays a text preceded by the mention "INFO :". */ - void information(QString) Q_DECL_OVERRIDE; + void message_information(QString) Q_DECL_OVERRIDE; /*! * Displays a blue text preceded by the mention "WARNING :". */ - void warning(QString) Q_DECL_OVERRIDE; + void message_warning(QString) Q_DECL_OVERRIDE; /*! * Displays a red text preceded by the mention "ERROR :". */ - void error(QString) Q_DECL_OVERRIDE; + void message_error(QString) Q_DECL_OVERRIDE; //!Displays a text in the chosen html color with the chosen html font. @@ -418,7 +418,7 @@ private: QAction* actionAddToGroup; QAction* actionResetDefaultLoaders; CGAL::Three::Three* three; - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { messages->message_information(message); } Messages_interface* messages; QDialog *statistics_dlg; diff --git a/Polyhedron/demo/Polyhedron/Messages_interface.h b/Polyhedron/demo/Polyhedron/Messages_interface.h index 3c8e8dc51e9..cec5ef3f655 100644 --- a/Polyhedron/demo/Polyhedron/Messages_interface.h +++ b/Polyhedron/demo/Polyhedron/Messages_interface.h @@ -7,9 +7,9 @@ class Messages_interface { public: virtual ~Messages_interface() {} - virtual void warning(QString) = 0; - virtual void error(QString) = 0; - virtual void information(QString) = 0; + virtual void message_warning(QString) = 0; + virtual void message_error(QString) = 0; + virtual void message_information(QString) = 0; }; Q_DECLARE_INTERFACE(Messages_interface, diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp index 71dd2874115..446a2322d0f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp @@ -47,7 +47,7 @@ std::size_t last; }; #endif // CGAL_LINKED_WITH_TBB - +#include typedef CGAL::Simple_cartesian Simple_kernel; typedef Simple_kernel::FT FT; typedef Simple_kernel::Point_3 Point; @@ -1193,12 +1193,12 @@ void Polyhedron_demo_cut_plugin::apply(Item* item, QMap< QObject*, Facets_tree*> const Mesh& mesh = *item->polyhedron(); if(!CGAL::is_triangle_mesh(mesh)) { - messages->warning(QString("%1 ignored (not a triangulated mesh)").arg(item->name())); + CGAL::Three::Three::warning(QString("%1 ignored (not a triangulated mesh)").arg(item->name())); return; } if(!CGAL::is_closed(mesh)) { - messages->warning(QString("%1 is not closed. Signed function will not be displayed.").arg(item->name())); + CGAL::Three::Three::warning(QString("%1 is not closed. Signed function will not be displayed.").arg(item->name())); } if(f_trees.find(item) == f_trees.end()) { PPMAP pmap(item->polyhedron()); @@ -1392,7 +1392,7 @@ void Polyhedron_demo_cut_plugin::computeIntersection() } } if(does_intersect) - messages->information(QString("cut (%1 ms). %2 edges.").arg(time.elapsed()).arg(edges_item->edges.size())); + CGAL::Three::Three::information(QString("cut (%1 ms). %2 edges.").arg(time.elapsed()).arg(edges_item->edges.size())); edges_item->invalidateOpenGLBuffers(); edges_item->itemChanged(); ready_to_cut = false; diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp index 91cef460b95..cae964740a6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Do_trees_intersect_plugin.cpp @@ -140,7 +140,7 @@ private Q_SLOTS: static_cast( CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this); QApplication::restoreOverrideCursor(); - messageInterface->information("Press `W` to switch between Wireframe and Transparency mode."); + CGAL::Three::Three::information("Press `W` to switch between Wireframe and Transparency mode."); } public Q_SLOTS: diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 45e5fdfaf87..2d3edcb1796 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -129,7 +130,7 @@ public: qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionClassification; } using Polyhedron_demo_plugin_helper::init; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp index 786cc6f1341..caae0705b5c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/GOCAD_io_plugin.cpp @@ -73,7 +73,7 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) { Scene_surface_mesh_item* item = new Scene_surface_mesh_item(new SMesh()); if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); return item; } SMesh& P = * const_cast(item->polyhedron()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp index ca13a2f89f1..11265427374 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Nef_io_plugin.cpp @@ -50,7 +50,7 @@ Polyhedron_demo_io_nef_plugin::load(QFileInfo fileinfo) { item->setName(fileinfo.baseName()); if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); return item; } if(!item->load(in)) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp index 8c32c5eb511..c0e57fe50e2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp @@ -53,7 +53,7 @@ Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_surface_mesh_item* item = new Scene_surface_mesh_item(SMesh()); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp index 0cd4bc33dd2..5d142129b4c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_to_nef_io_plugin.cpp @@ -36,7 +36,7 @@ Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) { Scene_nef_polyhedron_item* item = new Scene_nef_polyhedron_item(); if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); item->setName(fileinfo.completeBaseName()); return item; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp index 7dff4d962f6..3725e3e93df 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp @@ -81,7 +81,7 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); return 0; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp index ff96bc3e8f6..6cd47d92aa8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Polylines_io_plugin.cpp @@ -103,7 +103,7 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_polylines_item* item = new Scene_polylines_item; item->setName(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp index 76bcbe01263..18749766763 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp @@ -74,7 +74,7 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) { } if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_surface_mesh_item* item = new Scene_surface_mesh_item(); item->setName(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp index c38b28af40f..2302cfe4182 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp @@ -72,7 +72,7 @@ CGAL::Three::Scene_item* Surf_io_plugin::actual_load(QFileInfo fileinfo) if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_group_item* item = new Scene_group_item(fileinfo.completeBaseName()); return item; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 5ad012f3080..c5cbd68a15e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -353,7 +353,7 @@ public: if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_facegraph_item* item = new Scene_facegraph_item(poly); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp index e339f5222e1..7bed8af9e55 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/XYZ_io_plugin.cpp @@ -46,7 +46,7 @@ Polyhedron_demo_xyz_plugin::load(QFileInfo fileinfo) if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); Scene_points_with_normal_item* item = new Scene_points_with_normal_item(); item->setName(fileinfo.completeBaseName()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 8bb12b21db4..29aa230dfd9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -70,7 +70,7 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) { if(fileinfo.size() == 0) { - CGAL::Three::Three::s_warning( tr("The file you are trying to load is empty.")); + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); item->setName(fileinfo.completeBaseName()); return item; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp index dfac33c6d67..ecbffc3363c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp @@ -64,6 +64,7 @@ #include #include #endif +#include // Covariant return types don't work for scalar types and we cannot // have templates here, hence this unfortunate hack. @@ -365,7 +366,7 @@ public Q_SLOTS: } } if(group_map.keys().contains(seg_img)) - this->message_interface->warning("This item already has volume planes."); + CGAL::Three::Three::warning("This item already has volume planes."); else { // Opens a modal Dialog to prevent the user from manipulating things that could mess with the planes creation and cause a segfault. @@ -1153,7 +1154,7 @@ bool Io_image_plugin::loadDCM(QString dirname) { QMessageBox::warning(mw, mw->windowTitle(), tr("Cannot read directory %1!").arg(dirname)); - message_interface->warning(tr("Opening of directory %1 failed!").arg(dirname)); + CGAL::Three::Three::warning(tr("Opening of directory %1 failed!").arg(dirname)); result = false; } else @@ -1204,12 +1205,12 @@ bool Io_image_plugin::loadDCM(QString dirname) { QMessageBox::warning(mw, mw->windowTitle(), tr("Error with file %1/:\nunknown file format!").arg(dirname)); - message_interface->warning(tr("Opening of file %1/ failed!").arg(dirname)); + CGAL::Three::Three::warning(tr("Opening of file %1/ failed!").arg(dirname)); result = false; } else { - message_interface->information(tr("File %1/ successfully opened.").arg(dirname)); + CGAL::Three::Three::information(tr("File %1/ successfully opened.").arg(dirname)); } if(result) { @@ -1230,12 +1231,12 @@ bool Io_image_plugin::loadDCM(QString dirname) { QMessageBox::warning(mw, mw->windowTitle(), tr("Error with file %1/:\nunknown file format!").arg(dirname)); - message_interface->warning(tr("Opening of file %1/ failed!").arg(dirname)); + CGAL::Three::Three::warning(tr("Opening of file %1/ failed!").arg(dirname)); result = false; } else { - message_interface->information(tr("File %1/ successfully opened.").arg(dirname)); + CGAL::Three::Three::information(tr("File %1/ successfully opened.").arg(dirname)); } if(result) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp index c4320a49e8d..ecf2f4bc889 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp @@ -3,6 +3,7 @@ #ifdef CGAL_POLYHEDRON_DEMO_USE_SURFACE_MESHER #include +#include #include "Messages_interface.h" #include @@ -623,7 +624,7 @@ meshing_done(Meshing_thread* thread) .arg(bbox.zmin()) .arg(bbox.zmax())); - msg->information(qPrintable(str)); + CGAL::Three::Three::information(qPrintable(str)); // Treat new c3t3 item treat_result(*source_item_, result_item); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp index 344ab89ad0d..303e38fd5cc 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp @@ -9,6 +9,7 @@ #ifdef CGAL_POLYHEDRON_DEMO_USE_SURFACE_MESHER #include +#include #include "Messages_interface.h" #include "ui_Smoother_dialog.h" @@ -562,7 +563,7 @@ optimization_done(Optimizer_thread* thread) str.append(QString("( %1 )
").arg(param)); } - msg->information(qPrintable(str)); + CGAL::Three::Three::information(qPrintable(str)); // Treat new c3t3 item Scene_c3t3_item* result_item = thread->item(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Clip_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Clip_polyhedron_plugin.cpp index ea133fe6bdf..d6cf4c57458 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Clip_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Clip_polyhedron_plugin.cpp @@ -7,6 +7,7 @@ #include "Scene_plane_item.h" #include #include +#include #include #include "ui_Clip_polyhedron_plugin.h" @@ -168,7 +169,7 @@ public : } catch(CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception) { - messages->warning(tr("The requested operation is not possible due to the presence of self-intersections in the region handled.")); + CGAL::Three::Three::warning(tr("The requested operation is not possible due to the presence of self-intersections in the region handled.")); } } public Q_SLOTS: @@ -242,7 +243,7 @@ public Q_SLOTS: } catch(CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception) { - messages->warning(tr("The requested operation is not possible due to the presence of self-intersections in the region handled.")); + CGAL::Three::Three::warning(tr("The requested operation is not possible due to the presence of self-intersections in the region handled.")); } item->invalidateOpenGLBuffers(); viewer->update(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp index ce83faa6f5b..b00da7f7b54 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Corefinement_plugin.cpp @@ -3,6 +3,7 @@ #include #include "Messages_interface.h" #include +#include #include "Scene_surface_mesh_item.h" #include @@ -138,12 +139,12 @@ private: void apply_corefine(Item* item1, Item* item2) { if(! CGAL::is_triangle_mesh(*item1->face_graph())) { - messages->warning(tr("The face graph \"%1\" is not triangulated.") + CGAL::Three::Three::warning(tr("The face graph \"%1\" is not triangulated.") .arg(item1->name())); return; } if(! CGAL::is_triangle_mesh(*item2->face_graph())) { - messages->warning(tr("The face graph \"%1\" is not triangulated.") + CGAL::Three::Three::warning(tr("The face graph \"%1\" is not triangulated.") .arg(item2->name())); return; } @@ -158,7 +159,7 @@ private: } catch(CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception) { - messages->warning(tr("The requested operation is not possible due to the presence of self-intersections in the neighborhood of the intersection.")); + CGAL::Three::Three::warning(tr("The requested operation is not possible due to the presence of self-intersections in the neighborhood of the intersection.")); } // default cursor QApplication::restoreOverrideCursor(); @@ -169,12 +170,12 @@ private: { typedef typename Item::Face_graph FaceGraph; if(! CGAL::is_triangle_mesh(*first_item->face_graph())) { - messages->warning(tr("The polyhedron \"%1\" is not triangulated.") + CGAL::Three::Three::warning(tr("The polyhedron \"%1\" is not triangulated.") .arg(first_item->name())); return; } if(! CGAL::is_triangle_mesh(*item->face_graph())) { - messages->warning(tr("The polyhedron \"%1\" is not triangulated.") + CGAL::Three::Three::warning(tr("The polyhedron \"%1\" is not triangulated.") .arg(item->name())); return; } @@ -191,7 +192,7 @@ private: if (! PMP::corefine_and_compute_union(P, Q, *new_poly, params::throw_on_self_intersection(true)) ) { delete new_poly; - messages->warning(tr("The result of the requested operation is not manifold and has not been computed.")); + CGAL::Three::Three::warning(tr("The result of the requested operation is not manifold and has not been computed.")); // default cursor QApplication::restoreOverrideCursor(); return; @@ -203,7 +204,7 @@ private: if (! PMP::corefine_and_compute_intersection(P, Q, *new_poly, params::throw_on_self_intersection(true)) ) { delete new_poly; - messages->warning(tr("The result of the requested operation is not manifold and has not been computed.")); + CGAL::Three::Three::warning(tr("The result of the requested operation is not manifold and has not been computed.")); // default cursor QApplication::restoreOverrideCursor(); return; @@ -218,7 +219,7 @@ private: if (! PMP::corefine_and_compute_difference(P, Q, *new_poly, params::throw_on_self_intersection(true)) ) { delete new_poly; - messages->warning(tr("The result of the requested operation is not manifold and has not been computed.")); + CGAL::Three::Three::warning(tr("The result of the requested operation is not manifold and has not been computed.")); // default cursor QApplication::restoreOverrideCursor(); return; @@ -228,7 +229,7 @@ private: } catch(CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception) { - messages->warning(tr("The requested operation is not possible due to the presence of self-intersections in the neighborhood of the intersection.")); + CGAL::Three::Three::warning(tr("The requested operation is not possible due to the presence of self-intersections in the neighborhood of the intersection.")); QApplication::restoreOverrideCursor(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp index 2765e8993d2..e8974d7ecee 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -431,7 +432,7 @@ public Q_SLOTS: Scene_face_graph_item* itemB = qobject_cast(scene->item(scene->selectionIndices().last())); if(! CGAL::is_triangle_mesh(*itemA->polyhedron()) || !CGAL::is_triangle_mesh(*itemB->polyhedron()) ){ - messageInterface->error(QString("Distance not computed. (Both polyhedra must be triangulated)")); + CGAL::Three::Three::error(QString("Distance not computed. (Both polyhedra must be triangulated)")); return; } QApplication::setOverrideCursor(Qt::WaitCursor); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 6cad4ed03c9..71ff77275d3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -734,7 +734,7 @@ public Q_SLOTS: if (PMP::does_self_intersect(text_mesh_complete)) { QApplication::restoreOverrideCursor(); - messages->information("Error: text mesh self-intersects!"); + CGAL::Three::Three::information("Error: text mesh self-intersects!"); return; } @@ -745,7 +745,7 @@ public Q_SLOTS: if (!OK) { QApplication::restoreOverrideCursor(); - messages->information("Error: the output mesh is not manifold!"); + CGAL::Three::Three::information("Error: the output mesh is not manifold!"); return; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp index 8c968b5e323..4e97eb1b662 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -370,7 +371,7 @@ private Q_SLOTS: pMesh = new Face_graph(); if(!sel_item->export_selected_facets_as_polyhedron(pMesh)) { - messageInterface->error("Face selection is not valid. Aborting."); + CGAL::Three::Three::error("Face selection is not valid. Aborting."); return; } @@ -386,7 +387,7 @@ private Q_SLOTS: return; if(CGAL::is_closed(*pMesh)) { - messageInterface->error("The face graph must be open. Aborting."); + CGAL::Three::Three::error("The face graph must be open. Aborting."); return; } std::vector triangles; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp index 98cf548d126..3455e946f09 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp @@ -3,6 +3,7 @@ #include "Messages_interface.h" #include +#include #include "Scene_polyhedron_selection_item.h" #include "ui_Fairing_widget.h" @@ -42,7 +43,7 @@ public: return qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message);} + void print_message(QString message) { CGAL::Three::Three::information(message);} QList actions() const { return QList() << actionFairing; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp index 88523da2286..df3b96eea3a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp @@ -9,6 +9,7 @@ #include "Scene.h" #include +#include #include "ui_Hole_filling_widget.h" #include @@ -323,7 +324,7 @@ class Polyhedron_demo_hole_filling_plugin : public: bool applicable(QAction*) const { return qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionHoleFilling; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp index 605703178bc..9d90ffda2fd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp @@ -25,6 +25,7 @@ #include #include +#include struct Face : public CGAL::cpp11::array @@ -48,7 +49,7 @@ class Polyhedron_demo_hole_filling_polyline_plugin : Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") public: bool applicable(QAction *) const { return qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionHoleFillingPolyline; } void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m){ diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp index fc681f37cde..7fa8a640351 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -168,7 +169,7 @@ void Polyhedron_demo_join_and_split_polyhedra_plugin::on_actionSplitPolyhedra_tr if (new_polyhedra.size()==1) { delete new_polyhedra.front(); - msg_interface->information( tr("%1 has only one connected component").arg(item->name()) ); + CGAL::Three::Three::information( tr("%1 has only one connected component").arg(item->name()) ); QApplication::restoreOverrideCursor(); continue; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Orient_soup_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Orient_soup_plugin.cpp index d70f953d9a5..1ae9edc3f74 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Orient_soup_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Orient_soup_plugin.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "Messages_interface.h" using namespace CGAL::Three; class Polyhedron_demo_orient_soup_plugin : @@ -174,7 +175,7 @@ void Polyhedron_demo_orient_soup_plugin::orientSM() QApplication::restoreOverrideCursor(); } else{ - messages->warning(tr("This function is only applicable on polygon soups.")); + CGAL::Three::Three::warning(tr("This function is only applicable on polygon soups.")); } } } @@ -251,7 +252,7 @@ void Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline() if(nm_vertices.empty()) { delete points; - messages->information(tr("There is no non-manifold vertex in this soup.")); + CGAL::Three::Three::information(tr("There is no non-manifold vertex in this soup.")); } else { @@ -286,7 +287,7 @@ void Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline() } else { - messages->information(tr("There is no non-manifold edge in this soup.")); + CGAL::Three::Three::information(tr("There is no non-manifold edge in this soup.")); } QApplication::restoreOverrideCursor(); if(!items_created) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp index 9625fc02fc4..ff19d4af3bb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp @@ -5,7 +5,7 @@ #include "Scene_surface_mesh_item.h" #include "Scene_points_with_normal_item.h" #include - +#include #include #include @@ -52,7 +52,7 @@ public: //if the loop ends without returning true, return false return false; } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionPointInsidePolyhedron; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_slicer_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_slicer_plugin.cpp index 8209f04fe71..dea7f885bb3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_slicer_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Polyhedron_slicer_plugin.cpp @@ -9,6 +9,7 @@ #include "Scene.h" #include +#include #include "ui_Polyhedron_slicer_widget.h" #include @@ -40,7 +41,7 @@ public: return qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message);} + void print_message(QString message) { CGAL::Three::Three::information(message);} void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m); virtual void closure() diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index 548cc110464..a3a2e6e3fe8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "Messages_interface.h" #include @@ -125,7 +126,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveIsolatedVertices_t std::size_t nbv = CGAL::Polygon_mesh_processing::remove_isolated_vertices( *poly_item->polyhedron()); - messages->information(tr(" %1 isolated vertices have been removed.") + CGAL::Three::Three::information(tr(" %1 isolated vertices have been removed.") .arg(nbv)); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); @@ -150,7 +151,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_tr std::size_t nbv = CGAL::Polygon_mesh_processing::remove_degenerate_faces( *poly_item->polyhedron()); - messages->information(tr(" %1 degenerate faces have been removed.") + CGAL::Three::Three::information(tr(" %1 degenerate faces have been removed.") .arg(nbv)); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); @@ -176,7 +177,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveSelfIntersections_ CGAL::Polygon_mesh_processing::remove_self_intersections( *poly_item->polyhedron()); if (!solved) - messages->information(tr("Some self-intersection could not be fixed")); + CGAL::Three::Three::information(tr("Some self-intersection could not be fixed")); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); } @@ -202,7 +203,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionAutorefine_triggered(Sce } catch(CGAL::Polygon_mesh_processing::Corefinement::Triple_intersection_exception) { - messages->warning(tr("The result of the requested operation is not handled (triple intersection).")); + CGAL::Three::Three::warning(tr("The result of the requested operation is not handled (triple intersection).")); } poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); @@ -229,11 +230,11 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionAutorefineAndRMSelfInter CGAL::Polygon_mesh_processing::experimental:: autorefine_and_remove_self_intersections(*poly_item->polyhedron()); if (!solved) - messages->information(tr("Self-intersection could not be removed due to non-manifold edges in the output")); + CGAL::Three::Three::information(tr("Self-intersection could not be removed due to non-manifold edges in the output")); } catch(CGAL::Polygon_mesh_processing::Corefinement::Triple_intersection_exception) { - messages->warning(tr("The result of the requested operation is not handled (triple intersection).")); + CGAL::Three::Three::warning(tr("The result of the requested operation is not handled (triple intersection).")); } poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); @@ -268,7 +269,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionStitchCloseBorderHalfedg get(boost::vertex_point, *poly_item->polyhedron()), halfedges_to_stitch); PMP::stitch_borders(*poly_item->polyhedron(), halfedges_to_stitch); - messages->information(tr(" %1 pairs of halfedges stitched.").arg(halfedges_to_stitch.size())); + CGAL::Three::Three::information(tr(" %1 pairs of halfedges stitched.").arg(halfedges_to_stitch.size())); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); } @@ -290,7 +291,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_trig if (Item* poly_item = qobject_cast(scene->item(index))) { std::size_t nb_vd = PMP::duplicate_non_manifold_vertices(*poly_item->polyhedron()); - messages->information(tr(" %1 vertices created").arg(nb_vd)); + CGAL::Three::Three::information(tr(" %1 vertices created").arg(nb_vd)); if (nb_vd) { poly_item->invalidateOpenGLBuffers(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index dfb2cc2ad24..23e1c6f4d98 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -117,7 +117,7 @@ public: return qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { CGAL::Three::Three::s_information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionSelection; } void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Surface_intersection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Surface_intersection_plugin.cpp index 0bc18398d00..f437347ab0d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Surface_intersection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Surface_intersection_plugin.cpp @@ -4,6 +4,7 @@ #include "Kernel_type.h" #include "Scene_surface_mesh_item.h" #include +#include #include "Scene_polylines_item.h" #include "Scene_points_with_normal_item.h" @@ -124,7 +125,7 @@ void Polyhedron_demo_intersection_plugin::intersectionSurfaces() if(!is_triangle_mesh(*itemA->face_graph()) || !is_triangle_mesh(*itemB->face_graph())) { - mi->error("The two meshes must be triangle meshes."); + CGAL::Three::Three::error("The two meshes must be triangle meshes."); } QApplication::setOverrideCursor(Qt::WaitCursor); @@ -282,7 +283,7 @@ void Polyhedron_demo_intersection_plugin::intersectionSurfacePolyline() if(!is_triangle_mesh(*itemA->face_graph())) { - mi->error("The mesh must be a triangle mesh."); + CGAL::Three::Three::error("The mesh must be a triangle mesh."); } QApplication::setOverrideCursor(Qt::WaitCursor); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp index acf5bf53abe..bdcba79145f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Triangulate_facets_plugin.cpp @@ -3,6 +3,7 @@ #include #include "Messages_interface.h" #include +#include #include "Scene_surface_mesh_item.h" #include @@ -53,12 +54,12 @@ public Q_SLOTS: SMesh* pMesh = sm_item->polyhedron(); if(!pMesh) continue; if(is_triangle_mesh(*pMesh)) { - messages->warning(tr("The polyhedron \"%1\" is already triangulated.") + CGAL::Three::Three::warning(tr("The polyhedron \"%1\" is already triangulated.") .arg(sm_item->name()) ); continue; } if(!CGAL::Polygon_mesh_processing::triangulate_faces(*pMesh)) - messages->warning(tr("Some facets could not be triangulated.")); + CGAL::Three::Three::warning(tr("Some facets could not be triangulated.")); sm_item->invalidateOpenGLBuffers(); scene->itemChanged(sm_item); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp index 9b9c5853770..ef3e69879f1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "ui_Point_set_selection_widget.h" #include #include "Point_set_3.h" @@ -415,7 +416,7 @@ public: bool applicable(QAction*) const { return qobject_cast(scene->item(scene->mainSelectionIndex())); } - void print_message(QString message) { messages->information(message); } + void print_message(QString message) { CGAL::Three::Three::information(message); } QList actions() const { return QList() << actionPointSetSelection; } void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m) { @@ -615,7 +616,7 @@ protected: Neighbor_search search(tree, Point(point.x, point.y, point.z), 1); Point res = search.begin()->first; - messages->information(QString("Selected point : (%1, %2, %3)").arg(res.x()).arg(res.y()).arg(res.z())); + CGAL::Three::Three::information(QString("Selected point : (%1, %2, %3)").arg(res.x()).arg(res.y()).arg(res.z())); } return false; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp index 582335319fd..9ea6404172d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -184,7 +185,7 @@ private Q_SLOTS: if(!item || !item->point_set()->has_property_map("distance")) { - messageInterface->warning("You must select the resulting point set."); + CGAL::Three::Three::warning("You must select the resulting point set."); return; } PMap distance_map; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp index ad3e5642578..2fba3abfcb8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp @@ -3,6 +3,7 @@ #include "Messages_interface.h" #include #include +#include #include #include @@ -86,7 +87,7 @@ void Polyhedron_demo_point_set_upsampling_plugin::on_actionEdgeAwareUpsampling_t { if (!(item->has_normals ())) { - message_interface->error("Error: upsampling algorithm requires point set with normals."); + CGAL::Three::Three::error("Error: upsampling algorithm requires point set with normals."); return; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Subdivision_methods/Subdivision_methods_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Subdivision_methods/Subdivision_methods_plugin.cpp index 2b54e27cf3e..0d00de8eb16 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Subdivision_methods/Subdivision_methods_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Subdivision_methods/Subdivision_methods_plugin.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "Messages_interface.h" #include "Scene_surface_mesh_item.h" @@ -82,10 +83,10 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_loop(FaceGraphItem* item, typename FaceGraphItem::Face_graph* graph = item->face_graph(); QTime time; time.start(); - messages->information("Loop subdivision..."); + CGAL::Three::Three::information("Loop subdivision..."); QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Subdivision_method_3::Loop_subdivision(*graph, params::number_of_iterations(nb_steps)); - messages->information(QString("ok (%1 ms)").arg(time.elapsed())); + CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed())); QApplication::restoreOverrideCursor(); item->invalidateOpenGLBuffers(); scene->itemChanged(item); @@ -114,10 +115,10 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_catmullclark(FaceGraphIte if(!graph) return; QTime time; time.start(); - messages->information("Catmull-Clark subdivision..."); + CGAL::Three::Three::information("Catmull-Clark subdivision..."); QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Subdivision_method_3::CatmullClark_subdivision(*graph, params::number_of_iterations(nb_steps)); - messages->information(QString("ok (%1 ms)").arg(time.elapsed())); + CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed())); QApplication::restoreOverrideCursor(); item->invalidateOpenGLBuffers(); scene->itemChanged(item); @@ -144,10 +145,10 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_sqrt3(FaceGraphItem* item if(!graph) return; QTime time; time.start(); - messages->information("Sqrt-3 subdivision..."); + CGAL::Three::Three::information("Sqrt-3 subdivision..."); QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Subdivision_method_3::Sqrt3_subdivision(*graph, params::number_of_iterations(nb_steps)); - messages->information(QString("ok (%1 ms)").arg(time.elapsed())); + CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed())); QApplication::restoreOverrideCursor(); item->invalidateOpenGLBuffers(); scene->itemChanged(item); @@ -176,10 +177,10 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_doosabin(FaceGraphItem* i if(!graph) return; QTime time; time.start(); - messages->information("Doo-Sabin subdivision..."); + CGAL::Three::Three::information("Doo-Sabin subdivision..."); QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Subdivision_method_3::DooSabin_subdivision(*graph, params::number_of_iterations(nb_steps)); - messages->information(QString("ok (%1 ms)").arg(time.elapsed())); + CGAL::Three::Three::information(QString("ok (%1 ms)").arg(time.elapsed())); QApplication::restoreOverrideCursor(); item->invalidateOpenGLBuffers(); scene->itemChanged(item); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index 06a7f88598b..c2aa15287a3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -9,6 +9,7 @@ #include "SMesh_type.h" #include #include +#include #include "Scene.h" #include #include @@ -540,14 +541,14 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio if(!poly_item) { - messages->error("Selected item is not of the right type."); + CGAL::Three::Three::error("Selected item is not of the right type."); return; } Face_graph* pMesh = poly_item->face_graph(); if(!pMesh) { - messages->error("Selected item has no valid polyhedron."); + CGAL::Three::Three::error("Selected item has no valid polyhedron."); return; } Scene_polyhedron_selection_item* sel_item = NULL; @@ -579,7 +580,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio if(!is_seamed && is_closed(*pMesh)) { - messages->error("The selected mesh has no (real or virtual) border."); + CGAL::Three::Three::error("The selected mesh has no (real or virtual) border."); return; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp index c397aa48ebe..9df5eec30ac 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp @@ -9,6 +9,7 @@ #include #include +#include #include typedef Scene_polyhedron_shortest_path_item It; @@ -242,9 +243,9 @@ void Scene_polyhedron_shortest_path_item_priv::ensure_shortest_paths_tree() { if (!m_shortestPaths->changed_since_last_build()) { - m_messages->information("Recomputing shortest paths tree..."); + CGAL::Three::Three::information("Recomputing shortest paths tree..."); m_shortestPaths->build_sequence_tree(); - m_messages->information("Done."); + CGAL::Three::Three::information("Done."); } } @@ -387,7 +388,7 @@ bool Scene_polyhedron_shortest_path_item_priv::run_point_select(const Ray_3& ray if (faceLocation.first == GraphTraits::null_face()) { - m_messages->information(QObject::tr("Shortest Paths: No face under cursor.")); + CGAL::Three::Three::information(QObject::tr("Shortest Paths: No face under cursor.")); QApplication::restoreOverrideCursor(); return false; } @@ -395,7 +396,7 @@ bool Scene_polyhedron_shortest_path_item_priv::run_point_select(const Ray_3& ray { boost::property_map::type fimap = get(CGAL::face_index, *item->polyhedron()); - m_messages->information(QObject::tr("Shortest Paths: Selected Face: %1; Barycentric coordinates: %2 %3 %4") + CGAL::Three::Three::information(QObject::tr("Shortest Paths: Selected Face: %1; Barycentric coordinates: %2 %3 %4") .arg(get(fimap, faceLocation.first)) .arg(double(faceLocation.second[0])) .arg(double(faceLocation.second[1])) @@ -442,7 +443,7 @@ bool Scene_polyhedron_shortest_path_item_priv::run_point_select(const Ray_3& ray polylines->polylines.push_back(Scene_polylines_item::Polyline()); - m_messages->information(QObject::tr("Computing shortest path polyline...")); + CGAL::Three::Three::information(QObject::tr("Computing shortest path polyline...")); QTime time; time.start(); @@ -462,7 +463,7 @@ bool Scene_polyhedron_shortest_path_item_priv::run_point_select(const Ray_3& ray } else { - m_messages->warning(QObject::tr("No source points to compute shortest paths from.")); + CGAL::Three::Three::warning(QObject::tr("No source points to compute shortest paths from.")); } break; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp index b9995cba4f1..b411c8c6a17 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "Scene_surface_mesh_item.h" #include "Scene_polyhedron_shortest_path_item.h" @@ -192,14 +193,14 @@ void Polyhedron_demo_shortest_path_plugin::new_item(int itemIndex) if(!polyhedronItem) { CGAL_assertion(item->polyhedron_item() == NULL); // which means it is coming from selection_io loader - this->m_messages->information(tr("Error: please select corresponding polyhedron item from Geometric Objects list.")); + CGAL::Three::Three::information(tr("Error: please select corresponding polyhedron item from Geometric Objects list.")); scene->erase(itemIndex); return; } if(!item->deferred_load(polyhedronItem, this->scene, this->m_messages, this->mw)) { - this->m_messages->information("Error: loading selection item is not successful!"); + CGAL::Three::Three::information("Error: loading selection item is not successful!"); scene->erase(itemIndex); return; } @@ -248,12 +249,12 @@ void Polyhedron_demo_shortest_path_plugin::on_actionMakeShortestPaths_triggered( } else { - this->m_messages->warning(tr("A shortest path item for this polyhedron already exists (only one allowed per for now)")); + CGAL::Three::Three::warning(tr("A shortest path item for this polyhedron already exists (only one allowed per for now)")); } } else { - this->m_messages->warning("No polyhedron selected."); + CGAL::Three::Three::warning("No polyhedron selected."); } } diff --git a/Polyhedron/demo/Polyhedron/Three.cpp b/Polyhedron/demo/Polyhedron/Three.cpp index ea6da3ec9f2..07feeb0b7ac 100644 --- a/Polyhedron/demo/Polyhedron/Three.cpp +++ b/Polyhedron/demo/Polyhedron/Three.cpp @@ -134,17 +134,17 @@ void Three::autoConnectActions(Polyhedron_demo_plugin_interface *plugin) } // end foreach action of actions() } -void Three::s_information(QString s) +void Three::information(QString s) { - qobject_cast(mainWindow())->information(s); + qobject_cast(mainWindow())->message_information(s); } -void Three::s_warning(QString s) +void Three::warning(QString s) { - qobject_cast(mainWindow())->warning(s); + qobject_cast(mainWindow())->message_warning(s); } -void Three::s_error(QString s) +void Three::error(QString s) { - qobject_cast(mainWindow())->error(s); + qobject_cast(mainWindow())->message_error(s); } RenderingMode Three::defaultSurfaceMeshRenderingMode() { diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index dc33c4af860..f2a65485dea 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -76,15 +76,15 @@ public: * in the plugin. */ static void autoConnectActions(CGAL::Three::Polyhedron_demo_plugin_interface* plugin); - static void s_information(QString); + static void information(QString); /*! * Displays a blue text preceded by the mention "WARNING :". */ - static void s_warning(QString); + static void warning(QString); /*! * Displays a red text preceded by the mention "ERROR :". */ - static void s_error(QString); + static void error(QString); protected: static QMainWindow* s_mainwindow; static Scene_interface* s_scene; From 8ab7e69a5c877d2d00ef90cc39a5dff50110036d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 14 Jan 2019 15:29:51 +0100 Subject: [PATCH 114/186] Test global bbox intersection before creating all bboxes. --- .../Polygon_mesh_processing/intersection.h | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index a36b14d8803..6a646c0c381 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -411,6 +411,14 @@ compute_face_face_intersection(const FaceRange& face_range1, typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + CGAL::Bbox_3 b1 = CGAL::Polygon_mesh_processing::bbox(tm1, np1), + b2 = CGAL::Polygon_mesh_processing::bbox(tm2, np2); + + if(!CGAL::do_overlap(b1, b2)) + { + return out; + } // make one box per facet std::vector boxes1; @@ -525,6 +533,16 @@ compute_face_polyline_intersection( const FaceRange& face_range, CGAL_precondition(CGAL::is_triangle_mesh(tm)); + CGAL::Bbox_3 b1,b2; + b1 = CGAL::Polygon_mesh_processing::bbox(tm, np); + for(std::size_t i =0; i< polyline.size(); ++i) + { + b2 += CGAL::bbox_3(polyline[i].begin(), + polyline[i].end()); + } + + if(!CGAL::do_overlap(b1,b2)) + return out; typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename GetVertexPointMap::const_type VertexPointMap; @@ -648,7 +666,18 @@ compute_face_polylines_intersection(const FaceRange& face_range, using boost::get_param; CGAL_precondition(CGAL::is_triangle_mesh(tm)); - + + CGAL::Bbox_3 b1,b2; + b1 = CGAL::Polygon_mesh_processing::bbox(tm, np); + for(std::size_t i =0; i< polyline_range.size(); ++i) + { + b2 += CGAL::bbox_3(polyline_range[i].begin(), + polyline_range[i].end()); + } + + if(!CGAL::do_overlap(b1,b2)) + return out; + typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename GetVertexPointMap::const_type VertexPointMap; @@ -849,18 +878,26 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, std::vector boxes1; std::vector boxes2; std::size_t polylines_size = 0; + CGAL::Bbox_3 b1, b2; BOOST_FOREACH(Polyline poly, polylines1) { polylines_size += std::distance( boost::begin(poly), boost::end(poly) ) -1; + BOOST_FOREACH(Point p, poly) + { + b1 += p.bbox(); + } } boxes1.reserve( polylines_size ); polylines_size = 0; BOOST_FOREACH(Polyline poly, polylines2) { polylines_size += std::distance( boost::begin(poly), boost::end(poly) ) -1; + b2 += CGAL::bbox_3(poly.begin(), poly.end()); } boxes2.reserve(polylines_size); - + + if(!CGAL::do_overlap(b1,b2)) + return out; std::size_t range_size = std::distance( boost::begin(polylines1), boost::end(polylines1) ); for(std::size_t j = 0; j < range_size; ++j) { @@ -1207,7 +1244,6 @@ bool do_intersect(const TriangleMesh& tm1, { using boost::choose_param; using boost::get_param; - bool test_overlap = choose_param(get_param(np1, internal_np::overlap_test),false) || choose_param(get_param(np2, internal_np::overlap_test),false); @@ -1298,7 +1334,6 @@ bool do_intersect(const TriangleMesh& tm, ) { CGAL_precondition(CGAL::is_triangle_mesh(tm)); - try { typedef boost::function_output_iterator OutputIterator; @@ -1354,7 +1389,6 @@ bool do_intersect(const TriangleMesh& tm, ) { CGAL_precondition(CGAL::is_triangle_mesh(tm)); - try { typedef boost::function_output_iterator OutputIterator; @@ -1381,7 +1415,6 @@ bool do_intersect(const TriangleMesh& tm, >::type* = 0) { CGAL_precondition(CGAL::is_triangle_mesh(tm)); - return CGAL::Polygon_mesh_processing::do_intersect(tm, polylines, parameters::all_default()); } @@ -1404,7 +1437,6 @@ bool do_intersect(const TriangleMesh& tm, >::type* = 0) { CGAL_precondition(CGAL::is_triangle_mesh(tm)); - return CGAL::Polygon_mesh_processing::do_intersect(tm, polyline, parameters::all_default()); } From 656a5a316a2af4c2652141ec21565641ad92d4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 14 Jan 2019 17:45:09 +0100 Subject: [PATCH 115/186] fix compilation error + indent + simplify --- .../Polygon_mesh_processing/intersection.h | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index 6a646c0c381..916cb5a1377 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -413,7 +413,7 @@ compute_face_face_intersection(const FaceRange& face_range1, typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; CGAL::Bbox_3 b1 = CGAL::Polygon_mesh_processing::bbox(tm1, np1), - b2 = CGAL::Polygon_mesh_processing::bbox(tm2, np2); + b2 = CGAL::Polygon_mesh_processing::bbox(tm2, np2); if(!CGAL::do_overlap(b1, b2)) { @@ -533,14 +533,9 @@ compute_face_polyline_intersection( const FaceRange& face_range, CGAL_precondition(CGAL::is_triangle_mesh(tm)); - CGAL::Bbox_3 b1,b2; - b1 = CGAL::Polygon_mesh_processing::bbox(tm, np); - for(std::size_t i =0; i< polyline.size(); ++i) - { - b2 += CGAL::bbox_3(polyline[i].begin(), - polyline[i].end()); - } - + CGAL::Bbox_3 b1 = CGAL::Polygon_mesh_processing::bbox(tm, np), + b2 = CGAL::bbox_3(polyline.begin(), polyline.end()); + if(!CGAL::do_overlap(b1,b2)) return out; typedef TriangleMesh TM; @@ -671,7 +666,7 @@ compute_face_polylines_intersection(const FaceRange& face_range, b1 = CGAL::Polygon_mesh_processing::bbox(tm, np); for(std::size_t i =0; i< polyline_range.size(); ++i) { - b2 += CGAL::bbox_3(polyline_range[i].begin(), + b2 += CGAL::bbox_3(polyline_range[i].begin(), polyline_range[i].end()); } @@ -882,17 +877,14 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, BOOST_FOREACH(Polyline poly, polylines1) { polylines_size += std::distance( boost::begin(poly), boost::end(poly) ) -1; - BOOST_FOREACH(Point p, poly) - { - b1 += p.bbox(); - } + b1 += CGAL::bbox_3(poly.begin(), poly.end()); } boxes1.reserve( polylines_size ); polylines_size = 0; BOOST_FOREACH(Polyline poly, polylines2) { polylines_size += std::distance( boost::begin(poly), boost::end(poly) ) -1; - b2 += CGAL::bbox_3(poly.begin(), poly.end()); + b2 += CGAL::bbox_3(poly.begin(), poly.end()); } boxes2.reserve(polylines_size); From 3979b415ece81fe2be3bdcca47cec80b58ffd5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 14 Jan 2019 17:49:17 +0100 Subject: [PATCH 116/186] remove useless heading messing up brief --- .../doc/Straight_skeleton_2/Concepts/VertexContainer_2.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Straight_skeleton_2/doc/Straight_skeleton_2/Concepts/VertexContainer_2.h b/Straight_skeleton_2/doc/Straight_skeleton_2/Concepts/VertexContainer_2.h index 15dfdf25092..b35ba7ee047 100644 --- a/Straight_skeleton_2/doc/Straight_skeleton_2/Concepts/VertexContainer_2.h +++ b/Straight_skeleton_2/doc/Straight_skeleton_2/Concepts/VertexContainer_2.h @@ -2,8 +2,6 @@ \ingroup PkgStraightSkeleton2Concepts \cgalConcept -\cgalHeading{Introduction} - A model for the `VertexContainer_2` concept defines the requirements for a resizable container of 2D points. It is used to output the offset polygons generated by the `Polygon_offset_builder_2` class. \cgalHasModel CGAL::Polygon_2 From 829c412b10a6e64eec345d54653920fe4673ee8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 14 Jan 2019 17:53:40 +0100 Subject: [PATCH 117/186] move note outside the brief --- .../Concepts/PolynomialTraits_d--PolynomialSubresultants.h | 4 ++-- ...PolynomialTraits_d--PolynomialSubresultantsWithCofactors.h | 4 ++-- .../PolynomialTraits_d--PrincipalSturmHabichtSequence.h | 4 ++-- .../Concepts/PolynomialTraits_d--PrincipalSubresultants.h | 4 ++-- .../Concepts/PolynomialTraits_d--SturmHabichtSequence.h | 4 ++-- .../PolynomialTraits_d--SturmHabichtSequenceWithCofactors.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultants.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultants.h index 87cdc87ecc6..026c76a8848 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultants.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultants.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the polynomial subresultant of two polynomials \f$ p\f$ and \f$ q\f$ of type `PolynomialTraits_d::Polynomial_d` with respect to outermost variable. Let @@ -23,6 +21,8 @@ The result is written in an output range, starting with the \f$ 0\f$-th subresul \f$ \mathrm{Sres}_0(p,q)\f$ (aka as the resultant of \f$ p\f$ and \f$ q\f$). +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultantsWithCofactors.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultantsWithCofactors.h index b1981463df7..56c1e14f641 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultantsWithCofactors.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PolynomialSubresultantsWithCofactors.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the polynomial subresultant of two polynomials \f$ p\f$ and \f$ q\f$ of degree \f$ n\f$ and \f$ m\f$, respectively, as defined in the documentation of `PolynomialTraits_d::PolynomialSubresultants`. @@ -16,6 +14,8 @@ the cofactors of \f$ \mathrm{Sres}_i(p,q)\f$. The result is written in three output ranges, each of length \f$ \min\{n,m\}+1\f$, starting with the \f$ 0\f$-th subresultant and the corresponding cofactors. +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSturmHabichtSequence.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSturmHabichtSequence.h index bd4bd491935..376a3e279ef 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSturmHabichtSequence.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSturmHabichtSequence.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the principal leading coefficients of the Sturm-Habicht sequence of a polynomials \f$ f\f$ of type `PolynomialTraits_d::Polynomial_d` with respect a certain variable \f$ x_i\f$. @@ -19,6 +17,8 @@ In case that `PolynomialTraits_d::Coefficient_type` is `RealEmbeddable`, the fun on the resulting sequence to count the number of distinct real roots of the polynomial \f$ f\f$. +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSubresultants.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSubresultants.h index 2cddb81e1ed..3a63bc6f76d 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSubresultants.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--PrincipalSubresultants.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the principal subresultant of two polynomials \f$ p\f$ and \f$ q\f$ of type `PolynomialTraits_d::Coefficient_type` with respect to the outermost variable. @@ -19,6 +17,8 @@ principal subresultant \f$ \mathrm{sres}_0(p,q)\f$ ,aka as the resultant of \f$ p\f$ and \f$ q\f$. (Note that \f$ \mathrm{sres}_0(p,q)=\mathrm{Sres}_0(p,q)\f$ by definition) +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequence.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequence.h index f6a4676dfc3..32478346def 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequence.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequence.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the Sturm-Habicht sequence (aka the signed subresultant sequence) of a polynomial \f$ f\f$ of type @@ -27,6 +25,8 @@ The result is written in an output range, starting with the \f$ 0\f$-th Sturm-Habicht polynomial (which is equal to the discriminant of \f$ f\f$ up to a multiple of the leading coefficient). +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` diff --git a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequenceWithCofactors.h b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequenceWithCofactors.h index e77f9b78cd2..85efdb9edf9 100644 --- a/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequenceWithCofactors.h +++ b/Polynomial/doc/Polynomial/Concepts/PolynomialTraits_d--SturmHabichtSequenceWithCofactors.h @@ -3,8 +3,6 @@ \ingroup PkgPolynomialConcepts \cgalConcept -Note: This functor is optional! - Computes the Sturm-Habicht polynomials of a polynomial \f$ f\f$ of degree \f$ n\f$, as defined in the documentation of `PolynomialTraits_d::SturmHabichtSequence`. Moreover, for \f$ \mathrm{Stha}_i(f)\f$, polynomials \f$ u_i\f$ and \f$ v_i\f$ @@ -16,6 +14,8 @@ The result is written in three output ranges, each of length \f$ \min\{n,m\}+1\f starting with the \f$ 0\f$-th Sturm-Habicht polynomial \f$ \mathrm{Stha_0(f)}\f$ and the corresponding cofactors. +\note This functor is optional. + \cgalRefines `AdaptableBinaryFunction` \cgalRefines `CopyConstructible` \cgalRefines `DefaultConstructible` From 1d64eae84387527c0e6b2e3911c59b8ee58baf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 14 Jan 2019 17:58:49 +0100 Subject: [PATCH 118/186] reduce brief --- .../doc/Solver_interface/Concepts/DiagonalizeTraits.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h b/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h index 345bd48dd39..678dc2c87a2 100644 --- a/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h +++ b/Solver_interface/doc/Solver_interface/Concepts/DiagonalizeTraits.h @@ -4,7 +4,9 @@ Concept providing functions to extract eigenvectors and eigenvalues from covariance matrices represented by an array `a`, using symmetric -diagonalization. For example, a matrix of dimension 3 is defined as +diagonalization. + +For example, a matrix of dimension 3 is defined as follows:
\f$ \begin{bmatrix} From 82c93c87ed8571fb2162c37430240a03a39317f5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 15 Jan 2019 16:29:58 +0100 Subject: [PATCH 119/186] Restore unwanted change to ms_2 test --- .../test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp index c4c887ab209..c887fef70e5 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp @@ -178,8 +178,7 @@ int main(int argc, char* argv[]) ++i; continue; } - std::vector* crash = nullptr; - crash->push_back(0); + std::cout << "Testing " << argv[i] << " + " << argv[i+1] << std::endl; if (!read_polygon(argv[i], p)) return -1; if (!read_polygon(argv[i+1], q)) return -1; From cb10422e3ceaab789e56c1192b4f064e3906c8a0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 16 Jan 2019 09:58:02 +0100 Subject: [PATCH 120/186] Fix indentation and markdown --- BGL/doc/BGL/PackageDescription.txt | 2 +- BGL/include/CGAL/IO/vtp_io.h | 42 ++++++++-------- .../Constrained_Delaunay_triangulation_2.cpp | 50 +++++++++---------- Installation/CHANGES.md | 8 +-- Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 4 +- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 0bb14dfbb42..cde8cb34f89 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -708,7 +708,7 @@ user might encounter. ## I/O Functions ## - \link PkgBGLIOFct CGAL::read_off() \endlink - \link PkgBGLIOFct CGAL::write_off() \endlink -- \link PkgBGLIOFct `CGAL::write_VTP()` \endlink +- \link PkgBGLIOFct CGAL::write_VTP() \endlink - \link PkgBGLIOFct CGAL::write_wrl() \endlink */ diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h index 6a09aa5ae82..77e7c717e13 100644 --- a/BGL/include/CGAL/IO/vtp_io.h +++ b/BGL/include/CGAL/IO/vtp_io.h @@ -50,18 +50,18 @@ write_polys(std::ostream& os, std::vector connectivity_table; std::vector offsets; std::vector cell_type(num_faces(mesh),5); // triangle == 5 - + std::size_t off = 0; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; ++fit ) - { - off += 3; - offsets.push_back(off); - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(V[v]); - } + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } write_vector(os,connectivity_table); write_vector(os,offsets); write_vector(os,cell_type); @@ -105,13 +105,13 @@ write_polys_tag(std::ostream& os, else { os << "\">\n"; for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << V[v] << " "; - } + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } os << " \n"; } @@ -128,12 +128,12 @@ write_polys_tag(std::ostream& os, os << "\">\n"; std::size_t polys_offset = 0; for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - polys_offset += 3; - os << polys_offset << " "; - } + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } os << " \n"; } diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 9aafc882385..efec041a6f3 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -85,12 +85,12 @@ discoverInfiniteComponent(const CDT & ct) Face_handle fh = queue.front(); queue.pop_front(); fh->set_in_domain(false); - + for(int i = 0; i < 3; i++) { Face_handle fi = fh->neighbor(i); if(fi->is_in_domain() - && !ct.is_constrained(CDT::Edge(fh,i))) + && !ct.is_constrained(CDT::Edge(fh,i))) queue.push_back(fi); } } @@ -270,7 +270,7 @@ MainWindow::MainWindow() dgi->setFacesInDomainBrush(facesColor); QObject::connect(this, SIGNAL(changed()), - dgi, SLOT(modelChanged())); + dgi, SLOT(modelChanged())); dgi->setVerticesPen( QPen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); dgi->setVoronoiPen( @@ -286,8 +286,8 @@ MainWindow::MainWindow() // the signal/slot mechanism pi = new CGAL::Qt::GraphicsViewPolylineInput(this, &scene, 0, true); // inputs polylines which are not closed QObject::connect(pi, SIGNAL(generate(CGAL::Object)), - this, SLOT(processInput(CGAL::Object))); - + this, SLOT(processInput(CGAL::Object))); + tcc = new CGAL::Qt::TriangulationCircumcircle(&scene, &cdt, this); tcc->setPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); @@ -299,8 +299,8 @@ MainWindow::MainWindow() // Manual handling of actions // QObject::connect(this->actionQuit, SIGNAL(triggered()), - this, SLOT(close())); - + this, SLOT(close())); + // We put mutually exclusive actions in an QActionGroup QActionGroup* ag = new QActionGroup(this); ag->addAction(this->actionInsertPolyline); @@ -339,7 +339,7 @@ MainWindow::MainWindow() this->addRecentFiles(this->menuFile, this->actionQuit); connect(this, SIGNAL(openRecentFile(QString)), - this, SLOT(open(QString))); + this, SLOT(open(QString))); } @@ -535,11 +535,11 @@ void MainWindow::on_actionLoadConstraints_triggered() { QString fileName = QFileDialog::getOpenFileName(this, - tr("Open Constraint File"), - ".", - tr("Edge files (*.edg);;" + tr("Open Constraint File"), + ".", + tr("Edge files (*.edg);;" "Plg files (*.plg);;" - "Poly files (*.poly)")); + "Poly files (*.poly)")); open(fileName); } @@ -656,10 +656,10 @@ void MainWindow::on_actionSaveConstraints_triggered() { QString fileName = QFileDialog::getSaveFileName(this, - tr("Save Constraints"), - ".", - tr("Poly files (*.poly)\n" - "Edge files (*.edg)\n" + tr("Save Constraints"), + ".", + tr("Poly files (*.poly)\n" + "Edge files (*.edg)\n" "VTU files (*.vtu)")); if(! fileName.isEmpty()){ saveConstraints(fileName); @@ -804,15 +804,15 @@ MainWindow::on_actionInsertRandomPoints_triggered() bool ok = false; const int number_of_points = - QInputDialog::getInt(this, - tr("Number of random points"), - tr("Enter number of random points"), - 100, - 0, - (std::numeric_limits::max)(), - 1, - &ok); - + QInputDialog::getInt(this, + tr("Number of random points"), + tr("Enter number of random points"), + 100, + 0, + (std::numeric_limits::max)(), + 1, + &ok); + if(!ok) { return; } diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 800b85233fa..f98c94b84a4 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -63,10 +63,10 @@ Release date: March 2019 `Arr_polycurve_basic_traits_2`. ### 2D and 3D Mesh Generation -- Added 3 functions for writing in modern VTK formats: - -`CGAL::output_to_vtu()` - -`CGAL::write_VTU()` - -`CGAL::write_VTP()` +- Added 3 functions for writing in XML VTK formats: + - `CGAL::output_to_vtu()` + - `CGAL::write_VTU()` + - `CGAL::write_VTP()` ### CGAL and the Boost Graph Library (BGL) diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index a1727dec86d..952100e9b32 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -13,6 +13,6 @@ namespace CGAL{ //! template void output_to_vtu(std::ostream& os, - const C3T3& c3t3, - bool binary = true); + const C3T3& c3t3, + bool binary = true); } From 3a7269b8f66e00f8e73507eb7a4dd0d3290c9978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 16 Jan 2019 12:00:07 +0100 Subject: [PATCH 121/186] improve doc --- BGL/doc/BGL/CGAL/IO/vtp_io.h | 31 ------------ BGL/doc/BGL/Doxyfile.in | 2 +- BGL/include/CGAL/IO/vtp_io.h | 73 ++++++++++++++++++---------- Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h | 22 ++++----- Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h | 17 +++---- 5 files changed, 68 insertions(+), 77 deletions(-) delete mode 100644 BGL/doc/BGL/CGAL/IO/vtp_io.h diff --git a/BGL/doc/BGL/CGAL/IO/vtp_io.h b/BGL/doc/BGL/CGAL/IO/vtp_io.h deleted file mode 100644 index 6604cdc7db3..00000000000 --- a/BGL/doc/BGL/CGAL/IO/vtp_io.h +++ /dev/null @@ -1,31 +0,0 @@ -//!\ingroup PkgBGLIOFct -//! -//! \brief writes the content of a triangulated surface mesh in the .vtp -//! XML format. -//! -//! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. -//! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" -//! -//! \param os a `std::ostream`. -//! \param mesh an instance of `TriangleMesh` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). -//! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the -//! ones listed below -//! -//! \cgalNamedParamsBegin -//! \cgalParamBegin{vertex_point_map} the property map with the points associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_point_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalParamBegin{vertex_index_map} the property map with the indices associated to -//! the vertices of `mesh`. If this parameter is omitted, an internal property map for -//! `CGAL::vertex_index_t` must be available in `TriangleMesh`. -//! \cgalParamEnd -//! \cgalNamedParamsEnd -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np); diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index 2ce62be128d..afdb3bfb933 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -14,7 +14,7 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \ - ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/IO/vtp_io.h diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h index 77e7c717e13..75e6e722c48 100644 --- a/BGL/include/CGAL/IO/vtp_io.h +++ b/BGL/include/CGAL/IO/vtp_io.h @@ -33,7 +33,7 @@ //todo try to factorize with functors namespace CGAL{ -// writes the polys appended data at the end of the .vtp file +// writes the polys appended data at the end of the .vtp file template void @@ -46,7 +46,7 @@ write_polys(std::ostream& os, typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - + std::vector connectivity_table; std::vector offsets; std::vector cell_type(num_faces(mesh),5); // triangle == 5 @@ -69,7 +69,7 @@ write_polys(std::ostream& os, //todo use named params for maps template -void +void write_polys_tag(std::ostream& os, const Mesh & mesh, bool binary, @@ -81,7 +81,7 @@ write_polys_tag(std::ostream& os, typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - + std::string formatattribute = binary ? " format=\"appended\"" : " format=\"ascii\""; @@ -96,14 +96,14 @@ write_polys_tag(std::ostream& os, os << " \n" << " \n"; offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); // 3 indices (size_t) per triangle + length of the encoded data (size_t) } else { - os << "\">\n"; + os << "\">\n"; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; ++fit ) @@ -114,18 +114,18 @@ write_polys_tag(std::ostream& os, } os << " \n"; } - + // Write offsets os << " \n"; offset += (num_faces(mesh) + 1) * sizeof(std::size_t); // 1 offset (size_t) per triangle + length of the encoded data (size_t) } else { - os << "\">\n"; + os << "\">\n"; std::size_t polys_offset = 0; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; @@ -133,7 +133,7 @@ write_polys_tag(std::ostream& os, { polys_offset += 3; os << polys_offset << " "; - } + } os << " \n"; } @@ -147,7 +147,7 @@ write_polys_tag(std::ostream& os, // 1 unsigned char per cell + length of the encoded data (size_t) } else { - os << "\">\n"; + os << "\">\n"; for(std::size_t i = 0; i< num_faces(mesh); ++i) os << "5 "; os << " \n"; @@ -159,12 +159,12 @@ write_polys_tag(std::ostream& os, //overload for facegraph template -void +void write_points_tag(std::ostream& os, const Mesh & mesh, bool binary, std::size_t& offset, - const NamedParameters& np) + const NamedParameters& np) { typedef typename boost::graph_traits::vertex_iterator vertex_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; @@ -182,12 +182,12 @@ write_points_tag(std::ostream& os, << format; if (binary) { - os << "\" offset=\"" << offset << "\"/>\n"; + os << "\" offset=\"" << offset << "\"/>\n"; offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); // 3 coords per points + length of the encoded data (size_t) } else { - os << "\">\n"; + os << "\">\n"; for( vertex_iterator vit = vertices(mesh).begin(); vit != vertices(mesh).end(); ++vit) @@ -201,7 +201,7 @@ write_points_tag(std::ostream& os, } -// writes the points appended data at the end of the .vtp file +// writes the points appended data at the end of the .vtp file template void @@ -228,14 +228,37 @@ write_polys_points(std::ostream& os, write_vector(os,coordinates); } -//public API - -template void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np) + const TriangleMesh& mesh, + bool binary, + const NamedParameters& np) { os << "\n" << "\n" << " " << "\n"; - - os << " \n"; std::size_t offset = 0; write_points_tag(os,mesh,binary,offset, np); @@ -260,7 +283,7 @@ void write_VTP(std::ostream& os, os << " \n" << " \n"; if (binary) { - os << "\n_"; + os << "\n_"; write_polys_points(os,mesh, np); write_polys(os,mesh, np); } diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h index 27c2dce50c4..c86692d761b 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h @@ -1,16 +1,16 @@ namespace CGAL{ //!\ingroup PkgMesh2 -//! \brief writes the content of a `CDT` in the .vtu -//! XML format. -//! -//! The triangles inside the domain and the constrained edges will be outputted. -//! -//! \tparam CDT a `Constrained_Delaunay_triangulation_2`. -//! -//! \param os a `std::ostream`. -//! \param tr an instance of `CDT` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). +//! \brief writes the faces of a domain and its constrained edges embedded in +//! a 2D constrained Delaunay triangulation using the `PolyData` XML format. +//! +//! The faces output are those for which `DelaunayMeshFaceBase_2::is_in_domain()` returns `true`, +//! the edges are those for which `ConstrainedTriangulationFaceBase_2::is_constained()` returns `true`. +//! \tparam CDT a `Constrained_Delaunay_triangulation_2` with face type model of `DelaunayMeshFaceBase_2`. +//! +//! \param os the stream used for writting. +//! \param tr the triangulated domain to be written. +//! \param binary decides if the data should be written in binary (`true`) +//! or in ASCII (`false`). //! template void write_VTU(std::ostream& os, diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h index 952100e9b32..63c44a13a64 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h @@ -1,15 +1,14 @@ namespace CGAL{ //! \ingroup PkgMesh_3IOFunctions -//! -//! \brief writes the content of a `C3t3` in the .vtu -//! XML format. -//! +//! +//! \brief writes a tetrahedron mesh using the `UnstructuredGrid` XML format. +//! //! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. -//! -//! \param os a `std::ostream`. -//! \param c3t3 an instance of `C3T3` to be written. -//! \param binary decides if the data should be written in binary(`true`) -//! or in ASCII(`false`). +//! +//! \param os the stream used for writting. +//! \param c3t3 the instance of `C3T3` to be written. +//! \param binary decides if the data should be written in binary (`true`) +//! or in ASCII (`false`). //! template void output_to_vtu(std::ostream& os, From 40cf3869ba1ddf183db8b10dac9c6fad64be8641 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 16 Jan 2019 16:15:01 +0100 Subject: [PATCH 122/186] My changes for write_vtp --- BGL/doc/BGL/Doxyfile.in | 3 +- BGL/doc/BGL/PackageDescription.txt | 2 +- BGL/include/CGAL/IO/vtp_io.h | 302 ------------------ BGL/include/CGAL/boost/graph/io.h | 279 ++++++++++++++++ Installation/CHANGES.md | 3 +- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 4 +- 6 files changed, 285 insertions(+), 308 deletions(-) delete mode 100644 BGL/include/CGAL/IO/vtp_io.h diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index afdb3bfb933..9681886835a 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -14,8 +14,7 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \ - ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h \ - ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/IO/vtp_io.h + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \ diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index cde8cb34f89..2ae5f33bd19 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -708,7 +708,7 @@ user might encounter. ## I/O Functions ## - \link PkgBGLIOFct CGAL::read_off() \endlink - \link PkgBGLIOFct CGAL::write_off() \endlink -- \link PkgBGLIOFct CGAL::write_VTP() \endlink +- \link PkgBGLIOFct CGAL::write_vtp() \endlink - \link PkgBGLIOFct CGAL::write_wrl() \endlink */ diff --git a/BGL/include/CGAL/IO/vtp_io.h b/BGL/include/CGAL/IO/vtp_io.h deleted file mode 100644 index 75e6e722c48..00000000000 --- a/BGL/include/CGAL/IO/vtp_io.h +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) 2018 GeometryFactory (France). -// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). -// Copyright (c) 2009 INRIA Sophia-Antipolis (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) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno - -#ifndef CGAL_VTP_IO_H -#define CGAL_VTP_IO_H - -#include - - -#include -#include -#include - - -//todo try to factorize with functors -namespace CGAL{ -// writes the polys appended data at the end of the .vtp file -template -void -write_polys(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - std::vector connectivity_table; - std::vector offsets; - std::vector cell_type(num_faces(mesh),5); // triangle == 5 - - std::size_t off = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - off += 3; - offsets.push_back(off); - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - connectivity_table.push_back(V[v]); - } - write_vector(os,connectivity_table); - write_vector(os,offsets); - write_vector(os,cell_type); -} -//todo use named params for maps -template -void -write_polys_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; - Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), - get_const_property_map(CGAL::internal_np::vertex_index, mesh)); - - std::string formatattribute = - binary ? " format=\"appended\"" : " format=\"ascii\""; - - std::string typeattribute; - switch(sizeof(std::size_t)) { - case 8: typeattribute = " type=\"UInt64\""; break; - case 4: typeattribute = " type=\"UInt32\""; break; - default: CGAL_error_msg("Unknown size of std::size_t"); - } - - // Write connectivity table - os << " \n" - << " \n"; - offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); - // 3 indices (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - BOOST_FOREACH(vertex_descriptor v, - vertices_around_face(halfedge(*fit, mesh), mesh)) - os << V[v] << " "; - } - os << " \n"; - } - - // Write offsets - os << " \n"; - offset += (num_faces(mesh) + 1) * sizeof(std::size_t); - // 1 offset (size_t) per triangle + length of the encoded data (size_t) - } - else { - os << "\">\n"; - std::size_t polys_offset = 0; - for( face_iterator fit = faces(mesh).begin() ; - fit != faces(mesh).end() ; - ++fit ) - { - polys_offset += 3; - os << polys_offset << " "; - } - os << " \n"; - } - - // Write cell type (triangle == 5) - os << " \n"; - offset += num_faces(mesh) + sizeof(std::size_t); - // 1 unsigned char per cell + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for(std::size_t i = 0; i< num_faces(mesh); ++i) - os << "5 "; - os << " \n"; - } - os << " \n"; -} - -//todo : use namedparams for points and ids -//overload for facegraph -template -void -write_points_tag(std::ostream& os, - const Mesh & mesh, - bool binary, - std::size_t& offset, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - - std::string format = binary ? "appended" : "ascii"; - std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; - - os << " \n" - << " \n"; - offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); - // 3 coords per points + length of the encoded data (size_t) - } - else { - os << "\">\n"; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " - << get(vpm, *vit).z() << " "; - } - os << " \n"; - } - os << " \n"; -} - - -// writes the points appended data at the end of the .vtp file -template -void -write_polys_points(std::ostream& os, - const Mesh & mesh, - const NamedParameters& np) -{ - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; - Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), - get_const_property_map(CGAL::vertex_point, mesh)); - typedef typename boost::property_traits::value_type Point_t; - typedef typename CGAL::Kernel_traits::Kernel Gt; - typedef typename Gt::FT FT; - std::vector coordinates; - for( vertex_iterator vit = vertices(mesh).begin(); - vit != vertices(mesh).end(); - ++vit) - { - coordinates.push_back(get(vpm, *vit).x()); - coordinates.push_back(get(vpm, *vit).y()); - coordinates.push_back(get(vpm, *vit).z()); - } - write_vector(os,coordinates); -} - -/*!\ingroup PkgBGLIOFct - * - * \brief writes a triangulated surface mesh in the `PolyData` XML format. - * - * \tparam TriangleMesh a model of `FaceListGraph` with only triangle faces. - * \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * \param os the stream used for writting. - * \param mesh the triangle mesh to be written. - * \param binary decides if the data should be written in binary (`true`) - * or in ASCII (`false`). - * \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the - * ones listed below - * - * \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to - * the vertices of `mesh`. If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` must be available in `TriangleMesh`. - * \cgalParamEnd - * \cgalParamBegin{vertex_index_map} the property map with the indices associated to - * the vertices of `mesh`. If this parameter is omitted, an internal property map for - * `CGAL::vertex_index_t` must be available in `TriangleMesh`. - * \cgalParamEnd - * \cgalNamedParamsEnd - */ -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary, - const NamedParameters& np) -{ - os << "\n" - << "\n" - << " " << "\n"; - - os << " \n"; - std::size_t offset = 0; - write_points_tag(os,mesh,binary,offset, np); - write_polys_tag(os,mesh,binary,offset, np); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_polys_points(os,mesh, np); - write_polys(os,mesh, np); - } - os << "\n"; -} - -template -void write_VTP(std::ostream& os, - const TriangleMesh& mesh, - bool binary = true) -{ - write_VTP(os, mesh, binary, CGAL::parameters::all_default()); -} - -} //end CGAL -#endif // CGAL_VTP_IO_H diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index 60dcfca72ad..11a2b60ce0c 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace CGAL { /*! @@ -401,6 +402,284 @@ bool write_inp(std::ostream& os, { return write_inp(os, g, name, type, parameters::all_default()); } + +namespace internal { + namespace write_vtp { + +// writes the polys appended data at the end of the .vtp file +template +void +write_polys(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + std::vector connectivity_table; + std::vector offsets; + std::vector cell_type(num_faces(mesh),5); // triangle == 5 + + std::size_t off = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + off += 3; + offsets.push_back(off); + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + connectivity_table.push_back(V[v]); + } + write_vector(os,connectivity_table); + write_vector(os,offsets); + write_vector(os,cell_type); +} +//todo use named params for maps +template +void +write_polys_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_iterator face_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; + Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), + get_const_property_map(CGAL::internal_np::vertex_index, mesh)); + + std::string formatattribute = + binary ? " format=\"appended\"" : " format=\"ascii\""; + + std::string typeattribute; + switch(sizeof(std::size_t)) { + case 8: typeattribute = " type=\"UInt64\""; break; + case 4: typeattribute = " type=\"UInt32\""; break; + default: CGAL_error_msg("Unknown size of std::size_t"); + } + + // Write connectivity table + os << " \n" + << " \n"; + offset += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); + // 3 indices (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + BOOST_FOREACH(vertex_descriptor v, + vertices_around_face(halfedge(*fit, mesh), mesh)) + os << V[v] << " "; + } + os << " \n"; + } + + // Write offsets + os << " \n"; + offset += (num_faces(mesh) + 1) * sizeof(std::size_t); + // 1 offset (size_t) per triangle + length of the encoded data (size_t) + } + else { + os << "\">\n"; + std::size_t polys_offset = 0; + for( face_iterator fit = faces(mesh).begin() ; + fit != faces(mesh).end() ; + ++fit ) + { + polys_offset += 3; + os << polys_offset << " "; + } + os << " \n"; + } + + // Write cell type (triangle == 5) + os << " \n"; + offset += num_faces(mesh) + sizeof(std::size_t); + // 1 unsigned char per cell + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for(std::size_t i = 0; i< num_faces(mesh); ++i) + os << "5 "; + os << " \n"; + } + os << " \n"; +} + +//todo : use namedparams for points and ids +//overload for facegraph +template +void +write_points_tag(std::ostream& os, + const Mesh & mesh, + bool binary, + std::size_t& offset, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; + + os << " \n" + << " \n"; + offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); + // 3 coords per points + length of the encoded data (size_t) + } + else { + os << "\">\n"; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " + << get(vpm, *vit).z() << " "; + } + os << " \n"; + } + os << " \n"; +} + + +// writes the points appended data at the end of the .vtp file +template +void +write_polys_points(std::ostream& os, + const Mesh & mesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; + Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), + get_const_property_map(CGAL::vertex_point, mesh)); + typedef typename boost::property_traits::value_type Point_t; + typedef typename CGAL::Kernel_traits::Kernel Gt; + typedef typename Gt::FT FT; + std::vector coordinates; + for( vertex_iterator vit = vertices(mesh).begin(); + vit != vertices(mesh).end(); + ++vit) + { + coordinates.push_back(get(vpm, *vit).x()); + coordinates.push_back(get(vpm, *vit).y()); + coordinates.push_back(get(vpm, *vit).z()); + } + write_vector(os,coordinates); +} + + } // end namespace CGAL::internal::write_vtp +} // end namespace CGAL::internal + +/*!\ingroup PkgBGLIOFct + * + * \brief writes a triangulated surface mesh in the `PolyData` XML format. + * + * \tparam TriangleMesh a model of `FaceListGraph` with only triangle faces. + * \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * \param os the stream used for writting. + * \param mesh the triangle mesh to be written. + * \param mode decides if the data should be written in binary (`IO::BINARY`) + * or in ASCII (`IO::ASCII`). `IO::BINARY` is the default. + * \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the + * ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} the property map with the points associated to + * the vertices of `mesh`. If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` must be available in `TriangleMesh`. + * \cgalParamEnd + * \cgalParamBegin{vertex_index_map} the property map with the indices associated to + * the vertices of `mesh`. If this parameter is omitted, an internal property map for + * `CGAL::vertex_index_t` must be available in `TriangleMesh`. + * \cgalParamEnd + * \cgalNamedParamsEnd + */ +template +void write_vtp(std::ostream& os, + const TriangleMesh& mesh, + IO::Mode mode, + const NamedParameters& np) +{ + os << "\n" + << "\n" + << " " << "\n"; + + os << " \n"; + std::size_t offset = 0; + const bool binary = (mode == IO::BINARY); + internal::write_vtp::write_points_tag(os,mesh,binary,offset, np); + internal::write_vtp::write_polys_tag(os,mesh,binary,offset, np); + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + internal::write_vtp::write_polys_points(os,mesh, np); + internal::write_vtp::write_polys(os,mesh, np); + } + os << "\n"; +} + +/*! \ingroup PkgBGLIOFct + * Overload that implements the default arguments + * + * Calls `write_vtp(os, mesh, mode, parameters::all_default())`. + */ +template +void write_vtp(std::ostream& os, + const TriangleMesh& mesh, + IO::Mode mode = IO::BINARY) +{ + write_vtp(os, mesh, mode, CGAL::parameters::all_default()); +} + } // namespace CGAL #endif // CGAL_BOOST_GRAPH_IO_H diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index f98c94b84a4..4ad6bfb5279 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -66,7 +66,8 @@ Release date: March 2019 - Added 3 functions for writing in XML VTK formats: - `CGAL::output_to_vtu()` - `CGAL::write_VTU()` - - `CGAL::write_VTP()` + - `CGAL::write_vtp()`, that writes a triangulated face graph in a + `.vtp` file. ### CGAL and the Boost Graph Library (BGL) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 2eebc0ce1f1..24eca7c80e1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include @@ -329,7 +329,7 @@ public: std::ofstream os(output_filename.data()); os << std::setprecision(16); //write header - CGAL::write_VTP(os, *mesh); + CGAL::write_vtp(os, *mesh); } } else From 1754057d24051840948b3e8633519596fbd85f5c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 16 Jan 2019 16:50:45 +0100 Subject: [PATCH 123/186] My changes to write_vtu --- .../Constrained_Delaunay_triangulation_2.cpp | 4 ++-- Installation/CHANGES.md | 4 ++-- .../doc/Mesh_2/CGAL/IO/{vtk_io_2.h => write_vtu.h} | 12 ++++++------ Mesh_2/doc/Mesh_2/PackageDescription.txt | 9 ++++++++- Mesh_2/include/CGAL/IO/{vtk_io_2.h => write_vtu.h} | 7 ++++--- 5 files changed, 22 insertions(+), 14 deletions(-) rename Mesh_2/doc/Mesh_2/CGAL/IO/{vtk_io_2.h => write_vtu.h} (70%) rename Mesh_2/include/CGAL/IO/{vtk_io_2.h => write_vtu.h} (98%) diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index efec041a6f3..3285004ecb1 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include // Qt headers #include @@ -676,7 +676,7 @@ MainWindow::saveConstraints(QString fileName) output << cdt; else if (output) { - CGAL::write_VTU(output, cdt); + CGAL::write_vtu(output, cdt); } } diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 4ad6bfb5279..fe1fc7a4366 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -64,8 +64,8 @@ Release date: March 2019 ### 2D and 3D Mesh Generation - Added 3 functions for writing in XML VTK formats: - - `CGAL::output_to_vtu()` - - `CGAL::write_VTU()` + - `CGAL::output_to_vtu()`, + - `CGAL::write_vtu()`, that writes a 2D mesh in a `.vtu` file, - `CGAL::write_vtp()`, that writes a triangulated face graph in a `.vtp` file. diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h b/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h similarity index 70% rename from Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h rename to Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h index c86692d761b..471e824389d 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h @@ -1,19 +1,19 @@ namespace CGAL{ -//!\ingroup PkgMesh2 +//!\ingroup PkgMesh2IO //! \brief writes the faces of a domain and its constrained edges embedded in //! a 2D constrained Delaunay triangulation using the `PolyData` XML format. //! //! The faces output are those for which `DelaunayMeshFaceBase_2::is_in_domain()` returns `true`, -//! the edges are those for which `ConstrainedTriangulationFaceBase_2::is_constained()` returns `true`. +//! the edges are those for which `ConstrainedTriangulationFaceBase_2::is_constrained()` returns `true`. //! \tparam CDT a `Constrained_Delaunay_triangulation_2` with face type model of `DelaunayMeshFaceBase_2`. //! //! \param os the stream used for writting. //! \param tr the triangulated domain to be written. -//! \param binary decides if the data should be written in binary (`true`) -//! or in ASCII (`false`). +//! \param mode decides if the data should be written in binary (`IO::BINARY`) +//! or in ASCII (`IO::ASCII`). //! template -void write_VTU(std::ostream& os, +void write_vtu(std::ostream& os, const CDT& tr, - bool binary = true); + IO::Mode mode = IO::BINARY); } diff --git a/Mesh_2/doc/Mesh_2/PackageDescription.txt b/Mesh_2/doc/Mesh_2/PackageDescription.txt index 38289e92ef8..313f3901185 100644 --- a/Mesh_2/doc/Mesh_2/PackageDescription.txt +++ b/Mesh_2/doc/Mesh_2/PackageDescription.txt @@ -11,6 +11,11 @@ /// \defgroup PkgMesh2Enum Enumerations /// \ingroup PkgMesh2Ref +/// \defgroup PkgMesh2IO I/O Functions +/// \ingroup PkgMesh2Ref +/// In addition to the stream extraction and insertion operators for +/// %CGAL 2D triangulations, the following functions can be used. + /*! \addtogroup PkgMesh2Ref \cgalPkgDescriptionBegin{2D Conforming Triangulations and Meshes,PkgMesh2} @@ -57,7 +62,9 @@ The package can handle intersecting input constraints and set no restriction on - `CGAL::make_conforming_Gabriel_2` - `CGAL::refine_Delaunay_mesh_2` - `CGAL::lloyd_optimize_mesh_2` -- `CGAL::write_VTU()` + +## I/O Functions ## +- `CGAL::write_vtu()` ## Enumerations ## - `CGAL::Mesh_optimization_return_code` diff --git a/Mesh_2/include/CGAL/IO/vtk_io_2.h b/Mesh_2/include/CGAL/IO/write_vtu.h similarity index 98% rename from Mesh_2/include/CGAL/IO/vtk_io_2.h rename to Mesh_2/include/CGAL/IO/write_vtu.h index 160e383bcf6..155e147ec7c 100644 --- a/Mesh_2/include/CGAL/IO/vtk_io_2.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -275,9 +275,9 @@ write_points(std::ostream& os, template -void write_VTU(std::ostream& os, - const CDT& tr, - bool binary = true) +void write_vtu(std::ostream& os, + const CDT& tr, + IO::Mode mode = IO::BINARY) { typedef typename CDT::Vertex_handle Vertex_handle; std::map V; @@ -309,6 +309,7 @@ void write_VTU(std::ostream& os, os << " \n"; std::size_t offset = 0; + const bool binary = (mode == IO::BINARY); write_points_tag(os,tr,V,binary,offset); write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); os << " \n" From c951217d8b18c994c6831123a681146a641a5cc9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 17 Jan 2019 10:11:41 +0100 Subject: [PATCH 124/186] Add missing handling of vmin/vmax in clusters and meshes --- .../Classification/Cluster_classification.cpp | 37 ++++++++++++++----- .../Surface_mesh_item_classification.cpp | 31 +++++++++++++--- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 6dce115eb68..a8ed8358285 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -549,19 +549,29 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) float min = std::numeric_limits::max(); float max = -std::numeric_limits::max(); - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->first_selected(); ++ it) + if (vmin != NULL && vmax != NULL + && *vmin != std::numeric_limits::infinity() + && *vmax != std::numeric_limits::infinity()) { - int cid = m_cluster_id[*it]; - if (cid != -1) + min = *vmin; + max = *vmax; + } + else + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) { - if (feature->value(cid) > max) - max = feature->value(cid); - if (feature->value(cid) < min) - min = feature->value(cid); + int cid = m_cluster_id[*it]; + if (cid != -1) + { + if (feature->value(cid) > max) + max = feature->value(cid); + if (feature->value(cid) < min) + min = feature->value(cid); + } } } - + for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) { @@ -569,11 +579,20 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) if (cid != -1) { float v = (feature->value(cid) - min) / (max - min); + if (v < 0.f) v = 0.f; + if (v > 1.f) v = 1.f; + m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } else m_points->point_set()->set_color(*it); } + + if (vmin != NULL && vmax != NULL) + { + *vmin = min; + *vmax = max; + } } } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 3f6fdcec51f..eb0ce9b3bc5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -172,21 +172,40 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo float min = std::numeric_limits::max(); float max = -std::numeric_limits::max(); - BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + if (vmin != NULL && vmax != NULL + && *vmin != std::numeric_limits::infinity() + && *vmax != std::numeric_limits::infinity()) { - if (feature->value(fd) > max) - max = feature->value(fd); - if (feature->value(fd) < min) - min = feature->value(fd); + min = *vmin; + max = *vmax; } - + else + { + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) + { + if (feature->value(fd) > max) + max = feature->value(fd); + if (feature->value(fd) < min) + min = feature->value(fd); + } + } + BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) { float v = (feature->value(fd) - min) / (max - min); + if (v < 0.f) v = 0.f; + if (v > 1.f) v = 1.f; + m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), (unsigned char)(ramp.g(v) * 255), (unsigned char)(ramp.b(v) * 255)); } + + if (vmin != NULL && vmax != NULL) + { + *vmin = min; + *vmax = max; + } } } } From c1d4608665caf1171849a67a4bacdce990989603 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 16 Jan 2019 16:59:08 +0100 Subject: [PATCH 125/186] My changes to output_to_vtu --- Mesh_2/include/CGAL/IO/write_vtu.h | 6 +++--- Mesh_3/doc/Mesh_3/CGAL/IO/{vtk_io.h => output_to_vtu.h} | 8 ++++---- Mesh_3/include/CGAL/IO/{vtk_io.h => output_to_vtu.h} | 9 +++++---- Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) rename Mesh_3/doc/Mesh_3/CGAL/IO/{vtk_io.h => output_to_vtu.h} (66%) rename Mesh_3/include/CGAL/IO/{vtk_io.h => output_to_vtu.h} (98%) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 155e147ec7c..15a3813e221 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -21,8 +21,8 @@ // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno -#ifndef CGAL_VTK_IO_H -#define CGAL_VTK_IO_H +#ifndef CGAL_WRITE_VTU_H +#define CGAL_WRITE_VTU_H #include #include @@ -323,4 +323,4 @@ void write_vtu(std::ostream& os, } } //end CGAL -#endif // CGAL_VTK_IO_H +#endif // CGAL_WRITE_VTU_H diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h b/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h similarity index 66% rename from Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h rename to Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h index 63c44a13a64..7cd634d987c 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/vtk_io.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h @@ -1,5 +1,5 @@ namespace CGAL{ -//! \ingroup PkgMesh_3IOFunctions +//! \ingroup PkgMesh3IOFunctions //! //! \brief writes a tetrahedron mesh using the `UnstructuredGrid` XML format. //! @@ -7,11 +7,11 @@ namespace CGAL{ //! //! \param os the stream used for writting. //! \param c3t3 the instance of `C3T3` to be written. -//! \param binary decides if the data should be written in binary (`true`) -//! or in ASCII (`false`). +//! \param mode decides if the data should be written in binary (`IO::BINARY`) +//! or in ASCII (`IO::ASCII`). //! template void output_to_vtu(std::ostream& os, const C3T3& c3t3, - bool binary = true); + IO::Mode mode = IO::BINARY); } diff --git a/Mesh_3/include/CGAL/IO/vtk_io.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h similarity index 98% rename from Mesh_3/include/CGAL/IO/vtk_io.h rename to Mesh_3/include/CGAL/IO/output_to_vtu.h index 182a8b2cb7d..37ec370ea3b 100644 --- a/Mesh_3/include/CGAL/IO/vtk_io.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -20,8 +20,8 @@ // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno -#ifndef CGAL_VTK_IO_H -#define CGAL_VTK_IO_H +#ifndef CGAL_OUTPUT_TO_VTU_H +#define CGAL_OUTPUT_TO_VTU_H #include @@ -257,8 +257,8 @@ write_attributes(std::ostream& os, //public API template void output_to_vtu(std::ostream& os, - const C3T3& c3t3, - bool binary = true) + const C3T3& c3t3, + IO::Mode mode = IO::BINARY) { typedef typename C3T3::Triangulation Tr; typedef typename Tr::Vertex_handle Vertex_handle; @@ -284,6 +284,7 @@ void output_to_vtu(std::ostream& os, os << " \n"; std::size_t offset = 0; + const bool binary = (mode == IO::BINARY); write_points_tag(os,tr,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); std::vector mids; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 24eca7c80e1..f91da4aaf92 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include From 11db055bfe116c2783808fb5023db3e0fc6132b4 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 16 Jan 2019 17:16:40 +0100 Subject: [PATCH 126/186] Modify CHANGES.md Split the changes into two different paragraphs (2D/3D meshes, and BGL). --- Installation/CHANGES.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fe1fc7a4366..9a50868e0ef 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -63,15 +63,17 @@ Release date: March 2019 `Arr_polycurve_basic_traits_2`. ### 2D and 3D Mesh Generation -- Added 3 functions for writing in XML VTK formats: - - `CGAL::output_to_vtu()`, + +- Added two functions for writing in XML VTK formats: - `CGAL::write_vtu()`, that writes a 2D mesh in a `.vtu` file, - - `CGAL::write_vtp()`, that writes a triangulated face graph in a - `.vtp` file. + - `CGAL::output_to_vtu()`, that writes a 3D mesh in a `.vtu` file. ### CGAL and the Boost Graph Library (BGL) -- Add function `write_wrl()` for writing into VRML 2.0 format. +- Added function `write_wrl()` for writing into VRML 2.0 format. +- Added functions `CGAL::write_vtp()` for writing a triangulated + face graph in a `.vtp` file (XML VTK format). + Release 4.13 ------------ From 06b973b5348e63ccb630624f69347a282b47fbe2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 16 Jan 2019 17:17:13 +0100 Subject: [PATCH 127/186] Update the Doxygen link --- BGL/doc/BGL/PackageDescription.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 2ae5f33bd19..a3b67ca990c 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -708,8 +708,8 @@ user might encounter. ## I/O Functions ## - \link PkgBGLIOFct CGAL::read_off() \endlink - \link PkgBGLIOFct CGAL::write_off() \endlink -- \link PkgBGLIOFct CGAL::write_vtp() \endlink - \link PkgBGLIOFct CGAL::write_wrl() \endlink +- `CGAL::write_vtp()` */ From eadb08d976161381dd80a1d2b1984bd8ac4d77cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 17 Jan 2019 15:43:42 +0100 Subject: [PATCH 128/186] replace mode by a np --- BGL/doc/BGL/NamedParameters.txt | 7 +++++++ BGL/include/CGAL/boost/graph/io.h | 20 +++++++------------ .../CGAL/boost/graph/parameters_interface.h | 1 + BGL/test/BGL/test_cgal_bgl_named_params.cpp | 3 +++ Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h | 2 +- Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h | 2 +- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/BGL/doc/BGL/NamedParameters.txt b/BGL/doc/BGL/NamedParameters.txt index f775e26ce48..ce3be60f8f4 100644 --- a/BGL/doc/BGL/NamedParameters.txt +++ b/BGL/doc/BGL/NamedParameters.txt @@ -81,6 +81,13 @@ being marked or not.\n Default: a default property map where no edge is constrained \cgalNPEnd +\cgalNPBegin{use_binary_mode} \anchor BGL_use_binary_mode +is a Boolean indicating whether the binary mode or the ASCII mode should be used +when writing data into a stream.\n +Type: `bool`\n +Default: Function specific. +\cgalNPEnd + \cgalNPBegin{METIS_options} \anchor BGL_METIS_options is a parameter used in `partition_graph()` and `partition_dual_graph()` to pass options to the METIS graph partitioner. The many options of METIS diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index 11a2b60ce0c..cb5c8082b21 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -611,14 +611,15 @@ write_polys_points(std::ostream& os, * \tparam TriangleMesh a model of `FaceListGraph` with only triangle faces. * \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * - * \param os the stream used for writting. + * \param os the stream used for writing. * \param mesh the triangle mesh to be written. - * \param mode decides if the data should be written in binary (`IO::BINARY`) - * or in ASCII (`IO::ASCII`). `IO::BINARY` is the default. * \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the * ones listed below * * \cgalNamedParamsBegin + * \cgalParamBegin{use_binary_mode} a Boolean indicating if the + * data should be written in binary (`true`, the default) or in ASCII (`false`). + * \cgalParamEnd * \cgalParamBegin{vertex_point_map} the property map with the points associated to * the vertices of `mesh`. If this parameter is omitted, an internal property map for * `CGAL::vertex_point_t` must be available in `TriangleMesh`. @@ -633,7 +634,6 @@ template void write_vtp(std::ostream& os, const TriangleMesh& mesh, - IO::Mode mode, const NamedParameters& np) { os << "\n" @@ -654,7 +654,7 @@ void write_vtp(std::ostream& os, os << " \n"; std::size_t offset = 0; - const bool binary = (mode == IO::BINARY); + const bool binary = boost::choose_param(boost::get_param(np, internal_np::use_binary_mode), true); internal::write_vtp::write_points_tag(os,mesh,binary,offset, np); internal::write_vtp::write_polys_tag(os,mesh,binary,offset, np); os << " \n" @@ -667,17 +667,11 @@ void write_vtp(std::ostream& os, os << "\n"; } -/*! \ingroup PkgBGLIOFct - * Overload that implements the default arguments - * - * Calls `write_vtp(os, mesh, mode, parameters::all_default())`. - */ template void write_vtp(std::ostream& os, - const TriangleMesh& mesh, - IO::Mode mode = IO::BINARY) + const TriangleMesh& mesh) { - write_vtp(os, mesh, mode, CGAL::parameters::all_default()); + write_vtp(os, mesh, CGAL::parameters::all_default()); } } // namespace CGAL diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 9e38eec688d..8c8d7549ab1 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -28,6 +28,7 @@ CGAL_add_named_parameter(edge_is_constrained_t, edge_is_constrained, edge_is_con CGAL_add_named_parameter(first_index_t, first_index, first_index) CGAL_add_named_parameter(number_of_iterations_t, number_of_iterations, number_of_iterations) CGAL_add_named_parameter(verbosity_level_t, verbosity_level, verbosity_level) +CGAL_add_named_parameter(use_binary_mode_t, use_binary_mode, use_binary_mode) CGAL_add_named_parameter(metis_options_t, METIS_options, METIS_options) CGAL_add_named_parameter(vertex_partition_id_t, vertex_partition_id, vertex_partition_id_map) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index 71cf1369565..346043ff037 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -102,6 +102,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::use_binary_mode).v == 51); assert(get_param(np, CGAL::internal_np::projection_functor).v == 42); assert(get_param(np, CGAL::internal_np::apply_per_connected_component).v == 46); assert(get_param(np, CGAL::internal_np::output_iterator).v == 47); @@ -182,6 +183,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<51>(get_param(np, CGAL::internal_np::use_binary_mode)); check_same_type<42>(get_param(np, CGAL::internal_np::projection_functor)); check_same_type<46>(get_param(np, CGAL::internal_np::apply_per_connected_component)); check_same_type<47>(get_param(np, CGAL::internal_np::output_iterator)); @@ -241,6 +243,7 @@ int main() .weight_calculator(A<39>(39)) .preserve_genus(A<40>(40)) .verbosity_level(A<41>(41)) + .use_binary_mode(A<51>(51)) .projection_functor(A<42>(42)) .throw_on_self_intersection(A<43>(43)) .clip_volume(A<44>(44)) diff --git a/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h b/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h index 471e824389d..146cb6bb785 100644 --- a/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h +++ b/Mesh_2/doc/Mesh_2/CGAL/IO/write_vtu.h @@ -7,7 +7,7 @@ namespace CGAL{ //! the edges are those for which `ConstrainedTriangulationFaceBase_2::is_constrained()` returns `true`. //! \tparam CDT a `Constrained_Delaunay_triangulation_2` with face type model of `DelaunayMeshFaceBase_2`. //! -//! \param os the stream used for writting. +//! \param os the stream used for writing. //! \param tr the triangulated domain to be written. //! \param mode decides if the data should be written in binary (`IO::BINARY`) //! or in ASCII (`IO::ASCII`). diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h b/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h index 7cd634d987c..70a64f586c7 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/doc/Mesh_3/CGAL/IO/output_to_vtu.h @@ -5,7 +5,7 @@ namespace CGAL{ //! //! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. //! -//! \param os the stream used for writting. +//! \param os the stream used for writing. //! \param c3t3 the instance of `C3T3` to be written. //! \param mode decides if the data should be written in binary (`IO::BINARY`) //! or in ASCII (`IO::ASCII`). From 043d3c60fa06f5161a38ff4779ba09150e772bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 17 Jan 2019 16:29:59 +0100 Subject: [PATCH 129/186] Fixed wrongly using the (unsigned) degree type in CatmullClark mask computations --- .../include/CGAL/Subdivision_method_3/subdivision_masks_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h index e6353e38b61..6e753295000 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h @@ -215,13 +215,13 @@ public: /// computes the Catmull-Clark vertex-point `pt` of the vertex `vertex`. void vertex_node(vertex_descriptor vertex, Point& pt) { Halfedge_around_target_circulator vcir(vertex, *(this->pmesh)); - typename boost::graph_traits::degree_size_type n = degree(vertex, *(this->pmesh)); + int n = static_cast(degree(vertex, *(this->pmesh))); FT Q[] = {0.0, 0.0, 0.0}, R[] = {0.0, 0.0, 0.0}; Point_ref S = get(this->vpmap,vertex); Point q; - for (typename boost::graph_traits::degree_size_type i = 0; i < n; i++, ++vcir) { + for (int i = 0; i < n; i++, ++vcir) { Point_ref p2 = get(this->vpmap, target(opposite(*vcir, *(this->pmesh)), *(this->pmesh))); R[0] += (S[0] + p2[0]) / 2; R[1] += (S[1] + p2[1]) / 2; From dbd569d51c2b8ddc8c1f013059cba0c1280d854e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 17 Jan 2019 18:29:27 +0100 Subject: [PATCH 130/186] Fix the result of check_headers --- Mesh_2/include/CGAL/IO/write_vtu.h | 9 ++++++--- Mesh_3/include/CGAL/IO/output_to_vtu.h | 5 ++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 15a3813e221..e2a5b71b911 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -24,11 +24,14 @@ #ifndef CGAL_WRITE_VTU_H #define CGAL_WRITE_VTU_H -#include -#include - #include +#include +#include +#include +#include +#include +#include //todo try to factorize with functors namespace CGAL{ diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 37ec370ea3b..7e802343cfe 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -26,8 +26,11 @@ #include -#include +#include #include +#include +#include +#include #include //todo try to factorize with functors From 8f658695f81de2f0afb13c2679b0561c713904f6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 21 Jan 2019 16:17:28 +0100 Subject: [PATCH 131/186] Rename internal methods to avoid a namespace class There was two methods named `CGAL::write_points_tag`. I renamed then to: - `write_c3t3_points_tag`, and - `write_cdt_points_tag`. --- Mesh_2/include/CGAL/IO/write_vtu.h | 12 ++++++------ Mesh_3/include/CGAL/IO/output_to_vtu.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index e2a5b71b911..4af962fba72 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -206,11 +206,11 @@ write_cells_2(std::ostream& os, // writes the points tags before binary data is appended template void -write_points_tag(std::ostream& os, - const Tr & tr, - std::map & V, - bool binary, - std::size_t& offset) +write_cdt_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) { std::size_t dim = 2; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; @@ -313,7 +313,7 @@ void write_vtu(std::ostream& os, << "\" NumberOfCells=\"" << number_of_triangles + std::distance(tr.constrained_edges_begin(), tr.constrained_edges_end()) << "\">\n"; std::size_t offset = 0; const bool binary = (mode == IO::BINARY); - write_points_tag(os,tr,V,binary,offset); + write_cdt_points_tag(os,tr,V,binary,offset); write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); os << " \n" << " \n"; diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 7e802343cfe..369a0d45a47 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -150,11 +150,11 @@ write_cells(std::ostream& os, template void -write_points_tag(std::ostream& os, - const Tr & tr, - std::map & V, - bool binary, - std::size_t& offset) +write_c3t3_points_tag(std::ostream& os, + const Tr & tr, + std::map & V, + bool binary, + std::size_t& offset) { std::size_t dim = 3; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; @@ -288,7 +288,7 @@ void output_to_vtu(std::ostream& os, << "\" NumberOfCells=\"" << c3t3.number_of_cells() << "\">\n"; std::size_t offset = 0; const bool binary = (mode == IO::BINARY); - write_points_tag(os,tr,V,binary,offset); + write_c3t3_points_tag(os,tr,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); std::vector mids; os << " Date: Mon, 21 Jan 2019 16:32:37 +0100 Subject: [PATCH 132/186] Rename two write_points functions as well --- Mesh_2/include/CGAL/IO/write_vtu.h | 10 +++++----- Mesh_3/include/CGAL/IO/output_to_vtu.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 4af962fba72..9580d434b49 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -252,10 +252,10 @@ write_cdt_points_tag(std::ostream& os, // writes the points appended data at the end of the .vtu file template void -write_points(std::ostream& os, - const Tr & tr, - std::map & V) +write_cdt_points(std::ostream& os, + const Tr & tr, + std::map & V) { std::size_t dim = 2; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; @@ -319,7 +319,7 @@ void write_vtu(std::ostream& os, << " \n"; if (binary) { os << "\n_"; - write_points(os,tr,V); // write points before cells to fill the std::map V + write_cdt_points(os,tr,V); // write points before cells to fill the std::map V write_cells_2(os,tr, number_of_triangles, V); } os << "\n"; diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 369a0d45a47..c5d621462c4 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -196,10 +196,10 @@ write_c3t3_points_tag(std::ostream& os, // writes the points appended data at the end of the .vtu file template void -write_points(std::ostream& os, - const Tr & tr, - std::map & V) +write_c3t3_points(std::ostream& os, + const Tr & tr, + std::map & V) { std::size_t dim = 3; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; @@ -299,7 +299,7 @@ void output_to_vtu(std::ostream& os, << " \n"; if (binary) { os << "\n_"; - write_points(os,tr,V); // write points before cells to fill the std::map V + write_c3t3_points(os,tr,V); // write points before cells to fill the std::map V write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag write_attributes(os,mids); } From ae108c5d96a00c33cb5778fb5bcd65278c4a1764 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 21 Jan 2019 17:14:14 +0100 Subject: [PATCH 133/186] Improve comments and fix indentation --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index c5d621462c4..ad14ca8b417 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -289,18 +289,18 @@ void output_to_vtu(std::ostream& os, std::size_t offset = 0; const bool binary = (mode == IO::BINARY); write_c3t3_points_tag(os,tr,V,binary,offset); - write_cells_tag(os,c3t3,V,binary,offset); + write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII std::vector mids; - os << " \n"; - write_attribute_tag(os,"MeshDomain",mids,binary,offset); - os << " \n"; + os << " \n"; + write_attribute_tag(os,"MeshDomain",mids,binary,offset); + os << " \n"; os << " \n" << " \n"; if (binary) { os << "\n_"; - write_c3t3_points(os,tr,V); // write points before cells to fill the std::map V - write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag + write_c3t3_points(os,tr,V); // fills V if the mode is BINARY + write_cells(os,c3t3,V, mids); write_attributes(os,mids); } os << "\n"; From 59453c8dc82f497c815f3567d7c02b00dcaf6d45 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 22 Jan 2019 09:05:49 +0100 Subject: [PATCH 134/186] replace remaining message_interface-> --- Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp index ecbffc3363c..bf3faa0f254 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp @@ -1248,7 +1248,7 @@ bool Io_image_plugin::loadDCM(QString dirname) } return result; #else - message_interface->warning("You need VTK to read a DCM file"); + CGAL::Three::Three::warning("You need VTK to read a DCM file"); CGAL_USE(dirname); return false; #endif @@ -1276,7 +1276,7 @@ Image* Io_image_plugin::createDCMImage(QString dirname) image = new Image; *image = CGAL::read_vtk_image_data(vtk_image); #else - message_interface->warning("You need VTK to read a DCM file"); + CGAL::Three::Three::warning("You need VTK to read a DCM file"); CGAL_USE(dirname); #endif return image; From 4d3df85cb3b02139b83ca27a4ee97f46f0d96b67 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 22 Jan 2019 10:38:48 +0100 Subject: [PATCH 135/186] Remove far points --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index ad14ca8b417..5eda1cab3d3 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -152,6 +152,7 @@ template void write_c3t3_points_tag(std::ostream& os, const Tr & tr, + std::size_t size_of_vertices, std::map & V, bool binary, std::size_t& offset) @@ -171,7 +172,7 @@ write_c3t3_points_tag(std::ostream& os, if (binary) { os << "\" offset=\"" << offset << "\"/>\n"; - offset += 3 * tr.number_of_vertices() * sizeof(FT) + sizeof(std::size_t); + offset += 3 * size_of_vertices * sizeof(FT) + sizeof(std::size_t); // dim coords per points + length of the encoded data (size_t) } else { @@ -180,14 +181,15 @@ write_c3t3_points_tag(std::ostream& os, vit != tr.finite_vertices_end(); ++vit) { + if(vit->in_dimension() <= -1) continue; V[vit] = inum++; - os << vit->point()[0] << " "; - os << vit->point()[1] << " "; - if(dim == 3) - os << vit->point()[2] << " "; - else - os << 0.0 << " "; - } + os << vit->point()[0] << " "; + os << vit->point()[1] << " "; + if(dim == 3) + os << vit->point()[2] << " "; + else + os << 0.0 << " "; + } os << " \n"; } os << " \n"; @@ -212,6 +214,7 @@ write_c3t3_points(std::ostream& os, vit != tr.finite_vertices_end(); ++vit) { + if(vit->in_dimension() <= -1) continue; V[vit] = inum++; // binary output => the map has not been filled yet coordinates.push_back(vit->point()[0]); coordinates.push_back(vit->point()[1]); @@ -283,12 +286,13 @@ void output_to_vtu(std::ostream& os, } os << ">\n" << " " << "\n"; - - os << " \n"; std::size_t offset = 0; const bool binary = (mode == IO::BINARY); - write_c3t3_points_tag(os,tr,V,binary,offset); + write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII std::vector mids; os << " Date: Tue, 22 Jan 2019 10:40:21 +0100 Subject: [PATCH 136/186] rename extensions of shaders --- .../{heat_intensity_shader.f => heat_intensity_shader.frag} | 0 .../{heat_intensity_shader.v => heat_intensity_shader.vert} | 0 .../compatibility_shaders/{shader_c3t3.f => shader_c3t3.frag} | 0 .../compatibility_shaders/{shader_c3t3.v => shader_c3t3.vert} | 0 .../{shader_c3t3_edges.f => shader_c3t3_edges.frag} | 0 .../{shader_c3t3_edges.v => shader_c3t3_edges.vert} | 0 .../{shader_c3t3_spheres.v => shader_c3t3_spheres.vert} | 0 .../{shader_instanced.v => shader_instanced.vert} | 0 ..._no_light_no_selection.f => shader_no_light_no_selection.frag} | 0 .../{shader_old_flat.f => shader_old_flat.frag} | 0 .../{shader_plane_two_faces.f => shader_plane_two_faces.frag} | 0 .../{shader_spheres.v => shader_spheres.vert} | 0 .../{shader_with_light.f => shader_with_light.frag} | 0 .../{shader_with_light.v => shader_with_light.vert} | 0 .../{shader_with_texture.f => shader_with_texture.frag} | 0 .../{shader_with_texture.v => shader_with_texture.vert} | 0 ...ader_with_textured_edges.f => shader_with_textured_edges.frag} | 0 ...ader_with_textured_edges.v => shader_with_textured_edges.vert} | 0 .../{shader_without_light.f => shader_without_light.frag} | 0 .../{shader_without_light.v => shader_without_light.vert} | 0 .../{heat_intensity_shader.f => heat_intensity_shader.frag} | 0 .../{heat_intensity_shader.v => heat_intensity_shader.vert} | 0 .../{no_interpolation_shader.f => no_interpolation_shader.frag} | 0 .../{no_interpolation_shader.g => no_interpolation_shader.geom} | 0 .../{no_interpolation_shader.v => no_interpolation_shader.vert} | 0 .../demo/Polyhedron/resources/{shader_c3t3.f => shader_c3t3.frag} | 0 .../demo/Polyhedron/resources/{shader_c3t3.v => shader_c3t3.vert} | 0 .../resources/{shader_c3t3_edges.f => shader_c3t3_edges.frag} | 0 .../resources/{shader_c3t3_edges.v => shader_c3t3_edges.vert} | 0 .../resources/{shader_c3t3_spheres.v => shader_c3t3_spheres.vert} | 0 .../demo/Polyhedron/resources/{shader_flat.f => shader_flat.frag} | 0 .../demo/Polyhedron/resources/{shader_flat.g => shader_flat.geom} | 0 .../demo/Polyhedron/resources/{shader_flat.v => shader_flat.vert} | 0 .../resources/{shader_instanced.v => shader_instanced.vert} | 0 ..._no_light_no_selection.f => shader_no_light_no_selection.frag} | 0 .../resources/{shader_old_flat.f => shader_old_flat.frag} | 0 .../{shader_plane_two_faces.f => shader_plane_two_faces.frag} | 0 .../resources/{shader_spheres.v => shader_spheres.vert} | 0 .../resources/{shader_with_light.f => shader_with_light.frag} | 0 .../resources/{shader_with_light.v => shader_with_light.vert} | 0 .../resources/{shader_with_texture.f => shader_with_texture.frag} | 0 .../resources/{shader_with_texture.v => shader_with_texture.vert} | 0 ...ader_with_textured_edges.f => shader_with_textured_edges.frag} | 0 ...ader_with_textured_edges.v => shader_with_textured_edges.vert} | 0 .../{shader_without_light.f => shader_without_light.frag} | 0 .../{shader_without_light.v => shader_without_light.vert} | 0 .../{solid_wireframe_shader.f => solid_wireframe_shader.frag} | 0 .../{solid_wireframe_shader.g => solid_wireframe_shader.geom} | 0 .../{solid_wireframe_shader.v => solid_wireframe_shader.vert} | 0 49 files changed, 0 insertions(+), 0 deletions(-) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{heat_intensity_shader.f => heat_intensity_shader.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{heat_intensity_shader.v => heat_intensity_shader.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_c3t3.f => shader_c3t3.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_c3t3.v => shader_c3t3.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_c3t3_edges.f => shader_c3t3_edges.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_c3t3_edges.v => shader_c3t3_edges.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_c3t3_spheres.v => shader_c3t3_spheres.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_instanced.v => shader_instanced.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_no_light_no_selection.f => shader_no_light_no_selection.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_old_flat.f => shader_old_flat.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_plane_two_faces.f => shader_plane_two_faces.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_spheres.v => shader_spheres.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_light.f => shader_with_light.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_light.v => shader_with_light.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_texture.f => shader_with_texture.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_texture.v => shader_with_texture.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_textured_edges.f => shader_with_textured_edges.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_with_textured_edges.v => shader_with_textured_edges.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_without_light.f => shader_without_light.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/compatibility_shaders/{shader_without_light.v => shader_without_light.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{heat_intensity_shader.f => heat_intensity_shader.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{heat_intensity_shader.v => heat_intensity_shader.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{no_interpolation_shader.f => no_interpolation_shader.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{no_interpolation_shader.g => no_interpolation_shader.geom} (100%) rename Polyhedron/demo/Polyhedron/resources/{no_interpolation_shader.v => no_interpolation_shader.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_c3t3.f => shader_c3t3.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_c3t3.v => shader_c3t3.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_c3t3_edges.f => shader_c3t3_edges.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_c3t3_edges.v => shader_c3t3_edges.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_c3t3_spheres.v => shader_c3t3_spheres.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_flat.f => shader_flat.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_flat.g => shader_flat.geom} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_flat.v => shader_flat.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_instanced.v => shader_instanced.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_no_light_no_selection.f => shader_no_light_no_selection.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_old_flat.f => shader_old_flat.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_plane_two_faces.f => shader_plane_two_faces.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_spheres.v => shader_spheres.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_light.f => shader_with_light.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_light.v => shader_with_light.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_texture.f => shader_with_texture.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_texture.v => shader_with_texture.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_textured_edges.f => shader_with_textured_edges.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_with_textured_edges.v => shader_with_textured_edges.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_without_light.f => shader_without_light.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{shader_without_light.v => shader_without_light.vert} (100%) rename Polyhedron/demo/Polyhedron/resources/{solid_wireframe_shader.f => solid_wireframe_shader.frag} (100%) rename Polyhedron/demo/Polyhedron/resources/{solid_wireframe_shader.g => solid_wireframe_shader.geom} (100%) rename Polyhedron/demo/Polyhedron/resources/{solid_wireframe_shader.v => solid_wireframe_shader.vert} (100%) diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/heat_intensity_shader.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_spheres.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_spheres.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_spheres.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_spheres.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_instanced.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_instanced.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_instanced.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_instanced.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_no_light_no_selection.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_no_light_no_selection.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_no_light_no_selection.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_no_light_no_selection.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_old_flat.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_old_flat.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_old_flat.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_old_flat.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_plane_two_faces.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_plane_two_faces.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_plane_two_faces.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_plane_two_faces.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_spheres.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_spheres.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_spheres.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_spheres.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_texture.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_textured_edges.vert diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.f b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.f rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.frag diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.v b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.v rename to Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_without_light.vert diff --git a/Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.f b/Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.f rename to Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.frag diff --git a/Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.v b/Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.v rename to Polyhedron/demo/Polyhedron/resources/heat_intensity_shader.vert diff --git a/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.f b/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.f rename to Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.frag diff --git a/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.g b/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.geom similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.g rename to Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.geom diff --git a/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.v b/Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.v rename to Polyhedron/demo/Polyhedron/resources/no_interpolation_shader.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_c3t3.f b/Polyhedron/demo/Polyhedron/resources/shader_c3t3.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_c3t3.f rename to Polyhedron/demo/Polyhedron/resources/shader_c3t3.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_c3t3.v b/Polyhedron/demo/Polyhedron/resources/shader_c3t3.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_c3t3.v rename to Polyhedron/demo/Polyhedron/resources/shader_c3t3.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.f b/Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.f rename to Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.v b/Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.v rename to Polyhedron/demo/Polyhedron/resources/shader_c3t3_edges.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_c3t3_spheres.v b/Polyhedron/demo/Polyhedron/resources/shader_c3t3_spheres.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_c3t3_spheres.v rename to Polyhedron/demo/Polyhedron/resources/shader_c3t3_spheres.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_flat.f b/Polyhedron/demo/Polyhedron/resources/shader_flat.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_flat.f rename to Polyhedron/demo/Polyhedron/resources/shader_flat.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_flat.g b/Polyhedron/demo/Polyhedron/resources/shader_flat.geom similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_flat.g rename to Polyhedron/demo/Polyhedron/resources/shader_flat.geom diff --git a/Polyhedron/demo/Polyhedron/resources/shader_flat.v b/Polyhedron/demo/Polyhedron/resources/shader_flat.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_flat.v rename to Polyhedron/demo/Polyhedron/resources/shader_flat.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_instanced.v b/Polyhedron/demo/Polyhedron/resources/shader_instanced.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_instanced.v rename to Polyhedron/demo/Polyhedron/resources/shader_instanced.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_no_light_no_selection.f b/Polyhedron/demo/Polyhedron/resources/shader_no_light_no_selection.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_no_light_no_selection.f rename to Polyhedron/demo/Polyhedron/resources/shader_no_light_no_selection.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_old_flat.f b/Polyhedron/demo/Polyhedron/resources/shader_old_flat.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_old_flat.f rename to Polyhedron/demo/Polyhedron/resources/shader_old_flat.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_plane_two_faces.f b/Polyhedron/demo/Polyhedron/resources/shader_plane_two_faces.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_plane_two_faces.f rename to Polyhedron/demo/Polyhedron/resources/shader_plane_two_faces.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_spheres.v b/Polyhedron/demo/Polyhedron/resources/shader_spheres.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_spheres.v rename to Polyhedron/demo/Polyhedron/resources/shader_spheres.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.f b/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_light.f rename to Polyhedron/demo/Polyhedron/resources/shader_with_light.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.v b/Polyhedron/demo/Polyhedron/resources/shader_with_light.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_light.v rename to Polyhedron/demo/Polyhedron/resources/shader_with_light.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_texture.f b/Polyhedron/demo/Polyhedron/resources/shader_with_texture.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_texture.f rename to Polyhedron/demo/Polyhedron/resources/shader_with_texture.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_texture.v b/Polyhedron/demo/Polyhedron/resources/shader_with_texture.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_texture.v rename to Polyhedron/demo/Polyhedron/resources/shader_with_texture.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.f b/Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.f rename to Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.v b/Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.v rename to Polyhedron/demo/Polyhedron/resources/shader_with_textured_edges.vert diff --git a/Polyhedron/demo/Polyhedron/resources/shader_without_light.f b/Polyhedron/demo/Polyhedron/resources/shader_without_light.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_without_light.f rename to Polyhedron/demo/Polyhedron/resources/shader_without_light.frag diff --git a/Polyhedron/demo/Polyhedron/resources/shader_without_light.v b/Polyhedron/demo/Polyhedron/resources/shader_without_light.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/shader_without_light.v rename to Polyhedron/demo/Polyhedron/resources/shader_without_light.vert diff --git a/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.f b/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.frag similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.f rename to Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.frag diff --git a/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.g b/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.geom similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.g rename to Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.geom diff --git a/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.v b/Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.vert similarity index 100% rename from Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.v rename to Polyhedron/demo/Polyhedron/resources/solid_wireframe_shader.vert From f528e8f532edbc18054898e588e283a060a4a7bd Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 22 Jan 2019 10:46:30 +0100 Subject: [PATCH 137/186] replace in calls too --- .../Plugins/PCA/Scene_edit_box_item.cpp | 8 +- .../Plugins/Point_set/Alpha_shape_plugin.cpp | 2 +- .../demo/Polyhedron/Scene_image_item.cpp | 6 +- Polyhedron/demo/Polyhedron/Viewer.cpp | 98 +++++++++---------- 4 files changed, 57 insertions(+), 57 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp index baffa4ebf55..4846d60a13d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp @@ -203,13 +203,13 @@ struct Scene_edit_box_item_priv{ if(QOpenGLContext::currentContext()->format().majorVersion() >= 3) { - pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/shader_spheres.v"); - pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/shader_without_light.f"); + pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/shader_spheres.vert"); + pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/shader_without_light.frag"); } else { - pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_spheres.v"); - pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.f"); + pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_spheres.vert"); + pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.frag"); } pick_sphere_program.bindAttributeLocation("colors", 1); pick_sphere_program.link(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp index 921ff997411..ad5493d3843 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp @@ -342,7 +342,7 @@ Scene_alpha_shape_item::Scene_alpha_shape_item(Scene_points_with_normal_item *po { facet_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_source_comp); } - facet_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_old_flat.f"); + facet_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_old_flat.frag"); facet_program.link(); invalidateOpenGLBuffers(); alpha_changed(alpha); diff --git a/Polyhedron/demo/Polyhedron/Scene_image_item.cpp b/Polyhedron/demo/Polyhedron/Scene_image_item.cpp index c61f608d2f5..8ff062cb5cb 100644 --- a/Polyhedron/demo/Polyhedron/Scene_image_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_image_item.cpp @@ -592,16 +592,16 @@ void Scene_image_item_priv::compile_shaders() } else { - if(!rendering_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/no_interpolation_shader.v")) + if(!rendering_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/no_interpolation_shader.vert")) { std::cerr<<"adding vertex shader FAILED"<addShaderFromSourceFile(QOpenGLShader::Geometry,":/cgal/Polyhedron_3/resources/shader_flat.g" )) + if(!program->addShaderFromSourceFile(QOpenGLShader::Geometry,":/cgal/Polyhedron_3/resources/shader_flat.geom" )) { std::cerr<<"adding geometry shader FAILED"<addShaderFromSourceFile(QOpenGLShader::Geometry,":/cgal/Polyhedron_3/resources/solid_wireframe_shader.g" )) + if(!program->addShaderFromSourceFile(QOpenGLShader::Geometry,":/cgal/Polyhedron_3/resources/solid_wireframe_shader.geom" )) { std::cerr<<"adding geometry shader FAILED"<setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasCutPlane", true); @@ -1058,18 +1058,18 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_C3T3_EDGES: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_c3t3_edges.v" , ":/cgal/Polyhedron_3/resources/shader_c3t3_edges.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_edges.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_edges.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_c3t3_edges.vert" , ":/cgal/Polyhedron_3/resources/shader_c3t3_edges.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_edges.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_edges.frag"); program->setProperty("hasCutPlane", true); return program; } case PROGRAM_WITH_LIGHT: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_light.v" , ":/cgal/Polyhedron_3/resources/shader_with_light.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_light.vert" , ":/cgal/Polyhedron_3/resources/shader_with_light.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasTransparency", true); @@ -1079,9 +1079,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_HEAT_INTENSITY: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/heat_intensity_shader.v" , ":/cgal/Polyhedron_3/resources/heat_intensity_shader.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/heat_intensity_shader.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/heat_intensity_shader.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/heat_intensity_shader.vert" , ":/cgal/Polyhedron_3/resources/heat_intensity_shader.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/heat_intensity_shader.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/heat_intensity_shader.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasTransparency", true); @@ -1091,27 +1091,27 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_WITHOUT_LIGHT: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.v" , ":/cgal/Polyhedron_3/resources/shader_without_light.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.vert" , ":/cgal/Polyhedron_3/resources/shader_without_light.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.frag"); program->setProperty("hasFMatrix", true); return program; } case PROGRAM_NO_SELECTION: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.v" , ":/cgal/Polyhedron_3/resources/shader_no_light_no_selection.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_no_light_no_selection.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.vert" , ":/cgal/Polyhedron_3/resources/shader_no_light_no_selection.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_no_light_no_selection.frag"); program->setProperty("hasFMatrix", true); return program; } case PROGRAM_WITH_TEXTURE: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_texture.v" , ":/cgal/Polyhedron_3/resources/shader_with_texture.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_texture.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_texture.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_texture.vert" , ":/cgal/Polyhedron_3/resources/shader_with_texture.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_texture.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_texture.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasFMatrix", true); @@ -1121,9 +1121,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_PLANE_TWO_FACES: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ?declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.v" , ":/cgal/Polyhedron_3/resources/shader_plane_two_faces.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_plane_two_faces.f"); + ?declare_program(name, ":/cgal/Polyhedron_3/resources/shader_without_light.vert" , ":/cgal/Polyhedron_3/resources/shader_plane_two_faces.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_plane_two_faces.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); return program; @@ -1131,9 +1131,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_WITH_TEXTURED_EDGES: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_textured_edges.v" , ":/cgal/Polyhedron_3/resources/shader_with_textured_edges.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_textured_edges.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_textured_edges.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_textured_edges.vert" , ":/cgal/Polyhedron_3/resources/shader_with_textured_edges.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_textured_edges.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_textured_edges.frag"); program->setProperty("hasFMatrix", true); program->setProperty("hasTexture", true); return program; @@ -1141,9 +1141,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_INSTANCED: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_instanced.v" , ":/cgal/Polyhedron_3/resources/shader_with_light.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_instanced.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_instanced.vert" , ":/cgal/Polyhedron_3/resources/shader_with_light.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_instanced.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); @@ -1153,9 +1153,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_INSTANCED_WIRE: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_instanced.v" , ":/cgal/Polyhedron_3/resources/shader_without_light.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_instanced.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_instanced.vert" , ":/cgal/Polyhedron_3/resources/shader_without_light.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_instanced.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasBarycenter", true); @@ -1165,9 +1165,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_CUTPLANE_SPHERES: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_c3t3_spheres.v" , ":/cgal/Polyhedron_3/resources/shader_c3t3.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_spheres.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3.f"); + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_c3t3_spheres.vert" , ":/cgal/Polyhedron_3/resources/shader_c3t3.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3_spheres.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_c3t3.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasBarycenter", true); @@ -1178,9 +1178,9 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_SPHERES: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ?declare_program(name, ":/cgal/Polyhedron_3/resources/shader_spheres.v" , ":/cgal/Polyhedron_3/resources/shader_with_light.f") - : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_spheres.v" , - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.f"); + ?declare_program(name, ":/cgal/Polyhedron_3/resources/shader_spheres.vert" , ":/cgal/Polyhedron_3/resources/shader_with_light.frag") + : declare_program(name, ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_spheres.vert" , + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); program->setProperty("hasBarycenter", true); @@ -1196,7 +1196,7 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const std::cerr<<"An OpenGL context of version 4.3 is required for the program ("<setProperty("hasLight", true); program->setProperty("hasNormals", true); return program; @@ -1204,10 +1204,10 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const case PROGRAM_OLD_FLAT: { QOpenGLShaderProgram* program = isOpenGL_4_3() - ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_light.v", ":/cgal/Polyhedron_3/resources/shader_old_flat.f") + ? declare_program(name, ":/cgal/Polyhedron_3/resources/shader_with_light.vert", ":/cgal/Polyhedron_3/resources/shader_old_flat.frag") : declare_program(name, - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.v", - ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_old_flat.f"); + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_with_light.vert", + ":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_old_flat.frag"); program->setProperty("hasLight", true); program->setProperty("hasNormals", true); return program; @@ -1219,8 +1219,8 @@ QOpenGLShaderProgram* Viewer::getShaderProgram(int name) const return 0; } return declare_program(name, - ":/cgal/Polyhedron_3/resources/solid_wireframe_shader.v", - ":/cgal/Polyhedron_3/resources/solid_wireframe_shader.f"); + ":/cgal/Polyhedron_3/resources/solid_wireframe_shader.vert", + ":/cgal/Polyhedron_3/resources/solid_wireframe_shader.frag"); break; default: std::cerr<<"ERROR : Program not found."< Date: Tue, 22 Jan 2019 10:54:16 +0100 Subject: [PATCH 138/186] ...and in the qrc --- Polyhedron/demo/Polyhedron/Polyhedron_3.qrc | 98 ++++++++++----------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc index ddfef37241e..bca90692a1f 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc +++ b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc @@ -34,23 +34,23 @@ resources/about.html - resources/shader_with_light.v - resources/shader_with_light.f - resources/shader_without_light.f - resources/shader_without_light.v - resources/shader_with_texture.f - resources/shader_with_textured_edges.f - resources/shader_with_textured_edges.v - resources/shader_with_texture.v - resources/shader_instanced.v - resources/shader_no_light_no_selection.f - resources/shader_c3t3_spheres.v - resources/shader_c3t3_edges.v - resources/shader_c3t3_edges.f - resources/shader_c3t3.v - resources/shader_c3t3.f - resources/shader_plane_two_faces.f - resources/shader_spheres.v + resources/shader_with_light.vert + resources/shader_with_light.frag + resources/shader_without_light.frag + resources/shader_without_light.vert + resources/shader_with_texture.frag + resources/shader_with_textured_edges.frag + resources/shader_with_textured_edges.vert + resources/shader_with_texture.vert + resources/shader_instanced.vert + resources/shader_no_light_no_selection.frag + resources/shader_c3t3_spheres.vert + resources/shader_c3t3_edges.vert + resources/shader_c3t3_edges.frag + resources/shader_c3t3.vert + resources/shader_c3t3.frag + resources/shader_plane_two_faces.frag + resources/shader_spheres.vert resources/general_collapse.png resources/add_facet1.png resources/add_facet2.png @@ -58,7 +58,7 @@ resources/euler_facet.png resources/euler_vertex.png javascript/lib.js - resources/shader_flat.f + resources/shader_flat.frag resources/hexahedron.png resources/icosphere.png resources/tetrahedron.png @@ -67,37 +67,37 @@ resources/prism-open.png resources/pyramid.png resources/pyramid-open.png - resources/no_interpolation_shader.f - resources/no_interpolation_shader.g - resources/no_interpolation_shader.v - resources/shader_flat.g - resources/shader_flat.v - resources/shader_old_flat.f - resources/solid_wireframe_shader.v - resources/solid_wireframe_shader.f - resources/solid_wireframe_shader.g - resources/compatibility_shaders/shader_c3t3_edges.f - resources/compatibility_shaders/shader_c3t3_edges.v - resources/compatibility_shaders/shader_c3t3_spheres.v - resources/compatibility_shaders/shader_c3t3.f - resources/compatibility_shaders/shader_c3t3.v - resources/compatibility_shaders/shader_instanced.v - resources/compatibility_shaders/shader_no_light_no_selection.f - resources/compatibility_shaders/shader_old_flat.f - resources/compatibility_shaders/shader_plane_two_faces.f - resources/compatibility_shaders/shader_spheres.v - resources/compatibility_shaders/shader_with_light.f - resources/compatibility_shaders/shader_with_light.v - resources/compatibility_shaders/shader_with_texture.f - resources/compatibility_shaders/shader_with_texture.v - resources/compatibility_shaders/shader_with_textured_edges.f - resources/compatibility_shaders/shader_with_textured_edges.v - resources/compatibility_shaders/shader_without_light.f - resources/compatibility_shaders/shader_without_light.v - resources/heat_intensity_shader.f - resources/heat_intensity_shader.v - resources/compatibility_shaders/heat_intensity_shader.f - resources/compatibility_shaders/heat_intensity_shader.v + resources/no_interpolation_shader.frag + resources/no_interpolation_shader.geom + resources/no_interpolation_shader.vert + resources/shader_flat.geom + resources/shader_flat.vert + resources/shader_old_flat.frag + resources/solid_wireframe_shader.vert + resources/solid_wireframe_shader.frag + resources/solid_wireframe_shader.geom + resources/compatibility_shaders/shader_c3t3_edges.frag + resources/compatibility_shaders/shader_c3t3_edges.vert + resources/compatibility_shaders/shader_c3t3_spheres.vert + resources/compatibility_shaders/shader_c3t3.frag + resources/compatibility_shaders/shader_c3t3.vert + resources/compatibility_shaders/shader_instanced.vert + resources/compatibility_shaders/shader_no_light_no_selection.frag + resources/compatibility_shaders/shader_old_flat.frag + resources/compatibility_shaders/shader_plane_two_faces.frag + resources/compatibility_shaders/shader_spheres.vert + resources/compatibility_shaders/shader_with_light.frag + resources/compatibility_shaders/shader_with_light.vert + resources/compatibility_shaders/shader_with_texture.frag + resources/compatibility_shaders/shader_with_texture.vert + resources/compatibility_shaders/shader_with_textured_edges.frag + resources/compatibility_shaders/shader_with_textured_edges.vert + resources/compatibility_shaders/shader_without_light.frag + resources/compatibility_shaders/shader_without_light.vert + resources/heat_intensity_shader.frag + resources/heat_intensity_shader.vert + resources/compatibility_shaders/heat_intensity_shader.frag + resources/compatibility_shaders/heat_intensity_shader.vert resources/rotate_around_cursor.png From b74753680bf26253c2f9beaaaedd613b0e81c273 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 22 Jan 2019 12:03:05 +0100 Subject: [PATCH 139/186] Fix "\n"; write_attribute_tag(os,"MeshDomain",mids,binary,offset); os << " \n"; From a57db0bac4cfffb97f421025de17996f2cc74d29 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 22 Jan 2019 12:20:53 +0100 Subject: [PATCH 140/186] Fix the filling of 'mids' --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 1b4b8ba9e15..020faeb33b7 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -124,8 +124,7 @@ template void write_cells(std::ostream& os, const C3T3 & c3t3, - std::map & V, - std::vector& mids) + std::map & V) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::vector connectivity_table; @@ -140,7 +139,6 @@ write_cells(std::ostream& os, offsets.push_back(off); for (int i=0; i<4; i++) connectivity_table.push_back(V[cit->vertex(i)]); - mids.push_back(cit->subdomain_index()); } write_vector(os,connectivity_table); write_vector(os,offsets); @@ -294,7 +292,15 @@ void output_to_vtu(std::ostream& os, const bool binary = (mode == IO::BINARY); write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII - std::vector mids; + + std::vector mids; + mids.reserve(c3t3.number_of_cells_in_complex()); + for( typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) { + mids.push_back(cit->subdomain_index()); + } + os << " \n"; write_attribute_tag(os,"MeshDomain",mids,binary,offset); @@ -304,7 +310,7 @@ void output_to_vtu(std::ostream& os, if (binary) { os << "\n_"; write_c3t3_points(os,tr,V); // fills V if the mode is BINARY - write_cells(os,c3t3,V, mids); + write_cells(os,c3t3,V); write_attributes(os,mids); } os << "\n"; From a5d89b1f33639f61fe6140bc3c9799745ef40ec4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 14:20:43 +0100 Subject: [PATCH 141/186] Specialize conversion of mpq_rational to interval copy-paste of the code for Gmpq/mpq_class --- Number_types/include/CGAL/boost_mp.h | 110 +++++++++++++++++---------- 1 file changed, 69 insertions(+), 41 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index cae81077612..38ff8b20ddb 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -57,6 +57,9 @@ # include #endif +#ifdef CGAL_USE_MPFR +# include +#endif // TODO: work on the coercions (end of the file) @@ -136,6 +139,13 @@ struct AST_boost_mp +struct Algebraic_structure_traits > +: AST_boost_mp > {}; +template +struct Algebraic_structure_traits > +: Algebraic_structure_traits::result_type > {}; + // Real_embeddable_traits template @@ -211,26 +221,58 @@ struct RET_boost_mp struct RET_boost_mp > - : RET_boost_mp_base { -#if BOOST_VERSION < 105700 - typedef NT Type; + : RET_boost_mp_base {}; + +#ifdef CGAL_USE_MPFR +// Because of this full specialization, things get instantiated more eagerly. Make it artificially partial if necessary. +template <> +struct RET_boost_mp > + : RET_boost_mp_base { + typedef boost::multiprecision::mpq_rational Type; struct To_interval : public CGAL::cpp98::unary_function< Type, std::pair< double, double > > { std::pair operator()(const Type& x) const { - std::pair p_num = CGAL::to_interval (numerator (x)); - std::pair p_den = CGAL::to_interval (denominator (x)); - typedef Interval_nt IA; - IA::Protector P; - // assume the conversion is within 1 ulp for integers, but the conversion from rational may be unsafe, see boost trac #10085 - IA i_num (p_num.first, p_num.second); - IA i_den (p_den.first, p_den.second); - IA i = i_num / i_den; - return std::pair(i.inf(), i.sup()); +# if MPFR_VERSION_MAJOR >= 3 + mpfr_exp_t emin = mpfr_get_emin(); + mpfr_set_emin(-1073); + MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ + int r = mpfr_set_q (y, x.backend().data(), MPFR_RNDA); + r = mpfr_subnormalize (y, r, MPFR_RNDA); /* Round subnormals */ + double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ + mpfr_set_emin(emin); /* Restore old value, users may care */ + // With mpfr_set_emax(1024) we could drop the is_finite test + if (r == 0 && is_finite (i)) + return std::pair(i, i); + else + { + double s = nextafter (i, 0); + if (i < 0) + return std::pair(i, s); + else + return std::pair(s, i); + } +# else + mpfr_t y; + mpfr_init2 (y, 53); /* Assume IEEE-754 */ + mpfr_set_q (y, x.backend().data(), GMP_RNDD); + double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ + mpfr_set_q (y, x.backend().data(), GMP_RNDU); + double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ + mpfr_clear (y); + return std::pair(i, s); +# endif } }; -#endif }; +#endif + +template +struct Real_embeddable_traits > +: RET_boost_mp > {}; +template +struct Real_embeddable_traits > +: Real_embeddable_traits::result_type > {}; // Modular_traits @@ -262,6 +304,13 @@ struct MT_boost_mp +struct Modular_traits > +: MT_boost_mp > {}; +template +struct Modular_traits > +: Modular_traits::result_type > {}; + // Split_double template ::value> > @@ -284,6 +333,13 @@ struct SD_boost_mp +struct Split_double > +: SD_boost_mp > {}; +template +struct Split_double > +: Split_double::result_type > {}; + // Fraction_traits @@ -335,27 +391,6 @@ struct FT_boost_mp -struct Algebraic_structure_traits > -: AST_boost_mp > {}; -template -struct Algebraic_structure_traits > -: Algebraic_structure_traits::result_type > {}; - -template -struct Real_embeddable_traits > -: RET_boost_mp > {}; -template -struct Real_embeddable_traits > -: Real_embeddable_traits::result_type > {}; - -template -struct Modular_traits > -: MT_boost_mp > {}; -template -struct Modular_traits > -: Modular_traits::result_type > {}; - template struct Fraction_traits > : FT_boost_mp > {}; @@ -363,13 +398,6 @@ template struct Fraction_traits > : Fraction_traits::result_type > {}; -template -struct Split_double > -: SD_boost_mp > {}; -template -struct Split_double > -: Split_double::result_type > {}; - // Coercions From 92f55fb8ca4f080fcae4ad28653d3b7e9dad8a2d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 14:32:08 +0100 Subject: [PATCH 142/186] Specialize conversion of mpz_int to interval copy-paste of the code for Gmpz/mpz_class --- Number_types/include/CGAL/boost_mp.h | 39 ++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index 38ff8b20ddb..4c598778222 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -224,9 +224,44 @@ struct RET_boost_mp {}; #ifdef CGAL_USE_MPFR -// Because of this full specialization, things get instantiated more eagerly. Make it artificially partial if necessary. +// Because of these full specializations, things get instantiated more eagerly. Make them artificially partial if necessary. template <> -struct RET_boost_mp > +struct RET_boost_mp + : RET_boost_mp_base { + typedef boost::multiprecision::mpz_int Type; + struct To_interval + : public CGAL::cpp98::unary_function< Type, std::pair< double, double > > { + std::pair + operator()(const Type& x) const { +#if MPFR_VERSION_MAJOR >= 3 + MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ + int r = mpfr_set_z (y, x.backend().data(), MPFR_RNDA); + double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ + if (r == 0 && is_finite (i)) + return std::pair(i, i); + else + { + double s = nextafter (i, 0); + if (i < 0) + return std::pair(i, s); + else + return std::pair(s, i); + } +#else + mpfr_t y; + mpfr_init2 (y, 53); /* Assume IEEE-754 */ + mpfr_set_z (y, x.backend().data(), GMP_RNDD); + double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ + mpfr_set_z (y, x.backend().data(), GMP_RNDU); + double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ + mpfr_clear (y); + return std::pair(i, s); +#endif + } + }; +}; +template <> +struct RET_boost_mp : RET_boost_mp_base { typedef boost::multiprecision::mpq_rational Type; struct To_interval From 201b96db557822c26a1ef1388c5a2e56ae3c2c1c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 15:34:14 +0100 Subject: [PATCH 143/186] Coercion traits between builtins and expressions --- Number_types/include/CGAL/boost_mp.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index 4c598778222..2c69a5f23df 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -503,7 +503,7 @@ typename boost::multiprecision::detail::expression::result_type, boost::multiprecision::number > { }; -// TODO: coercion with expressions, fix existing coercions +// TODO: fix existing coercions // (double -> rational is implicit only for 1.56+, see ticket #10082) // The real solution would be to avoid specializing Coercion_traits for all pairs of number types and let it auto-detect what works, so only broken types need an explicit specialization. @@ -521,7 +521,13 @@ struct Coercion_traits, int> { \ }; \ template \ struct Coercion_traits > \ -: Coercion_traits, int> {} +: Coercion_traits, int> {}; \ +template \ +struct Coercion_traits, int> \ +: Coercion_traits::result_type, int>{}; \ +template \ +struct Coercion_traits > \ +: Coercion_traits::result_type, int>{} CGAL_COERCE_INT(short); CGAL_COERCE_INT(int); @@ -542,7 +548,13 @@ struct Coercion_traits, float> { \ }; \ template \ struct Coercion_traits > \ -: Coercion_traits, float> {} +: Coercion_traits, float> {}; \ +template \ +struct Coercion_traits, float> \ +: Coercion_traits::result_type, float>{}; \ +template \ +struct Coercion_traits > \ +: Coercion_traits::result_type, float>{} CGAL_COERCE_FLOAT(float); CGAL_COERCE_FLOAT(double); From 34fdb829800a9e7fdc5ba5e5b1fcc84d1d866ad0 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 15:34:36 +0100 Subject: [PATCH 144/186] add boost types to tests --- Number_types/test/Number_types/utilities.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Number_types/test/Number_types/utilities.cpp b/Number_types/test/Number_types/utilities.cpp index b29517bfd82..53a132e5b16 100644 --- a/Number_types/test/Number_types/utilities.cpp +++ b/Number_types/test/Number_types/utilities.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CGAL_USE_GMP #include @@ -82,6 +83,12 @@ int main() TESTIT(CGAL::Lazy_exact_nt, "Lazy_exact_nt >") TESTIT(CGAL::Interval_nt<>, "Interval_nt<>") + // Boost.Multiprecision +#ifdef CGAL_USE_BOOST_MP + TESTIT(boost::multiprecision::cpp_int, "cpp_int") + TESTIT(boost::multiprecision::cpp_rational, "cpp_rational") +#endif + // GMP based NTs #ifdef CGAL_USE_GMP TESTIT(CGAL::Gmpz, "Gmpz") @@ -90,6 +97,10 @@ int main() TESTIT(CGAL::Mpzf, "Mpzf") # endif TESTIT(CGAL::Gmpq, "Gmpq") +# ifdef CGAL_USE_BOOST_MP + TESTIT(boost::multiprecision::mpz_int, "mpz_int") + TESTIT(boost::multiprecision::mpq_rational, "mpq_rational") +# endif #endif // CGAL_USE_GMP #ifdef CGAL_USE_GMPXX TESTIT(mpz_class, "mpz_class") From 624cf0793fdc2d62247f3f501173f973cf401824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 22 Jan 2019 16:03:52 +0100 Subject: [PATCH 145/186] remove applications directory --- Scripts/developer_scripts/cgal_create_release_with_cmake.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake b/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake index db6119a6bf5..4b2cef873a6 100644 --- a/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake +++ b/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake @@ -198,6 +198,7 @@ if (TESTSUITE) endif() # removal of extra directories and files +file(REMOVE_RECURSE ${release_dir}/applications) file(REMOVE_RECURSE ${release_dir}/benchmark) file(REMOVE_RECURSE ${release_dir}/archive) file(REMOVE ${release_dir}/include/CGAL/license/generate_files.cmake) From 9f42c9380dee2ad6001c68ca97f3823dbaa17306 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 18:19:12 +0100 Subject: [PATCH 146/186] Tighter conversion of boost multiprecision types to intervals. --- Number_types/include/CGAL/boost_mp.h | 105 ++++++++++++++------------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index 2c69a5f23df..bd943c802b6 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -203,11 +203,18 @@ struct RET_boost_mp_base : public CGAL::cpp98::unary_function< Type, std::pair< double, double > > { std::pair operator()(const Type& x) const { + // See if https://github.com/boostorg/multiprecision/issues/108 suggests anything better // assume the conversion is within 1 ulp // adding IA::smallest() doesn't work because inf-e=inf, even rounded down. - double d = x.template convert_to(); + double i = x.template convert_to(); + double s = i; double inf = std::numeric_limits::infinity(); - return std::pair (nextafter (d, -inf), nextafter (d, inf)); + int cmp = x.compare(i); + if (cmp > 0) + s = nextafter(s, +inf); + else if (cmp < 0) + i = nextafter(i, -inf); + return std::pair (i, s); } }; }; @@ -234,28 +241,28 @@ struct RET_boost_mp std::pair operator()(const Type& x) const { #if MPFR_VERSION_MAJOR >= 3 - MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ - int r = mpfr_set_z (y, x.backend().data(), MPFR_RNDA); - double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ - if (r == 0 && is_finite (i)) - return std::pair(i, i); - else - { - double s = nextafter (i, 0); - if (i < 0) - return std::pair(i, s); - else - return std::pair(s, i); - } + MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ + int r = mpfr_set_z (y, x.backend().data(), MPFR_RNDA); + double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ + if (r == 0 && is_finite (i)) + return std::pair(i, i); + else + { + double s = nextafter (i, 0); + if (i < 0) + return std::pair(i, s); + else + return std::pair(s, i); + } #else - mpfr_t y; - mpfr_init2 (y, 53); /* Assume IEEE-754 */ - mpfr_set_z (y, x.backend().data(), GMP_RNDD); - double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ - mpfr_set_z (y, x.backend().data(), GMP_RNDU); - double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ - mpfr_clear (y); - return std::pair(i, s); + mpfr_t y; + mpfr_init2 (y, 53); /* Assume IEEE-754 */ + mpfr_set_z (y, x.backend().data(), GMP_RNDD); + double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ + mpfr_set_z (y, x.backend().data(), GMP_RNDU); + double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ + mpfr_clear (y); + return std::pair(i, s); #endif } }; @@ -269,33 +276,33 @@ struct RET_boost_mp std::pair operator()(const Type& x) const { # if MPFR_VERSION_MAJOR >= 3 - mpfr_exp_t emin = mpfr_get_emin(); - mpfr_set_emin(-1073); - MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ - int r = mpfr_set_q (y, x.backend().data(), MPFR_RNDA); - r = mpfr_subnormalize (y, r, MPFR_RNDA); /* Round subnormals */ - double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ - mpfr_set_emin(emin); /* Restore old value, users may care */ - // With mpfr_set_emax(1024) we could drop the is_finite test - if (r == 0 && is_finite (i)) - return std::pair(i, i); - else - { - double s = nextafter (i, 0); - if (i < 0) - return std::pair(i, s); - else - return std::pair(s, i); - } + mpfr_exp_t emin = mpfr_get_emin(); + mpfr_set_emin(-1073); + MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ + int r = mpfr_set_q (y, x.backend().data(), MPFR_RNDA); + r = mpfr_subnormalize (y, r, MPFR_RNDA); /* Round subnormals */ + double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ + mpfr_set_emin(emin); /* Restore old value, users may care */ + // With mpfr_set_emax(1024) we could drop the is_finite test + if (r == 0 && is_finite (i)) + return std::pair(i, i); + else + { + double s = nextafter (i, 0); + if (i < 0) + return std::pair(i, s); + else + return std::pair(s, i); + } # else - mpfr_t y; - mpfr_init2 (y, 53); /* Assume IEEE-754 */ - mpfr_set_q (y, x.backend().data(), GMP_RNDD); - double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ - mpfr_set_q (y, x.backend().data(), GMP_RNDU); - double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ - mpfr_clear (y); - return std::pair(i, s); + mpfr_t y; + mpfr_init2 (y, 53); /* Assume IEEE-754 */ + mpfr_set_q (y, x.backend().data(), GMP_RNDD); + double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ + mpfr_set_q (y, x.backend().data(), GMP_RNDU); + double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ + mpfr_clear (y); + return std::pair(i, s); # endif } }; From 811ab8ac43d57c0ee69ca59e439b36e69a2fbc14 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 18:27:36 +0100 Subject: [PATCH 147/186] Add checks in the conversion to interval. I am more or less asserting that x belongs to to_interval(x). --- Number_types/include/CGAL/boost_mp.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index bd943c802b6..edaa005a8e7 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -210,10 +210,14 @@ struct RET_boost_mp_base double s = i; double inf = std::numeric_limits::infinity(); int cmp = x.compare(i); - if (cmp > 0) + if (cmp > 0) { s = nextafter(s, +inf); - else if (cmp < 0) + CGAL_assertion(x.compare(s) < 0); + } + else if (cmp < 0) { i = nextafter(i, -inf); + CGAL_assertion(x.compare(i) > 0); + } return std::pair (i, s); } }; From e34ddaef38fd61204bd48cad4dc061eeca53085f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 22 Jan 2019 19:04:41 +0100 Subject: [PATCH 148/186] reset the halfedge pointer of the faces before setting them that way in the bounded case, the infinite face has no halfedge associated, only holes. Before the patch it could be that an erased one was associated --- Nef_2/include/CGAL/Nef_2/HDS_items.h | 4 +++- Nef_2/include/CGAL/Nef_2/PM_const_decorator.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Nef_2/include/CGAL/Nef_2/HDS_items.h b/Nef_2/include/CGAL/Nef_2/HDS_items.h index 1265cb2eb87..25b7da232d1 100644 --- a/Nef_2/include/CGAL/Nef_2/HDS_items.h +++ b/Nef_2/include/CGAL/Nef_2/HDS_items.h @@ -389,7 +389,9 @@ public: hit->reset_fcit(); for (Isolated_vertex_iterator vit = iv_begin(); vit!=iv_end(); ++vit) vit->reset_ivit(); - FC.clear(); IV.clear(); } + FC.clear(); IV.clear(); + _e=Halfedge_handle(); + } /*{\Mtext There are the same iterator ranges defined for the const iterators |Hole_const_iterator|, |Isolated_vertex_const_iterator|. diff --git a/Nef_2/include/CGAL/Nef_2/PM_const_decorator.h b/Nef_2/include/CGAL/Nef_2/PM_const_decorator.h index 2e0f62cb940..5f4b92ef5d2 100644 --- a/Nef_2/include/CGAL/Nef_2/PM_const_decorator.h +++ b/Nef_2/include/CGAL/Nef_2/PM_const_decorator.h @@ -473,7 +473,7 @@ check_integrity_and_topological_planarity(bool faces) const int fc_num(0),iv_num(0); Face_const_iterator fit; for (fit = faces_begin(); fit != faces_end(); ++fit) { - if (!first) { + if (!first && halfedge(fit)!=Halfedge_const_handle()) { CGAL_assertion( face(halfedge(fit))==fit ); ++fc_num; } Hole_const_iterator fcit; From b8933836fa7ffbd74f1236853b5a10902facbc5d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 23 Jan 2019 09:31:35 +0100 Subject: [PATCH 149/186] Fix normal estimation parameter --- .../Plugins/Point_set/Point_set_normal_estimation_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ab53c6c887b..784e49120e8 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 @@ -235,7 +235,7 @@ void Polyhedron_demo_point_set_normal_estimation_plugin::on_actionNormalEstimati std::cerr << "Estimates normal direction by Jet Fitting (k=" << dialog.jet_neighbors() <<")...\n"; // Estimates normals direction. - Jet_estimate_normals_functor functor (points, dialog.pca_neighbors()); + Jet_estimate_normals_functor functor (points, dialog.jet_neighbors()); run_with_qprogressdialog (functor, "Estimating normals by jet fitting...", mw); std::size_t memory = CGAL::Memory_sizer().virtual_size(); From e610f8a8ff2131739b179370e780707e13c6fef6 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 23 Jan 2019 10:59:09 +0100 Subject: [PATCH 150/186] Adapt the vsa plugin --- .../Surface_mesh_approximation_plugin.cpp | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp index b83bf4c9758..f8f8b13e033 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -281,7 +282,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(sm_id)); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } @@ -357,7 +358,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked update_seeds_item(approx, pmesh); - mi->information(QString("Done, #proxies = %1. (%2 ms)").arg( + CGAL::Three::Three::information(QString("Done, #proxies = %1. (%2 ms)").arg( approx.number_of_proxies()).arg(time.elapsed())); sm_item->color_vector() = approx.proxy_colors(); sm_item->setItemIsMulticolor(true); @@ -384,12 +385,12 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonFit_clicked() { Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); if (search == m_sm_wrapper_map.end() || !search->second->initialized()) { - mi->information(QString("Please initialize seeds first.")); + CGAL::Three::Three::information(QString("Please initialize seeds first.")); return; } SMesh *pmesh = search->first->face_graph(); @@ -402,7 +403,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonFit_clicked() { approx.output(CGAL::parameters::face_proxy_map(pidmap)); update_seeds_item(approx, pmesh); - mi->information(QString("Fit one iteration, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("Fit one iteration, #proxies = %1.").arg(approx.number_of_proxies())); sm_item->color_vector() = approx.proxy_colors(); @@ -432,12 +433,12 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonAdd_clicked() { Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); if (search == m_sm_wrapper_map.end() || !search->second->initialized()) { - mi->information(QString("Please initialize seeds first.")); + CGAL::Three::Three::information(QString("Please initialize seeds first.")); return; } SMesh *pmesh = search->first->face_graph(); @@ -446,11 +447,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonAdd_clicked() { QApplication::setOverrideCursor(Qt::WaitCursor); if (approx.add_one_proxy() == 0) { - mi->information(QString("No proxy added, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("No proxy added, #proxies = %1.").arg(approx.number_of_proxies())); QApplication::restoreOverrideCursor(); return; } - mi->information(QString("One proxy added, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("One proxy added, #proxies = %1.").arg(approx.number_of_proxies())); Patch_id_pmap pidmap(get(CGAL::face_patch_id_t(), *pmesh)); approx.output(CGAL::parameters::face_proxy_map(pidmap)); @@ -484,12 +485,12 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); if (search == m_sm_wrapper_map.end() || !search->second->initialized()) { - mi->information(QString("Please initialize seeds first.")); + CGAL::Three::Three::information(QString("Please initialize seeds first.")); return; } SMesh *pmesh = search->first->face_graph(); @@ -498,7 +499,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke QApplication::setOverrideCursor(Qt::WaitCursor); if (approx.teleport_one_proxy() == 0) { - mi->information(QString("No proxy teleported, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("No proxy teleported, #proxies = %1.").arg(approx.number_of_proxies())); QApplication::restoreOverrideCursor(); return; } @@ -506,7 +507,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke approx.output(CGAL::parameters::face_proxy_map(pidmap)); update_seeds_item(approx, pmesh); - mi->information(QString("One proxy teleported, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("One proxy teleported, #proxies = %1.").arg(approx.number_of_proxies())); sm_item->color_vector() = approx.proxy_colors(); @@ -536,12 +537,12 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSplit_clicked() Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); if (search == m_sm_wrapper_map.end() || !search->second->initialized()) { - mi->information(QString("Please initialize seeds first.")); + CGAL::Three::Three::information(QString("Please initialize seeds first.")); return; } SMesh *pmesh = search->first->face_graph(); @@ -552,11 +553,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSplit_clicked() if (!approx.split(ui_widget.split_proxy_idx->value(), ui_widget.split_nb_sections->value(), ui_widget.split_nb_relaxations->value())) { - mi->information(QString("No proxy splitted, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("No proxy splitted, #proxies = %1.").arg(approx.number_of_proxies())); QApplication::restoreOverrideCursor(); return; } - mi->information(QString("One proxy splitted, #proxies = %1.").arg(approx.number_of_proxies())); + CGAL::Three::Three::information(QString("One proxy splitted, #proxies = %1.").arg(approx.number_of_proxies())); Patch_id_pmap pidmap(get(CGAL::face_patch_id_t(), *pmesh)); approx.output(CGAL::parameters::face_proxy_map(pidmap)); @@ -590,12 +591,12 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonMeshing_clicked Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); if (search == m_sm_wrapper_map.end() || !search->second->initialized()) { - mi->information(QString("Please initialize seeds first.")); + CGAL::Three::Three::information(QString("Please initialize seeds first.")); return; } SMesh *pmesh = search->first->face_graph(); @@ -612,7 +613,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonMeshing_clicked sm_item->setVisible(false); - mi->information(QString("Meshing done.")); + CGAL::Three::Three::information(QString("Meshing done.")); QApplication::restoreOverrideCursor(); } @@ -621,7 +622,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_comboMetric_currentIn Scene_surface_mesh_item *sm_item = qobject_cast( scene->item(scene->mainSelectionIndex())); if (!sm_item) { - mi->information(QString("No surface mesh item selected.")); + CGAL::Three::Three::information(QString("No surface mesh item selected.")); return; } SM_wrapper_map::iterator search = m_sm_wrapper_map.find(sm_item); From d3956b463df4ebe700c61d8ab42e033a86292578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 24 Jan 2019 14:47:16 +0100 Subject: [PATCH 151/186] Fixed not using periodic vertex classes in P2T2 examples --- .../p2t2_info_insert_with_pair_iterator_2.cpp | 17 ++++++++++------- ...t2_info_insert_with_transform_iterator_2.cpp | 17 ++++++++++------- .../p2t2_info_insert_with_zip_iterator_2.cpp | 17 ++++++++++------- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_pair_iterator_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_pair_iterator_2.cpp index 3788ffaa3d6..921afdc0bd1 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_pair_iterator_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_pair_iterator_2.cpp @@ -2,18 +2,21 @@ #include #include +#include +#include #include #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; -typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; -typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 Tds; -typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; -typedef Delaunay::Point Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; +typedef CGAL::Periodic_2_triangulation_vertex_base_2 Vbb; +typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; +typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 Tds; +typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; +typedef Delaunay::Point Point; int main() { diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp index 223fc38446e..59f1e70e696 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp @@ -2,18 +2,21 @@ #include #include +#include +#include #include #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; -typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; -typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 Tds; -typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; -typedef Delaunay::Point Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; +typedef CGAL::Periodic_2_triangulation_vertex_base_2 Vbb; +typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; +typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 Tds; +typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; +typedef Delaunay::Point Point; //a functor that returns a std::pair. //the unsigned integer is incremented at each call to diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp index a5a844ec2c8..7862f102373 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp @@ -2,18 +2,21 @@ #include #include +#include +#include #include #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; -typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; -typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 Tds; -typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; -typedef Delaunay::Point Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 Gt; +typedef CGAL::Periodic_2_triangulation_vertex_base_2 Vbb; +typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; +typedef CGAL::Periodic_2_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 Tds; +typedef CGAL::Periodic_2_Delaunay_triangulation_2 Delaunay; +typedef Delaunay::Point Point; int main() { From 851458caabeada6eef93e6fad792764971972b11 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 24 Jan 2019 16:47:59 +0100 Subject: [PATCH 152/186] Prefer Quotient to cpp_rational for now. Keeping cpp_int for Exact_integer, since MP_Float was never an alternative there. --- Number_types/include/CGAL/internal/Exact_type_selector.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/internal/Exact_type_selector.h b/Number_types/include/CGAL/internal/Exact_type_selector.h index f98f2ace0d6..a0c64f326fd 100644 --- a/Number_types/include/CGAL/internal/Exact_type_selector.h +++ b/Number_types/include/CGAL/internal/Exact_type_selector.h @@ -73,8 +73,10 @@ struct Exact_field_selector # endif #elif defined(CGAL_USE_LEDA) { typedef leda_rational Type; }; -#elif defined(CGAL_USE_BOOST_MP) -{ typedef boost::multiprecision::cpp_rational Type; }; +#elif 0 && defined(CGAL_USE_BOOST_MP) +// See the discussion in https://github.com/CGAL/cgal/pull/3614 +// This is disabled for now because cpp_rational is even slower than Quotient. Quotient will be a good candidate after some polishing. +{ typedef BOOST_cpp_arithmetic_kernel::Rational Type; }; #else { typedef Quotient Type; }; #endif From d37913665081a78d30d4d75f05347ad955fa5d0e Mon Sep 17 00:00:00 2001 From: Lingjie Zhu Date: Fri, 25 Jan 2019 10:33:39 +0800 Subject: [PATCH 153/186] add visual items after meshing fix #3617 --- .../Surface_mesh_approximation_plugin.cpp | 138 +++++++++--------- .../Plugins/Surface_mesh/VSA_wrapper.h | 2 + 2 files changed, 68 insertions(+), 72 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp index b83bf4c9758..c759ca6f394 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp @@ -243,11 +243,6 @@ public: BOOST_FOREACH(const QColor &c, approx.proxy_colors()) fcolors.push_back(CGAL::Color(c.red(), c.green(), c.blue())); approx.visual_items().planes->load(cvx_hull_points, cvx_hulls, fcolors, std::vector()); - - approx.visual_items().triangles->setVisible(true); - approx.visual_items().polygons->setVisible(true); - approx.visual_items().anchors->setVisible(false); - approx.visual_items().planes->setVisible(false); } public Q_SLOTS: @@ -307,8 +302,8 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked Patch_id_pmap pidmap(get(CGAL::face_patch_id_t(), *sm_item->face_graph())); approx.output(CGAL::parameters::face_proxy_map(pidmap)); - // TODO: previous items // new group items + // leave the memory management to the scene Scene_group_item *group = new Scene_group_item(tr("Approximation of %1").arg(sm_item->name())); scene->addItem(group); @@ -318,42 +313,13 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked scene->addItem(seeds_item); scene->changeGroup(seeds_item, group); - Scene_polygon_soup_item *triangles_item = new Scene_polygon_soup_item(); - triangles_item->setName(tr("Triangle soup")); - triangles_item->setColor(Qt::lightGray); - triangles_item->setRenderingMode(FlatPlusEdges); - triangles_item->setVisible(false); - scene->addItem(triangles_item); - scene->changeGroup(triangles_item, group); - - Scene_polylines_item *polygons_item = new Scene_polylines_item(); - polygons_item->setName(tr("Patch polygons")); - polygons_item->setColor(Qt::red); - polygons_item->setVisible(false); - scene->addItem(polygons_item); - scene->changeGroup(polygons_item, group); - - Scene_polylines_item *anchors_item = new Scene_polylines_item(); - anchors_item->setName(tr("Anchors")); - anchors_item->setColor(Qt::blue); - anchors_item->setVisible(false); - scene->addItem(anchors_item); - scene->changeGroup(anchors_item, group); - - Scene_polygon_soup_item *planes_item = new Scene_polygon_soup_item(); - planes_item->setName(tr("Patch planes")); - planes_item->setColor(Qt::yellow); - planes_item->setRenderingMode(FlatPlusEdges); - planes_item->setVisible(false); - scene->addItem(planes_item); - scene->changeGroup(planes_item, group); - approx.visual_items().group = group; approx.visual_items().seeds = seeds_item; - approx.visual_items().triangles = triangles_item; - approx.visual_items().polygons = polygons_item; - approx.visual_items().anchors = anchors_item; - approx.visual_items().planes = planes_item; + approx.visual_items().has_meshing_items = false; + approx.visual_items().triangles = NULL; + approx.visual_items().polygons = NULL; + approx.visual_items().anchors = NULL; + approx.visual_items().planes = NULL; update_seeds_item(approx, pmesh); @@ -366,14 +332,8 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked sm_item->invalidateOpenGLBuffers(); scene->itemChanged(scene->item_id(sm_item)); - if (ui_widget.checkAutomatic->isChecked()) { - update_meshing_items(approx, pmesh, - CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) - .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) - .with_dihedral_angle(ui_widget.with_dihedral_angle->isChecked()) - .optimize_anchor_location(ui_widget.if_optimize_anchor_location->isChecked()) - .pca_plane(ui_widget.pca_plane->isChecked())); - } + // default non auto-meshing + ui_widget.checkAutomatic->setChecked(false); scene->setSelectedItem(sm_id); @@ -404,12 +364,6 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonFit_clicked() { mi->information(QString("Fit one iteration, #proxies = %1.").arg(approx.number_of_proxies())); - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - sm_item->color_vector() = approx.proxy_colors(); sm_item->setItemIsMulticolor(true); sm_item->computeItemColorVectorAutomatically(false); @@ -417,6 +371,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonFit_clicked() { scene->itemChanged(scene->item_id(sm_item)); if (ui_widget.checkAutomatic->isChecked()) { + if (!approx.visual_items().has_meshing_items) { + mi->information(QString("Please meshing before checking auto meshing.")); + QApplication::restoreOverrideCursor(); + return; + } update_meshing_items(approx, pmesh, CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) @@ -456,12 +415,6 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonAdd_clicked() { approx.output(CGAL::parameters::face_proxy_map(pidmap)); update_seeds_item(approx, pmesh); - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - sm_item->color_vector() = approx.proxy_colors(); sm_item->setItemIsMulticolor(true); sm_item->computeItemColorVectorAutomatically(false); @@ -469,6 +422,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonAdd_clicked() { scene->itemChanged(scene->item_id(sm_item)); if (ui_widget.checkAutomatic->isChecked()) { + if (!approx.visual_items().has_meshing_items) { + mi->information(QString("Please meshing before checking auto meshing.")); + QApplication::restoreOverrideCursor(); + return; + } update_meshing_items(approx, pmesh, CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) @@ -508,12 +466,6 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke mi->information(QString("One proxy teleported, #proxies = %1.").arg(approx.number_of_proxies())); - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - sm_item->color_vector() = approx.proxy_colors(); sm_item->setItemIsMulticolor(true); sm_item->computeItemColorVectorAutomatically(false); @@ -521,6 +473,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke scene->itemChanged(scene->item_id(sm_item)); if (ui_widget.checkAutomatic->isChecked()) { + if (!approx.visual_items().has_meshing_items) { + mi->information(QString("Please meshing before checking auto meshing.")); + QApplication::restoreOverrideCursor(); + return; + } update_meshing_items(approx, pmesh, CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) @@ -562,12 +519,6 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSplit_clicked() approx.output(CGAL::parameters::face_proxy_map(pidmap)); update_seeds_item(approx, pmesh); - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - - sm_item->color_vector() = approx.proxy_colors(); - sm_item->color_vector() = approx.proxy_colors(); sm_item->setItemIsMulticolor(true); sm_item->computeItemColorVectorAutomatically(false); @@ -575,6 +526,11 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSplit_clicked() scene->itemChanged(scene->item_id(sm_item)); if (ui_widget.checkAutomatic->isChecked()) { + if (!approx.visual_items().has_meshing_items) { + mi->information(QString("Please meshing before checking auto meshing.")); + QApplication::restoreOverrideCursor(); + return; + } update_meshing_items(approx, pmesh, CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) @@ -603,6 +559,44 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonMeshing_clicked QApplication::setOverrideCursor(Qt::WaitCursor); + // and meshing items to group + CGAL::Three::Scene_group_item *group = approx.visual_items().group; + Scene_polygon_soup_item *triangles_item = new Scene_polygon_soup_item(); + triangles_item->setName(tr("Triangle soup")); + triangles_item->setColor(Qt::lightGray); + triangles_item->setRenderingMode(FlatPlusEdges); + triangles_item->setVisible(true); + scene->addItem(triangles_item); + scene->changeGroup(triangles_item, group); + + Scene_polylines_item *polygons_item = new Scene_polylines_item(); + polygons_item->setName(tr("Patch polygons")); + polygons_item->setColor(Qt::red); + polygons_item->setVisible(true); + scene->addItem(polygons_item); + scene->changeGroup(polygons_item, group); + + Scene_polylines_item *anchors_item = new Scene_polylines_item(); + anchors_item->setName(tr("Anchors")); + anchors_item->setColor(Qt::blue); + anchors_item->setVisible(true); + scene->addItem(anchors_item); + scene->changeGroup(anchors_item, group); + + Scene_polygon_soup_item *planes_item = new Scene_polygon_soup_item(); + planes_item->setName(tr("Patch planes")); + planes_item->setColor(Qt::yellow); + planes_item->setRenderingMode(FlatPlusEdges); + planes_item->setVisible(true); + scene->addItem(planes_item); + scene->changeGroup(planes_item, group); + + approx.visual_items().has_meshing_items = true; + approx.visual_items().triangles = triangles_item; + approx.visual_items().polygons = polygons_item; + approx.visual_items().anchors = anchors_item; + approx.visual_items().planes = planes_item; + update_meshing_items(approx, pmesh, CGAL::parameters::subdivision_ratio(ui_widget.chord_error->value()) .relative_to_chord(ui_widget.comboRelative->currentIndex() == 1) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h index 4da8af95e26..96516f5cefb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h @@ -111,6 +111,7 @@ public: Visual_items() : group(NULL), seeds(NULL), + has_meshing_items(false), triangles(NULL), polygons(NULL), anchors(NULL), @@ -118,6 +119,7 @@ public: CGAL::Three::Scene_group_item *group; Scene_polylines_item *seeds; + bool has_meshing_items; Scene_polygon_soup_item *triangles; Scene_polylines_item *polygons; Scene_polylines_item *anchors; From cb402f1e91e685383d2d5e333e12def2b6d9b91b Mon Sep 17 00:00:00 2001 From: Lingjie Zhu Date: Fri, 25 Jan 2019 10:56:15 +0800 Subject: [PATCH 154/186] update ui --- .../Surface_mesh_approximation_dockwidget.ui | 36 +++++++++++++++---- .../Surface_mesh_approximation_plugin.cpp | 3 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui index 65b1d9a5f1e..8b67236b224 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui @@ -6,8 +6,8 @@ 0 0 - 717 - 356 + 667 + 360 @@ -120,7 +120,7 @@ - true + false Negative value is ignored @@ -135,7 +135,7 @@ 4 - -1.000000000000000 + 0.001000000000000 1.000000000000000 @@ -144,7 +144,7 @@ 0.010000000000000 - -1.000000000000000 + 0.100000000000000 @@ -184,6 +184,13 @@ + + + + + + + @@ -485,5 +492,22 @@ - + + + enable_error_drop + toggled(bool) + error_drop + setEnabled(bool) + + + 127 + 168 + + + 153 + 167 + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp index c759ca6f394..0a9c67c2e5d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp @@ -295,7 +295,8 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSeeding_clicked approx.initialize_seeds(CGAL::parameters::seeding_method( static_cast(ui_widget.comboMethod->currentIndex())) .max_number_of_proxies(ui_widget.nb_proxies->value()) - .min_error_drop(ui_widget.error_drop->value()) + .min_error_drop( + ui_widget.enable_error_drop->isChecked() ? ui_widget.error_drop->value() : -1.0) .number_of_relaxations(ui_widget.nb_relaxations->value())); approx.run(ui_widget.nb_iterations->value()); From fb63d960e80b3eb0c31bcf8c3dcc216c28f54625 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 25 Jan 2019 09:32:32 +0100 Subject: [PATCH 155/186] Update doc based on reviews --- .../doc/Classification/Classification.txt | 16 +++++++++------- .../ETHZ/Random_forest_classifier.h | 6 +++--- .../OpenCV/Random_forest_classifier.h | 4 ++-- .../Sum_of_weighted_features_classifier.h | 2 +- .../TensorFlow/Neural_network_classifier.h | 15 ++++++++------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index b107408a547..2138985acd5 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -203,6 +203,10 @@ Example of cluster classification mesh (left: input, middle: clusters computed f \cgal provides four models for this concept, [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier), [OpenCV::Random_forest_classifier](@ref CGAL::Classification::OpenCV::Random_forest_classifier), [TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier) and [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier). +\note Currently, [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier) +is the best classifier available in \cgal and we strongly advise users +to use it. + To perform classification based on four classifiers, please refer to \ref Classification_classification_functions. \subsection Classification_ETHZ_random_forest ETHZ Random Forest @@ -215,9 +219,6 @@ the user does not have to install anything more). This classifier uses a ground truth training set to construct several decision trees that are then used to assign a label to each input item. -__This classifier is currently the best available in \cgal and we -strongly advise users to use it.__ - This classifier cannot be set up by hand and requires a ground truth training set. The training algorithm is fast but usually requires a high number of inliers. The training algorithm uses more memory at @@ -239,7 +240,6 @@ package. Note that this classifier usually produces results with a lower quality than [ETHZ::Random_forest_classifier](@ref CGAL::Classification::ETHZ::Random_forest_classifier). - It is provided for the sake of completeness and for testing purposes, but if you are not sure what to use, we advise using the ETHZ Random Forest instead. @@ -257,7 +257,7 @@ It uses the C++ API of the \ref thirdpartyTensorFlow library. \warning This feature is still experimental: it may not be stable and is likely to undergo substantial changes in future releases of -\cgal. Use at your own risk. +\cgal. The API changes will be announced in the release notes. The provided interface is a feature-based neural network: a set of features is used as an input layer followed by a user-specified number @@ -364,7 +364,7 @@ Top-Left: input point set. Top-Right: raw output classification represented by a Mathematical details are provided hereafter. -\subsection Classification_classify Raw classification +\subsection Classification_classify Raw Classification - `CGAL::Classification::classify()`: this is the fastest method that provides acceptable but usually noisy results (see Figure @@ -520,7 +520,9 @@ The following example shows how to use the classifier [OpenCV::Random_forest_cla \subsection Classification_example_tensorflow_neural_network TensorFlow Neural Network -The following example shows how to use the classifier [TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier) using an input training set. +The following example shows how to use the classifier +[TensorFlow::Neural_network_classifier](@ref CGAL::Classification::TensorFlow::Neural_network_classifier) +using an input training set. \cgalExample{Classification/example_tensorflow_neural_network.cpp} diff --git a/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h index 3535ec20c74..e0910e57275 100644 --- a/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h @@ -66,7 +66,7 @@ namespace ETHZ { /*! \ingroup PkgClassificationClassifiersETHZ - \brief %Classifier based on the ETH Zurich version of random forest algorithm \cgalCite{cgal:w-erftl-14}. + \brief %Classifier based on the ETH Zurich version of the random forest algorithm \cgalCite{cgal:w-erftl-14}. \note This classifier is distributed under the MIT license. @@ -88,7 +88,7 @@ public: /// @{ /*! - \brief Instantiate the classifier using the sets of `labels` and `features`. + \brief Instantiates the classifier using the sets of `labels` and `features`. */ Random_forest_classifier (const Label_set& labels, @@ -262,7 +262,7 @@ public: respect to a training set: if a feature is used a lot, that means that it has a strong discriminative power with respect to how the labels are represented by the feature set; on the contrary, if a - feature is not used very often, it's discriminative power is + feature is not used very often, its discriminative power is probably low; if a feature is _never_ used, it likely has no interest at all and is completely uncorrelated to the label segmentation of the training set. diff --git a/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h b/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h index acfa4b46e23..8b04c5d0b8d 100644 --- a/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/OpenCV/Random_forest_classifier.h @@ -42,7 +42,7 @@ namespace OpenCV { /*! \ingroup PkgClassificationClassifiersOpenCV - \brief %Classifier based on the OpenCV version of random forest algorithm. + \brief %Classifier based on the OpenCV version of the random forest algorithm. \note This class requires the \ref thirdpartyOpenCV library. @@ -70,7 +70,7 @@ public: /// @{ /*! - \brief Instantiate the classifier using the sets of `labels` and `features`. + \brief Instantiates the classifier using the sets of `labels` and `features`. Parameters documentation is copy-pasted from [the official documentation of OpenCV](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html). For more details on this method, please refer to it. diff --git a/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h b/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h index 2b159e27934..7426f275899 100644 --- a/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h +++ b/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h @@ -173,7 +173,7 @@ public: /*! - \brief Instantiate the classifier using the sets of `labels` and `features`. + \brief Instantiates the classifier using the sets of `labels` and `features`. \note If the label set of the feature set are modified after instantiating this object (addition of removal of a label and/or of diff --git a/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h b/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h index 23b0e473998..b3df48bb72b 100644 --- a/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h +++ b/Classification/include/CGAL/Classification/TensorFlow/Neural_network_classifier.h @@ -55,7 +55,8 @@ namespace TFops = tensorflow::ops; /*! \ingroup PkgClassificationClassifiersTensorFlow - \brief %Classifier based on the TensorFlow version of neural network. + \brief %Classifier based on the TensorFlow version of the neural + network algorithm. This class provides an interface to a feature-based neural network: a set of features is used as an input layer followed by a @@ -65,14 +66,14 @@ namespace TFops = tensorflow::ops; \warning This feature is still experimental: it may not be stable and is likely to undergo substantial changes in future releases of - \cgal. Use at your own risk. + \cgal. The API changes will be announced in the release notes. \note This class requires the \ref thirdpartyTensorFlow library. \tparam ActivationFunction Chosen activation function for the hidden - layers. Relu is used as default. The following functions can be used - (please refer to the documentation of TensorFlow for more - information): + layers. `Relu` is used as default. The following functions can be + used (please refer to the documentation of \ref thirdpartyTensorFlow + for more information): - `tensorflow::ops::Elu` - `tensorflow::ops::Relu6` - `tensorflow::ops::Relu` @@ -122,7 +123,7 @@ public: /// @{ /*! - \brief Instantiate the classifier using the sets of `labels` and `features`. + \brief Instantiates the classifier using the sets of `labels` and `features`. */ Neural_network_classifier (const Label_set& labels, @@ -230,7 +231,7 @@ public: information should be given the value `-1`. \param restart_from_scratch should be set to `false` if the user - wants to continue adjusting weights and bias based, and kept to + wants to continue adjusting weights and bias based, and set to `true` if the neural network should be re-created from scratch (discarding all previous training results). From ff18d34ab0ffee6cfa2a35920c4bf2d2649e92bf Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Jan 2019 10:32:11 +0100 Subject: [PATCH 156/186] Fix Erase_all so it wont hang on a lock child item. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index b45aca5ac1b..f8f28512e94 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1963,9 +1963,11 @@ bool MainWindow::on_actionErase_triggered() void MainWindow::on_actionEraseAll_triggered() { - scene->setSelectedItem(0); - while(on_actionErase_triggered()) { - } + QList all_ids; + for(int i = 0; i < scene->numberOfEntries(); ++i) + all_ids.push_back(i); + scene->setSelectedItemsList(all_ids); + on_actionErase_triggered(); } void MainWindow::on_actionDuplicate_triggered() From 1ce8c87b64316d41c75c2937ea8a56e59de33f3a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Jan 2019 13:45:43 +0100 Subject: [PATCH 157/186] Add a function that writes a vtu from a c3t3 and a list of attributes --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 51 ++++++++++++++++++-------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 020faeb33b7..9a2be82e1b4 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -258,11 +258,11 @@ write_attributes(std::ostream& os, write_vector(os,att); } -//public API template -void output_to_vtu(std::ostream& os, - const C3T3& c3t3, - IO::Mode mode = IO::BINARY) +void output_to_vtu_with_attributes(std::ostream& os, + const C3T3& c3t3, + std::vector*> >& attributes, + IO::Mode mode = IO::BINARY) { typedef typename C3T3::Triangulation Tr; typedef typename Tr::Vertex_handle Vertex_handle; @@ -289,21 +289,16 @@ void output_to_vtu(std::ostream& os, os << " \n"; std::size_t offset = 0; + + const bool binary = (mode == IO::BINARY); write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII - - std::vector mids; - mids.reserve(c3t3.number_of_cells_in_complex()); - for( typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) { - mids.push_back(cit->subdomain_index()); + os << " \n"; + for(std::size_t i = 0; i< attributes.size(); ++i) + { + write_attribute_tag(os,attributes[i].first, *attributes[i].second, binary,offset); } - - os << " \n"; - write_attribute_tag(os,"MeshDomain",mids,binary,offset); os << " \n"; os << " \n" << " \n"; @@ -311,10 +306,34 @@ void output_to_vtu(std::ostream& os, os << "\n_"; write_c3t3_points(os,tr,V); // fills V if the mode is BINARY write_cells(os,c3t3,V); - write_attributes(os,mids); + for(std::size_t i = 0; i< attributes.size(); ++i) + write_attributes(os, *attributes[i].second); } os << "\n"; } + + +//public API +template +void output_to_vtu(std::ostream& os, + const C3T3& c3t3, + IO::Mode mode = IO::BINARY) +{ + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; + typedef typename Tr::Vertex_handle Vertex_handle; + std::vector mids; + for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; + cit != c3t3.cells_in_complex_end() ; + ++cit ) + { + mids.push_back(cit->subdomain_index()); + } + std::vector* > > atts; + atts.push_back(std::make_pair("MeshDomain", &mids)); + output_to_vtu_with_attributes(os, c3t3, atts, mode); +} + } //end CGAL #endif // CGAL_VTK_IO_H From 06b42de0558863a9158a6973dbcfcf56dbea2a93 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Jan 2019 14:43:58 +0100 Subject: [PATCH 158/186] Fixes --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 9a2be82e1b4..e1f67ec3b33 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -261,7 +261,7 @@ write_attributes(std::ostream& os, template void output_to_vtu_with_attributes(std::ostream& os, const C3T3& c3t3, - std::vector*> >& attributes, + std::vector*> >& attributes, IO::Mode mode = IO::BINARY) { typedef typename C3T3::Triangulation Tr; @@ -289,12 +289,11 @@ void output_to_vtu_with_attributes(std::ostream& os, os << " \n"; std::size_t offset = 0; - - + const bool binary = (mode == IO::BINARY); write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII - os << " \n"; + os << " \n"; for(std::size_t i = 0; i< attributes.size(); ++i) { write_attribute_tag(os,attributes[i].first, *attributes[i].second, binary,offset); From b812f333a0e5f2124c077100b584a086e5d3c9a1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Jan 2019 15:04:37 +0100 Subject: [PATCH 159/186] Dont export far points when converting to vtkUnstructuredGrid --- .../CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h b/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h index 8b9cd7e7520..8370bab261f 100644 --- a/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h +++ b/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h @@ -50,7 +50,7 @@ output_c3t3_to_vtk_unstructured_grid(const C3T3& c3t3, vtkCellArray* const vtk_facets = vtkCellArray::New(); vtkCellArray* const vtk_cells = vtkCellArray::New(); - vtk_points->Allocate(c3t3.triangulation().number_of_vertices()); + vtk_points->Allocate(c3t3.triangulation().number_of_vertices()- c3t3.number_of_far_points()); vtk_facets->Allocate(c3t3.number_of_facets_in_complex()); vtk_cells->Allocate(c3t3.number_of_cells_in_complex()); @@ -64,11 +64,14 @@ output_c3t3_to_vtk_unstructured_grid(const C3T3& c3t3, ++vit) { typedef typename Triangulation::Weighted_point Weighted_point; - const Weighted_point& p = tr.point(vit); - vtk_points->InsertNextPoint(CGAL::to_double(p.x()), - CGAL::to_double(p.y()), - CGAL::to_double(p.z())); - V[vit] = inum++; + if(vit->in_dimension() > -1) + { + const Weighted_point& p = tr.point(vit); + vtk_points->InsertNextPoint(CGAL::to_double(p.x()), + CGAL::to_double(p.y()), + CGAL::to_double(p.z())); + V[vit] = inum++; + } } for(typename C3T3::Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(), From e456d29abfa671252ac409fc7ccc31b72bfee724 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Jan 2019 16:10:03 +0100 Subject: [PATCH 160/186] WIP write_vtu_with_attributes --- Mesh_2/include/CGAL/IO/write_vtu.h | 93 ++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 9580d434b49..15aeb489e8c 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -276,6 +276,99 @@ write_cdt_points(std::ostream& os, write_vector(os,coordinates); } +// writes the attribute tags before binary data is appended +template +void +write_attribute_tag_2 (std::ostream& os, + const std::string& attr_name, + const std::vector& attribute, + bool binary, + std::size_t& offset) +{ + std::string format = binary ? "appended" : "ascii"; + std::string type = (sizeof(T) == 8) ? "Float64" : "Float32"; + os << " \n"; + offset += attribute.size() * sizeof(T) + sizeof(std::size_t); + } + else { + typedef typename std::vector::const_iterator Iterator; + os << "\">\n"; + for (Iterator it = attribute.begin(); + it != attribute.end(); + ++it ) + os << *it << " "; + os << " \n"; + } +} + +// writes the attributes appended data at the end of the .vtu file +template +void +write_attributes_2(std::ostream& os, + const std::vector& att) +{ + write_vector(os,att); +} + +template +void write_vtu_with_attributes(std::ostream& os, + const CDT& tr, + std::vector*> >& attributes, + IO::Mode mode = IO::BINARY) +{ + typedef typename CDT::Vertex_handle Vertex_handle; + std::map V; + //write header + os << "\n" + << "\n" + << " " << "\n"; + + int number_of_triangles = 0; + for(typename CDT::Finite_faces_iterator + fit = tr.finite_faces_begin(), + end = tr.finite_faces_end(); + fit != end; ++fit) + { + if(fit->is_in_domain()) ++number_of_triangles; + } + os << " \n"; + std::size_t offset = 0; + const bool binary = (mode == IO::BINARY); + write_cdt_points_tag(os,tr,V,binary,offset); + write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); + os << " \n"; + for(std::size_t i = 0; i< attributes.size(); ++i) + { + write_attribute_tag_2(os,attributes[i].first, *attributes[i].second, binary,offset); + } + os << " \n" + << " \n"; + if (binary) { + os << "\n_"; + write_cdt_points(os,tr,V); // write points before cells to fill the std::map V + write_cells_2(os,tr, number_of_triangles, V); + for(std::size_t i = 0; i< attributes.size(); ++i) + write_attributes_2(os, *attributes[i].second); + } + os << "\n"; +} + template void write_vtu(std::ostream& os, From 02de899d268c8e39b08cd45352a0d97cdc1c5c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 28 Jan 2019 15:17:58 +0100 Subject: [PATCH 161/186] fix wrong ref --- .../include/CGAL/Polygon_mesh_processing/border.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h index 1c6d870c28f..6e7c905b64d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h @@ -258,7 +258,7 @@ namespace Polygon_mesh_processing { return border_counter; } - /// @ingroup PkgPolygonMeshProcessing + /// @ingroup PkgPolygonMeshProcessingRef /// extracts boundary cycles as a list of halfedges, with one halfedge per border. /// /// @tparam PolygonMesh a model of `HalfedgeListGraph` From 0322901c39ad1f4a8e32317db2b1125ed7b72307 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 30 Jan 2019 10:09:45 +0100 Subject: [PATCH 162/186] Link with ImageIO --- Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt index 7097e37e4fe..7992f99ddfc 100644 --- a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt +++ b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt @@ -5,9 +5,10 @@ project( Periodic_3_mesh_3_Tests ) cmake_minimum_required(VERSION 3.1) -find_package( CGAL QUIET ) +find_package( CGAL QUIET COMPONENTS ImageIO ) if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) From ad300da617a09bfe934042c95f19d1ee8dd01a1f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 30 Jan 2019 16:55:27 +0100 Subject: [PATCH 163/186] Fix write_vtu_with_argumetns --- Mesh_2/include/CGAL/IO/write_vtu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 15aeb489e8c..41534385280 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -357,6 +357,7 @@ void write_vtu_with_attributes(std::ostream& os, { write_attribute_tag_2(os,attributes[i].first, *attributes[i].second, binary,offset); } + os << " \n"; os << " \n" << " \n"; if (binary) { From 16f61704da4f09bdf2bb1406c9c24793f816e0a6 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 31 Jan 2019 10:55:25 +0100 Subject: [PATCH 164/186] Set policy --- Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt index 7992f99ddfc..68ab382ea9f 100644 --- a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt +++ b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt @@ -5,6 +5,10 @@ project( Periodic_3_mesh_3_Tests ) cmake_minimum_required(VERSION 3.1) +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() + find_package( CGAL QUIET COMPONENTS ImageIO ) if ( CGAL_FOUND ) From ec1de6d0773c23bde2fdd5d6cacd299b8862d9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 31 Jan 2019 11:49:41 +0100 Subject: [PATCH 165/186] fix warning --- Point_set_processing_3/include/CGAL/mst_orient_normals.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Point_set_processing_3/include/CGAL/mst_orient_normals.h b/Point_set_processing_3/include/CGAL/mst_orient_normals.h index 72cd4e3b48f..8dd0bd69d92 100644 --- a/Point_set_processing_3/include/CGAL/mst_orient_normals.h +++ b/Point_set_processing_3/include/CGAL/mst_orient_normals.h @@ -488,6 +488,7 @@ create_mst_graph( CGAL_USE(point_map); CGAL_USE(k); CGAL_USE(kernel); + CGAL_USE(index_map); // Bring private stuff to scope using namespace internal; From 3b1b080330eeccbc17ee2785c1925645e091c4e5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 31 Jan 2019 13:39:44 +0100 Subject: [PATCH 166/186] Do for example what we did for test --- .../examples/Periodic_3_mesh_3/CMakeLists.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt b/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt index ef572651d9f..4c3efde1ded 100644 --- a/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt +++ b/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt @@ -5,10 +5,16 @@ project( Periodic_3_mesh_3_Examples ) cmake_minimum_required(VERSION 3.1) -# CGAL and its components -find_package( CGAL QUIET ) +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() -if ( NOT CGAL_FOUND ) +# CGAL and its components +find_package( CGAL QUIET COMPONENTS ImageIO ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) +else() message(STATUS "This project requires the CGAL library, and will not be compiled.") return() endif() From c59c95d030e8287633b8ae2197a9919b2dae75db Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 31 Jan 2019 13:50:55 +0100 Subject: [PATCH 167/186] Fix Plugin. --- .../Surface_mesh/Surface_mesh_approximation_plugin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp index 68c11cca37c..ec49ce6c9db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp @@ -374,7 +374,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonFit_clicked() { if (ui_widget.checkAutomatic->isChecked()) { if (!approx.visual_items().has_meshing_items) { - mi->information(QString("Please meshing before checking auto meshing.")); + CGAL::Three::Three::information(QString("Please mesh before checking auto meshing.")); QApplication::restoreOverrideCursor(); return; } @@ -425,7 +425,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonAdd_clicked() { if (ui_widget.checkAutomatic->isChecked()) { if (!approx.visual_items().has_meshing_items) { - mi->information(QString("Please meshing before checking auto meshing.")); + CGAL::Three::Three::information(QString("Please mesh before checking auto meshing.")); QApplication::restoreOverrideCursor(); return; } @@ -476,7 +476,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonTeleport_clicke if (ui_widget.checkAutomatic->isChecked()) { if (!approx.visual_items().has_meshing_items) { - mi->information(QString("Please meshing before checking auto meshing.")); + CGAL::Three::Three::information(QString("Please mesh before checking auto meshing.")); QApplication::restoreOverrideCursor(); return; } @@ -529,7 +529,7 @@ void Polyhedron_demo_surface_mesh_approximation_plugin::on_buttonSplit_clicked() if (ui_widget.checkAutomatic->isChecked()) { if (!approx.visual_items().has_meshing_items) { - mi->information(QString("Please meshing before checking auto meshing.")); + CGAL::Three::Three::information(QString("Please mesh before checking auto meshing.")); QApplication::restoreOverrideCursor(); return; } From b5a25de3e820364bb28d552104602d05e62ee642 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 31 Jan 2019 14:07:13 +0100 Subject: [PATCH 168/186] Fix the Qt warning about semdMessage in the mainwindow --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 87b373c8b3f..3dc40771444 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -261,8 +261,10 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren connect(viewer, SIGNAL(requestContextMenu(QPoint)), this, SLOT(contextMenuRequested(QPoint))); - connect(viewer, SIGNAL(sendMessage(QString)), - this, SLOT(information(QString))); + connect(viewer, &Viewer::sendMessage, + this, [this](QString s){ + information(s); + }); // The contextMenuPolicy of infoLabel is now the default one, so that one // can easily copy-paste its text. From 5163d04c8ac020f4f037fa3fa87526355ee2258f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 31 Jan 2019 15:09:07 +0100 Subject: [PATCH 169/186] Fix AABB_tree --- .../AABB_tree/AABB_custom_indexed_triangle_set_example.cpp | 2 +- .../examples/AABB_tree/AABB_custom_triangle_soup_example.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AABB_tree/examples/AABB_tree/AABB_custom_indexed_triangle_set_example.cpp b/AABB_tree/examples/AABB_tree/AABB_custom_indexed_triangle_set_example.cpp index b6c9d360951..4311d1cbbf8 100644 --- a/AABB_tree/examples/AABB_tree/AABB_custom_indexed_triangle_set_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_custom_indexed_triangle_set_example.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/AABB_tree/examples/AABB_tree/AABB_custom_triangle_soup_example.cpp b/AABB_tree/examples/AABB_tree/AABB_custom_triangle_soup_example.cpp index 0bcfbb6ca9a..590c5c0c7ba 100644 --- a/AABB_tree/examples/AABB_tree/AABB_custom_triangle_soup_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_custom_triangle_soup_example.cpp @@ -1,10 +1,11 @@ + // Author(s) : Camille Wormser, Pierre Alliez // Example of an AABB tree used with a simple list of // triangles (a triangle soup) stored into an array of points. #include #include -#include +#include #include #include From f1e1b57fa40a57bc89d90ed7476f47378353bcbb Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 31 Jan 2019 19:00:14 +0100 Subject: [PATCH 170/186] Remove call of setprecision() as it has no effect --- CGAL_Core/include/CGAL/CORE/CoreDefs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/CGAL_Core/include/CGAL/CORE/CoreDefs.h b/CGAL_Core/include/CGAL/CORE/CoreDefs.h index 1d136ab43d1..c9851e6c09c 100644 --- a/CGAL_Core/include/CGAL/CORE/CoreDefs.h +++ b/CGAL_Core/include/CGAL/CORE/CoreDefs.h @@ -322,7 +322,6 @@ inline bool setRationalReduceFlag(bool f) { inline void CORE_init(long d) { get_static_defAbsPrec() = CORE_posInfty; get_static_defOutputDigits() = d; - std::setprecision(get_static_defOutputDigits()); } /// change to scientific output format From f3dc5f1de7a7fcfd6f1483940bcdd4d47226ad9c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 1 Feb 2019 09:13:36 +0100 Subject: [PATCH 171/186] Remove useless full find_package for OpenCV --- Classification/examples/Classification/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 5789622899a..d3b5ebe366f 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -111,7 +111,6 @@ if( WIN32 ) endif() endif() -find_package(OpenCV QUIET) if (OpenCV_FOUND) message(STATUS "Found OpenCV ${OpenCV_VERSION}") include_directories(${OpenCV_INCLUDE_DIRS}) From f2f2196280b31ca818623b5141346a7ab178389d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 09:45:32 +0100 Subject: [PATCH 172/186] fix warning --- 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 3dc40771444..103eda2d57e 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -262,7 +262,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren connect(viewer, SIGNAL(requestContextMenu(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(viewer, &Viewer::sendMessage, - this, [this](QString s){ + this, [](QString s){ information(s); }); From 8baad2fcb3c253a9be9505320ca85c528a3a9df7 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 12:22:08 +0100 Subject: [PATCH 173/186] Fix the tests for GCC<4.4 so it wont match clang. --- .../examples/Triangulation/delaunay_triangulation.cpp | 2 +- Triangulation/examples/Triangulation/triangulation.cpp | 3 +-- Triangulation/test/Triangulation/test_delaunay.cpp | 2 +- Triangulation/test/Triangulation/test_torture.cpp | 2 +- Triangulation/test/Triangulation/test_triangulation.cpp | 4 +--- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index 036c0de6d50..7118aa379a8 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/examples/Triangulation/triangulation.cpp b/Triangulation/examples/Triangulation/triangulation.cpp index 043c3cd38f6..602893f7ec4 100644 --- a/Triangulation/examples/Triangulation/triangulation.cpp +++ b/Triangulation/examples/Triangulation/triangulation.cpp @@ -1,5 +1,4 @@ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) - +#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index a8e5ca5b761..58deb6ae64f 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_torture.cpp b/Triangulation/test/Triangulation/test_torture.cpp index f85047f2293..bfc1f86b809 100644 --- a/Triangulation/test/Triangulation/test_torture.cpp +++ b/Triangulation/test/Triangulation/test_torture.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index 308b3f10c7d..34a6dcfa5c3 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -1,5 +1,4 @@ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) - +#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { @@ -7,7 +6,6 @@ int main() } #else - #include #include #include From ed3f2cf357dc6ce388d60c2be667a97b74f33f48 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 15:32:38 +0100 Subject: [PATCH 174/186] Fix Color_each_components --- .../Polyhedron/Scene_surface_mesh_item.cpp | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index b3b517b254c..c7b50f1d84c 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -537,7 +537,12 @@ void Scene_surface_mesh_item_priv::compute_elements(Scene_item_rendering_helper: Point p = positions[source(hd, *smesh_)]; EPICK::Vector_3 n = fnormals[fd]; CGAL::Color *c; - if(has_fcolors) + if(has_fpatch_id) + { + QColor color = item->color_vector()[fpatch_id_map[fd] - min_patch_id]; + c = new CGAL::Color(color.red(),color.green(),color.blue()); + } + else if(has_fcolors) c= &fcolors[fd]; else c = 0; @@ -572,6 +577,8 @@ void Scene_surface_mesh_item_priv::compute_elements(Scene_item_rendering_helper: ,fnormals[fd] , c , name); + if(has_fpatch_id) + delete c; } else if(is_convex) { @@ -855,7 +862,12 @@ void Scene_surface_mesh_item_priv::triangulate_convex_facet(face_descriptor fd, if(!index) { CGAL::Color* color; - if(has_fcolors) + if(has_fpatch_id) + { + QColor c = item->color_vector()[fpatch_id_map[fd] - min_patch_id]; + color = new CGAL::Color(c.red(),c.green(),c.blue()); + } + else if(has_fcolors) color = &(*fcolors)[fd]; else color = 0; @@ -872,6 +884,8 @@ void Scene_surface_mesh_item_priv::triangulate_convex_facet(face_descriptor fd, (*fnormals)[fd], color, name); + if(has_fpatch_id) + delete color; } else if(name.testFlag(Scene_item_rendering_helper::GEOMETRY)) { @@ -940,7 +954,12 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd, if(!index) { CGAL::Color* color; - if(has_fcolors) + if(has_fpatch_id) + { + QColor c= item->color_vector()[fpatch_id_map[fd] - min_patch_id]; + color = new CGAL::Color(c.red(),c.green(),c.blue()); + } + else if(has_fcolors) color = &(*fcolors)[fd]; else color = 0; @@ -958,6 +977,8 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd, (*fnormals)[fd], color, name); + if(has_fpatch_id) + delete color; } //adds the indices to the appropriate vector else From ed127d3696d46f2b720e347e0e7a9114357b4f5d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 15:41:50 +0100 Subject: [PATCH 175/186] Invalidate bbox when invalidate geometry in sm item. --- Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index c7b50f1d84c..bc44f100eff 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -1251,6 +1251,7 @@ void Scene_surface_mesh_item::invalidate(Gl_data_names name) Q_EMIT item_is_about_to_be_changed(); if(name.testFlag(GEOMETRY)) { + is_bbox_computed = false; delete_aabb_tree(this); d->smesh_->collect_garbage(); d->invalidate_stats(); From 1c1677e48d2b2f46a9d3c153e0e02aa3f0580ddc Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 15:54:56 +0100 Subject: [PATCH 176/186] If all points of polyline are equal, display as points. --- Polyhedron/demo/Polyhedron/Scene_polylines_item.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_polylines_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polylines_item.cpp index 801205d5653..fcc1e85634b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polylines_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polylines_item.cpp @@ -110,6 +110,7 @@ Scene_polylines_item_private::computeElements() const QApplication::setOverrideCursor(Qt::WaitCursor); positions_lines.resize(0); double mean = 0; + bool all_equal=true; //Fills the VBO with the lines for(std::list >::const_iterator it = item->polylines.begin(); it != item->polylines.end(); @@ -122,6 +123,8 @@ Scene_polylines_item_private::computeElements() const { const Point_3& a = (*it)[i]; const Point_3& b = (*it)[i+1]; + if(a!=b) + all_equal = false; if(!computed_stats) { ++nb_edges; @@ -148,6 +151,8 @@ Scene_polylines_item_private::computeElements() const } } + if(all_equal) + item->setPointsMode(); if(!computed_stats) mean_length = mean/double(nb_edges); computed_stats = true; @@ -446,7 +451,9 @@ Scene_polylines_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const { d->computeElements(); d->initializeBuffers(viewer); } - + GLfloat point_size; + viewer->glGetFloatv(GL_POINT_SIZE, &point_size); + viewer->setGlPointSize(GLfloat(5)); vaos[Scene_polylines_item_private::Edges]->bind(); attribBuffers(viewer, PROGRAM_NO_SELECTION); QOpenGLShaderProgram *program = getShaderProgram(PROGRAM_NO_SELECTION); @@ -457,6 +464,7 @@ Scene_polylines_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const { // Clean-up vaos[Scene_polylines_item_private::Edges]->release(); program->release(); + viewer->setGlPointSize(point_size); } if(d->draw_extremities) { From 126dd4d7dc300ba32b83342f31015dfa8545b69d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 1 Feb 2019 16:29:21 +0100 Subject: [PATCH 177/186] Add an action to save files (not as) --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 17 +++++++++++++++++ Polyhedron/demo/Polyhedron/MainWindow.h | 2 ++ Polyhedron/demo/Polyhedron/MainWindow.ui | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 87b373c8b3f..a86ad7c9e7b 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2767,3 +2767,20 @@ void MainWindow::invalidate_bbox(bool do_recenter) updateViewerBBox(true); } + +void MainWindow::on_action_Save_triggered() +{ + if(QMessageBox::question(this, "Save", "Are you sure you want to override these files ?") + == QMessageBox::No) + return; + Scene_item* item = nullptr; + Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) + { + item = scene->item(id); + if(!item->property("source filename").toString().isEmpty()) + { + QString filename = item->property("source filename").toString(); + save(filename, item); + } + } +} diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index e13f316ed8c..0689df3183e 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -327,6 +327,8 @@ protected Q_SLOTS: //Preferences edition //!Opens the Preferences dialog. void on_actionPreferences_triggered(); + //!Save selected items if able. + void on_action_Save_triggered(); // save as... //!Opens a dialog to save selected item if able. void on_actionSaveAs_triggered(); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index c5057750dcf..5329803091d 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -48,6 +48,7 @@ + @@ -498,6 +499,11 @@ Sa&ve the Scene as a Script File... + + + &Save + + From 6cff52c485616d94cac4fd537e52a6a041a6f653 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 4 Feb 2019 09:58:47 +0100 Subject: [PATCH 178/186] write_vtu uses write_vtu_with_attributes --- Mesh_2/include/CGAL/IO/write_vtu.h | 48 ++++-------------------------- 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/Mesh_2/include/CGAL/IO/write_vtu.h b/Mesh_2/include/CGAL/IO/write_vtu.h index 41534385280..bab5d5b4c11 100644 --- a/Mesh_2/include/CGAL/IO/write_vtu.h +++ b/Mesh_2/include/CGAL/IO/write_vtu.h @@ -352,7 +352,10 @@ void write_vtu_with_attributes(std::ostream& os, const bool binary = (mode == IO::BINARY); write_cdt_points_tag(os,tr,V,binary,offset); write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); - os << " \n"; + if(attributes.empty()) + os << " \n"; + else + os << " \n"; for(std::size_t i = 0; i< attributes.size(); ++i) { write_attribute_tag_2(os,attributes[i].first, *attributes[i].second, binary,offset); @@ -376,47 +379,8 @@ void write_vtu(std::ostream& os, const CDT& tr, IO::Mode mode = IO::BINARY) { - typedef typename CDT::Vertex_handle Vertex_handle; - std::map V; - //write header - os << "\n" - << "\n" - << " " << "\n"; - - int number_of_triangles = 0; - for(typename CDT::Finite_faces_iterator - fit = tr.finite_faces_begin(), - end = tr.finite_faces_end(); - fit != end; ++fit) - { - if(fit->is_in_domain()) ++number_of_triangles; - } - os << " \n"; - std::size_t offset = 0; - const bool binary = (mode == IO::BINARY); - write_cdt_points_tag(os,tr,V,binary,offset); - write_cells_tag_2(os,tr,number_of_triangles, V,binary,offset); - os << " \n" - << " \n"; - if (binary) { - os << "\n_"; - write_cdt_points(os,tr,V); // write points before cells to fill the std::map V - write_cells_2(os,tr, number_of_triangles, V); - } - os << "\n"; + std::vector*> > dummy_atts; + write_vtu_with_attributes(os, tr, dummy_atts, mode); } } //end CGAL From de8dde79f4a7032fa382898ca780365fe15fde6d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 4 Feb 2019 10:40:00 +0100 Subject: [PATCH 179/186] Replace not by ! in preprocessor directives --- .../cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake | 2 +- Triangulation/examples/Triangulation/delaunay_triangulation.cpp | 2 +- Triangulation/examples/Triangulation/triangulation.cpp | 2 +- Triangulation/test/Triangulation/test_delaunay.cpp | 2 +- Triangulation/test/Triangulation/test_torture.cpp | 2 +- Triangulation/test/Triangulation/test_triangulation.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake index e22308e0025..66e7007f3d1 100644 --- a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake @@ -56,7 +56,7 @@ endif() # See the release notes of CGAL-4.10: CGAL_Core now requires # Boost.Thread, with all compilers but MSVC. if (NOT MSVC) - find_package( Boost 1.48 REQUIRED thread system ) + find_package( Boost 1.48 REQUIRED COMPONENTS thread system ) endif() function(CGAL_setup_CGAL_Core_dependencies target) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index 7118aa379a8..d0b210e0b63 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/examples/Triangulation/triangulation.cpp b/Triangulation/examples/Triangulation/triangulation.cpp index 602893f7ec4..a06ab7ab23d 100644 --- a/Triangulation/examples/Triangulation/triangulation.cpp +++ b/Triangulation/examples/Triangulation/triangulation.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 58deb6ae64f..476d44807ee 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_torture.cpp b/Triangulation/test/Triangulation/test_torture.cpp index bfc1f86b809..6a9877026a3 100644 --- a/Triangulation/test/Triangulation/test_torture.cpp +++ b/Triangulation/test/Triangulation/test_torture.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index 34a6dcfa5c3..ec29fce1d3d 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && not defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { From 302a2cd225058b24ae428d9eeab2d2c415a807e2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 4 Feb 2019 14:13:40 +0100 Subject: [PATCH 180/186] Use BOOST_GCC --- .../examples/Triangulation/delaunay_triangulation.cpp | 3 ++- Triangulation/examples/Triangulation/triangulation.cpp | 3 ++- Triangulation/test/Triangulation/test_delaunay.cpp | 3 ++- Triangulation/test/Triangulation/test_torture.cpp | 3 ++- Triangulation/test/Triangulation/test_triangulation.cpp | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index d0b210e0b63..f9db18d22c0 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#include +#if defined(BOOST_GCC) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/examples/Triangulation/triangulation.cpp b/Triangulation/examples/Triangulation/triangulation.cpp index a06ab7ab23d..06420697921 100644 --- a/Triangulation/examples/Triangulation/triangulation.cpp +++ b/Triangulation/examples/Triangulation/triangulation.cpp @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#include +#if defined(BOOST_GCC) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 476d44807ee..8ba85a3d84d 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#include +#if defined(BOOST_GCC) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_torture.cpp b/Triangulation/test/Triangulation/test_torture.cpp index 6a9877026a3..72cefb83552 100644 --- a/Triangulation/test/Triangulation/test_torture.cpp +++ b/Triangulation/test/Triangulation/test_torture.cpp @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#include +#if defined(BOOST_GCC) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index ec29fce1d3d..1f9a8b5c8a2 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && ! defined (__clang__) && defined(__GNUC_MINOR__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) +#include +#if defined(BOOST_GCC) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 4) #include int main() { From 02690350eece48890e07b715eb8171b10651a75a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 4 Feb 2019 15:30:24 +0100 Subject: [PATCH 181/186] Replace include(CTest) by minimal usage - Define the option `BUILD_TESTING` - Call to `enable_testing()` if `BUILD_TESTING` is on. --- CMakeLists.txt | 4 +++- Installation/CMakeLists.txt | 4 +++- Installation/cmake/modules/CGAL_add_test.cmake | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c884132d3e..216f1c2829f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,11 +37,13 @@ message( "== CMake setup (DONE) ==\n" ) # Enable testing with BUILD_TESTING option(BUILD_TESTING "Build the testing tree." OFF) -include(CTest) if(BUILD_TESTING AND NOT POLICY CMP0064) message(FATAL_ERROR "CGAL support of CTest requires CMake version 3.4 or later. The variable BUILD_TESTING must be set of OFF.") endif() +if(BUILD_TESTING) + enable_testing() +endif() # and finally start actual build add_subdirectory( Installation ) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 88e41c1c455..f40f327b608 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -108,11 +108,13 @@ else ( CGAL_BRANCH_BUILD ) # Enable testing with BUILD_TESTING option(BUILD_TESTING "Build the testing tree." OFF) - include(CTest) if(BUILD_TESTING AND NOT POLICY CMP0064) message(FATAL_ERROR "CGAL support of CTest requires CMake version 3.4 or later. The variable BUILD_TESTING must be set of OFF.") endif() + if(BUILD_TESTING) + enable_testing() + endif() endif (CGAL_BRANCH_BUILD ) #message(STATUS "Packages found: ${CGAL_CONFIGURED_PACKAGES}") diff --git a/Installation/cmake/modules/CGAL_add_test.cmake b/Installation/cmake/modules/CGAL_add_test.cmake index 2f0aec7163a..adf2430ff66 100644 --- a/Installation/cmake/modules/CGAL_add_test.cmake +++ b/Installation/cmake/modules/CGAL_add_test.cmake @@ -3,6 +3,8 @@ if(CGAL_add_test_included) endif(CGAL_add_test_included) set(CGAL_add_test_included TRUE) +option(BUILD_TESTING "Build the testing tree." OFF) + if(NOT POLICY CMP0064) # CMake <= 3.3 if(BUILD_TESTING) @@ -19,7 +21,9 @@ if(NOT POLICY CMP0064) return() endif() -include(CTest) +if(BUILD_TESTING) + enable_testing() +endif() cmake_policy(SET CMP0064 NEW) From dc275ec013e2a10083ba99ef323c9399617eccba Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 4 Feb 2019 15:47:07 +0100 Subject: [PATCH 182/186] Fix a warning about unused local type --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index e1f67ec3b33..040bebd7d6c 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -319,9 +319,7 @@ void output_to_vtu(std::ostream& os, const C3T3& c3t3, IO::Mode mode = IO::BINARY) { - typedef typename C3T3::Triangulation Tr; typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - typedef typename Tr::Vertex_handle Vertex_handle; std::vector mids; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; From 37cc9b03c720a17c4a60cb317864afd8de2250fc Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Feb 2019 16:42:00 +0100 Subject: [PATCH 183/186] Fix output_to_vtu --- Mesh_3/include/CGAL/IO/output_to_vtu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/Mesh_3/include/CGAL/IO/output_to_vtu.h index 040bebd7d6c..5c9583ba272 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/Mesh_3/include/CGAL/IO/output_to_vtu.h @@ -327,7 +327,7 @@ void output_to_vtu(std::ostream& os, { mids.push_back(cit->subdomain_index()); } - std::vector* > > atts; + std::vector* > > atts; atts.push_back(std::make_pair("MeshDomain", &mids)); output_to_vtu_with_attributes(os, c3t3, atts, mode); } From 9c31f25653c96df4ce1bd5e579b2f23f305ee0cc Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 7 Feb 2019 13:29:39 +0100 Subject: [PATCH 184/186] trivial fix (Python issue) --- Scripts/developer_scripts/list_pull_requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/list_pull_requests.py b/Scripts/developer_scripts/list_pull_requests.py index 70dfe831f4e..ea93906844e 100755 --- a/Scripts/developer_scripts/list_pull_requests.py +++ b/Scripts/developer_scripts/list_pull_requests.py @@ -68,7 +68,7 @@ else: print_verbose(" index path is {}".format(repo.index_path())) print_verbose("Getting commits in current branch", end='') print_verbose(" {}".\ - format(str(repo.refs.read_ref('HEAD'), "ascii")), end='') + format(str(repo.refs.read_ref(b'HEAD'), "ascii")), end='') sys.stderr.flush() walk = repo.get_walker(include=repo.head(),\ exclude=[repo.get_refs()[b'refs/remotes/cgal/master']]) From d884aaadeab08bacdf03882d896a4017681a9daa Mon Sep 17 00:00:00 2001 From: Maxime GIMENO Date: Tue, 12 Feb 2019 09:23:09 +0100 Subject: [PATCH 185/186] Travis: Upgrade travis to xenial (#3666) Upgrade travis to xenial --- .travis.yml | 8 ++++---- .travis/build_package.sh | 2 +- .travis/generate_travis.sh | 2 +- .travis/install.sh | 20 +++++--------------- .travis/template.txt | 8 ++++---- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 981151439f8..7591e1e74a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: cpp -dist: trusty +dist: xenial sudo: required git: depth: 3 @@ -51,19 +51,19 @@ env: - PACKAGE='Three Triangulation Triangulation_2 ' - PACKAGE='Triangulation_3 Union_find Visibility_2 ' - PACKAGE='Voronoi_diagram_2 wininst ' -compiler: clang-3.6 +compiler: clang install: - echo "$PWD" - if [ -n "$TRAVIS_PULL_REQUEST" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi - bash .travis/install.sh - - export CXX=clang++-3.6 CC=clang-3.6; + - export CXX=clang++ CC=clang; before_script: - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe - sudo mv doxygen_exe /usr/bin/doxygen - sudo chmod +x /usr/bin/doxygen - mkdir -p build - cd build -- cmake -DCMAKE_CXX_FLAGS="-std=c++11" -DCGAL_HEADER_ONLY=ON -DQt5_DIR="/opt/qt55/lib/cmake/Qt5" -DQt5Svg_DIR="/opt/qt55/lib/cmake/Qt5Svg" -DQt5OpenGL_DIR="/opt/qt55/lib/cmake/Qt5OpenGL" -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. +- cmake -DCMAKE_CXX_FLAGS="-std=c++11" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. - make - sudo make install &>/dev/null - cd .. diff --git a/.travis/build_package.sh b/.travis/build_package.sh index c47cd822c21..66dc6802a05 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -45,7 +45,7 @@ function build_demo { QGLVIEWERROOT=$PWD/qglviewer export QGLVIEWERROOT fi - cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DQt5_DIR="/opt/qt55/lib/cmake/Qt5" -DQt5Svg_DIR="/opt/qt55/lib/cmake/Qt5Svg" -DQt5OpenGL_DIR="/opt/qt55/lib/cmake/Qt5OpenGL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. + cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. make -j2 } old_IFS=$IFS diff --git a/.travis/generate_travis.sh b/.travis/generate_travis.sh index 5e6c46889d4..63a5e1f3705 100755 --- a/.travis/generate_travis.sh +++ b/.travis/generate_travis.sh @@ -60,7 +60,7 @@ done COPY=0 for LINE in $(cat "$PWD/.travis/template.txt") do - if [ "$LINE" = "compiler: clang-3.6" ] + if [ "$LINE" = "compiler: clang" ] then COPY=1 fi diff --git a/.travis/install.sh b/.travis/install.sh index 4d78446fc74..11e94f59b1d 100644 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -2,23 +2,13 @@ [ -n "$CGAL_DEBUG_TRAVIS" ] && set -x DONE=0 +sudo apt-get update while [ $DONE = 0 ] do - DONE=1 && sudo -E apt-add-repository -y "ppa:ppsspp/cmake" || DONE=0 && sleep 5 -done -DONE=0 -while [ $DONE = 0 ] -do - DONE=1 && sudo -E apt-add-repository -y "ppa:hedges/qt5.5" || DONE=0 && sleep 5 -done - -DONE=0 -while [ $DONE = 0 ] -do - DONE=1 && sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install clang-3.6 zsh \ -flex bison cmake graphviz libgmp-dev libmpfr-dev libmpfi-dev zlib1g-dev libeigen3-dev libboost1.55-dev \ -libboost-system1.55-dev libboost-program-options1.55-dev libboost-thread1.55-dev libboost-iostreams1.55-dev \ -qt55base qt55script qt55svg qt55tools qt55graphicaleffects libopencv-dev mesa-common-dev libmetis-dev libglu1-mesa-dev \ + DONE=1 && sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install clang zsh \ +flex bison cmake graphviz libgmp-dev libmpfr-dev libmpfi-dev zlib1g-dev libeigen3-dev libboost-dev \ +libboost-system-dev libboost-program-options-dev libboost-thread-dev libboost-iostreams-dev \ +qtbase5-dev libqt5opengl5-dev qtscript5-dev libqt5svg5-dev qttools5-dev qttools5-dev-tools qml-module-qtgraphicaleffects libopencv-dev mesa-common-dev libmetis-dev libglu1-mesa-dev \ || DONE=0 && sudo apt-get update done exit 0 diff --git a/.travis/template.txt b/.travis/template.txt index 1632aa16cbf..97662bb5b89 100644 --- a/.travis/template.txt +++ b/.travis/template.txt @@ -1,5 +1,5 @@ language: cpp -dist: trusty +dist: xenial sudo: required git: depth: 3 @@ -7,19 +7,19 @@ env: matrix: PACKAGES_MATRIX -compiler: clang-3.6 +compiler: clang install: - echo "$PWD" - if [ -n "$TRAVIS_PULL_REQUEST" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi - bash .travis/install.sh - - export CXX=clang++-3.6 CC=clang-3.6; + - export CXX=clang++ CC=clang; before_script: - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe - sudo mv doxygen_exe /usr/bin/doxygen - sudo chmod +x /usr/bin/doxygen - mkdir -p build - cd build -- cmake -DCMAKE_CXX_FLAGS="-std=c++11" -DCGAL_HEADER_ONLY=ON -DQt5_DIR="/opt/qt55/lib/cmake/Qt5" -DQt5Svg_DIR="/opt/qt55/lib/cmake/Qt5Svg" -DQt5OpenGL_DIR="/opt/qt55/lib/cmake/Qt5OpenGL" -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. +- cmake -DCMAKE_CXX_FLAGS="-std=c++11" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. - make - sudo make install &>/dev/null - cd .. From 73a22a8655433e3c3c8108141f376a235ff24ad9 Mon Sep 17 00:00:00 2001 From: Maxime GIMENO Date: Tue, 12 Feb 2019 12:06:29 +0100 Subject: [PATCH 186/186] Remove QGLViewer from travis (#3676) --- .travis/build_package.sh | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 66dc6802a05..adfc3bda083 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -18,40 +18,18 @@ function build_tests { function build_demo { mkdir -p build-travis cd build-travis - if [ $NEED_3D = 1 ]; then - #install libqglviewer - git clone --depth=4 -b v2.6.3 --single-branch https://github.com/GillesDebunne/libQGLViewer.git ./qglviewer - pushd ./qglviewer/QGLViewer - #use qt5 instead of qt4 -# export QT_SELECT=5 - qmake NO_QT_VERSION_SUFFIX=yes - make -j2 - if [ ! -f libQGLViewer.so ]; then - echo "libQGLViewer.so not made" - exit 1 - else - echo "QGLViewer built successfully" - fi - #end install qglviewer - popd - fi EXTRA_CXX_FLAGS= case "$CC" in clang*) EXTRA_CXX_FLAGS="-Werror=inconsistent-missing-override" ;; esac - if [ $NEED_3D = 1 ]; then - QGLVIEWERROOT=$PWD/qglviewer - export QGLVIEWERROOT - fi cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. make -j2 } old_IFS=$IFS IFS=$' ' ROOT="$PWD/.." -NEED_3D=0 for ARG in $(echo "$@") do #skip package maintenance @@ -146,12 +124,6 @@ cd $ROOT EXAMPLES="$ARG/examples/$ARG" TEST="$ARG/test/$ARG" DEMOS=$ROOT/$ARG/demo/* - if [ "$ARG" = AABB_tree ] || [ "$ARG" = Alpha_shapes_3 ] ||\ - [ "$ARG" = Circular_kernel_3 ] || [ "$ARG" = Linear_cell_complex ] ||\ - [ "$ARG" = Periodic_3_triangulation_3 ] || [ "$ARG" = Principal_component_analysis ] ||\ - [ "$ARG" = Surface_mesher ] || [ "$ARG" = Triangulation_3 ]; then - NEED_3D=1 - fi if [ -d "$ROOT/$EXAMPLES" ] then @@ -206,10 +178,9 @@ cd $ROOT done if [ "$ARG" = Polyhedron_demo ]; then DEMO=Polyhedron/demo/Polyhedron - NEED_3D=1 cd "$ROOT/$DEMO" build_demo - fi + fi done IFS=$old_IFS # Local Variables: