2014-02-11 23:04:22 +00:00
|
|
|
/*
|
2014-08-11 17:00:55 +00:00
|
|
|
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
* Neither the name of the Universite de Sherbrooke nor the
|
|
|
|
|
names of its contributors may be used to endorse or promote products
|
|
|
|
|
derived from this software without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
#include "GraphViewer.h"
|
|
|
|
|
|
2015-03-16 19:51:22 +00:00
|
|
|
#include <QGraphicsView>
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
|
#include <QGraphicsEllipseItem>
|
2014-02-11 23:04:22 +00:00
|
|
|
#include <QtGui/QWheelEvent>
|
2015-03-16 19:51:22 +00:00
|
|
|
#include <QGraphicsSceneHoverEvent>
|
|
|
|
|
#include <QMenu>
|
2014-02-11 23:04:22 +00:00
|
|
|
#include <QtGui/QDesktopServices>
|
|
|
|
|
#include <QtGui/QContextMenuEvent>
|
2015-03-16 19:51:22 +00:00
|
|
|
#include <QColorDialog>
|
2014-02-11 23:04:22 +00:00
|
|
|
#include <QtSvg/QSvgGenerator>
|
2015-03-16 19:51:22 +00:00
|
|
|
#include <QInputDialog>
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
#include <QtCore/QDir>
|
|
|
|
|
#include <QtCore/QDateTime>
|
|
|
|
|
#include <QtCore/QUrl>
|
|
|
|
|
|
|
|
|
|
#include <rtabmap/core/util3d.h>
|
|
|
|
|
#include <rtabmap/gui/UCv2Qt.h>
|
|
|
|
|
#include <rtabmap/utilite/UStl.h>
|
2014-07-29 21:48:37 +00:00
|
|
|
#include <rtabmap/utilite/ULogger.h>
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
namespace rtabmap {
|
|
|
|
|
|
|
|
|
|
class NodeItem: public QGraphicsEllipseItem
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// in meter
|
2015-05-22 15:06:05 -04:00
|
|
|
NodeItem(int id, int mapId, const Transform & pose, float radius) :
|
2014-02-11 23:04:22 +00:00
|
|
|
QGraphicsEllipseItem(QRectF(-radius,-radius,radius*2.0f,radius*2.0f)),
|
|
|
|
|
_id(id),
|
2015-05-22 15:06:05 -04:00
|
|
|
_mapId(mapId),
|
2014-07-29 21:48:37 +00:00
|
|
|
_pose(pose)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
this->setPos(-pose.y(),-pose.x());
|
|
|
|
|
this->setBrush(pen().color());
|
|
|
|
|
this->setAcceptHoverEvents(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
QPen p = this->pen();
|
|
|
|
|
p.setColor(color);
|
|
|
|
|
this->setPen(p);
|
|
|
|
|
QBrush b = this->brush();
|
|
|
|
|
b.setColor(color);
|
|
|
|
|
this->setBrush(b);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 00:29:54 -04:00
|
|
|
const Transform & pose() const {return _pose;}
|
2014-02-11 23:04:22 +00:00
|
|
|
void setPose(const Transform & pose) {this->setPos(-pose.y(),-pose.x()); _pose=pose;}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
|
|
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
this->setToolTip(QString("%1 [%2] %3").arg(_id).arg(_mapId).arg(_pose.prettyPrint().c_str()));
|
2014-02-11 23:04:22 +00:00
|
|
|
this->setScale(2);
|
|
|
|
|
QGraphicsEllipseItem::hoverEnterEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
|
|
|
|
|
{
|
|
|
|
|
this->setScale(1);
|
|
|
|
|
QGraphicsEllipseItem::hoverEnterEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
int _id;
|
2015-05-22 15:06:05 -04:00
|
|
|
int _mapId;
|
2014-02-11 23:04:22 +00:00
|
|
|
Transform _pose;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class LinkItem: public QGraphicsLineItem
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// in meter
|
2015-05-22 15:06:05 -04:00
|
|
|
LinkItem(int from, int to, const Transform & poseA, const Transform & poseB, Link::Type type, bool interSessionClosure) :
|
2014-02-11 23:04:22 +00:00
|
|
|
QGraphicsLineItem(-poseA.y(), -poseA.x(), -poseB.y(), -poseB.x()),
|
2015-01-07 17:30:20 -05:00
|
|
|
_from(from),
|
|
|
|
|
_to(to),
|
2014-02-11 23:04:22 +00:00
|
|
|
_poseA(poseA),
|
|
|
|
|
_poseB(poseB),
|
2015-05-22 15:06:05 -04:00
|
|
|
_type(type),
|
|
|
|
|
_interSession(interSessionClosure)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
this->setAcceptHoverEvents(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
QPen p = this->pen();
|
|
|
|
|
p.setColor(color);
|
|
|
|
|
this->setPen(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setPoses(const Transform & poseA, const Transform & poseB)
|
|
|
|
|
{
|
|
|
|
|
this->setLine(-poseA.y(), -poseA.x(), -poseB.y(), -poseB.x());
|
|
|
|
|
_poseA = poseA;
|
|
|
|
|
_poseB = poseB;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-30 15:30:57 -05:00
|
|
|
Link::Type linkType() const {return _type;}
|
2015-05-22 15:06:05 -04:00
|
|
|
bool isInterSession() const {return _interSession;}
|
2015-01-07 17:30:20 -05:00
|
|
|
int from() const {return _from;}
|
|
|
|
|
int to() const {return _to;}
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
|
|
|
|
|
{
|
2015-04-27 18:16:04 -04:00
|
|
|
this->setToolTip(QString("%1->%2 %3 m").arg(_from).arg(_to).arg(_poseA.getDistance(_poseB)));
|
|
|
|
|
QPen pen = this->pen();
|
|
|
|
|
pen.setWidthF(pen.widthF()+0.02);
|
|
|
|
|
this->setPen(pen);
|
2014-02-11 23:04:22 +00:00
|
|
|
QGraphicsLineItem::hoverEnterEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
|
|
|
|
|
{
|
2015-04-27 18:16:04 -04:00
|
|
|
QPen pen = this->pen();
|
|
|
|
|
pen.setWidthF(pen.widthF()-0.02);
|
|
|
|
|
this->setPen(pen);
|
2014-02-11 23:04:22 +00:00
|
|
|
QGraphicsLineItem::hoverEnterEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2015-01-07 17:30:20 -05:00
|
|
|
int _from;
|
|
|
|
|
int _to;
|
2014-02-11 23:04:22 +00:00
|
|
|
Transform _poseA;
|
|
|
|
|
Transform _poseB;
|
2015-01-30 15:30:57 -05:00
|
|
|
Link::Type _type;
|
2015-05-22 15:06:05 -04:00
|
|
|
bool _interSession;
|
2014-02-11 23:04:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
GraphViewer::GraphViewer(QWidget * parent) :
|
|
|
|
|
QGraphicsView(parent),
|
|
|
|
|
_nodeColor(Qt::blue),
|
2015-05-03 18:16:55 -04:00
|
|
|
_currentGoalColor(Qt::darkMagenta),
|
2014-02-11 23:04:22 +00:00
|
|
|
_neighborColor(Qt::blue),
|
|
|
|
|
_loopClosureColor(Qt::red),
|
2015-01-30 15:30:57 -05:00
|
|
|
_loopClosureLocalColor(Qt::yellow),
|
|
|
|
|
_loopClosureUserColor(Qt::red),
|
|
|
|
|
_loopClosureVirtualColor(Qt::magenta),
|
2015-04-17 18:30:12 -04:00
|
|
|
_localPathColor(Qt::cyan),
|
|
|
|
|
_globalPathColor(Qt::darkMagenta),
|
2015-05-22 15:06:05 -04:00
|
|
|
_loopIntraSessionColor(Qt::red),
|
|
|
|
|
_loopInterSessionColor(Qt::green),
|
|
|
|
|
_intraInterSessionColors(false),
|
2014-02-11 23:04:22 +00:00
|
|
|
_root(0),
|
2014-06-23 20:43:08 +00:00
|
|
|
_nodeRadius(0.01),
|
2014-02-13 21:32:46 +00:00
|
|
|
_linkWidth(0),
|
2014-06-09 20:47:35 +00:00
|
|
|
_gridMap(0),
|
2015-02-17 17:53:44 -05:00
|
|
|
_referential(0),
|
2015-05-03 18:16:55 -04:00
|
|
|
_gridCellSize(0.0f),
|
|
|
|
|
_localRadius(0)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
this->setScene(new QGraphicsScene(this));
|
|
|
|
|
this->setDragMode(QGraphicsView::ScrollHandDrag);
|
|
|
|
|
_workingDirectory = QDir::homePath();
|
|
|
|
|
|
|
|
|
|
this->scene()->clear();
|
2015-01-06 10:53:43 -05:00
|
|
|
_root = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
// add referential
|
2015-02-18 14:15:46 -05:00
|
|
|
_originReferential = new QGraphicsItemGroup();
|
|
|
|
|
this->scene()->addItem(_originReferential); // ownership transfered
|
2014-02-11 23:04:22 +00:00
|
|
|
QGraphicsLineItem * item = this->scene()->addLine(0,0,0,-1, QPen(QBrush(Qt::red), _linkWidth));
|
|
|
|
|
item->setZValue(100);
|
|
|
|
|
item->setParentItem(_root);
|
2015-02-18 14:15:46 -05:00
|
|
|
_originReferential->addToGroup(item);
|
2014-02-11 23:04:22 +00:00
|
|
|
item = this->scene()->addLine(0,0,-1,0, QPen(QBrush(Qt::green), _linkWidth));
|
|
|
|
|
item->setZValue(100);
|
|
|
|
|
item->setParentItem(_root);
|
2015-02-18 14:15:46 -05:00
|
|
|
_originReferential->addToGroup(item);
|
2014-02-11 23:04:22 +00:00
|
|
|
|
2014-07-03 20:16:39 +00:00
|
|
|
// current pose
|
2015-02-17 17:53:44 -05:00
|
|
|
_referential = new QGraphicsItemGroup();
|
2015-02-18 14:15:46 -05:00
|
|
|
this->scene()->addItem(_referential); // ownership transfered
|
2014-07-03 20:16:39 +00:00
|
|
|
item = this->scene()->addLine(0,0,0,-0.5, QPen(QBrush(Qt::red), _linkWidth));
|
|
|
|
|
item->setZValue(100);
|
|
|
|
|
item->setParentItem(_root);
|
2015-02-17 17:53:44 -05:00
|
|
|
_referential->addToGroup(item);
|
2014-07-03 20:16:39 +00:00
|
|
|
item = this->scene()->addLine(0,0,-0.5,0, QPen(QBrush(Qt::green), _linkWidth));
|
|
|
|
|
item->setZValue(100);
|
|
|
|
|
item->setParentItem(_root);
|
2015-02-17 17:53:44 -05:00
|
|
|
_referential->addToGroup(item);
|
2014-07-03 20:16:39 +00:00
|
|
|
|
2015-05-03 18:16:55 -04:00
|
|
|
_localRadius = this->scene()->addEllipse(-0.0001,-0.0001,0.0001,0.0001);
|
|
|
|
|
_localRadius->setZValue(1);
|
|
|
|
|
_localRadius->setParentItem(_root);
|
|
|
|
|
_localRadius->setVisible(false);
|
|
|
|
|
_localRadius->setPen(QPen(Qt::DashLine));
|
2014-07-03 20:16:39 +00:00
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
_gridMap = this->scene()->addPixmap(QPixmap());
|
|
|
|
|
_gridMap->setZValue(0);
|
|
|
|
|
_gridMap->setParentItem(_root);
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
this->restoreDefaults();
|
2015-05-03 18:16:55 -04:00
|
|
|
|
|
|
|
|
this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GraphViewer::~GraphViewer()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
|
2015-05-22 15:06:05 -04:00
|
|
|
const std::multimap<int, Link> & constraints,
|
|
|
|
|
const std::map<int, int> & mapIds)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-02-03 11:09:10 -05:00
|
|
|
bool wasEmpty = _nodeItems.size() == 0 && _linkItems.size() == 0;
|
2015-01-07 17:30:20 -05:00
|
|
|
UDEBUG("poses=%d constraints=%d", (int)poses.size(), (int)constraints.size());
|
2014-02-11 23:04:22 +00:00
|
|
|
//Hide nodes and links
|
|
|
|
|
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->hide();
|
|
|
|
|
iter.value()->setColor(_nodeColor); // reset color
|
|
|
|
|
}
|
2015-01-30 17:27:34 -05:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter = _linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
iter.value()->hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
|
|
|
|
{
|
2015-01-07 17:30:20 -05:00
|
|
|
if(!iter->second.isNull())
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-07 17:30:20 -05:00
|
|
|
QMap<int, NodeItem*>::iterator itemIter = _nodeItems.find(iter->first);
|
|
|
|
|
if(itemIter != _nodeItems.end())
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setPose(iter->second);
|
|
|
|
|
itemIter.value()->show();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// create node item
|
|
|
|
|
const Transform & pose = iter->second;
|
2015-05-22 15:06:05 -04:00
|
|
|
NodeItem * item = new NodeItem(iter->first, uContains(mapIds, iter->first)?mapIds.at(iter->first):-1, pose, _nodeRadius);
|
2015-01-07 17:30:20 -05:00
|
|
|
this->scene()->addItem(item);
|
2015-05-03 18:16:55 -04:00
|
|
|
item->setZValue(20);
|
2015-01-07 17:30:20 -05:00
|
|
|
item->setColor(_nodeColor);
|
|
|
|
|
item->setParentItem(_root);
|
|
|
|
|
_nodeItems.insert(iter->first, item);
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(std::multimap<int, Link>::const_iterator iter=constraints.begin(); iter!=constraints.end(); ++iter)
|
|
|
|
|
{
|
2015-02-03 11:09:10 -05:00
|
|
|
// make the first id the smallest one
|
|
|
|
|
int idFrom = iter->first<iter->second.to()?iter->first:iter->second.to();
|
|
|
|
|
int idTo = iter->first<iter->second.to()?iter->second.to():iter->first;
|
|
|
|
|
|
|
|
|
|
std::map<int, Transform>::const_iterator jterA = poses.find(idFrom);
|
|
|
|
|
std::map<int, Transform>::const_iterator jterB = poses.find(idTo);
|
2015-01-07 17:30:20 -05:00
|
|
|
if(jterA != poses.end() && jterB != poses.end() &&
|
2015-02-03 11:09:10 -05:00
|
|
|
_nodeItems.contains(iter->first) && _nodeItems.contains(idTo))
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
const Transform & poseA = jterA->second;
|
|
|
|
|
const Transform & poseB = jterB->second;
|
|
|
|
|
|
2015-01-07 17:30:20 -05:00
|
|
|
bool added = false;
|
2015-02-03 11:09:10 -05:00
|
|
|
if(_linkItems.contains(idFrom))
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 17:27:34 -05:00
|
|
|
QMultiMap<int, LinkItem*>::iterator itemIter = _linkItems.find(iter->first);
|
2015-02-03 11:09:10 -05:00
|
|
|
while(itemIter.key() == idFrom && itemIter != _linkItems.end())
|
2015-01-07 17:30:20 -05:00
|
|
|
{
|
2015-02-03 11:09:10 -05:00
|
|
|
if(itemIter.value()->to() == idTo)
|
2015-01-07 17:30:20 -05:00
|
|
|
{
|
|
|
|
|
itemIter.value()->setPoses(poseA, poseB);
|
|
|
|
|
itemIter.value()->show();
|
|
|
|
|
added = true;
|
2015-02-03 11:09:10 -05:00
|
|
|
// reset color
|
|
|
|
|
if(iter->second.type() == Link::kNeighbor)
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setColor(_neighborColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kVirtualClosure)
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setColor(_loopClosureVirtualColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kUserClosure)
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setColor(_loopClosureUserColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kLocalSpaceClosure || iter->second.type() == Link::kLocalTimeClosure)
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setColor(_loopClosureLocalColor);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setColor(_loopClosureColor);
|
|
|
|
|
}
|
2015-01-07 17:30:20 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++itemIter;
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-07 17:30:20 -05:00
|
|
|
if(!added)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
//create a link item
|
2015-05-22 15:06:05 -04:00
|
|
|
bool interSessionClosure = false;
|
|
|
|
|
if(uContains(mapIds, jterA->first) && uContains(mapIds, jterB->first))
|
|
|
|
|
{
|
|
|
|
|
interSessionClosure = mapIds.at(jterA->first) != mapIds.at(jterB->first);
|
|
|
|
|
}
|
|
|
|
|
LinkItem * item = new LinkItem(idFrom, idTo, poseA, poseB, iter->second.type(), interSessionClosure);
|
2014-02-11 23:04:22 +00:00
|
|
|
QPen p = item->pen();
|
|
|
|
|
p.setWidthF(_linkWidth);
|
|
|
|
|
item->setPen(p);
|
2015-05-22 15:06:05 -04:00
|
|
|
item->setZValue(10);
|
2015-01-30 15:30:57 -05:00
|
|
|
if(iter->second.type() == Link::kNeighbor)
|
|
|
|
|
{
|
|
|
|
|
item->setColor(_neighborColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kVirtualClosure)
|
|
|
|
|
{
|
|
|
|
|
item->setColor(_loopClosureVirtualColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kUserClosure)
|
|
|
|
|
{
|
|
|
|
|
item->setColor(_loopClosureUserColor);
|
|
|
|
|
}
|
|
|
|
|
else if(iter->second.type() == Link::kLocalSpaceClosure || iter->second.type() == Link::kLocalTimeClosure)
|
|
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
if(_intraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
item->setColor(interSessionClosure?_loopInterSessionColor:_loopIntraSessionColor);
|
|
|
|
|
item->setZValue(interSessionClosure?8:9);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
item->setColor(_loopClosureLocalColor);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
if(_intraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
item->setColor(interSessionClosure?_loopInterSessionColor:_loopIntraSessionColor);
|
|
|
|
|
item->setZValue(interSessionClosure?8:9);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
item->setColor(_loopClosureColor);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
2015-05-22 15:06:05 -04:00
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
this->scene()->addItem(item);
|
|
|
|
|
item->setParentItem(_root);
|
2015-02-03 11:09:10 -05:00
|
|
|
_linkItems.insert(idFrom, item);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//remove not used nodes and links
|
|
|
|
|
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end();)
|
|
|
|
|
{
|
|
|
|
|
if(!iter.value()->isVisible())
|
|
|
|
|
{
|
|
|
|
|
delete iter.value();
|
|
|
|
|
iter = _nodeItems.erase(iter);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-30 17:27:34 -05:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter = _linkItems.begin(); iter!=_linkItems.end();)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
if(!iter.value()->isVisible())
|
|
|
|
|
{
|
|
|
|
|
delete iter.value();
|
2015-01-30 17:27:34 -05:00
|
|
|
iter = _linkItems.erase(iter);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_nodeItems.size())
|
|
|
|
|
{
|
2014-07-03 20:16:39 +00:00
|
|
|
(--_nodeItems.end()).value()->setColor(Qt::green);
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
2015-02-03 11:09:10 -05:00
|
|
|
|
2015-02-17 17:53:44 -05:00
|
|
|
if(wasEmpty)
|
2015-02-03 11:09:10 -05:00
|
|
|
{
|
|
|
|
|
this->fitInView(this->scene()->itemsBoundingRect(), Qt::KeepAspectRatio);
|
|
|
|
|
}
|
2015-02-17 17:53:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphViewer::updateReferentialPosition(const Transform & t)
|
|
|
|
|
{
|
|
|
|
|
QTransform qt(t.r11(), t.r12(), t.r21(), t.r22(), -t.o24(), -t.o14());
|
|
|
|
|
_referential->setTransform(qt);
|
2015-05-03 18:16:55 -04:00
|
|
|
_localRadius->setTransform(qt);
|
2015-02-17 17:53:44 -05:00
|
|
|
|
|
|
|
|
this->ensureVisible(_referential);
|
2015-05-05 17:38:38 -04:00
|
|
|
if(_localRadius->isVisible())
|
|
|
|
|
{
|
|
|
|
|
this->ensureVisible(_localRadius, 0, 0);
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
2014-07-29 21:48:37 +00:00
|
|
|
void GraphViewer::updateMap(const cv::Mat & map8U, float resolution, float xMin, float yMin)
|
|
|
|
|
{
|
|
|
|
|
UASSERT(map8U.empty() || (!map8U.empty() && resolution > 0.0f));
|
|
|
|
|
if(!map8U.empty())
|
|
|
|
|
{
|
|
|
|
|
_gridCellSize = resolution;
|
|
|
|
|
QImage image = uCvMat2QImage(map8U, false);
|
|
|
|
|
_gridMap->resetTransform();
|
2015-03-16 19:51:22 +00:00
|
|
|
_gridMap->setTransform(QTransform::fromScale(resolution, -resolution), true);
|
2014-07-29 21:48:37 +00:00
|
|
|
_gridMap->setRotation(90);
|
|
|
|
|
_gridMap->setPixmap(QPixmap::fromImage(image));
|
|
|
|
|
_gridMap->setPos(-yMin, -xMin);
|
2015-02-23 15:48:25 -05:00
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
2014-07-29 21:48:37 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this->clearMap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-07 17:30:20 -05:00
|
|
|
void GraphViewer::updatePosterior(const std::map<int, float> & posterior)
|
|
|
|
|
{
|
|
|
|
|
//find max
|
|
|
|
|
float max = 0.0f;
|
|
|
|
|
for(std::map<int, float>::const_iterator iter = posterior.begin(); iter!=posterior.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
if(iter->first > 0 && iter->second>max)
|
|
|
|
|
{
|
|
|
|
|
max = iter->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(max > 0.0f)
|
|
|
|
|
{
|
|
|
|
|
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
std::map<int,float>::const_iterator jter = posterior.find(iter.key());
|
|
|
|
|
if(jter != posterior.end())
|
|
|
|
|
{
|
|
|
|
|
UDEBUG("id=%d max=%f hyp=%f color = %f", iter.key(), max, jter->second, (1-jter->second/max)*240.0f/360.0f);
|
|
|
|
|
iter.value()->setColor(QColor::fromHsvF((1-jter->second/max)*240.0f/360.0f, 1, 1, 1)); //0=red 240=blue
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(QColor::fromHsvF(240.0f/360.0f, 1, 1, 1)); // blue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 18:30:12 -04:00
|
|
|
void GraphViewer::setGlobalPath(const std::vector<std::pair<int, Transform> > & globalPath)
|
|
|
|
|
{
|
|
|
|
|
UDEBUG("Set global path size=%d", (int)globalPath.size());
|
|
|
|
|
qDeleteAll(_globalPathLinkItems);
|
|
|
|
|
_globalPathLinkItems.clear();
|
|
|
|
|
|
|
|
|
|
if(globalPath.size() >= 2)
|
|
|
|
|
{
|
|
|
|
|
for(unsigned int i=0; i<globalPath.size()-1; ++i)
|
|
|
|
|
{
|
|
|
|
|
//create a link item
|
|
|
|
|
int idFrom = globalPath[i].first;
|
|
|
|
|
int idTo = globalPath[i+1].first;
|
2015-05-22 15:06:05 -04:00
|
|
|
LinkItem * item = new LinkItem(idFrom, idTo, globalPath[i].second, globalPath[i+1].second, Link::kUndef, false);
|
2015-04-17 18:30:12 -04:00
|
|
|
QPen p = item->pen();
|
|
|
|
|
p.setWidthF(_linkWidth);
|
|
|
|
|
item->setPen(p);
|
|
|
|
|
item->setColor(_globalPathColor);
|
|
|
|
|
this->scene()->addItem(item);
|
2015-05-03 18:16:55 -04:00
|
|
|
item->setZValue(15);
|
2015-04-17 18:30:12 -04:00
|
|
|
item->setParentItem(_root);
|
|
|
|
|
_globalPathLinkItems.insert(idFrom, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-03 18:16:55 -04:00
|
|
|
void GraphViewer::setCurrentGoalID(int id)
|
|
|
|
|
{
|
|
|
|
|
NodeItem * node = _nodeItems.value(id, 0);
|
|
|
|
|
if(node)
|
|
|
|
|
{
|
|
|
|
|
node->setColor(_currentGoalColor);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UWARN("Curent goal %d not found in the graph", id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphViewer::setLocalRadius(float radius)
|
|
|
|
|
{
|
|
|
|
|
_localRadius->setRect(-radius, -radius, radius*2, radius*2);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 11:09:10 -05:00
|
|
|
void GraphViewer::updateLocalPath(const std::vector<int> & localPath)
|
|
|
|
|
{
|
2015-05-06 00:29:54 -04:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter = _localPathLinkItems.begin(); iter!=_localPathLinkItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->hide();
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 11:09:10 -05:00
|
|
|
if(localPath.size() > 1)
|
|
|
|
|
{
|
|
|
|
|
for(unsigned int i=0; i<localPath.size()-1; ++i)
|
|
|
|
|
{
|
2015-05-06 00:29:54 -04:00
|
|
|
int idFrom = localPath[i]<localPath[i+1]?localPath[i]:localPath[i+1];
|
|
|
|
|
int idTo = localPath[i]<localPath[i+1]?localPath[i+1]:localPath[i];
|
|
|
|
|
if(_nodeItems.contains(idFrom) && _nodeItems.contains(idTo))
|
2015-02-03 11:09:10 -05:00
|
|
|
{
|
2015-05-06 00:29:54 -04:00
|
|
|
bool updated = false;
|
|
|
|
|
if(_localPathLinkItems.contains(idFrom))
|
2015-02-03 11:09:10 -05:00
|
|
|
{
|
2015-05-06 00:29:54 -04:00
|
|
|
QMultiMap<int, LinkItem*>::iterator itemIter = _localPathLinkItems.find(idFrom);
|
|
|
|
|
while(itemIter.key() == idFrom && itemIter != _localPathLinkItems.end())
|
2015-02-03 11:09:10 -05:00
|
|
|
{
|
2015-05-06 00:29:54 -04:00
|
|
|
if(itemIter.value()->to() == idTo)
|
|
|
|
|
{
|
|
|
|
|
itemIter.value()->setPoses(_nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose());
|
|
|
|
|
itemIter.value()->show();
|
|
|
|
|
updated = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++itemIter;
|
2015-02-03 11:09:10 -05:00
|
|
|
}
|
2015-05-06 00:29:54 -04:00
|
|
|
}
|
|
|
|
|
if(!updated)
|
|
|
|
|
{
|
|
|
|
|
//create a link item
|
2015-05-22 15:06:05 -04:00
|
|
|
LinkItem * item = new LinkItem(idFrom, idTo, _nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose(), Link::kUndef, false);
|
2015-05-06 00:29:54 -04:00
|
|
|
QPen p = item->pen();
|
|
|
|
|
p.setWidthF(_linkWidth);
|
|
|
|
|
item->setPen(p);
|
|
|
|
|
item->setColor(_localPathColor);
|
|
|
|
|
this->scene()->addItem(item);
|
|
|
|
|
item->setZValue(16); // just over the global path
|
|
|
|
|
item->setParentItem(_root);
|
|
|
|
|
_localPathLinkItems.insert(idFrom, item);
|
2015-02-03 11:09:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-06 00:29:54 -04:00
|
|
|
|
|
|
|
|
// remove not used links
|
|
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter = _localPathLinkItems.begin(); iter!=_localPathLinkItems.end();)
|
|
|
|
|
{
|
|
|
|
|
if(!iter.value()->isVisible())
|
|
|
|
|
{
|
|
|
|
|
delete iter.value();
|
|
|
|
|
iter = _localPathLinkItems.erase(iter);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++iter;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-03 11:09:10 -05:00
|
|
|
}
|
|
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
void GraphViewer::clearGraph()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(_nodeItems);
|
|
|
|
|
_nodeItems.clear();
|
2015-01-30 17:27:34 -05:00
|
|
|
qDeleteAll(_linkItems);
|
|
|
|
|
_linkItems.clear();
|
2015-05-06 00:29:54 -04:00
|
|
|
qDeleteAll(_localPathLinkItems);
|
|
|
|
|
_localPathLinkItems.clear();
|
2015-04-17 18:30:12 -04:00
|
|
|
qDeleteAll(_globalPathLinkItems);
|
|
|
|
|
_globalPathLinkItems.clear();
|
2015-05-06 00:29:54 -04:00
|
|
|
|
2015-02-17 17:53:44 -05:00
|
|
|
_referential->resetTransform();
|
2015-05-03 18:16:55 -04:00
|
|
|
_localRadius->resetTransform();
|
2014-02-11 23:04:22 +00:00
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 21:48:37 +00:00
|
|
|
void GraphViewer::clearMap()
|
|
|
|
|
{
|
|
|
|
|
_gridMap->setPixmap(QPixmap());
|
2015-02-18 14:17:53 -05:00
|
|
|
_gridCellSize = 0.0f;
|
2015-02-23 15:48:25 -05:00
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
2014-07-29 21:48:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-01-07 17:30:20 -05:00
|
|
|
void GraphViewer::clearPosterior()
|
|
|
|
|
{
|
|
|
|
|
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(Qt::blue); // blue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 21:48:37 +00:00
|
|
|
void GraphViewer::clearAll()
|
|
|
|
|
{
|
|
|
|
|
clearMap();
|
|
|
|
|
clearGraph();
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 17:27:44 -05:00
|
|
|
void GraphViewer::saveSettings(QSettings & settings, const QString & group) const
|
|
|
|
|
{
|
|
|
|
|
if(!group.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
settings.beginGroup(group);
|
|
|
|
|
}
|
2015-04-06 00:28:04 -04:00
|
|
|
settings.setValue("node_radius", (double)this->getNodeRadius());
|
|
|
|
|
settings.setValue("link_width", (double)this->getLinkWidth());
|
2015-03-04 17:27:44 -05:00
|
|
|
settings.setValue("node_color", this->getNodeColor());
|
2015-05-03 18:16:55 -04:00
|
|
|
settings.setValue("current_goal_color", this->getCurrentGoalColor());
|
2015-03-04 17:27:44 -05:00
|
|
|
settings.setValue("neighbor_color", this->getNeighborColor());
|
|
|
|
|
settings.setValue("global_color", this->getGlobalLoopClosureColor());
|
|
|
|
|
settings.setValue("local_color", this->getLocalLoopClosureColor());
|
|
|
|
|
settings.setValue("user_color", this->getUserLoopClosureColor());
|
|
|
|
|
settings.setValue("virtual_color", this->getVirtualLoopClosureColor());
|
|
|
|
|
settings.setValue("local_path_color", this->getLocalPathColor());
|
2015-04-17 18:30:12 -04:00
|
|
|
settings.setValue("global_path_color", this->getGlobalPathColor());
|
2015-05-22 15:06:05 -04:00
|
|
|
settings.setValue("intra_session_color", this->getIntraSessionLoopColor());
|
|
|
|
|
settings.setValue("inter_session_color", this->getInterSessionLoopColor());
|
|
|
|
|
settings.setValue("intra_inter_session_colors_enabled", this->isIntraInterSessionColorsEnabled());
|
2015-03-04 17:27:44 -05:00
|
|
|
settings.setValue("grid_visible", this->isGridMapVisible());
|
|
|
|
|
settings.setValue("origin_visible", this->isOriginVisible());
|
|
|
|
|
settings.setValue("referential_visible", this->isReferentialVisible());
|
2015-05-03 18:16:55 -04:00
|
|
|
settings.setValue("local_radius_visible", this->isLocalRadiusVisible());
|
2015-03-04 17:27:44 -05:00
|
|
|
if(!group.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
settings.endGroup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphViewer::loadSettings(QSettings & settings, const QString & group)
|
|
|
|
|
{
|
|
|
|
|
if(!group.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
settings.beginGroup(group);
|
|
|
|
|
}
|
|
|
|
|
this->setNodeRadius(settings.value("node_radius", this->getNodeRadius()).toDouble());
|
|
|
|
|
this->setLinkWidth(settings.value("link_width", this->getLinkWidth()).toDouble());
|
|
|
|
|
this->setNodeColor(settings.value("node_color", this->getNodeColor()).value<QColor>());
|
2015-05-03 18:16:55 -04:00
|
|
|
this->setCurrentGoalColor(settings.value("current_goal_color", this->getCurrentGoalColor()).value<QColor>());
|
2015-03-04 17:27:44 -05:00
|
|
|
this->setNeighborColor(settings.value("neighbor_color", this->getNeighborColor()).value<QColor>());
|
|
|
|
|
this->setGlobalLoopClosureColor(settings.value("global_color", this->getGlobalLoopClosureColor()).value<QColor>());
|
|
|
|
|
this->setLocalLoopClosureColor(settings.value("local_color", this->getLocalLoopClosureColor()).value<QColor>());
|
|
|
|
|
this->setUserLoopClosureColor(settings.value("user_color", this->getUserLoopClosureColor()).value<QColor>());
|
|
|
|
|
this->setVirtualLoopClosureColor(settings.value("virtual_color", this->getVirtualLoopClosureColor()).value<QColor>());
|
|
|
|
|
this->setLocalPathColor(settings.value("local_path_color", this->getLocalPathColor()).value<QColor>());
|
2015-04-17 18:30:12 -04:00
|
|
|
this->setGlobalPathColor(settings.value("global_path_color", this->getGlobalPathColor()).value<QColor>());
|
2015-05-22 15:06:05 -04:00
|
|
|
this->setIntraSessionLoopColor(settings.value("intra_session_color", this->getIntraSessionLoopColor()).value<QColor>());
|
|
|
|
|
this->setInterSessionLoopColor(settings.value("inter_session_color", this->getInterSessionLoopColor()).value<QColor>());
|
2015-03-04 17:27:44 -05:00
|
|
|
this->setGridMapVisible(settings.value("grid_visible", this->isGridMapVisible()).toBool());
|
|
|
|
|
this->setOriginVisible(settings.value("origin_visible", this->isOriginVisible()).toBool());
|
|
|
|
|
this->setReferentialVisible(settings.value("referential_visible", this->isReferentialVisible()).toBool());
|
2015-05-03 18:16:55 -04:00
|
|
|
this->setLocalRadiusVisible(settings.value("local_radius_visible", this->isLocalRadiusVisible()).toBool());
|
2015-05-22 15:06:05 -04:00
|
|
|
this->setIntraInterSessionColorsEnabled(settings.value("intra_inter_session_colors_enabled", this->isIntraInterSessionColorsEnabled()).toBool());
|
2015-03-04 17:27:44 -05:00
|
|
|
if(!group.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
settings.endGroup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-30 15:30:57 -05:00
|
|
|
bool GraphViewer::isGridMapVisible() const
|
|
|
|
|
{
|
|
|
|
|
return _gridMap->isVisible();
|
|
|
|
|
}
|
2015-02-18 14:15:46 -05:00
|
|
|
bool GraphViewer::isOriginVisible() const
|
|
|
|
|
{
|
|
|
|
|
return _originReferential->isVisible();
|
|
|
|
|
}
|
|
|
|
|
bool GraphViewer::isReferentialVisible() const
|
|
|
|
|
{
|
|
|
|
|
return _referential->isVisible();
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
bool GraphViewer::isLocalRadiusVisible() const
|
|
|
|
|
{
|
|
|
|
|
return _localRadius->isVisible();
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
void GraphViewer::setWorkingDirectory(const QString & path)
|
|
|
|
|
{
|
|
|
|
|
_workingDirectory = path;
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setNodeRadius(float radius)
|
|
|
|
|
{
|
|
|
|
|
_nodeRadius = radius;
|
2015-01-30 17:19:51 -05:00
|
|
|
for(QMap<int, NodeItem*>::iterator iter=_nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
iter.value()->setRect(-_nodeRadius, -_nodeRadius, _nodeRadius*2.0f, _nodeRadius*2.0f);
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setLinkWidth(float width)
|
|
|
|
|
{
|
|
|
|
|
_linkWidth = width;
|
|
|
|
|
QList<QGraphicsItem*> items = this->scene()->items();
|
|
|
|
|
for(int i=0; i<items.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
QGraphicsLineItem * line = qgraphicsitem_cast<QGraphicsLineItem *>(items[i]);
|
|
|
|
|
if(line)
|
|
|
|
|
{
|
|
|
|
|
QPen pen = line->pen();
|
|
|
|
|
pen.setWidthF(_linkWidth);
|
|
|
|
|
line->setPen(pen);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setNodeColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_nodeColor = color;
|
2015-01-30 17:19:51 -05:00
|
|
|
for(QMap<int, NodeItem*>::iterator iter=_nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
iter.value()->setColor(_nodeColor);
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
void GraphViewer::setCurrentGoalColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_currentGoalColor = color;
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
void GraphViewer::setNeighborColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_neighborColor = color;
|
2015-01-30 17:27:34 -05:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:27:34 -05:00
|
|
|
if(iter.value()->linkType() == Link::kNeighbor)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(_neighborColor);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setGlobalLoopClosureColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopClosureColor = color;
|
2015-05-22 15:06:05 -04:00
|
|
|
if(!_intraInterSessionColors)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
if(iter.value()->linkType() == Link::kGlobalClosure)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(_loopClosureColor);
|
|
|
|
|
iter.value()->setZValue(10);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setLocalLoopClosureColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopClosureLocalColor = color;
|
2015-05-22 15:06:05 -04:00
|
|
|
if(!_intraInterSessionColors)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-05-22 15:06:05 -04:00
|
|
|
if(iter.value()->linkType() == Link::kLocalSpaceClosure ||
|
|
|
|
|
iter.value()->linkType() == Link::kLocalTimeClosure)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(_loopClosureLocalColor);
|
|
|
|
|
iter.value()->setZValue(10);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setUserLoopClosureColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopClosureUserColor = color;
|
2015-01-30 17:27:34 -05:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
if(iter.value()->linkType() == Link::kUserClosure)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
iter.value()->setColor(_loopClosureUserColor);
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setVirtualLoopClosureColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopClosureVirtualColor = color;
|
2015-01-30 17:27:34 -05:00
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
if(iter.value()->linkType() == Link::kVirtualClosure)
|
2015-01-30 15:30:57 -05:00
|
|
|
{
|
2015-01-30 17:19:51 -05:00
|
|
|
iter.value()->setColor(_loopClosureVirtualColor);
|
2015-01-30 15:30:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-03 11:09:10 -05:00
|
|
|
void GraphViewer::setLocalPathColor(const QColor & color)
|
|
|
|
|
{
|
2015-04-17 18:30:12 -04:00
|
|
|
_localPathColor = color;
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setGlobalPathColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_globalPathColor = color;
|
2015-02-03 11:09:10 -05:00
|
|
|
}
|
2015-05-22 15:06:05 -04:00
|
|
|
void GraphViewer::setIntraSessionLoopColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopIntraSessionColor = color;
|
|
|
|
|
if(_intraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
if((iter.value()->linkType() == Link::kGlobalClosure ||
|
|
|
|
|
iter.value()->linkType() == Link::kLocalSpaceClosure ||
|
|
|
|
|
iter.value()->linkType() == Link::kLocalTimeClosure) &&
|
|
|
|
|
!iter.value()->isInterSession())
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(_loopIntraSessionColor);
|
|
|
|
|
iter.value()->setZValue(9);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setInterSessionLoopColor(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
_loopInterSessionColor = color;
|
|
|
|
|
if(_intraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
if((iter.value()->linkType() == Link::kGlobalClosure ||
|
|
|
|
|
iter.value()->linkType() == Link::kLocalSpaceClosure ||
|
|
|
|
|
iter.value()->linkType() == Link::kLocalTimeClosure) &&
|
|
|
|
|
iter.value()->isInterSession())
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setColor(_loopInterSessionColor);
|
|
|
|
|
iter.value()->setZValue(8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphViewer::setIntraInterSessionColorsEnabled(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
_intraInterSessionColors = enabled;
|
|
|
|
|
if(_intraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
this->setIntraSessionLoopColor(_loopIntraSessionColor);
|
|
|
|
|
this->setInterSessionLoopColor(_loopInterSessionColor);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this->setGlobalLoopClosureColor(_loopClosureColor);
|
|
|
|
|
this->setLocalLoopClosureColor(_loopClosureLocalColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-30 15:30:57 -05:00
|
|
|
void GraphViewer::setGridMapVisible(bool visible)
|
|
|
|
|
{
|
|
|
|
|
_gridMap->setVisible(visible);
|
|
|
|
|
}
|
2015-02-18 14:15:46 -05:00
|
|
|
void GraphViewer::setOriginVisible(bool visible)
|
|
|
|
|
{
|
|
|
|
|
_originReferential->setVisible(visible);
|
|
|
|
|
}
|
|
|
|
|
void GraphViewer::setReferentialVisible(bool visible)
|
|
|
|
|
{
|
|
|
|
|
_referential->setVisible(visible);
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
void GraphViewer::setLocalRadiusVisible(bool visible)
|
|
|
|
|
{
|
|
|
|
|
_localRadius->setVisible(visible);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
void GraphViewer::restoreDefaults()
|
|
|
|
|
{
|
|
|
|
|
setNodeRadius(0.01f);
|
|
|
|
|
setLinkWidth(0.0f);
|
|
|
|
|
setNodeColor(Qt::blue);
|
|
|
|
|
setNeighborColor(Qt::blue);
|
|
|
|
|
setGlobalLoopClosureColor(Qt::red);
|
|
|
|
|
setLocalLoopClosureColor(Qt::yellow);
|
|
|
|
|
setUserLoopClosureColor(Qt::red);
|
|
|
|
|
setVirtualLoopClosureColor(Qt::magenta);
|
|
|
|
|
setGridMapVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
void GraphViewer::wheelEvent ( QWheelEvent * event )
|
|
|
|
|
{
|
2015-02-23 18:20:31 -05:00
|
|
|
if(event->delta() < 0)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
this->scale(0.95, 0.95);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this->scale(1.05, 1.05);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-30 15:30:57 -05:00
|
|
|
QIcon createIcon(const QColor & color)
|
|
|
|
|
{
|
|
|
|
|
QPixmap pixmap(50, 50);
|
|
|
|
|
pixmap.fill(color);
|
|
|
|
|
return QIcon(pixmap);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
|
|
|
|
{
|
|
|
|
|
QMenu menu;
|
|
|
|
|
QAction * aScreenShotPNG = menu.addAction(tr("Take a screenshot (PNG)"));
|
|
|
|
|
QAction * aScreenShotSVG = menu.addAction(tr("Take a screenshot (SVG)"));
|
|
|
|
|
menu.addSeparator();
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
QAction * aChangeNodeColor = menu.addAction(createIcon(_nodeColor), tr("Set node color..."));
|
2015-05-03 18:16:55 -04:00
|
|
|
QAction * aChangeCurrentGoalColor = menu.addAction(createIcon(_currentGoalColor), tr("Set current goal color..."));
|
2015-01-30 15:30:57 -05:00
|
|
|
aChangeNodeColor->setIconVisibleInMenu(true);
|
2015-05-03 18:16:55 -04:00
|
|
|
aChangeCurrentGoalColor->setIconVisibleInMenu(true);
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
// Links
|
|
|
|
|
QMenu * menuLink = menu.addMenu(tr("Set link color..."));
|
|
|
|
|
QAction * aChangeNeighborColor = menuLink->addAction(tr("Neighbor"));
|
|
|
|
|
QAction * aChangeGlobalLoopColor = menuLink->addAction(tr("Global loop closure"));
|
|
|
|
|
QAction * aChangeLocalLoopColor = menuLink->addAction(tr("Local loop closure"));
|
|
|
|
|
QAction * aChangeUserLoopColor = menuLink->addAction(tr("User loop closure"));
|
|
|
|
|
QAction * aChangeVirtualLoopColor = menuLink->addAction(tr("Virtual loop closure"));
|
2015-02-03 11:09:10 -05:00
|
|
|
QAction * aChangeLocalPathColor = menuLink->addAction(tr("Local path"));
|
2015-04-17 18:30:12 -04:00
|
|
|
QAction * aChangeGlobalPathColor = menuLink->addAction(tr("Global path"));
|
2015-05-22 15:06:05 -04:00
|
|
|
menuLink->addSeparator();
|
|
|
|
|
QAction * aSetIntraInterSessionColors = menuLink->addAction(tr("Enable intra/inter-session colors"));
|
|
|
|
|
QAction * aChangeIntraSessionLoopColor = menuLink->addAction(tr("Intra-session loop closure"));
|
|
|
|
|
QAction * aChangeInterSessionLoopColor = menuLink->addAction(tr("Inter-session loop closure"));
|
2015-01-30 15:30:57 -05:00
|
|
|
aChangeNeighborColor->setIcon(createIcon(_neighborColor));
|
|
|
|
|
aChangeGlobalLoopColor->setIcon(createIcon(_loopClosureColor));
|
|
|
|
|
aChangeLocalLoopColor->setIcon(createIcon(_loopClosureLocalColor));
|
|
|
|
|
aChangeUserLoopColor->setIcon(createIcon(_loopClosureUserColor));
|
|
|
|
|
aChangeVirtualLoopColor->setIcon(createIcon(_loopClosureVirtualColor));
|
2015-04-17 18:30:12 -04:00
|
|
|
aChangeLocalPathColor->setIcon(createIcon(_localPathColor));
|
|
|
|
|
aChangeGlobalPathColor->setIcon(createIcon(_globalPathColor));
|
2015-05-22 15:06:05 -04:00
|
|
|
aChangeIntraSessionLoopColor->setIcon(createIcon(_loopIntraSessionColor));
|
|
|
|
|
aChangeInterSessionLoopColor->setIcon(createIcon(_loopInterSessionColor));
|
2015-01-30 15:30:57 -05:00
|
|
|
aChangeNeighborColor->setIconVisibleInMenu(true);
|
|
|
|
|
aChangeGlobalLoopColor->setIconVisibleInMenu(true);
|
|
|
|
|
aChangeLocalLoopColor->setIconVisibleInMenu(true);
|
|
|
|
|
aChangeUserLoopColor->setIconVisibleInMenu(true);
|
|
|
|
|
aChangeVirtualLoopColor->setIconVisibleInMenu(true);
|
2015-02-03 11:09:10 -05:00
|
|
|
aChangeLocalPathColor->setIconVisibleInMenu(true);
|
2015-04-17 18:30:12 -04:00
|
|
|
aChangeGlobalPathColor->setIconVisibleInMenu(true);
|
2015-05-22 15:06:05 -04:00
|
|
|
aChangeIntraSessionLoopColor->setIconVisibleInMenu(true);
|
|
|
|
|
aChangeInterSessionLoopColor->setIconVisibleInMenu(true);
|
|
|
|
|
aSetIntraInterSessionColors->setCheckable(true);
|
|
|
|
|
aSetIntraInterSessionColors->setChecked(_intraInterSessionColors);
|
2015-01-30 15:30:57 -05:00
|
|
|
|
2014-02-11 23:04:22 +00:00
|
|
|
menu.addSeparator();
|
|
|
|
|
QAction * aSetNodeSize = menu.addAction(tr("Set node radius..."));
|
|
|
|
|
QAction * aSetLinkSize = menu.addAction(tr("Set link width..."));
|
|
|
|
|
menu.addSeparator();
|
|
|
|
|
QAction * aShowHideGridMap;
|
2015-02-18 14:15:46 -05:00
|
|
|
QAction * aShowHideOrigin;
|
|
|
|
|
QAction * aShowHideReferential;
|
2015-05-03 18:16:55 -04:00
|
|
|
QAction * aShowHideLocalRadius;
|
2015-05-08 14:13:53 -04:00
|
|
|
QAction * aClearGlobalPath;
|
2014-02-11 23:04:22 +00:00
|
|
|
if(_gridMap->isVisible())
|
|
|
|
|
{
|
|
|
|
|
aShowHideGridMap = menu.addAction(tr("Hide grid map"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aShowHideGridMap = menu.addAction(tr("Show grid map"));
|
|
|
|
|
}
|
2015-02-18 14:15:46 -05:00
|
|
|
if(_originReferential->isVisible())
|
|
|
|
|
{
|
|
|
|
|
aShowHideOrigin = menu.addAction(tr("Hide origin referential"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aShowHideOrigin = menu.addAction(tr("Show origin referential"));
|
|
|
|
|
}
|
|
|
|
|
if(_referential->isVisible())
|
|
|
|
|
{
|
|
|
|
|
aShowHideReferential = menu.addAction(tr("Hide current referential"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aShowHideReferential = menu.addAction(tr("Show current referential"));
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
if(_localRadius->isVisible())
|
|
|
|
|
{
|
|
|
|
|
aShowHideLocalRadius = menu.addAction(tr("Hide local radius"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aShowHideLocalRadius = menu.addAction(tr("Show local radius"));
|
|
|
|
|
}
|
2015-05-08 14:13:53 -04:00
|
|
|
if(_globalPathLinkItems.size() && _globalPathLinkItems.begin().value()->isVisible())
|
|
|
|
|
{
|
|
|
|
|
aClearGlobalPath = menu.addAction(tr("Hide global path"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aClearGlobalPath = menu.addAction(tr("Show global path"));
|
|
|
|
|
}
|
|
|
|
|
aClearGlobalPath->setEnabled(_globalPathLinkItems.size());
|
2015-01-30 15:30:57 -05:00
|
|
|
menu.addSeparator();
|
|
|
|
|
QAction * aRestoreDefaults = menu.addAction(tr("Restore defaults"));
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
QAction * r = menu.exec(event->globalPos());
|
|
|
|
|
if(r == aScreenShotPNG || r == aScreenShotSVG)
|
|
|
|
|
{
|
|
|
|
|
if(_root)
|
|
|
|
|
{
|
|
|
|
|
QString targetDir = _workingDirectory + "/ScreensCaptured";
|
|
|
|
|
QDir dir;
|
|
|
|
|
if(!dir.exists(targetDir))
|
|
|
|
|
{
|
|
|
|
|
dir.mkdir(targetDir);
|
|
|
|
|
}
|
|
|
|
|
targetDir += "/";
|
|
|
|
|
targetDir += "Graph_view";
|
|
|
|
|
if(!dir.exists(targetDir))
|
|
|
|
|
{
|
|
|
|
|
dir.mkdir(targetDir);
|
|
|
|
|
}
|
|
|
|
|
targetDir += "/";
|
|
|
|
|
bool isPNG = r == aScreenShotPNG;
|
|
|
|
|
QString name = (QDateTime::currentDateTime().toString("yyMMddhhmmsszzz") + (isPNG?".png":".svg"));
|
|
|
|
|
|
2014-07-29 21:48:37 +00:00
|
|
|
if(_gridCellSize)
|
|
|
|
|
{
|
|
|
|
|
_root->setScale(1.0f/_gridCellSize); // grid map precision (for 5cm grid cell, x20 to have 1pix/5cm)
|
|
|
|
|
}
|
2015-02-18 14:15:46 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_root->setScale(this->transform().m11()); // current view
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
|
|
|
|
|
this->scene()->clearSelection(); // Selections would also render to the file
|
|
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
|
|
|
|
QSize sceneSize = this->scene()->sceneRect().size().toSize();
|
|
|
|
|
|
|
|
|
|
if(isPNG)
|
|
|
|
|
{
|
|
|
|
|
QImage image(sceneSize, QImage::Format_ARGB32); // Create the image with the exact size of the shrunk scene
|
|
|
|
|
image.fill(Qt::transparent); // Start all pixels transparent
|
|
|
|
|
QPainter painter(&image);
|
|
|
|
|
|
|
|
|
|
this->scene()->render(&painter);
|
|
|
|
|
image.save(targetDir + name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
QSvgGenerator svgGen;
|
|
|
|
|
|
|
|
|
|
svgGen.setFileName( targetDir + name );
|
|
|
|
|
svgGen.setSize(sceneSize);
|
|
|
|
|
svgGen.setViewBox(QRect(0, 0, sceneSize.width(), sceneSize.height()));
|
|
|
|
|
svgGen.setTitle(tr("RTAB-Map graph"));
|
|
|
|
|
svgGen.setDescription(tr("RTAB-Map map and graph"));
|
|
|
|
|
|
|
|
|
|
QPainter painter( &svgGen );
|
|
|
|
|
|
|
|
|
|
this->scene()->render(&painter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//reset scale
|
|
|
|
|
_root->setScale(1.0f);
|
|
|
|
|
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(targetDir + name));
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
return; // without emitting configChanged
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-05-22 15:06:05 -04:00
|
|
|
else if(r == aSetIntraInterSessionColors)
|
|
|
|
|
{
|
|
|
|
|
setIntraInterSessionColorsEnabled(aSetIntraInterSessionColors->isChecked());
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
else if(r == aChangeNodeColor ||
|
2015-05-03 18:16:55 -04:00
|
|
|
r == aChangeCurrentGoalColor ||
|
2014-02-11 23:04:22 +00:00
|
|
|
r == aChangeNeighborColor ||
|
2015-01-30 15:30:57 -05:00
|
|
|
r == aChangeGlobalLoopColor ||
|
|
|
|
|
r == aChangeLocalLoopColor ||
|
|
|
|
|
r == aChangeUserLoopColor ||
|
2015-02-03 11:09:10 -05:00
|
|
|
r == aChangeVirtualLoopColor ||
|
2015-04-17 18:30:12 -04:00
|
|
|
r == aChangeLocalPathColor ||
|
2015-05-22 15:06:05 -04:00
|
|
|
r == aChangeGlobalPathColor ||
|
|
|
|
|
r == aChangeIntraSessionLoopColor ||
|
|
|
|
|
r == aChangeInterSessionLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
|
|
|
|
QColor color;
|
|
|
|
|
if(r == aChangeNodeColor)
|
|
|
|
|
{
|
|
|
|
|
color = _nodeColor;
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
else if(r == aChangeCurrentGoalColor)
|
|
|
|
|
{
|
|
|
|
|
color = _currentGoalColor;
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeGlobalLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
color = _loopClosureColor;
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeLocalLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
color = _loopClosureLocalColor;
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeUserLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
color = _loopClosureUserColor;
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeVirtualLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
color = _loopClosureVirtualColor;
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-02-03 11:09:10 -05:00
|
|
|
else if(r == aChangeLocalPathColor)
|
|
|
|
|
{
|
2015-04-17 18:30:12 -04:00
|
|
|
color = _localPathColor;
|
|
|
|
|
}
|
|
|
|
|
else if(r == aChangeGlobalPathColor)
|
|
|
|
|
{
|
|
|
|
|
color = _globalPathColor;
|
2015-02-03 11:09:10 -05:00
|
|
|
}
|
2015-05-22 15:06:05 -04:00
|
|
|
else if(r == aChangeIntraSessionLoopColor)
|
|
|
|
|
{
|
|
|
|
|
color = _loopIntraSessionColor;
|
|
|
|
|
}
|
|
|
|
|
else if(r == aChangeInterSessionLoopColor)
|
|
|
|
|
{
|
|
|
|
|
color = _loopInterSessionColor;
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else //if(r == aChangeNeighborColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
color = _neighborColor;
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
color = QColorDialog::getColor(color, this);
|
|
|
|
|
if(color.isValid())
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
|
|
|
|
|
if(r == aChangeNodeColor)
|
|
|
|
|
{
|
|
|
|
|
this->setNodeColor(color);
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
else if(r == aChangeCurrentGoalColor)
|
|
|
|
|
{
|
|
|
|
|
this->setCurrentGoalColor(color);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeGlobalLoopColor)
|
|
|
|
|
{
|
|
|
|
|
this->setGlobalLoopClosureColor(color);
|
|
|
|
|
}
|
|
|
|
|
else if(r == aChangeLocalLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
this->setLocalLoopClosureColor(color);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeUserLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
this->setUserLoopClosureColor(color);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aChangeVirtualLoopColor)
|
2014-02-11 23:04:22 +00:00
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
this->setVirtualLoopClosureColor(color);
|
|
|
|
|
}
|
2015-02-03 11:09:10 -05:00
|
|
|
else if(r == aChangeLocalPathColor)
|
|
|
|
|
{
|
|
|
|
|
this->setLocalPathColor(color);
|
|
|
|
|
}
|
2015-05-22 15:06:05 -04:00
|
|
|
else if(r == aChangeIntraSessionLoopColor)
|
|
|
|
|
{
|
|
|
|
|
this->setIntraSessionLoopColor(color);
|
|
|
|
|
}
|
|
|
|
|
else if(r == aChangeInterSessionLoopColor)
|
|
|
|
|
{
|
|
|
|
|
this->setInterSessionLoopColor(color);
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else //if(r == aChangeNeighborColor)
|
|
|
|
|
{
|
|
|
|
|
this->setNeighborColor(color);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return; // without emitting configChanged
|
|
|
|
|
}
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
else if(r == aSetNodeSize)
|
|
|
|
|
{
|
|
|
|
|
bool ok;
|
2015-04-17 18:30:12 -04:00
|
|
|
double value = QInputDialog::getDouble(this, tr("Node radius"), tr("Radius (m)"), _nodeRadius, 0.001, 100, 3, &ok);
|
2014-02-11 23:04:22 +00:00
|
|
|
if(ok)
|
|
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
setNodeRadius(value);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(r == aSetLinkSize)
|
|
|
|
|
{
|
|
|
|
|
bool ok;
|
2015-01-07 17:30:20 -05:00
|
|
|
double value = QInputDialog::getDouble(this, tr("Link width"), tr("Width (m)"), _linkWidth, 0, 100, 2, &ok);
|
2014-02-11 23:04:22 +00:00
|
|
|
if(ok)
|
|
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
setLinkWidth(value);
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(r == aShowHideGridMap)
|
|
|
|
|
{
|
2015-01-30 15:30:57 -05:00
|
|
|
this->setGridMapVisible(!this->isGridMapVisible());
|
|
|
|
|
}
|
2015-02-18 14:15:46 -05:00
|
|
|
else if(r == aShowHideOrigin)
|
|
|
|
|
{
|
|
|
|
|
this->setOriginVisible(!this->isOriginVisible());
|
|
|
|
|
}
|
|
|
|
|
else if(r == aShowHideReferential)
|
|
|
|
|
{
|
|
|
|
|
this->setReferentialVisible(!this->isReferentialVisible());
|
|
|
|
|
}
|
2015-05-03 18:16:55 -04:00
|
|
|
else if(r == aShowHideLocalRadius)
|
|
|
|
|
{
|
|
|
|
|
this->setLocalRadiusVisible(!this->isLocalRadiusVisible());
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
else if(r == aRestoreDefaults)
|
|
|
|
|
{
|
|
|
|
|
this->restoreDefaults();
|
|
|
|
|
}
|
2015-05-08 14:13:53 -04:00
|
|
|
else if(r == aClearGlobalPath)
|
|
|
|
|
{
|
|
|
|
|
for(QMap<int, LinkItem*>::iterator iter=_globalPathLinkItems.begin(); iter!=_globalPathLinkItems.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
iter.value()->setVisible(!iter.value()->isVisible());
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-30 15:30:57 -05:00
|
|
|
if(r)
|
|
|
|
|
{
|
|
|
|
|
emit configChanged();
|
2014-02-11 23:04:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} /* namespace rtabmap */
|