mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-15 17:14:39 +00:00
292 lines
9.4 KiB
C++
292 lines
9.4 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* An extendible mesh processor o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005, 2006 \/)\/ *
|
|
* Visual Computing Lab /\/| *
|
|
* ISTI - Italian National Research Council | *
|
|
* \ *
|
|
* All rights reserved. *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
* for more details. *
|
|
* *
|
|
****************************************************************************/
|
|
/****************************************************************************
|
|
History
|
|
|
|
$Log: stdpardialog.cpp,v $
|
|
|
|
****************************************************************************/
|
|
|
|
#include <GL/glew.h>
|
|
#include <QDockWidget>
|
|
#include "edit_align.h"
|
|
|
|
#include "alignDialog.h"
|
|
#include <meshlab/glarea.h>
|
|
|
|
static QTextEdit *globalLogTextEdit = 0;
|
|
|
|
MeshNode *AlignDialog::currentNode() { return edit->currentNode(); }
|
|
|
|
// Global function to write on the log in the lower part of the window.
|
|
bool AlignCallBackPos(const int, const char * message)
|
|
{
|
|
assert(globalLogTextEdit);
|
|
|
|
globalLogTextEdit->insertPlainText(QString(message));
|
|
globalLogTextEdit->ensureCursorVisible();
|
|
globalLogTextEdit->update();
|
|
qApp->processEvents();
|
|
|
|
return true;
|
|
}
|
|
// This signal is used to make a connection between the closure of the align dialog and the end of the editing in the GLArea
|
|
void AlignDialog::closeEvent(QCloseEvent * /*event*/)
|
|
{
|
|
emit closing();
|
|
}
|
|
|
|
AlignDialog::AlignDialog(QWidget *parent, EditAlignPlugin *_edit) : QDockWidget(parent)
|
|
{
|
|
// setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint | Qt::SubWindow);
|
|
//setVisible(false);
|
|
AlignDialog::ui.setupUi(this);
|
|
this->setWidget(ui.frame);
|
|
this->setFeatures(QDockWidget::AllDockWidgetFeatures);
|
|
this->setAllowedAreas(Qt::LeftDockWidgetArea);
|
|
QPoint p = parent->mapToGlobal(QPoint(0, 0));
|
|
this->setFloating(true);
|
|
this->setGeometry(p.x() + (parent->width() - width()), p.y() + 40, width(), height());
|
|
this->edit = _edit;
|
|
// The following connection is used to associate the click with the change of the current mesh.
|
|
connect(ui.alignTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(onClickItem(QTreeWidgetItem *, int)));
|
|
globalLogTextEdit = ui.logTextEdit;
|
|
currentArc = 0;
|
|
meshTree = 0;
|
|
}
|
|
|
|
|
|
void AlignDialog::setCurrentArc(vcg::AlignPair::Result *_currentArc)
|
|
{
|
|
assert(meshTree);
|
|
|
|
// First clear the backgrund of previously selected arc
|
|
MeshTreeWidgetItem *oldArcF = A2Tf[currentArc];
|
|
MeshTreeWidgetItem *oldArcB = A2Tb[currentArc];
|
|
if (oldArcF != NULL)
|
|
{
|
|
assert(oldArcF->a == currentArc);
|
|
oldArcF->setBackground(3, QBrush());
|
|
oldArcB->setBackground(3, QBrush());
|
|
}
|
|
|
|
// if we clicked twice on the same arc deselect it
|
|
if (_currentArc == currentArc) {
|
|
currentArc = 0;
|
|
return;
|
|
}
|
|
|
|
MeshTreeWidgetItem *newArcB = A2Tb[_currentArc];
|
|
MeshTreeWidgetItem *newArcF = A2Tf[_currentArc];
|
|
if (newArcB != NULL)
|
|
{
|
|
assert(newArcB->a == _currentArc);
|
|
newArcB->setBackground(3, QBrush(QColor("#d0ffff")));
|
|
newArcF->setBackground(3, QBrush(QColor("#c0ffff")));
|
|
}
|
|
newArcF->treeWidget()->expandItem(newArcF->parent());
|
|
newArcB->treeWidget()->expandItem(newArcB->parent());
|
|
currentArc = _currentArc;
|
|
updateButtons();
|
|
}
|
|
|
|
|
|
void AlignDialog::updateCurrentNodeBackground()
|
|
{
|
|
static MeshNode *lastCurrentNode = 0;
|
|
assert(meshTree);
|
|
|
|
if (lastCurrentNode && M2T[lastCurrentNode])
|
|
M2T[lastCurrentNode]->setBackground(3, QBrush());
|
|
|
|
MeshTreeWidgetItem *newNodeItem = M2T[currentNode()];
|
|
if (newNodeItem != NULL)
|
|
{
|
|
newNodeItem->setBackground(3, QBrush(QColor(Qt::lightGray)));
|
|
lastCurrentNode = currentNode();
|
|
}
|
|
}
|
|
|
|
void AlignDialog::setTree(MeshTree *_meshTree)
|
|
{
|
|
assert(meshTree == 0);
|
|
meshTree = _meshTree;
|
|
meshTree->cb = AlignCallBackPos;
|
|
rebuildTree();
|
|
}
|
|
|
|
void AlignDialog::updateDialog()
|
|
{
|
|
assert(meshTree != 0);
|
|
assert(currentNode() == meshTree->find(currentNode()->m));
|
|
updateButtons();
|
|
}
|
|
|
|
void AlignDialog::updateButtons()
|
|
{
|
|
if (currentNode() == NULL)
|
|
return;
|
|
if (currentNode()->glued)
|
|
ui.glueHereButton->setText("Unglue Mesh ");
|
|
else ui.glueHereButton->setText("Glue Here Mesh");
|
|
|
|
ui.pointBasedAlignButton->setDisabled(currentNode()->glued);
|
|
ui.manualAlignButton->setDisabled(currentNode()->glued);
|
|
ui.recalcButton->setDisabled(currentArc == 0);
|
|
ui.icpParamCurrentButton->setDisabled(currentArc == 0);
|
|
ui.baseMeshButton->setDisabled(!currentNode()->glued);
|
|
}
|
|
|
|
MeshTreeWidgetItem::MeshTreeWidgetItem(MeshNode *meshNode)
|
|
{
|
|
QString meshName = meshNode->m->label();
|
|
|
|
QString labelText;
|
|
setText(0, QString::number(meshNode->Id()));
|
|
if (meshNode->glued) setText(2, "*");
|
|
if (meshNode->m->visible) setIcon(1, QIcon(":/layer_eye_open.png"));
|
|
else setIcon(1, QIcon(":/layer_eye_close.png"));
|
|
|
|
labelText.sprintf("%s", qUtf8Printable(meshName));
|
|
setText(3, labelText);
|
|
|
|
n = meshNode;
|
|
a = 0;
|
|
}
|
|
|
|
|
|
MeshTreeWidgetItem::MeshTreeWidgetItem(MeshTree* /*meshTree*/, vcg::AlignPair::Result *A, MeshTreeWidgetItem *parent)
|
|
{
|
|
n = 0;
|
|
a = A;
|
|
parent->addChild(this);
|
|
QString buf = QString("Arc: %1 -> %2 Area: %3 Err: %4 Sample# %5 (%6)")
|
|
.arg((*A).FixName)
|
|
.arg((*A).MovName)
|
|
.arg((*A).area, 6, 'f', 3)
|
|
.arg((*A).err, 6, 'f', 3)
|
|
.arg((*A).ap.SampleNum, 6)
|
|
.arg((*A).as.lastSampleUsed());
|
|
setText(3, buf);
|
|
|
|
QFont fixedFont("Courier");
|
|
std::vector<vcg::AlignPair::Stat::IterInfo> &I = (*A).as.I;
|
|
QTreeWidgetItem *itemArcIter;
|
|
buf.sprintf("Iter - MinD - Error - Sample - Used - DistR - BordR - AnglR ");
|
|
// " 12 123456 1234567 12345 12345 12345 12345 12345
|
|
itemArcIter = new QTreeWidgetItem(this);
|
|
itemArcIter->setFont(3, fixedFont);
|
|
itemArcIter->setText(3, buf);
|
|
for (size_t qi = 0; qi < I.size(); ++qi)
|
|
{
|
|
buf.sprintf(" %02zu %6.2f %7.4f %05i %05i %5i %5i %5i",
|
|
qi, I[qi].MinDistAbs, I[qi].pcl50,
|
|
I[qi].SampleTested, I[qi].SampleUsed, I[qi].DistanceDiscarded, I[qi].BorderDiscarded, I[qi].AngleDiscarded);
|
|
itemArcIter = new QTreeWidgetItem(this);
|
|
itemArcIter->setFont(3, fixedFont);
|
|
itemArcIter->setText(3, buf);
|
|
}
|
|
}
|
|
|
|
void AlignDialog::rebuildTree()
|
|
{
|
|
currentArc = 0;
|
|
gla = edit->_gla;
|
|
ui.alignTreeWidget->clear();
|
|
M2T.clear();
|
|
A2Tf.clear();
|
|
A2Tb.clear();
|
|
// QList<MeshNode*> &meshList = meshTree->nodeList;
|
|
// for (int i = 0; i < meshList.size(); ++i)
|
|
for(auto ni=meshTree->nodeMap.begin();ni!=meshTree->nodeMap.end();++ni)
|
|
{
|
|
MeshNode *mn=ni->second;
|
|
// MeshTreeWidgetItem *item = new MeshTreeWidgetItem(meshList.value(i));
|
|
MeshTreeWidgetItem *item = new MeshTreeWidgetItem(mn);
|
|
// if(meshList.value(i)==currentNode) item->setBackground(0,QBrush(QColor(Qt::lightGray)));
|
|
// M2T[meshList.value(i)] = item;
|
|
M2T[mn] = item;
|
|
ui.alignTreeWidget->addTopLevelItem(item);
|
|
}
|
|
|
|
// Second part add the arcs to the tree
|
|
vcg::AlignPair::Result *A;
|
|
MeshTreeWidgetItem *parent;
|
|
MeshTreeWidgetItem *item;
|
|
for (int i = 0; i < meshTree->resultList.size(); ++i)
|
|
{
|
|
A = &(meshTree->resultList[i]);
|
|
// Forward arc
|
|
// parent = M2T[meshList.at((*A).FixName)];
|
|
parent = M2T[meshTree->nodeMap[(*A).FixName] ];
|
|
item = new MeshTreeWidgetItem(meshTree, A, parent);
|
|
A2Tf[A] = item;
|
|
// Backward arc
|
|
// parent = M2T[meshList.at((*A).MovName)];
|
|
parent = M2T[meshTree->nodeMap [(*A).MovName] ];
|
|
item = new MeshTreeWidgetItem(meshTree, A, parent);
|
|
A2Tb[A] = item;
|
|
}
|
|
ui.alignTreeWidget->resizeColumnToContents(0);
|
|
ui.alignTreeWidget->resizeColumnToContents(1);
|
|
ui.alignTreeWidget->resizeColumnToContents(2);
|
|
assert(currentNode());
|
|
updateCurrentNodeBackground();
|
|
updateButtons();
|
|
}
|
|
void AlignDialog::currentMeshChanged(int)
|
|
{
|
|
this->updateDialog();
|
|
this->rebuildTree();
|
|
}
|
|
|
|
// Called when a user click over the tree;
|
|
void AlignDialog::onClickItem(QTreeWidgetItem * item, int column)
|
|
{
|
|
// int row = item->data(1,Qt::DisplayRole).toInt();
|
|
MeshTreeWidgetItem *mItem = dynamic_cast<MeshTreeWidgetItem *>(item);
|
|
if (!mItem)
|
|
return; // user clicked on a iteration info (neither a node nor an arc)
|
|
|
|
MeshNode * nn = mItem->n;
|
|
if (nn) {
|
|
if (column == 1)
|
|
{
|
|
nn->m->visible = !nn->m->visible;
|
|
emit updateMeshSetVisibilities();
|
|
if (nn->m->visible) mItem->setIcon(1, QIcon(":/layer_eye_open.png"));
|
|
else mItem->setIcon(1, QIcon(":/layer_eye_close.png"));
|
|
}
|
|
else {
|
|
this->edit->_md->setCurrentMesh(nn->Id());
|
|
updateCurrentNodeBackground();
|
|
}
|
|
}
|
|
else {
|
|
assert(mItem->a);
|
|
setCurrentArc(mItem->a);
|
|
}
|
|
gla->update();
|
|
updateButtons();
|
|
}
|