QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GeoMapMissionDirectionArrows.qml
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 *
5 * QGroundControl is licensed according to the terms in the file
6 * COPYING.md in the root of the source code directory.
7 *
8 ****************************************************************************/
9
10import QtQuick
11import QtPositioning
12
13import QGroundControl
14import QGroundControl.Controls
15
16/// General flight-path direction indicators for the GeoMap: one arrow per
17/// entry in MissionController.directionArrows (added to the second flight
18/// path segment and every 5 segments thereafter, regardless of simple vs
19/// complex item — see MissionController::_recalcFlightPathSegments),
20/// mirroring the MapLineArrow Repeater in src/FlightMap/MapItems/PlanMapItems.qml.
21Item {
22 id: root
23
24 property var missionController
25 property var scene
26 property var surfaceModel
27 property real homeTerrainBias: 0 ///< See GeoMapWaypointItem.homeTerrainBias
28
29 Repeater {
30 model: root.missionController ? root.missionController.directionArrows : 0
31
32 GeoMapSegmentArrow {
33 id: arrow
34 scene: root.scene
35 surfaceModel: root.surfaceModel
36 fromCoord: {
37 _terrainRev
38 return _terrainLeg ? _drapedPoint(0.75 - _halfChordFraction)
39 : QtPositioning.coordinate(object.coordinate1.latitude, object.coordinate1.longitude,
40 object.coord1AMSLAlt + root.homeTerrainBias)
41 }
42 toCoord: {
43 _terrainRev
44 return _terrainLeg ? _drapedPoint(0.75 + _halfChordFraction)
45 : QtPositioning.coordinate(object.coordinate2.latitude, object.coordinate2.longitude,
46 object.coord2AMSLAlt + root.homeTerrainBias)
47 }
48 fraction: _terrainLeg ? 0.5 : 0.75
49
50 // Terrain-frame legs are draped over the DEM (see
51 // GeoMapMissionPath), so anchor the arrow to a short draped chord
52 // around the 0.75 mark rather than the straight AMSL chord: the
53 // chord midpoint puts the arrow on the ribbon and the chord ends
54 // give it the local tangent heading
55 readonly property bool _terrainLeg: !!root.surfaceModel && object.segmentType === FlightPathSegment.SegmentTypeTerrainFrame
56
57 // Cap the chord at 50 m so it stays local to the ribbon on long
58 // legs (a 10% chord averages away terrain curvature), while short
59 // legs keep enough screen separation for a stable heading
60 readonly property real _halfChordFraction: {
61 const len = object.coordinate1.distanceTo(object.coordinate2)
62 return len > 0 ? Math.min(0.05, 25 / len) : 0.05
63 }
64
65 // terrainHeightAt is not NOTIFY-reactive; read in the coordinate
66 // bindings above so they re-sample as DEM patches stream in
67 property int _terrainRev: 0
68
69 // Same AGL-ramp draping as GeoMapMissionPath._appendTerrainLeg
70 function _drapedPoint(f) {
71 const c1 = object.coordinate1
72 const c2 = object.coordinate2
73 const point = c1.atDistanceAndAzimuth(c1.distanceTo(c2) * f, c1.azimuthTo(c2))
74 const agl1 = object.coord1AMSLAlt - root.surfaceModel.terrainHeightAt(c1)
75 const agl2 = object.coord2AMSLAlt - root.surfaceModel.terrainHeightAt(c2)
76 return QtPositioning.coordinate(point.latitude, point.longitude,
77 root.surfaceModel.terrainHeightAt(point) + agl1 + ((agl2 - agl1) * f) + root.homeTerrainBias)
78 }
79
80 Connections {
81 target: root.surfaceModel
82 enabled: arrow._terrainLeg
83 function onTerrainHeightsChanged() { arrow._terrainRev++ }
84 }
85 }
86 }
87}