2016-02-27 3 views
1

У меня возникают проблемы с вычислением углов по часовой стрелке между непрерывными двумерными векторами. Мои расчетные углы не кажутся правильными, когда я сравниваю их на глазу на сюжете. Ниже мой процесс в R.Углы между непрерывными 2D-векторами

При необходимости, установить и включить «круговой» пакет:

install.packages('circular') 
library(circular) 

Сформировать небольшой кадр данных 2D координаты:

functest <- data.frame(x=c(2,8,4,9,10,7),y=c(6,8,2,5,1,4)) 

земля точки для справки:

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) 

Создать функцию, которая вычисляет угол между двумя векторами:

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 
} 

Сформировать вектор углов компаса в градусах (вращение по часовой стрелке):

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 

Я подозреваю, что что-то неправильно, может быть, протекающие в моих последних трех строк кода, когда я пытаюсь преобразовать «нормальный» против часовой стрелки углов в радианах до углов компаса по часовой стрелке в градусах. Любая помощь будет принята с благодарностью!

ответ

1

Не знаете R, но видите, что вы вычисляете угол между векторами, используя скалярное произведение.

Обратите внимание, что приведенный угол не направлен - он не равен ни по часовой стрелке, ни против часовой стрелки (считайте, что скалярное произведение нечувствительно к векторному обмену).

Если вам действительно нужен направленный угол (угол, необходимый для поворота первого вектора, чтобы сделать его коллинеарны со второй), вы должны применять ArcTan2 (atan2) подход
(диапазон результата обычно -Pi..Pi)

Theta = ArcTan2(CrossProduct(v1,v2), DotProduct(v1,v2)) 
+0

Кроме того, 'acos()' имеет проблемы (точность и численная неустойчивость), когда угол близок к 0 или 180 градусов, а 'atan2 (,)' численно устойчив под любым углом. – comingstorm

0

Эта линия не имеет никакого смысла для меня:

dot.prod <- crossprod(m[, 1], m[, 2]) 

присваивается декартово произведение двух векторов переменной с именем скалярного произведения.

Я не читал остальную часть вашего кода, но это две разные вещи.

Точечный продукт производит скалярное значение; перекрестное произведение создает вектор, ортогональный двум другим.

Вы уверены, что ваше именование не отражает непонимание этих двух операций? Это может объяснить, почему у вас проблемы.

Вы можете получить угол между любыми двумя векторами, используя точечный продукт. Почему вы думаете, что вам нужно идти на все проблемы в этом методе?

Смежные вопросы