How to set map rect with user location at the centre? - iphone

I have a mapView with one pin and the users location. I have made it so the VisibleMapRect is set so both pins can be seen.
The problem Im having is that I am using MKUserTrackingModeFollowWithHeading to show the users move movements and when I set the rect like this the movement is very jerky. I believe this is because the user location pin is not in the centre of the map.
How can I get both pins to be visible but keep the user location in the centre?
This is my code that starts the location and sets the rect.
[locationManager startUpdatingLocation];
// Start heading updates.
if ([CLLocationManager headingAvailable]) {
locationManager.headingFilter = kCLHeadingFilterNone;
[locationManager startUpdatingHeading];
//set the view to fit both the pins
MKMapPoint annotationPoint = MKMapPointForCoordinate(MapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
for (id <MKAnnotation> annotation in MapView.annotations)
{
if (![annotation isKindOfClass:[MKUserLocation class]] ) {
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
}
NSLog(#"%f",zoomRect.size.height);
NSLog(#"%f",zoomRect.size.width);
[MapView setVisibleMapRect:zoomRect animated:NO];
}
I have tried commenting out the part that sets the rect and the movement of the user is smooth so I can tell my problem is this code.
I have also tried setting the centre point after the rect using
[MapView setCenterCoordinate:MapView.userLocation.coordinate animated:YES];
This did not seem to work. Also setting this after may make it so the other pin is not shown anymore.

I use this method:
- (void)setRegionFromCoordinates:(NSArray *)waypoints animated:(BOOL)animated {
if (waypoints != nil) {
CLLocationDegrees maxX = -DBL_MAX;
CLLocationDegrees maxY = -DBL_MAX;
CLLocationDegrees minX = DBL_MAX;
CLLocationDegrees minY = DBL_MAX;
for (NSUInteger i=0; i < waypoints.count; i++) {
CLLocationCoordinate2D currentLocation = [waypoints objectAtIndex:i];
MKMapPoint mapPoint = MKMapPointForCoordinate(currentLocation);
if (mapPoint.x > maxX) {
maxX = mapPoint.x;
}
if (mapPoint.x < minX) {
minX = mapPoint.x;
}
if (mapPoint.y > maxY) {
maxY = mapPoint.y;
}
if (mapPoint.y < minY) {
minY = mapPoint.y;
}
}
if (maxX != -DBL_MAX && minX != DBL_MAX) {
MKMapRect mapRect = MKMapRectMake(minX,minY,maxX-minX,maxY-minY);
[map setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(50.f, 50.f, 50.f, 50.f) animated:animated];
}
}
}

For Display All the Annotation with Your Current location use following method
- (void)zoomToFitMapAnnotations:(MKMapView *)mapView {
if ([mapView.annotations count] == 0) return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(id<MKAnnotation> annotation in mapView.annotations) {
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
// Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}

Related

How to reduce the zoom level of MKMapview with annotation?

I'm having only one annotation in the mapview.
I'm using the following code to zoom to that annotation pin
- (void)zoomToFitMapAnnotations:(MKMapView *)mapView {
if ([mapView.annotations count] == 0) return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(id<MKAnnotation> annotation in mapView.annotations) {
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 0.1;
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 0.1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}
But it zooms to the extreme, I need to reduce the zoom level so the user can see some area around the annotation.
I tried changing the values of region.span, but can't get the solution.
Any suggestions would be appreciated.
Are you sure that this code :
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 0.1;
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 0.1;
doesn't return latitude/longitude = 0 ?
Try to hardcode the span to 0.05 or something close.
The code below will center your map to your current position , you can change locationManager.coordinates with your annotation.coordinates.
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
MKCoordinateSpan span;
MKCoordinateRegion region;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
location.latitude = locationManager.location.coordinate.latitude;
location.longitude = locationManager.location.coordinate.longitude;
NSLog(#"%f",location.latitude);
region.span = span;
region.center = location;
[_mapVIew setRegion:region animated:YES];
use this code to adjust your mapView zoom level
MKCoordinateRegion mapRegion;
// set the center of the map region to the now updated map view center
mapRegion.center = self.mapView.centerCoordinate;
mapRegion.span.latitudeDelta = 0.1;
mapRegion.span.longitudeDelta = 0.1;
mapView.region=mapRegion;
I used the below code for zooming to the annotation,
CLLocation *location = [[CLLocation alloc] initWithLatitude:[#"My annotation's latitude" doubleValue] longitude:[#"My annotation's longitude" doubleValue]];
MKCoordinateRegion mkr;
mkr.center = location.coordinate;
MKCoordinateSpan span;
span.latitudeDelta = 0.0144927536;
span.longitudeDelta = 0.0144927536;
mkr.span = span;
[mapView setRegion:mkr animated:YES];
Currently, it zooms to one mile around the lat long. If I want to zoom more or less, I'll change the latlong delta value.
ie, for 2 miles = 0.0144927536*2 and for 0.5 mile = 0.0144927536/2. I hope, it will be useful for others.

MapKit Polyline custom zoom?

I am trying to learn how to use a polyline to connect two points on a map in ios6. First off, I have read over every tutorial on this subject that a simple Google search turns up and can not get polylines to work for one reason. Every tutorial that I have seen always adds the polyline to the map and adjusts the zoom of the map to fit the whole line. How would I go about making and adding a polyline to a map in ios6 if I want the map to stay zoomed in at a constant distance and only show the end of the polyline if it is larger then the current view?
For example say I had a polyline that was a mile long and wanted the map to stay zoomed in at a constand distacne equivelent to:
MKCoordinateRegion userRegion = MKCoordinateRegionMakeWithDistance(self.currentLocation.coordinate, 1000, 1000);
[self.mainMap setRegion:[self.mainMap regionThatFits:userRegion] animated:YES];
How would I go about doing this? Please provide full code examples or a sample project that I could download!
MKMapPoint * malloc / assign:
MKMapPoint *newPoints = malloc((sizeof (MKMapPoint) * nbPoints));
newPoints[index] = varMKMapPoint;
free(newPoints);
MKPolyline must be initialize in your needed :
MKPolyline *polyline = [MKPolyline polylineWithPoints:newPoints count:nbPoints];
[self.mapView addOverlay:polyline];
to display your MKPolyline, you have to use viewForOverlay :
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = [[MKOverlayView alloc] initWithOverlay:overlay];
if([overlay isKindOfClass:[MKPolyline class]]) {
MKPolylineView *backgroundView = [[MKPolylineView alloc] initWithPolyline:overlay];
backgroundView.fillColor = [UIColor blackColor];
backgroundView.strokeColor = backgroundView.fillColor;
backgroundView.lineWidth = 10;
backgroundView.lineCap = kCGLineCapSquare;
overlayView = backgroundView;
}
return overlayView;
}
To use this method, you have to convert your points to CLLocation, it will returns a MKCoordinateRegion that you will set to mapView :
- (MKCoordinateRegion)getCenterRegionFromPoints:(NSArray *)points
{
CLLocationCoordinate2D topLeftCoordinate;
topLeftCoordinate.latitude = -90;
topLeftCoordinate.longitude = 180;
CLLocationCoordinate2D bottomRightCoordinate;
bottomRightCoordinate.latitude = 90;
bottomRightCoordinate.longitude = -180;
for (CLLocation *location in points) {
topLeftCoordinate.longitude = fmin(topLeftCoordinate.longitude, location.coordinate.longitude);
topLeftCoordinate.latitude = fmax(topLeftCoordinate.latitude, location.coordinate.latitude);
bottomRightCoordinate.longitude = fmax(bottomRightCoordinate.longitude, location.coordinate.longitude);
bottomRightCoordinate.latitude = fmin(bottomRightCoordinate.latitude, location.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoordinate.latitude - (topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 0.5;
region.center.longitude = topLeftCoordinate.longitude + (bottomRightCoordinate.longitude - topLeftCoordinate.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoordinate.latitude - bottomRightCoordinate.latitude) * 1.2; //2
region.span.longitudeDelta = fabs(bottomRightCoordinate.longitude - topLeftCoordinate.longitude) * 1.2; //2
// NSLog(#"zoom lvl : %f, %f", region.span.latitudeDelta, region.span.latitudeDelta);
return region;
}
Hope this helps.

Zoom Out the Location in MapView

Im Having MapView In which I added some 5 Annotations in the Areas of Chennai.. I want to Zoom Out the Chennai as soon as the MapView Begins Loading so that Annotations will be Visible Clearly.
In viewDidLoad:
CLLocationCoordinate2D location6;
location6.latitude=12.9758;
location6.longitude=80.2205;
MapAnnotation *ann6=[[MapAnnotation alloc]initWithTitle:#"Chennai-Velacherry" andCoordinate:location6];
[mapView addAnnotation:ann6];
CLLocationCoordinate2D centerlocation;
centerlocation.longitude=13.0810;
centerlocation.longitude=80.2740;
[mapView setCenterCoordinate:centerlocation animated:NO];
[self.view addSubview:mapView];
use this,
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = [currentPlace.latitude doubleValue];
region.center.longitude = [currentPlace.longitude doubleValue];
region.span.longitudeDelta = 0.03f;
region.span.latitudeDelta = 0.03f;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
mapView.zoomEnabled = YES;
mapView.scrollEnabled = NO;
these will vary your zoom level,
region.span.longitudeDelta = 0.03f;
region.span.latitudeDelta = 0.03f;
You cannot have a predefined set of zoom levels. Instead, you can set the visible area of a MKMapView using MKCoordinateRegion. Sample code available here.
You can do that like this:
Create a function like :
-(void)zoomToFitMapAnnotations:(MKMapView*)mv {
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(MKAnnotations* annotation in mv.annotations)
{
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
region = [mv regionThatFits:region];
[mv setRegion:region animated:YES];
}
And call this function in viewDidLoad after all the pins are plotted
Try this
#define kMAPSPAN 1600
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 1*kMAPSPAN, 1*kMAPSPAN);
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
[_mapView setRegion:adjustedRegion animated:YES];
mapView is your MKMapView object and kMAPSPAN can be set according to your need and zoomLocation is your coordinate2D location for chennai

Map Bounding Box with Annotations

I have an algorithm that calculates the size and location of a bounding box for a map that contains a set of given coordinates. While it works perfectly, the bounds that it produces don't always accommodate the push pin that I place at coordinates that often lie right on the edge of the bounding box:
...and again, it produces an acceptable result most of the time:
I've mulled it over for awhile, but I haven't been able to think of a way to modify my algorithm to ensure that the push pins are always within the bounding box. My algorithm is listed below, and any suggestions would be greatly appreciated. :)
MKMapPoint *points = malloc([coordinates count] * sizeof(MKMapPoint));
MKMapPoint upperRightCorner;
MKMapPoint lowerLeftCorner;
for(int i = 0; i < [coordinates count]; i++)
{
CLLocation *location = [coordinates objectAtIndex:i];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(herp.coordinate.latitude, herp.coordinate.longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
points[i] = point;
if (i == 0) {
upperRightCorner = point;
lowerLeftCorner = point;
}
else {
if (point.x > upperRightCorner.x) upperRightCorner.x = point.x;
if (point.y > upperRightCorner.y) upperRightCorner.y = point.y;
if (point.x < lowerLeftCorner.x) lowerLeftCorner.x = point.x;
if (point.y < lowerLeftCorner.y) lowerLeftCorner.y = point.y;
}
}
MKMapRect boundingBox = MKMapRectMake(lowerLeftCorner.x, lowerLeftCorner.y,
upperRightCorner.x - lowerLeftCorner.x,
upperRightCorner.y - lowerLeftCorner.y);
I think it might be late, but here's a solution it works for me, quite similar to yours, I ended up adding a padding at the end.
- (MKCoordinateRegion)boundingBoxForAnnotations:(NSArray *)annotations {
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for (id<MKAnnotation> annotation in annotations) {
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;
return region;
}

Zoom to fit region for all annotations - ending up zooming in between annotations

I have a problem with fitting all my annotations to the screen... sometimes it shows all annotations, but some other times the app is zooming in between the two annotations so that none of them are visible...
I want the app to always fit the region to the annotations and not to zoom in between them... what do I do wrong?
if ([mapView.annotations count] == 2) {
CLLocationCoordinate2D SouthWest = location;
CLLocationCoordinate2D NorthEast = savedPosition;
NorthEast.latitude = MAX(NorthEast.latitude, savedPosition.latitude);
NorthEast.longitude = MAX(NorthEast.longitude, savedPosition.longitude);
SouthWest.latitude = MIN(SouthWest.latitude, location.latitude);
SouthWest.longitude = MIN(SouthWest.longitude, location.longitude);
CLLocation *locSouthWest = [[CLLocation alloc] initWithLatitude:SouthWest.latitude longitude:SouthWest.longitude];
CLLocation *locNorthEast = [[CLLocation alloc] initWithLatitude:NorthEast.latitude longitude:NorthEast.longitude];
CLLocationDistance meter = [locSouthWest distanceFromLocation:locNorthEast];
MKCoordinateRegion region;
region.span.latitudeDelta = meter / 111319.5;
region.span.longitudeDelta = 0.0;
region.center.latitude = (SouthWest.latitude + NorthEast.latitude) / 2.0;
region.center.longitude = (SouthWest.longitude + NorthEast.longitude) / 2.0;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
[locSouthWest release];
[locNorthEast release];
}
Any ideas?
Thanks!!
Use the following code
-(void)zoomToFitMapAnnotations:(MKMapView*)mapView{
if([mapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(FSMapAnnotation* annotation in mapView.annotations)
{
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}
Instead of:
region.span.latitudeDelta = meter / 111319.5;
region.span.longitudeDelta = 0.0;
region.center.latitude = (SouthWest.latitude + NorthEast.latitude) / 2.0;
region.center.longitude = (SouthWest.longitude + NorthEast.longitude) / 2.0;
Try adding:
region.span.latitudeDelta = fabs(NorthEast.latitude - SouthWest.latitude) * 1.2;
region.span.longitudeDelta = fabs(SouthWest.longitude - NorthEast.longitude) * 1.2;
region.center.latitude = NorthEast.latitude - (NorthEast.latitude - SouthWest.latitude) * 0.5;
region.center.longitude = NorthEast.longitude + (SouthWest.longitude - NorthEast.longitude) * 0.5;
And removing:
CLLocationDistance meter = [locSouthWest distanceFromLocation:locNorthEast];