2

这是一个我与它斗争了一段时间但找不到好的答案的问题。我最终确实在 R 中解决了它,但我想无论如何我都会发布它以防其他人需要它。如果有人有更优雅的解决方案,我很乐意看到它。这是一种蛮力的努力。

我有一系列成对的 XY(笛卡尔)坐标。我可以使用简单的 atan() 命令轻松获得它们之间的角度。但是,我想要指南针(极地?基数?)方向(北=0°,东=90°,等等)的角度。这是制作数据和笛卡尔角度的最小示例,我在下面发布了我的蛮力转换为罗盘角度。度数转换(从弧度)使用“圆形”包中的 deg()。

require(circular)
test <- data.frame(x=c(0,1,1,1,0,-1,-1,-1),y=c(1,1,0,-1,-1,-1,0,1))
test$angle <- deg(atan(test$y/test$x))
test

...产生

   x  y angle
1  0  1    90
2  1  1    45
3  1  0     0
4  1 -1   -45
5  0 -1   -90
6 -1 -1    45
7 -1  0     0
8 -1  1   -45

请注意,进入左下和左上象限的角度与进入右下和右上象限的角度相同,失去了向量的方向性。

4

4 回答 4

3
ang <- function(x,y) { 
  z <- x + 1i * y
  res <- 90 - Arg(z) / pi * 180
  res %% 360
}

ang(test$x, test$y)
#[1]   0  45  90 135 180 225 270 315
于 2014-04-11T17:23:18.827 回答
2

它都是线性的。有两个难点:增加角度的方向在笛卡尔系统中是CCW,在导航系统中是CW,0°笛卡尔在海图上是90°。我们可以通过改变符号来解决第一个问题:N <= -C。

现在 0 映射到 0。我们希望 0 映射到 90,所以只需添加 90:N <= -C + 90。

但是,哎呀,这给了我们一些超出通常范围 0-360 的角度。但是,角度重复 mod 360,所以我们可以很容易地解决这个问题:N <= -c + 90 modulo 360。

模运算符对于如何处理负数意见不一,所以为了安全起见,先加 360 以消除问题:N <= (-C + 90 + 360) 模 360。

在 Excel 中,MOD(450 - C, 360) 或在 javascript 中,((450 - C)) % 360。恐怕我不知道 R。[但在 Fortran IV 中,它将是 FN = mod(450.0 - C, 360.0)]

于 2018-04-29T21:37:46.977 回答
1

首先,通过减去 90 度来改变代码的角度线(感谢 JK),可以轻松地移动角度以测量 y 轴(或 North=0):

test$angle <- 90-deg(atan(test$y/test$x))

但是,需要保持左边界向量的转换,因此我的解决方案是根据 X 和 Y 值的符号对这些角度进行调整:

# Make new column for the polar/compass angles
test$polar <- test$angle
# Then make the necessary adjustments
# Adjustment for quadrant C (bottom left, 180 to 270°)
test[sign(test$x)==-1 & sign(test$y)==-1,"polar"] <- ((1-(test[sign(test$x)==-1 & sign(test$y)==-1,"angle"]/90))*90)+180
# Adjustment for quadrant D (top left, 270 to 360°)
test[sign(test$x)==-1 & sign(test$y)>=0, "polar"] <- abs(test[sign(test$x)==-1 & sign(test$y)>=0,"angle"])+180

...生产:

   x  y angle polar
1  0  1     0     0
2  1  1    45    45
3  1  0    90    90
4  1 -1   135   135
5  0 -1   180   180
6 -1 -1    45   225
7 -1  0    90   270
8 -1  1   135   315

同样,我将其发布为一个可行的解决方案,但更优雅或更简单的建议也将不胜感激!

于 2014-04-11T16:34:58.750 回答
0

最近我遇到了同样的问题

这里的诀窍是使用:

  • 跟踪象限(符号)的函数 atan2()
  • 运算符(函数)模 %%

这是我可重现的例子

x <- c(1, 1, 0, -1, -1, -1,  0,  1)
y <- c(0, 1, 1,  1,  0, -1, -1, -1)

mydf<- data.frame(x,y)

mydf$radians<-with(mydf, atan2(y,x))

# define a function for calculation of degrees from radians
rad2deg <- function(rad) {(rad * 180) / (pi)}

mydf$deg_cartesian<-rad2deg(mydf$radians)

# here calculating the modulus by 450 mod degrees
# 450 = 360+90. i.e. shifting by 90 degrees
mydf$deg_compass<-with(mydf,(450-deg_cartesian)%%360)

mydf

作为后续和未来的记忆发布(尤其是我的!)

于 2021-11-21T17:36:09.977 回答