9 required property var mapControl ///< Map engine contract: fromCoordinate/toCoordinate
10 property var showText: obstacleDistance._showText
12 readonly property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
13 readonly property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
15 function paintObstacleOverlay(ctx) {
16 const vehiclePoint = root.mapControl.fromCoordinate(_activeVehicleCoordinate, false)
17 const centerX = vehiclePoint.x
18 const centerY = vehiclePoint.y
19 const maxRadiusPixels = 0.9 * root.height / 2 // Max pixels to center
20 const minRadiusPixels = maxRadiusPixels * 0.2
21 const metersPerPixelInCycle = (maxRadiusPixels - minRadiusPixels) / obstacleDistance._maxRadiusMeters
23 const leftCoord = root.mapControl.toCoordinate(Qt.point(0, root.y), false)
24 const rightCoord = root.mapControl.toCoordinate(Qt.point(100, root.y), false)
25 const metersIn100Pixels = leftCoord.distanceTo(rightCoord)
26 // Tilted 3D camera rays can miss the ground, leaving no usable scale
27 if (!leftCoord.isValid || !rightCoord.isValid || !isFinite(metersIn100Pixels) || metersIn100Pixels <= 0) {
30 const metersPerPixel = 100.0 / metersIn100Pixels
32 var minGradPixels = minRadiusPixels
33 var maxGradPixels = maxRadiusPixels
34 var metersToPixels = metersPerPixelInCycle
35 if (metersIn100Pixels < 4) {
37 maxGradPixels = obstacleDistance._maxRadiusMeters * metersPerPixel
38 metersToPixels = metersPerPixel
41 var grad = ctx.createRadialGradient(centerX, centerY, minGradPixels, centerX, centerY, maxGradPixels)
42 grad.addColorStop(0, Qt.rgba(1, 0, 0, 1))
43 grad.addColorStop(0.1, Qt.rgba(1, 0, 0, 0.7))
44 grad.addColorStop(0.5, Qt.rgba(1, 0.64, 0, 0.7))
45 grad.addColorStop(0.65, Qt.rgba(1, 0.64, 0, 0.3))
46 grad.addColorStop(0.95, Qt.rgba(0, 1, 0, 0.3))
47 grad.addColorStop(1, Qt.rgba(0, 1, 0, 0))
50 const height = minRadiusPixels / 8
51 for (var i = 0; i < obstacleDistance._rangesLen; ++i) {
52 const deg = i * obstacleDistance._incrementDeg
53 const rad = deg * Math.PI / 180.0
54 const m = obstacleDistance._ranges[obstacleDistance._degToRangeIdx(deg, true)] / 100.0
55 const pixels = minGradPixels + m * metersToPixels
56 const outerX = centerX + pixels * Math.sin(rad)
57 const outerY = centerY - pixels * Math.cos(rad)
58 const innerX = centerX + (pixels - height) * Math.sin(rad)
59 const innerY = centerY - (pixels - height) * Math.cos(rad)
61 points.push({'outer_x': outerX, 'outer_y': outerY, 'inner_x': innerX, 'inner_y': innerY, 'range': m})
64 ctx.strokeStyle = Qt.rgba(0, 0, 0, 0.8)
65 ctx.font = "bold 22px sans-serif"
68 for (var i = 0; i < points.length; i += 3) {
69 const i3 = (i + 3) % points.length // catch the line from the last to the first point
73 ctx.moveTo(points[i].inner_x, points[i].inner_y)
74 ctx.lineTo(points[i].outer_x, points[i].outer_y)
76 points[i + 1].outer_x, points[i + 1].outer_y,
77 points[i + 2].outer_x, points[i + 2].outer_y,
78 points[i3].outer_x, points[i3].outer_y)
79 ctx.lineTo(points[i3].inner_x, points[i3].inner_y)
81 points[i3].inner_x, points[i3].inner_y,
82 points[i + 2].inner_x, points[i + 2].inner_y,
83 points[i + 1].inner_x, points[i + 1].inner_y)
88 for (var k = iMin + 1; k < iMin + 2; ++k) {
89 const idx = k % points.length
90 if (points[idx].range < points[iMin].range)
94 var m = points[iMin].range
95 if (m < obstacleDistance._maxRadiusMeters && Math.abs(m - mPrev) > 2.0) {
96 const textX = points[iMin].inner_x
97 const textY = points[iMin].inner_y
99 ctx.fillStyle = Qt.rgba(1, 1, 1, 0.9)
100 const text = obstacleDistance._rangeToShow(m)
101 ctx.strokeText(text, textX, textY)
102 ctx.fillText(text, textX, textY)
109 ObstacleDistanceOverlay {