Search code examples
rfunctionvectordistanceangle

Creating R function to find both distance and angle between two points


I am trying to create or find a function that calculates the distance and angle between two points, the idea is that I can have two data.frames with x, y coordinates as follows:

Example dataset

From <- data.frame(x = c(0.5,1, 4, 0), y = c(1.5,1, 1, 0))

To <- data.frame(x =c(3, 0, 5, 1), y =c(3, 0, 6, 1))

Current function

For now, I've managed to develop the distance part using Pythagoras:

distance <- function(from, to){
  D <- sqrt((abs(from[,1]-to[,1])^2) + (abs(from[,2]-to[,2])^2))
  return(D)
}

Which works fine:

distance(from = From, to = To)


[1] 2.915476 1.414214 5.099020 1.414214

but I can't figure out how to get the angle part.

What I tried so far:

I tried adapting the second solution of this question

angle <- function(x,y){
  dot.prod <- x%*%y 
  norm.x <- norm(x,type="2")
  norm.y <- norm(y,type="2")
  theta <- acos(dot.prod / (norm.x * norm.y))
  as.numeric(theta)
}

x <- as.matrix(c(From[,1],To[,1]))
y <- as.matrix(c(From[,2],To[,2]))
angle(t(x),y)

But I am clearly making a mess of it

Desired output

I would like having the angle part of the function added to my first function, where I get both the distance and angle between the from and to dataframes


Solution

  • By angle between two points, I am assuming you mean angle between two vectors defined by endpoints (and assuming the start is the origin).

    The example you used was designed around only a single pair of points, with the transpose used only on this principle. It is however robust enough to work in more than 2 dimensions.

    Your function should be vectorised as your distance function is, as it is expecting a number of pairs of points (and we are only considering 2 dimensional points).

    angle <- function(from,to){
        dot.prods <- from$x*to$x + from$y*to$y
        norms.x <- distance(from = `[<-`(from,,,0), to = from)
        norms.y <- distance(from = `[<-`(to,,,0), to = to)
        thetas <- acos(dot.prods / (norms.x * norms.y))
        as.numeric(thetas)
    }
    
    angle(from=From,to=To)
    [1] 0.4636476       NaN 0.6310794       NaN
    

    The NaNs are due to you having zero-length vectors.