Merge pull request #4811 from maxGimeno/Demo-Fixes_and_features-maxGimeno

Polyhedron demo: fixes and features
This commit is contained in:
Sebastien Loriot 2020-10-02 15:17:25 +02:00 committed by GitHub
commit aff306bb55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 247 additions and 53 deletions

View File

@ -371,6 +371,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren
// Setup the submenu of the View menu that can toggle the dockwidgets
Q_FOREACH(QDockWidget* widget, findChildren<QDockWidget*>()) {
widget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable);
ui->menuDockWindows->addAction(widget->toggleViewAction());
}
ui->menuDockWindows->removeAction(ui->dummyAction);
@ -1285,7 +1286,7 @@ QList<Scene_item*> MainWindow::loadItem(QFileInfo fileinfo,
QCursor tmp_cursor(Qt::WaitCursor);
CGAL::Three::Three::CursorScopeGuard guard(tmp_cursor);
QList<Scene_item*> result = loader->load(fileinfo, ok, add_to_scene);
if(result.empty() || !ok)
if(!ok)
{
QApplication::restoreOverrideCursor();
QMessageBox::warning(this, tr("Error"),
@ -1579,6 +1580,8 @@ void MainWindow::showSceneContextMenu(const QPoint& p) {
has_stats = true;
}
QMenu menu;
menu.addAction(actionAddToGroup);
menu.insertSeparator(0);
Q_FOREACH(QString name, menu_actions.keys())
{
if(name == QString("alpha slider")
@ -2579,6 +2582,10 @@ void MainWindow::makeNewGroup()
{
Scene_group_item * group = new Scene_group_item();
scene->addItem(group);
for(Scene::Item_id id : scene->selectionIndices())
{
scene->changeGroup(scene->item(id), group);
}
}
void MainWindow::on_upButton_pressed()
@ -2956,6 +2963,7 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered()
std::vector<QColor> colors;
std::vector<int> rendering_modes;
QStringList not_saved;
Polyhedron_demo_io_plugin_interface* camera_plugin = nullptr;
for(int i = 0; i < scene->numberOfEntries(); ++i)
{
Scene_item* item = scene->item(i);
@ -2963,6 +2971,8 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered()
QString ext;
for(Polyhedron_demo_io_plugin_interface* iop : io_plugins)
{
if(iop->name() == "camera_positions_plugin")
camera_plugin = iop;
if(iop->isDefaultLoader(item))
{
QString sf = iop->saveNameFilters().split(";;").first();
@ -2992,6 +3002,23 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered()
colors.push_back(item->color());
rendering_modes.push_back(item->renderingMode());
}
bool has_camera_positions = false;
if(camera_plugin)
{
QString fullpath = make_fullpath("camera_tmp.camera.txt");
QList<Scene_item*> dummy;
if(camera_plugin->save(QFileInfo(fullpath), dummy))
{
QByteArray item = file_to_string(fullpath.toStdString().c_str());
os << "var camera_positions= [\'";
os<<qCompress(item, 9).toBase64().toStdString().c_str();
os << "\']\n" ;
//delete temp file
QFile tmp_file(fullpath);
tmp_file.remove();
has_camera_positions =true;
}
}
if(loaders.empty())
return;
//path
@ -3054,6 +3081,12 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered()
os << " it.setRenderingMode(rendering_modes[index]);\n";
os << "});\n";
os << "viewer.moveCameraToCoordinates(camera, 0.05);\n";
if(has_camera_positions)
{
os<<" var path=\"cams.camera.txt\";\n";
os<<" var fullpath = main_window.write_string_to_file(camera_positions, path);\n";
os<<" main_window.open(fullpath,\'camera_positions_plugin\');\n";
}
os.close();
if(!not_saved.empty())
QMessageBox::warning(this,
@ -3238,6 +3271,13 @@ void MainWindow::setupViewer(Viewer* viewer, SubViewer* subviewer)
}
viewer->setTotalPass(nb);
});
action = subviewer->findChild<QAction*>("actionScaleScene");
action->setCheckable(true);
action->setChecked(false);
connect(action, &QAction::triggered,
viewer, &Viewer::scaleScene);
action= subviewer->findChild<QAction*>("actionBackFrontShading");
connect(action, SIGNAL(toggled(bool)),
viewer, SLOT(setBackFrontShading(bool)));
@ -3450,6 +3490,10 @@ SubViewer::SubViewer(QWidget *parent, MainWindow* mw, Viewer* mainviewer)
actionBackFrontShading->setChecked(false);
viewMenu->addAction(actionBackFrontShading);
QAction* actionScaleScene = new QAction("&Scale the Scene...",this);
actionScaleScene->setObjectName("actionScaleScene");
viewMenu->addAction(actionScaleScene);
if(mainviewer)
setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(QIcon(":/cgal/icons/resources/menu.png"));

View File

@ -89,13 +89,9 @@ void Camera_positions_list::activatedRow(QModelIndex index)
Three::activeViewer()->moveCameraToCoordinates(s);
}
void Camera_positions_list::on_saveButton_pressed()
{
QString filename =
QFileDialog::getSaveFileName(this,
tr("Save camera coordinates to file"),
QString(),
tr("(*.camera.txt)"));
bool Camera_positions_list::save(QString filename) {
if(m_model->rowCount() <1)
return false;
QFile file(filename);
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
@ -108,6 +104,17 @@ void Camera_positions_list::on_saveButton_pressed()
<< "\n";
}
file.close();
return true;
}
void Camera_positions_list::on_saveButton_pressed()
{
QString filename =
QFileDialog::getSaveFileName(this,
tr("Save camera coordinates to file"),
QString(),
tr("(*.camera.txt)"));
save(filename);
}
void Camera_positions_list::on_openButton_pressed()

View File

@ -15,6 +15,7 @@ public:
public Q_SLOTS:
void load(QString filename);
bool save(QString filename);
protected Q_SLOTS:
void on_plusButton_pressed();
void on_minusButton_pressed();
@ -41,3 +42,4 @@ private:
};
#endif

View File

@ -31,8 +31,11 @@ public:
return QList<Scene_item*>();
}
bool canSave(const Scene_item*) override { return false; }
bool save(QFileInfo,QList<CGAL::Three::Scene_item*>& ) override {return false; }
bool canSave(const Scene_item*) override { return true; }
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& ) override
{
return cpl->save(fileinfo.filePath());
}
private:
Camera_positions_list* cpl;
};

