Files
gcs-nf/opmap/mapwidget/opmapwidget.cpp
T
2020-12-12 20:33:45 +08:00

1921 lines
52 KiB
C++

/**
******************************************************************************
*
* @file opmapwidget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The Map Widget, this is the part exposed to the user
* @see The GNU Public License (GPL) Version 3
* @defgroup OPMapWidget
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "opmapwidget.h"
#include <QtGui>
#include <QMetaObject>
#include "waypointitem.h"
#include "QDir"
#include <QGraphicsSceneMouseEvent>
#include "QTextCodec"
namespace mapcontrol {
OPMapWidget::OPMapWidget(QWidget *parent, Configuration *config) : QGraphicsView(parent), configuration(config), UAV(0), GPS(0), Home(0)
, followmouse(true), compass(0), showuav(false), showhome(false), diagTimer(0), diagGraphItem(0), showDiag(false), overlayOpacity(1),isWPCreate(false)
{
//QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf8"));
/*
QTranslator * translator = NULL;
translator->load(QCoreApplication::applicationDirPath() + "\\MAP_zh_CN.qm");
QCoreApplication::installTranslator(translator);
*/
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
core = new internals::Core;
QDir *MapDir = new QDir;
if(!MapDir->exists("./maps"))
MapDir->mkdir("./maps");//如果文件夹不存在就新建
config->SetCacheLocation(QDir::currentPath() + QDir::separator() + "maps" + QDir::separator());
map = new MapGraphicItem(core, config);
mscene.addItem(map);//添加图层
this->setScene(&mscene);
Home = new HomeItem(map, this);
Home->setParentItem(map);
Home->setZValue(-1);
this->adjustSize();
connect(map, SIGNAL(zoomChanged(double, double, double)), this, SIGNAL(zoomChanged(double, double, double)));
connect(map->core, SIGNAL(OnCurrentPositionChanged(internals::PointLatLng)), this, SIGNAL(OnCurrentPositionChanged(internals::PointLatLng)));
connect(map->core, SIGNAL(OnEmptyTileError(int, core::Point)), this, SIGNAL(OnEmptyTileError(int, core::Point)));
connect(map->core, SIGNAL(OnMapDrag()), this, SIGNAL(OnMapDrag()));
connect(map->core, SIGNAL(OnMapTypeChanged(MapType::Types)), this, SIGNAL(OnMapTypeChanged(MapType::Types)));
connect(map->core, SIGNAL(OnMapZoomChanged()), this, SIGNAL(OnMapZoomChanged()));
connect(map->core, SIGNAL(OnTileLoadComplete()), this, SIGNAL(OnTileLoadComplete()));
connect(map->core, SIGNAL(OnTileLoadStart()), this, SIGNAL(OnTileLoadStart()));
connect(map->core, SIGNAL(OnTilesStillToLoad(int)), this, SIGNAL(OnTilesStillToLoad(int)));
connect(map, SIGNAL(wpdoubleclicked(WayPointItem *)), this, SIGNAL(OnWayPointDoubleClicked(WayPointItem *)));
connect(&mscene, SIGNAL(selectionChanged()), this, SLOT(OnSelectionChanged()));
SetShowDiagnostics(showDiag);
this->setMouseTracking(followmouse);
SetShowCompass(false);
QPixmapCache::setCacheLimit(1024 * 1024);//set 1M byte
setOverlayOpacity(overlayOpacity);
altitudeitem = new AltitudeItem(map,Qt::red);
altitudeitem->setParentItem(map);
altitudeitem->setPos(0,(this->height() - altitudeitem->boundingRect().height())/2);
altitudeitem->hide();
NoOperationTimer = new QTimer(this);
connect(NoOperationTimer,SIGNAL(timeout()),
this,SLOT(NOPTimeout()));
NoOperationTimer->start(20000);//20s不操作
}
void OPMapWidget::SetShowDiagnostics(bool const & value)
{
showDiag = value;
}
void OPMapWidget::SetUavPic(QString UAVPic)
{
if (UAV != 0) {
UAV->SetUavPic(UAVPic);
}
if (GPS != 0) {
GPS->SetUavPic(UAVPic);
}
}
void OPMapWidget::SetShowUAV(const bool &value)
{
if (value && UAV == 0) {
UAV = new UAVItem(map, this);
UAV->setParentItem(map);
connect(this, SIGNAL(UAVLeftSafetyBouble(internals::PointLatLng)), UAV, SIGNAL(UAVLeftSafetyBouble(internals::PointLatLng)));
connect(this, SIGNAL(UAVReachedWayPoint(int, WayPointItem *)), UAV, SIGNAL(UAVReachedWayPoint(int, WayPointItem *)));
connect(UAV,SIGNAL(selected(int,int)),
this,SIGNAL(uav_selected(int,int)));
UAV->setOpacity(overlayOpacity);
} else if (!value) {
if (UAV != 0) {
delete UAV;
UAV = NULL;
}
}
}
void OPMapWidget::addUAV(int sysid,int compid)
{
UAVItem *uavItem = new UAVItem(map, this);
uavItem->setParentItem(map);
uavItem->SetUavPic("Fixwing.png");
uavItem->setID(sysid,compid);
connect(this, SIGNAL(UAVLeftSafetyBouble(internals::PointLatLng)),
uavItem, SIGNAL(UAVLeftSafetyBouble(internals::PointLatLng)));
connect(this, SIGNAL(UAVReachedWayPoint(int, WayPointItem *)),
uavItem, SIGNAL(UAVReachedWayPoint(int, WayPointItem *)));
connect(uavItem,SIGNAL(selected(int,int)),
this,SIGNAL(uav_selected(int,int)));
uavItem->setOpacity(overlayOpacity);
//检测,如果只有一个飞机,那么就选中
uint32_t uavCount = 0;
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
uavCount ++;
}
}
if(uavCount <= 1)
{
uavItem->setSelect(true);
}
else
{
uavItem->setSelect(false);
}
this->SetCurrentPosition();
}
void OPMapWidget::NOPTimeout()
{
//qDebug() << "NOPTimeout";
//这个超限
if(isWPCreate == false)
{
isLNOP = true;
}
}
void OPMapWidget::SetCurrentPosition()
{
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->Select())//当前选中,那么检查如果超出了屏幕范围,就将位置拉回中点
{
map->core->SetCurrentPosition(u->UAVPos());//缓慢拉回来
}
}
}
}
void OPMapWidget::SetCurrentPosition(internals::PointLatLng const & value)
{
map->core->SetCurrentPosition(value);
}
void OPMapWidget::setUAVPos(int sysid,int compid,double x,double y,double z)
{
//qDebug() << sysid << compid;
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->SysID() == sysid)
{
internals::PointLatLng LatLng;
LatLng.SetLat(x);
LatLng.SetLng(y);
u->SetUAVPos(LatLng,z);
/*
//==========================
编辑界面不拉回
飞行界面 20s不操作才会拉回一次
//===========================*/
if(isWPCreate == false)
{
if(u->Select())//当前选中,那么检查如果超出了屏幕范围,就将位置拉回中点
{
if(((u->pos().x() <= 0)||
(u->pos().x() >= this->size().width())||
(u->pos().y() < 0)||
(u->pos().y() >= this->size().height()))&&(isLNOP == true))
{
this->SetCurrentPosition(LatLng);//缓慢拉回来
}
}
}
}
}
}
}
void OPMapWidget::setUAVHeading(int sysid,int compid,float Heading)
{
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->SysID() == sysid)
{
u->SetUAVHeading(Heading);
//qDebug() << Heading;
}
}
}
}
int OPMapWidget::getUAVCurrent(void)
{
int num = -1;
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->Select())
{
num = u->SysID();
}
}
}
return num;
}
void OPMapWidget::DeleteTrail(void)
{
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->Select())
{
u->DeleteTrail();
}
}
}
}
WayPointLine *OPMapWidget::WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color, bool dashed, int width)
{
if (!from | !to) {
return NULL;
}
WayPointLine *ret = new WayPointLine(from, to, map, color, dashed, width);
ret->setOpacity(overlayOpacity);
return ret;
}
WayPointLine *OPMapWidget::WPLineCreate(HomeItem *from, WayPointItem *to, QColor color, bool dashed, int width)
{
if (!from | !to) {
return NULL;
}
WayPointLine *ret = new WayPointLine(from, to, map, color, dashed, width);
ret->setOpacity(overlayOpacity);
return ret;
}
void OPMapWidget::WPLineDelete(WayPointItem *from, WayPointItem *to)
{
do
{
WayPointLine *line = WPLineFind(from,to);
if(line)
{
delete line;
}
else
{
break;
}
}while(0);
}
WayPointLine *OPMapWidget::WPLineFind(WayPointItem *from, WayPointItem *to)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *w = qgraphicsitem_cast<WayPointLine *>(i);
if (w) {
if (w->WPLineFrom() == from) {
return w;
}
}
}
return NULL;
}
WayPointCircle *OPMapWidget::WPCircleCreate(WayPointItem *center, double radius, bool clockwise, QColor color, bool dashed, int width)
{
if (!center | !radius) {
return NULL;
}
WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color, dashed, width);
ret->setOpacity(overlayOpacity);
return ret;
}
WayPointCircle *OPMapWidget::WPCircleCreate(HomeItem *center, double radius, bool clockwise, QColor color, bool dashed, int width)
{
if (!center | !radius) {
return NULL;
}
WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color, dashed, width);
ret->setOpacity(overlayOpacity);
return ret;
}
void OPMapWidget::SetShowHome(const bool &value)
{
Home->setVisible(value);
}
void OPMapWidget::resizeEvent(QResizeEvent *event)
{
if (scene()) {
scene()->setSceneRect(
QRect(QPoint(0,0), event->size()));
}
QGraphicsView::resizeEvent(event);
if (compass) {
compass->setScale(0.1 + 0.05 * (qreal)(event->size().width()) / 1000 * (qreal)(event->size().height()) / 600);
}
}
QSize OPMapWidget::sizeHint() const
{
return map->sizeHint();
}
void OPMapWidget::showEvent(QShowEvent *event)
{
connect(&mscene, SIGNAL(sceneRectChanged(QRectF)), map, SLOT(resize(QRectF)));
map->start();
QGraphicsView::showEvent(event);
}
OPMapWidget::~OPMapWidget()
{
if (UAV) {
delete UAV;
}
if (Home) {
delete Home;
}
if (map) {
delete map;
}
if (core) {
delete core;
}
if (configuration) {
delete configuration;
}
foreach(QGraphicsItem * i, this->items()) {
if (i) {
delete i;
}
}
}
void OPMapWidget::closeEvent(QCloseEvent *event)
{
core->OnMapClose();
event->accept();
}
void OPMapWidget::SetUseOpenGL(const bool &value)
{
useOpenGL = value;
if (useOpenGL) {
setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
} else {
setupViewport(new QWidget());
}
update();
}
internals::PointLatLng OPMapWidget::currentMousePosition()
{
return currentmouseposition;
}
void OPMapWidget::mouseMoveEvent(QMouseEvent *event)
{
QGraphicsView::mouseMoveEvent(event);
QPointF p = event->pos();
//qDebug() << "mouseMoveEvent";
p = map->mapFromParent(p);
currentmouseposition = map->FromLocalToLatLng(p.x(), p.y());
isLNOP = false;
emit EmitCurrentMousePosition(currentmouseposition);
}
void OPMapWidget::mousePressEvent(QMouseEvent *event)
{
QGraphicsView::mousePressEvent(event);
//qDebug() << "mousePressEvent";
isLNOP = false;
emit MousePressEvent(event);
}
void OPMapWidget::mouseReleaseEvent(QMouseEvent *event)
{
isLNOP = false;
QGraphicsView::mouseReleaseEvent(event);
emit MouseReleaseEvent(event);
}
void OPMapWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QGraphicsView::mouseDoubleClickEvent(event);
isLNOP = false;
//生成一个列表
if(isWPCreate == true)
{
if(event->button() == Qt::LeftButton)
{
QPointF p = event->pos();
p = map->mapFromParent(p);
internals::PointLatLng LatLng;
LatLng = map->FromLocalToLatLng(p.x(), p.y());
WayPointItem *Item = WPCreate(LatLng,50);
WPLineCreate(WPFind(Item->Number() - 1),Item,Qt::green,false,2);
qDebug() << "WPCreate Point"
<< QThread::currentThreadId();
}
}
emit MouseDoubleClickEvent(event);
}
////////////////WAYPOINT////////////////////////
WayPointItem *OPMapWidget::WPCreate()
{
WayPointItem *item = new WayPointItem(this->CurrentPosition(), 0, map);
ConnectWP(item);
item->setParentItem(map);
int position = item->Number();
emit WPCreated(position, item);
return item;
}
WayPointItem *OPMapWidget::magicWPCreate()
{
WayPointItem *item = new WayPointItem(map, true);
item->SetShowNumber(false);
item->setParentItem(map);
return item;
}
void OPMapWidget::WPCreate(WayPointItem *item)
{
ConnectWP(item);
item->setParentItem(map);
int position = item->Number();
emit WPCreated(position, item);
setOverlayOpacity(overlayOpacity);
}
WayPointItem *OPMapWidget::WPCreate(internals::PointLatLng const & coord, int const & altitude)
{
WayPointItem *item = new WayPointItem(coord, altitude, map);
ConnectWP(item);
item->setParentItem(map);
int position = item->Number();
emit WPCreated(position, item);
setOverlayOpacity(overlayOpacity);
return item;
}
WayPointItem *OPMapWidget::WPCreate(internals::PointLatLng const & coord, int const & altitude, QString const & description)
{
WayPointItem *item = new WayPointItem(coord, altitude, description, map);
ConnectWP(item);
item->setParentItem(map);
int position = item->Number();
emit WPCreated(position, item);
setOverlayOpacity(overlayOpacity);
return item;
}
WayPointItem *OPMapWidget::WPCreate(const distBearingAltitude &relativeCoord, const QString &description)
{
WayPointItem *item = new WayPointItem(relativeCoord, description, map);
ConnectWP(item);
item->setParentItem(map);
int position = item->Number();
emit WPCreated(position, item);
setOverlayOpacity(overlayOpacity);
return item;
}
void OPMapWidget::WPInsert(const int &position)
{
internals::PointLatLng latlng;
WayPointItem *item_old0 = WPFind(position-1);
WayPointItem *item_old1 = WPFind(position);
WayPointItem *item_old2 = WPFind(position+1);
//删除连线
if((item_old1)&&(item_old2))
{
WPLineDelete(item_old1,item_old2);
//WPLineDelete(item_old1,item_old2);
//WPLineDelete(item_old1,item_old2);
}
//删除连线
if((item_old1)&&(item_old0))
{
WPLineDelete(item_old0,item_old1);
//WPLineDelete(item_old0,item_old1);
//WPLineDelete(item_old0,item_old1);
internals::PointLatLng latlng1 = item_old0->Coord();
internals::PointLatLng latlng2 = item_old1->Coord();
latlng.SetLat((latlng1.Lat() + latlng2.Lat())/2);
latlng.SetLng((latlng1.Lng() + latlng2.Lng())/2);
}
else
{
if(item_old1)
{
latlng = item_old1->Coord();
}
}
if(item_old1)//如果指定的点存在,那么就可以在这之前插入一个点
{
WayPointItem *item = new WayPointItem(latlng, item_old1->Altitude(), map);
ConnectWP(item);
item->SetNumber(position);
item->setParentItem(map);
setOverlayOpacity(overlayOpacity);
setSelectedWP(item);
item->emitWPProperty();//这个没有执行
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if(w != item)
{
if(w->Number() >= item->Number())
{
w->SetNumber(w->Number()+1);
}
}
}
}
WayPointItem *w_next = WPFind(item->Number() + 1);
if(w_next)
{
WPLineCreate(item,w_next,Qt::green,false,2);
WayPointItem *w_next_1 = WPFind(w_next->Number() + 1);
if(w_next_1)
{
WPLineCreate(w_next,w_next_1,Qt::green,false,2);
}
}
/*
WayPointItem *w_last = WPFind(item->Number() - 1);
if(w_last)
{
WPLineCreate(w_last,item,Qt::green,false,2);
WayPointItem *w_last2 = WPFind(item->Number() - 2);
if(w_last2)
{
WPLineCreate(w_last2,w_last,Qt::green,false,2);
}
}
*/
}
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
//qDebug() << "all number" << w->Number() << w->snumber;
WPFollowPrevious(w->FollowPrevious(),w);
}
}
}
void OPMapWidget::WPInsert(WayPointItem *item, const int &position)
{
item->SetNumber(position);
ConnectWP(item);
item->setParentItem(map);
emit WPInserted(position, item);
setOverlayOpacity(overlayOpacity);
}
WayPointItem *OPMapWidget::WPInsert(internals::PointLatLng const & coord, int const & altitude, const int &position)
{
WayPointItem *item = new WayPointItem(coord, altitude, map);
item->SetNumber(position);
ConnectWP(item);
item->setParentItem(map);
emit WPInserted(position, item);
setOverlayOpacity(overlayOpacity);
return item;
}
WayPointItem *OPMapWidget::WPInsert(internals::PointLatLng const & coord, int const & altitude, QString const & description, const int &position)
{
internals::PointLatLng mcoord;
bool reloc = false;
if (mcoord == internals::PointLatLng(0, 0)) {
mcoord = CurrentPosition();
reloc = true;
} else {
mcoord = coord;
}
WayPointItem *item = new WayPointItem(mcoord, altitude, description, map);
item->SetNumber(position);
ConnectWP(item);
item->setParentItem(map);
emit WPInserted(position, item);
if (reloc) {
emit WPValuesChanged(item);
}
setOverlayOpacity(overlayOpacity);
return item;
}
WayPointItem *OPMapWidget::WPInsert(distBearingAltitude const & relative, QString const & description, const int &position)
{
WayPointItem *item = new WayPointItem(relative, description, map);
item->SetNumber(position);
ConnectWP(item);
item->setParentItem(map);
emit WPInserted(position, item);
setOverlayOpacity(overlayOpacity);
return item;
}
void OPMapWidget::WPDelete(WayPointItem *item)
{
int number = item->Number();
emit WPDeleted(number, item);
delete item;
//当前选中为上一点
WayPointItem *w = WPFind(number -1);
if(w)
{
setSelectedWP(w);
w->emitWPProperty();
WayPointItem *w_next = WPFind(w->Number() + 1);
if(w_next)
{
WPLineCreate(w,w_next,Qt::green,false,2);
}
}
else
{
WayPointItem *ww = WPFind(number);
if(ww)
{
setSelectedWP(ww);
ww->emitWPProperty();
}
}
}
void OPMapWidget::WPDelete(int number)
{
WayPointItem *w = WPFind(number);
if (w) {
qDebug() << "delete" <<w->Number();
emit WPDeleted(w->Number(), w);
delete w;
}
//当前选中为上一点
WayPointItem *item = WPFind(number -1);
if(item)
{
setSelectedWP(item);
item->emitWPProperty();
WayPointItem *item_next = WPFind(item->Number() + 1);
if(item_next)
{
WPLineCreate(item,item_next,Qt::green,false,2);
}
else
{
qDebug() << "can not find next fine";
}
}
else
{
WayPointItem *ww = WPFind(number);
if(ww)
{
setSelectedWP(ww);
ww->emitWPProperty();
}
}
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
WPFollowPrevious(w->FollowPrevious(),w);
}
}
}
WayPointItem *OPMapWidget::WPFind(int number)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if (w->Number() == number) {
return w;
}
}
}
return nullptr;
}
void OPMapWidget::WPSetVisibleAll(bool value)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if (w->Number() != -1) {
w->setVisible(value);
}
}
}
}
void OPMapWidget::WPDeleteAll()
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
emit WPDeleted(w->Number(), w);
delete w;
/*
if (w->Number() != -1) {
emit WPDeleted(w->Number(), w);
delete w;
}
*/
}
}
}
bool OPMapWidget::WPPresent()
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if (w->Number() != -1) {
return true;
}
}
}
return false;
}
void OPMapWidget::deleteAllOverlays()
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *w = qgraphicsitem_cast<WayPointLine *>(i);
if (w) {
w->deleteLater();
} else {
WayPointCircle *ww = qgraphicsitem_cast<WayPointCircle *>(i);
if (ww) {
ww->deleteLater();
}
}
}
}
QList<WayPointItem *> OPMapWidget::WPSelected()
{
QList<WayPointItem *> list;
foreach(QGraphicsItem * i, mscene.selectedItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
list.append(w);
}
}
return list;
}
void OPMapWidget::WPRenumber(WayPointItem *item, const int &newnumber)
{
item->SetNumber(newnumber);
}
void OPMapWidget::ConnectWP(WayPointItem *item)
{
connect(item, SIGNAL(WPNumberChanged(int, int, WayPointItem *)), this, SIGNAL(WPNumberChanged(int, int, WayPointItem *)), Qt::DirectConnection);
connect(item, SIGNAL(WPValuesChanged(WayPointItem *)), this, SIGNAL(WPValuesChanged(WayPointItem *)), Qt::DirectConnection);
connect(item, SIGNAL(localPositionChanged(QPointF, WayPointItem *)), this, SIGNAL(WPLocalPositionChanged(QPointF, WayPointItem *)), Qt::DirectConnection);
connect(item, SIGNAL(manualCoordChange(WayPointItem *)), this, SIGNAL(WPManualCoordChange(WayPointItem *)), Qt::DirectConnection);
connect(this, SIGNAL(WPInserted(int, WayPointItem *)), item, SLOT(WPInserted(int, WayPointItem *)), Qt::DirectConnection);
connect(this, SIGNAL(WPNumberChanged(int, int, WayPointItem *)), item, SLOT(WPRenumbered(int, int, WayPointItem *)), Qt::DirectConnection);
connect(this, SIGNAL(WPDeleted(int, WayPointItem *)), item, SLOT(WPDeleted(int, WayPointItem *)), Qt::DirectConnection);
connect(item,SIGNAL(WPChanged(int,double,double)),this,SIGNAL(WPChanged(int,double,double)));
connect(item, SIGNAL(WPProperty(float,float,float,float,int32_t,int32_t,float,uint16_t,uint16_t,uint16_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t)),
this, SIGNAL(WPProperty(float,float,float,float,int32_t,int32_t,float,uint16_t,uint16_t,uint16_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t)),Qt::DirectConnection);
connect(this, SIGNAL(setWPProperty(float,float,float,float,int32_t,int32_t,float,uint16_t,uint16_t,uint16_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t)),
item, SLOT(setWPProperty(float,float,float,float,int32_t,int32_t,float,uint16_t,uint16_t,uint16_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t)),Qt::DirectConnection);
connect(item, SIGNAL(WPProperty(float,float,float,float,int32_t,int32_t,float,uint16_t,uint16_t,uint16_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t)),
this, SLOT(find_PointNumber()),Qt::DirectConnection);
connect(item, SIGNAL(WPFollowPrevious(bool,WayPointItem*)),
this, SLOT(WPFollowPrevious(bool,WayPointItem*)),Qt::DirectConnection);
connect(item, SIGNAL(localPositionChanged(QPointF, WayPointItem *)),
this, SLOT(WPLocalChanged(QPointF, WayPointItem *)), Qt::DirectConnection);
connect(item,SIGNAL(SetCurrent(int)),
this,SIGNAL(setCurrent(int)), Qt::DirectConnection);
connect(item,SIGNAL(ElevationChanged(int,double)),
this,SLOT(ElevationChanged(int,double)), Qt::DirectConnection);
connect(item,SIGNAL(AltitudeChanged(int,double)),
this,SLOT(AltitudeChanged(int,double)), Qt::DirectConnection);
connect(item,SIGNAL(setCurrentPoint(int)),
this,SLOT(setCurrentPoint(int)), Qt::DirectConnection);
//生成后立即选中,并且把信息发给ui界面
setSelectedWP(item);
item->emitWPProperty();
}
void OPMapWidget::diagRefresh()
{
if (showDiag) {
if (diagGraphItem == 0) {
diagGraphItem = new QGraphicsTextItem();
mscene.addItem(diagGraphItem);
diagGraphItem->setPos(10, 100);
diagGraphItem->setZValue(3);
diagGraphItem->setFlag(QGraphicsItem::ItemIsMovable, true);
diagGraphItem->setDefaultTextColor(Qt::yellow);
}
diagGraphItem->setPlainText(core->GetDiagnostics().toString());
} else if (diagGraphItem != 0) {
delete diagGraphItem;
diagGraphItem = 0;
}
}
//////////////////////////////////////////////
void OPMapWidget::SetShowCompass(const bool &value)
{
if (value && !compass) {
compass = new QGraphicsSvgItem(QString::fromUtf8(":/markers/images/compas.svg"));
compass->setScale(0.1 + 0.05 * (qreal)(this->size().width()) / 1000 * (qreal)(this->size().height()) / 600);
// compass->setTransformOriginPoint(compass->boundingRect().width(),compass->boundingRect().height());
compass->setFlag(QGraphicsItem::ItemIsMovable, true);
compass->setFlag(QGraphicsItem::ItemIsSelectable, true);
mscene.addItem(compass);
compass->setTransformOriginPoint(compass->boundingRect().width() / 2, compass->boundingRect().height() / 2);
compass->setPos(55 - compass->boundingRect().width() / 2, 55 - compass->boundingRect().height() / 2);
compass->setZValue(3);
compass->setOpacity(0.7);
}
if (!value && compass) {
delete compass;
compass = 0;
}
}
void OPMapWidget::setOverlayOpacity(qreal value)
{
map->setOverlayOpacity(value);
overlayOpacity = value;
}
void OPMapWidget::SetRotate(qreal const & value)
{
map->mapRotate(value);
if (compass && (compass->rotation() != value)) {
compass->setRotation(value);
}
}
void OPMapWidget::RipMap()
{
new MapRipper(core, map->SelectedArea());
}
void OPMapWidget::setSelectedWP(QList<WayPointItem * >list)
{
this->scene()->clearSelection();
foreach(WayPointItem * wp, list) {
wp->setSelected(true);
if(altitudeitem)
{
if(!wp->FollowPrevious())
altitudeitem->setCurrentPoint(wp->Number());
}
}
}
void OPMapWidget::setSelectedWP(int number)
{
this->scene()->clearSelection();
WayPointItem *wp = WPFind(number);
wp->setSelected(true);
if(altitudeitem)
{
if(!wp->FollowPrevious())
altitudeitem->setCurrentPoint(wp->Number());
}
}
void OPMapWidget::setSelectedWP(WayPointItem *item)
{
this->scene()->clearSelection();
item->setSelected(true);
if(altitudeitem)
{
if(!item->FollowPrevious())
altitudeitem->setCurrentPoint(item->Number());
}
}
void OPMapWidget::OnSelectionChanged()
{
QList<QGraphicsItem *> list;
QList<WayPointItem *> wplist;
list = this->scene()->selectedItems();
foreach(QGraphicsItem * item, list) {
WayPointItem *wp = qgraphicsitem_cast<WayPointItem *>(item);
qDebug() << "selete item" << wp->Number();
if (wp) {
wplist.append(wp);
}
}
if (wplist.length() > 0) {
emit selectedWPChanged(wplist);
}
}
void OPMapWidget::WPotherPoint(int number)
{
WayPointItem *wp = WPFind(number);
if(wp)
{
setSelectedWP(number);
wp->emitWPProperty();
}
}
void OPMapWidget::setWPLock(bool const & lock)
{
bool isEdit = false;
if(lock == true)
{
isEdit = false;
}
else
{
isEdit = true;
}
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
qDebug() << "set Edit" <<isEdit;
w->WPSetEdit(isEdit);
}
}
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *uav = qgraphicsitem_cast<UAVItem *>(i);
if (uav) {
uav->setEdit(isEdit);
}
}
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *l = qgraphicsitem_cast<WayPointLine *>(i);
if (l) {
l->setEdit(isEdit);
}
}
}
void OPMapWidget::WPSetCurrent(int seq)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if(w->Number() == seq)
{
w->WPSetCurrent(true);
//qDebug() << "map WPSetCurrent" << seq;
}
else
{
w->WPSetCurrent(false);
}
}
}
}
void OPMapWidget::WPsearchall(void)
{
//重新排序一下
//QList<mapcontrol::WayPointItem *> list;
QMap<int,int> list;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
list.insert(w->Number(),w->Command());
}
}
for (QMap<int,int>::iterator i = list.begin();i != list.end(); ++i)
{
qDebug() << i.key() << i.value();
}
if(list.size() != 0)
{
emit allPoint(list);
}
}
void OPMapWidget::setWPCreate(bool const & value)
{
isWPCreate = value;
if(altitudeitem)
{
if(value)
{
altitudeitem->show();
}
else
{
altitudeitem->hide();
}
}
}
void OPMapWidget::WPLocalChanged(QPointF p, WayPointItem *w)
{
WayPointItem *item = WPFind(w->Number() + 1);
if(item)
{
if(item->FollowPrevious() == true)
{
QPointF pos = p;
pos.setX(pos.x() + w->boundingRect().width());
item->setPosition(pos);
}
}
}
void OPMapWidget::WPFollowPrevious(bool flag,WayPointItem *w)
{
int Point_Count = 0;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {//逐渐往下增加
Point_Count++;
}
}
if(flag)
{
WayPointItem *item = WPFind(w->Number() - 1);
if(item)
{
WPLineDelete(item,w);
//跟随上一点的位置
QPointF pos = item->pos();
pos.setX(pos.x() + w->boundingRect().width());
w->setPosition(pos);
//找到前后两个不是跟随的点,将他们连接起来
WayPointItem *front_item;
int front_seq = w->Number();
do{
front_item = WPFind(front_seq--);
if(front_item)
{
if(front_item->FollowPrevious() == false)
{
qDebug() << "front_item" << front_item->Number();
break;
}
else {
continue;
}
}
else
{
break;
}
}while(front_seq > 0);
WayPointItem *next_item;
int next_seq = w->Number();
do{
next_item = WPFind(next_seq++);
if(next_item)
{
WPLineDelete(w,next_item);
if(next_item->FollowPrevious() == false)
{
qDebug() << "next_item" << next_item->Number();
break;
}
else {
continue;
}
}
else
{
break;
}
}while(next_seq <= Point_Count);
if(next_item)
{
WPLineDelete(w,next_item);
}
if((front_item)&&(next_item))
{
WPLineCreate(front_item,next_item,Qt::green,false,2);
}
}
}
else
{
//找到前后两个不是跟随的点,将他们连接起来
WayPointItem *front_item;
int front_seq = w->Number()-1;
do{
front_item = WPFind(front_seq--);
if(front_item)
{
if(front_item->FollowPrevious() == false)
{
qDebug() << "front_item" << front_item->Number();
break;
}
else {
//如果上一点存在,那么就删除掉线
qDebug() << "Delete front" << front_item->Number();
WPLineDelete(front_item,w);
continue;
}
}
else
{
break;
}
}while(front_seq > 0);
WayPointItem *next_item;
int next_seq = w->Number()+1;
do{
next_item = WPFind(next_seq++);
if(next_item)
{
if(next_item->FollowPrevious() == false)
{
qDebug() << "next_item" << next_item->Number();
break;
}
else {
continue;
}
}
else
{
break;
}
}while(next_seq <= Point_Count);
if((front_item)&&(next_item))
{
WPLineDelete(front_item,next_item);
}
if(front_item)
{
WPLineCreate(front_item,w,Qt::green,false,2);
}
if(next_item)
{
WPLineCreate(w,next_item,Qt::green,false,2);
}
}
}
//先清除再读取
void OPMapWidget::WPLoad(QString path)//带文件目录参数
{
//清除所有
WPDeleteAll();
qDebug() << "WPLoad" << path;
//读取
QFile jsonFile(path);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open file" << path << jsonFile.errorString();
return;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << path << "Unable to open json document" << jsonParseError.errorString();
return;
}
QJsonObject json = doc.object();
//解码
QJsonArray itemsArray = json.value("mission").toObject().value("items").toArray();
for(QJsonValue item: itemsArray) {
if (!item.isObject()) {
return;
}
uint8_t AMSLAltAboveTerrain = item.toObject().find("AMSLAltAboveTerrain").value().toInt();
uint8_t Altitude = item.toObject().find("Altitude").value().toDouble();
uint8_t AltitudeMode = item.toObject().find("AltitudeMode").value().toInt();
uint8_t autocontinue = item.toObject().find("autoContinue").value().toBool()?(1):(0);//bool
uint16_t command = item.toObject().find("command").value().toInt();
uint16_t seq = item.toObject().find("doJumpId").value().toInt();
uint8_t frame = item.toObject().find("frame").value().toInt();
QJsonArray params = item.toObject().find("params").value().toArray();//array
uint8_t mission_type = item.toObject().find("type").value().toInt();
float param1 = params.at(0).toDouble();
float param2 = params.at(1).toDouble();
float param3 = params.at(2).toDouble();
float param4 = params.at(3).toDouble();
int32_t x = params.at(4).toDouble() * 10e6;
int32_t y = params.at(5).toDouble() * 10e6;;
float z = params.at(6).toDouble();
internals::PointLatLng LatLng;
LatLng.SetLat(x * 10e-8);
LatLng.SetLng(y * 10e-8);
qDebug() << "LatLng" << LatLng.Lat() << LatLng.Lng();
WayPointItem *Item = WPCreate(LatLng,z);
Item->SetNumber(seq);
if(command > MAV_CMD::MAV_CMD_NAV_LAST)
{
}
else
{
//WPLineCreate(WPFind(Item->Number() - 1),Item,Qt::green,false,2);
}
//Item->setParent(map);
qDebug() << "autocontinue" << autocontinue;
emit setWPProperty(param1,param2,param3,param4,
x,y,z,
seq,
0,
command,
0,
0,
frame,
0,
autocontinue,
mission_type);
Item->emitWPProperty();
}
}
void OPMapWidget::WPSave(QString path)//带文件目录参数
{
qDebug() << "WPSave" << path;
//保存到文件 *.plan,使用qgc的协议 json读写
QJsonDocument *doc = new QJsonDocument();
QJsonObject root= doc->object();
QJsonObject geoFence;
QJsonObject mission;
QJsonObject rallyPoints;
//geoFence节点写入
{
QJsonArray circles;
QJsonArray polygons;
geoFence.insert("circles",circles);
geoFence.insert("polygons",polygons);
geoFence.insert("version",2);
}
//mission节点写入
{
QJsonArray items;
QJsonArray plannedHomePosition;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {//逐渐往下增加
if(w->Number()>0)
{
//存到items
QJsonArray params;
params.append(w->Param1());
params.append(w->Param2());
params.append(w->Param3());
params.append(w->Param4());
params.append(w->Coord().Lat());
params.append(w->Coord().Lng());
params.append(w->Alt());
//可能有点问题
QJsonObject item;
item.insert("AMSLAltAboveTerrain",0);
item.insert("Altitude",w->Alt());
item.insert("AltitudeMode",1);
item.insert("autoContinue",w->AutoContinue()?true:false);
item.insert("command",w->Command());
item.insert("doJumpId",w->Number());
item.insert("frame",w->Frame());
item.insert("params",params);
item.insert("type","SimpleItem");
//这里有问题
items.append(item);
}
if(w->Number() == 1)
{
plannedHomePosition.append(w->Coord().Lat());
plannedHomePosition.append(w->Coord().Lng());
plannedHomePosition.append(w->Alt());
}
}
}
mission.insert("cruiseSpeed",2);
mission.insert("firmwareType",2);
mission.insert("hoverSpeed",2);
mission.insert("items",items);
mission.insert("plannedHomePosition",plannedHomePosition);
mission.insert("vehicleType",20);
mission.insert("version",2);
}
//rallyPoints节点写入
{
QJsonArray points;
rallyPoints.insert("points",points);
rallyPoints.insert("version",2);
}
//根节点写入
root.insert("fileType","Plan");
root.insert("geoFence",geoFence);
root.insert("groundStation","GCS_nf");
root.insert("mission", mission);
root.insert("rallyPoints", rallyPoints);
root.insert("version", 1);
//设置文档
doc->setObject(root);
//如果没有后缀名,那就追加
if(path.right(5) != ".plan")
{
path.append(".plan");
}
QFile file(path);
if(!file.open(QIODevice::ReadWrite|QFile::Truncate)) {
qDebug() << "File open error";
}
file.write(doc->toJson());
file.close();
}
void OPMapWidget::WPDownload(void)
{
//请求读取航点
qDebug() << "WPDownload";
WPDeleteAll();
int sysid = 0;
int compid = 0;
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->Select() == true)
{
sysid = u->SysID();
compid = u->CompID();
emit signal_WPDownload(sysid,compid);
}
}
}
}
void OPMapWidget::WPUpload(void)
{
//发送第一个
QList<mapcontrol::WayPointItem *> list;
//先发送一个清空指令
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
list.append(w);
w->emitWPProperty();
//w->setVisible(false);
}
}
/*
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *l = qgraphicsitem_cast<WayPointLine *>(i);
if (l) {
l->setVisible(false);
}
}
*/
//qDebug() << "WPUpload" << list.size();
if(list.size() <= 0)
{
emit showMessage(tr("please create a plan"));
return;
}
emit showMessage(tr("start to send mossion %1").arg(list.size()));
//选择当前ID号
int sysid = 0;
int compid = 0;
foreach(QGraphicsItem * i, map->childItems()) {
UAVItem *u = qgraphicsitem_cast<UAVItem *>(i);
if (u) {
if(u->Select() == true)
{
sysid = u->SysID();
compid = u->CompID();
//如果有选中,那么就发送,选中几个就发几个
emit signal_WPUpload(sysid,compid,list.size());//直接发送全部航点到
}
}
}
}
void OPMapWidget::WPSendItemOK(uint16_t seq, bool flag)
{
if(flag == true)
{
QString str;
str.append(tr("send way point %1").arg(seq));
emit showMessage(str);
}
else
{
QString str;
str.append(tr("fail to send %1").arg(seq));
emit showMessage(str);
}
/*
if(flag == true)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if(w->Number() == (seq))
{
w->setVisible(true);
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *l = qgraphicsitem_cast<WayPointLine *>(i);
if (l) {
if(l->WPLineTo() == w)
l->setVisible(true);
}
}
}
}
}
}
*/
/*
if(flag == true)
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) {
if(w->Number() == (seq))
{
w->setVisible(true);
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *l = qgraphicsitem_cast<WayPointLine *>(i);
if (l) {
if(l->WPLineTo() == w)
l->setVisible(true);
}
}
}
}
}
}
else
{
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w) w->setVisible(true);
}
foreach(QGraphicsItem * i, map->childItems()) {
WayPointLine *l = qgraphicsitem_cast<WayPointLine *>(i);
if (l) l->setVisible(true);
}
}
*/
}
//这个有可能是其他线程运行,导致生成的航点不对,下载得到
void OPMapWidget::receivedPoint(float param1,float param2,float param3,float param4,
int32_t x,int32_t y,float z,
uint16_t seq,
uint16_t group,
uint16_t command,
uint8_t target_system,
uint8_t target_component,
uint8_t frame,
uint8_t current,
uint8_t autocontinue,
uint8_t mission_type)
{
qDebug() << "receivers Point";
// << QThread::currentThreadId();
emit showMessage(tr("recieve way point %1").arg(seq + 1));
//qDebug() << "receivers Point" << x * 10e-8 << y * 10e-8 << 10e-8;
internals::PointLatLng LatLng;
LatLng.SetLat(x * 10e-8);
LatLng.SetLng(y * 10e-8);
WayPointItem *Item = WPCreate(LatLng,z);
Item->SetNumber(seq+1);
emit setWPProperty(param1,param2,param3,param4,
x,y,z,
seq+1,
group,
command,
target_system,
target_component,
frame,
current,
autocontinue,
mission_type);
Item->emitWPProperty();
}
void OPMapWidget::getMapTypes(void)
{
emit MapTypes(Helper::MapTypes());
}
void OPMapWidget::setMapTypes(QVariant value)
{
this->SetMapType(Helper::MapTypeFromString(value.toString()));
}
void OPMapWidget::ElevationChanged(int seq,double value)
{
QMap<int,float> Info;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w)
{
if(!w->FollowPrevious())
Info.insert(w->Number(),w->getElevation());
}
}
if(altitudeitem)
{
altitudeitem->setElevation(Info);
}
}
void OPMapWidget::AltitudeChanged(int seq,double value)
{
QMap<int,float> Info;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w)
{
if(!w->FollowPrevious())
Info.insert(w->Number(),w->Alt());
}
}
if(altitudeitem)
{
altitudeitem->setAltitude(Info);
}
updateMessage();
}
void OPMapWidget::setCurrentPoint(int value)
{
if(altitudeitem)
{
altitudeitem->setCurrentPoint(value);
}
}
void OPMapWidget::updateMessage(void)
{
totalDistance = 0;
WayPointItem *Last = nullptr;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w)
{
if(Last != nullptr)
{
totalDistance += internals::PureProjection::DistanceBetweenLatLng(Last->Coord(),w->Coord()) * 10e2;
}
Last = w;
}
}
Last = nullptr;
delete Last;
emit TotalDistanceUpdate(totalDistance);
}
void OPMapWidget::find_PointNumber()
{
QList<int> nums;
nums.clear();
int number = 0;
foreach(QGraphicsItem * i, map->childItems()) {
WayPointItem *w = qgraphicsitem_cast<WayPointItem *>(i);
if (w)
{
number = w->Number();
if(w->Command() < MAV_CMD::MAV_CMD_NAV_LAST)
{
nums.append(number);
}
}
}
qDebug() << "nums" << nums;
emit PointNumber(nums);
}
}