Home > OS >  PHP - How to compare two headings on a compass rose?
PHP - How to compare two headings on a compass rose?

Time:03-29

Working on a tool to make runway recommendations for flight simulation enthusiasts based off of the real world winds at a given airport. The ultimate goal is to compare, and return a list of available runways in a list, with the smallest wind variance displaying at the top of the list.

I would say that I probably have 95% of what I need, but where it gets slippery is for wind headings that approach 0 degrees (360 on a compass rose).

If runway heading is 029 and wind heading is 360, it is only a difference of 29 degrees, but the formula that I have written displays a difference of 331 degrees.

I have tried experimenting with abs() as part of the comparison but have gotten nowhere. I will link my current results here: https://extendsclass.com/php-bin/7eba5c8

Attempted switching comparisons for wind heading and runway heading (subtracting one from the other, and then the other way around) with the same result.

I am sure that the key lies in some little three line nonsense that I just cannot get the knack of (disadvantage of being a self-taught cowboy coder, I guess).

I saw a post about how to do it in C# from about 11 years ago but I never messed around with that particular deep, dark corner of the programming world.

The code is included below:

<?php
    echo "<pre>\n";
    //Dummy Runways. Will be replaced by data from AVWX
    $rwy_hdgs = array(
    "04R" => "029",
    "04L" => "029",
    "22R" => "209",
    "22L" => "209",
    "03R" => "029",
    "03L" => "029",
    "21L" => "216",
    "21R" => "216",
    "09L" => "089",
    "09R" => "089",
    "27R" => "269",
    "27L" => "269"
    );
    
    //Dummy Wind Heading. Will be replaced by data from AVWX
    $wind_dir = "360";
    
    $runways = array();
    $i = 1;
    foreach($rwy_hdgs as $key => $value)
    {
            $diff = $value - $wind_dir;
            
            $runways[$i]["rwy"] = $key;
            $runways[$i]["hdg"] = $value;
            $runways[$i]["diff"] = abs($diff);
            $i  ;
        
    }
    //Select "diff" value
    $diff = array_column($runways, "diff");
    
    //Sort $runways by difference betweeen wind and runways, with smallest value first
    array_multisort($diff, SORT_ASC, $runways);
    
    foreach ($runways as $runway){
        echo "Wind Heading: " . $wind_dir . "\n";
        echo "Runway: " . $runway["rwy"] . "\n";
        echo "Heading: " . $runway["hdg"] . "\n";
        echo "Variance: " . $runway["diff"] . "&#176;\n\n";
    }
    echo "</pre>\n";
?>

CodePudding user response:

When you subtract two angles in a circle, you can either go the "short way" or the "long way" - it's a circle... So you have to calculate both ways and then find out, which one is shorter - and the direction too, because you have a fixed start angle and a fixed target angle:

function angleDiff($angleStart, $angleTarget) {
  $delta = $angleTarget - $angleStart;
  $direction = ($delta > 0) ? -1 : 1;
  $absDelta1 = abs($delta);
  $absDelta2 = 360 - $absDelta1;
  return $direction * ($absDelta1 < $absDelta2 ? $absDelta1 : $absDelta2);
}

This should give you positive numbers for clockwise turning and negative numbers for counter-clockwise turning from start to target angle. Disclaimer: didn't actually test the code, sorry, might have flaws ;)

CodePudding user response:

When I got it right, you want to calculate the difference between two angles always going the short way. So you could do it like this:

$diff = min([abs($a - $b), 360 - abs($a - $b)]);

whith $a and $b being the two angles. The result will always be between 0 and 180 degrees.

  •  Tags:  
  • php
  • Related