QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GeoMapADSBVehicleItem.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 QtQuick3D
12import QtPositioning
13
14import QGroundControl
15import QGroundControl.Controls
16import QGroundControl.GeoMap
17
18/// ADS-B traffic marker: the GeoMap counterpart of ADSBVehicleMapItem.qml.
19/// The 2D screen-space icon crossfades into a flat quad lying on the map
20/// plane in 3D (traffic reports heading only — no attitude — so no full 3D
21/// model), anchored at the reported AMSL altitude with a circular drop
22/// shadow on the terrain for vertical situational awareness. Targets
23/// without an altitude clamp to the ground.
24Item {
25 id: root
26
27 property var scene
28 property var surfaceModel
29 property var coordinate ///< QGeoCoordinate lat/lon (altitude passed separately)
30 property double altitude: Number.NaN ///< AMSL meters, NaN to clamp to ground
31 property string callsign: ""
32 property double heading: Number.NaN ///< Degrees from north, NaN for none
33 property bool alert: false ///< Collision alert
34 property real size: ScreenTools.defaultFontPixelHeight * 3
35 property real homeTerrainBias: 0 ///< DEM-vs-AMSL bias at the active vehicle's home (see FlyViewGeoMap)
36
37 readonly property bool _hasAltitude: !isNaN(altitude)
38 readonly property var _camera: scene ? scene.camera : null
39 readonly property string _iconSource: alert ? "/qmlimages/AlertAircraft.svg" : "/qmlimages/AwarenessAircraft.svg"
40
41 // Constant apparent size: scene units per screen pixel at the camera's
42 // look-at distance. The built-in #Rectangle mesh is 100 units across.
43 readonly property real _quadScale: _camera
44 ? size * _camera.distance * _camera.unitsPerPixelAtUnitDistance / 100
45 : 1
46
47 function _labelText() {
48 return root._hasAltitude ? QGroundControl.unitsConversion.metersToAppSettingsVerticalDistanceUnitsString(root.altitude, 0) + "\n" + root.callsign : ""
49 }
50
51 // Drop shadow on the terrain below the target, draped as a filled circle
52 // so it follows slopes instead of clipping into them (a flat 3D quad at
53 // the sampled ground height gets partially buried on sloped terrain).
54 // Fades with the same terrainScale ramp as the icon crossfade.
55 GeoMapCircle {
56 readonly property real _terrainScale: root.scene ? root.scene.terrainScale : 0
57
58 visible: iconItem.visible && root._hasAltitude && _terrainScale > 0
59 opacity: _terrainScale
60 scene: root.scene
61 surfaceModel: root.surfaceModel
62 center: root.coordinate && root.coordinate.isValid ? root.coordinate : QtPositioning.coordinate()
63 radiusMeters: root._camera
64 ? ScreenTools.defaultFontPixelHeight * root._camera.distance * root._camera.unitsPerPixelAtUnitDistance
65 : 1
66 strokeColor: "transparent"
67 strokeWidth: 0
68 fillColor: Qt.alpha("black", 0.35)
69 }
70
71 GeoMapItem {
72 id: iconItem
73 visible: root.visible && root.coordinate && root.coordinate.isValid
74 scene: root.scene
75 surfaceModel: root.surfaceModel
76 altitudeMode: root._hasAltitude ? GeoMapItem.Absolute : GeoMapItem.ClampToGround
77 coordinate: {
78 if (!root.coordinate || !root.coordinate.isValid) {
79 return QtPositioning.coordinate()
80 }
81 return root._hasAltitude
82 ? QtPositioning.coordinate(root.coordinate.latitude, root.coordinate.longitude,
83 root.altitude + root.homeTerrainBias)
84 : root.coordinate
85 }
86 width: root.size
87 height: root.size
88 anchorPoint: Qt.point(width / 2, height / 2)
89
90 Image {
91 anchors.fill: parent
92 source: root._iconSource
93 mipmap: true
94 sourceSize.width: root.size
95 fillMode: Image.PreserveAspectFit
96 opacity: iconItem.contentOpacity2D
97 // Camera heading rotates map north on screen; the icon follows
98 rotation: (isNaN(root.heading) ? 0 : root.heading) + (root._camera ? root._camera.heading : 0)
99 }
100
101 // Flat map-plane icon for 3D: crossfades in against the 2D icon
102 delegate3D: Component {
103 // Scene axes are x east, y north, z up; heading is CW from north
104 // while positive z-rotation is CCW, hence the negation
105 Node {
106 eulerRotation.z: -(isNaN(root.heading) ? 0 : root.heading)
107 scale: Qt.vector3d(root._quadScale, root._quadScale, 1)
108
109 Model {
110 source: "#Rectangle"
111
112 materials: PrincipledMaterial {
113 lighting: PrincipledMaterial.NoLighting
114 alphaMode: PrincipledMaterial.Blend
115 cullMode: Material.NoCulling
116 baseColorMap: Texture {
117 sourceItem: Image {
118 source: root._iconSource
119 sourceSize: Qt.size(128, 128)
120 fillMode: Image.PreserveAspectFit
121 }
122 }
123 }
124 }
125 }
126 }
127
128 QGCLabel {
129 id: altitudeLabel
130 objectName: "adsbAltitudeLabel"
131 anchors.top: parent.bottom
132 anchors.horizontalCenter: parent.horizontalCenter
133 horizontalAlignment: Text.AlignHCenter
134 color: "white"
135 font.bold: true
136 visible: root._hasAltitude
137 text: root._labelText()
138 }
139 }
140
141 Connections {
142 target: QGroundControl.unitsConversion
143
144 function onUnitsChanged() {
145 altitudeLabel.text = Qt.binding(root._labelText)
146 }
147 }
148}