Search code examples
rgeometrygeography

Transform angles from polar coordinates


I am in need of some help with angles.

Calculating bearings with the package fossil and the function fossil::earth.bear we obtain, according to the help,

"the bearing in degrees clockwise from True North between any two points on the globe".

I have a vector of angles obtained with this function, and I need to transform them so the origin (0º) is on the x axis (East) and the angles increment counterclockwise.

Basically I need a way to rotate 90º clockwise my angles (so the 0º will be on the x axis "facing East") and then calculate the angle in the opposite direction (counterclockwise).

Intuitively, I've tried adding 90º to my bearings (to rotate clockwise) and then substracting them from 360 (to calculate the angle in the "opposite direction").

However, it does not work and I highly suspect that there is a different thing to do for each quadrant, but I just can't figure it out.

Below a test with dummy data and polar histograms to prove that the solution is not working as the resulting vector bearings2is not equivalent to the starting vector bearings

# Generate vector with 100 random values between 0 and 360
set.seed(123)
bearing <- runif(100, 0,360)
# generate a histogram with values binned every 5º
breaks = seq(0, 360, by=5)   
bearing.cut = cut(bearing, breaks, right=FALSE) 
bearing.freq = as.data.frame(table(bearing.cut))
bearing.freq$bearing.cut <- seq(5,360, by = 5)
#plot with ggplot
library(ggplot2)
ggplot(bearing.freq, aes(x = bearing.cut, y = Freq)) +
  coord_polar(theta = "x", start = 0 direction = 1) + #start 0 for north, direction 1 for cloclwise
  geom_bar(stat = "identity") +
  scale_x_continuous(breaks = seq(0, 360, 5))

This is the plot that this createsenter image description here Now I perform the mentioned operations in my bearing vector

bearing2 <- 360-(bearing-90)
# repeat the process to generate freq table and plot 
breaks = seq(0, 360, by=5)    
bearing.cut2 = cut(bearing2, breaks, right=FALSE) 
bearing.freq2 = as.data.frame(table(bearing.cut2))
bearing.freq2$bearing.cut <- seq(5,360, by = 5)
#plot with ggplot
library(ggplot2)
ggplot(bearing.freq2, aes(x = bearing.cut2, y = Freq)) +
  coord_polar(theta = "x", start = -pi/2, direction = -1) + # now start at E and counterclockwise
  geom_bar(stat = "identity") +
  scale_x_continuous(breaks = seq(0, 360, 5))

And this is the plot that this generates. Clearly, if my conversion was correct, these two plots should look the same... and they don't. enter image description here

** I have edited as per Gregor's suggestion (and to set a seed so it is repeatable). Looks better but we lose all angles between 0º and 90º. Which reinforces my initial idea that there's a different operation to do for each quadrant, but still can't figure it out. Still, thanks for the tip!


Solution

  • Ok I think I figured it out but not really sure why it works. I'll just leave it here to mark the question as answered.

    The solution is that, for the first quadrant (angles between 0º and 90º, we need to calculate the complementray angle so we need 90-bearing . For the rest of the quadrants, we do what Gregor suggested(360-(bearing-90)).

    Below the complete code to a reproducible example

    library(ggplot2)
    set.seed(123)
    
    # 0º at North and clockwise
    bearing <- runif(100, 0,360)
    
    #create histogram
    breaks = seq(0, 360, by=5)    # half-integer sequence 
    bearing.cut = cut(bearing, breaks, right=FALSE) 
    bearing.freq = as.data.frame(table(bearing.cut))
    bearing.freq$bearing.cut <- seq(5,360, by = 5)
    
    #plot
    p1 <- ggplot(bearing.freq, aes(x = bearing.cut, y = Freq)) +
            coord_polar(theta = "x", start =0, direction = 1) +
            geom_bar(stat = "identity") +
            scale_x_continuous(breaks = seq(0, 360, 5))
    
    # transform to 0º at E and counterclockwise
    bearing2 <- ifelse(bearing <=90, (90-bearing), (360 - (bearing - 90)))
    
    #create histogram
    bearing.cut2 = cut(bearing2, breaks, right=FALSE) 
    bearing.freq2 = as.data.frame(table(bearing.cut2))
    bearing.freq2$bearing.cut <- seq(5,360, by = 5)
    
    # plot
    p2 <- ggplot(bearing.freq2, aes(x = bearing.cut, y = Freq)) +
            coord_polar(theta = "x", start = -pi/2, direction = -1) +
            geom_bar(stat = "identity") +
            scale_x_continuous(breaks = seq(0, 360, 5))
    
    require(gridExtra)
    grid.arrange(p1, p2, ncol=2)
    

    enter image description here