Merge pull request #3516 from maxGimeno/Demo-fixes-GF

Polyhedron Demo: Fixes.
This commit is contained in:
Sébastien Loriot 2019-01-31 11:41:58 +01:00
commit 6c6244d9b8
26 changed files with 391 additions and 228 deletions

View File

@ -1649,7 +1649,7 @@ bool remove_degenerate_faces( TriangleMesh& tmesh,
}
template<class TriangleMesh>
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());

View File

@ -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<QAction*> 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<QAction*> 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 <CGAL/Three/exceptions.h>
@ -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);
@ -968,6 +996,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()) {
@ -986,9 +1016,9 @@ void MainWindow::reloadItem() {
new_item->setRenderingMode(item->renderingMode());
new_item->setVisible(item->visible());
Scene_item_with_properties *property_item = dynamic_cast<Scene_item_with_properties*>(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();
}
@ -1169,16 +1199,19 @@ 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()));
}
QApplication::setOverrideCursor(Qt::WaitCursor);
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());
@ -1201,11 +1234,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());
}
}
@ -1220,6 +1255,8 @@ void MainWindow::selectSceneItems(QList<int> 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());
@ -1403,6 +1440,15 @@ void MainWindow::showSceneContextMenu(const QPoint& p) {
QMap<QString, QAction*> menu_actions;
QVector<QMenu*> 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())
@ -1565,10 +1611,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()));
@ -2196,6 +2245,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);

View File

@ -453,6 +453,9 @@ private:
QMap<QString, QPair<QStringList, QString> >plugin_metadata_map;
QMap<QString, bool> ignored_map;
const QStringList& accepted_keywords;
private:
QMap<QAction*, QMenu*> action_menu_map;
};
#endif // ifndef MAINWINDOW_H

View File

@ -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 {}

View File

@ -13,6 +13,7 @@
#include <CGAL/boost/graph/helpers.h>
#include "Kernel_type.h"
#include <CGAL/Three/Three.h>
typedef Kernel::Plane_3 Plane;
typedef Kernel::Iso_cuboid_3 Iso_cuboid;
typedef Kernel::Triangle_3 Triangle;
@ -99,148 +100,150 @@ void Polyhedron_demo_pca_plugin::on_actionFitPlane_triggered()
Scene_surface_mesh_item* sm_item =
qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
QApplication::setOverrideCursor(Qt::WaitCursor);
std::list<Triangle> 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_points_with_normal_item*>(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(Qt::WaitCursor);
if(sm_item){
std::list<Triangle> 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_points_with_normal_item*>(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(Qt::WaitCursor);
Scene_surface_mesh_item* sm_item =
qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
QApplication::setOverrideCursor(Qt::WaitCursor);
CGAL::Bbox_3 bb;
qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
std::list<Triangle> 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<Triangle> 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 +300,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 +317,6 @@ void Polyhedron_demo_pca_plugin::on_actionFitLine_triggered()
scene->addItem(new_item);
}
}
QApplication::restoreOverrideCursor();
}
#include "Pca_plugin.moc"

View File

@ -152,6 +152,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);

View File

@ -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{

View File

@ -449,6 +449,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;

View File

@ -103,6 +103,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();
@ -128,6 +129,7 @@ public Q_SLOTS:
for(std::vector<boost::graph_traits<FaceGraph>::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();

View File

@ -366,6 +366,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;
@ -860,7 +861,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();
}

View File

@ -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;

View File

@ -148,9 +148,10 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_tr
qobject_cast<Item*>(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());
nbv -= num_faces(*poly_item->polyhedron());
CGAL::Three::Three::information(tr(" %1 degenerate faces have been removed.")
.arg(nbv));
poly_item->invalidateOpenGLBuffers();

View File

@ -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)
{

View File

@ -137,6 +137,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);
@ -771,7 +776,8 @@ public Q_SLOTS:
bool is_valid = true;
BOOST_FOREACH(boost::graph_traits<Face_graph>::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;

View File

@ -551,7 +551,7 @@
</item>
<item>
<property name="text">
<string>Split edges</string>
<string>Split edge</string>
</property>
</item>
<item>

View File

@ -60,7 +60,8 @@ public Q_SLOTS:
}
if(!CGAL::Polygon_mesh_processing::triangulate_faces(*pMesh))
CGAL::Three::Three::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

View File

@ -317,6 +317,10 @@ public:
return _actions;
}
~Polyhedron_demo_parameterization_plugin()
{
delete navigation;
}
void init(QMainWindow* mainWindow,
Scene_interface* scene_interface,
Messages_interface* msg)
@ -825,6 +829,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
if (i == QDialog::Rejected)
{
std::cout << "Aborting parameterization" << std::endl;
QApplication::restoreOverrideCursor();
return;
}
@ -837,6 +842,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;
}
@ -848,6 +854,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;
}
@ -882,6 +889,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;
}

View File

