Raw File
QuickAlignment.cpp
#include "QuickAlignment.h"
#include "ui_QuickAlignment.h"
#include <QMatrix4x4>

#define M_PI_4     0.785398163397448309616
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

QuickAlignment::QuickAlignment(Structure::Graph *graphA, Structure::Graph *graphB,
                               QWidget *parent) : QDialog(parent), ui(new Ui::QuickAlignment)
{
	ui->setupUi(this);

    this->ga = graphA;
    this->gb = graphB;

    // Populate lists
    foreach(Structure::Node * n, ga->nodes) ui->list1->addItem(new QListWidgetItem(n->id));
    foreach(Structure::Node * n, gb->nodes) ui->list2->addItem(new QListWidgetItem(n->id));

	// Connections
	this->connect(ui->alignButton, SIGNAL(clicked()), SLOT(doPartAlignment()));
	this->connect(ui->list1, SIGNAL(itemSelectionChanged()), SLOT(visualizeSelections()));
	this->connect(ui->list2, SIGNAL(itemSelectionChanged()), SLOT(visualizeSelections()));
}

QuickAlignment::~QuickAlignment()
{
    delete ui;
}

int QuickAlignment::quadrant(Vector3 v)
{
	// Treat as degenerate vector
	if(v.norm() < 1e-10) return -1;

	v.normalize();

	double threshold = 0.1;
	if(abs(v[0]) < threshold) return ((v[1] > 0) ? 2 : 6);	// On y-axis
	if(abs(v[1]) < threshold) return ((v[0] > 0) ? 0 : 4);	// On x-axis

	if(v[0] * v[1] > 0 && v[0] > 0) return 1;	// First quadrant
	if(v[0] < 0 && v[1] > 0) return 3;			// Second
	if(v[0] < 0 && v[1] < 0) return 5;			// Third
	return 7;									// Fourth
}

void QuickAlignment::doPartAlignment()
{
	QString nodeA = ui->list1->selectedItems().first()->text();
	QString nodeB = ui->list2->selectedItems().first()->text();

	Structure::Node * na = ga->getNode( nodeA );
	Structure::Node * nb = gb->getNode( nodeB );
	
	Eigen::AlignedBox3d boxA, boxB;
	QMatrix4x4 mat;

	// Scaling
	boxA = na->bbox(); boxB = nb->bbox();
	double maxDimA = qMax( qMax(boxA.diagonal().x(), boxA.diagonal().y()), boxA.diagonal().z() );
	double maxDimB = qMax( qMax(boxB.diagonal().x(), boxB.diagonal().y()), boxB.diagonal().z() );
	double scale = maxDimA / maxDimB;
	mat.setToIdentity();
	mat.scale(scale);
	gb->transform(mat);

	// Rotation
	boxA = na->bbox(); boxB = nb->bbox();
	Vector3d va = Vector3d(boxA.center().x(), boxA.center().y(), 0).normalized();
	Vector3d vb = Vector3d(boxB.center().x(), boxB.center().y(), 0).normalized();
	int qa = quadrant(va);
	int qb = quadrant(vb);
	int diff = qb - qa;

	mat.setToIdentity();
	mat.rotate( RADIANS_TO_DEGREES(diff * M_PI_4), QVector3(0,0,1) );
	ga->transform( mat );

	// Translation
	boxA = na->bbox(); boxB = nb->bbox();
	mat.setToIdentity();
	mat.translate( 0, 0, boxB.center().z() - boxA.center().z() );
	ga->transform( mat );


	emit( updateView() );
}

void QuickAlignment::visualizeSelections()
{
	QList<QListWidgetItem *> items1 = ui->list1->selectedItems();
	QList<QListWidgetItem *> items2 = ui->list2->selectedItems();

	// Set black for all
	foreach (Structure::Node * node,  ga->nodes)
	{
		node->vis_property["color"] = Qt::lightGray;
		node->vis_property["showControl"] = false;
	}
	foreach (Structure::Node * node,  gb->nodes)
	{
		node->vis_property["color"] = Qt::lightGray;
		node->vis_property["showControl"] = false;
	}

	// Set red for landmark
	foreach (QListWidgetItem * item, items1)
		ga->getNode(item->text())->vis_property["color"] = Qt::red;
	
	foreach (QListWidgetItem * item, items2)
		gb->getNode(item->text())->vis_property["color"] = Qt::green;

	emit( updateView() );
}
back to top