Zoom MKMapView to fit polyline points
Asked Answered
K

8

35

I have an array, allCollections, that holds programmatically-created arrays of CLLocations the user has recorded through my iOS app. Each sub-array in allCollections holds all the location points in a trip taken.

I draw MKPolylines off of the CLLocations in the arrays in allCollections to represent those trips on an MKMapView. My question is this: With the polylines added to the map, how would I go about programmatically zooming and centering the map to display all of them?

Ko answered 26/11, 2012 at 16:47 Comment(0)
T
71
-(void)zoomToPolyLine: (MKMapView*)map polyline: (MKPolyline*)polyline animated: (BOOL)animated
{
    [map setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0) animated:animated];
}
Tate answered 27/9, 2013 at 3:18 Comment(4)
@BradKoch This solution uses boundingMapRect to define a rectangle that encompasses the polyline overlay. It then sets the map zoom area to that rectangle with setVisibleMapRect taking into account the adjustable padding values with edgePadding. I found this solution to be the most helpful, since it solves the problem efficiently with few lines of code and also allows for changes to the map view area through insets.Granthem
This works for me. But apparently this sets the zoom factor to fill the screen, instead of fit. Can you think of a solution for thatDiscussant
Plus one for a solution with insets.Lido
Good solution +1. Only thing is that Padding needs to be adjusted as per visual needs, that way it will support all the other overlays.Astir
M
15
-(void)zoomToPolyLine: (MKMapView*)map polyLine: (MKPolyline*)polyLine 
animated (BOOL)animated
{
MKPolygon* polygon = 
    [MKPolygon polygonWithPoints:polyLine.points count:polyLine.pointCount];

[map setRegion:MKCoordinateRegionForMapRect([polygon boundingMapRect]) 
     animated:animated];
}
Marybelle answered 4/2, 2013 at 21:51 Comment(2)
It is not required to create a MKPolygon as MKPolyline already implement boundingMapRectEndodontist
how are you assigning fence to CLLocation ?? means in goefencing how to you allocate that CLregion instead of circular region???Condemn
B
15

in swift:

if let first = mapView.overlays.first {
    let rect = mapView.overlays.reduce(first.boundingMapRect, combine: {MKMapRectUnion($0, $1.boundingMapRect)})
    mapView.setVisibleMapRect(rect, edgePadding: UIEdgeInsets(top: 50.0, left: 50.0, bottom: 50.0, right: 50.0), animated: true)
}

this will zoom/pan to fit all overlays with a little buffer

Bjorn answered 7/12, 2015 at 18:17 Comment(0)
M
10

You could loop through all CLLocations recording the max/min coordinates and use that to set a view rect like they do on this question iOS MKMapView zoom to show all markers .

Or you could go through each of your overlays and get their boundingMapRect then use MKMapRectUnion (http://developer.apple.com/library/ios/documentation/MapKit/Reference/MapKitFunctionsReference/Reference/reference.html#//apple_ref/c/func/MKMapRectUnion) to combine them all until you have one MKMapRect that covers them all and use that to set the view.

[mapView setVisibleMapRect:zoomRect animated:YES]

This question shows a simple loop combining the maprects in unions as I suggested: MKMapRect zooms too much

Monied answered 26/11, 2012 at 20:45 Comment(2)
I owe you a beer for that :)Guaiacum
MKMapRectUnion link is broken, here's the new page developer.apple.com/documentation/mapkit/1452123-mkmaprectunionSandry
B
9

Swift 3 version of garafajon excellent code

    if let first = self.mapView.overlays.first {
        let rect = self.mapView.overlays.reduce(first.boundingMapRect, {MKMapRectUnion($0, $1.boundingMapRect)})
        self.mapView.setVisibleMapRect(rect, edgePadding: UIEdgeInsets(top: 50.0, left: 50.0, bottom: 50.0, right: 50.0), animated: true)
    }
Babushka answered 17/3, 2017 at 10:45 Comment(1)
Swift 5 version: the second line of code from above changes a bit: let rect = self.mapView.overlays.reduce(first.boundingMapRect, {$0.union($1.boundingMapRect)}) }Ambiguous
M
9

Swift 4 / slightly modified version of fundtimer's answer.

 func setVisibleMapArea(polyline: MKPolyline, edgeInsets: UIEdgeInsets, animated: Bool = false) {
    mapView.setVisibleMapRect(polyline.boundingMapRect, edgePadding: edgeInsets, animated: animated)
}

Calling the above using a route's polyline and leaving the default of not animated, and adding small edge insets of 10 all around:

setVisibleMapArea(polyline: route.polyline, edgeInsets: UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0))
Mariannamarianne answered 15/11, 2017 at 7:55 Comment(1)
A simple solution - nice!Complexioned
B
1

I have another solution for this problem

private func mapRegion() -> MKCoordinateRegion? {


    let latitudes = self.coordinates.map { location -> Double in

        return location.latitude
    }

    let longitudes = self.coordinates.map { location -> Double in

        return location.longitude
    }

    let maxLat = latitudes.max()!
    let minLat = latitudes.min()!
    let maxLong = longitudes.max()!
    let minLong = longitudes.min()!

    let center = CLLocationCoordinate2D(latitude: (minLat + maxLat) / 2,
                                        longitude: (minLong + maxLong) / 2)
    let span = MKCoordinateSpan(latitudeDelta: (maxLat - minLat) * 1.3,
                                longitudeDelta: (maxLong - minLong) * 1.3)
    return MKCoordinateRegion(center: center, span: span)
}

Where coordinates is Array of CLLocationCoordinate2D

Hope it is helpful to someone

Boyce answered 1/2, 2019 at 4:56 Comment(0)
A
0

@Fundtimer pointed it right way, Only thing is that Padding needs to be adjusted as per visual needs, that way it will support all the other overlays and following is the generic solution for all overlays.

-(void)zoomIntoExistingMapObjectForAnnot:(CustomMapAnnotation *)annot
{
   id overlay = annot.shape;//I have overlay property in custom annotation class.
   [_mapView setVisibleMapRect:[overlay boundingMapRect] edgePadding:UIEdgeInsetsMake(150.0, 150.0, 150.0, 150.0) animated:YES];
}
Astir answered 25/7, 2017 at 6:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.