Page 1 of 1
UDT for calculation of distance between two geo-coordinates
Posted: Sat Jan 17, 2009 11:15 pm
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
Re: UDT for calculation of distance between two geo-coordinates
Posted: Sat Jan 17, 2009 11:48 pm
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;
Re: UDT for calculation of distance between two geo-coordinates
Posted: Mon Jan 19, 2009 5:11 pm
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.
Re: UDT for calculation of distance between two geo-coordinates
Posted: Mon Jan 19, 2009 5:20 pm
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'}
Re: UDT for calculation of distance between two geo-coordinates
Posted: Mon Jan 19, 2009 5:33 pm
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
Re: UDT for calculation of distance between two geo-coordinates
Posted: Mon Jan 19, 2009 5:55 pm
by calguy1000
Just for smarty plugins..... whether they're done as UDT's or in a module like CGSimpleSmarty does.... or as seperate files.
Re: UDT for calculation of distance between two geo-coordinates
Posted: Mon Jan 19, 2009 7:56 pm
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