diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 07d1880da35..54cfde41e68 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -151,6 +151,9 @@ MainWindow::MainWindow(QWidget* parent) QShortcut* shortcut = new QShortcut(QKeySequence(Qt::ALT+Qt::Key_Q), this); connect(shortcut, SIGNAL(activated()), this, SLOT(setFocusToQuickSearch())); + shortcut = new QShortcut(QKeySequence(Qt::Key_F5), this); + connect(shortcut, SIGNAL(activated()), + this, SLOT(reloadItem())); } proxyModel = new QSortFilterProxyModel(this); @@ -888,44 +891,36 @@ void MainWindow::updateViewerBBox(bool recenter = true) } void MainWindow::reloadItem() { - QAction* sender_action = qobject_cast(sender()); - if(!sender_action) return; - Scene_item* item = (Scene_item*)sender_action->data().value(); - if(!item) { - std::cerr << "Cannot reload item: " - << "the reload action has not item attached\n"; - return; + Scene_item* item = NULL; + + Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) + { + item = scene->item(id); + QString filename = item->property("source filename").toString(); + QString loader_name = item->property("loader_name").toString(); + if(filename.isEmpty() || loader_name.isEmpty()) { + this->warning(QString("Cannot reload item %1: " + "the item has no \"source filename\" or no \"loader_name\" attached\n").arg(item->name())); + continue; + } + + CGAL::Three::Polyhedron_demo_io_plugin_interface* fileloader = findLoader(loader_name); + QFileInfo fileinfo(filename); + + CGAL::Three::Scene_item* new_item = loadItem(fileinfo, fileloader); + + new_item->setName(item->name()); + new_item->setColor(item->color()); + new_item->setRenderingMode(item->renderingMode()); + new_item->setVisible(item->visible()); + Scene_item_with_properties *property_item = dynamic_cast(new_item); + if(property_item) + property_item->copyProperties(item); + scene->replaceItem(scene->item_id(item), new_item, true); + new_item->invalidateOpenGLBuffers(); + item->deleteLater(); } - if(!item) { - std::cerr << "Cannot reload item: " - << "the reload action has a QObject* pointer attached\n" - << "that is not a Scene_item*\n"; - return; - } - QString filename = item->property("source filename").toString(); - QString loader_name = item->property("loader_name").toString(); - if(filename.isEmpty() || loader_name.isEmpty()) { - std::cerr << "Cannot reload item: " - << "the item has no \"source filename\" or no \"loader_name\" attached\n"; - return; - } - - CGAL::Three::Polyhedron_demo_io_plugin_interface* fileloader = findLoader(loader_name); - QFileInfo fileinfo(filename); - - CGAL::Three::Scene_item* new_item = loadItem(fileinfo, fileloader); - - new_item->setName(item->name()); - new_item->setColor(item->color()); - new_item->setRenderingMode(item->renderingMode()); - new_item->setVisible(item->visible()); - Scene_item_with_properties *property_item = dynamic_cast(new_item); - if(property_item) - property_item->copyProperties(item); - scene->replaceItem(scene->item_id(item), new_item, true); - new_item->invalidateOpenGLBuffers(); - item->deleteLater(); } CGAL::Three::Polyhedron_demo_io_plugin_interface* MainWindow::findLoader(const QString& loader_name) const { @@ -1280,7 +1275,7 @@ void MainWindow::showSceneContextMenu(int selectedItemIndex, menu->addSeparator(); if(!item->property("source filename").toString().isEmpty()) { QAction* reload = menu->addAction(tr("&Reload Item from File")); - reload->setData(qVariantFromValue((void*)item)); + reload->setProperty("is_groupable", true); connect(reload, SIGNAL(triggered()), this, SLOT(reloadItem())); } @@ -1304,8 +1299,8 @@ void MainWindow::showSceneContextMenu(int selectedItemIndex, void MainWindow::showSceneContextMenu(const QPoint& p) { QWidget* sender = qobject_cast(this->sender()); if(!sender) return; + int main_index = scene->selectionIndices().first(); - int index = -1; if(sender == sceneView) { QModelIndex modelIndex = sceneView->indexAt(p); if(!modelIndex.isValid()) @@ -1323,17 +1318,48 @@ void MainWindow::showSceneContextMenu(const QPoint& p) { menu->exec(sender->mapToGlobal(p)); return; } - else + else if(scene->selectionIndices().size() > 1 ) { - index = scene->getIdFromModelIndex(proxyModel->mapToSource(modelIndex)); - scene->setSelectedItemIndex(index); + QMap menu_actions; + Q_FOREACH(QAction* action, scene->item(main_index)->contextMenu()->actions()) + { + if(action->property("is_groupable").toBool()) + menu_actions[action->text()] = action; + } + Q_FOREACH(Scene::Item_id index, scene->selectionIndices()) + { + if(index == main_index) + continue; + + CGAL::Three::Scene_item* item = scene->item(index); + if(!item) + continue; + QVector action_names; + Q_FOREACH(QAction* action, item->contextMenu()->actions()) + { + action_names.push_back(action->text()); + } + } + QMenu menu; + Q_FOREACH(QString name, menu_actions.keys()) + { + QAction* action = menu.addAction(name); + connect(action, &QAction::triggered, this, &MainWindow::propagate_action); + } + + 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())); + menu.exec(sender->mapToGlobal(p)); + return; } } - else { - index = scene->mainSelectionIndex(); - } - - showSceneContextMenu(index, sender->mapToGlobal(p)); + showSceneContextMenu(main_index, sender->mapToGlobal(p)); + return; } void MainWindow::removeManipulatedFrame(CGAL::Three::Scene_item* item) @@ -1547,56 +1573,68 @@ void MainWindow::on_actionLoad_triggered() void MainWindow::on_actionSaveAs_triggered() { Scene_item* item = NULL; - QAction* sender_action = qobject_cast(sender()); - if(sender_action && !sender_action->data().isNull()) { - item = (Scene_item*)sender_action->data().value(); - } - if(!item) + Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) { - item = scene->item(scene->mainSelectionIndex()); - } - if(!item) - return; - - QVector canSavePlugins; - QStringList filters; - Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin, io_plugins) { - if(plugin->canSave(item)) { - canSavePlugins << plugin; - filters += plugin->saveNameFilters(); + item = scene->item(id); + QVector canSavePlugins; + QStringList filters; + Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin, io_plugins) { + if(plugin->canSave(item)) { + canSavePlugins << plugin; + filters += plugin->saveNameFilters(); + } } - } - QString ext; - if(!filters.isEmpty()) - { + QString ext1, ext2; QRegExp extensions("\\(\\*\\..+\\)"); - extensions.indexIn(filters.first().split(";;").first()); - ext = extensions.cap(); + QStringList filter_ext; + Q_FOREACH(QString s, filters.first().split(";;")) + { + int pos = extensions.indexIn(s); + if( pos >-1) + filter_ext.append(extensions.capturedTexts()); + } filters << tr("All files (*)"); - } - if(canSavePlugins.isEmpty()) { - QMessageBox::warning(this, - tr("Cannot save"), - tr("The selected object %1 cannot be saved.") - .arg(item->name())); - return; - } - QString caption = tr("Save %1 to File...%2").arg(item->name()).arg(ext); - //remove `)` - ext.chop(1); - //remove `(*.` - ext = ext.right(ext.size()-3); - QString filename = - QFileDialog::getSaveFileName(this, - caption, - QString("%1.%2").arg(item->name()).arg(ext), - filters.join(";;")); - if(filename.isEmpty()) - return; + if(canSavePlugins.isEmpty()) { + QMessageBox::warning(this, + tr("Cannot save"), + tr("The selected object %1 cannot be saved.") + .arg(item->name())); + continue; + } + QString caption = tr("Save %1 to File...").arg(item->name()); + QString sf; + QString filename = + QFileDialog::getSaveFileName(this, + caption, + QString("%1").arg(item->name()), + filters.join(";;"), + &sf); + extensions.indexIn(sf.split(";;").first()); + ext1 = extensions.cap(); + //remove `)` + ext1.chop(1); + //remove `(*` + ext1 = ext1.right(ext1.size()-2); + if(filename.isEmpty()) + continue; - viewer->update(); - save(filename, item); + ext2 = filename.split(".").last(); + QStringList final_extensions; + Q_FOREACH(QString s, filter_ext) + { + //remove `)` + s.chop(1); + //remove `(*.` + final_extensions.append(s.right(s.size()-3)); + } + if(!final_extensions.contains(ext2)) + { + filename = filename.append(ext1); + } + viewer->update(); + save(filename, item); + } } void MainWindow::save(QString filename, CGAL::Three::Scene_item* item) { @@ -2118,3 +2156,22 @@ void MainWindow::exportStatistics() outStream << str; output.close(); } + +void MainWindow::propagate_action() +{ + QAction* sender = qobject_cast(this->sender()); + if(!sender) return; + QString name = sender->text(); + Q_FOREACH(Scene::Item_id id, scene->selectionIndices()) + { + Scene_item* item = scene->item(id); + Q_FOREACH(QAction* action, item->contextMenu()->actions()) + { + if(action->text() == name) + { + action->trigger(); + break; + } + } + } +} diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index cb91014cc56..dbf92ec601f 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -354,6 +354,8 @@ protected Q_SLOTS: void on_actionRecenterScene_triggered(); //!Resizes the header of the scene view void resetHeader(); + //!apply an action named `name` to all selected items + void propagate_action(); protected: QList createSubMenus(QList); /*! For each objects in the Geometric Objects view, loads the associated plugins. diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp index e112da19b4c..54a111dbb88 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp @@ -146,6 +146,7 @@ Polyhedron_demo_off_plugin::load_obj(QFileInfo fileinfo) { std::move(faces), *(poly_item->polyhedron())); item = poly_item; + item->invalidateOpenGLBuffers(); } else { Scene_polygon_soup_item* polygon_soup_item = new Scene_polygon_soup_item(); polygon_soup_item->load(std::move(points), std::move(faces)); 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 a4961ed2855..52561c7a577 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surface_mesh_io_plugin.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include "Scene_surface_mesh_item.h" #include "Scene_polygon_soup_item.h" @@ -35,7 +37,9 @@ public: return QList(); } QString name() const { return "surface_mesh_io_plugin"; } - QString nameFilters() const { return "OFF files to Surface_mesh (*.off);;Wavefront Surface_mesh OBJ (*.obj)"; } + QString loadNameFilters() const { return "OFF files to Surface_mesh (*.off);;Wavefront Surface_mesh OBJ (*.obj)"; } + QString saveNameFilters() const { return "OFF files (*.off);;Wavefront OBJ (*.obj)"; } + QString nameFilters() const { return QString(); } bool canLoad() const { return true; } CGAL::Three::Scene_item* load(QFileInfo fileinfo) { if(fileinfo.suffix().toLower() == "off") @@ -68,6 +72,24 @@ public: } Scene_surface_mesh_item* item = new Scene_surface_mesh_item(surface_mesh); item->setName(fileinfo.completeBaseName()); + std::size_t isolated_v = 0; + BOOST_FOREACH(vertex_descriptor v, vertices(*surface_mesh)) + { + if(surface_mesh->is_isolated(v)) + { + ++isolated_v; + } + } + if(isolated_v >0) + { + item->setNbIsolatedvertices(isolated_v); + //needs two restore, it's not a typo + QApplication::restoreOverrideCursor(); + QMessageBox::warning((QWidget*)NULL, + tr("Isolated vertices"), + tr("%1 isolated vertices found") + .arg(item->getNbIsolatedvertices())); + } return item; } else if(fileinfo.suffix().toLower() == "obj") @@ -86,8 +108,8 @@ public: return 0; } - bool canSave(const CGAL::Three::Scene_item* ) { - return true; + bool canSave(const CGAL::Three::Scene_item* item) { + return qobject_cast(item) != 0; } bool save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp index 1df8a8f2b6f..88ee9889a1b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp @@ -195,16 +195,36 @@ public: lastMatrix.setToIdentity(); mw = _mw; this->scene = scene_interface; - actionTransformPolyhedron = new QAction("Affine Transformation", mw); + + + actionTransformPolyhedron = new QAction( + #ifdef CGAL_USE_SURFACE_MESH + tr("Affine Transformation for Surface Mesh") + #else + tr("Affine Transformation for Polyhedron") + #endif + , mw); if(actionTransformPolyhedron) { connect(actionTransformPolyhedron, SIGNAL(triggered()),this, SLOT(go())); } transform_item = NULL; transform_points_item = NULL; - dock_widget = new QDockWidget(mw); + dock_widget = new QDockWidget( + #ifdef CGAL_USE_SURFACE_MESH + tr("Affine Transformation for Surface Mesh") + #else + tr("Affine Transformation for Polyhedron") + #endif + , mw); ui.setupUi(dock_widget); - + dock_widget->setWindowTitle(tr( + #ifdef CGAL_USE_SURFACE_MESH + "Affine Transformation for Surface Mesh" + #else + "Affine Transformation for Polyhedron" + #endif + )); addDockWidget(dock_widget); dock_widget->hide(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Clipping_box_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Clipping_box_plugin.cpp index 618fe29f454..d1b7e6f5e7e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Clipping_box_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Clipping_box_plugin.cpp @@ -88,6 +88,12 @@ dock_widget->show(); item = new Scene_edit_box_item(scene); connect(item, SIGNAL(destroyed()), this, SLOT(enableAction())); + connect(item, &Scene_edit_box_item::aboutToBeDestroyed, + this, [this]() + { + clip(false); + dock_widget->pushButton->setChecked(false); + }); item->setName("Clipping box"); item->setRenderingMode(FlatPlusEdges); QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_bbox_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_bbox_mesh_plugin.cpp index 4d1a7471140..3aba3fbb967 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_bbox_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_bbox_mesh_plugin.cpp @@ -27,7 +27,8 @@ public: void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*); QList actions() const; bool applicable(QAction*) const { - if(scene->mainSelectionIndex() != -1) + if(scene->mainSelectionIndex() != -1 + && scene->item(scene->mainSelectionIndex())->isFinite()) return true; return false;} 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 00c09a184c8..7b743eb31b2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp @@ -995,6 +995,8 @@ void Scene_edit_box_item_priv::reset_selection() //intercept events for picking bool Scene_edit_box_item::eventFilter(QObject *obj, QEvent *event) { + if(!visible()) + return false; QGLViewer* viewer = qobject_cast(obj); if(!viewer) return false; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp index 5e8194089e3..1f4b212c807 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp @@ -57,16 +57,35 @@ public: mw = mainWindow; scene = scene_interface; messages = m; - actionFairing = new QAction(tr("Refinement and Fairing"), mw); + actionFairing = new QAction(tr( + #ifdef USE_SURFACE_MESH + "Refinement and Fairing for Surface Mesh" + #else + "Refinement and Fairing for Polyhedron" + #endif + ), mw); actionFairing->setProperty("subMenuName", "Polygon Mesh Processing"); connect(actionFairing, SIGNAL(triggered()), this, SLOT(fairing_action())); - dock_widget = new QDockWidget("Refinement and Fairing", mw); + dock_widget = new QDockWidget( + #ifdef USE_SURFACE_MESH + "Refinement and Fairing for Surface Mesh" + #else + "Refinement and Fairing for Polyhedron" + #endif + , mw); dock_widget->setVisible(false); ui_widget.setupUi(dock_widget); addDockWidget(dock_widget); + dock_widget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "Fairing for Surface Mesh" + #else + "Fairing for Polyhedron" + #endif + )); connect(ui_widget.Fair_button, SIGNAL(clicked()), this, SLOT(on_Fair_button_clicked())); connect(ui_widget.Refine_button, SIGNAL(clicked()), this, SLOT(on_Refine_button_clicked())); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp index 3af8ea7ce2f..e7a5e8dff1a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp @@ -435,11 +435,23 @@ void Polyhedron_demo_hole_filling_plugin::init(QMainWindow* mainWindow, scene = scene_interface; messages = m; - actionHoleFilling = new QAction(tr("Hole Filling"), mw); + actionHoleFilling = new QAction(tr( + #ifdef USE_SURFACE_MESH + "Hole Filling for Surface Mesh" + #else + "Hole Filling for Polyhedron" + #endif + ), mw); actionHoleFilling->setProperty("subMenuName", "Polygon Mesh Processing"); connect(actionHoleFilling, SIGNAL(triggered()), this, SLOT(hole_filling_action())); - dock_widget = new QDockWidget("Hole Filling", mw); + dock_widget = new QDockWidget( + #ifdef USE_SURFACE_MESH + "Hole Filling for Surface Mesh" + #else + "Hole Filling for Polyhedron" + #endif + , mw); dock_widget->setVisible(false); dock_widget->installEventFilter(this); @@ -448,6 +460,13 @@ void Polyhedron_demo_hole_filling_plugin::init(QMainWindow* mainWindow, ui_widget.Reject_button->setVisible(false); addDockWidget(dock_widget); + dock_widget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "Hole Filling for Surface Mesh" + #else + "Hole Filling for Polyhedron" + #endif + )); connect(ui_widget.Fill_from_selection_button, SIGNAL(clicked()), this, SLOT(on_Fill_from_selection_button())); connect(ui_widget.Visualize_holes_button, SIGNAL(clicked()), this, SLOT(on_Visualize_holes_button())); 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 f1b49b47b2f..e0b0f6e36cb 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 @@ -118,7 +118,13 @@ public: dockWidget = NULL; ui = NULL; - actionMCFSkeleton = new QAction(tr("Mean Curvature Skeleton (Advanced)"), mainWindow); + actionMCFSkeleton = new QAction(tr( + #ifdef USE_SURFACE_MESH + "Mean Curvature Skeleton (Advanced) for Surface Mesh" + #else + "Mean Curvature Skeleton (Advanced) for Polyhedron" + #endif + ), mainWindow); actionMCFSkeleton->setProperty("subMenuName", "Triangulated Surface Mesh Skeletonization"); actionMCFSkeleton->setObjectName("actionMCFSkeleton"); @@ -126,14 +132,26 @@ public: actionConvert_to_medial_skeleton->setProperty("subMenuName", "Triangulated Surface Mesh Skeletonization"); actionConvert_to_medial_skeleton->setObjectName("actionConvert_to_medial_skeleton"); - dockWidget = new QDockWidget(mw); + dockWidget = new QDockWidget(tr( + #ifdef USE_SURFACE_MESH + "Mean Curvature Skeleton for Surface Mesh" + #else + "Mean Curvature Skeleton for Polyhedron" + #endif + ),mw); dockWidget->setVisible(false); ui = new Ui::Mean_curvature_flow_skeleton_plugin(); ui->setupUi(dockWidget); dockWidget->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); - dockWidget->setWindowTitle("Mean Curvature Flow Skeleton"); + dockWidget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "Mean Curvature Skeleton for Surface Mesh" + #else + "Mean Curvature Skeleton for Polyhedron" + #endif + )); addDockWidget(dockWidget); connect(ui->pushButton_contract, SIGNAL(clicked()), 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 335777f6303..f299fcbeb1b 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 @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "opengl_tools.h" #include "Messages_interface.h" @@ -22,6 +24,7 @@ #include #include #include +#include #include #include @@ -225,10 +228,18 @@ public: connect(ui_widget.box, SIGNAL(toggled(bool)), this, SLOT(on_box_toggled(bool))); + connect(ui_widget.helpButton, &QAbstractButton::clicked, + [this](){ + QMessageBox::information(dock_widget, QString("Help"), + QString("SHIFT + Left Click : selection\n" + "CONTROL + Left Click : print coordinates of point under cursor.")); + } + ); visualizer = NULL; edit_box = NULL; shift_pressing = false; + ctrl_pressing = false; QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin(); viewer->installEventFilter(this); @@ -260,6 +271,7 @@ protected: Qt::KeyboardModifiers modifiers = keyEvent->modifiers(); shift_pressing = modifiers.testFlag(Qt::ShiftModifier); + ctrl_pressing = modifiers.testFlag(Qt::ControlModifier); #if QGLVIEWER_VERSION >= 0x020700 background = static_cast(*QGLViewer::QGLViewerPool().begin())->grabFramebuffer(); #else @@ -310,7 +322,32 @@ protected: visualizer->sample_mouse_path(background); return true; } + //Position request + else if(ctrl_pressing && event->type() == QEvent::MouseButtonPress) + { + QMouseEvent* m_e = static_cast(event); + Scene_points_with_normal_item* item = + qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!item) + return false; + QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin(); + bool found = false; + QPoint pixel(m_e->pos().x(), + viewer->camera()->screenHeight()-1-m_e->pos().y()); + qglviewer::Vec point = viewer->camera()->pointUnderPixel(m_e->pos(), + found); + if(!found) + return false; + typedef Kernel::Point_3 Point; + typedef CGAL::Search_traits_3 TreeTraits; + typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; + typedef Neighbor_search::Tree Tree; + Tree tree(item->point_set()->points().begin(), item->point_set()->points().end()); + 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())); + } return false; } @@ -563,6 +600,7 @@ public Q_SLOTS: } + void reset_editbox() { edit_box = NULL; @@ -578,6 +616,7 @@ private: Ui::PointSetSelection ui_widget; Scene_point_set_selection_visualizer* visualizer; bool shift_pressing; + bool ctrl_pressing; Scene_edit_box_item* edit_box; }; // end Polyhedron_demo_point_set_selection_plugin diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_widget.ui index 04680455563..a928273065f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_widget.ui @@ -6,8 +6,8 @@ 0 0 - 389 - 101 + 514 + 281 @@ -254,6 +254,26 @@ + + + + + + + + :/cgal/icons/resources/help_button.png:/cgal/icons/resources/help_button.png + + + + 16 + 16 + + + + false + + + @@ -287,6 +307,9 @@ + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index ca2f0dfdbd0..afce55e99f6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -385,9 +385,27 @@ public: autoConnectActions(); Q_FOREACH(QAction *action, _actions) action->setProperty("subMenuName", - "Triangulated Surface Mesh Parameterization"); - dock_widget = new QDockWidget("UVMapping", mw); + #ifdef USE_SURFACE_MESH + "Triangulated Surface Mesh Parameterization" + #else + "Triangulated Surface Mesh Parameterization for Polyhedron" + #endif + ); + dock_widget = new QDockWidget( + #ifdef USE_SURFACE_MESH + "UVMapping for Surface Mesh" + #else + "UVMapping for Polyhedron" + #endif + , mw); ui_widget.setupUi(dock_widget); + dock_widget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "UVMapping for Surface Mesh" + #else + "UVMapping for Polyhedron" + #endif + )); graphics_scene = new QGraphicsScene(dock_widget); ui_widget.graphicsView->setScene(graphics_scene); ui_widget.graphicsView->setRenderHints(QPainter::Antialiasing); 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 003a08c4c0b..8ecc9053a6b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Shortest_path_plugin.cpp @@ -89,17 +89,36 @@ public: this->mw = mainWindow; this->m_messages = messages; - dock_widget = new QDockWidget("Shortest path", mw); + dock_widget = new QDockWidget( + #ifdef USE_SURFACE_MESH + "Shortest Path for Surface Mesh" + #else + "Shortest Path for Polyhedron" + #endif + , mw); dock_widget->setVisible(false); ui_widget.setupUi(dock_widget); + dock_widget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "Shortest Path for Surface Mesh" + #else + "Shortest Path for Polyhedron" + #endif + )); addDockWidget(dock_widget); connect(ui_widget.Selection_type_combo_box, SIGNAL(currentIndexChanged(int)), this, SLOT(on_Selection_type_combo_box_changed(int))); connect(ui_widget.Primitives_type_combo_box, SIGNAL(currentIndexChanged(int)), this, SLOT(on_Primitives_type_combo_box_changed(int))); - actionMakeShortestPaths = new QAction("Make Shortest Path", this->mw); + actionMakeShortestPaths = new QAction( + #ifdef USE_SURFACE_MESH + "Make Shortest Path for Surface Mesh" + #else + "Make Shortest Path for Polyhedron" + #endif + , this->mw); actionMakeShortestPaths->setProperty("subMenuName", "Triangulated Surface Mesh Shortest Paths"); actionMakeShortestPaths->setObjectName("actionMakeShortestPaths"); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Edit_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Edit_polyhedron_plugin.cpp index 8493ea9ed47..854b6b56f10 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Edit_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Edit_polyhedron_plugin.cpp @@ -126,7 +126,13 @@ void Polyhedron_demo_edit_polyhedron_plugin::init(QMainWindow* mainWindow, CGAL: { mw = mainWindow; scene = scene_interface; - actionDeformation = new QAction("Surface Mesh Deformation", mw); + actionDeformation = new QAction( + #ifdef USE_SURFACE_MESH + "Surface Mesh Deformation" + #else + " Polyhedron Deformation" + #endif + , mw); actionDeformation->setProperty("subMenuName", "Triangulated Surface Mesh Deformation"); actionDeformation->setObjectName("actionDeformation"); actionDeformation->setShortcutContext(Qt::ApplicationShortcut); @@ -140,10 +146,24 @@ void Polyhedron_demo_edit_polyhedron_plugin::init(QMainWindow* mainWindow, CGAL: ////////////////// Construct widget ///////////////////////////// // First time, construct docking window - dock_widget = new QDockWidget("Mesh Deformation", mw); + dock_widget = new QDockWidget( + #ifdef USE_SURFACE_MESH + "Surface Mesh Deformation" + #else + " Polyhedron Deformation" + #endif + , mw); dock_widget->setVisible(false); // do not show at the beginning ui_widget.setupUi(dock_widget); + dock_widget->setWindowTitle(tr( + #ifdef USE_SURFACE_MESH + "Surface Mesh Deformation" + #else + " Polyhedron Deformation" + #endif + )); + mw->addDockWidget(Qt::LeftDockWidgetArea, dock_widget); connect(ui_widget.AddCtrlVertPushButton, SIGNAL(clicked()), this, SLOT(on_AddCtrlVertPushButton_clicked())); diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc index ca73b090935..1f8e93f2977 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc +++ b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc @@ -29,6 +29,7 @@ resources/pss_union.png resources/pss_inter.png resources/pss_diff.png + resources/help_button.png resources/about.html diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 279b8f4f981..1b1b7970b7b 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -217,6 +217,15 @@ Scene::erase(QList indices) && item->parentGroup()->isChildLocked(item)) if(!indices.contains(item_id(item->parentGroup()))) continue; + Scene_group_item* group = qobject_cast(item); + if(group) + { + Q_FOREACH(Scene_item* child, group->getChildren()) + { + if(!to_be_removed.contains(child)) + to_be_removed.push_back(child); + } + } if(!to_be_removed.contains(item)) to_be_removed.push_back(item); } @@ -781,6 +790,10 @@ Scene::setData(const QModelIndex &index, return true; break; case ColorColumn: + if(!selectionIndices().empty()) + Q_FOREACH(Item_id item_index, selectionIndices()) + this->item(item_index)->setColor(value.value()); + else item->setColor(value.value()); Q_EMIT dataChanged(index, index); return true; diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index ea399e3ce66..e889bcf4403 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -191,7 +191,7 @@ public Q_SLOTS: if(group) { QList list; - Q_FOREACH(CGAL::Three::Scene_item* child, group->getChildren()) + Q_FOREACH(CGAL::Three::Scene_item* child, group->getChildrenForSelection()) list< *p_vertices, std::vector *p_normals, @@ -298,7 +299,6 @@ struct Scene_c3t3_item_priv { tree.clear(); if(frame) { - static_cast(QGLViewer::QGLViewerPool().first())->setManipulatedFrame(0); delete frame; frame = NULL; delete tet_Slider; @@ -317,7 +317,7 @@ struct Scene_c3t3_item_priv { intersection = NULL; spheres_are_shown = false; cnc_are_shown = false; - show_tetrahedra = false; + show_tetrahedra = true; is_aabb_tree_built = false; are_intersection_buffers_filled = false; is_grid_shown = true; @@ -915,6 +915,7 @@ void Scene_c3t3_item::draw(CGAL::Three::Viewer_interface* viewer) const { vaos[Scene_c3t3_item_priv::Facets]->release(); if(d->show_tetrahedra){ + ncthis->show_intersection(true); if(!d->frame->isManipulated()) d->intersection->setFast(false); else @@ -925,6 +926,7 @@ void Scene_c3t3_item::draw(CGAL::Three::Viewer_interface* viewer) const { ncthis->d->computeIntersections(); d->intersection->initialize_buffers(viewer); d->are_intersection_buffers_filled = true; + ncthis->show_intersection(true); } } @@ -1829,7 +1831,7 @@ bool Scene_c3t3_item::keyPressEvent(QKeyEvent *event) d->tet_Slider->setValue(d->tet_Slider->value() -5); itemChanged(); } - return true; + return false; } QString Scene_c3t3_item::computeStats(int type) diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h index 7b7cc8f1710..dde7f7a76bc 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h @@ -118,6 +118,8 @@ public: void draw(CGAL::Three::Viewer_interface* viewer) const Q_DECL_OVERRIDE; void drawEdges(CGAL::Three::Viewer_interface* viewer) const Q_DECL_OVERRIDE; void drawPoints(CGAL::Three::Viewer_interface * viewer) const Q_DECL_OVERRIDE; + //When selecting a c3t3 item, we don't want to select its children, so we can still apply Operations to it + QList getChildrenForSelection() const Q_DECL_OVERRIDE { return QList(); } public: QMenu* contextMenu() Q_DECL_OVERRIDE; void copyProperties(Scene_item *) Q_DECL_OVERRIDE; diff --git a/Polyhedron/demo/Polyhedron/Scene_item.cpp b/Polyhedron/demo/Polyhedron/Scene_item.cpp index a785f8537fb..1cd1a602099 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item.cpp @@ -123,10 +123,6 @@ QMenu* CGAL::Three::Scene_item::contextMenu() } defaultContextMenu = new QMenu(name()); - // defaultContextMenu->addAction(name()); - // defaultContextMenu->addSeparator(); - // QMenu* modeMenu = new QMenu(QObject::tr("Rendering mode"), - // defaultContextMenu); for(unsigned int mode = 0; mode < NumberOfRenderingMode; ++mode) { @@ -136,8 +132,8 @@ QMenu* CGAL::Three::Scene_item::contextMenu() .arg(mName), this, slotName(RenderingMode(mode))); + defaultContextMenu->actions().last()->setProperty("is_groupable", true); } - // defaultContextMenu->addAction(modeMenu->menuAction()); return defaultContextMenu; } diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index 457a72d9aba..68b55bb7b56 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -168,8 +168,11 @@ Scene_points_with_normal_item::Scene_points_with_normal_item(const Scene_points_ setRenderingMode(Points); is_selected = true; } - - invalidateOpenGLBuffers(); + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); + invalidateOpenGLBuffers(); } // Converts polyhedron to point set @@ -182,6 +185,10 @@ Scene_points_with_normal_item::Scene_points_with_normal_item(const SMesh& input_ d = new Scene_points_with_normal_item_priv(input_mesh, this); setRenderingMode(PointsPlusNormals); is_selected = true; + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); invalidateOpenGLBuffers(); } @@ -193,6 +200,10 @@ Scene_points_with_normal_item::Scene_points_with_normal_item(const Polyhedron& i d = new Scene_points_with_normal_item_priv(input_mesh, this); setRenderingMode(PointsPlusNormals); is_selected = true; + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); invalidateOpenGLBuffers(); } @@ -369,10 +380,6 @@ void Scene_points_with_normal_item_priv::compute_normals_and_vertices() const normals.resize(0); colors_points.resize(0); - if(item->point_set()->number_of_points() < 30 ) - point_Slider->setValue(5); - else - point_Slider->setValue(2); //Shuffle container to allow quick display random points std::random_shuffle (m_points->begin(), m_points->first_selected()); if (m_points->nb_selected_points() != 0) @@ -594,7 +601,10 @@ bool Scene_points_with_normal_item::read_ply_point_set(std::istream& stream) bool ok = stream && CGAL::read_ply_point_set (stream, *(d->m_points), &(d->m_comments)) && !isEmpty(); - + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); std::cerr << d->m_points->info(); if (d->m_points->has_normal_map()) @@ -637,6 +647,10 @@ bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream) bool ok = stream && CGAL::read_off_point_set(stream, *(d->m_points)) && !isEmpty(); + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); invalidateOpenGLBuffers(); return ok; } @@ -662,7 +676,10 @@ bool Scene_points_with_normal_item::read_xyz_point_set(std::istream& stream) bool ok = stream && CGAL::read_xyz_point_set (stream, *(d->m_points)) && !isEmpty(); - + if(d->m_points->number_of_points() < 30 ) + d->point_Slider->setValue(5); + else + d->point_Slider->setValue(2); invalidateOpenGLBuffers(); return ok; } @@ -1004,7 +1021,8 @@ void Scene_points_with_normal_item::copyProperties(Scene_item *item) Scene_points_with_normal_item* point_item = qobject_cast(item); if(!point_item) return; - d->point_Slider->setValue(point_item->getPointSliderValue()); + int value = point_item->getPointSliderValue(); + setPointSize(value); if(has_normals()) d->normal_Slider->setValue(point_item->getNormalSliderValue()); } diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp index 1dabf35592b..8b4b8fad5c6 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_item.cpp @@ -121,10 +121,9 @@ struct Scene_polyhedron_item_priv{ nb_f_lines = 0; is_multicolor = false; no_flat = false; - vertices_displayed = true; - edges_displayed = true; - faces_displayed = true; - all_primitives_displayed = false; + vertices_displayed = false; + edges_displayed = false; + faces_displayed = false; invalidate_stats(); CGAL::set_halfedgeds_items_id(*poly); } @@ -189,7 +188,6 @@ struct Scene_polyhedron_item_priv{ mutable bool vertices_displayed; mutable bool edges_displayed; mutable bool faces_displayed; - mutable bool all_primitives_displayed; mutable QList text_ids; mutable std::vector targeted_id; void initialize_buffers(CGAL::Three::Viewer_interface *viewer = 0) const; @@ -1078,7 +1076,7 @@ Scene_polyhedron_item::toolTip() const QObject::tr("