View File

@ -95,7 +95,7 @@ target_link_libraries(surface_intersection_plugin PUBLIC scene_surface_mesh_item
qt5_wrap_ui( repairUI_FILES RemoveNeedlesDialog.ui)
polyhedron_demo_plugin(repair_polyhedron_plugin Repair_polyhedron_plugin ${repairUI_FILES} KEYWORDS PMP)
target_link_libraries(repair_polyhedron_plugin PUBLIC scene_surface_mesh_item)
target_link_libraries(repair_polyhedron_plugin PUBLIC scene_points_with_normal_item scene_surface_mesh_item)
qt5_wrap_ui( isotropicRemeshingUI_FILES Isotropic_remeshing_dialog.ui)
polyhedron_demo_plugin(isotropic_remeshing_plugin Isotropic_remeshing_plugin ${isotropicRemeshingUI_FILES} KEYWORDS PMP)

View File

@ -1,6 +1,7 @@
#include <QtCore/qglobal.h>
#include "Scene_surface_mesh_item.h"
#include "Scene_points_with_normal_item.h"
#include <CGAL/Three/Scene_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
@ -47,6 +48,7 @@ public:
actionRemoveSelfIntersections = new QAction(tr("Remove Self-Intersections"), mw);
actionStitchCloseBorderHalfedges = new QAction(tr("Stitch Close Border Halfedges"), mw);
actionDuplicateNMVertices = new QAction(tr("Duplicate Non-Manifold Vertices"), mw);
actionExtractNMVertices = new QAction(tr("Extract Non-Manifold Vertices"), mw);
actionMergeDuplicatedVerticesOnBoundaryCycles = new QAction(tr("Merge Duplicated Vertices on Boundary Cycles"), mw);
actionAutorefine = new QAction(tr("Autorefine Mesh"), mw);
actionAutorefineAndRMSelfIntersections = new QAction(tr("Autorefine and Remove Self-Intersections"), mw);
@ -57,6 +59,7 @@ public:
actionRemoveSelfIntersections->setObjectName("actionRemoveSelfIntersections");
actionStitchCloseBorderHalfedges->setObjectName("actionStitchCloseBorderHalfedges");
actionDuplicateNMVertices->setObjectName("actionDuplicateNMVertices");
actionExtractNMVertices->setObjectName("actionExtractNMVertices");
actionMergeDuplicatedVerticesOnBoundaryCycles->setObjectName("actionMergeDuplicatedVerticesOnBoundaryCycles");
actionAutorefine->setObjectName("actionAutorefine");
actionAutorefineAndRMSelfIntersections->setObjectName("actionAutorefineAndRMSelfIntersections");
@ -67,6 +70,7 @@ public:
actionRemoveSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
actionRemoveIsolatedVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
actionDuplicateNMVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
actionExtractNMVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
actionMergeDuplicatedVerticesOnBoundaryCycles->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
actionAutorefine->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
actionAutorefineAndRMSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
@ -82,6 +86,7 @@ public:
<< actionRemoveSelfIntersections
<< actionStitchCloseBorderHalfedges
<< actionDuplicateNMVertices
<< actionExtractNMVertices
<< actionMergeDuplicatedVerticesOnBoundaryCycles
<< actionAutorefine
<< actionAutorefineAndRMSelfIntersections
@ -104,6 +109,8 @@ public:
template <typename Item>
void on_actionDuplicateNMVertices_triggered(Scene_interface::Item_id index);
template <typename Item>
void on_actionExtractNMVertices_triggered(Scene_interface::Item_id index);
template <typename Item>
void on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered(Scene_interface::Item_id index);
template <typename Item>
void on_actionAutorefine_triggered(Scene_interface::Item_id index);
@ -116,6 +123,7 @@ public Q_SLOTS:
void on_actionRemoveSelfIntersections_triggered();
void on_actionStitchCloseBorderHalfedges_triggered();
void on_actionDuplicateNMVertices_triggered();
void on_actionExtractNMVertices_triggered();
void on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered();
void on_actionAutorefine_triggered();
void on_actionAutorefineAndRMSelfIntersections_triggered();
@ -127,6 +135,7 @@ private:
QAction* actionRemoveSelfIntersections;
QAction* actionStitchCloseBorderHalfedges;
QAction* actionDuplicateNMVertices;
QAction* actionExtractNMVertices;
QAction* actionMergeDuplicatedVerticesOnBoundaryCycles;
QAction* actionAutorefine;
QAction* actionAutorefineAndRMSelfIntersections;
@ -347,6 +356,32 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_trig
}
}
template <typename Item>
void Polyhedron_demo_repair_polyhedron_plugin::on_actionExtractNMVertices_triggered(Scene_interface::Item_id index)
{
namespace PMP = CGAL::Polygon_mesh_processing;
typedef typename boost::graph_traits<typename Item::Face_graph>::halfedge_descriptor halfedge_descriptor;
if (Item* poly_item = qobject_cast<Item*>(scene->item(index)))
{
std::vector<halfedge_descriptor> hds;
PMP::non_manifold_vertices(*poly_item->face_graph(), std::back_inserter(hds));
if(hds.empty())
{
CGAL::Three::Three::information(tr(" No NM vertex found."));
return;
}
Scene_points_with_normal_item* pitem = new Scene_points_with_normal_item();
pitem->setColor(Qt::red);
pitem->setName(QString("%1 nm vertices").arg(poly_item->name()));
for(const auto& h : hds)
{
pitem->point_set()->insert(poly_item->face_graph()->point(target(h, *poly_item->face_graph())));
}
scene->addItem (pitem);
}
}
void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_triggered()
{
QApplication::setOverrideCursor(Qt::WaitCursor);
@ -355,6 +390,14 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_trig
QApplication::restoreOverrideCursor();
}
void Polyhedron_demo_repair_polyhedron_plugin::on_actionExtractNMVertices_triggered()
{
QApplication::setOverrideCursor(Qt::WaitCursor);
const Scene_interface::Item_id index = scene->mainSelectionIndex();
on_actionExtractNMVertices_triggered<Scene_surface_mesh_item>(index);
QApplication::restoreOverrideCursor();
}
template <typename Item>
void Polyhedron_demo_repair_polyhedron_plugin::on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered(Scene_interface::Item_id index)
{

View File

@ -9,7 +9,7 @@ void CGAL::Three::Polyhedron_demo_plugin_helper::addDockWidget(QDockWidget* dock
{
mw->addDockWidget(::Qt::LeftDockWidgetArea, dock_widget);
dock_widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
dock_widget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable);
QList<QDockWidget*> dockWidgets = mw->findChildren<QDockWidget*>();
int counter = 0;
Q_FOREACH(QDockWidget* dock, dockWidgets) {

View File

@ -90,6 +90,8 @@ Scene::addItem(CGAL::Three::Scene_item* item)
item->drawEdges(CGAL::Three::Three::mainViewer());
item->drawPoints(CGAL::Three::Three::mainViewer());
CGAL::Three::Three::mainViewer()->setDepthPeelingFbo(fbo);
if(group)
m_groups.append(id);
return id;
}
@ -110,6 +112,7 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi
QList<Scene_item*> group_children;
if(group)
{
m_groups.removeAll(index);
Q_FOREACH(Item_id id, group->getChildren())
{
CGAL::Three::Scene_item* child = group->getChild(id);
@ -152,6 +155,7 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi
if(group)
{
addGroup(group);
m_groups.append(index);
}
itemChanged(index);
Q_EMIT restoreCollapsedState();
@ -173,6 +177,7 @@ Scene::erase(Scene::Item_id index)
setSelectedItemsList(QList<Scene_interface::Item_id>()<<item_id(item));
return erase(selectionIndices());
}
m_groups.removeAll(index);
if(item->parentGroup()
&& item->parentGroup()->isChildLocked(item))
return -1;
@ -248,6 +253,7 @@ Scene::erase(QList<int> indices)
item->parentGroup()->removeChild(item);
children.removeAll(removed_item);
indexErased(removed_item);
m_groups.removeAll(removed_item);
m_entries.removeAll(item);
Q_EMIT itemAboutToBeDestroyed(item);
@ -1359,9 +1365,15 @@ QItemSelection Scene::createSelectionAll()
//it is not possible to directly create a selection with items that have different parents, so
//we do it iteratively.
QItemSelection sel;
for(int i=0; i< m_entries.size(); ++i)
sel.select(index_map.keys(i).at(0),
index_map.keys(i).at(4));
sel.select(this->createIndex(0, 0),
this->createIndex(m_entries.size(), LastColumn));
for(const auto& gid : m_groups)
{
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item(gid));
sel.select(index_map.keys(group->getChildren().first()).at(0),
index_map.keys(group->getChildren().last()).at(4));
}
return sel;
}
@ -1726,7 +1738,7 @@ void Scene::updatePrimitiveIds(CGAL::Three::Scene_item* it)
}
}
}
bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer)
bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler)
{
CGAL::Three::Scene_item *i = item(mainSelectionIndex());
if(!i)
@ -1734,7 +1746,7 @@ bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_inte
Scene_print_item_interface* spit= qobject_cast<Scene_print_item_interface*>(i);
if(spit && i->visible())
{
bool res = spit->testDisplayId(x,y,z, viewer);
bool res = spit->testDisplayId(x,y,z, viewer, scaler);
return res;
}
else

View File

@ -64,6 +64,7 @@ public:
int numberOfEntries() const Q_DECL_OVERRIDE;
// returns the list of items.
const QList<CGAL::Three::Scene_item*>& entries() const { return m_entries; }
Q_INVOKABLE CGAL::Three::Scene_item* item(int) const Q_DECL_OVERRIDE;
int item_id(CGAL::Three::Scene_item*) const Q_DECL_OVERRIDE;
@ -94,7 +95,7 @@ public:
void printAllIds() Q_DECL_OVERRIDE;
//!Re-computes the primitiveIds for `item`
void updatePrimitiveIds(Scene_item *item) Q_DECL_OVERRIDE;
bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) Q_DECL_OVERRIDE;
bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler) Q_DECL_OVERRIDE;
Bbox bbox() const Q_DECL_OVERRIDE;
void computeBbox();
double len_diagonal() const Q_DECL_OVERRIDE
@ -280,6 +281,7 @@ private:
typedef QList<CGAL::Three::Scene_item*> Entries;
//List containing all the scene_items.
Entries m_entries;
QList<Item_id> m_groups; //used to optimize createSelectionAll()
QList<Item_id> children;
// Index of the currently selected item.
int selected_item;

