UDT for calculation of distance between two geo-coordinates

Do something cool with CMS? Show us ...
This board is for 'Answers', and the discussion of answers... Not for questions.
Post Reply
nhaack

UDT for calculation of distance between two geo-coordinates

Post by nhaack »

Hi there,

for a project I needed a quick way to calculate the distance between two gps coordinates. I though this code might be handy for others (e.g. in combination with the Geocoder API Plug-in).

Save this as a UDT with the name "calculate_distance"

Code: Select all


//
// Check for parameters, if not set or empty, set default
//

// This parameter is used to select the scaling of the result returned
if (isset($params['convert']) AND ($params['convert'] != '')) {		
	$convert = strtolower($params['convert']);	
} else {$convert = 'mi';}	

// This is the latitude of the first point
if (isset($params['gps_lat_1']) AND ($params['gps_lat_1'] != '')) {		
	$gps_lat_1 = (float)$params['gps_lat_1'];	
} else {$gps_lat_1 = -10;}	

// This is the latitude of the first point
if (isset($params['gps_lat_2']) AND ($params['gps_lat_2'] != '')) {		
	$gps_lat_2 = (float)$params['gps_lat_2'];	
} else {$gps_lat_2 = 11;}	

// This is the longitude of the second point
if (isset($params['gps_long_1']) AND ($params['gps_long_1'] != '')) {		
	$gps_long_1 = (float)$params['gps_long_1'];	
} else {$gps_long_1 = 10;}	

// This is the longitude of the second point
if (isset($params['gps_long_2']) AND ($params['gps_long_2'] != '')) {		
	$gps_long_2 = (float)$params['gps_long_2'];	
} else {$gps_long_2 = 11;}	

//
// Do the distance calculation
//

	$result = sin(deg2rad($gps_lat_1)) * sin(deg2rad($gps_lat_2)) + cos(deg2rad($gps_lat_1)) * cos(deg2rad($gps_lat_2)) * cos(deg2rad($gps_long_1 - $gps_long_2));
	$result = rad2deg(acos($result)) * 69.09;

//
// If a converting is required do this
//

	if ($convert== 'km' ) {$result = $result * 1.609344;}

//
// Return integer value for distance in selected scaling	
//

return (integer)round($result,0);

Then you can do the calculation in your templates. E.g.

{calculate_distance convert="km" gps_lat_1=10 gps_lat_2=11.63 gps_long_1=53.5123 gps_long_2=55.123}

