MapFitFunctions.qml 7.22 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
import QGroundControl           1.0
import QGroundControl.FlightMap 1.0
15 16 17 18 19

/// 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
20 21 22 23 24
    property var    planMasterController

    property var    _missionController:     planMasterController.missionController
    property var    _geoFenceController:    planMasterController.geoFenceController
    property var    _rallyPointController:  planMasterController.rallyPointController
25 26 27 28 29 30 31

    property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

    function fitHomePosition() {
        var homePosition = QtPositioning.coordinate()
        var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle
        if (usePlannedHomePosition) {
32
            homePosition = _missionController.visualItems.get(0).coordinate
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
        } 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) {
52
        var mapFitViewport = Qt.rect(0, 0, map.width, map.height)
53
        if (coordList.length === 0) {
Don Gagne's avatar
Don Gagne committed
54 55 56 57
            var homeCoord = fitHomePosition()
            if (homeCoord.isValid) {
                map.center = homeCoord
            }
58 59 60 61 62 63 64 65
            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
66
        for (var i = 1; i < coordList.length; i++) {
67 68 69 70
            var lat = normalizeLat(coordList[i].latitude)
            var lon = normalizeLon(coordList[i].longitude)
            north = Math.max(north, lat)
            south = Math.min(south, lat)
71 72
            east  = Math.max(east,  lon)
            west  = Math.min(west,  lon)
73 74 75 76
        }

        // Expand the coordinate bounding rect to make room for the tools around the edge of the map
        var latDegreesPerPixel = (north - south) / mapFitViewport.width
77
        var lonDegreesPerPixel = (east  - west)  / mapFitViewport.height
78 79
        north = Math.min(north + (mapFitViewport.y * latDegreesPerPixel), 180)
        south = Math.max(south - ((map.height - mapFitViewport.bottom) * latDegreesPerPixel), 0)
80 81 82 83
        west  = Math.max(west  - (mapFitViewport.x * lonDegreesPerPixel), 0)
        east  = Math.min(east  + ((map.width - mapFitViewport.right) * lonDegreesPerPixel), 360)

        // Back off on zoom level
84 85 86 87 88 89 90 91
//        var alpha1 = 1.0000075 // original value
//        var alpha2= 0.9999925 // original value
        var alpha1 = 1
        var alpha2 = 1
        east  = Math.min(east  * alpha1, 360)
        north = Math.min(north * alpha1, 180)
        west  = west  * alpha2
        south = south * alpha2
92

Gus Grubba's avatar
Gus Grubba committed
93
        // Fit the map region to the new bounding rect
94
        var topLeftCoord      = QtPositioning.coordinate(north - 90.0, west - 180.0)
95 96
        var bottomRightCoord  = QtPositioning.coordinate(south - 90.0, east - 180.0)
        map.setVisibleRegion(QtPositioning.rectangle(topLeftCoord, bottomRightCoord))
97

98 99 100
    }

    function addMissionItemCoordsForFit(coordList) {
101
        for (var i = 1; i < _missionController.visualItems.count; i++) {
102
            var missionItem = _missionController.visualItems.get(i)
103
            if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
104 105 106 107 108 109
                if(missionItem.boundingCube.isValid()) {
                    coordList.push(missionItem.boundingCube.pointNW)
                    coordList.push(missionItem.boundingCube.pointSE)
                } else {
                    coordList.push(missionItem.coordinate)
                }
110 111 112 113 114
            }
        }
    }

    function fitMapViewportToMissionItems() {
115
        if (!_missionController.visualItems) {
116 117 118
            // Being called prior to controller.start
            return
        }
119 120 121 122 123 124 125 126 127 128 129 130 131
        /*
        for (var i=1; i<_missionController.visualItems.count; i++) {
            var missionItem = _missionController.visualItems.get(i)
            if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
                console.log(missionItem.boundingCube.pointNW)
                console.log(missionItem.boundingCube.pointSE)
                var loc = QtPositioning.rectangle(missionItem.boundingCube.pointNW, missionItem.boundingCube.pointSE)
                console.log(loc)
                map.visibleRegion = loc
                return
            }
        }
        */
132 133 134 135 136 137
        var coordList = [ ]
        addMissionItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }

    function addFenceItemCoordsForFit(coordList) {
138
        var i
139
        var homePosition = fitHomePosition()
140
        if (homePosition.isValid && _geoFenceController.circleEnabled) {
141
            var azimuthList = [ 0, 180, 90, 270 ]
142
            for (i = 0; i < azimuthList.length; i++) {
143
                var edgeCoordinate = homePosition.atDistanceAndAzimuth(_geoFenceController.circleRadius, azimuthList[i])
144 145 146
                coordList.push(edgeCoordinate)
            }
        }
147
        if (_geoFenceController.polygonEnabled && _geoFenceController.mapPolygon.path.count > 2) {
148
            for (i = 0; i < _geoFenceController.mapPolygon.path.count; i++) {
149
                coordList.push(_geoFenceController.mapPolygon.path[i])
150 151 152 153 154 155 156 157 158 159 160
            }
        }
    }

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

    function addRallyItemCoordsForFit(coordList) {
161 162
        for (var i=0; i<_rallyPointController.points.count; i++) {
            coordList.push(_rallyPointController.points.get(i).coordinate)
163 164 165 166 167 168 169 170 171 172
        }
    }

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

    function fitMapViewportToAllItems() {
173
        if (!_missionController.visualItems) {
174 175 176
            // Being called prior to controller.start
            return
        }
177 178 179 180 181 182 183
        var coordList = [ ]
        addMissionItemCoordsForFit(coordList)
        addFenceItemCoordsForFit(coordList)
        addRallyItemCoordsForFit(coordList)
        fitMapViewportToAllCoordinates(coordList)
    }
} // Item