【问题标题】:How do I easily convert a line angle to a navigational-bearing scale (i.e., with range of [0,360) and "North" = 0 deg)?如何轻松地将线角转换为导航方位角(即范围为 [0,360)和“北”= 0 度)?
【发布时间】:2015-08-05 17:15:25
【问题描述】:

我有两点,(x1,y1)(x2,y2),我想在它们之间划一条线。我知道我可以使用反正切和斜率计算出那条线的角度(以度为单位):

atan((y2-y1)/(x2-x1))*180/pi

但是,如何将此角度转换为 [0,360] 比例?基本上,我希望我的角度处于罗盘刻度上,其中“北”为 0 度,“东”为 90 度,“南”为 180 度,“西”为 270 度。

谢谢!

【问题讨论】:

  • 顺便说一下我用的是r

标签: r trigonometry angle


【解决方案1】:
(450-atan2(y2-y1,x2-x1)*180/pi)%%360​​​​​​​​​​​​​​​

segmentToAngle <- function(x1,y1,x2,y2) atan2(y2-y1,x2-x1)*180/pi;
segmentToAngle(0,0,1,0); ## east
## [1] 0
segmentToAngle(0,0,0,1); ## north
## [1] 90
segmentToAngle(0,0,-1,0); ## west
## [1] 180
segmentToAngle(0,0,0,-1); ## south
## [1] -90
segmentToCompassAngle <- function(x1,y1,x2,y2) (450-segmentToAngle(x1,y1,x2,y2))%%360;
segmentToCompassAngle(0,0,1,0); ## east
## [1] 90
segmentToCompassAngle(0,0,0,1); ## north
## [1] 0
segmentToCompassAngle(0,0,-1,0); ## west
## [1] 270
segmentToCompassAngle(0,0,0,-1); ## south
## [1] 180

【讨论】:

  • 我不明白你的符号。你能解释一下这是什么意思吗?还有,为什么是 450??
  • (1) 什么符号?这都是 R 代码,您可以通过复制并粘贴到 R 会话中来自己运行它。我还将每行代码的输出作为注释包括在内。 (2) 不必是 450,因为我们在减法之后立即修改 360;它必须是 90 加上 360 的倍数。这只是执行此转换所需的算术。减法反转增加角度的方向并将北设置为 0°,并且 mod 360 强制结果为 [0,360)。
  • 你叫 %% "mod"?我不知道 %% 是做什么的。
  • %%modulus operation 的 R 令牌。
  • 对于任何整数 n,被减数必须是 90+360 n。我没有特别的原因使用 450 = 90+360(1),你发现 90 = 90+360(0) 也可以。但无论您使用什么 n,结果总是相同的。这里起作用的一般原则是 a mod m = (a + nm) mod m 表示任意整数 n
【解决方案2】:

只是概括@bgoldst 的答案:

(A1 - atan2(y2-y1,x2-x1) * 180/pi ) %%360

以下是对这个等式各个部分的解释:

  1. 您必须使用atan2() 而不是atan()

    atan2() 是具有两个参数的反正切函数。使用两个参数的目的是收集有关输入符号的信息,以便返回计算角度的适当象限。这对于单参数反正切 (atan) 函数是不可能的。

  2. 在这种情况下,模数运算符%% 用于给出角度除以 360 的余数。这样,​​我们强制角度在 360 处“环绕”。

  3. 使用atan2 计算的角度乘以180/pi,以便将答案从弧度(atan2 的默认输出)转换为度数。

  4. 如果我们停在那里,生成的角度将基于标准三角函数形式,其中“东”= 0 度。所有角度都相对于“东”= 0。

    通过从某个角度 (A1) 中减去我们计算的角度(以度为单位),我们可以将计算的角度偏移 A1 度。对于导航方位角(“北”= 0 度),我们将设置A1 = 90

     (90 - atan2(y2-y1,x2-x1) * 180/pi ) %%360
    

【讨论】:

  • 正如@bgoldst 指出的那样,A1 = 90 + 360 * any_integer 将具有与设置A1=90 相同的效果。这是%%360 操作的结果。
【解决方案3】:

对于“北”0 度。 “东”90度。 “南”180度。和“西”270度。

你可以使用公式:

f(E,N)=180-90*(1+sign(N))* (1-sign(E)^2)-45*(2+sign(N))*sign(E)

     -180/pi()*sign(E*N)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))

      E=E2-E1 and  N=N2-N1

【讨论】:

    【解决方案4】:

    我不想抹黑这里以数学为中心的讨论。但是,您说的是导航方位。据我推测,您的重点是导航 := 应用数学来完成导航任务(我的个人定义)。

    “geosphere 包”将在这方面为您提供很多帮助。它提供了一组地理/导航功能(用于球面计算)。要从一个点 p1 移动到另一个点 p2,函数 'geosphere::bearing()' 或 'geosphere::bearingRhumb()' 将为您提供以度数表示的方位角方向,即 -180 ... +180。 您可以在answer to this related question 中找到更多解释。

    正如@theforestecologist 所指出的那样,以下将使用模数方法来确定超出整圆(即 360 度)的任何角度数学的余数。 模运算符为您提供模基础之上的其余部分(在我们的例子中为 360)。这解决了方位角的负号问题。例如

    • -90 + 360 = 270 ==> 270 %% 360 := (0 * 360) + 270 = 270
    • 30 + 360 = 30 ==> 30 %% 360 := (0 * 360) + 30 = 30
    • 对于数学纯粹主义者重新取模,可以添加任意数量的完整圆圈,例如2* 360 度 = 720。这将产生:-30 + 720 = 690 ==> 690 %% 360 := (1 * 360) + 330 = 330

    在 R/RStudio 中使用以下内容并加载 geosherepackage。请注意,geosphere 包使用 x-y 位置概念,即经度在纬度之前,而不是经纬度之前的导航实践(例如 43N 3E)!

    brg <- geosphere::bearing(c(p1_lon, p1_lat), c(p2_lon, p2_lat))
    crs <- (brg + 360) %% 360  # to generate 0...360 courses
    

    注意 2:如果您使用多个点对点关系。使用 cbind() 将它们重新编码为矩阵:

    brg <- geosphere::bearing(cbind(p1_lon, p1_lat), cbind(p2_lon, p2_lat))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多