MapFitFunctions.qml 5.97 KB
Newer Older
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/

10 11
import QtQuick          2.3
import QtPositioning    5.3
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

import QGroundControl 1.0

/// Set of functions for fitting the map viewpoer to a specific constraint
Item {
    property var    map
    property bool   usePlannedHomePosition      ///< true: planned home position used for calculations, false: vehicle home position use for calculations
    property var    mapGeoFenceController
    property var    mapMissionController
    property var    mapRallyPointController

    property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

    function fitHomePosition() {
        var homePosition = QtPositioning.coordinate()
        var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle
        if (usePlannedHomePosition) {
            homePosition = mapMissionController.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) {
49
        var mapFitViewport = Qt.rect(0, 0, map.width, map.height)
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
        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))
82 83 84

        // Back off on zoom level
        map.zoomLevel = Math.abs(map.zoomLevel) - 1
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    }

    function addMissionItemCoordsForFit(coordList) {
        var homePosition = fitHomePosition()
        if (homePosition.isValid) {
            coordList.push(homePosition)
        }
        for (var i=1; i<mapMissionController.visualItems.count; i++) {
            var missionItem = mapMissionController.visualItems.get(i)
            if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
                coordList.push(missionItem.coordinate)
            }
        }
    }

    function fitMapViewportToMissionItems() {
101 102 103 104
        if (!mapMissionController.visualItems) {
            // Being called prior to controller.start
            return
        }
105 106 107 108 109 110 111 112 113 114 115 116 117 118
        var coordList = [ ]
        addMissionItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }

    function addFenceItemCoordsForFit(coordList) {
        var homePosition = fitHomePosition()
        if (homePosition.isValid && mapGeoFenceController.circleEnabled) {
            var azimuthList = [ 0, 180, 90, 270 ]
            for (var i=0; i<azimuthList.length; i++) {
                var edgeCoordinate = homePosition.atDistanceAndAzimuth(mapGeoFenceController.circleRadius, azimuthList[i])
                coordList.push(edgeCoordinate)
            }
        }
119 120 121
        if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.mapPolygon.path.count > 2) {
            for (var i=0; i<mapGeoFenceController.mapPolygon.path.count; i++) {
                coordList.push(mapGeoFenceController.mapPolygon.path[i])
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
            }
        }
    }

    function fitMapViewportToFenceItems() {
        var coordList = [ ]
        addFenceItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }

    function addRallyItemCoordsForFit(coordList) {
        for (var i=0; i<mapRallyPointController.points.count; i++) {
            coordList.push(mapRallyPointController.points.get(i).coordinate)
        }
    }

    function fitMapViewportToRallyItems() {
        var coordList = [ ]
        addRallyItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }

    function fitMapViewportToAllItems() {
145 146 147 148
        if (!mapMissionController.visualItems) {
            // Being called prior to controller.start
            return
        }
149 150 151 152 153 154 155
        var coordList = [ ]
        addMissionItemCoordsForFit(coordList)
        addFenceItemCoordsForFit(coordList)
        addRallyItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }
} // Item