Forum Moderators: coopster

Message Too Old, No Replies

Convert bearing from degrees to direction

         

ocon

2:54 am on May 4, 2010 (gmt 0)

10+ Year Member Top Contributors Of The Month



I have many bearings that I would like to convert into directions.

Is there a better way to see if a number falls within certain ranges?

if($bearing>=0 && $bearing>22.5) $direction="N";
else if($bearing>=22.5 && $bearing>67.5) $direction="NE";
else if($bearing>=67.5 && $bearing>112.5) $direction="E";
else if($bearing>=112.5 && $bearing>157.5) $direction="SE";
else if($bearing>=157.5 && $bearing>202.5) $direction="S";
else if($bearing>=202.5 && $bearing>247.5) $direction="SW";
else if($bearing>=247.5 && $bearing>292.5) $direction="W";
else if($bearing>=292.5 && $bearing>337.5) $direction="NW";
else $direction="N"

Thanks

astupidname

6:48 am on May 4, 2010 (gmt 0)

10+ Year Member



For the current task at hand, about the only other way I can think of at this time (only moderately prettier -eye of the beholder-, and very slightly quicker -approx .00025 seconds- ) :

$bearing = 321;

$cardinalDirections = array(
'N' => array(337.5, 22.5),
'NE' => array(22.5, 67.5),
'E' => array(67.5, 112.5),
'SE' => array(112.5, 157.5),
'S' => array(157.5, 202.5),
'SW' => array(202.5, 247.5),
'W' => array(247.5, 292.5),
'NW' => array(292.5, 337.5)
);

foreach ($cardinalDirections as $dir => $angles) {
if ($bearing >= $angles[0] && $bearing < $angles[1]) {
$direction = $dir;
break;
}
}

echo $direction;

CyBerAliEn

4:44 pm on May 4, 2010 (gmt 0)

10+ Year Member



A more robust approach (if you are checking/working with multiple bearings)...

function getDirection($bearing)
{
$cardinalDirections = array(
'N' => array(337.5, 22.5),
'NE' => array(22.5, 67.5),
'E' => array(67.5, 112.5),
'SE' => array(112.5, 157.5),
'S' => array(157.5, 202.5),
'SW' => array(202.5, 247.5),
'W' => array(247.5, 292.5),
'NW' => array(292.5, 337.5)
);

foreach ($cardinalDirections as $dir => $angles)
{
if ($bearing >= $angles[0] && $bearing < $angles[1])
{
$direction = $dir;
break;
}
}
return $direction;
}


code from astupidname, wrapped into a function

This way, you can call "getDirection()" and pass any bearing into it, and get the right direction out. IE:

$thisbearing = 321;
$thisdirection = getDirection($bearing);
//$thisdirection would equal 'NW'

ocon

8:06 pm on May 4, 2010 (gmt 0)

10+ Year Member Top Contributors Of The Month



I like the array function much better than a series of if/else statements, if not for aesthetics alone. I'm actually surprised that you have to run through a loop to detect if a number is within a range, it would seem there would be a more direct approach.

eelixduppy

8:11 pm on May 4, 2010 (gmt 0)



Orrrr....if you want the fastest way I can think of, we just skip all comparisons and go right for the gold ;)

function getDir($b) { $dirs = array('N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'); return $dirs[round($b/45)]; }

Readie

8:17 pm on May 4, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There's actually a more efficient way to do this. The above script carries on the loop after a match is made, so a for loop would most likely be more appropriate here:
function getDirection($bearing) {
$cardinalDirections = array(
array('N', 337.5, 22.5),
array('NE', 22.5, 67.5),
array('E', 67.5, 112.5),
array('SE', 112.5, 157.5),
array('S', 157.5, 202.5),
array('SW', 202.5, 247.5),
array('W', 247.5, 292.5),
array('NW', 292.5, 337.5)
);

$count = count($cardinalDirections);

for ($i = 0; $i < $count; $i++) {
if ($bearing >= $cardinalDirections[$i][1] && $bearing < $cardinalDirections[$i][2]) {
$direction = $cardinalDirections[$i][0];
$i = $count;
}
}
return $direction;
}
Should result in slightly faster run times.

EDIT:

Doh, just noticed the break; command in the above code. Oh well, for() has less overhead than foreach() anyways. Also, eelix posted as I was typing this :)

EDIT2:

Also... The array we've all blindely been using won't work.

array('N', 337.5, 22.5)

Need two N's:

array('N', 0, 22.5),
array('N', 337.5, 360)