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.
… or you could just do this instead
mapView?.setVisibleCoordinates(
coordinates,
count: UInt(coordinates.count),
edgePadding: UIEdgeInsetsMake(20, 20, 20, 20),
animated: true
)
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)
}
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With