topo-blend.cpp
#include <QElapsedTimer>
#include <QFileDialog>
#include <QDialog>
#include <QStack>
#include <QQueue>
#include "StarlabMainWindow.h"
#include "StarlabDrawArea.h"
#include "interfaces/ModePluginDockWidget.h"
#include "topo-blend.h"
#include "../CustomDrawObjects.h"
#include "GraphModifyWidget.h"
#include "QuickAlignment.h"
#include "GraphExplorer.h"
using namespace NURBS;
using namespace Structure;
#include "DynamicGraph.h"
#include "ExportDynamicGraph.h"
#include "GraphDistance.h"
#include "GraphCorresponder.h"
#include "TopoBlender.h"
#include "Scheduler.h"
#include "Task.h"
#include "Synthesizer.h"
#include "graphs-manager.h"
#include "correspondence-manager.h"
#include "SynthesisManager.h"
#define BBOX_WIDTH(box) (box.max().x()-box.min().x())
#define PADDING_FACTOR 1.0
// Simple UI
#include "wizard.h"
#include "QuickMeshDraw.h"
// Relations
//#include "RelationWidget.h"
#include "ScorerWidget.h"
//RelationWidget * rwidget = NULL;
ScorerWidget * swidget = NULL;
topoblend::topoblend()
{
widget = NULL;
wizard = NULL;
graph_explorer = NULL;
gcoor = NULL;
blender = NULL;
scheduler = NULL;
g_manager = new GraphsManager(this);
c_manager = new CorrespondenceManager(this);
s_manager = new SynthesisManager(NULL, NULL, NULL);
}
void topoblend::create()
{
if(!widget)
{
ModePluginDockWidget * dockwidget = new ModePluginDockWidget("TopoBlender", mainWindow());
widget = new topo_blend_widget(this);
dockwidget->setWidget(widget);
dockwidget->setWindowTitle(widget->windowTitle());
mainWindow()->addDockWidget(Qt::RightDockWidgetArea, dockwidget);
points = mesh()->vertex_property<Vector3>("v:point");
// Events
this->connect(this, SIGNAL(statusBarMessage(QString)), SLOT(setStatusBarMessage(QString)));
this->connect(s_manager, SIGNAL(setMessage(QString)), SLOT(setStatusBarMessage(QString)));
this->connect(s_manager, SIGNAL(updateViewer()), SLOT(updateDrawArea()));
// Simple UI
this->wizard = new Wizard(this, widget->simpleWidget());
// Explore graph and its properties
this->graph_explorer = new GraphExplorer;
// Add relation detector widget
//this->widget->addTab( (rwidget = new RelationWidget()) );
//this->connect(rwidget->r_manager, SIGNAL(message(QString)), SLOT(setStatusBarMessage(QString)));
this->widget->addTab( (swidget = new ScorerWidget()) );
this->connect(swidget->s_manager, SIGNAL(message(QString)), SLOT(setStatusBarMessage(QString)));
}
drawArea()->setSelectRegionHeight( 20 );
drawArea()->setSelectRegionWidth( 20 );
drawArea()->setShortcut(QGLViewer::DRAW_AXIS, Qt::Key_A);
drawArea()->setShortcut(QGLViewer::DRAW_GRID, Qt::Key_G);
// Change camera type
drawArea()->camera()->setType(qglviewer::Camera::PERSPECTIVE);
setSceneBounds();
mainWindow()->showMaximized();
}
void topoblend::drawFancyBackground()
{
// Fancy background
int width = drawArea()->width();
int height = drawArea()->height();
drawArea()->startScreenCoordinatesSystem();
glDisable(GL_LIGHTING);
glBegin(GL_QUADS);
glColor3d(0,0,0); glVertex2d(0,0); glVertex2d(width,0);
glColor3d(0.2,0.2,0.2); glVertex2d(width,height); glVertex2d(0,height);
glEnd();
glEnable(GL_LIGHTING);
glClear(GL_DEPTH_BUFFER_BIT);
drawArea()->stopScreenCoordinatesSystem();
}
void topoblend::decorate()
{
drawFancyBackground();
// Make sure we draw smooth objects
glEnable(GL_MULTISAMPLE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//drawBBox(bigbox);
// 2D view
//glDisable(GL_LIGHTING);
//for(int g = 0; g < (int) graphs.size(); g++)
//{
// if(graphs[g]->edges.size() < 2) continue;
// drawArea()->startScreenCoordinatesSystem();
// graphs[g]->draw2D(150,150);
// drawArea()->stopScreenCoordinatesSystem();
//}
// DEBUG distance:
for(int g = 0; g < (int) graphs.size(); g++){
if(graphs[g]->misc.contains("distance")){
GraphDistance * gd = (GraphDistance *)graphs[g]->misc["distance"];
gd->draw();
}
}
// DEBUG:
glDisable(GL_LIGHTING);
//glClear( GL_DEPTH_BUFFER_BIT );
// Points 1
glPushMatrix();
glTranslatef(0, -drawArea()->sceneRadius(), 0);
glPointSize(4); glColor3d(1,0,0); glBegin(GL_POINTS); foreach(Vector3 v, debugPoints) glVector3(v); glEnd();
glPointSize(8); glColor3d(1,1,1); glBegin(GL_POINTS); foreach(Vector3 v, debugPoints) glVector3(v); glEnd();
glPopMatrix();
// Points 2
glPushMatrix();
glTranslatef(0.0, drawArea()->sceneRadius(), 0);
glColor3d(0,1,0); glBegin(GL_POINTS); foreach(Vector3 v, debugPoints2) glVector3(v); glEnd();
glPopMatrix();
glColor3d(0,0,1); glBegin(GL_POINTS); foreach(Vector3 v, debugPoints3) glVector3(v); glEnd();
// Lines
typedef QPair<Vector3,Vector3> MyLine;
glColor3d(1,0,0); glBegin(GL_LINES); foreach(MyLine l, debugLines) {glVector3(l.first); glVector3(l.second);} glEnd();
glColor3d(0,1,0); glBegin(GL_LINES); foreach(MyLine l, debugLines2) {glVector3(l.first); glVector3(l.second);} glEnd();
glColor3d(0,0,1); glBegin(GL_LINES); foreach(MyLine l, debugLines3) {glVector3(l.first); glVector3(l.second);} glEnd();
glEnable(GL_LIGHTING);
if(blender) blender->drawDebug();
// 3D visualization
glEnable(GL_LIGHTING);
if( scheduler && scheduler->allGraphs.size() == 0 && !property["forceDrawGraphs"].toBool() )
{
QVector<Structure::Graph*> currentGraphs;
currentGraphs.push_back(scheduler->activeGraph);
currentGraphs.push_back(scheduler->targetGraph);
// Visualize tasks
glDisable(GL_LIGHTING);
foreach(Structure::Graph * g, currentGraphs){
foreach(Node * n, g->nodes){
if(!n->vis_property["glow"].toBool() || n->id.contains("_null")) continue;
int nType = n->property["taskTypeReal"].toInt();
double posX = g->property["posX"].toDouble();
QString taskName = TaskNames[nType];
glColorQt(TaskColors[nType]);
qglviewer::Vec end(drawArea()->width() * 0.5, 20, 0);
// Draw arc
drawArea()->startScreenCoordinatesSystem();
Vector3 boxCenter = n->bbox().center();
boxCenter.x() += posX;
qglviewer::Vec start = drawArea()->camera()->projectedCoordinatesOf( qglviewer::Vec(boxCenter) );
double bend = currentGraphs.front() == g ? -1 : 1;
std::vector<Vector3> arc = BezierArc(Vector3(start.x,start.y,start.z), Vector3(end.x,end.y,end.z), 10, bend);
for(int i = 0; i < (int) arc.size(); i++){
glLineWidth(3);
glBegin(GL_LINE_STRIP);
foreach(Vector3 p, arc) glVector3(p);
glEnd();
}
// Draw box
int w = 30, h = 10;
glBegin (GL_POLYGON);
glVertex2d (end.x - w, end.y - h);
glVertex2d (end.x + w, end.y - h);
glVertex2d (end.x + w, end.y + h);
glVertex2d (end.x - w, end.y + h);
glEnd();
// Draw text
QFont font = QFont();
QFontMetrics metric(font);
glColor3d(0,0,0);
drawArea()->renderText(end.x - (metric.width(taskName) * 0.5), end.y + 4, taskName);
drawArea()->stopScreenCoordinatesSystem();
glEnable(GL_MULTISAMPLE);
}
}
glEnable(GL_LIGHTING);
// Draw nodes both selected and regular
foreach(Structure::Graph * g, currentGraphs){
foreach(Node * n, g->nodes){
if(n->id.contains("_null")) continue;
double posX = g->property["posX"].toDouble();
glPushMatrix();
glTranslated(posX, 0, 0);
SurfaceMesh::Model* nodeMesh = g->getMesh(n->id);
if( !nodeMesh || !nodeMesh->n_vertices() || !viz_params["showMeshes"].toBool() )
{
if(viz_params["showNodes"].toBool())
n->draw();
}
else
{
if(n->vis_property["glow"].toBool())
{
QColor meshColor(255,255,0);
QuickMeshDraw::drawMeshSolid( nodeMesh, meshColor );
}
else
{
QColor meshColor(180,180,180,220);
QuickMeshDraw::drawMeshSolid( nodeMesh, meshColor );
}
}
glPopMatrix();
}
}
// Draw synthesis samples if available
if(viz_params["showSamples"].toBool())
s_manager->drawSampled();
}
else if(graphs.size())
{
double startX = bigbox.min().x();
for(int g = 0; g < (int) graphs.size(); g++)
{
// Apply visualization options
graphs[g]->property["showEdges"] = viz_params["showEdges"];
graphs[g]->property["showMeshes"] = viz_params["showMeshes"];
graphs[g]->property["showTasks"] = viz_params["showTasks"];
graphs[g]->property["showCtrlPts"] = viz_params["showCtrlPts"];
graphs[g]->property["showNodes"] = viz_params["showNodes"];
graphs[g]->property["showNames"] = viz_params["showNames"];
graphs[g]->property["showCurveFrames"] = viz_params["showCurveFrames"];
// Place and draw graph
glPushMatrix();
Eigen::AlignedBox3d curbox = graphs[g]->bbox();
double curwidth = (curbox.max().x() - curbox.min().x());
double deltaX = curwidth * 0.5;
double padding = 0;
if(g > 0) padding = curwidth * PADDING_FACTOR;
double posX = startX + deltaX + padding;
if(graphs.size() < 2) posX = 0;
glTranslated(posX, 0, 0);
// store for later use
graphs[g]->property["posX"] = posX;
graphs[g]->draw( drawArea() );
//drawBBox( curbox );
glPopMatrix();
startX += curwidth + padding;
}
if( scheduler && scheduler->allGraphs.size() )
{
s_manager->isSplatRenderer = viz_params["isSplatRenderer"].toBool();
s_manager->splatSize = viz_params["splatSize"].toDouble();
if(scheduler->property["progressDone"].toBool())
s_manager->drawSynthesis( graphs.back() );
}
}
// Textual information
glColor4d(1,1,1,0.25);
drawArea()->renderText(40,40, "[TopoBlend]");
if( property["correspondenceMode"].toBool() )
{
glColor4d(1,1,1,1);
drawArea()->renderText(40,60, "Correspondence Mode");
}
}
void topoblend::drawWithNames()
{
if(property["correspondenceMode"].toBool())
{
c_manager->drawWithNames();
return;
}
// Select control points
for(int gID = 0; gID < (int) graphs.size(); gID++)
{
Structure::Graph *g = graphs[gID];
int nodeID_base = gID * NODE_ID_RANGE;
glPushMatrix();
glTranslated(g->property["posX"].toDouble(), 0, 0);
for (int nID = 0; nID < (int)g->nodes.size(); nID++)
{
g->nodes[nID]->drawWithNames(nodeID_base + nID, POINT_ID_RANGE);
}
glPopMatrix();
}
}
bool topoblend::postSelection( const QPoint& point )
{
Q_UNUSED(point);
int selectedID = drawArea()->selectedName();
if(property["correspondenceMode"].toBool())
{
// mesh visualization - set to solid gray
foreach(Graph * g, graphs){
foreach(Node * n, g->nodes){
int nodeID = n->property["meshSelectID"].toInt();
if(n->property["is_corresponded"].toBool())
continue;
if( selectedID == nodeID )
{
if( n->property["nodeSelected"].toBool() )
{
n->property["nodeSelected"] = false;
n->vis_property["meshColor"].setValue( QColor(180,180,180) );
}
else
{
n->property["nodeSelected"] = true;
n->vis_property["meshColor"].setValue( QColor(50,70,255) );
}
}
}
}
return false;
}
if (selectedID == -1) return false;
int gID, nID, pID;
getIndicesFromSelectedName(selectedID, gID, nID, pID);
graphs[gID]->nodes[nID]->addSelectionWithColor(pID, Qt::green);
qDebug() << "Selected ID is " << selectedID;
return true;
}
void topoblend::setSceneBounds()
{
if(!graphs.size())
{
drawArea()->setSceneRadius(2);
drawArea()->setSceneCenter(qglviewer::Vec(0,0,0));
drawArea()->setSceneBoundingBox(qglviewer::Vec(-1,-1,-1), qglviewer::Vec(1,1,1));
drawArea()->camera()->setPosition(qglviewer::Vec(-1,-3,2));
drawArea()->showEntireScene();
drawArea()->updateGL();
return;
}
// Set scene bounds
bigbox = graphs.front()->bbox();
double deltaX = BBOX_WIDTH(bigbox);
bigbox.translate( Vector3(deltaX * 0.5, 0, 0) ); // start from zero
for(int i = 1; i < (int)graphs.size(); i++)
{
Eigen::AlignedBox3d curbox = graphs[i]->bbox();
double curWidth = BBOX_WIDTH(curbox);
double padding = curWidth * PADDING_FACTOR;
curbox.translate( Vector3(deltaX + (0.5 * curWidth) + padding, 0, 0) );
bigbox = bigbox.merged( Eigen::AlignedBox3d(curbox) );
deltaX += BBOX_WIDTH(curbox) + padding;
}
// Move to center
bigbox.translate( Vector3(-bigbox.center().x(), 0, 0) );
Vector3 a = bigbox.min();
Vector3 b = bigbox.max();
qglviewer::Vec vecA(a.x(), a.y(), a.z());
qglviewer::Vec vecB(b.x(), b.y(), b.z());
drawArea()->setSceneCenter((vecA + vecB) * 0.5);
drawArea()->setSceneBoundingBox(vecA, vecB);
drawArea()->showEntireScene();
drawArea()->updateGL();
}
bool topoblend::mouseReleaseEvent( QMouseEvent * event )
{
bool used = false;
if( property["correspondenceMode"].toBool() )
{
if( event->button() == Qt::RightButton )
{
c_manager->assignCorrespondence();
}
}
return used;
}
bool topoblend::keyPressEvent( QKeyEvent* event )
{
bool used = false;
QElapsedTimer timer; timer.start();
if(event->key() == Qt::Key_I)
{
if(graphs.size())
{
if(graphs.size() == 2 && scheduler)
graph_explorer->update(scheduler->activeGraph);
else
graph_explorer->update(graphs.back());
if(graph_explorer) graph_explorer->show();
}
property["forceDrawGraphs"] = true;
used = true;
}
if(event->key() == Qt::Key_C)
{
c_manager->clearCorrespondence();
used = true;
}
if(event->key() == Qt::Key_Space)
{
c_manager->correspondenceMode();
used = true;
}
if(event->key() == Qt::Key_M)
{
if(graphs.size())
{
QVector< QMap<QString, int> > graphsInfo;
for(int i = 0; i < scheduler->allGraphs.size(); i++)
{
Structure::Graph * g = Structure::Graph::actualGraph( scheduler->allGraphs[i] );
QMap<QString, int> info;
info["id"] = i;
info["V"] = g->nodes.size();
info["E"] = g->edges.size();
info["A"] = g->articulationPoints().size();
info["L"] = g->leaves().size();
graphsInfo.push_back(info);
}
// Output to file
QString filename( "blendJob.json" );
QFile file(filename); file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out << "{ \"items\": [";
for(int i = 0; i < graphsInfo.size(); i++)
{
QMap<QString, int> info = graphsInfo[i];
QStringList item;
foreach(QString name, info.keys()) item << QString("\"%1\": %2").arg(name).arg(info[name]);
out << "{" << item.join(",") << "}";
if( i < graphsInfo.size() - 1 ) out << ",";
out << "\n";
}
out << "]}";
file.close();
}
used = true;
}
/*
if(event->key() == Qt::Key_Space && (event->modifiers() & Qt::ShiftModifier))
{
for(int g = 0; g < (int) graphs.size(); g++)
{
graphs[g]->materialize(0);
}
qDebug() << "Materialized graphs (voxel only) " << timer.elapsed() << " ms";
used = true;
}
if(event->key() == Qt::Key_E)
{
for(int g = 0; g < (int) graphs.size(); g++)
{
graphs[g]->cached_mesh.clear();
SurfaceMesh::Model * m = new SurfaceMesh::Model( QString("Voxel_%1.obj").arg(g), QString("Voxel_%1").arg(g) );
graphs[g]->materialize(m);
DynamicVoxel::MeanCurvatureFlow(m, 0.05);
//DynamicVoxel::LaplacianSmoothing(m);
document()->pushBusy();
document()->addModel(m);
document()->popBusy();
}
qDebug() << "Materialized graphs, generated smooth mesh " << timer.elapsed() << " ms";
used = true;
}
*/
if(event->key() == Qt::Key_W)
{
if(graphs.size() < 1) return true;
Structure::Graph * g = graphs.back();
QElapsedTimer t; t.start();
GraphDistance * gd = new GraphDistance(g);
std::vector<Vector3> starts;
starts.push_back(Vector3(1,-0.5,2.5));
starts.push_back(Vector3(-1,-0.5,2.5));
gd->computeDistances(starts, g->bbox().diagonal().norm() * 0.01);
g->misc["distance"] = gd;
mainWindow()->setStatusBarMessage( "Distance test: " + QString::number(t.elapsed()) );
used = true;
}
if(event->key() == Qt::Key_N)
{
viz_params["showNames"] = !viz_params["showNames"].toBool();
used = true;
}
if(event->key() == Qt::Key_R)
{
for(int g = 0; g < (int) graphs.size(); g++)
{
qDebug() << "Root (by valence) = " << graphs[g]->rootByValence()->id;
qDebug() << "Root (by size) = " << graphs[g]->rootBySize()->id;
}
used = true;
}
if(event->key() == Qt::Key_T)
{
qglviewer::Vec q = drawArea()->camera()->revolveAroundPoint();
Vector3d p(q[0],q[1],q[2]);
QString sample_details = "";
for(int gi = 0; gi < (int) graphs.size(); gi++)
{
Structure::Graph * g = graphs[gi];
g->property.remove("selectedSample");
foreach(Structure::Node * node, g->nodes)
{
if(node->property.contains("cached_points"))
{
/*
double minDist = DBL_MAX;
QVector<Eigen::Vector3f> & pnts = *(node->property["cached_points"].value< QVector<Eigen::Vector3f>* >());
QVector<ParameterCoord> & samples = *(node->property["samples"].value< QVector<ParameterCoord>* >());
QVector<float> & offsets = *(node->property["offsets"].value< QVector<float>* >());
Vector3f delta = Vector3f(g->property["posX"].toDouble(),0,0);
Vector3f q = p.cast<float>() - delta;
for(int i = 0; i < (int)pnts.size(); i++)
{
double dist = Vector3f(pnts[i] - q).norm();
if(dist < minDist && dist < 0.01){
ParameterCoord s = samples[i];
sample_details = QString("[%5] u= %1 v= %2 theta= %3 psi= %4 offset = %6").arg(s.u
).arg(s.v).arg(s.theta).arg(s.psi).arg(node->id).arg(offsets[i]);
minDist = dist;
g->property["selectedSample"].setValue(pnts[i]);
g->property["selectedNode"].setValue(node->id);
if(s.origNode) sample_details += QString(" [orig %1][").arg(s.origNode->id);
QString graphName = g->property["name"].toString().section('\\', -1).section('.', 0, 0);
sample_details = "["+graphName+"] " + sample_details;
}
}*/
}
}
}
setStatusBarMessage(sample_details);
used = true;
}
if(event->key() == Qt::Key_J)
{
QString key = "ViewerStateFile";
QString value = qApp->applicationDirPath() + "/viewer_state.xml";
drawArea()->settings()->set( key, value );
drawArea()->settings()->sync();
drawArea()->setStateFileName( value );
drawArea()->saveStateToFile();
mainWindow()->setStatusBarMessage("Viewer state saved to file.");
used = true;
}
if(event->key() == Qt::Key_K)
{
QString key = "ViewerStateFile";
QString value = drawArea()->settings()->getString(key);
drawArea()->setStateFileName( value );
drawArea()->restoreStateFromFile();
mainWindow()->setStatusBarMessage("Viewer state loaded.");
used = true;
}
if(event->key() == Qt::Key_G)
{
if(scheduler && blender)
{
QDir dir("");
dir.setCurrent(QFileDialog::getExistingDirectory());
QString sGraphName = gcoor->sgName();
QString tGraphName = gcoor->tgName();
// Export source and target
DynamicGraphs::DynamicGraph sdg(blender->sg);
DynamicGraphs::DynamicGraph tdg(blender->tg);
toGraphviz(sdg, sGraphName, true, QString("V = %1, E = %2").arg(sdg.nodes.size()).arg(sdg.edges.size()), "original source");
toGraphviz(tdg, tGraphName, true, QString("V = %1, E = %2").arg(tdg.nodes.size()).arg(tdg.edges.size()), "original target");
// Export supers
DynamicGraphs::DynamicGraph sdg_super(scheduler->activeGraph);
DynamicGraphs::DynamicGraph tdg_super(scheduler->targetGraph);
toGraphviz(sdg_super, sGraphName + "_super", true, QString("V = %1, E = %2").arg(sdg_super.nodes.size()).arg(sdg_super.edges.size()), "super source");
toGraphviz(tdg_super, tGraphName + "_super", true, QString("V = %1, E = %2").arg(tdg_super.nodes.size()).arg(tdg_super.edges.size()), "super target");
QImage img1(sGraphName + "_super"), img2(tGraphName + "_super");
QImage bothImg(img1.width() + img2.width(), qMax(img1.height(), img2.height()), QImage::Format_RGB32);
bothImg.fill(Qt::white);
QPainter paint;
paint.begin(&bothImg);
paint.drawImage(0,0,img1);
paint.drawImage(img1.width(),0,img2);
paint.end();
bothImg.save("All_Graphs.png");
used = true;
}
else if(graphs.size())
{
QDir dir("");
dir.setCurrent(QFileDialog::getExistingDirectory());
DynamicGraphs::DynamicGraph sdg(graphs.front());
toGraphviz(sdg, graphs.front()->name(), true, QString("V = %1, E = %2").arg(sdg.nodes.size()).arg(sdg.edges.size()), "Graph");
used = true;
}
}
if(event->key() == Qt::Key_F)
{
QString graphFilename = "tempGraph_"+QString::number(QDateTime::currentMSecsSinceEpoch());
visualizeStructureGraph(graphs.back(), graphFilename, "Current graph");
QImage img(graphFilename+".png");
QMessageBox* msgBox = new QMessageBox;
msgBox->setAttribute( Qt::WA_DeleteOnClose );
msgBox->setIconPixmap( QPixmap::fromImage(img) );
msgBox->setModal( false );
msgBox->setMinimumSize(img.width(), img.height());
msgBox->open();
used = true;
}
// Visualize relinking
if(event->key() == Qt::Key_Y && graph_explorer)
{
QString dotPath = "dot";
#ifdef Q_OS_WIN
dotPath = "\"" + QString(exec("where dot").c_str()).replace("\\","/").trimmed() + "\"";
#else
dotPath = QString(exec("which dot").c_str());
#endif
QProcess * p = graph_explorer->p;
p = new QProcess;
p->start( dotPath, QStringList() << "-Tsvg" );
p->waitForStarted();
p->write( qPrintable( graphs.front()->property["relinkGraph"].toString() ) );
p->closeWriteChannel();
p->waitForFinished(-1);
QString svgData = p->readAllStandardOutput();
QTemporaryFile file;
if (file.open()){
QTextStream out(&file);
out << svgData;
file.close();
}
graph_explorer->svgViewer->openFile(file);
}
drawArea()->updateGL();
return used;
}
void topoblend::doBlend()
{
if ( graphs.size() < 2 )
{
qDebug() << "Please load at least two graphs.";
return;
}
QElapsedTimer timer; timer.start();
if(scheduler)
{
// Old signals
scheduler->disconnect(this);
this->disconnect(scheduler);
scheduler->dock->close();
scheduler = NULL;
if(s_manager) s_manager->scheduler = scheduler;
}
if( !gcoor )
{
gcoor = c_manager->makeCorresponder();
}
if( !gcoor->isReady )
{
gcoor->computeCorrespondences();
}
c_manager->exitCorrespondenceMode(true);
scheduler = new Scheduler( );
if(s_manager) s_manager->scheduler = scheduler;
blender = new TopoBlender( gcoor, scheduler );
blender->parentWidget = mainWindow();
blender->setupUI();
// Update for relations widget
swidget->s_manager->init(this->gcoor,this->scheduler,this->graphs);
// Update active graph
this->connect(scheduler, SIGNAL(activeGraphChanged( Structure::Graph* )), SLOT(updateActiveGraph( Structure::Graph* )));
// Render connections
this->s_manager->connect(scheduler, SIGNAL(renderAll()), SLOT(renderAll()), Qt::UniqueConnection);
this->s_manager->connect(scheduler, SIGNAL(renderCurrent()), SLOT(renderCurrent()), Qt::UniqueConnection);
// Other connections
this->connect(scheduler, SIGNAL(updateExternalViewer()), SLOT(updateDrawArea()));
setSceneBounds();
updateDrawArea();
setStatusBarMessage( QString("Created TopoBlender and tasks in [ %1 ms ]").arg( timer.elapsed() ) );
}
void topoblend::updateDrawArea()
{
drawArea()->updateGL();
}
Structure::Graph * topoblend::getGraph(int id)
{
if (id >= 0 && id < graphs.size())
return graphs[id];
else
return NULL;
}
void topoblend::updateActiveGraph( Structure::Graph * newActiveGraph )
{
if(s_manager->renderData.size())
widget->setCheckOption("showNodes", false);
widget->setCheckOption("showMeshes", false);
graphs.clear();
this->graphs.push_back( new Structure::Graph( *newActiveGraph ) );
drawArea()->updateGL();
if(graph_explorer->isVisible()){
graph_explorer->update( newActiveGraph );
}
}
void topoblend::setStatusBarMessage(QString message)
{
mainWindow()->setStatusBarMessage(message, 1000);
drawArea()->updateGL();
}
void topoblend::drawBBox(Eigen::AlignedBox3d bbox)
{
float min[3];
min[0] = bbox.min().x();
min[1] = bbox.min().y();
min[2] = bbox.min().z();
float max[3];
max[0] = bbox.max().x();
max[1] = bbox.max().y();
max[2] = bbox.max().z();
/// --- Inherited from VCG ---
glPushAttrib(GL_ENABLE_BIT);
glColor3d(1,1,0.5);
glLineWidth(3);
glLineStipple(3, 0xAAAA);
glEnable(GL_LINE_STIPPLE);
glDisable(GL_LIGHTING);
glBegin(GL_LINE_STRIP);
glVertex3f((float)min[0],(float)min[1],(float)min[2]);
glVertex3f((float)max[0],(float)min[1],(float)min[2]);
glVertex3f((float)max[0],(float)max[1],(float)min[2]);
glVertex3f((float)min[0],(float)max[1],(float)min[2]);
glVertex3f((float)min[0],(float)min[1],(float)min[2]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f((float)min[0],(float)min[1],(float)max[2]);
glVertex3f((float)max[0],(float)min[1],(float)max[2]);
glVertex3f((float)max[0],(float)max[1],(float)max[2]);
glVertex3f((float)min[0],(float)max[1],(float)max[2]);
glVertex3f((float)min[0],(float)min[1],(float)max[2]);
glEnd();
glBegin(GL_LINES);
glVertex3f((float)min[0],(float)min[1],(float)min[2]);
glVertex3f((float)min[0],(float)min[1],(float)max[2]);
glVertex3f((float)max[0],(float)min[1],(float)min[2]);
glVertex3f((float)max[0],(float)min[1],(float)max[2]);
glVertex3f((float)max[0],(float)max[1],(float)min[2]);
glVertex3f((float)max[0],(float)max[1],(float)max[2]);
glVertex3f((float)min[0],(float)max[1],(float)min[2]);
glVertex3f((float)min[0],(float)max[1],(float)max[2]);
glEnd();
glPopAttrib();
}
bool topoblend::mousePressEvent( QMouseEvent * event )
{
property["mousePressPos"] = event->pos();
return false;
}
bool topoblend::mouseMoveEvent( QMouseEvent * event )
{
if( property["correspondenceMode"].toBool() )
{
if( event->buttons() & Qt::LeftButton ){
QPoint startPos = property["mousePressPos"].toPoint();
if((event->pos()-startPos).manhattanLength()){
setStatusBarMessage(QString::number(event->pos().x()));
qglviewer::Vec orig, dir;
drawArea()->camera()->convertClickToLine(event->pos(), orig, dir);
for(int gID = 0; gID < (int) graphs.size(); gID++)
{
//Structure::Graph *g = graphs[gID];
//foreach(Node * n, g->nodes)
//{
//SurfaceMesh::Model* nodeMesh = g->getMesh(n->id);
//double posX = g->property["posX"].toDouble();
//}
}
}
}
}
return false;
}
bool topoblend::rayBBoxIntersect( Eigen::AlignedBox3d bbox, Vector3 origin, Vector3 ray )
{
Q_UNUSED(bbox)
Q_UNUSED(origin)
Q_UNUSED(ray)
return false;
}
Q_EXPORT_PLUGIN(topoblend)