mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 09:30:25 +08:00
DbViewer: added "Edit optimized map" and "Regenerate Optimized Map" actions
This commit is contained in:
@@ -32,6 +32,7 @@ SET(headers_ui
|
||||
../include/${PROJECT_PREFIX}/gui/TexturingState.h
|
||||
../include/${PROJECT_PREFIX}/gui/RecoveryState.h
|
||||
../include/${PROJECT_PREFIX}/gui/EditDepthArea.h
|
||||
../include/${PROJECT_PREFIX}/gui/EditMapArea.h
|
||||
)
|
||||
|
||||
SET(uis
|
||||
@@ -98,6 +99,7 @@ SET(SRC_FILES
|
||||
./MapVisibilityWidget.cpp
|
||||
./GraphViewer.cpp
|
||||
./EditDepthArea.cpp
|
||||
./EditMapArea.cpp
|
||||
./CreateSimpleCalibrationDialog.cpp
|
||||
./ParametersToolBox.cpp
|
||||
./DepthCalibrationDialog.cpp
|
||||
|
||||
@@ -75,6 +75,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rtabmap/gui/DataRecorder.h"
|
||||
#include "rtabmap/gui/ExportCloudsDialog.h"
|
||||
#include "rtabmap/gui/EditDepthArea.h"
|
||||
#include "rtabmap/gui/EditMapArea.h"
|
||||
#include "rtabmap/core/SensorData.h"
|
||||
#include "rtabmap/core/GainCompensator.h"
|
||||
#include "rtabmap/gui/ExportDialog.h"
|
||||
@@ -100,6 +101,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
octomap_(0),
|
||||
exportDialog_(new ExportCloudsDialog(this)),
|
||||
editDepthDialog_(new QDialog(this)),
|
||||
editMapDialog_(new QDialog(this)),
|
||||
savedMaximized_(false),
|
||||
firstCall_(true),
|
||||
iniFilePath_(ini),
|
||||
@@ -136,6 +138,20 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
editDepthDialog_->setLayout(vLayout);
|
||||
editDepthDialog_->setWindowTitle(tr("Edit Depth Image"));
|
||||
|
||||
editMapDialog_->resize(640, 480);
|
||||
vLayout = new QVBoxLayout(editMapDialog_);
|
||||
editMapArea_ = new EditMapArea(editMapDialog_);
|
||||
vLayout->setContentsMargins(0,0,0,0);
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->addWidget(editMapArea_, 1);
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel | QDialogButtonBox::Reset, Qt::Horizontal, editMapDialog_);
|
||||
vLayout->addWidget(buttonBox);
|
||||
connect(buttonBox, SIGNAL(accepted()), editMapDialog_, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), editMapDialog_, SLOT(reject()));
|
||||
connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), editMapArea_, SLOT(resetChanges()));
|
||||
editMapDialog_->setLayout(vLayout);
|
||||
editMapDialog_->setWindowTitle(tr("Edit Optimized Map"));
|
||||
|
||||
QString title("RTAB-Map Database Viewer[*]");
|
||||
this->setWindowTitle(title);
|
||||
|
||||
@@ -251,8 +267,10 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->actionPoses_KML, SIGNAL(triggered()), this , SLOT(exportPosesKML()));
|
||||
connect(ui_->actionGPS_TXT, SIGNAL(triggered()), this , SLOT(exportGPS_TXT()));
|
||||
connect(ui_->actionGPS_KML, SIGNAL(triggered()), this , SLOT(exportGPS_KML()));
|
||||
connect(ui_->actionEdit_optimized_2D_map, SIGNAL(triggered()), this , SLOT(editSaved2DMap()));
|
||||
connect(ui_->actionExport_saved_2D_map, SIGNAL(triggered()), this , SLOT(exportSaved2DMap()));
|
||||
connect(ui_->actionImport_2D_map, SIGNAL(triggered()), this , SLOT(import2DMap()));
|
||||
connect(ui_->actionRegenerate_optimized_2D_map, SIGNAL(triggered()), this , SLOT(regenerateSavedMap()));
|
||||
connect(ui_->actionView_optimized_mesh, SIGNAL(triggered()), this , SLOT(viewOptimizedMesh()));
|
||||
connect(ui_->actionExport_optimized_mesh, SIGNAL(triggered()), this , SLOT(exportOptimizedMesh()));
|
||||
connect(ui_->actionUpdate_optimized_mesh, SIGNAL(triggered()), this , SLOT(updateOptimizedMesh()));
|
||||
@@ -285,7 +303,10 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
ui_->menuExport_poses->setEnabled(false);
|
||||
ui_->menuExport_GPS->setEnabled(false);
|
||||
ui_->actionPoses_KML->setEnabled(false);
|
||||
ui_->actionEdit_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionExport_saved_2D_map->setEnabled(false);
|
||||
ui_->actionImport_2D_map->setEnabled(false);
|
||||
ui_->actionRegenerate_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionView_optimized_mesh->setEnabled(false);
|
||||
ui_->actionExport_optimized_mesh->setEnabled(false);
|
||||
ui_->actionUpdate_optimized_mesh->setEnabled(false);
|
||||
@@ -968,8 +989,10 @@ bool DatabaseViewer::closeDatabase()
|
||||
ui_->menuExport_poses->setEnabled(false);
|
||||
ui_->menuExport_GPS->setEnabled(false);
|
||||
ui_->actionPoses_KML->setEnabled(false);
|
||||
ui_->actionEdit_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionExport_saved_2D_map->setEnabled(false);
|
||||
ui_->actionImport_2D_map->setEnabled(false);
|
||||
ui_->actionRegenerate_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionView_optimized_mesh->setEnabled(false);
|
||||
ui_->actionExport_optimized_mesh->setEnabled(false);
|
||||
ui_->actionUpdate_optimized_mesh->setEnabled(false);
|
||||
@@ -1526,8 +1549,10 @@ void DatabaseViewer::updateIds()
|
||||
ui_->menuExport_poses->setEnabled(false);
|
||||
ui_->menuExport_GPS->setEnabled(false);
|
||||
ui_->actionPoses_KML->setEnabled(false);
|
||||
ui_->actionEdit_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionExport_saved_2D_map->setEnabled(false);
|
||||
ui_->actionImport_2D_map->setEnabled(false);
|
||||
ui_->actionRegenerate_optimized_2D_map->setEnabled(false);
|
||||
ui_->actionView_optimized_mesh->setEnabled(false);
|
||||
ui_->actionExport_optimized_mesh->setEnabled(false);
|
||||
ui_->actionUpdate_optimized_mesh->setEnabled(uStrNumCmp(dbDriver_->getDatabaseVersion(), "0.13.0") >= 0);
|
||||
@@ -1705,8 +1730,10 @@ void DatabaseViewer::updateIds()
|
||||
|
||||
float xMin, yMin, cellSize;
|
||||
bool hasMap = !dbDriver_->load2DMap(xMin, yMin, cellSize).empty();
|
||||
ui_->actionEdit_optimized_2D_map->setEnabled(hasMap);
|
||||
ui_->actionExport_saved_2D_map->setEnabled(hasMap);
|
||||
ui_->actionImport_2D_map->setEnabled(hasMap);
|
||||
ui_->actionRegenerate_optimized_2D_map->setEnabled(uStrNumCmp(dbDriver_->getDatabaseVersion(), "0.17.0") >= 0);
|
||||
|
||||
if(!dbDriver_->loadOptimizedMesh().empty())
|
||||
{
|
||||
@@ -2425,6 +2452,74 @@ void DatabaseViewer::exportGPS(int format)
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::editSaved2DMap()
|
||||
{
|
||||
if(!dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot edit 2D map"), tr("A database must must loaded first...\nUse File->Open database."));
|
||||
return;
|
||||
}
|
||||
|
||||
if(uStrNumCmp(dbDriver_->getDatabaseVersion(), "0.17.0") < 0)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot edit 2D map"),
|
||||
tr("The database has too old version (%1) to saved "
|
||||
"optimized map. Version 0.17.0 minimum required.").arg(dbDriver_->getDatabaseVersion().c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
if(linksAdded_.size() || linksRefined_.size() || linksRemoved_.size() || generatedLocalMaps_.size())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot edit 2D map"),
|
||||
tr("The database has modified links and/or modified local "
|
||||
"occupancy grids, the 2D optimized map cannot be modified."));
|
||||
return;
|
||||
}
|
||||
|
||||
float xMin, yMin, cellSize;
|
||||
cv::Mat map = dbDriver_->load2DMap(xMin, yMin, cellSize);
|
||||
if(map.empty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot export 2D map"), tr("The database doesn't contain a saved 2D map."));
|
||||
return;
|
||||
}
|
||||
|
||||
cv::Mat map8U = rtabmap::util3d::convertMap2Image8U(map, false);
|
||||
cv::Mat map8UFlip, map8URotated;
|
||||
cv::flip(map8U, map8UFlip, 0);
|
||||
if(!ui_->graphViewer->isOrientationENU())
|
||||
{
|
||||
cv::rotate(map8UFlip, map8URotated, cv::ROTATE_90_COUNTERCLOCKWISE);
|
||||
}
|
||||
else
|
||||
{
|
||||
map8URotated = map8UFlip;
|
||||
}
|
||||
|
||||
editMapArea_->setMap(map8URotated);
|
||||
if(editMapDialog_->exec() == QDialog::Accepted && editMapArea_->isModified())
|
||||
{
|
||||
cv::Mat map = editMapArea_->getModifiedMap();
|
||||
|
||||
if(!ui_->graphViewer->isOrientationENU())
|
||||
{
|
||||
cv::rotate(map, map8URotated, cv::ROTATE_90_CLOCKWISE);
|
||||
}
|
||||
else
|
||||
{
|
||||
map8URotated = map;
|
||||
}
|
||||
cv::flip(map8URotated, map8UFlip, 0);
|
||||
|
||||
UASSERT(map8UFlip.type() == map8U.type());
|
||||
UASSERT(map8UFlip.cols == map8U.cols);
|
||||
UASSERT(map8UFlip.rows == map8U.rows);
|
||||
|
||||
dbDriver_->save2DMap(rtabmap::util3d::convertImage8U2Map(map8UFlip, false), xMin, yMin, cellSize);
|
||||
QMessageBox::information(this, tr("Edit 2D map"), tr("Map updated!"));
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::exportSaved2DMap()
|
||||
{
|
||||
if(!dbDriver_)
|
||||
@@ -2469,6 +2564,22 @@ void DatabaseViewer::import2DMap()
|
||||
return;
|
||||
}
|
||||
|
||||
if(uStrNumCmp(dbDriver_->getDatabaseVersion(), "0.17.0") < 0)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot edit 2D map"),
|
||||
tr("The database has too old version (%1) to saved "
|
||||
"optimized map. Version 0.17.0 minimum required.").arg(dbDriver_->getDatabaseVersion().c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
if(linksAdded_.size() || linksRefined_.size() || linksRemoved_.size() || generatedLocalMaps_.size())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot import 2D map"),
|
||||
tr("The database has modified links and/or modified local "
|
||||
"occupancy grids, the 2D optimized map cannot be modified."));
|
||||
return;
|
||||
}
|
||||
|
||||
float xMin, yMin, cellSize;
|
||||
cv::Mat mapOrg = dbDriver_->load2DMap(xMin, yMin, cellSize);
|
||||
if(mapOrg.empty())
|
||||
@@ -2500,6 +2611,64 @@ void DatabaseViewer::import2DMap()
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::regenerateSavedMap()
|
||||
{
|
||||
if(!dbDriver_)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot import 2D map"), tr("A database must must loaded first...\nUse File->Open database."));
|
||||
return;
|
||||
}
|
||||
|
||||
if(uStrNumCmp(dbDriver_->getDatabaseVersion(), "0.17.0") < 0)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot edit 2D map"),
|
||||
tr("The database has too old version (%1) to saved "
|
||||
"optimized map. Version 0.17.0 minimum required.").arg(dbDriver_->getDatabaseVersion().c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
if(linksAdded_.size() || linksRefined_.size() || linksRemoved_.size() || generatedLocalMaps_.size())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot import 2D map"),
|
||||
tr("The database has modified links and/or modified local "
|
||||
"occupancy grids, the 2D optimized map cannot be modified."));
|
||||
return;
|
||||
}
|
||||
|
||||
if((int)graphes_.empty() || localMaps_.empty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot regenerate 2D map"),
|
||||
tr("Graph is empty, make sure you opened the "
|
||||
"Graph View and there is a map shown."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//update scans
|
||||
UINFO("Update local maps list...");
|
||||
OccupancyGrid grid(ui_->parameters_toolbox->getParameters());
|
||||
for(std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=localMaps_.begin(); iter!=localMaps_.end(); ++iter)
|
||||
{
|
||||
grid.addToCache(iter->first, iter->second.first.first, iter->second.first.second, iter->second.second);
|
||||
}
|
||||
grid.update(graphes_.back());
|
||||
float xMin, yMin;
|
||||
cv::Mat map = grid.getMap(xMin, yMin);
|
||||
|
||||
if(map.empty())
|
||||
{
|
||||
QMessageBox::information(this, tr("Regenerate 2D map"), tr("Failed to renegerate the map, resulting map is empty!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbDriver_->save2DMap(map, xMin, yMin, grid.getCellSize());
|
||||
QMessageBox::information(this, tr("Regenerate 2D map"), tr("Map regenerated!"));
|
||||
ui_->actionEdit_optimized_2D_map->setEnabled(true);
|
||||
ui_->actionExport_saved_2D_map->setEnabled(true);
|
||||
ui_->actionImport_2D_map->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::viewOptimizedMesh()
|
||||
{
|
||||
if(!dbDriver_)
|
||||
|
||||
248
guilib/src/EditMapArea.cpp
Normal file
248
guilib/src/EditMapArea.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Copyright (c) 2010-2016, 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.
|
||||
*/
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include "rtabmap/gui/EditMapArea.h"
|
||||
#include <rtabmap/utilite/ULogger.h>
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
EditMapArea::EditMapArea(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setAttribute(Qt::WA_StaticContents);
|
||||
modified_ = false;
|
||||
scribbling_ = false;
|
||||
myPenWidth_ = 3;
|
||||
|
||||
menu_ = new QMenu(tr(""), this);
|
||||
setPenWidth_ = menu_->addAction(tr("Set Pen Width..."));
|
||||
addObstacle_ = menu_->addAction(tr("Add Obstacle"));
|
||||
addObstacle_->setCheckable(true);
|
||||
addObstacle_->setChecked(true);
|
||||
clearObstacle_ = menu_->addAction(tr("Clear Obstacle"));
|
||||
clearObstacle_->setCheckable(true);
|
||||
clearObstacle_->setChecked(false);
|
||||
setUnknown_ = menu_->addAction(tr("Set Unknown"));
|
||||
setUnknown_->setCheckable(true);
|
||||
setUnknown_->setChecked(false);
|
||||
QActionGroup * group = new QActionGroup(this);
|
||||
group->addAction(addObstacle_);
|
||||
group->addAction(clearObstacle_);
|
||||
group->addAction(setUnknown_);
|
||||
resetChanges_ = menu_->addAction(tr("Reset Changes"));
|
||||
}
|
||||
|
||||
void EditMapArea::setMap(const cv::Mat &map)
|
||||
{
|
||||
UASSERT(!map.empty());
|
||||
UASSERT(map.type() == CV_8UC1);
|
||||
originalMap_ = map;
|
||||
|
||||
map_ = uCvMat2QImage(map, true).convertToFormat(QImage::Format_RGB32);
|
||||
|
||||
modified_ = false;
|
||||
update();
|
||||
}
|
||||
|
||||
cv::Mat EditMapArea::getModifiedMap() const
|
||||
{
|
||||
cv::Mat modifiedMap = originalMap_.clone();
|
||||
if(modified_)
|
||||
{
|
||||
UASSERT(map_.width() == modifiedMap.cols &&
|
||||
map_.height() == modifiedMap.rows);
|
||||
UASSERT(modifiedMap.type() == CV_8UC1);
|
||||
for(int j=0; j<map_.height(); ++j)
|
||||
{
|
||||
for(int i=0; i<map_.width(); ++i)
|
||||
{
|
||||
modifiedMap.at<unsigned char>(j,i) = qRed(map_.pixel(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
return modifiedMap;
|
||||
}
|
||||
|
||||
void EditMapArea::setPenWidth(int newWidth)
|
||||
{
|
||||
myPenWidth_ = newWidth;
|
||||
}
|
||||
|
||||
void EditMapArea::resetChanges()
|
||||
{
|
||||
map_ = uCvMat2QImage(originalMap_).convertToFormat(QImage::Format_RGB32);
|
||||
modified_ = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void EditMapArea::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
float scale, offsetX, offsetY;
|
||||
computeScaleOffsets(rect(), scale, offsetX, offsetY);
|
||||
lastPoint_.setX((event->pos().x()-offsetX)/scale);
|
||||
lastPoint_.setY((event->pos().y()-offsetY)/scale);
|
||||
|
||||
scribbling_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EditMapArea::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if ((event->buttons() & Qt::LeftButton) && scribbling_)
|
||||
{
|
||||
float scale, offsetX, offsetY;
|
||||
computeScaleOffsets(rect(), scale, offsetX, offsetY);
|
||||
QPoint to;
|
||||
to.setX((event->pos().x()-offsetX)/scale);
|
||||
to.setY((event->pos().y()-offsetY)/scale);
|
||||
drawLineTo(to);
|
||||
}
|
||||
}
|
||||
|
||||
void EditMapArea::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && scribbling_) {
|
||||
float scale, offsetX, offsetY;
|
||||
computeScaleOffsets(rect(), scale, offsetX, offsetY);
|
||||
QPoint to;
|
||||
to.setX((event->pos().x()-offsetX)/scale);
|
||||
to.setY((event->pos().y()-offsetY)/scale);
|
||||
drawLineTo(to);
|
||||
scribbling_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EditMapArea::computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const
|
||||
{
|
||||
scale = 1.0f;
|
||||
offsetX = 0.0f;
|
||||
offsetY = 0.0f;
|
||||
|
||||
if(!map_.isNull())
|
||||
{
|
||||
float w = map_.width();
|
||||
float h = map_.height();
|
||||
float widthRatio = float(targetRect.width()) / w;
|
||||
float heightRatio = float(targetRect.height()) / h;
|
||||
|
||||
//printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().height());
|
||||
if(widthRatio < heightRatio)
|
||||
{
|
||||
scale = widthRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = heightRatio;
|
||||
}
|
||||
|
||||
//printf("ratio=%f\n",ratio);
|
||||
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
if(w < targetRect.width())
|
||||
{
|
||||
offsetX = (targetRect.width() - w)/2.0f;
|
||||
}
|
||||
if(h < targetRect.height())
|
||||
{
|
||||
offsetY = (targetRect.height() - h)/2.0f;
|
||||
}
|
||||
//printf("offsetX=%f, offsetY=%f\n",offsetX, offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
void EditMapArea::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
//Scale
|
||||
float ratio, offsetX, offsetY;
|
||||
this->computeScaleOffsets(event->rect(), ratio, offsetX, offsetY);
|
||||
QPainter painter(this);
|
||||
|
||||
painter.translate(offsetX, offsetY);
|
||||
painter.scale(ratio, ratio);
|
||||
painter.drawImage(QPoint(0,0), map_);
|
||||
}
|
||||
|
||||
void EditMapArea::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
void EditMapArea::contextMenuEvent(QContextMenuEvent * e)
|
||||
{
|
||||
QAction * action = menu_->exec(e->globalPos());
|
||||
if(action == setPenWidth_)
|
||||
{
|
||||
bool ok;
|
||||
int width = QInputDialog::getInt(this, tr("Set Pen Width"), tr("Width:"), penWidth(), 1, 99, 1, &ok);
|
||||
if(ok)
|
||||
{
|
||||
myPenWidth_ = width;
|
||||
}
|
||||
}
|
||||
else if(action == resetChanges_)
|
||||
{
|
||||
this->resetChanges();
|
||||
}
|
||||
}
|
||||
|
||||
void EditMapArea::drawLineTo(const QPoint &endPoint)
|
||||
{
|
||||
QPainter painter(&map_);
|
||||
QColor color;
|
||||
|
||||
//base on util3d::convertMap2Image8U();
|
||||
if(addObstacle_->isChecked())
|
||||
{
|
||||
color.setRgb(0,0,0);
|
||||
}
|
||||
else if(clearObstacle_->isChecked())
|
||||
{
|
||||
color.setRgb(178,178,178);
|
||||
}
|
||||
else //unknown
|
||||
{
|
||||
color.setRgb(89,89,89);
|
||||
}
|
||||
painter.setPen(QPen(color, myPenWidth_, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
painter.drawLine(lastPoint_, endPoint);
|
||||
modified_ = true;
|
||||
|
||||
update();
|
||||
lastPoint_ = endPoint;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -61,7 +61,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>398</width>
|
||||
<width>413</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -287,7 +287,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>397</width>
|
||||
<width>412</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -647,7 +647,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1547</width>
|
||||
<height>25</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -687,8 +687,10 @@
|
||||
<addaction name="menuExport_poses"/>
|
||||
<addaction name="menuExport_GPS"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionEdit_optimized_2D_map"/>
|
||||
<addaction name="actionExport_saved_2D_map"/>
|
||||
<addaction name="actionImport_2D_map"/>
|
||||
<addaction name="actionRegenerate_optimized_2D_map"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionView_optimized_mesh"/>
|
||||
<addaction name="actionUpdate_optimized_mesh"/>
|
||||
@@ -1300,7 +1302,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>318</width>
|
||||
<height>219</height>
|
||||
<height>197</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1461,8 +1463,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>282</width>
|
||||
<height>885</height>
|
||||
<width>280</width>
|
||||
<height>875</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1995,8 +1997,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>307</width>
|
||||
<height>171</height>
|
||||
<width>296</width>
|
||||
<height>160</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -2124,7 +2126,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>185</width>
|
||||
<height>487</height>
|
||||
<height>485</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -2781,12 +2783,12 @@
|
||||
</action>
|
||||
<action name="actionExport_saved_2D_map">
|
||||
<property name="text">
|
||||
<string>Export saved 2D map...</string>
|
||||
<string>Export optimized 2D map...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_2D_map">
|
||||
<property name="text">
|
||||
<string>Import 2D map...</string>
|
||||
<string>Import optimized 2D map...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_optimized_mesh">
|
||||
@@ -2822,6 +2824,16 @@
|
||||
<string>RGBD-SLAM (stamp tx ty tz qx qy qz qw)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_optimized_2D_map">
|
||||
<property name="text">
|
||||
<string>Edit optimized 2D map...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRegenerate_optimized_2D_map">
|
||||
<property name="text">
|
||||
<string>Regenerate optimized 2D map...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
Reference in New Issue
Block a user