mirror of https://github.com/CGAL/cgal
805 lines
27 KiB
C++
805 lines
27 KiB
C++
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
#include <CGAL/bounding_box.h>
|
|
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
|
#include <CGAL/boost/graph/copy_face_graph.h>
|
|
#include <CGAL/algorithm.h>
|
|
#include <CGAL/Three/Scene_item_rendering_helper.h>
|
|
#include <CGAL/Three/Three.h>
|
|
#include <CGAL/Three/Point_container.h>
|
|
|
|
#include <CGAL/Polygon_mesh_processing/transform.h>
|
|
#include "Scene_surface_mesh_item.h"
|
|
|
|
#include "Scene_facegraph_transform_item.h"
|
|
#include "Scene_points_with_normal_item.h"
|
|
#include "Scene_polylines_item.h"
|
|
|
|
#include <QString>
|
|
#include <QAction>
|
|
#include <QMenu>
|
|
#include <QMainWindow>
|
|
#include <QDockWidget>
|
|
#include <QDialog>
|
|
#include <QApplication>
|
|
#include <QElapsedTimer>
|
|
#include <QMessageBox>
|
|
|
|
#include "ui_Transformation_widget.h"
|
|
|
|
using namespace CGAL::Three;
|
|
typedef Viewer_interface Vi;
|
|
typedef Point_container Pc;
|
|
|
|
#include "ui_MeshOnGrid_dialog.h"
|
|
typedef Scene_surface_mesh_item Facegraph_item;
|
|
|
|
|
|
class Scene_transform_point_set_item : public Scene_item_rendering_helper
|
|
{
|
|
Q_OBJECT
|
|
typedef Point_set_3<Kernel> Point_set;
|
|
public:
|
|
Scene_transform_point_set_item(Scene_points_with_normal_item *item, const CGAL::qglviewer::Vec& pos)
|
|
: base(item),
|
|
center_(pos),
|
|
frame(new CGAL::Three::Scene_item::ManipulatedFrame())
|
|
{
|
|
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
|
|
frame->setPosition(pos+offset);
|
|
Point_set ps= *item->point_set();
|
|
const Kernel::Point_3& p = ps.point(*(ps.begin()));
|
|
CGAL::Bbox_3 bbox(p.x(), p.y(), p.z(), p.x(), p.y(), p.z());
|
|
CGAL::cpp98::random_shuffle (ps.begin(), ps.end());
|
|
points.reserve(3*ps.size());
|
|
for (Point_set::const_iterator it = ps.begin(); it != ps.first_selected(); it++)
|
|
{
|
|
const Kernel::Point_3& p = ps.point(*it);
|
|
bbox = bbox + p.bbox();
|
|
points.push_back(p.x()-center_.x);
|
|
points.push_back(p.y()-center_.y);
|
|
points.push_back(p.z()-center_.z);
|
|
}
|
|
setPointContainer(0, new Pc(Vi::PROGRAM_NO_SELECTION, false));
|
|
setBbox(Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(),
|
|
bbox.xmax(),bbox.ymax(),bbox.zmax()));
|
|
|
|
nb_points = points.size();
|
|
for(auto v : CGAL::QGLViewer::QGLViewerPool())
|
|
{
|
|
CGAL::Three::Viewer_interface* viewer = static_cast<CGAL::Three::Viewer_interface*>(v);
|
|
initGL(viewer);
|
|
}
|
|
Pc* pc = getPointContainer(0);
|
|
pc->allocate(Pc::Vertices,
|
|
points.data(),
|
|
static_cast<int>(points.size()*sizeof(float)));
|
|
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
|
initializeBuffers(qobject_cast<Vi*>(v));
|
|
}
|
|
|
|
void initializeBuffers(Viewer_interface *v) const
|
|
{
|
|
Pc* pc = getPointContainer(0);
|
|
pc->initializeBuffers(v);
|
|
pc->setFlatDataSize(nb_points);
|
|
points.clear();
|
|
points.shrink_to_fit();
|
|
}
|
|
bool manipulatable() const { return true; }
|
|
|
|
Scene_item* clone()const{ return NULL; }
|
|
|
|
bool supportsRenderingMode(RenderingMode m) const { return m==Points ; }
|
|
|
|
QString toolTip() const {
|
|
return QObject::tr("<p>Affine transformation of <b>%1</b></p>"
|
|
"<p>Keep <b>Ctrl</b> pressed and use the arcball to define an affine transformation.<br />"
|
|
"Press <b>S</b> to apply the affine transformation to a copy of <b>%1</b>.</p>")
|
|
.arg(getBase()->name());
|
|
}
|
|
|
|
void setFMatrix(double matrix[16])
|
|
{
|
|
for (int i=0; i<16; ++i)
|
|
f_matrix.data()[i] = (float)matrix[i];
|
|
}
|
|
|
|
~Scene_transform_point_set_item() {delete frame; Q_EMIT killed(); }
|
|
void drawPoints(Viewer_interface *viewer) const
|
|
{
|
|
GLfloat point_size;
|
|
viewer->glGetFloatv(GL_POINT_SIZE, &point_size);
|
|
viewer->setGlPointSize(6.f);
|
|
double ratio_displayed = 1.0;
|
|
if ((viewer->inFastDrawing () || frame->isManipulated()) &&
|
|
(nb_points /3 > 300000)) // arbitrary large value
|
|
ratio_displayed = 3 * 300000. / (double)nb_points;
|
|
|
|
Pc* pc = getPointContainer(0);
|
|
std::size_t real_size = pc->getFlatDataSize();
|
|
pc->setFlatDataSize(ratio_displayed * real_size);
|
|
pc->setColor(QColor(Qt::green));
|
|
pc->setFrameMatrix(f_matrix);
|
|
pc->draw(viewer, true);
|
|
pc->setFlatDataSize(real_size);
|
|
}
|
|
bool keyPressEvent(QKeyEvent* e){
|
|
if (e->key()==Qt::Key_S){
|
|
Q_EMIT stop();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
const Scene_points_with_normal_item* getBase()const{return base;}
|
|
const CGAL::qglviewer::Vec& center() const { return center_; }
|
|
CGAL::Three::Scene_item::ManipulatedFrame* manipulatedFrame() { return frame; }
|
|
void compute_bbox() const
|
|
{
|
|
Point_set ps= *base->point_set();
|
|
const Kernel::Point_3& p = ps.point(*(ps.begin()));
|
|
CGAL::Bbox_3 bbox(p.x(), p.y(), p.z(), p.x(), p.y(), p.z());
|
|
|
|
for (Point_set::const_iterator it = ps.begin(); it != ps.first_selected(); it++)
|
|
{
|
|
bbox = bbox + ps.point(*it).bbox();
|
|
}
|
|
CGAL::qglviewer::Vec v_min(bbox.xmin(),bbox.ymin(),bbox.zmin());
|
|
CGAL::qglviewer::Vec v_max(bbox.xmax(),bbox.ymax(),bbox.zmax());
|
|
|
|
setBbox(Bbox(v_min.x,v_min.y,v_min.z,
|
|
v_max.x,v_max.y,v_max.z));
|
|
}
|
|
bool isEmpty() const{return false;}
|
|
Q_SIGNALS:
|
|
void stop();
|
|
void killed();
|
|
private:
|
|
const Scene_points_with_normal_item* base;
|
|
CGAL::qglviewer::Vec center_;
|
|
CGAL::Three::Scene_item::ManipulatedFrame* frame;
|
|
mutable std::vector<float> points;
|
|
std::size_t nb_points;
|
|
QMatrix4x4 f_matrix;
|
|
|
|
};
|
|
|
|
using namespace CGAL::Three;
|
|
class Polyhedron_demo_affine_transform_plugin :
|
|
public QObject,
|
|
public Polyhedron_demo_plugin_helper
|
|
{
|
|
Q_OBJECT
|
|
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
|
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
|
|
|
public:
|
|
|
|
Polyhedron_demo_affine_transform_plugin():started(false){}
|
|
|
|
QList<QAction*> actions() const {
|
|
return QList<QAction*>() << actionTransformPolyhedron
|
|
<< actionMeshOnGrid;
|
|
}
|
|
|
|
bool applicable(QAction* a) const {
|
|
if(a == actionMeshOnGrid)
|
|
{
|
|
return qobject_cast<Facegraph_item*>(scene->item(scene->mainSelectionIndex()));
|
|
}
|
|
else
|
|
return qobject_cast<Facegraph_item*>(scene->item(scene->mainSelectionIndex()))
|
|
|| qobject_cast<Scene_facegraph_transform_item*>(scene->item(scene->mainSelectionIndex()))
|
|
|| qobject_cast<Scene_points_with_normal_item*>(scene->item(scene->mainSelectionIndex()))
|
|
|| qobject_cast<Scene_transform_point_set_item*>(scene->item(scene->mainSelectionIndex()));
|
|
}
|
|
|
|
void init(QMainWindow* _mw, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) {
|
|
for(int i=0; i<3; ++i)
|
|
{
|
|
scaling[i] = 1;
|
|
lastScaling[i] = 1 ;
|
|
}
|
|
lastMatrix.setToIdentity();
|
|
mw = _mw;
|
|
this->scene = scene_interface;
|
|
|
|
actionMeshOnGrid = new QAction(
|
|
tr("Create a Grid of Surface Meshes")
|
|
, mw);
|
|
if(actionMeshOnGrid) {
|
|
connect(actionMeshOnGrid, SIGNAL(triggered()),this, SLOT(grid()));
|
|
}
|
|
|
|
actionTransformPolyhedron = new QAction(
|
|
tr("Affine Transformation")
|
|
, mw);
|
|
if(actionTransformPolyhedron) {
|
|
connect(actionTransformPolyhedron, SIGNAL(triggered()),this, SLOT(go()));
|
|
}
|
|
transform_item = NULL;
|
|
transform_points_item = NULL;
|
|
|
|
dock_widget = new QDockWidget(
|
|
tr("Affine Transformation")
|
|
, mw);
|
|
ui.setupUi(dock_widget);
|
|
dock_widget->setWindowTitle(tr(
|
|
"Affine Transformation"
|
|
));
|
|
addDockWidget(dock_widget);
|
|
dock_widget->hide();
|
|
|
|
QList<QLineEdit*> lineEdits;
|
|
lineEdits<<ui.lineEditA<<ui.lineEditX<<ui.lineEditY<<ui.lineEditZ;
|
|
Q_FOREACH(QLineEdit* widget, lineEdits)
|
|
{
|
|
QSizePolicy sp_retain = widget->sizePolicy();
|
|
sp_retain.setRetainSizeWhenHidden(true);
|
|
widget->setSizePolicy(sp_retain);
|
|
}
|
|
connect(ui.applyTransfo_Button, &QPushButton::clicked,
|
|
this, &Polyhedron_demo_affine_transform_plugin::applySingleTransformation);
|
|
connect(ui.transfo_ComboBox, SIGNAL(currentIndexChanged(int)),
|
|
this, SLOT(updateSingleTransfoValues(int)));
|
|
connect(ui.resetMatrix_Button, &QPushButton::clicked,
|
|
this, &Polyhedron_demo_affine_transform_plugin::resetTransformMatrix);
|
|
connect(ui.clearButton, &QPushButton::clicked,
|
|
this, &Polyhedron_demo_affine_transform_plugin::clear);
|
|
connect(ui.undoButton, &QPushButton::clicked,
|
|
this, &Polyhedron_demo_affine_transform_plugin::undo);
|
|
connect(ui.validatePushButton, &QPushButton::clicked,
|
|
this, &Polyhedron_demo_affine_transform_plugin::end);
|
|
//initial state is Translation: no need for this one
|
|
ui.lineEditA->hide();
|
|
}
|
|
|
|
void start(FaceGraph *facegraph, const QString name, const Scene_item::Bbox&);
|
|
void start(Scene_points_with_normal_item*);
|
|
void end();
|
|
void closure()
|
|
{
|
|
dock_widget->hide();
|
|
}
|
|
|
|
private:
|
|
QDockWidget* dock_widget;
|
|
Ui::TransformationWidget ui;
|
|
QAction* actionTransformPolyhedron;
|
|
QAction* actionMeshOnGrid;
|
|
Scene_facegraph_transform_item* transform_item;
|
|
Scene_transform_point_set_item* transform_points_item;
|
|
CGAL::Three::Scene_interface::Item_id tr_item_index;
|
|
CGAL::Three::Scene_interface* scene;
|
|
bool started;
|
|
double scaling[3];
|
|
double lastScaling[3];
|
|
QMatrix4x4 lastMatrix;
|
|
|
|
//takes a double[16]
|
|
void transformMatrix( double* res)const
|
|
{
|
|
bool is_point_set = false;
|
|
if(!transform_item)
|
|
{
|
|
if(transform_points_item)
|
|
is_point_set = true;
|
|
}
|
|
|
|
QMatrix4x4 tMatrix, manipulatedMatrix, scalingMatrix;
|
|
if(!is_point_set)
|
|
for(int i=0; i<16; ++i)
|
|
{
|
|
manipulatedMatrix.data()[i] = transform_item->manipulatedFrame()->matrix()[i];
|
|
scalingMatrix.data()[i] = 0;
|
|
}
|
|
else
|
|
for(int i=0; i<16; ++i)
|
|
{
|
|
manipulatedMatrix.data()[i] = transform_points_item->manipulatedFrame()->matrix()[i];
|
|
scalingMatrix.data()[i] = 0;
|
|
}
|
|
scalingMatrix.data()[0] = scaling[0];
|
|
scalingMatrix.data()[5] = scaling[1];
|
|
scalingMatrix.data()[10] = scaling[2];
|
|
scalingMatrix.data()[15] = 1;
|
|
tMatrix = manipulatedMatrix*scalingMatrix;
|
|
for(int i=0; i<16; ++i)
|
|
res[i] = (double)tMatrix.data()[i];
|
|
}
|
|
template<class Item>
|
|
void normalize(Item*);
|
|
public Q_SLOTS:
|
|
void grid();
|
|
void go();
|
|
void transformed_killed();
|
|
|
|
void updateUiMatrix();
|
|
void clear()
|
|
{
|
|
ui.lineEditA->clear();
|
|
ui.lineEditX->clear();
|
|
ui.lineEditY->clear();
|
|
ui.lineEditZ->clear();
|
|
}
|
|
void resetTransformMatrix()
|
|
{
|
|
bool is_point_set = false;
|
|
if(!transform_item)
|
|
{
|
|
if(transform_points_item)
|
|
is_point_set = true;
|
|
else
|
|
return;
|
|
}
|
|
double matrix[16] = {0};
|
|
scaling[0]=scaling[1]=scaling[2]=1.0;
|
|
matrix[0]=1; matrix[5] = 1; matrix[10] = 1; matrix[15] = 1;
|
|
matrix[12] = is_point_set ? transform_points_item->center().x : transform_item->center().x;
|
|
matrix[13] = is_point_set ? transform_points_item->center().y : transform_item->center().y;
|
|
matrix[14] = is_point_set ? transform_points_item->center().z : transform_item->center().z;
|
|
|
|
if(!is_point_set)
|
|
{
|
|
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
|
|
transform_item->manipulatedFrame()->setFromMatrix(matrix);
|
|
transform_item->manipulatedFrame()->translate(offset);
|
|
transform_item->itemChanged();
|
|
}
|
|
else
|
|
{
|
|
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
|
|
transform_points_item->manipulatedFrame()->setFromMatrix(matrix);
|
|
transform_points_item->manipulatedFrame()->translate(offset);
|
|
transform_points_item->itemChanged();
|
|
}
|
|
}
|
|
void updateSingleTransfoValues(int);
|
|
void applySingleTransformation();
|
|
void resetItems()
|
|
{
|
|
transform_item = NULL;
|
|
transform_points_item = NULL;
|
|
}
|
|
void undo()
|
|
{
|
|
bool is_point_set = false;
|
|
if(!transform_item)
|
|
{
|
|
if(transform_points_item)
|
|
is_point_set = true;
|
|
else
|
|
return;
|
|
}
|
|
|
|
double matrix[16];
|
|
for(short i = 0; i<16; ++i)
|
|
matrix[i] = (double)lastMatrix.data()[i];
|
|
|
|
for(short i = 0; i< 3; ++i)
|
|
scaling[i] = lastScaling[i];
|
|
|
|
if(!is_point_set)
|
|
{
|
|
transform_item->manipulatedFrame()->setFromMatrix(matrix);
|
|
transform_item->itemChanged();
|
|
}
|
|
else
|
|
{
|
|
transform_points_item->manipulatedFrame()->setFromMatrix(matrix);
|
|
transform_points_item->itemChanged();
|
|
}
|
|
}
|
|
|
|
}; // end class Polyhedron_demo_affine_transform_plugin
|
|
|
|
class GridDialog :
|
|
public QDialog,
|
|
public Ui::GridDialog
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
GridDialog(QWidget* =0)
|
|
{
|
|
setupUi(this);
|
|
}
|
|
};
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::grid()
|
|
{
|
|
Facegraph_item* item =
|
|
qobject_cast<Facegraph_item*>(scene->item(scene->mainSelectionIndex()));
|
|
if(!item)
|
|
return;
|
|
|
|
|
|
FaceGraph m = *item->face_graph();
|
|
|
|
Scene_item::Bbox b = item->bbox();
|
|
|
|
|
|
double x_t(1.001*((b.max)(0)- (b.min)(0))),
|
|
y_t(1.001*((b.max)(1)- (b.min)(1))),
|
|
z_t(1.001*((b.max)(2)- (b.min)(2)));
|
|
|
|
GridDialog dialog(mw);
|
|
dialog.x_space_doubleSpinBox->setValue(x_t);
|
|
dialog.y_space_doubleSpinBox->setValue(y_t);
|
|
dialog.z_space_doubleSpinBox->setValue(z_t);
|
|
if(!dialog.exec())
|
|
return;
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
int i_max=dialog.x_spinBox->value(),
|
|
j_max=dialog.y_spinBox->value(),
|
|
k_max=dialog.z_spinBox->value();
|
|
x_t = dialog.x_space_doubleSpinBox->value();
|
|
y_t = dialog.y_space_doubleSpinBox->value();
|
|
z_t = dialog.z_space_doubleSpinBox->value();
|
|
|
|
for(int i = 0; i < i_max; ++i)
|
|
{
|
|
for(int j = 0; j< j_max; ++j)
|
|
{
|
|
for(int k = 0; k< k_max; ++k)
|
|
{
|
|
FaceGraph e;
|
|
CGAL::copy_face_graph(m,e);
|
|
|
|
Kernel::Aff_transformation_3 trans(CGAL::TRANSLATION, Kernel::Vector_3(i*x_t,j*y_t,k*z_t));
|
|
CGAL::Polygon_mesh_processing::transform(trans, e);
|
|
Facegraph_item* t_item = new Facegraph_item(e);
|
|
t_item->setName(tr("%1 %2,%3,%4")
|
|
.arg(item->name())
|
|
.arg(i)
|
|
.arg(j)
|
|
.arg(k));
|
|
scene->addItem(t_item);
|
|
}
|
|
}
|
|
}
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
void Polyhedron_demo_affine_transform_plugin::go(){
|
|
if (!started){
|
|
Scene_item* item = scene->item(scene->mainSelectionIndex());
|
|
Scene_points_with_normal_item* points_item = NULL;
|
|
Facegraph_item* poly_item = qobject_cast<Facegraph_item*>(item);
|
|
if(!poly_item)
|
|
{
|
|
points_item = qobject_cast<Scene_points_with_normal_item*>(item);
|
|
if(!points_item)
|
|
return;
|
|
}
|
|
dock_widget->show();
|
|
dock_widget->raise();
|
|
started=true;
|
|
actionTransformPolyhedron->setText("Apply affine transformation");
|
|
if(poly_item)
|
|
{
|
|
start(poly_item->polyhedron(), poly_item->name(), poly_item->bbox());
|
|
}
|
|
else if(points_item)
|
|
start(points_item);
|
|
ui.validatePushButton->setEnabled(true);
|
|
}
|
|
else
|
|
end();
|
|
}
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::transformed_killed(){
|
|
started=false;
|
|
actionTransformPolyhedron->setText("Affine Transformation");
|
|
}
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::start(FaceGraph *facegraph, const QString name, const Scene_item::Bbox &bbox){
|
|
QApplication::setOverrideCursor(Qt::PointingHandCursor);
|
|
|
|
double x=(bbox.xmin()+bbox.xmax())/2;
|
|
double y=(bbox.ymin()+bbox.ymax())/2;
|
|
double z=(bbox.zmin()+bbox.zmax())/2;
|
|
lastMatrix.setToIdentity();
|
|
lastMatrix.data()[12] = x;
|
|
lastMatrix.data()[13] = y;
|
|
lastMatrix.data()[14] = z;
|
|
transform_item = new Scene_facegraph_transform_item(CGAL::qglviewer::Vec(x,y,z),facegraph, name);
|
|
connect(transform_item, &Scene_item::aboutToBeDestroyed,
|
|
[](){ QApplication::restoreOverrideCursor(); });
|
|
transform_item->setManipulatable(true);
|
|
transform_item->setColor(Qt::green);
|
|
transform_item->setRenderingMode(Wireframe);
|
|
transform_item->setName(tr("Affine Transformation"));
|
|
scaling[0] = 1;
|
|
scaling[1] = 1;
|
|
scaling[2] = 1;
|
|
connect(transform_item, SIGNAL(stop()),this, SLOT(go()));
|
|
connect(transform_item, SIGNAL(killed()),this, SLOT(transformed_killed()));
|
|
connect(transform_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified,
|
|
this, &Polyhedron_demo_affine_transform_plugin::updateUiMatrix);
|
|
connect(transform_item, &Scene_facegraph_transform_item::aboutToBeDestroyed,
|
|
dock_widget, &QDockWidget::hide);
|
|
connect(transform_item, &Scene_facegraph_transform_item::aboutToBeDestroyed,
|
|
this, &Polyhedron_demo_affine_transform_plugin::resetItems);
|
|
tr_item_index=scene->addItem(transform_item);
|
|
scene->setSelectedItem(tr_item_index);
|
|
resetTransformMatrix();
|
|
}
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::start(Scene_points_with_normal_item* points_item){
|
|
QApplication::setOverrideCursor(Qt::PointingHandCursor);
|
|
|
|
Scene_points_with_normal_item::Bbox bbox = points_item->bbox();
|
|
double x=(bbox.xmin()+bbox.xmax())/2;
|
|
double y=(bbox.ymin()+bbox.ymax())/2;
|
|
double z=(bbox.zmin()+bbox.zmax())/2;
|
|
lastMatrix.setToIdentity();
|
|
lastMatrix.data()[12] = x;
|
|
lastMatrix.data()[13] = y;
|
|
lastMatrix.data()[14] = z;
|
|
|
|
transform_points_item = new Scene_transform_point_set_item(points_item,CGAL::qglviewer::Vec(x,y,z));
|
|
connect(transform_points_item, &Scene_item::aboutToBeDestroyed,
|
|
[](){ QApplication::restoreOverrideCursor(); });
|
|
transform_points_item->setRenderingMode(Points);
|
|
transform_points_item->setName(tr("Affine Transformation"));
|
|
connect(transform_points_item, SIGNAL(stop()),this, SLOT(go()));
|
|
connect(transform_points_item, SIGNAL(killed()),this, SLOT(transformed_killed()));
|
|
connect(transform_points_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified,
|
|
this, &Polyhedron_demo_affine_transform_plugin::updateUiMatrix);
|
|
connect(transform_points_item, &Scene_transform_point_set_item::aboutToBeDestroyed,
|
|
dock_widget, &QDockWidget::hide);
|
|
connect(transform_points_item, &Scene_transform_point_set_item::aboutToBeDestroyed,
|
|
this, &Polyhedron_demo_affine_transform_plugin::resetItems);
|
|
tr_item_index=scene->addItem(transform_points_item);
|
|
scene->setSelectedItem(tr_item_index);
|
|
resetTransformMatrix();
|
|
}
|
|
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::end(){
|
|
ui.validatePushButton->setEnabled(false);
|
|
QApplication::restoreOverrideCursor();
|
|
double matrix[16];
|
|
transformMatrix(&matrix[0]);
|
|
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
|
|
matrix[12]-=offset.x;
|
|
matrix[13]-=offset.y;
|
|
matrix[14]-=offset.z;
|
|
resetTransformMatrix();
|
|
QMatrix4x4 transform_matrix;
|
|
for(int i=0; i<16; ++i)
|
|
transform_matrix.data()[i] = (float)matrix[i];
|
|
|
|
if(transform_item)
|
|
{
|
|
CGAL::qglviewer::Vec c = transform_item->center();
|
|
FaceGraph* new_sm = new FaceGraph();
|
|
CGAL::copy_face_graph(*transform_item->getFaceGraph(), *new_sm);
|
|
typedef boost::property_map<FaceGraph,CGAL::vertex_point_t>::type VPmap;
|
|
VPmap vpmap = get(CGAL::vertex_point, *new_sm);
|
|
|
|
for (boost::graph_traits<FaceGraph>::vertex_iterator it=vertices(*new_sm).begin(),
|
|
endit=vertices(*new_sm).end();endit!=it;++it)
|
|
{
|
|
QVector3D vec = transform_matrix * QVector3D(get(vpmap, *it).x() - c.x,
|
|
get(vpmap, *it).y() - c.y,
|
|
get(vpmap, *it).z() - c.z);
|
|
|
|
put(vpmap, *it, Kernel::Point_3 (vec.x(), vec.y(), vec.z()));
|
|
}
|
|
Facegraph_item* new_item=new Facegraph_item(new_sm);
|
|
new_item->setName(tr("%1_transformed").arg(transform_item->name()));
|
|
scene->replaceItem(tr_item_index,new_item);
|
|
delete transform_item;
|
|
transform_item = NULL;
|
|
}
|
|
else if(transform_points_item)
|
|
{
|
|
Scene_points_with_normal_item* new_item
|
|
= new Scene_points_with_normal_item (*(transform_points_item->getBase()));
|
|
Point_set* new_ps = new_item->point_set();
|
|
CGAL::qglviewer::Vec c = transform_points_item->center();
|
|
|
|
for(Point_set::Index idx : *new_ps)
|
|
{
|
|
QVector3D vec = transform_matrix * QVector3D(new_ps->point(idx).x() - c.x,
|
|
new_ps->point(idx).y() - c.y,
|
|
new_ps->point(idx).z() - c.z);
|
|
new_ps->point(idx) = Kernel::Point_3 (vec.x(), vec.y(), vec.z());
|
|
}
|
|
|
|
new_item->setName(tr("%1_transformed").arg(transform_points_item->getBase()->name()));
|
|
scene->replaceItem(tr_item_index,new_item);
|
|
delete transform_points_item;
|
|
transform_points_item = NULL;
|
|
}
|
|
dock_widget->hide();
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::updateUiMatrix()
|
|
{
|
|
bool is_point_set = false;
|
|
if(!transform_item)
|
|
{
|
|
if(transform_points_item)
|
|
is_point_set = true;
|
|
else
|
|
return;
|
|
}
|
|
double tmatrix[16];
|
|
transformMatrix(&tmatrix[0]);
|
|
if(is_point_set)
|
|
transform_points_item->setFMatrix(tmatrix);
|
|
else
|
|
transform_item->setFMatrix(tmatrix);
|
|
//this matrix is not mandatory but it clarifies the code to use one.
|
|
QMatrix4x4 matrix;
|
|
for (int i=0; i<16; ++i)
|
|
matrix.data()[i] = tmatrix[i];
|
|
if(!is_point_set)
|
|
{
|
|
matrix(0,3) -= transform_item->center().x;
|
|
matrix(1,3) -= transform_item->center().y;
|
|
matrix(2,3) -= transform_item->center().z;
|
|
}
|
|
else
|
|
{
|
|
matrix(0,3) -= transform_points_item->center().x;
|
|
matrix(1,3) -= transform_points_item->center().y;
|
|
matrix(2,3) -= transform_points_item->center().z;
|
|
}
|
|
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
|
|
matrix.data()[12]-=offset.x;
|
|
matrix.data()[13]-=offset.y;
|
|
matrix.data()[14]-=offset.z;
|
|
ui.matrix_00->setText(QString("%1").arg(matrix(0,0))); ui.matrix_01->setText(QString("%1").arg(matrix(0,1))); ui.matrix_02->setText(QString("%1").arg(matrix(0,2))); ui.matrix_03->setText(QString("%1").arg(matrix(0,3)));
|
|
ui.matrix_10->setText(QString("%1").arg(matrix(1,0))); ui.matrix_11->setText(QString("%1").arg(matrix(1,1))); ui.matrix_12->setText(QString("%1").arg(matrix(1,2))); ui.matrix_13->setText(QString("%1").arg(matrix(1,3)));
|
|
ui.matrix_20->setText(QString("%1").arg(matrix(2,0))); ui.matrix_21->setText(QString("%1").arg(matrix(2,1))); ui.matrix_22->setText(QString("%1").arg(matrix(2,2))); ui.matrix_23->setText(QString("%1").arg(matrix(2,3)));
|
|
ui.matrix_30->setText(QString("%1").arg(matrix(3,0))); ui.matrix_31->setText(QString("%1").arg(matrix(3,1))); ui.matrix_32->setText(QString("%1").arg(matrix(3,2))); ui.matrix_33->setText(QString("%1").arg(matrix(3,3)));
|
|
|
|
}
|
|
|
|
void Polyhedron_demo_affine_transform_plugin::updateSingleTransfoValues(int index)
|
|
{
|
|
ui.lineEditZ->setToolTip("Value along the z-axis.");
|
|
switch(index)
|
|
{
|
|
case 0:
|
|
ui.lineEditA->show();
|
|
ui.lineEditX->show();
|
|
ui.lineEditY->show();
|
|
ui.lineEditZ->show();
|
|
ui.transfo_ComboBox->setToolTip("Angle, axis coordinates");
|
|
break;
|
|
case 1:
|
|
ui.lineEditA->hide();
|
|
ui.lineEditX->show();
|
|
ui.lineEditY->show();
|
|
ui.lineEditZ->show();
|
|
ui.transfo_ComboBox->setToolTip("Axis coordinates");
|
|
break;
|
|
case 2:
|
|
ui.lineEditA->hide();
|
|
ui.lineEditX->show();
|
|
ui.lineEditY->show();
|
|
ui.lineEditZ->show();
|
|
ui.transfo_ComboBox->setToolTip("Scaling along each axis");
|
|
break;
|
|
default:
|
|
ui.lineEditA->hide();
|
|
ui.lineEditX->hide();
|
|
ui.lineEditY->hide();
|
|
ui.lineEditZ->hide();
|
|
ui.transfo_ComboBox->setToolTip("Scales coordinates between [0..1] ");
|
|
break;
|
|
}
|
|
}
|
|
|
|
template<class Item>
|
|
void Polyhedron_demo_affine_transform_plugin::normalize(Item* item)
|
|
{
|
|
Kernel::Point_3 bil(item->bbox().xmin(),
|
|
item->bbox().ymin(),
|
|
item->bbox().zmin());
|
|
|
|
Kernel::Point_3 tsr(item->bbox().xmax(),
|
|
item->bbox().ymax(),
|
|
item->bbox().zmax());
|
|
//Get the scale factor for the item's coordinates to be in [0..1]
|
|
double max = (std::max)((double)tsr.x()-bil.x(), (double)tsr.y()-bil.y());
|
|
max = (std::max)(max, (double)tsr.z()-bil.z());
|
|
QVector3D v_bil= QVector3D(bil.x(),bil.y(),bil.z());
|
|
QMatrix4x4 frameMat = QMatrix();
|
|
QVector3D center(item->center().x,
|
|
item->center().y,
|
|
item->center().z);
|
|
frameMat.translate(-(v_bil-center)/max);
|
|
double d_mat[16];
|
|
for(int i=0; i<16; ++i)
|
|
d_mat[i] = (double)frameMat.data()[i];
|
|
scaling[0]=scaling[1]=scaling[2]=1.0/max;
|
|
item->manipulatedFrame()->setFromMatrix(d_mat);
|
|
}
|
|
void Polyhedron_demo_affine_transform_plugin::applySingleTransformation()
|
|
{
|
|
bool is_point_set = false;
|
|
if(!transform_item)
|
|
{
|
|
if(transform_points_item)
|
|
is_point_set = true;
|
|
else
|
|
return;
|
|
}
|
|
//save the matrix before the change
|
|
for(short i = 0; i<3; ++i)
|
|
lastScaling[i]=scaling[i];
|
|
double currentMatrix[16];
|
|
transformMatrix(¤tMatrix[0]);
|
|
for(short i = 0; i < 16; ++i)
|
|
lastMatrix.data()[i] = (float)currentMatrix[i];
|
|
|
|
switch(ui.transfo_ComboBox->currentIndex())
|
|
{
|
|
//rotation
|
|
case 0:
|
|
{
|
|
CGAL::qglviewer::Vec axis(ui.lineEditX->text().toDouble(),
|
|
ui.lineEditY->text().toDouble(),
|
|
ui.lineEditZ->text().toDouble());
|
|
|
|
if(!is_point_set)
|
|
transform_item->manipulatedFrame()->rotate(CGAL::qglviewer::Quaternion(axis, ui.lineEditA->text().toDouble()*CGAL_PI/180.0));
|
|
else
|
|
transform_points_item->manipulatedFrame()->rotate(CGAL::qglviewer::Quaternion(axis, ui.lineEditA->text().toDouble()*CGAL_PI/180.0));
|
|
break;
|
|
}
|
|
//translation
|
|
case 1:
|
|
{
|
|
if(!is_point_set)
|
|
transform_item->manipulatedFrame()->translate(CGAL::qglviewer::Vec(ui.lineEditX->text().toDouble() ,
|
|
ui.lineEditY->text().toDouble() ,
|
|
ui.lineEditZ->text().toDouble() ));
|
|
else
|
|
transform_points_item->manipulatedFrame()->translate(CGAL::qglviewer::Vec(ui.lineEditX->text().toDouble() ,
|
|
ui.lineEditY->text().toDouble() ,
|
|
ui.lineEditZ->text().toDouble() ));
|
|
break;
|
|
}
|
|
//scaling
|
|
case 2:
|
|
{
|
|
scaling[0] = ui.lineEditX->text().isEmpty() ? 1 : scaling[0]*ui.lineEditX->text().toDouble();
|
|
scaling[1] = ui.lineEditY->text().isEmpty() ? 1 : scaling[1]*ui.lineEditY->text().toDouble();
|
|
scaling[2] = ui.lineEditZ->text().isEmpty() ? 1 : scaling[2]*ui.lineEditZ->text().toDouble();
|
|
break;
|
|
}
|
|
//normalizing
|
|
case 3:
|
|
{
|
|
resetTransformMatrix();
|
|
if(!is_point_set)
|
|
normalize(transform_item);
|
|
else
|
|
normalize(transform_points_item);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
updateUiMatrix();
|
|
if(is_point_set)
|
|
{
|
|
transform_points_item->compute_bbox();
|
|
transform_points_item->itemChanged();
|
|
}
|
|
else
|
|
{
|
|
transform_item->compute_bbox();
|
|
transform_item->itemChanged();
|
|
}
|
|
}
|
|
|
|
#include "Affine_transform_plugin.moc"
|