Polyhedron_3 %1 (mode: %5, color: %6)

" "

Number of vertices: %2
" "Number of edges: %3
" - "Number of facets: %4") + "Number of faces: %4") .arg(this->name()) .arg(d->poly->size_of_vertices()) .arg(d->poly->size_of_halfedges()/2) @@ -1142,13 +1140,6 @@ QMenu* Scene_polyhedron_item::contextMenu() connect(actionPrintFaces, SIGNAL(triggered(bool)), this, SLOT(showFaces(bool))); - QAction* actionPrintAll= - menu->addAction(tr("Display All Ids")); - actionPrintAll->setCheckable(true); - actionPrintAll->setObjectName("actionPrintAll"); - connect(actionPrintAll, SIGNAL(triggered(bool)), - this, SLOT(showPrimitives(bool))); - QAction* actionZoomToId= menu->addAction(tr("Zoom to Index")); actionZoomToId->setObjectName("actionZoomToId"); @@ -1212,8 +1203,6 @@ QMenu* Scene_polyhedron_item::contextMenu() if(action) action->setChecked(d->edges_displayed); action = menu->findChild("actionPrintFaces"); if(action) action->setChecked(d->faces_displayed); - action = menu->findChild("actionPrintAll"); - if(action) action->setChecked(d->all_primitives_displayed); return menu; } @@ -1845,8 +1834,6 @@ CGAL::Three::Scene_item::Header_data Scene_polyhedron_item::header() const void Scene_polyhedron_item::printPrimitiveId(QPoint point, CGAL::Three::Viewer_interface *viewer) { - if(d->all_primitives_displayed) - return; typedef Input_facets_AABB_tree Tree; Tree* aabb_tree = static_cast(d->get_aabb_tree()); if(!aabb_tree) @@ -1871,8 +1858,7 @@ void Scene_polyhedron_item_priv::fillTargetedIds(const Polyhedron::Facet_handle& textVItems, textEItems, textFItems, - &targeted_id, - &all_primitives_displayed); + &targeted_id); if(vertices_displayed @@ -1928,8 +1914,7 @@ void Scene_polyhedron_item_priv::killIds() textVItems, textEItems, textFItems, - &targeted_id, - &all_primitives_displayed); + &targeted_id); } void Scene_polyhedron_item::printAllIds(CGAL::Three::Viewer_interface *viewer) @@ -1944,7 +1929,6 @@ void Scene_polyhedron_item::printAllIds(CGAL::Three::Viewer_interface *viewer) s3(printFaceIds(viewer)); if((s1 && s2 && s3)) { - d->all_primitives_displayed = true; viewer->update(); } return; @@ -2251,6 +2235,9 @@ void Scene_polyhedron_item::zoomToId() QString text = QInputDialog::getText(QApplication::activeWindow(), tr("Zoom to Index"), tr("Simplex"), QLineEdit::Normal, tr("v0"), &ok); + if(!ok) + return; + CGAL::Three::Viewer_interface* viewer = qobject_cast(QGLViewer::QGLViewerPool().first()); Point p; diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 8fd8db1dcc8..93bf7e18f11 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -88,10 +88,9 @@ struct Scene_surface_mesh_item_priv{ item = parent; has_feature_edges = false; invalidate_stats(); - vertices_displayed = true; - edges_displayed = true; - faces_displayed = true; - all_primitives_displayed = false; + vertices_displayed = false; + edges_displayed = false; + faces_displayed = false; } Scene_surface_mesh_item_priv(SMesh* sm, Scene_surface_mesh_item *parent): @@ -100,10 +99,9 @@ struct Scene_surface_mesh_item_priv{ item = parent; has_feature_edges = false; invalidate_stats(); - vertices_displayed = true; - edges_displayed = true; - faces_displayed = true; - all_primitives_displayed = false; + vertices_displayed = false; + edges_displayed = false; + faces_displayed = false; } ~Scene_surface_mesh_item_priv() @@ -165,7 +163,6 @@ struct Scene_surface_mesh_item_priv{ mutable bool vertices_displayed; mutable bool edges_displayed; mutable bool faces_displayed; - mutable bool all_primitives_displayed; mutable QList text_ids; mutable std::vector targeted_id; @@ -774,16 +771,18 @@ Scene_surface_mesh_item::isEmpty() const QString Scene_surface_mesh_item::toolTip() const { - return QObject::tr("

