'Converting atan2 Excel code to R, to produce flow direction in Cartesian Coordinates

I have earth flow displacements in two directions, converted to point data, which I am trying to combine for an overall offset direction (point to where the flow is going). I have magnitude in a separate raster file.

I'm trying to convert an old excel code into R so I can work with larger datasets. I have an IF statement in excel which will convert 2 displacements into direction in Cartesian co-ordinates using atan2. I know that Excel and R have opposite argument placements for atan2, so I've swapped them.

Where it gets messy is after atan2, when I need to convert to degrees and "bin" the results in a correct quadrant. Ultimately, I'd like the values in Cartesian coordinates (0 to 360), rather than -180 to 180 (radians).

I've tried running through these already asked questions, but am still lost:

How to map atan2() to degrees 0-360
Reshaping EPA wind speed & direction data with dcast in R

Here is my excel code:

(N2 = the displacement in north direction)
(E2 = the displacement in east direction)

=IF(
    (ATAN2(N2,E2)*180/PI())<0, 360+(ATAN2(N2,E2)*180/PI()), 
    ATAN2(N2,E2)*180/PI()
)

I tried running this in R like this:

theta_rad <- atan2(E,N)
if(theta_rad < 0)
    theta_rad +2*pi

theta_deg <- theta_rad*(180/pi)`  # Convert to degrees

I've also tried the following, which just crashes R

dir <- (theta_rad > 0 ? x : (2*pi + theta_rad)) * 360 / (2*pi)

Warnings: The condition has length >1 and only the first element will be used.



Solution 1:[1]

Because atan2 returns on the domain of (-pi,pi] but you want it starting at 0 instead ((0,2pi] in radians), then modulus works for you here.

cbind(a=seq(-pi, pi, len=11), b=(2*pi+seq(-pi, pi, len=11))%%(2*pi))
#                a         b
#  [1,] -3.1415927 3.1415927
#  [2,] -2.5132741 3.7699112
#  [3,] -1.8849556 4.3982297
#  [4,] -1.2566371 5.0265482
#  [5,] -0.6283185 5.6548668
#  [6,]  0.0000000 0.0000000
#  [7,]  0.6283185 0.6283185
#  [8,]  1.2566371 1.2566371
#  [9,]  1.8849556 1.8849556
# [10,]  2.5132741 2.5132741
# [11,]  3.1415927 3.1415927

Converting this to degrees is just doing the standard conversion. I think your code should be

(360 + atan2(E, N) * 180 / pi) %% 360

Solution 2:[2]

thank you for your response. Based from your code, I was able to come up with an azimuth function as shown below. But I do not understand why I have to use either 450 or 90 on the add.degree variable:

add.degree <- ifelse(delta.xy[1] < 0 & delta.xy[2]>0, 450, 90)
return(add.degree-deg(atan2(delta.xy[2],delta.xy[1])))

Notheless, I found out later that the st_azimuth is now available as: nngeo::st_azimuth(st_point(.start),st_point(.end))

# quadrant 1
.start <- c(100.805, 79.600)
.end <- c(123.389, 123.400)
azimuth(.start, .end)
# [1] 27.27638

# quadrant 2
.start <- c(100.805, 123.400)
.end <- c(123.389, 79.600)
azimuth(.start, .end)
# [1] 152.7236

# quadrant 3
.start <- c(123.389, 123.400)
.end <- c(100.805, 79.600)
azimuth(.start, .end)
# [1] 207.2764

# quadrant 4
.start <- c(123.389, 79.600)
.end <- c(100.805, 123.400)
azimuth(.start, .end)
#[1] 332.7236

azimuth <- function(v.origin, v.ending) {
  delta.xy <- v.ending - v.origin
  add.degree <- ifelse(delta.xy[1] < 0 & delta.xy[2]>0, 450, 90)
  return(add.degree-deg(atan2(delta.xy[2],delta.xy[1])))
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 r2evans
Solution 2