diff --git a/src/FlightMap/MapItems/MissionLineView.qml b/src/FlightMap/MapItems/MissionLineView.qml index 39382391f3f2d2c5569351083fa3086716f21f93..4f9fe11d68a6b4813530050cbbc38066eae12b73 100644 --- a/src/FlightMap/MapItems/MissionLineView.qml +++ b/src/FlightMap/MapItems/MissionLineView.qml @@ -17,8 +17,6 @@ import QGroundControl.Palette 1.0 /// The MissionLineView control is used to add lines between mission items MapItemView { - id: _root - property bool homePositionValid: true ///< true: show home position, false: don't show home position delegate: MapPolyline { @@ -26,9 +24,6 @@ MapItemView { line.color: "#be781c" // Hack, can't get palette to work in here z: QGroundControl.zOrderWaypointLines - path: object ? [ - object.coordinate1, - object.coordinate2, - ] : [] + path: object ? [ object.coordinate1, object.coordinate2 ] : [ ] } } diff --git a/src/MissionManager/MapLineArrow.qml b/src/MissionManager/MapLineArrow.qml index d9d0e59713dd0b23e04d7a0fcc200ecce0863e0b..50b80439b82930ae406ae81de9ec1843b785d3db 100644 --- a/src/MissionManager/MapLineArrow.qml +++ b/src/MissionManager/MapLineArrow.qml @@ -22,17 +22,17 @@ MapQuickItem { property color arrowColor: "white" property var fromCoord: QtPositioning.coordinate() property var toCoord: QtPositioning.coordinate() - property bool exitPosition: false + property int arrowPosition: 1 ///< 1: first quarter, 2: halfway, 3: last quarter property var _map: parent - property real _arrowSize: 20 + property real _arrowSize: 15 property real _arrowHeading: 0 function _updateArrowDetails() { if (fromCoord && fromCoord.isValid && toCoord && toCoord.isValid) { _arrowHeading = fromCoord.azimuthTo(toCoord) var lineDistanceQuarter = fromCoord.distanceTo(toCoord) / 4 - coordinate = fromCoord.atDistanceAndAzimuth(lineDistanceQuarter * (exitPosition ? 3 : 1), _arrowHeading) + coordinate = fromCoord.atDistanceAndAzimuth(lineDistanceQuarter * arrowPosition, _arrowHeading) } else { coordinate = QtPositioning.coordinate() _arrowHeading = 0 diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 5c5f065e78cb7904f23946aa4ba854f22fafcb72..14c138de4b9b4eaea885cbe75470c5535b3a5144 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -1070,30 +1070,36 @@ double MissionController::_calcDistanceToHome(VisualMissionItem* currentItem, Vi return distanceOk ? homeCoord.distanceTo(currentCoord) : 0.0; } -void MissionController::_addWaypointLineSegment(CoordVectHashTable& prevItemPairHashTable, VisualItemPair& pair) +CoordinateVector* MissionController::_addWaypointLineSegment(CoordVectHashTable& prevItemPairHashTable, VisualItemPair& pair) { + CoordinateVector* coordVector = nullptr; + if (prevItemPairHashTable.contains(pair)) { // Pair already exists and connected, just re-use - _linesTable[pair] = prevItemPairHashTable.take(pair); + _linesTable[pair] = coordVector = prevItemPairHashTable.take(pair); } else { // Create a new segment and wire update notifiers - auto linevect = new CoordinateVector(pair.first->isSimpleItem() ? pair.first->coordinate() : pair.first->exitCoordinate(), pair.second->coordinate(), this); + coordVector = new CoordinateVector(pair.first->isSimpleItem() ? pair.first->coordinate() : pair.first->exitCoordinate(), pair.second->coordinate(), this); auto originNotifier = pair.first->isSimpleItem() ? &VisualMissionItem::coordinateChanged : &VisualMissionItem::exitCoordinateChanged; auto endNotifier = &VisualMissionItem::coordinateChanged; // Use signals/slots to update the coordinate endpoints - connect(pair.first, originNotifier, linevect, &CoordinateVector::setCoordinate1); - connect(pair.second, endNotifier, linevect, &CoordinateVector::setCoordinate2); + connect(pair.first, originNotifier, coordVector, &CoordinateVector::setCoordinate1); + connect(pair.second, endNotifier, coordVector, &CoordinateVector::setCoordinate2); // FIXME: We should ideally have signals for 2D position change, alt change, and 3D position change // Not optimal, but still pretty fast, do a full update of range/bearing/altitudes connect(pair.second, &VisualMissionItem::coordinateChanged, this, &MissionController::_recalcMissionFlightStatus); - _linesTable[pair] = linevect; + _linesTable[pair] = coordVector; } + + return coordVector; } void MissionController::_recalcWaypointLines(void) { + int segmentCount = 0; + CoordinateVector* lastCoordVector = nullptr; bool firstCoordinateItem = true; VisualMissionItem* lastCoordinateItem = qobject_cast(_visualItems->get(0)); @@ -1105,6 +1111,7 @@ void MissionController::_recalcWaypointLines(void) _linesTable.clear(); _waypointLines.clear(); _waypointPath.clear(); + _directionArrows.clear(); bool linkEndToHome; SimpleMissionItem* lastItem = _visualItems->value(_visualItems->count() - 1); @@ -1128,13 +1135,20 @@ void MissionController::_recalcWaypointLines(void) } if (item->specifiesCoordinate() && !item->isStandaloneCoordinate()) { - firstCoordinateItem = false; if (lastCoordinateItem != _settingsItem || (homePositionValid && linkStartToHome)) { if (!_flyView) { VisualItemPair pair(lastCoordinateItem, item); - _addWaypointLineSegment(old_table, pair); + lastCoordVector = _addWaypointLineSegment(old_table, pair); + segmentCount++; + if (firstCoordinateItem || !lastCoordinateItem->isSimpleItem() || !item->isSimpleItem()) { + _directionArrows.append(lastCoordVector); + } else if (segmentCount > 5) { + segmentCount = 0; + _directionArrows.append(lastCoordVector); + } } } + firstCoordinateItem = false; _waypointPath.append(QVariant::fromValue(item->coordinate())); lastCoordinateItem = item; } @@ -1147,7 +1161,7 @@ void MissionController::_recalcWaypointLines(void) if (linkEndToHome && lastCoordinateItem != _settingsItem && homePositionValid) { if (!_flyView) { VisualItemPair pair(lastCoordinateItem, _settingsItem); - _addWaypointLineSegment(old_table, pair); + lastCoordVector = _addWaypointLineSegment(old_table, pair); } else { _waypointPath.append(QVariant::fromValue(_settingsItem->coordinate())); } @@ -1168,10 +1182,14 @@ void MissionController::_recalcWaypointLines(void) // Anything left in the old table is an obsolete line object that can go qDeleteAll(old_table); + if (lastCoordVector) { + _directionArrows.append(lastCoordVector); + } + _recalcMissionFlightStatus(); if (_waypointPath.count() == 0) { - // MapPolyLine has a bug where if you can from a path which has elements to an empty path the line drawn + // MapPolyLine has a bug where if you change from a path which has elements to an empty path the line drawn // is not cleared from the map. This hack works around that since it causes the previous lines to be remove // as then doesn't draw anything on the map. _waypointPath.append(QVariant::fromValue(QGeoCoordinate(0, 0))); diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index abe5ac741ee43935d119d8be1e32edaa868c715b..6fa43f346c8efae974d2945eaded4d2825c3a481 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -70,6 +70,7 @@ public: Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged) Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) ///< Used by Plan view only for interactive editing Q_PROPERTY(QVariantList waypointPath READ waypointPath NOTIFY waypointPathChanged) ///< Used by Fly view only for static display + Q_PROPERTY(QmlObjectListModel* directionArrows READ directionArrows CONSTANT) Q_PROPERTY(QStringList complexMissionItemNames READ complexMissionItemNames NOTIFY complexMissionItemNamesChanged) Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged) @@ -169,6 +170,7 @@ public: QmlObjectListModel* visualItems (void) { return _visualItems; } QmlObjectListModel* waypointLines (void) { return &_waypointLines; } + QmlObjectListModel* directionArrows (void) { return &_directionArrows; } QVariantList waypointPath (void) { return _waypointPath; } QStringList complexMissionItemNames (void) const; QGeoCoordinate plannedHomePosition (void) const; @@ -273,7 +275,7 @@ private: void _updateBatteryInfo(int waypointIndex); bool _loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString); void _initLoadedVisualItems(QmlObjectListModel* loadedVisualItems); - void _addWaypointLineSegment(CoordVectHashTable& prevItemPairHashTable, VisualItemPair& pair); + CoordinateVector* _addWaypointLineSegment(CoordVectHashTable& prevItemPairHashTable, VisualItemPair& pair); void _addTimeDistance(bool vtolInHover, double hoverTime, double cruiseTime, double extraTime, double distance, int seqNum); int _insertComplexMissionItemWorker(ComplexMissionItem* complexItem, int i); void _warnIfTerrainFrameUsed(void); @@ -285,6 +287,7 @@ private: MissionSettingsItem* _settingsItem; QmlObjectListModel _waypointLines; QVariantList _waypointPath; + QmlObjectListModel _directionArrows; CoordVectHashTable _linesTable; bool _firstItemsFromVehicle; bool _itemsRequested; diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 0418e9fb0eeaa106399cf3db9384dbda18e0ed1b..8a141c2558d1e61a3c4882e3862fe5dd123a463b 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -472,6 +472,17 @@ Item { model: _editingLayer == _layerMission ? _missionController.waypointLines : undefined } + MapItemView { + model: _editingLayer == _layerMission ? _missionController.directionArrows : undefined + + delegate: MapLineArrow { + fromCoord: object ? object.coordinate1 : undefined + toCoord: object ? object.coordinate2 : undefined + arrowPosition: 2 + z: QGroundControl.zOrderWaypointLines + } + } + // Add the vehicles to the map MapItemView { model: QGroundControl.multiVehicleManager.vehicles diff --git a/src/PlanView/TransectStyleMapVisuals.qml b/src/PlanView/TransectStyleMapVisuals.qml index 90d93ce7a2dd1387bc06f04707d81bdeb0e6c964..8e8e328cb4e756ffb1b1b9876bdb7b2634437a84 100644 --- a/src/PlanView/TransectStyleMapVisuals.qml +++ b/src/PlanView/TransectStyleMapVisuals.qml @@ -138,7 +138,7 @@ Item { MapLineArrow { fromCoord: _transectPoints[_firstTrueTransectIndex] toCoord: _transectPoints[_firstTrueTransectIndex + 1] - exitPosition: false + arrowPosition: 1 visible: _currentItem } } @@ -149,7 +149,7 @@ Item { MapLineArrow { fromCoord: _transectPoints[nextTrueTransectIndex] toCoord: _transectPoints[nextTrueTransectIndex + 1] - exitPosition: false + arrowPosition: 1 visible: _currentItem && _transectCount > 3 property int nextTrueTransectIndex: _firstTrueTransectIndex + (_hasTurnaround ? 4 : 2) @@ -162,7 +162,7 @@ Item { MapLineArrow { fromCoord: _transectPoints[_lastTrueTransectIndex - 1] toCoord: _transectPoints[_lastTrueTransectIndex] - exitPosition: true + arrowPosition: 3 visible: _currentItem } } @@ -173,7 +173,7 @@ Item { MapLineArrow { fromCoord: _transectPoints[prevTrueTransectIndex - 1] toCoord: _transectPoints[prevTrueTransectIndex] - exitPosition: true + arrowPosition: 13 visible: _currentItem && _transectCount > 3 property int prevTrueTransectIndex: _lastTrueTransectIndex - (_hasTurnaround ? 4 : 2)