cgal/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp

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(&currentMatrix[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"