2020-06-01 16:50:51 +02:00

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();
}