@ -60,7 +60,7 @@
<x>0</x>
<y>0</y>
<width>278</width>
<height>432</height>
<height>499</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -118,6 +118,9 @@
<property name="prefix">
<string>Transparency Pass Number: </string>
</property>
<property name="minimum">
<number>4</number>
</property>
<property name="value">
<number>4</number>
</property>
@ -311,7 +314,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Tick plugins you don't want to load at start up</string>
<string>Tick plugins you want to load at start up</string>
</property>
</widget>
</item>

View File

@ -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<int> 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<int> 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();
@ -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*
@ -683,6 +684,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<double>. 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<QVariant> picked_point;
picked_point <<point.x
<<point.y
<<point.z;
viewer->setProperty("picked_point", picked_point);
}
else{
viewer->setProperty("picked_point", QList<QVariant>());
}
}
else {
viewer->setProperty("picked_point", {});
}
}
if(!with_names && has_alpha())
{
std::vector<QOpenGLFramebufferObject*> fbos;
@ -1188,8 +1217,9 @@ void Scene::moveRowUp()
}
}
}
if(!to_select.isEmpty())
if(!to_select.isEmpty()){
selectionChanged(to_select);
}
}
void Scene::moveRowDown()
{
@ -1544,7 +1574,6 @@ void Scene::redraw_model()
index_map.clear();
//fills the model
Q_FOREACH(Item_id id, children)
{
organize_items(m_entries[id], invisibleRootItem(), 0);
}

View File

@ -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]()
{

View File

@ -185,7 +185,8 @@ public:
if(has_normals)
{
const Kernel::Vector_3& n = point_set->normal(*it);
Point_set_3<Kernel>::Point q = p + length * n;
Kernel::FT normalizer = 1.0/CGAL::sqrt(n.squared_length());
Point_set_3<Kernel>::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
{

View File

@ -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 {

View File

@ -1112,6 +1112,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::set<fg_vertex_d
set_active_handle_type(static_cast<Active_handle::Type>(1));
d->tempInstructions("Face split.",
"Select a facet (1/3).");
polyhedron_item()->resetColors();
polyhedron_item()->invalidateOpenGLBuffers();
}
}
@ -1337,6 +1338,7 @@ bool Scene_polyhedron_selection_item:: treat_selection(const std::set<fg_edge_de
temp_selected_edges.clear();
temp_selected_vertices.clear();
compute_normal_maps();
polyhedron_item()->resetColors();
invalidateOpenGLBuffers();
polyhedron_item()->invalidateOpenGLBuffers();
d->tempInstructions("Face and vertex added.",
@ -1387,6 +1389,7 @@ bool Scene_polyhedron_selection_item:: treat_selection(const std::set<fg_edge_de
temp_selected_vertices.clear();
temp_selected_edges.clear();
compute_normal_maps();
polyhedron_item()->resetColors();
invalidateOpenGLBuffers();
polyhedron_item()->invalidateOpenGLBuffers();
d->tempInstructions("Face added.",
@ -1485,6 +1488,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::set<fg_face_des
invalidateOpenGLBuffers();
//reset selection mode
set_active_handle_type(static_cast<Active_handle::Type>(0));
poly_item->resetColors();
poly_item->invalidateOpenGLBuffers();
d->tempInstructions("Vertex splitted.", "Select the vertex you want splitted. (1/3)");
}
@ -1540,6 +1544,7 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::set<fg_face_des
if(total !=0)
put(vpm, target(hhandle,*polyhedron()), Point_3(x/(double)total, y/(double)total, z/(double)total));
compute_normal_maps();
polyhedron_item()->resetColors();
poly_item->invalidateOpenGLBuffers();
}

View File

@ -895,11 +895,10 @@ Scene_surface_mesh_item_priv::triangulate_facet(face_descriptor fd,
if(normal == CGAL::NULL_VECTOR)
{
boost::graph_traits<SMesh>::halfedge_descriptor start = prev(halfedge(fd, *smesh_), *smesh_);
boost::graph_traits<SMesh>::halfedge_descriptor next_;
boost::graph_traits<SMesh>::halfedge_descriptor hd = halfedge(fd, *smesh_);
boost::graph_traits<SMesh>::halfedge_descriptor next_=next(hd, *smesh_);
do
{
boost::graph_traits<SMesh>::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

View File

@ -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)
@ -708,12 +715,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<QVariant> 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)
@ -725,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);
dir.x, dir.y, dir.z);
this->setProperty("performing_selection", false);
}
}
bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame)
@ -990,6 +1014,7 @@ void Viewer::drawVisualHints()
if (d->_displayMessage)
d->textRenderer->removeText(message_text);
delete message_text;
}
QOpenGLShaderProgram* Viewer::declare_program(int name,

View File

@ -29,6 +29,7 @@
#include <QDockWidget>
#include <CGAL/Three/Scene_interface.h>
#include <QMainWindow>
#include <QApplication>
#ifdef three_EXPORTS
# define THREE_EXPORT Q_DECL_EXPORT
@ -96,6 +97,18 @@ protected:
static int default_normal_length;
static int default_lines_width;
public:
struct CursorScopeGuard
{
CursorScopeGuard(QCursor cursor)
{
QApplication::setOverrideCursor(cursor);
}
~CursorScopeGuard()
{
QApplication::restoreOverrideCursor();
}
};
};
}
}