/**************************************************************************** * * (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 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 i var homePosition = fitHomePosition() if (homePosition.isValid && geoFenceController.circleEnabled) { var azimuthList = [ 0, 180, 90, 270 ] for (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 (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("Launch") 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("Specified Location") Layout.fillWidth: true onClicked: { dropButton.hideDropDown() map.centerToSpecifiedLocation() } } 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