View File

@ -2254,9 +2254,9 @@ void Scene_polyhedron_selection_item::printAllIds()
{
d->item->polyhedron_item()->printAllIds();
}
bool Scene_polyhedron_selection_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer)const
bool Scene_polyhedron_selection_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler)const
{
return d->item->polyhedron_item()->testDisplayId(x, y, z, viewer);
return d->item->polyhedron_item()->testDisplayId(x, y, z, viewer, scaler);
return false;
}

View File

@ -218,7 +218,7 @@ public:
bool printEdgeIds() const;
bool printFaceIds() const;
void printAllIds();
bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*)const;
bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*, const QVector3D&)const;
bool shouldDisplayIds(CGAL::Three::Scene_item *current_item) const;
QString defaultSaveName() const
{

View File

@ -2130,7 +2130,7 @@ void Scene_surface_mesh_item::printAllIds()
d->killIds();
}
bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer)const
bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler)const
{
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
EPICK::Point_3 src(x - offset.x,
@ -2138,13 +2138,14 @@ bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL::
z - offset.z);
CGAL::qglviewer::Camera* cam = viewer->camera();
EPICK::Point_3 dest( cam->position().x - offset.x,
cam->position().y - offset.y,
cam->position().z - offset.z);
EPICK::Point_3 dest( cam->position().x/scaler.x() - offset.x,
cam->position().y/scaler.y() - offset.y,
cam->position().z/scaler.z() - offset.z);
EPICK::Vector_3 v(src,dest);
EPICK::Vector_3 dir(cam->viewDirection().x,
cam->viewDirection().y,
cam->viewDirection().z);
if(-CGAL::scalar_product(v, dir) < cam->zNear()) //if src is behind the near plane, don't display.
return false;
v = 0.01*v;

View File

@ -149,7 +149,7 @@ public:
bool printFaceIds()const Q_DECL_OVERRIDE;
void printAllIds() Q_DECL_OVERRIDE;
bool shouldDisplayIds(CGAL::Three::Scene_item *current_item) const Q_DECL_OVERRIDE;
bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface*)const Q_DECL_OVERRIDE;
bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface*, const QVector3D &scaler)const Q_DECL_OVERRIDE;
float alpha() const Q_DECL_OVERRIDE;
void setAlpha(int alpha) Q_DECL_OVERRIDE;
QSlider* alphaSlider();

