【问题标题】:Convert cartesian angles to polar / compass / cardinal angles in R?将笛卡尔角转换为R中的极坐标/罗盘/基角?
【发布时间】:2014-05-25 22:21:33
【问题描述】:

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

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

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

【问题讨论】:

  • 你在atan2(x,y)之后吗?
  • 我确实尝试过 atan2(),但它在左象限返回负角,因此仍需要转换为极坐标。

标签: r angle polar-coordinates cartesian-coordinates


【解决方案1】:
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

【讨论】:

  • 谢谢罗兰。这似乎完美无缺。我得稍微解构一下,因为我不熟悉一些复数符号。
  • 嗯,构造z 应该很明显,Arg 只是给出了极坐标的角度。
  • 是的,使用复数符号的漂亮而紧凑的解决方案,现在我明白了!还要注意必要的 90 度偏移以从北方返回方向。比我提出的解决方案要好得多。
【解决方案2】:

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

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

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

模运算符对于如何处理负数意见不一,所以为了安全起见,先加 360 以消除问题:N

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

【讨论】:

    【解决方案3】:

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

    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
    

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

    【讨论】:

      【解决方案4】:

      最近遇到了同样的问题

      这里的诀窍是使用:

      • 跟踪象限(符号)的函数 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
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-14
        • 1970-01-01
        相关资源
        最近更新 更多