Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development > iPhone SDK Development - Advanced Discussion

Reply
 
LinkBack Thread Tools Display Modes
Old 12-24-2009, 12:23 PM   #1 (permalink)
Registered Member
 
Join Date: Mar 2009
Location: I'm a Brit-pat.
Posts: 171
Default Modifying CLLocations

Hi all,

I have a line object made up of two CLLocation's (startPoint and endPoint). I am adding a tolerance set in metres (say 3000 metres) around an MBR (Minimum Bounding Rectangle) derived from these two points.

The question I have is how would I add say 3000 metres to a CLLocation and arrive at a new CLLocation, especially given that there's no function like this?

Code:
-(CLLocation *) addDistanceToLocation:(CLLocation*)location:(float)metresLatitude:(float)metresLongitude;
What I'd ideally like to do is something like this:

Code:
startPoint = addDistanceToLocation:startPoint:3000:-3000
EDIT: I've changed my MBR code to read like this:
Code:
	MBR *mbr = [MBR alloc];
	CLLocation *x1y1 = [[CLLocation alloc] init];
	CLLocation *x2y2 = [[CLLocation alloc] init];
	x1y1.coordinate.latitude = MAX(startPoint.coordinate.latitude, [endPoint.coordinate.latitude]);
	x1y1.coordinate.longitude = MIN(startPoint.coordinate.longitude, [endPoint.coordinate.longitude]);
	x2y2.coordinate.latitude = MIN(startPoint.coordinate.latitude, [endPoint.coordinate.latitude]);
	x2y2.coordinate.longitude = MAX(startPoint.coordinate.longitude, [endPoint.coordinate.longitude]);
	mbr.topLeft = x1y1;
	mbr.bottomRight = x2y2;
Thought it might be easier to work with two CLLocations (topLeft and bottomRight). Still can't see how to add distances to these and arrive at a new set of points.

Thanks,

Jason

Last edited by coulls; 12-24-2009 at 01:15 PM.
coulls is offline   Reply With Quote
Old 12-24-2009, 03:01 PM   #2 (permalink)
Registered Member
 
Join Date: Mar 2009
Location: I'm a Brit-pat.
Posts: 171
Default

Found the solution, so don't worry...

Just incase anyone else hits this, here's how I did it.


Code:
-(CLLocation*) offsetLocation:(CLLocation*)startLocation:(double)offsetMeters:(double)bearing
{
	
	double EARTH_MEAN_RADIUS_METERS = 6372796.99;
	double lat2 = asin( sin(startLocation.coordinate.latitude) * cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) + cos(startLocation.coordinate.latitude) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(bearing) );
	double lon2 = startLocation.coordinate.longitude + atan2( sin(bearing) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(startLocation.coordinate.latitude), cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) - sin(startLocation.coordinate.latitude) * sin(lat2));
	CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:lat2 longitude:lon2];

	return tempLocation;
}
So, if I wanted to move something 3000 meters south (180 degree bearing).

newLocation = [self offsetLocation: oldLocation :3000 :180];

Cheers,

Jason
coulls is offline   Reply With Quote
Old 03-08-2010, 08:00 PM   #3 (permalink)
b.dot
 
Join Date: Mar 2010
Location: New York, NY
Posts: 2
Default Can Someone Check Me On This?

Quote:
Originally Posted by coulls View Post

Code:
	
	double lat2 = asin( sin(startLocation.coordinate.latitude) * cos(offsetMeters/EARTH_MEAN_RADIUS_METERS) + cos(startLocation.coordinate.latitude) * sin(offsetMeters/EARTH_MEAN_RADIUS_METERS) * cos(bearing) );
@coulls

Thanks for helping me with a starting point. I'm building a bounding box, and trying to determine the maximum latitude north. This is the exact calculation that I need, however given the following:

offsetLocation: latitude 37.331688999999997, longitude -122.030731
offsetMeters: 1000
bearing: 0
lat2 returns -0.36726592610659514