View File

@ -2,7 +2,7 @@
#include <CGAL/Three/Scene_item.h>
#include <CGAL/Three/Scene_print_item_interface.h>
#include "Scene_polyhedron_selection_item.h"
void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer)
void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer, const QVector3D& scaler)
{
QPainter *painter = viewer->getPainter();
if (!painter->isActive())
@ -23,10 +23,15 @@ void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer)
if(viewer->testDisplayId(src.x, src.y, src.z))
{
if(item->is_3D())
rect = QRect(int(camera->projectedCoordinatesOf(src).x-item->width()/2),
int(camera->projectedCoordinatesOf(src).y-item->height()/2),
{
src.x *= scaler.x();
src.y *= scaler.y();
src.z *= scaler.z();
rect = QRect(int(camera->projectedCoordinatesOf(src).x -item->width()/2),
int(camera->projectedCoordinatesOf(src).y -item->height()/2),
int(item->width()),
int(item->height()));
}
else
rect = QRect(int(src.x-item->width()/2),
int(src.y-item->height()/2),

View File

@ -17,6 +17,7 @@
#include <QOpenGLDebugLogger>
#include <QStyleFactory>
#include <QAction>
#include <QMultipleInputDialog.h>
#include <QRegularExpressionMatch>
#ifdef CGAL_USE_WEBSOCKETS
#include <QtWebSockets/QWebSocket>
@ -25,6 +26,7 @@
#include <CGAL/Three/Three.h>
#include "ui_LightingDialog.h"
#include "CGAL_double_edit.h"
#if defined(_WIN32)
#include <QMimeData>
@ -46,8 +48,10 @@ public:
bool clipping;
bool projection_is_ortho;
bool cam_sharing;
bool scene_scaling;
GLfloat gl_point_size;
QVector4D clipbox[6];
QVector3D scaler;
QPainter *painter;
// L i g h t i n g
@ -117,6 +121,7 @@ public:
{
return shader_programs;
}
#ifdef CGAL_USE_WEBSOCKETS
QWebSocket m_webSocket;
#endif
@ -292,6 +297,8 @@ void Viewer::doBindings()
d->textRenderer = new TextRenderer();
d->is_2d_selection_mode = false;
d->is_connected = false;
d->scene_scaling = false;
d->scaler = QVector3D(1,1,1);
connect( d->textRenderer, SIGNAL(sendMessage(QString,int)),
this, SLOT(printMessage(QString,int)) );
@ -407,7 +414,7 @@ Viewer::~Viewer()
.arg(d->back_color.redF())
.arg(d->back_color.greenF())
.arg(d->back_color.blueF()));
makeCurrent();
d->vao.destroy();
if(d->_recentFunctions)
delete d->_recentFunctions;
@ -831,9 +838,23 @@ void Viewer::postSelection(const QPoint& pixel)
point = camera()->pointUnderPixel(pixel, found) - offset();
}
if(found) {
Q_EMIT selectedPoint(point.x,
point.y,
point.z);
QVector3D transformed_point(point.x,
point.y,
point.z);
if(d->scene_scaling)
{
transformed_point = QVector3D(
point.x+offset().x,
point.y+offset().y,
point.z+offset().z);
transformed_point = transformed_point/d->scaler;
transformed_point[0] -=offset().x ;
transformed_point[1] -=offset().y ;
transformed_point[2] -=offset().z ;
}
Q_EMIT selectedPoint(transformed_point.x(),
transformed_point.y(),
transformed_point.z());
CGAL::qglviewer::Vec dir;
CGAL::qglviewer::Vec orig;
if(d->projection_is_ortho)
@ -931,6 +952,10 @@ void Viewer::attribBuffers(int program_name) const {
this->camera()->getModelViewProjectionMatrix(d_mat);
for (int i=0; i<16; ++i)
mvp_mat.data()[i] = GLfloat(d_mat[i]);
if(d->scene_scaling){
mvp_mat.scale(d->scaler);
mv_mat.scale(d->scaler);
}
QOpenGLShaderProgram* program = getShaderProgram(program_name);
program->bind();
@ -1130,7 +1155,7 @@ void Viewer::drawVisualHints()
{
d->textRenderer->addText(message_text);
}
d->textRenderer->draw(this);
d->textRenderer->draw(this, d->scaler);
if (d->_displayMessage)
d->textRenderer->removeText(message_text);
@ -1458,7 +1483,7 @@ void Viewer::wheelEvent(QWheelEvent* e)
bool Viewer::testDisplayId(double x, double y, double z)
{
return d->scene->testDisplayId(x,y,z,this);
return d->scene->testDisplayId(x,y,z,this, d->scaler);
}
QPainter* Viewer::getPainter(){return d->painter;}
@ -1552,26 +1577,26 @@ void Viewer_impl::showDistance(QPoint pixel)
rendering_program_dist.setAttributeBuffer("vertex",GL_FLOAT,0,3);
buffer.release();
vao.release();
distance_is_displayed = true;
double dist = std::sqrt((BPoint.x-APoint.x)*(BPoint.x-APoint.x) + (BPoint.y-APoint.y)*(BPoint.y-APoint.y) + (BPoint.z-APoint.z)*(BPoint.z-APoint.z));
double dist = std::sqrt((BPoint.x-APoint.x)/scaler.x()*(BPoint.x-APoint.x)/scaler.x() + (BPoint.y-APoint.y)/scaler.y()*(BPoint.y-APoint.y)/scaler.y() + (BPoint.z-APoint.z)/scaler.z()*(BPoint.z-APoint.z)/scaler.z());
QFont font;
font.setBold(true);
TextItem *ACoord = new TextItem(float(APoint.x),
float(APoint.y),
float(APoint.z),
QString("A(%1,%2,%3)")
.arg(APoint.x-viewer->offset().x, 0, 'g', 10)
.arg(APoint.y-viewer->offset().y, 0, 'g', 10)
.arg(APoint.z-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true);
.arg(APoint.x/scaler.x()-viewer->offset().x, 0, 'g', 10)
.arg(APoint.y/scaler.y()-viewer->offset().y, 0, 'g', 10)
.arg(APoint.z/scaler.z()-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true);
distance_text.append(ACoord);
TextItem *BCoord = new TextItem(float(BPoint.x),
float(BPoint.y),
float(BPoint.z),
QString("B(%1,%2,%3)")
.arg(BPoint.x-viewer->offset().x, 0, 'g', 10)
.arg(BPoint.y-viewer->offset().y, 0, 'g', 10)
.arg(BPoint.z-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true);
.arg(BPoint.x/scaler.x()-viewer->offset().x, 0, 'g', 10)
.arg(BPoint.y/scaler.y()-viewer->offset().y, 0, 'g', 10)
.arg(BPoint.z/scaler.z()-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true);
distance_text.append(BCoord);
CGAL::qglviewer::Vec centerPoint = 0.5*(BPoint+APoint);
TextItem *centerCoord = new TextItem(float(centerPoint.x),
@ -1583,12 +1608,12 @@ void Viewer_impl::showDistance(QPoint pixel)
Q_FOREACH(TextItem* ti, distance_text)
textRenderer->addText(ti);
Q_EMIT(viewer->sendMessage(QString("First point : A(%1,%2,%3), second point : B(%4,%5,%6), distance between them : %7")
.arg(APoint.x-viewer->offset().x)
.arg(APoint.y-viewer->offset().y)
.arg(APoint.z-viewer->offset().z)
.arg(BPoint.x-viewer->offset().x)
.arg(BPoint.y-viewer->offset().y)
.arg(BPoint.z-viewer->offset().z)
.arg(APoint.x/scaler.x()-viewer->offset().x)
.arg(APoint.y/scaler.y()-viewer->offset().y)
.arg(APoint.z/scaler.z()-viewer->offset().z)
.arg(BPoint.x/scaler.x()-viewer->offset().x)
.arg(BPoint.y/scaler.y()-viewer->offset().y)
.arg(BPoint.z/scaler.z()-viewer->offset().z)
.arg(dist, 0, 'g', 10)));
}
@ -1958,6 +1983,56 @@ bool Viewer::isClipping() const
{
return d->clipping;
}
void Viewer::scaleScene()
{
CGAL::Bbox_3 bbox = CGAL::Three::Three::scene()->bbox();
if(!d->scene_scaling)
{
QMultipleInputDialog dialog ("Scale Scene", CGAL::Three::Three::mainWindow());
DoubleEdit* x_val = dialog.add<DoubleEdit> ("Scale along X");
DoubleEdit* y_val = dialog.add<DoubleEdit> ("Scale along Y");
DoubleEdit* z_val = dialog.add<DoubleEdit> ("Scale along Z");
x_val->setMinimum(0);
y_val->setMinimum(0);
z_val->setMinimum(0);
if(bbox != CGAL::Bbox_3(0,0,0,0,0,0))
{
QPushButton* norm_button = dialog.add<QPushButton> ("");
norm_button->setText("Normalize");
norm_button->setToolTip("Automatically fill values to display the scene in a unit cube.");
connect(norm_button, &QPushButton::clicked, this,
[x_val, y_val, z_val, &bbox](){
x_val->setValue(1.0/(bbox.xmax()-bbox.xmin()));
y_val->setValue(1.0/(bbox.ymax()-bbox.ymin()));
z_val->setValue(1.0/(bbox.zmax()-bbox.zmin()));
});
}
if (dialog.exec() != QDialog::Accepted)
{
parent()->findChild<QAction*>("actionScaleScene")->setChecked(false);
return;
}
d->scaler.setX(x_val->text()==""?1.0:x_val->value());
d->scaler.setY(y_val->text()==""?1.0:y_val->value());
d->scaler.setZ(z_val->text()==""?1.0:z_val->value());
if(d->scaler.x() == 0.0 || d->scaler.y() == 0.0 || d->scaler.z()== 0.0)
{
parent()->findChild<QAction*>("actionScaleScene")->setChecked(false);
return;
}
}
else
d->scaler = QVector3D(1,1,1);
CGAL::qglviewer::Vec vmin(((float)bbox.xmin()+offset().x)*d->scaler.x(), ((float)bbox.ymin()+offset().y)*d->scaler.y(), ((float)bbox.zmin()+offset().z)*d->scaler.z()),
vmax(((float)bbox.xmax()+offset().x)*d->scaler.x(), ((float)bbox.ymax()+offset().y)*d->scaler.y(), ((float)bbox.zmax()+offset().z)*d->scaler.z());
camera()->setPivotPoint((vmin+vmax)*0.5);
camera()->fitBoundingBox(vmin, vmax);
d->scene_scaling = !d->scene_scaling;
}
#ifdef CGAL_USE_WEBSOCKETS
void Viewer::setShareCam(bool b, QString session)
{

View File

@ -137,7 +137,7 @@ public Q_SLOTS:
void onSocketConnected();
void onTextMessageSocketReceived(QString message);
#endif
void scaleScene();
protected:
void paintEvent(QPaintEvent *)Q_DECL_OVERRIDE;
void paintGL()Q_DECL_OVERRIDE;

View File

@ -61,7 +61,7 @@ public:
* \param z the Z coordinate of theTextItem's position.
* \param viewer the viewer used to display the Scene.
* \return true if the TextItem is visible. */
virtual bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) = 0;
virtual bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler) = 0;
///\brief displays all the vertices ids if there are less than max_textItems.
virtual void printVertexIds() = 0;

View File

@ -48,7 +48,7 @@ public:
//!
//! \returns true if the Id should be displayed
//! \returns false if the Id should not be displayed (if it is hidden for example)
virtual bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*)const = 0;
virtual bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*, const QVector3D& scaler)const = 0;
//! \brief Tests if this item should display its ids.
//!

View File

@ -139,7 +139,7 @@ public:
{
}
//!Draws all the `TextItem`s
void draw(CGAL::Three::Viewer_interface* viewer);
void draw(CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler);
//!\brief Adds a single TextItem to TextRenderer::local_textItems
//!
//! @see addText(float p_x, float p_y, float p_z, QString p_text, bool p_3D = true, QFont font = QFont(), QColor p_color = Qt::black)