The UDT will echo the pure value as integer (default scaling is US miles, optional: kilometer). For other scalings (e.g. nautic miles... just add your scalings below the KM conversion in the same pattern.

Best
Nils
Last edited by nhaack on Sat Jan 17, 2009 11:25 pm, edited 1 time in total.
nhaack

Re: UDT for calculation of distance between two geo-coordinates

Post by nhaack »

here is a quickly optimized version. I found a nice conversion table and integrated a few more possible scales. Output is now in smarty.  {$distance} will display the calculated distance in the requested scaling.

Just look at the source which scaling you want and use that string in the convert parameter.

Best
Nils

Code: Select all



//
// Check for parameters, if not set or empty, set default
//

// This parameter is used to select the scaling of the result returned
if (isset($params['round']) AND ($params['round'] != '')) {		
	$roundt = (integer)$params['round'];	
} else {$roundt = 0;}
	
// This parameter is used to select the scaling of the result returned
if (isset($params['convert']) AND ($params['convert'] != '')) {		
	$convert = strtolower($params['convert']);	
} else {$convert = 'mi';}	

// This is the latitude of the first point
if (isset($params['gps_lat_1']) AND ($params['gps_lat_1'] != '')) {		
	$gps_lat_1 = (float)$params['gps_lat_1'];	
} else {$gps_lat_1 = -10;}	

// This is the latitude of the first point
if (isset($params['gps_lat_2']) AND ($params['gps_lat_2'] != '')) {		
	$gps_lat_2 = (float)$params['gps_lat_2'];	
} else {$gps_lat_2 = 11;}	

// This is the longitude of the second point
if (isset($params['gps_long_1']) AND ($params['gps_long_1'] != '')) {		
	$gps_long_1 = (float)$params['gps_long_1'];	
} else {$gps_long_1 = 10;}	

// This is the longitude of the second point
if (isset($params['gps_long_2']) AND ($params['gps_long_2'] != '')) {		
	$gps_long_2 = (float)$params['gps_long_2'];	
} else {$gps_long_2 = 11;}	

//
// Do the distance calculation
//

	$result = sin(deg2rad($gps_lat_1)) * sin(deg2rad($gps_lat_2)) + cos(deg2rad($gps_lat_1)) * cos(deg2rad($gps_lat_2)) * cos(deg2rad($gps_long_1 - $gps_long_2));
	$result = rad2deg(acos($result)) * 69.09;

//
// If a converting is required do this
//
	// metric
	if ($convert== 'km' ) {$result = $result * 1.609344;}
	if ($convert== 'meter' ) {$result = $result * 1609.344;}
	if ($convert== 'cm' ) {$result = $result * 160934.4;}
	
	// imperial
	if ($convert== 'league' ) {$result = $result * 0.333333;}
	if ($convert== 'yard' ) {$result = $result * 1760;}
	if ($convert== 'foot' ) {$result = $result * 5280;}
	if ($convert== 'inch' ) {$result = $result * 63360;}
	
	// nautic
	if ($convert== 'sealeague' ) {$result = $result * 0.289659;}
	if ($convert== 'seamile' ) {$result = $result * 0.868976;}
	if ($convert== 'cable' ) {$result = $result * 7.33333;}
	if ($convert== 'shortcable' ) {$result = $result * 8.68976;}
	if ($convert== 'fathom' ) {$result = $result * 880;}
	
	// japanese
	if ($convert== 'ri' ) {$result = $result * 0.409784;}
	if ($convert== 'kairi' ) {$result = $result * 0.868976;}
	if ($convert== 'cho' ) {$result = $result * 14.7522;}
	if ($convert== 'iyo' ) {$result = $result * 531.08;}
	if ($convert== 'ken' ) {$result = $result * 885.133;}
	if ($convert== 'shyaku' ) {$result = $result * 5310.8;}
	
	// chinese imperial
	if ($convert== 'li' ) {$result = $result * 3.21869;}
	if ($convert== 'yin' ) {$result = $result * 48.2803;}
	if ($convert== 'zhang' ) {$result = $result * 482.803;}
	if ($convert== 'bu' ) {$result = $result * 965.606;}
	if ($convert== 'chi' ) {$result = $result * 4828.03;}
	if ($convert== 'cun' ) {$result = $result * 48280.3;}
	
	// German geographical
	if ($convert== 'geomile' ) {$result = $result * 0.216893;}
	
	// typographic - ATA system
	if ($convert== 'pica' ) {$result = $result * 381597;}
	if ($convert== 'point' ) {$result = $result * 4579160;}
	if ($convert== 'pixel' ) {$result = $result * 6105550;}
	
	// astronomic	
	if ($convert== 'redshift' ) {$result = $result * 1.23532e-23;}
	if ($convert== 'parsec' ) {$result = $result * 5.21553e-14;}
	if ($convert== 'astronomicalunit' ) {$result = $result * 1.70111e-13;}
	if ($convert== 'lightyear' ) {$result = $result * 1.07578e-8;}
	if ($convert== 'lightminute' ) {$result = $result * 8.94699e-8;}
	if ($convert== 'lightsecond' ) {$result = $result * 0.00000536819;}
	
	// ancient roman	
	if ($convert== 'millarium' ) {$result = $result * 1.00735;}
	if ($convert== 'akt' ) {$result = $result * 41.973;}
	if ($convert== 'decimpeda' ) {$result = $result * 503.676;}
	if ($convert== 'pace' ) {$result = $result * 1007.35;}
	if ($convert== 'cubit' ) {$result = $result * 3357.84;}
	if ($convert== 'ped' ) {$result = $result * 5036.76;} 		// ordinary ped
	if ($convert== 'ounce' ) {$result = $result * 60441.1;} 	// ounce (inch)
	if ($convert== 'digit' ) {$result = $result * 80588.1;}
	

//
// Return integer value for distance in selected scaling	
//

	$smarty->assign('distance', round($result,$roundt));
	
	return;

tyman00
Power Poster
Power Poster
Posts: 906
Joined: Tue Oct 24, 2006 5:59 pm

Re: UDT for calculation of distance between two geo-coordinates

Post by tyman00 »

Very nice! I don't have a need for it at the moment, but I could see how this would come in very handy.
If all else fails, use a bigger hammer.
M@rtijn wrote: This is a community. This means that we work together and have the same goal (a beautiful CMS), not that we try to put people down and make their (voluntary) job as difficult as can be.
calguy1000
Support Guru
Support Guru
Posts: 8169
Joined: Tue Oct 19, 2004 6:44 pm

Re: UDT for calculation of distance between two geo-coordinates

Post by calguy1000 »

quick tip:

Normally by convention we just 'return' the results, rather than hardcode a variable name..... we usually also try to use an 'assign' parameter
like this:

Code: Select all

if( isset($params['assign']) )
  {
      $smarty->assign(trim($params['assign']),$value);
      return;
  }
return $value;
That way you can call the UDT like this:

Code: Select all

{capture assign='mydistance'}{mydistancecalculator_udt}{/capture}
or

Code: Select all

{mydistancecalculator_udt assign='mydistance'}
Follow me on twitter
Please post system information from "Extensions >> System Information" (there is a bbcode option) on all posts asking for assistance.
--------------------
If you can't bother explaining your problem well, you shouldn't expect much in the way of assistance.
nhaack

Re: UDT for calculation of distance between two geo-coordinates

Post by nhaack »

Cool, thanks for tip.

Does this apply for UDTs only, or is this something I should keep in mind for all programming I do for CMSMS?
Sorry for asking, but I never really learnt programming - I just try very hard :)

Will adjust the code and put it in the wiki afterwards ....

Best
Nils
calguy1000
Support Guru
Support Guru
Posts: 8169
Joined: Tue Oct 19, 2004 6:44 pm

Re: UDT for calculation of distance between two geo-coordinates

Post by calguy1000 »

Just for smarty plugins..... whether they're done as UDT's or in a module like CGSimpleSmarty does.... or as seperate files.
Follow me on twitter
Please post system information from "Extensions >> System Information" (there is a bbcode option) on all posts asking for assistance.
--------------------
If you can't bother explaining your problem well, you shouldn't expect much in the way of assistance.
nhaack

Re: UDT for calculation of distance between two geo-coordinates

Post by nhaack »

Thanks, I will also soon adjust the plug-ins I have released, so they comply with the conventions. It is actually quite neat to be able to define the output variable name.

I tried searching the forum and the wiki but couldn't find any document regarding the code style - or are these generally accepted coding styles? I'd like to know more about how to make my code better for CMSMS.

Best
Nils
Post Reply

Return to “Tips and Tricks”