Any suggestions? I've coded around this particular formula until now and this one has me stumped.

b.dot
b.dot is offline   Reply With Quote
Old 03-09-2010, 10:15 AM   #4 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 4,814
Default You can't modify CLLocations - create another one instead.

Quote:
Originally Posted by coulls View Post
Hi all,

I have a line object made up of two CLLocation's (startPoint and endPoint). I am adding a tolerance set in metres (say 3000 metres) around an MBR (Minimum Bounding Rectangle) derived from these two points.

The question I have is how would I add say 3000 metres to a CLLocation and arrive at a new CLLocation, especially given that there's no function like this?

Code:
-(CLLocation *) addDistanceToLocation:(CLLocation*)location:(float)metresLatitude:(float)metresLongitude;
What I'd ideally like to do is something like this:

Code:
startPoint = addDistanceToLocation:startPoint:3000:-3000
EDIT: I've changed my MBR code to read like this:
Code:
	MBR *mbr = [MBR alloc];
	CLLocation *x1y1 = [[CLLocation alloc] init];
	CLLocation *x2y2 = [[CLLocation alloc] init];
	x1y1.coordinate.latitude = MAX(startPoint.coordinate.latitude, [endPoint.coordinate.latitude]);
	x1y1.coordinate.longitude = MIN(startPoint.coordinate.longitude, [endPoint.coordinate.longitude]);
	x2y2.coordinate.latitude = MIN(startPoint.coordinate.latitude, [endPoint.coordinate.latitude]);
	x2y2.coordinate.longitude = MAX(startPoint.coordinate.longitude, [endPoint.coordinate.longitude]);
	mbr.topLeft = x1y1;
	mbr.bottomRight = x2y2;
Thought it might be easier to work with two CLLocations (topLeft and bottomRight). Still can't see how to add distances to these and arrive at a new set of points.

Thanks,

Jason
I wrestled with this too. You can't change the values in a CLLocation. What you have to do is calculate the new coordinate you want, and then initialize a new one with the parameters from the old one.

You use the call initWithCoordinate:altitude:horizontalAccuracy:ver ticalAccuracy:timestamp: to create a new location using the values from the old location.

That lets you copy most, but not all, of the settings from the old location.


Regards,

Duncan C
WareTo
Duncan C is offline   Reply With Quote
Old 03-10-2010, 01:02 PM   #5 (permalink)
Registered Member
 
Join Date: Mar 2009
Location: I'm a Brit-pat.
Posts: 171
Default

Quote:
Originally Posted by b.dot View Post
@coulls

Thanks for helping me with a starting point. I'm building a bounding box, and trying to determine the maximum latitude north. This is the exact calculation that I need, however given the following:

offsetLocation: latitude 37.331688999999997, longitude -122.030731
offsetMeters: 1000
bearing: 0
lat2 returns -0.36726592610659514

Any suggestions? I've coded around this particular formula until now and this one has me stumped.

b.dot

I've not had a chance to come back to this one yet. I hope to attack it fairly soon though! :-)

Coulls
coulls is offline   Reply With Quote
Old 03-10-2010, 01:04 PM   #6 (permalink)
Registered Member
 
Join Date: Mar 2009
Location: I'm a Brit-pat.
Posts: 171
Default

Quote:
Originally Posted by Duncan C View Post
I wrestled with this too. You can't change the values in a CLLocation. What you have to do is calculate the new coordinate you want, and then initialize a new one with the parameters from the old one.
Thanks - I sort of arrived at that conclusion. The bigger problem for me next was the accuracy of the offset in metres when dealing with longitude. Still haven't quite had the time to sit down and figure that one out.

Coulls
coulls is offline   Reply With Quote
Old 03-11-2010, 09:25 PM   #7 (permalink)
Registered Member
 
Join Date: Mar 2009
Location: I'm a Brit-pat.
Posts: 171
Default

OK - Had to fix that bug, and it's looking good now... although much different to the first implementation. Much head scratching got me ready to throw the Mac out the window....

