如何计算三点之间的符号角

How to calculate signed angles between 3 points

我在计算 3 个点之间的角度符号时遇到问题。我的数据框的头部看起来像这样:

        x       y       z
6554 158.485 170.917 177.917
6228 159.138 171.466 179.099
6698 159.088 170.504 180.273
1833 157.945 169.852 180.449
1875 157.720 168.950 181.571
1893 156.800 167.829 181.119

我做了一个循环,使用 a.b = |a|*|b|*cos(alpha) 来计算它们之间的角度。不幸的是,我无法得到符号,因为 acos 函数只会从 [0,pi] 区间给我答案。这是我的循环:

  for(kh in 1:nrow(CA_list)) {
  CA_list[kh,4] <- CA_list[kh,1]-CA_list[kh+1,1]
  CA_list[kh,5] <- CA_list[kh,2]-CA_list[kh+1,2]
  CA_list[kh,6] <- CA_list[kh,3]-CA_list[kh+1,3]
}

colnames(CA_list)[4] <- "vecx"
colnames(CA_list)[5] <- "vecy"
colnames(CA_list)[6] <- "vecz"

CA_list$abs <- sqrt(CA_list$vecx^2+CA_list$vecy^2+CA_list$vecz^2)

for(kg in 1:nrow(CA_list)) {
  CA_list[kg,8] <- CA_list[kg,4]*CA_list[kg+1,4]+CA_list[kg,5]*CA_list[kg+1,5]+CA_list[kg,6]*CA_list[kg+1,6]
  CA_list[kg,9] <- CA_list[kg,7]*CA_list[kg+1,7]
}

colnames(CA_list)[8] <- "LHS"
colnames(CA_list)[9] <- "RHS"

CA_list$angles <- acos(CA_list$LHS/CA_list$RHS)

数据框将如下所示:

           x       y       z   vecx   vecy   vecz      abs      LHS      RHS   angles
6554 158.485 170.917 177.917 -0.653 -0.549 -1.182 1.457715 0.826880 2.213722 68.06684
6228 159.138 171.466 179.099  0.050  0.962 -1.174 1.518624 0.890998 2.016130 63.77260
6698 159.088 170.504 180.273  1.143  0.652 -0.176 1.327603 1.042751 1.934437 57.38127
1833 157.945 169.852 180.449  0.225  0.902 -1.122 1.457091 0.710998 2.213313 71.26225
1875 157.720 168.950 181.571  0.920  1.121  0.452 1.518995 0.884453 2.016499 63.98489
1893 156.800 167.829 181.119 -0.401  1.233 -0.285 1.327522 1.067264 1.932921 56.48529

现在我想用一些可以计算角度符号的函数来完成我的循环。对我来说最简单的方法是什么?

两个二维向量uv之间的符号角可以借助atan2函数获得:

angle_unsigned <- function(u, v){
  acos( sum(u*v) / ( sqrt(sum(u*u)) * sqrt(sum(v*v)) ) )
}

angle_signed <- function(u, v){
  atan2(v[2], v[1]) - atan2(u[2], u[1]) 
}

编辑

在 3D 中,您需要有一个 方向,由向量 n 表示。 returns 下面的 angle3D_signed 函数 [0,2pi[ 中向量 u 必须逆时针旋转的角度, 从 [=15= 定义的方向看],达到向量v.

crossProduct <- function(v, w){ 
  c(
    v[2] * w[3] - v[3] * w[2], 
    v[3] * w[1] - v[1] * w[3], 
    v[1] * w[2] - v[2] * w[1]
  )
}

angle3D_signed <- function(n, u, v){
  n <- n / sqrt(sum(n*n)) # normalize n
  unorm <- sqrt(sum(u*u))
  vnorm <- sqrt(sum(v*v))
  s <- sum(crossProduct(n, u) * v) # "unnormalized sine"
  cosAngle <- sum(u*v) / unorm / vnorm
  ifelse(s >= 0, acos(cosAngle), 2*pi - acos(cosAngle))
}