I am using mapkit to display my map, I have also created an overlay. Now I am tracking the user using CLLocationManager and outputting that to the consol for testing. I hope someone knows or has a tutorial/example of how to place a dot or annotation where the users location is based on the lat lon results.. This is what I am doing at the moment..
- (void)viewDidLoad
{
// Initialize the TileOverlay with tiles in the application's bundle's resource directory.
// Any valid tiled image directory structure in there will do.
NSString *tileDirectory = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Tiles"];
TileOverlay *overlay = [[TileOverlay alloc] initWithTileDirectory:tileDirectory];
[map addOverlay:overlay];
// zoom in by a factor of two from the rect that contains the bounds
// because MapKit always backs up to get to an integral zoom level so
// we need to go in one so that we don't end up backed out beyond the
// range of the TileOverlay.
MKMapRect visibleRect = [map mapRectThatFits:overlay.boundingMapRect];
visibleRect.size.width /= 2;
visibleRect.size.height /= 2;
visibleRect.origin.x += visibleRect.size.width / 2;
visibleRect.origin.y += visibleRect.size.height / 2;
map.visibleMapRect = visibleRect;
// map.showsUserLocation = YES;
//location tracking
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[overlay release]; // map is now keeping track of overlay
}
//OverLays Topographical map
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
TileOverlayView *view = [[TileOverlayView alloc] initWithOverlay:overlay];
view.tileAlpha = 0.6;
return [view autorelease];
}
//Tracks Users location and Prints out the Lat and Lon
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocationCoordinate2D here = newLocation.coordinate;
NSLog(#"%f %f ", here.latitude, here.longitude);
}
//Call [locationManager stopUpdatingLocation] as some point
Related
I made a count-steps app, I count the steps with the iPhone accelerometer and now I want to display the path I made on a mapView. I can easily show the map and catch the right position with the iPhone GPS, I can display the start and the end point and I can to draw a polyline to show the path I made. Now my problem is how to set a correct zoom on the map? When I open the ViewController with map the zoom it's too far and I've to zoom to see the path I made.
So my question is how to set a correct zoom?
I post here the code of the View Controller with the mapView:
ResultViewController.m
#import "ResultViewController.h"
#import "MapAnnotation.h"
#interface ResultViewController ()
#property (nonatomic, strong)NSMutableArray *mapAnnotation;
#property (nonatomic) BOOL needUpdateRegion;
#end
#implementation ResultViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.labelResult.text = self.totalSteps;
[self.mapView setDelegate:self];
self.needUpdateRegion = YES;
self.mapAnnotation = [[NSMutableArray alloc]initWithCapacity:2];
CLLocation *startLocation = [self.locationArray objectAtIndex:0];
CLLocation *stopLocation = [self.locationArray lastObject];
NSString *startLatitude = [NSString stringWithFormat:#"%f", startLocation.coordinate.latitude];
NSString *startLongitude = [NSString stringWithFormat:#"%f", startLocation.coordinate.longitude];
NSString *stopLatitude = [NSString stringWithFormat:#"%f", stopLocation.coordinate.latitude];
NSString *stopLongitude = [NSString stringWithFormat:#"%f", stopLocation.coordinate.longitude];
MapAnnotation *startPlace = [[MapAnnotation alloc]initWithCoordinate:startLatitude andLong:startLongitude];
MapAnnotation *stopPlace = [[MapAnnotation alloc]initWithCoordinate:stopLatitude andLong:stopLongitude];
[self.mapAnnotation insertObject:startPlace atIndex:0];
[self.mapAnnotation insertObject:stopPlace atIndex:1];
if (self.mapAnnotation) {
[self.mapView removeAnnotations:self.mapView.annotations];
}
[self.mapView addAnnotation:self.mapAnnotation[0]];
[self.mapView addAnnotation:self.mapAnnotation[1]];
[self updateRegion];
[self createMKpolylineAnnotation];
}
- (void)updateRegion
{
self.needUpdateRegion = NO;
CGRect boundingRect;
BOOL started = NO;
for (id <MKAnnotation> annotation in self.mapView.annotations) {
CGRect annotationRect = CGRectMake(annotation.coordinate.latitude, annotation.coordinate.longitude, 0, 0);
if (!started) {
started = YES;
boundingRect = annotationRect;
} else {
boundingRect = CGRectUnion(boundingRect, annotationRect);
}
}
if (started) {
boundingRect = CGRectInset(boundingRect, -0.2, -0.2);
if ((boundingRect.size.width < 20) && (boundingRect.size.height < 20)) {
MKCoordinateRegion region;
region.center.latitude = boundingRect.origin.x + boundingRect.size.width / 2;
region.center.longitude = boundingRect.origin.y + boundingRect.size.height / 2;
region.span.latitudeDelta = boundingRect.size.width;
region.span.longitudeDelta = boundingRect.size.height;
[self.mapView setRegion:region animated:YES];
}
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor blueColor];
polylineView.lineWidth = 5.0;
return polylineView;
}
- (void)createMKpolylineAnnotation {
NSInteger numberOfSteps = self.locationArray.count;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numberOfSteps);
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [self.locationArray objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coords[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coords count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)restart:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
What's wrong with this code? There's someone that can help me to zoom the map correctly?
Thank you
In that case I would recommend you to call the following method in order to zoom to a region of the map, you could add the call at the end your method - (void)createMKpolylineAnnotation;
Call:
[self zoomToPolyLine: self.mapView polyLine:polyLine animated:YES];
Method:
-(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];
}
firstly add this line in view did load after you set the mapview delegate as
[self.mapView setDelegate:self];
self.needUpdateRegion = YES;
mapView.zoomEnabled = YES;
mapView.scrollEnabled = YES;
....
}
then modify the below line to set the zoom level as required by you 60000=60 km..
[mapView setRegion: MKCoordinateRegionMakeWithDistance(site.coordinate, 60000, 60000) animated:YES];
or you can try this method for setting scale of zoom as
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
CGImageRef imageReference = self.overlayImage.CGImage;
MKMapRect theMapRect = self.overlay.boundingMapRect;
CGRect theRect = [self rectForMapRect:theMapRect];
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -theRect.size.height);
CGContextDrawImage(context, theRect, imageReference);
}
hope this helps you..Cheers!!
I have been building an app which draw the lines of the current user moving along the map. Now, in iOS5 when I add the overlay to the mapview, it justs add it directly, in iOS6 it adds the overlay with "fade in" animation. I don't want this annoying animation. I also have a function which plays the trail upon the coordinates saved (after the user is done running or walking), when I play this, the lines flicker very fast, just because of this animation. This is really annoying and I really would appreciate any guidance or a solution to get rid of this animation.
Code for adding overlays:
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D)*2);
pointsArray[0]= MKMapPointForCoordinate(oldLocation.coordinate);
pointsArray[1]= MKMapPointForCoordinate(newLocation.coordinate);
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
free(pointsArray);
[self.mapView addOverlay:self.routeLine];
Code for displaying overlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay{
MKOverlayView *overlayView = nil;
MKPolylineView *routeLineView = [[MKPolylineView alloc] initWithPolyline:(MKPolyline *)overlay];
routeLineView.fillColor = [UIColor blueColor];
routeLineView.strokeColor = [UIColor blueColor];
routeLineView.backgroundColor = [UIColor clearColor];
routeLineView.lineWidth = 10;
routeLineView.lineCap = kCGLineCapRound;
overlayView = routeLineView;
return overlayView;
}
Thanks!
EDIT:
Code for going through the path:
playTimer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(playPathTimer)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:playTimer forMode:NSRunLoopCommonModes];
- (void)playPathTimer{
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D) * 2);
double latitude1 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter]).latitude.doubleValue;
double longitude1 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter]).longitude.doubleValue;
double latitude2 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter+nextCord]).latitude.doubleValue;
double longitude2 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter+nextCord]).longitude.doubleValue;
CLLocation *location1 = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude1, longitude1)
altitude:0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
CLLocation *location2 = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude2, longitude2)
altitude:0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
pointsArray[0] = MKMapPointForCoordinate(location1.coordinate);
pointsArray[1] = MKMapPointForCoordinate(location2.coordinate);
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
free(pointsArray);
[self.mapView addOverlay:self.routeLine];
[playRouteLines addObject:self.routeLine];
// self.mapView.centerCoordinate = CLLocationCoordinate2DMake(latitude1, longitude1);
playCounter = playCounter + nextCord;
if(playCounter + nextCord >= coordsArray.count){
// [displayLink setPaused:YES];
// [displayLink invalidate];
[playTimer invalidate];
playTimer = nil;
playCounter = 0;
[self showStartAndEndFlags];
if(ee.trail.checkpoint.count > 0){
[self showCheckpoints];
}
self.playButton.enabled = YES;
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:[self getRegionWithCorrectZooming]];
[self.mapView setRegion:adjustedRegion animated:YES];
}
}
Instead of using a MKPolylineView you can use your own subclass of MKOverlayView (superclass of MKPolylineView) and then override drawMapRect:zoomScale:inContext: where you draw the lines yourself.
I guess with this you won't have any fade in animation (I'm using it and never noticed any animation).
Try the following code for your drawMapRect:zoomScale:inContext: implementation.
You need to create the properties lineColor(CGColor) and lineWidth (CGFloat).
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
MKPolyline *polyline = self.overlay;
CGContextSetStrokeColorWithColor(context, self.lineColor);
CGContextSetLineWidth(context, self.lineWidth/zoomScale);
CGMutablePathRef path = CGPathCreateMutable();
CGPoint *points = malloc(sizeof(CGPoint)*polyline.pointCount);
for (int i=0; i<polyline.pointCount; i++) {
points[i] = [self pointForMapPoint:polyline.points[i]];
}
CGPathAddLines(path, NULL, points, polyline.pointCount);
CGContextAddPath(context, path);
CGContextDrawPath(context, kCGPathStroke);
CGPathRelease(path);
free(points);
}
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.
I am just wondering how to center the map view as the user is vein tracked with CLLocationmanager and map kit
This is currently how I am tracking the user and updating the location etc.
- (void)viewDidLoad
{
// Initialize the TileOverlay with tiles in the application's bundle's resource directory.
// Any valid tiled image directory structure in there will do.
NSString *tileDirectory = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Tiles"];
TileOverlay *overlay = [[TileOverlay alloc] initWithTileDirectory:tileDirectory];
[map addOverlay:overlay];
// zoom in by a factor of two from the rect that contains the bounds
// because MapKit always backs up to get to an integral zoom level so
// we need to go in one so that we don't end up backed out beyond the
// range of the TileOverlay.
MKMapRect visibleRect = [map mapRectThatFits:overlay.boundingMapRect];
visibleRect.size.width /= 2;
visibleRect.size.height /= 2;
visibleRect.origin.x += visibleRect.size.width / 2;
visibleRect.origin.y += visibleRect.size.height / 2;
map.visibleMapRect = visibleRect;
// map.showsUserLocation = YES;
//location tracking
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
//Show the users location.. hopefully it works with tracking.
map.showsUserLocation = YES;
[overlay release]; // map is now keeping track of overlay
}
//OverLays Topographical map
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
TileOverlayView *view = [[TileOverlayView alloc] initWithOverlay:overlay];
view.tileAlpha = 0.6;
return [view autorelease];
}
//Tracks Users location and Prints out the Lat and Lon
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocationCoordinate2D here = newLocation.coordinate;
NSLog(#"%f %f ", here.latitude, here.longitude);
}
The below method focus a particular location in the map,
//Don't forget to add this method to your header also
-(void)focusLocationInMap:(CLLocationCoordinate2D)location
{
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.01;
span.longitudeDelta=0.01;
region.span=span;
region.center=location;
[self.yourMapView setRegion:region animated:TRUE];
[self.yourMapView regionThatFits:region];
}
You could use it anywhere by passing coordinates to it,
CLLocationCoordinate2D here = newLocation.coordinate;
[self focusLocationInMap:here];
here.coordinate is not correct, should be just 'here'
I"m using MapKit in my application and disaply the user location with
[mapview setShowUserLocation:YES];
I want to set the region.center.latitude and region.center.longitude with the coordinate of the userLocation, how to do it?
Here is my answer, I try something like that and its working:
//inside my ViewDidLOad
locManager = [[CLLocationManager alloc] init];
[locManager setDelegate:self];
[locManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locManager startUpdatingLocation];
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D loc = [newLocation coordinate];
[maptView setCenterCoordiante:loc];
}
Much easier:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 1500, 1500);
[mapView setRegion:region animated:YES];
}
For some reason, this didn't work for me. It's taking me to the coordinates (0.0000, 0.0000). Below is my code if you have a chance to check it out. Thanks for the help!
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
mapView.showsUserLocation=TRUE;
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
CLLocationCoordinate2D myCoord = {mapView.userLocation.location.coordinate.latitude,mapView.userLocation.location.coordinate.longitude};
[mapView setCenterCoordinate:myCoord animated:YES];
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
I think this answers your question :
Returning Mapkit Userlocation Coordinates
(uses the mapView.userLocation.location.coordinate.latitude and mapView.userLocation.location.coordinate.longitude properties )
and then inject those coordinates into the
-(void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated
of your MKMapView instance.
Using delegate:
Add Mapkit delegate: MKMapViewDelegate
Achieve method:MapView didUpdateUserLocation
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate,
500, 500);
[mapView setRegion:region animated:YES];
}
Without delegate:
[self.mapView setuserTrackingMode:MKUserTrackingModeFollow];