Monday, January 2, 2017

A PowerShell function to convert wind degrees to compass directions and italianate wind names

Winter has arrived and since there is no Windows Phone app for managing my pellet stove, I am working on a PowerShell module so that I know exactly how much my stove consumes by fetching the relevant data from the onboard management unit.

The module I am writing allows me to turn on and off my stove, and to configure it to suit my needs.

I have also added to this module a couple of additional functions to build a relation between the activity of my home stove with the data taken from the external weather data provider (I'll talk about this in a future post).

Now I live in a region where there can be strong winds that lower the temperature, so I thought necessary to add to my module a function specifically aimed at converting the wind direction (in degrees) into something more readable, such as one of the 16 compass headings as well as into its Italianate wind name.

This is what I am going to share with you here today.

I am not going to write an entire blog post on the history of the Rose of the Winds (there's a Wikipedia article for that), but, it is interesting to note that there are three possible ways to express a wind direction:
  1. in degress, such as 90°, 220° etc
  2. through its cardinal (north, south, east, west) and ordinal (northeast, southeast, southwest and northwest) directions
  3. through its italianate wind name
The italianate wind names, also known as the traditional wind names, derivate from the fact that during the 13th and 14th century the Italian was the lingua franca in the whole Mediterranean region, and sailors used it to name winds in an understandable way when crossing with people from from other countries.

So basically you have the following table with the eight principal winds:

Direction Italianate Name
--------- --------------
North     Tramontana
Northeast Grecale or Bora
East      Levante or Oriente
Southeast Scirocco or Exaloc
South     Ostro or Mezzogiorno
Southwest Libeccio or Garbino
West      Ponente or Zephyrus
Northwest Maestrale or Mistral

Now since I want my function to be more precise around the wind direction, I have choosen to adopt the 16-wind compass:

Direction       Italianate Name      
---------       --------------      
North           Tramontana
North Northeast Tramontana-Grecale
Northeast       Grecale
East Northeast  Grecale-Levante
East            Levante
East Southeast  Levante-Scirocco
Southeast       Scirocco
South Southeast Scirocco-Ostro
South           Ostro
South Southwest Ostro-Libeccio
Southwest       Libeccio
West Southwest  Libeccio-Ponente
West            Ponente
West Northwest  Ponente-Mastrale
Northwest       Maestrale
North Northwest Maestrale-Tramontana

This is the function I came up with:

function Get-WindDirection {

<#
.Synopsis
   Returns wind direction
.DESCRIPTION
   Returns wind direction and the italianate wind name
.EXAMPLE
   Get-WindDirection -degress 90
.NOTES
   happysysadm.com
   @sysadm2010
#>

    [CmdletBinding()]
    [OutputType([string])]
    Param
    (
        # Degrees
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [ValidateRange(0,360)][int]$Degree
    )
    Begin {
        $WindCompassDirection = @("North","North Northeast","Northeast","East Northeast","East","East Southeast", "Southeast", "South Southeast","South","South Southwest","Southwest","West Southwest","West","West Northwest","Northwest","North Northwest","North")
        $WindCompassName = @('Tramontana','Tramontana-Grecale','Grecale','Grecale-Levante','Levante','Levante-Scirocco','Scirocco','Scirocco-Ostro','Ostro','Ostro-Libeccio','Libeccio','Libeccio-Ponente','Ponente','Ponente-Mastrale','Maestrale','Maestrale-Tramontana','Tramontana')
        }

    Process {
        $Sector = $Degree/22.5  #Divide the angle by 22.5 because 360deg/16 directions = 22.5deg/direction change
        Write-Verbose "$Degree is in $Sector sector."
        $Value = "" | Select-Object -Property Direction,Name
        $Value.Direction = $WindCompassDirection[$Sector]
        $Value.Name = $WindCompassName[$Sector]
        return $Value
        }

    End {}
   
}

Let's move to see it in detail and to explain the process of converting wind directions in degrees to text words.

The first step is to divide the given wind angle by 22.5 because 360 degrees divided by 16 directions gives sectors 22.5 degrees wide. So:

PS C:\> 23/22.5
1.02222222222222

which means that a wind coming from 23° is in the first sector, after rounding.

Another example:

PS C:\> 177/22.5
7.86666666666667

which means that a wind coming from 177° is in the 7th sector.

Let's put that value into a $Sector variable:

$Sector = $Degree/22.5

Now I just have to tag each sector by creating an array containing all of them. Actually I want two arrays because I want to be able to print the cardinal and ordinal direction along the italianate wind name.

Each arrays has 17 sectors, not 16, so that I am certain to translate a value such as 359° to North:

$WindCompassDirection = @("North","North Northeast","Northeast","East Northeast","East","East Southeast", "Southeast", "South Southeast","South","South Southwest","Southwest","West Southwest","West","West Northwest","Northwest","North Northwest","North")

$ItalianateWindName = @('Tramontana','Tramontana-Grecale','Grecale','Grecale-Levante','Levante','Levante-Scirocco','Scirocco','Scirocco-Ostro','Ostro','Ostro-Libeccio','Libeccio','Libeccio-Ponente','Ponente','Ponente-Mastrale','Maestrale','Maestrale-Tramontana','Tramontana')

Now you already know for sure that you can echo back the value of an item (such as number 4) in a indexed PowerShell array with the following code:

$array[4]

This is the technique I use to access the value inside the array composed of wind names:

$value.Direction = $WindCompassDirection[$Sector]
$value.ItalianateName = $ItalianateWindName[$Sector]

It is worth noticing that when $Sector is a Double, such in the case

PS C:\> 177/22.5
7.86666666666667

it is automatically converted to an integer when used as index for a value inside an array:

PS C:\> $WindCompassDirection[7.86666666666667]
South

For sure we have to accept here the banker's rounding mechanism, which I have already explained in a previous post.

Stay tuned for more functions from my PowerShell module to manage a pellet stove in those cold times.

Happy new year, readers, and happy coding.

2 comments:

  1. Fun article. I hadn't ever heard of italianate names before. Thanks for sharing!

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...