Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How fit all coordinates into the bounds of the map? fitBounds equivalent?

Tags:

ios

swift

mapbox

I'm making a running app using the Mapbox API and I'm struggling on how set the bounds of MGLMapView to fit all of the polylines the user created by running. Mapbox has a version of this in JavaScript here: https://www.mapbox.com/mapbox-gl-js/example/zoomto-linestring/

But I have no idea how to implement this using swift. I can't find a fitBounds equivalent.

I'm storing each CLLocationCoordinate2D into a Array called pointsArray and passing that to the result view controller along with the mapView.

I had method of finding the longest distance between two points in the array and set that as the bounds but since the algorithm is O(n^2) it takes way too long to calculate if I have too many points. There were also other cases where that wouldn't fit all points.

If there's any particular code you want to see let me know. Not sure what to show since I have nothing to fit the bounds.

like image 545
Daniel Espina Avatar asked Oct 29 '17 18:10

Daniel Espina


3 Answers

… or you could just do this instead

    mapView?.setVisibleCoordinates(

        coordinates,
        count: UInt(coordinates.count),
        edgePadding: UIEdgeInsetsMake(20, 20, 20, 20),
        animated: true
    )
like image 64
IT Gypsy Avatar answered Nov 15 '22 07:11

IT Gypsy


This is my solution :

 
mapView.setVisibleCoordinateBounds(generateCoordinatesBounds(forCoordinates: [myCLLocationCoordinate2D]), animated: true)

func generateCoordinatesBounds(forCoordinates coordinates: [CLLocationCoordinate2D]) -> MGLCoordinateBounds {

var maxN = CLLocationDegrees(), maxS = CLLocationDegrees() , maxE = CLLocationDegrees() , maxW = CLLocationDegrees() for coordinates in coordinates { if coordinates.latitude >= maxN || maxN == 0 { maxN = coordinates.latitude } if coordinates.latitude <= maxS || maxS == 0 { maxS = coordinates.latitude } if coordinates.longitude >= maxE || maxE == 0 { maxE = coordinates.longitude } if coordinates.longitude <= maxW || maxW == 0{ maxW = coordinates.longitude } } let offset = 0.001 let maxNE = CLLocationCoordinate2D(latitude: maxN + offset, longitude: maxE + offset) let maxSW = CLLocationCoordinate2D(latitude: maxS - offset, longitude: maxW - offset) return MGLCoordinateBounds(sw: maxSW, ne: maxNE) }


like image 24
R. Cozma Avatar answered Nov 15 '22 08:11

R. Cozma


You can do something like this O(n) linear algorithm:

var flyTo = MKMapRectNull

for coordinate in coordinateArray {
    // convert CLCoordinate to MKMapPoint
    MKMapPoint point = MKMapPointForCoordinate (coordinate1);

    let pointRect = MKMapRectMake(point.x, point.y, 0, 0)
    if MKMapRectIsNull(flyTo) {
        flyTo = pointRect
    } else {
        flyTo = MKMapRectUnion(flyTo, pointRect)
    }    
}

let coordNE = getCoordinateFromMapRectanglePoint(x: flyTo.origin.x, y: MKMapRectGetMaxY(flyTo))
let coordSW = getCoordinateFromMapRectanglePoint(x: MKMapRectGetMaxX(flyTo), y: flyTo.origin.y)
let coordinateBound = MGLCoordinateBoundsMake(coordSW, coordNE)

var edgeInsets = UIEdgeInsetsMake(20, 20, 20, 20)

mapView.setVisibleCoordinateBounds(coordinateBound, edgePadding: edgeInsets, animated: true)

----

class func getCoordinateFromMapRectanglePoint(x: Double, y: Double) -> CLLocationCoordinate2D {
    let swMapPoint = MKMapPointMake(x, y)
    return MKCoordinateForMapPoint(swMapPoint)
}
like image 36
Gonzalo Durañona Avatar answered Nov 15 '22 07:11

Gonzalo Durañona