Reputation: 190
I'm having some trouble calculating the clockwise angles between continuous 2D vectors. My computed angles do not seem right when I compare them by eye on a plot. What follows is my process in R.
If necessary, install and enable the "circular" package:
install.packages('circular')
library(circular)
Generate a small data frame of 2D coordinates:
functest <- data.frame(x=c(2,8,4,9,10,7),y=c(6,8,2,5,1,4))
Plot the points for reference:
windows(height=8,width=8)
par(pty="s")
plot(functest, main = "Circular Functions Test")
## draw arrows from point to point :
s <- seq(length(functest$x)-1) # one shorter than data
arrows(functest$x[s], functest$y[s], functest$x[s+1], functest$y[s+1], col = 1:3)
Create a function that computes the angle between two vectors:
angle <- function(m)
{ # m is a matrix
dot.prod <- crossprod(m[, 1], m[, 2])
norm.x <- norm(m[, 1], type="2")
norm.y <- norm(m[, 2], type="2")
theta <- acos(dot.prod / (norm.x * norm.y))
as.numeric(theta) # returns the angle in radians
}
Generate a vector of compass angles in degrees (clockwise rotation):
functest_matrix <- cbind(x = functest$x,y = functest$y)
moves <- apply(functest_matrix, 2, diff)
tst <- lapply(seq(nrow(moves) - 1), function(idx) moves[c(idx, idx + 1), ])
functest_angles <- vapply(tst, angle, numeric(1))
functest_object <- circular(functest_angles, type="angles", units="radians", zero=0, rotation = "counter")
functest_convert <- conversion.circular(functest_object, type = "angles", units = "degrees", rotation = "clock", zero = pi/2)
functest_compass <- lapply(functest_convert, function(x) {if (x < 0) x+360 else x}) # converts any negative rotations to positive
I suspect something wrong may be occuring in my last three lines of code when I try to convert "normal" counterclockwise angles in radians to clockwise compass angles in degrees. Any help would be greatly appreciated!
Upvotes: 1
Views: 539
Reputation: 308908
This line makes no sense to me:
dot.prod <- crossprod(m[, 1], m[, 2])
You assign the cross product of two vectors to a variable named dot product.
I didn't read the rest of your code, but those are two very different things.
The dot product produces a scalar value; the cross product produces a vector orthogonal to the other two.
Are you sure your naming doesn't reflect a misunderstanding of those two operations? It might explain why you're having trouble.
You can get the angle between any two vectors using the dot product. Why do you think you need to go to all the trouble in that method?
Upvotes: 0
Reputation: 80232
Don't know R but see that you calculate angle between vectors using scalar product.
Note that resulted angle is not directed - it is neither clockwise, nor counterclockwise (consider that scalar product is insensitive to vector exchange).
If you really need directed angle (the angle needed to rotate the first vector to make it collinear with the second one), you have to apply ArcTan2
(atan2
) approach
(result range usually is -Pi..Pi
)
Theta = ArcTan2(CrossProduct(v1,v2), DotProduct(v1,v2))
Upvotes: 1