I am doing one application.In that i am using the CLLOcationmanager like below.
[self performSelectorOnMainThread:#selector(findlocation:) withObject:nil waitUntilDone:NO];
-(void)findlocation:(id)sender
{
//NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
locationManager=[[CLLocationManager alloc]init];
locationManager.delegate=self;
locationManager.distanceFilter=0.3f;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog#"%#",newlocation.timestamp];
}
I want to update the location for every 0.3 meters.But this delegate method is not fired for that distance. And after [self performSelectorOnMainThread:#selector(findlocation:) withObject:nil waitUntilDone:NO]; my remaining process is working.
I think this may help you. You need to adjust distance using longitude and latitude
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
MKCoordinateRegion region = { { 0.0f, 0.0f }, { 0.0f, 0.0f } };
region.center = newLocation.coordinate;
region.span.longitudeDelta = 0.15f;
region.span.latitudeDelta = 0.15f;
[self.mapView setRegion:region animated:YES];
}
Above code uses 0.15 degrees (0.15*111 Km).
OR try to use you distanceFilter".Using distanceFilter allows you to filter out that kind of extraneous motion.
Related
I want to get the user's current location from my iPhone app. I have tried Google search also, but can't get the exact answer. I am trying to develop the code.The location will not display properly.i can findout nearest location.But i canot find out exact location.Please give me any idea,how to display exact location.Thanks in advance.
MapviewAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([CLLocationManager locationServicesEnabled])
{
self.locationManager.delegate=self;
self.locationManager.distanceFilter=1;
[self.locationManager startUpdatingLocation];
}
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
double miles=12.0;
double scalingFactor= ABS( cos(2 * M_PI * newLocation.coordinate.latitude /360.0) );
MKCoordinateSpan span;
span.latitudeDelta=miles/69.0;
span.longitudeDelta=miles/(scalingFactor*69.0);
MKCoordinateRegion region;
region.span=span;
region.center=newLocation.coordinate;
[self.viewController.mapView setRegion:region animated:YES];
self.viewController.mapView.showsUserLocation=YES;
}
mapviewcontroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.showsUserLocation = YES;
MKCoordinateRegion region;
region.center = self.mapView.userLocation.coordinate;
MKCoordinateSpan span;
span.latitudeDelta = 20;
span.longitudeDelta = 20;
region.span = span;
[self.mapView setRegion:region animated:YES];
}
// create a region that fill fit all the locations in it
+ (MKCoordinateRegion) getRegionThatFitsLocations:(NSArray *)locations {
// initialize to minimums, maximums
CLLocationDegrees minLatitude = 90;
CLLocationDegrees maxLatitude = -90;
CLLocationDegrees minLongitude = 180;
CLLocationDegrees maxLongitude = -180;
// establish the min and max latitude and longitude
// of all the locations in the array
for (CLLocation *location in locations)
{
if (location.coordinate.latitude < minLatitude)
{
minLatitude = location.coordinate.latitude;
}
if (location.coordinate.latitude > maxLatitude)
{
maxLatitude = location.coordinate.latitude;
}
if (location.coordinate.longitude < minLongitude)
{
minLongitude = location.coordinate.longitude;
}
if (location.coordinate.longitude > maxLongitude)
{
maxLongitude = location.coordinate.longitude;
}
}
MKCoordinateSpan span;
CLLocationCoordinate2D center;
if ([locations count] > 1)
{
// for more than one location, the span is the diff between
// min and max latitude and longitude
span = MKCoordinateSpanMake(maxLatitude - minLatitude, maxLongitude - minLongitude);
// and the center is the min + the span (width) / 2
center.latitude = minLatitude + span.latitudeDelta / 2;
center.longitude = minLongitude + span.longitudeDelta / 2;
}
else
{
// for a single location make a fixed size span (pretty close in zoom)
span = MKCoordinateSpanMake(0.01, 0.01);
// and the center equal to the coords of the single point
// which will be the coords of the min (or max) coords
center.latitude = minLatitude;
center.longitude = minLongitude;
}
// create a region from the center and span
return MKCoordinateRegionMake(center, span);
}
Why not just enable userLocationVisible on the MKMapView? Then the users current location will be visible on the map as a blue dot.
Basically whenever you add mapView you should enable the showuserlocation option in the inspector.
The app will then start with your location when you run the app on the device.
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
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'
In my app I have a latitude-longitude of 1 fix location. Now user with iPhone device can move anywhere and even he rotate his device, the arrow (some uiimageview) should point to that fix location so User will get direction to that location every time. I tried as follows.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D here = newLocation.coordinate;
[self calculateUserAngle:here];
}
-(void) calculateUserAngle:(CLLocationCoordinate2D)user {
NSLog(#"my destination is %f ; %f", fixlocLat, fixlocLon);
degrees = degrees + atan2(sin(fixlocLon-user.longitude)*cos(fixlocLat),cos(user.latitude)*sin(fixlocLat) - sin(user.latitude)*cos(fixlocLat)*cos(fixlocLon-user.longitude));
//get angle between user location and fix location
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
arrow.transform = CGAffineTransformMakeRotation((degrees-newHeading.trueHeading) * M_PI / 180);
}
but the code above will always rotate arrow to approx. 2-3 degree north for every location.
My question looks similar to this Stack Overflow question.but using code from this link I am getting wrong direction.
please help me on this.
and also if any idea using accelerometer or gyrodata will be helpful for me.
thanx in advance.
This works for me: to rotate a Direction Arrow to particular location
-(void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
}
-(void) calculateUserAngle:(CLLocationCoordinate2D)current {
double x = 0, y = 0 , deg = 0,delLon = 0;
delLon = fixLon - current.longitude;
y = sin(delLon) * cos(fixLat);
x = cos(current.latitude) * sin(fixLat) - sin(current.latitude) * cos(fixLat) * cos(delLon);
deg = RADIANS_TO_DEGREES(atan2(y, x));
if(deg<0){
deg = -deg;
} else {
deg = 360 - deg;
}
degrees = deg;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D here = newLocation.coordinate;
[self calculateUserAngle:here];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
arrow.transform = CGAffineTransformMakeRotation((degrees-newHeading.trueHeading) * M_PI / 180);
}
this code may help you
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
// Use the true heading if it is valid.
CLLocationDirection direction = newHeading.magneticHeading;
CGFloat radians = -direction / 180.0 * M_PI;
self.strAccuracy = [NSString stringWithFormat:#"%.1fmi",newHeading.headingAccuracy];
[lblAccuracy setText:self.strAccuracy];
//Rotate Bearing View
[self rotateBearingView:bearingView radians:radians];
//For Rotate Niddle
CGFloat angle = RadiansToDegrees(radians);
[self setLatLonForDistanceAndAngle];
[self rotateArrowView:arrowView degrees:(angle + fltAngle)];
}
-(void)rotateArrowView:(UIView *)view degrees:(CGFloat)degrees
{
CGAffineTransform transform = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
view.transform = transform;
}
-(void)setLatLonForDistanceAndAngle
{
dblLat1 = DegreesToRadians(appDelegate.dblLatitude);
dblLon1 = DegreesToRadians(appDelegate.dblLongitude);
dblLat2 = DegreesToRadians(objClsProductSearch.dblLatitude);
dblLon2 = DegreesToRadians(objClsProductSearch.dblLongitude);
fltLat = dblLat2 - dblLat1;
fltLon = dblLon2 - dblLon1;
}
-(float)getAngleFromLatLon
{
//Calculate angle between two points taken from http://www.movable-type.co.uk/scripts /latlong.html
double y = sin(fltLon) * cos(dblLat2);
double x = cos(dblLat1) * sin(dblLat2) - sin(dblLat1) * cos(dblLat2) * cos(dblLon2);
CGFloat angle = RadiansToDegrees(atan2(y, x));
return angle;
}
-(void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
GeoAngle = [self setLatLonForDistanceAndAngle:newLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location=[locations lastObject];
GeoAngle = [self setLatLonForDistanceAndAngle:location];
}
-(float)setLatLonForDistanceAndAngle:(CLLocation *)userlocation
{
float lat1 = DegreesToRadians(userlocation.coordinate.latitude);
float lon1 = DegreesToRadians(userlocation.coordinate.longitude);
float lat2 = DegreesToRadians(Destination lattitude);
float lon2 = DegreesToRadians(Destination Longitude);
float dLon = lon2 - lon1;
float y = sin(dLon) * cos(lat2);
float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
float radiansBearing = atan2(y, x);
if(radiansBearing < 0.0)
{
radiansBearing += 2*M_PI;
}
return radiansBearing;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
float direction = -newHeading.trueHeading;
arrow.transform=CGAffineTransformMakeRotation((direction* M_PI / 180)+ GeoAngle);
}
Try this example. Its in C# Xamarin tho :)
"double heading" is the CLHeading.MagneticHeading from the eventobject in CLLocationManager.UpdatedHeading.
void UpdateCompass(Location origin, Location target, double heading)
{
var angle1 = GetAngleBetweenPoints(origin, target);
var angle2 = GetAngleFromHeading(heading);
var radian = Math.PI * (angle1 + angle2) / 180.0;
CompassArrow.Transform = CGAffineTransform.MakeRotation((nfloat)radian);
}
double GetAngleBetweenPoints(Location origin, Location target)
{
var n = 270 - (Math.Atan2(origin.Latitude - target.Latitude, origin.Longitude - target.Longitude)) * 180 / Math.PI;
return n % 360;
}
double GetAngleFromHeading(double heading)
{
var radians = -heading / 180.0 * Math.PI;
return radians * (180.0 / Math.PI);
}
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];