5import QGroundControl.FlightMap
7/// Set of functions for fitting the map view to a specific constraint
10 property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations
11 property var planMasterController
13 property var _missionController: planMasterController.missionController
14 property var _geoFenceController: planMasterController.geoFenceController
15 property var _rallyPointController: planMasterController.rallyPointController
17 function fitHomePosition() {
18 var homePosition = QtPositioning.coordinate()
19 var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle
20 if (usePlannedHomePosition) {
21 homePosition = _missionController.visualItems.get(0).coordinate
22 } else if (activeVehicle) {
23 homePosition = activeVehicle.homePosition
28 /// Normalize latitude to range: 0 to 180, S to N
29 function normalizeLat(lat) {
33 /// Normalize longitude to range: 0 to 360, W to E
34 function normalizeLon(lon) {
38 /// Fits the visible region of the map to inclues all of the specified coordinates. If no coordinates
39 /// are specified the map will center to fitHomePosition()
40 function fitMapViewportToAllCoordinates(coordList) {
41 var mapFitViewport = Qt.rect(0, 0, map.width, map.height)
42 if (coordList.length === 0) {
43 var homeCoord = fitHomePosition()
44 if (homeCoord.isValid) {
45 map.center = homeCoord
50 // Create the normalized lat/lon corners for the coordinate bounding rect from the list of coordinates
51 var north = normalizeLat(coordList[0].latitude)
53 var east = normalizeLon(coordList[0].longitude)
55 for (var i = 1; i < coordList.length; i++) {
56 var lat = coordList[i].latitude
57 var lon = coordList[i].longitude
58 if (isNaN(lat) || lat == 0 || isNaN(lon) || lon == 0) {
59 // Be careful of invalid coords which can happen when items are not yet complete
62 lat = normalizeLat(lat)
63 lon = normalizeLon(lon)
64 north = Math.max(north, lat)
65 south = Math.min(south, lat)
66 east = Math.max(east, lon)
67 west = Math.min(west, lon)
70 // Expand the coordinate bounding rect to make room for the tools around the edge of the map
71 var latDegreesPerPixel = (north - south) / mapFitViewport.height
72 var lonDegreesPerPixel = (east - west) / mapFitViewport.width
73 north = Math.min(north + (mapFitViewport.y * latDegreesPerPixel), 180)
74 south = Math.max(south - ((map.height - mapFitViewport.bottom) * latDegreesPerPixel), 0)
75 west = Math.max(west - (mapFitViewport.x * lonDegreesPerPixel), 0)
76 east = Math.min(east + ((map.width - mapFitViewport.right) * lonDegreesPerPixel), 360)
78 // Back off on zoom level
79 east = Math.min(east * 1.0000075, 360)
80 north = Math.min(north * 1.0000075, 180)
81 west = west * 0.9999925
82 south = south * 0.9999925
84 // Fit the map region to the new bounding rect
85 var topLeftCoord = QtPositioning.coordinate(north - 90.0, west - 180.0)
86 var bottomRightCoord = QtPositioning.coordinate(south - 90.0, east - 180.0)
87 map.setVisibleRegion(QtPositioning.rectangle(topLeftCoord, bottomRightCoord))
90 function addMissionItemCoordsForFit(coordList) {
91 for (var i = 1; i < _missionController.visualItems.count; i++) {
92 var missionItem = _missionController.visualItems.get(i)
93 if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
94 if(missionItem.boundingCube.isValid()) {
95 coordList.push(missionItem.boundingCube.pointNW)
96 coordList.push(missionItem.boundingCube.pointSE)
98 coordList.push(missionItem.coordinate)
104 function fitMapViewportToMissionItems() {
105 if (!_missionController.visualItems) {
106 // Being called prior to controller.start
110 addMissionItemCoordsForFit(coordList)
111 fitMapViewportToAllCoordinates(coordList)
114 function addFenceItemCoordsForFit(coordList) {
116 var homePosition = fitHomePosition()
117 if (homePosition.isValid && _geoFenceController.circleEnabled) {
118 var azimuthList = [ 0, 180, 90, 270 ]
119 for (i = 0; i < azimuthList.length; i++) {
120 var edgeCoordinate = homePosition.atDistanceAndAzimuth(_geoFenceController.circleRadius, azimuthList[i])
121 coordList.push(edgeCoordinate)
124 if (_geoFenceController.polygonEnabled && _geoFenceController.mapPolygon.path.count > 2) {
125 for (i = 0; i < _geoFenceController.mapPolygon.path.count; i++) {
126 coordList.push(_geoFenceController.mapPolygon.path[i])
131 function fitMapViewportToFenceItems() {
133 addFenceItemCoordsForFit(coordList)
134 fitMapViewportToAllCoordinates(coordList)
137 function addRallyItemCoordsForFit(coordList) {
138 for (var i=0; i<_rallyPointController.points.count; i++) {
139 coordList.push(_rallyPointController.points.get(i).coordinate)
143 function fitMapViewportToRallyItems() {
145 addRallyItemCoordsForFit(coordList)
146 fitMapViewportToAllCoordinates(coordList)
149 function fitMapViewportToAllItems() {
150 if (!_missionController.visualItems) {
151 // Being called prior to controller.start
155 addMissionItemCoordsForFit(coordList)
156 addFenceItemCoordsForFit(coordList)
157 addRallyItemCoordsForFit(coordList)
158 fitMapViewportToAllCoordinates(coordList)