1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import QtPositioning 5.3
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
DropButton {
id: dropButton
dropDirection: dropRight
buttonImage: "/qmlimages/MapCenter.svg"
viewportMargins: ScreenTools.defaultFontPixelWidth / 2
lightBorders: map.isSatelliteMap
property var map
property rect mapFitViewport
property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations
property var geoFenceController
property var missionController
property var rallyPointController
property bool showMission: true
property bool showAllItems: true
property bool showFollowVehicle: false
property bool followVehicle: false
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
function fitHomePosition() {
var homePosition = QtPositioning.coordinate()
var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle
if (usePlannedHomePosition) {
homePosition = missionController.visualItems.get(0).coordinate
} else if (activeVehicle) {
homePosition = activeVehicle.homePosition
}
return homePosition
}
/// Normalize latitude to range: 0 to 180, S to N
function normalizeLat(lat) {
return lat + 90.0
}
/// Normalize longitude to range: 0 to 360, W to E
function normalizeLon(lon) {
return lon + 180.0
}
/// Fits the visible region of the map to inclues all of the specified coordinates. If no coordinates
/// are specified the map will center to fitHomePosition()
function fitMapViewportToAllCoordinates(coordList) {
if (coordList.length == 0) {
map.center = fitHomePosition()
return
}
// Create the normalized lat/lon corners for the coordinate bounding rect from the list of coordinates
var north = normalizeLat(coordList[0].latitude)
var south = north
var east = normalizeLon(coordList[0].longitude)
var west = east
for (var i=1; i<coordList.length; i++) {
var lat = normalizeLat(coordList[i].latitude)
var lon = normalizeLon(coordList[i].longitude)
north = Math.max(north, lat)
south = Math.min(south, lat)
east = Math.max(east, lon)
west = Math.min(west, lon)
}
// Expand the coordinate bounding rect to make room for the tools around the edge of the map
var latDegreesPerPixel = (north - south) / mapFitViewport.width
var lonDegreesPerPixel = (east - west) / mapFitViewport.height
north = Math.min(north + (mapFitViewport.y * latDegreesPerPixel), 180)
south = Math.max(south - ((map.height - mapFitViewport.bottom) * latDegreesPerPixel), 0)
west = Math.max(west - (mapFitViewport.x * lonDegreesPerPixel), 0)
east = Math.min(east + ((map.width - mapFitViewport.right) * lonDegreesPerPixel), 360)
// Fix the map region to the new bounding rect
var topLeftCoord = QtPositioning.coordinate(north - 90.0, west - 180.0)
var bottomRightCoord = QtPositioning.coordinate(south - 90.0, east - 180.0)
map.setVisibleRegion(QtPositioning.rectangle(topLeftCoord, bottomRightCoord))
}
function addMissionItemCoordsForFit(coordList) {
var homePosition = fitHomePosition()
if (homePosition.isValid) {
coordList.push(homePosition)
}
for (var i=1; i<missionController.visualItems.count; i++) {
var missionItem = missionController.visualItems.get(i)
if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
coordList.push(missionItem.coordinate)
}
}
}
function fitMapViewportToMissionItems() {
var coordList = [ ]
addMissionItemCoordsForFit(coordList)
fitMapViewportToAllCoordinates(coordList)
}
function addFenceItemCoordsForFit(coordList) {
var homePosition = fitHomePosition()
if (homePosition.isValid && geoFenceController.circleEnabled) {
var azimuthList = [ 0, 180, 90, 270 ]
for (var i=0; i<azimuthList.length; i++) {
var edgeCoordinate = homePosition.atDistanceAndAzimuth(geoFenceController.circleRadius, azimuthList[i])
coordList.push(edgeCoordinate)
}
}
if (geoFenceController.polygonEnabled && geoFenceController.polygon.count() > 2) {
for (var i=0; i<geoFenceController.polygon.count(); i++) {
coordList.push(geoFenceController.polygon.path[i])
}
}
}
function fitMapViewportToFenceItems() {
var coordList = [ ]
addFenceItemCoordsForFit(coordList)
fitMapViewportToAllCoordinates(coordList)
}
function addRallyItemCoordsForFit(coordList) {
for (var i=0; i<rallyPointController.points.count; i++) {
coordList.push(rallyPointController.points.get(i).coordinate)
}
}
function fitMapViewportToRallyItems() {
var coordList = [ ]
addRallyItemCoordsForFit(coordList)
fitMapViewportToAllCoordinates(coordList)
}
function fitMapViewportToAllItems() {
var coordList = [ ]
addMissionItemCoordsForFit(coordList)
addFenceItemCoordsForFit(coordList)
addRallyItemCoordsForFit(coordList)
fitMapViewportToAllCoordinates(coordList)
}
dropDownComponent: Component {
ColumnLayout {
spacing: ScreenTools.defaultFontPixelWidth * 0.5
QGCLabel { text: qsTr("Center map on:") }
QGCButton {
text: qsTr("Mission")
Layout.fillWidth: true
visible: showMission
enabled: !followVehicleCheckBox.checked
onClicked: {
dropButton.hideDropDown()
fitMapViewportToMissionItems()
}
}
QGCButton {
text: qsTr("All items")
Layout.fillWidth: true
visible: showAllItems
enabled: !followVehicleCheckBox.checked
onClicked: {
dropButton.hideDropDown()
fitMapViewportToAllItems()
}
}
QGCButton {
text: qsTr("Home")
Layout.fillWidth: true
enabled: !followVehicleCheckBox.checked
onClicked: {
dropButton.hideDropDown()
map.center = fitHomePosition()
}
}
QGCButton {
text: qsTr("Current Location")
Layout.fillWidth: true
enabled: map.gcsPosition ? map.gcsPosition.isValid && !followVehicleCheckBox.checked : false
onClicked: {
dropButton.hideDropDown()
map.center = map.gcsPosition
}
}
QGCButton {
text: qsTr("Vehicle")
Layout.fillWidth: true
enabled: _activeVehicle && _activeVehicle.latitude != 0 && _activeVehicle.longitude != 0 && !followVehicleCheckBox.checked
onClicked: {
dropButton.hideDropDown()
map.center = activeVehicle.coordinate
}
}
QGCCheckBox {
id: followVehicleCheckBox
text: qsTr("Follow Vehicle")
checked: followVehicle
visible: showFollowVehicle
onClicked: {
dropButton.hideDropDown()
dropButton.followVehicle = checked
}
}
} // Column
} // Component - dropDownComponent
} // DropButton