Surface_mesh %1 (mode: %5, color: %6)

" - "

Number of vertices: %2
" - "Number of edges: %3
" - "Number of faces: %4

") - .arg(this->name()) - .arg(num_vertices(*d->smesh_)) - .arg(num_edges(*d->smesh_)) - .arg(num_faces(*d->smesh_)) - .arg(this->renderingModeName()) - .arg(this->color().name()); + QString str = QObject::tr("

Surface_mesh %1 (mode: %5, color: %6)

" + "

Number of vertices: %2
" + "Number of edges: %3
" + "Number of faces: %4

") + .arg(this->name()) + .arg(num_vertices(*d->smesh_)) + .arg(num_edges(*d->smesh_)) + .arg(num_faces(*d->smesh_)) + .arg(this->renderingModeName()) + .arg(this->color().name()); + str += QString("
Number of isolated vertices: %1
").arg(getNbIsolatedvertices()); + return str; } void Scene_surface_mesh_item_priv::checkFloat()const @@ -1706,12 +1705,6 @@ QMenu* Scene_surface_mesh_item::contextMenu() connect(actionPrintFaces, SIGNAL(triggered(bool)), this, SLOT(showFaces(bool))); - QAction* actionPrintAll= - menu->addAction(tr("Display All Ids")); - actionPrintAll->setCheckable(true); - actionPrintAll->setObjectName("actionPrintAll"); - connect(actionPrintAll, SIGNAL(triggered(bool)), - this, SLOT(showPrimitives(bool))); QAction* actionZoomToId= menu->addAction(tr("Zoom to Index")); @@ -1727,14 +1720,10 @@ QMenu* Scene_surface_mesh_item::contextMenu() if(action) action->setChecked(d->edges_displayed); action = menu->findChild("actionPrintFaces"); if(action) action->setChecked(d->faces_displayed); - action = menu->findChild("actionPrintAll"); - if(action) action->setChecked(d->all_primitives_displayed); return menu; } void Scene_surface_mesh_item::printPrimitiveId(QPoint point, CGAL::Three::Viewer_interface *viewer) { - if(d->all_primitives_displayed) - return; typedef Input_facets_AABB_tree Tree; Tree* aabb_tree = static_cast(d->get_aabb_tree()); if(!aabb_tree) @@ -1759,8 +1748,7 @@ void Scene_surface_mesh_item_priv::fillTargetedIds(const face_descriptor &select textVItems, textEItems, textFItems, - &targeted_id, - &all_primitives_displayed); + &targeted_id); if(vertices_displayed @@ -1816,8 +1804,7 @@ void Scene_surface_mesh_item_priv::killIds() textVItems, textEItems, textFItems, - &targeted_id, - &all_primitives_displayed); + &targeted_id); } void Scene_surface_mesh_item::printAllIds(CGAL::Three::Viewer_interface *viewer) @@ -1832,7 +1819,6 @@ void Scene_surface_mesh_item::printAllIds(CGAL::Three::Viewer_interface *viewer) s3(printFaceIds(viewer)); if((s1 && s2 && s3)) { - d->all_primitives_displayed = true; viewer->update(); } return; @@ -1887,7 +1873,7 @@ void Scene_surface_mesh_item::showEdges(bool b) if(d->textEItems->isEmpty()) { d->edges_displayed = b; - printFaceIds(viewer); + printEdgeIds(viewer); } else renderer->addTextList(d->textEItems); @@ -1932,6 +1918,9 @@ void Scene_surface_mesh_item::zoomToId() QString text = QInputDialog::getText(QApplication::activeWindow(), tr("Zoom to Index"), tr("Simplex"), QLineEdit::Normal, tr("v0"), &ok); + if(!ok) + return; + CGAL::Three::Viewer_interface* viewer = qobject_cast(QGLViewer::QGLViewerPool().first()); Point_3 p; diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index a8fa406f39f..3193e9978cd 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -53,9 +53,9 @@ public: }; //! The buffers used to draw the axis system - QOpenGLBuffer buffers[4]; + QOpenGLBuffer buffers[8]; //! The VAO used to draw the axis system - QOpenGLVertexArrayObject vao[2]; + QOpenGLVertexArrayObject vao[4]; //! The rendering program used to draw the axis system QOpenGLShaderProgram rendering_program; //! The rendering program used to draw the distance @@ -69,6 +69,9 @@ public: std::vector c_Axis; //! Decides if the axis system must be drawn or not bool axis_are_displayed; + bool grid_is_displayed; + std::size_t grid_size; + std::size_t v_gaxis_size; //! Decides if the text is displayed in the drawVisualHints function. bool has_text; //! Decides if the distance between APoint and BPoint must be drawn; @@ -96,6 +99,7 @@ public: * \param data the struct of std::vector that will contain the results. */ void makeArrow(double R, int prec, qglviewer::Vec from, qglviewer::Vec to, qglviewer::Vec color, AxisData &data); + void drawGrid(qreal size, int nbSubdivisions=10); //!Clears the distance display void clearDistancedisplay(); void draw_aux(bool with_names, Viewer*); @@ -138,6 +142,8 @@ Viewer::Viewer(QWidget* parent, bool antialiasing) tr("Toggle the primitive IDs visibility of the selected Item.")); setKeyDescription(Qt::Key_D, tr("Disable the distance between two points visibility.")); + setKeyDescription(Qt::Key_F5, + tr("Reload selected items if possible.")); #if QGLVIEWER_VERSION >= 0x020501 //modify mouse bindings that have been updated @@ -168,6 +174,8 @@ Viewer::Viewer(QWidget* parent, bool antialiasing) #endif // QGLVIEWER_VERSION >= 2.5.0 prev_radius = sceneRadius(); d->axis_are_displayed = true; + d->grid_is_displayed = false; + d->grid_size = 0; d->has_text = false; d->i_is_pressed = false; d->z_is_pressed = false; @@ -398,6 +406,12 @@ void Viewer::initializeGL() { d->vao[1].create(); d->buffers[3].create(); + d->vao[2].create(); + d->vao[3].create(); + d->buffers[4].create(); + d->buffers[5].create(); + d->buffers[6].create(); + d->buffers[7].create(); //Vertex source code const char vertex_source_dist[] = { @@ -557,6 +571,10 @@ void Viewer::keyPressEvent(QKeyEvent* e) d->axis_are_displayed = !d->axis_are_displayed; update(); } + else if(e->key() == Qt::Key_G) { + d->grid_is_displayed = !d->grid_is_displayed; + update(); + } else if(e->key() == Qt::Key_I) { d->i_is_pressed = true; } @@ -1141,6 +1159,71 @@ void Viewer::drawVisualHints() glLineWidth(1.0f); } + if(d->grid_is_displayed) + { + //draws the distance + QMatrix4x4 mvpMatrix; + double mat[16]; + //camera()->frame()->rotation().getMatrix(mat); + camera()->getModelViewProjectionMatrix(mat); + //nullifies the translation + for(int i=0; i < 16; i++) + { + mvpMatrix.data()[i] = (float)mat[i]; + } + d->rendering_program_dist.bind(); + d->rendering_program_dist.setUniformValue("mvp_matrix", mvpMatrix); + d->vao[2].bind(); + glDrawArrays(GL_LINES, 0, static_cast(d->grid_size)); + d->vao[2].release(); + d->rendering_program_dist.release(); + + d->rendering_program.bind(); + QMatrix4x4 mvMatrix; + for(int i=0; i < 16; i++) + { + mvMatrix.data()[i] = camera()->orientation().inverse().matrix()[i]; + } + QVector4D position(0.0f,0.0f,1.0f,1.0f ); + // define material + QVector4D ambient; + QVector4D diffuse; + QVector4D specular; + GLfloat shininess ; + // Ambient + ambient[0] = 0.29225f; + ambient[1] = 0.29225f; + ambient[2] = 0.29225f; + ambient[3] = 1.0f; + // Diffuse + diffuse[0] = 0.50754f; + diffuse[1] = 0.50754f; + diffuse[2] = 0.50754f; + diffuse[3] = 1.0f; + // Specular + specular[0] = 0.0f; + specular[1] = 0.0f; + specular[2] = 0.0f; + specular[3] = 0.0f; + // Shininess + shininess = 51.2f; + + d->rendering_program.setUniformValue("light_pos", position); + d->rendering_program.setUniformValue("mvp_matrix", mvpMatrix); + d->rendering_program.setUniformValue("mv_matrix", mvMatrix); + d->rendering_program.setUniformValue("light_diff", diffuse); + d->rendering_program.setUniformValue("light_spec", specular); + d->rendering_program.setUniformValue("light_amb", ambient); + d->rendering_program.setUniformValue("spec_power", shininess); + + d->vao[3].bind(); + // Axis viewport size, in pixels + glDrawArrays(GL_TRIANGLES, 0, static_cast(d->v_gaxis_size / 3)); + // The viewport and the scissor are restored. + d->vao[3].release(); + d->rendering_program.release(); + } + if (!d->painter->isActive()) d->painter->begin(this); //So that the text is drawn in front of everything @@ -1325,9 +1408,6 @@ void Viewer::postDraw() // Pivot point, line when camera rolls, zoom region drawVisualHints(); - if (gridIsDrawn()) { glLineWidth(1.0); drawGrid(camera()->sceneRadius()); } - if (axisIsDrawn()) { glLineWidth(2.0); drawAxis(camera()->sceneRadius()); } - // FPS computation const unsigned int maxCounter = 20; if (++d->fpsCounter == maxCounter) @@ -1663,6 +1743,7 @@ qglviewer::Vec Viewer::offset()const { return d->offset; } void Viewer::setSceneBoundingBox(const qglviewer::Vec &min, const qglviewer::Vec &max) { QGLViewer::setSceneBoundingBox(min+d->offset, max+d->offset); + d->drawGrid(camera()->sceneRadius()); } void Viewer::updateIds(CGAL::Three::Scene_item * item) @@ -1700,6 +1781,78 @@ void Viewer::enableClippingBox(QVector4D box[6]) bool Viewer::isOpenGL_4_3() const { return d->is_ogl_4_3; } +void Viewer_impl::drawGrid(qreal size, int nbSubdivisions) +{ + std::vector v_Grid; + std::vector v_gAxis; + std::vector n_gAxis; + std::vector c_gAxis; + for (int i=0; i<=nbSubdivisions; ++i) + { + const float pos = size*(2.0*i/nbSubdivisions-1.0); + v_Grid.push_back(pos); + v_Grid.push_back(-size); + v_Grid.push_back(0.0); + v_Grid.push_back(pos); + v_Grid.push_back(+size); + v_Grid.push_back(0.0); + + v_Grid.push_back(-size); + v_Grid.push_back(pos); + v_Grid.push_back(0.0); + + v_Grid.push_back( size); + v_Grid.push_back( pos); + v_Grid.push_back( 0.0); + } + rendering_program_dist.bind(); + vao[2].bind(); + buffers[4].bind(); + buffers[4].allocate(v_Grid.data(),static_cast(v_Grid.size()*sizeof(float))); + rendering_program_dist.enableAttributeArray("vertex"); + rendering_program_dist.setAttributeBuffer("vertex",GL_FLOAT,0,3); + buffers[4].release(); + vao[2].release(); + rendering_program_dist.release(); + grid_size = v_Grid.size(); + + Viewer_impl::AxisData data; + v_gAxis.resize(0); + n_gAxis.resize(0); + c_gAxis.resize(0); + data.vertices = &v_gAxis; + data.normals = &n_gAxis; + data.colors = &c_gAxis; + makeArrow(0.02*size,10, qglviewer::Vec(0,0,0),qglviewer::Vec(size,0,0),qglviewer::Vec(1,0,0), data); + makeArrow(0.02*size,10, qglviewer::Vec(0,0,0),qglviewer::Vec(0,size,0),qglviewer::Vec(0,1,0), data); + makeArrow(0.02*size,10, qglviewer::Vec(0,0,0),qglviewer::Vec(0,0,size),qglviewer::Vec(0,0,1), data); + + rendering_program.bind(); + vao[3].bind(); + buffers[5].bind(); + buffers[5].allocate(v_gAxis.data(), static_cast(v_gAxis.size()) * sizeof(float)); + rendering_program.enableAttributeArray("vertex"); + rendering_program.setAttributeBuffer("vertex",GL_FLOAT,0,3); + buffers[5].release(); + + buffers[6].bind(); + buffers[6].allocate(n_gAxis.data(), static_cast(n_gAxis.size() * sizeof(float))); + rendering_program.enableAttributeArray("normal"); + rendering_program.setAttributeBuffer("normal",GL_FLOAT,0,3); + buffers[6].release(); + + buffers[7].bind(); + buffers[7].allocate(c_gAxis.data(), static_cast(c_gAxis.size() * sizeof(float))); + rendering_program.enableAttributeArray("colors"); + rendering_program.setAttributeBuffer("colors",GL_FLOAT,0,3); + buffers[7].release(); + vao[3].release(); + + rendering_program.release(); + + v_gaxis_size = v_gAxis.size(); + +} QOpenGLFunctions_4_3_Compatibility* Viewer::openGL_4_3_functions() { return d->_recentFunctions; } #include "Viewer.moc" diff --git a/Polyhedron/demo/Polyhedron/include/id_printing.h b/Polyhedron/demo/Polyhedron/include/id_printing.h index cc31d037fbe..2e97d36d2f6 100644 --- a/Polyhedron/demo/Polyhedron/include/id_printing.h +++ b/Polyhedron/demo/Polyhedron/include/id_printing.h @@ -85,8 +85,7 @@ void deleteIds(CGAL::Three::Viewer_interface* viewer, TextListItem* vitems, TextListItem* eitems, TextListItem* fitems, - std::vector* targeted_ids, - bool *all_primitives_displayed) + std::vector* targeted_ids) { TextRenderer *renderer = viewer->textRenderer(); BOOST_FOREACH(TextItem* it, vitems->textList()) @@ -102,7 +101,6 @@ void deleteIds(CGAL::Three::Viewer_interface* viewer, fitems->clear(); renderer->removeTextList(fitems); targeted_ids->clear(); - *all_primitives_displayed = false; viewer->update(); } @@ -175,8 +173,7 @@ void compute_displayed_ids(Mesh& mesh, TextListItem* vitems, TextListItem* eitems, TextListItem* fitems, - std::vector* targeted_ids, - bool *all_primitives_displayed) + std::vector* targeted_ids) { typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -228,11 +225,11 @@ void compute_displayed_ids(Mesh& mesh, if(text_item->position() == point) { //hide and stop - deleteIds(viewer, vitems, eitems, fitems, targeted_ids, all_primitives_displayed); + deleteIds(viewer, vitems, eitems, fitems, targeted_ids); return; } } - deleteIds(viewer, vitems, eitems, fitems, targeted_ids, all_primitives_displayed); + deleteIds(viewer, vitems, eitems, fitems, targeted_ids); // test the midpoint of edges of the closest face BOOST_FOREACH(halfedge_descriptor e, halfedges_around_face(halfedge(selected_fh, mesh), mesh)) { diff --git a/Polyhedron/demo/Polyhedron/resources/help_button.png b/Polyhedron/demo/Polyhedron/resources/help_button.png new file mode 100644 index 00000000000..0c3d144072d Binary files /dev/null and b/Polyhedron/demo/Polyhedron/resources/help_button.png differ diff --git a/Three/include/CGAL/Three/Scene_group_item.h b/Three/include/CGAL/Three/Scene_group_item.h index 91381e75d41..7cb47523bc3 100644 --- a/Three/include/CGAL/Three/Scene_group_item.h +++ b/Three/include/CGAL/Three/Scene_group_item.h @@ -175,6 +175,15 @@ public : //! Only returns children that have this item as a parent. //! Children of these children are not returned. QList getChildren() const {return children;} + + //! \brief getChildrenForSelection returns the list of + //! children to select along with the group. + //! + //! When a `Scene_group_item` is added to the selection of the scene, + //! this function defines which of its children will be added too. + //! Typically overriden to allow applying an operation from the + //! Operation menu only to the parent item and not to its children. + virtual QList getChildrenForSelection() const {return children;} //!Removes a Scene_item from the list of children. //!@see getChildren() @see addChild() void removeChild( Scene_item* item)