/** ****************************************************************************** * * @file waypointitem.cpp * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. * @brief A graphicsItem representing a WayPoint * @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 "waypointitem.h" #include "homeitem.h" #include #include "QJsonArray" #include "QJsonDocument" #include "QJsonObject" #include "QJsonParseError" namespace mapcontrol { WayPointItem::WayPointItem(const internals::PointLatLng &coord, int const & altitude, MapGraphicItem *map, wptype type) : coord(coord), reached(false), description(""), shownumber(true), isDragging(false), altitude(altitude), map(map), myType(type) { numberI = 0; isEdit = true; isMagic = false; property.seq = WayPointItem::snumber; ++WayPointItem::snumber; this->setFlag(QGraphicsItem::ItemIsMovable, true); this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true); SetShowNumber(shownumber); RefreshPos(); SetDefault(coord.Lat(),coord.Lng(),altitude,property.seq); myHome = NULL; QList list = map->childItems(); foreach(QGraphicsItem * obj, list) { HomeItem *h = qgraphicsitem_cast (obj); if (h) { myHome = h; } } if (myHome) { map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing); relativeCoord.altitudeRelative = Altitude() - myHome->Altitude(); connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float))); } connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *))); emit manualCoordChange(this); connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos())); connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); this->setZValue(3); } WayPointItem::WayPointItem(MapGraphicItem *map, bool magicwaypoint) : reached(false), description(""), shownumber(true), isDragging(false), altitude(0), map(map) { isEdit = true; relativeCoord.bearing = 0; relativeCoord.distance = 0; relativeCoord.altitudeRelative = 0; myType = relative; if (magicwaypoint) { isMagic = true; property.seq = -1; } else { isMagic = false; property.seq = WayPointItem::snumber; ++WayPointItem::snumber; } numberI = 0; this->setFlag(QGraphicsItem::ItemIsMovable, true); this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true); SetShowNumber(shownumber); RefreshPos(); SetDefault(coord.Lat(),coord.Lng(),altitude,property.seq); myHome = NULL; QList list = map->childItems(); foreach(QGraphicsItem * obj, list) { HomeItem *h = qgraphicsitem_cast (obj); if (h) { myHome = h; } } if (myHome) { coord = map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing); SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative); connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float))); } connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *))); emit manualCoordChange(this); connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos())); connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); this->setZValue(3); } WayPointItem::WayPointItem(const internals::PointLatLng &coord, int const & altitude, const QString &description, MapGraphicItem *map, wptype type) : coord(coord), reached(false), description(description), shownumber(true), isDragging(false), altitude(altitude), map(map), myType(type) { isEdit = true; numberI = 0; isMagic = false; //picture.load(QString::fromUtf8(":/markers/images/marker.png")); property.seq = WayPointItem::snumber; ++WayPointItem::snumber; this->setFlag(QGraphicsItem::ItemIsMovable, true); this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true); SetShowNumber(shownumber); RefreshPos(); SetDefault(coord.Lat(),coord.Lng(),altitude,property.seq); myHome = NULL; QList list = map->childItems(); foreach(QGraphicsItem * obj, list) { HomeItem *h = qgraphicsitem_cast (obj); if (h) { myHome = h; } } if (myHome) { map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing); relativeCoord.altitudeRelative = Altitude() - myHome->Altitude(); connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float))); } connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *))); emit manualCoordChange(this); connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos())); connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); this->setZValue(3); } WayPointItem::WayPointItem(const distBearingAltitude &relativeCoordenate, const QString &description, MapGraphicItem *map) : relativeCoord(relativeCoordenate), reached(false), description(description), shownumber(true), isDragging(false), map(map) { isEdit = true; myHome = NULL; QList list = map->childItems(); foreach(QGraphicsItem * obj, list) { HomeItem *h = qgraphicsitem_cast (obj); if (h) { myHome = h; } } if (myHome) { connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float))); coord = map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing); SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative); } myType = relative; numberI = 0; isMagic = false; property.seq = WayPointItem::snumber; ++WayPointItem::snumber; this->setFlag(QGraphicsItem::ItemIsMovable, true); this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true); SetShowNumber(shownumber); RefreshPos(); SetDefault(coord.Lat(),coord.Lng(),altitude,property.seq); connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *))); emit manualCoordChange(this); connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos())); connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); this->setZValue(3); } void WayPointItem::setWPType(wptype type) { myType = type; emit WPValuesChanged(this); RefreshPos(); this->update(); } QRectF WayPointItem::boundingRect() const //鼠标可以操作的大小 { return QRectF(-10,-10,20,20); } void WayPointItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); if (this->isSelected()) { this->setZValue(4); } else { this->setZValue(3); } if(isSimple == true)//简单显示 { painter->setPen(Qt::green); painter->drawRect(-6,-6,12,12); painter->drawLine(-6,-6,6,6); painter->drawLine(-6,6,6,-6); if (this->isSelected()) { painter->setPen(Qt::red); painter->drawRect(QRectF(boundingRect())); } } else { QPen ePen; ePen.setWidth(1); if(isEdit == true)//编辑界面 { if (this->isSelected()) {//被选中才能是绿色 ePen.setColor(QColor("#008B00")); painter->setBrush(QColor("#008B00")); } else { ePen.setColor(QColor("#8B4500")); painter->setBrush(QColor("#8B4500")); } } else//飞行界面 { if (isCurrent) {//选择作为当前才能显示绿色 ePen.setColor(QColor("#008B00")); painter->setBrush(QColor("#008B00")); } else { ePen.setColor(QColor("#8B4500")); painter->setBrush(QColor("#8B4500")); } } painter->setPen(ePen); painter->drawEllipse(boundingRect()); ePen.setColor(QColor("#FFFFFF")); painter->setPen(ePen); QFont font; font.setWeight(QFont::ExtraLight); font.setFamily("Arial");//非衬线 font.setPixelSize(12); painter->setFont(font); painter->drawText(boundingRect(),Qt::AlignCenter,QString::number(property.seq)); /* font.setBold(true); painter->setFont(font); ePen.setColor(QColor("#FF4040")); painter->setPen(ePen); painter->drawText(QRect(12,-10,200,20),Qt::AlignLeft|Qt::AlignVCenter,QString::number(Elevation)); */ } } void WayPointItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { //qInfo() << "DoubleClickEvent"; emit waypointdoubleclick(this); } } void WayPointItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { //qInfo() << "PressEvent"; isDragging = true; qDebug() << "PressEvent isEdit" <parent(); } QGraphicsItem::mousePressEvent(event); } void WayPointItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { //qInfo() << "ReleaseEvent"; isDragging = false; //qDebug() << "isEdit" <pos(), this); emit WPValuesChanged(this); coord = map->FromLocalToLatLng(this->pos().x(), this->pos().y()); SetLat(coord.Lat()); SetLng(coord.Lng()); emit WPChanged(this->Number(),Coord().Lat(),Coord().Lng()); } ElevationTrig(); //发送航点的属性 emit WPProperty(property.param1,property.param2,property.param3,property.param4, property.x,property.y,property.z, property.seq, property.group, property.command, property.target_system, property.target_component, property.frame, property.current, property.autocontinue, property.mission_type); emit setCurrentPoint(this->Number()); } else//这时候是在飞行界面 { //发出可以设置当前点的信号 emit SetCurrent(this->Number()); } } QGraphicsItem::mouseReleaseEvent(event); } void WayPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (isDragging) { //qDebug() << "isFollowPrevious" <pos(), this); emit WPValuesChanged(this); } } QGraphicsItem::mouseMoveEvent(event); } void WayPointItem::setPosition(QPointF p) { coord = map->FromLocalToLatLng(p.x(),p.y()); SetLat(coord.Lat()); SetLng(coord.Lng()); this->setPos(p); emit localPositionChanged(this->pos(), this); emit WPValuesChanged(this); } void WayPointItem::SetAltitude(const float &value) { if (altitude == value) { return; } altitude = value; if (myHome) { relativeCoord.altitudeRelative = altitude - myHome->Altitude(); } emit WPValuesChanged(this); this->update(); } void WayPointItem::setRelativeCoord(distBearingAltitude value) { if (qAbs(value.distance - relativeCoord.distance) < 0.1 && qAbs(value.bearing - relativeCoord.bearing) < 0.01 && value.altitudeRelative == relativeCoord.altitudeRelative) { return; } relativeCoord = value; if (myHome) { SetCoord(map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing)); SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative); } RefreshPos(); emit WPValuesChanged(this); this->update(); } void WayPointItem::SetCoord(const internals::PointLatLng &value) { if (qAbs(Coord().Lat() - value.Lat()) < 0.0001 && qAbs(Coord().Lng() - value.Lng()) < 0.0001) { return; } coord = value; distBearingAltitude back = relativeCoord; if (myHome) { map->Projection()->offSetFromLatLngs(myHome->Coord(), Coord(), back.distance, back.bearing); } if (qAbs(back.bearing - relativeCoord.bearing) > 0.01 || qAbs(back.distance - relativeCoord.distance) > 0.1) { relativeCoord = back; } emit WPValuesChanged(this); RefreshPos(); this->update(); } void WayPointItem::SetDescription(const QString &value) { if (description == value) { return; } description = value; emit WPValuesChanged(this); this->update(); } void WayPointItem::SetNumber(const int &value) { int oldnumber = property.seq; property.seq = value; if(isSimple == true)//简单显示 { numberI->setText(QString::number(numberAdjusted())); } this->update(); //emit WPNumberChanged(oldnumber, value, this); } void WayPointItem::SetReached(const bool &value) { reached = value; emit WPValuesChanged(this); this->update(); } void WayPointItem::SetShowNumber(const bool &value) { if(isSimple == true)//简单显示 { shownumber = value; if ((numberI == 0) && value) { numberI = new QGraphicsSimpleTextItem(this); QFont font; font.setWeight(QFont::ExtraLight); font.setFamily("Arial");//非衬线 font.setPixelSize(12); numberI->setFont(font); numberI->setZValue(3); numberI->setPen(QPen(QColor("#FF00FF"))); numberI->setPos(10, -6); numberI->setText(QString::number(numberAdjusted())); } else if (!value && numberI) { delete numberI; } } this->update(); } void WayPointItem::WPDeleted(const int &onumber, WayPointItem *waypoint) { Q_UNUSED(waypoint); int n = property.seq; if (n > onumber) { SetNumber(--n); } } void WayPointItem::WPInserted(const int &onumber, WayPointItem *waypoint) { if (Number() == -1) { return; } if (waypoint != this) { int n = property.seq; if (onumber <= n) { SetNumber(++n); } } } void WayPointItem::onHomePositionChanged(internals::PointLatLng homepos, float homeAltitude) { if (myType == relative) { coord = map->Projection()->translate(homepos, relativeCoord.distance, relativeCoord.bearing); SetAltitude(relativeCoord.altitudeRelative + homeAltitude); emit WPValuesChanged(this); RefreshPos(); this->update(); } else { if (myHome) { map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing); relativeCoord.altitudeRelative = Altitude() - homeAltitude; } emit WPValuesChanged(this); } } void WayPointItem::WPRenumbered(const int &oldnumber, const int &newnumber, WayPointItem *waypoint) { if (waypoint != this) {//如果wp不是当前点,说明需要重新排序 if (((oldnumber > property.seq) && (newnumber <= property.seq))) { int n = property.seq; SetNumber(++n); } else if (((oldnumber < property.seq) && (newnumber > property.seq))) { int n = property.seq; SetNumber(--n); } else if (newnumber == property.seq) { int n = property.seq; SetNumber(++n); } qDebug() << "set property.seq" << property.seq; } } int WayPointItem::type() const { // Enable the use of qgraphicsitem_cast with this item. return Type; } WayPointItem::~WayPointItem() { emit aboutToBeDeleted(this); --WayPointItem::snumber; } void WayPointItem::RefreshPos() { core::Point point = map->FromLatLngToLocal(coord); SetLat(coord.Lat()); SetLng(coord.Lng()); this->setPos(point.X(), point.Y()); //qDebug() << "RefreshPos"; emit localPositionChanged(this->pos(), this); //ElevationUpdate(); //ElevationTrig(); } void WayPointItem::setOpacitySlot(qreal opacity) { setOpacity(opacity); } void WayPointItem::setFlag(QGraphicsItem::GraphicsItemFlag flag, bool enabled) { if (isMagic) { QGraphicsItem::setFlag(flag, enabled); return; } else if (flag == QGraphicsItem::ItemIsMovable) { if (enabled) { //picture.load(QString::fromUtf8(":/markers/images/marker.png")); } else { //picture.load(QString::fromUtf8(":/markers/images/waypoint_marker2.png")); } } QGraphicsItem::setFlag(flag, enabled); } //=============属性设置================= void WayPointItem::setWPProperty(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) { if(seq == property.seq) { qDebug() << seq << "set property"; internals::PointLatLng latlng; latlng.SetLng(y * 10e-8); latlng.SetLat(x * 10e-8); SetCoord(latlng); qDebug() << Coord().Lng() << Coord().Lat(); property.param1 = param1; property.param2 = param2; property.param3 = param3; property.param4 = param4; property.x = x; property.y = y; property.z = z; property.seq = seq; property.group = group; property.command = command; property.target_system = target_system; property.target_component = target_component; property.frame = frame; property.current = current; property.autocontinue = autocontinue; property.mission_type = mission_type; if(command > MAV_CMD::MAV_CMD_NAV_LAST) { qDebug() << "is cmd point"; isFollowPrevious = true; this->setFlag(QGraphicsItem::ItemIsMovable, false); } else { isFollowPrevious = false; this->setFlag(QGraphicsItem::ItemIsMovable, true); } qDebug() << this->Number(); emit WPFollowPrevious(isFollowPrevious,this); ElevationTrig(); } } void WayPointItem::emitWPProperty(void) { //发送航点的属性 qDebug() << property.seq << "emit property"; emit WPProperty(property.param1,property.param2,property.param3,property.param4, property.x,property.y,property.z, property.seq, property.group, property.command, property.target_system, property.target_component, property.frame, property.current, property.autocontinue, property.mission_type); } void WayPointItem::SetDefault(double lat,double lng,float alt,uint16_t seq) { property.param1 = 100; property.param2 = 50; property.param3 = 50; property.param4 = 0; property.x = lat * 10e6; property.y = lng * 10e6; property.z = alt; property.seq = seq; property.group = 0; property.command = MAV_CMD::MAV_CMD_NAV_WAYPOINT; property.target_system = 0; property.target_component = 0; property.frame = MAV_FRAME::MAV_FRAME_GLOBAL; property.current = 0; property.autocontinue = 0; property.mission_type = 0; if(property.command > MAV_CMD::MAV_CMD_NAV_LAST) { qDebug() << "is cmd point"; isFollowPrevious = true; this->setFlag(QGraphicsItem::ItemIsMovable, false); } else { isFollowPrevious = false; this->setFlag(QGraphicsItem::ItemIsMovable, true); } emit WPFollowPrevious(isFollowPrevious,this); ElevationTrig(); //emit AltitudeChanged(this->Number(),property.z); //... } void WayPointItem::SetParam1(float value) { property.param1 = value; } void WayPointItem::SetParam2(float value) { property.param2 = value; } void WayPointItem::SetParam3(float value) { property.param3 = value; } void WayPointItem::SetParam4(float value) { property.param4 = value; } void WayPointItem::SetLat(double value) { property.x = value * 10e6; } void WayPointItem::SetLng(double value) { property.y = value * 10e6; } void WayPointItem::SetAlt(float value) { property.z = value; //emit AltitudeChanged(this->Number(),property.z); } void WayPointItem::SetSeq(uint16_t value) { property.seq = value; } void WayPointItem::SetCommand(uint16_t value) { property.command = value; if(property.command > MAV_CMD::MAV_CMD_NAV_LAST) { qDebug() << "is cmd point"; isFollowPrevious = true; this->setFlag(QGraphicsItem::ItemIsMovable, false); } else { isFollowPrevious = false; this->setFlag(QGraphicsItem::ItemIsMovable, true); } emit WPFollowPrevious(isFollowPrevious,this); } void WayPointItem::SetGroup(uint16_t value) { property.group = value; } void WayPointItem::ElevationTrig(void) { if(isElevationLock) { isElevationRequest = true; } else { QNetworkAccessManager *networkManager = nullptr; networkManager=new QNetworkAccessManager; double lat = this->Coord().Lat(); double lng = this->Coord().Lng(); QString url = QString("https://api.airmap.com/elevation/v1/ele/?points=%1,%2").arg(lat).arg(lng); QNetworkRequest request = QNetworkRequest(QUrl(url)); connect(networkManager,SIGNAL(finished(QNetworkReply*)), this,SLOT(ElevationUpdate(QNetworkReply *))); networkManager->get(request); isElevationLock = true; isElevationRequest = false; } } void WayPointItem::ElevationUpdate(QNetworkReply *reply) { QByteArray bytes = reply->readAll(); QJsonParseError jsonParseError; QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError); if (jsonParseError.error != QJsonParseError::NoError) { return; } QJsonObject json = doc.object(); if(json.value("status").toString() == "success") { QJsonValue jsonValue = json.value("data"); if (!jsonValue.isArray()) { return; } QJsonArray Array = jsonValue.toArray(); Elevation = Array.at(0).toInt(); qDebug() << "Seq:" << this->Number() << "Elevation" << Elevation; emit ElevationChanged(this->Number(),Elevation); emit AltitudeChanged(this->Number(),property.z); update(); } isElevationLock = false; //结束之后检查一下是不是又触发了,是的话再查一次 if(isElevationRequest) { ElevationTrig(); } } //==============全局计数=================== int WayPointItem::snumber = 1;//从1开始 }