diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt index c2770c83aec..baa5f345435 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt @@ -6,10 +6,13 @@ include( polyhedron_demo_macros ) polyhedron_demo_plugin(point_set_from_vertices_plugin Point_set_from_vertices_plugin) target_link_libraries(point_set_from_vertices_plugin PUBLIC scene_surface_mesh_item scene_polygon_soup_item scene_points_with_normal_item) - if( METIS_FOUND ) + polyhedron_demo_plugin(diff_between_meshes_plugin Diff_between_meshes_plugin) + target_link_libraries(diff_between_meshes_plugin PUBLIC scene_surface_mesh_item) + + if( METIS_FOUND ) qt5_wrap_ui( partitionUI_FILES PartitionDialog.ui ) - polyhedron_demo_plugin(partition_plugin Partition_graph_plugin ${partitionUI_FILES}) - target_link_libraries(partition_plugin PUBLIC scene_surface_mesh_item ${METIS_LIBRARIES} ) + polyhedron_demo_plugin(partition_plugin Partition_graph_plugin ${partitionUI_FILES}) + target_link_libraries(partition_plugin PUBLIC scene_surface_mesh_item ${METIS_LIBRARIES} ) else() message("NOTICE : the Partition plugin needs METIS libraries and will not be compiled.") endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp new file mode 100644 index 00000000000..f70305e6e09 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include + +#include "Scene_surface_mesh_item.h" + +#include + +#include +#include +#include +#include "Messages_interface.h" + +using namespace CGAL::Three; +class Polyhedron_demo_diff_between_meshes_plugin : + public QObject, + public Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") + +public: + void init(QMainWindow* mainWindow, + CGAL::Three::Scene_interface* scene_interface, Messages_interface*); + + bool applicable(QAction*) const { + if(scene->selectionIndices().size() != 2) + return false; + for(int id : scene->selectionIndices()) + { + if(!qobject_cast(scene->item(id))) + { + return false; + } + } + return true; + } + + QList actions() const; + +public Q_SLOTS: + void diff(); + +private: + CGAL::Three::Scene_interface* scene; + QAction* actionDiff; + SMesh* diff(SMesh* m1, SMesh* m2, bool compute_common= false); + +}; // end Polyhedron_demo_diff_between_meshes_plugin + +void Polyhedron_demo_diff_between_meshes_plugin::init(QMainWindow* mainWindow, + CGAL::Three::Scene_interface* scene_interface, + Messages_interface*) +{ + scene = scene_interface; + actionDiff = new QAction(tr("&Differences between Meshes"), mainWindow); + actionDiff->setObjectName("actionDiff"); + connect(actionDiff, SIGNAL(triggered()), + this, SLOT(diff())); +} + +QList Polyhedron_demo_diff_between_meshes_plugin::actions() const { + return QList() << actionDiff; +} +SMesh* Polyhedron_demo_diff_between_meshes_plugin::diff(SMesh* m1, SMesh* m2, bool compute_common) +{ + //Collect points of both meshes in separate sets to easily detect if a point is + // contained by a mesh or not. +std::set m2_verts; + for(auto v : m2->vertices()) + { + m2_verts.insert(m2->point(v)); + } + + //Get Vertices that are in m1 but not in m2 + std::vector m1_points; + + std::map id_map; + std::size_t id = 0; + std::vector m1_faces; + + // parse faces of m1. Select each face that has at least one point that is not + // in m2. Fill a points vector with them. + for(auto f : m1->faces()) + { + bool take = false; + for(auto v : CGAL::vertices_around_face(halfedge(f, *m1), *m1)) + { + if(m2_verts.find(m1->point(v)) == m2_verts.end()) + { + take = true; + break; + } + } + if(take ^ compute_common) //XOR + { + m1_faces.push_back(f); + for(auto v : CGAL::vertices_around_face(halfedge(f, *m1), *m1)) + { + if(id_map.find(v) == id_map.end()) + { + m1_points.push_back(m1->point(v)); + id_map[v] = id++; + } + } + } + } + + //iterate m1_faces and fill a polygon vector using the id_map previously filled. + std::vector > polygons(m1_faces.size()); + id = 0; + for(auto f : m1_faces) + { + for(auto v : vertices_around_face(halfedge(f, *m1),*m1)) + { + polygons[id].push_back(id_map[v]); + } + ++id; + } + + SMesh* m1_over_m2 = new SMesh(); + CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh( + m1_points, polygons, *m1_over_m2); + return m1_over_m2; +} + +void Polyhedron_demo_diff_between_meshes_plugin::diff() +{ + + QCursor c(Qt::WaitCursor); + CGAL::Three::Three::CursorScopeGuard guard(c); + + //Get the two meshes. No need to check their existance, applicable() + //is not permissive enough to let it crash. + Scene_surface_mesh_item* m1_item = qobject_cast( + scene->item(scene->selectionIndices().front())), + *m2_item = qobject_cast( + scene->item(scene->selectionIndices().back())); + + SMesh* m1=m1_item->face_graph(), + *m2=m2_item->face_graph(); + + + SMesh* m1_over_m2 = diff(m1, m2); + SMesh* m2_over_m1 = diff(m2, m1); + SMesh* common = diff(m2, m1, true); + + Scene_surface_mesh_item* m1_over_m2_item = new Scene_surface_mesh_item(m1_over_m2); + m1_over_m2_item->setColor(QColor(Qt::blue)); + m1_over_m2_item->setName(QString("%1 - %2").arg(m1_item->name()).arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(m1_over_m2_item); + Scene_surface_mesh_item* m2_over_m1_item = new Scene_surface_mesh_item(m2_over_m1); + m2_over_m1_item->setColor(QColor(Qt::red)); + m2_over_m1_item->setName(QString("%2 - %1").arg(m1_item->name()).arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(m2_over_m1_item); + Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common); + common_item->setColor(QColor(Qt::green)); + CGAL::Three::Three::scene()->addItem(common_item); + common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); + + Scene_group_item* group = new Scene_group_item(); + group->setName("Diff result"); + CGAL::Three::Three::scene()->addItem(group); + CGAL::Three::Three::scene()->changeGroup(m1_over_m2_item, group); + CGAL::Three::Three::scene()->changeGroup(m2_over_m1_item, group); + CGAL::Three::Three::scene()->changeGroup(common_item, group); + + m1_item->setVisible(false); + m2_item->setVisible(false); + +} + + +#include "Diff_between_meshes_plugin.moc"