Add this at the top of your .m file. (Note the ArcCos hack I had to make as couldn't get the quiet_nan to work).
Code:
#include <math.h>
#define KmPerDegree		111.12000071117
#define	DegreesPerKm	(1.0/KmPerDegree)
#define PI				M_PI
#define TwoPI			(M_PI+M_PI)
#define HalfPI			M_PI_2
#define RadiansPerDegree	(PI/180.0)
#define	DegreesPerRadian	(180.0/PI)
#define copysign(x,y)		(((y)<0.0)?-fabs(x):fabs(x))
#define NGT1(x)		(fabs(x)>1.0?copysign(1.0,x):(x))
//#define ArcCos(x)	(fabs(x)>1?quiet_nan():acos(x)) //Hack
#define ArcCos(x)	(acos(x))
#define hav(x)		((1.0-cos(x))*0.5)		/* haversine */
#define ahav(x)		(ArcCos(NGT1(1.0-((x)*2.0))))	/* arc haversine */
#define sec(x)		(1.0/cos(x))			/* secant */
#define csc(x)		(1.0/sin(x))			/* cosecant */

The new function (take a deep breath - I kept the function signature the same, though) looks like this:

Code:
//Moves a CLLocation from one point to another in the bearing specified by the meters specified in that direction.
-(CLLocation*) moveLocation:(CLLocation*)startLocation:(double)movementInMeters:(double)movementBearing
{
	
	double	dist = (movementInMeters / 1000);	/* -> great-circle distance (km) */
	double	course = movementBearing;			/* -> initial great-circle course (degrees) */
	double	slt = startLocation.coordinate.latitude;	/* -> starting decimal latitude (-S) */
	double	slg = startLocation.coordinate.longitude;	/* -> starting decimal longitude(-W) */
	double	xlt = 0;	/* <- ending decimal latitude (-S) */
	double	xlg = 0;	/* <- ending decimal longitude(-W) */
	
	double	c, d, dLo, L1, L2, coL1, coL2, l;
		
	if (dist > KmPerDegree*180.0) {
		course -= 180.0;
		if (course < 0.0) course += 360.0;
		dist    = KmPerDegree*360.0-dist;
	}
	
	if (course > 180.0) course -= 360.0;
	c    = course*RadiansPerDegree;
	d    = dist*DegreesPerKm*RadiansPerDegree;
	L1   = slt*RadiansPerDegree;
	slg *= RadiansPerDegree;
	coL1 = (90.0-slt)*RadiansPerDegree;
	coL2 = ahav(hav(c)/(sec(L1)*csc(d))+hav(d-coL1));
	L2   = HalfPI-coL2;
	l    = L2-L1;
	if ((dLo=(cos(L1)*cos(L2))) != 0.0)
		dLo  = ahav((hav(d)-hav(l))/dLo);
	if (c < 0.0) dLo = -dLo;
	slg += dLo;
	if (slg < -PI)
		slg += TwoPI;
	else if (slg > PI)
		slg -= TwoPI;
		
	xlt = L2*DegreesPerRadian;
	xlg = slg*DegreesPerRadian;
		
	CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:xlt longitude:xlg];
	return tempLocation;
}
The source of this solution is here:
http://sam.ucsd.edu/sio210/propseawater/ppsw_c/gcdist.c

Cheers,

Coulls
coulls is offline   Reply With Quote
Reply

Bookmarks

Tags
cllocation, core location, distances, mbr

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 252
22 members and 230 guests
@sandris, ADY, bookesp, ckgni, dacapo, Dani77, DarkAn, Davey555, Desert Diva, HemiMG, iDifferent, jakerocheleau, JasonR, LEARN2MAKE, prchn4christ, Rudy, ryantcb, Speed, themathminister, theone8one
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,885
Threads: 89,230
Posts: 380,766
Top Poster: BrianSlick (7,129)
Welcome to our newest member, bookesp
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 02:41 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0