How do I easily convert a line angle to a navigational-bearing scale (i.e., with range of [0,360) and “North” = 0 deg)?

混江龙づ霸主 提交于 2020-01-02 11:02:18

问题


I have two points, (x1,y1) and (x2,y2), that I'd like to draw a line between. I know I can figure out the angle (in degrees) of that line using arctangent and the slope:

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

However, how would I convert this angle to a [0,360] scale? Basically, I want my angle to be on a compass scale in which "North" is 0 deg, "East" is 90 deg, "South" is 180 deg, and "West" is 270 deg.

Thanks!


回答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



回答2:


Just to generalize @bgoldst's answer:

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

Here is the explanation of the various parts of this equation:

  1. You have to use atan2() instead of atan().

    atan2() is the arctangent function with two arguments. The purpose of using two arguments is to gather information on the signs of the inputs in order to return the appropriate quadrant of the computed angle. This is not possible for the single-argument arctangent (atan) function.

  2. The modulus operator %% is used in this case to give the remainder of dividing the angle by 360. In this way, we force the angles to "wrap around" at 360.

  3. The angle calculated using atan2 is multiplied by 180/pi in order to convert the answer from radians (atan2's default output) into degrees.

  4. If we stopped there, the resulting angle would be based on standard trigonometric form in which "East" = 0 degrees. All angles would be relative to "East" = 0.

    By subtracting our calculated angle in degrees from some angle (A1), we can offset the calculated angle by A1 degrees. In the case of the navigational-bearing scale (with "North" = 0 degrees) we would set A1 = 90.

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



回答3:


For "North" 0 deg. "East" 90 deg. "South" 180 deg. and "West" 270 deg.

you can use the formula:

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:


I do not want to discredit the math-focussed discussion here. However, you are speaking about a navigational bearing. From that I assume, your focus is on navigating := applying math to get a navigational task done (my personal definition).

The 'geosphere package' will help you a lot in this area. It offers a set of geo / nav functions (for spherical calculations). To move from one point p1 to another p2, the functions 'geosphere::bearing()' or 'geosphere::bearingRhumb()' will give you the azimuth direction expressed in degrees, i.e. -180 ... +180. You can find a bit of more explanation in the answer to this related question.

As also flagged by @theforestecologist, the following will do the trick using the modulo approach to determine the rest of any angle math beyond a full circle, i.e. 360 degrees. The modulo operator gives you the rest on top of the modulo basis (in our case 360). This solves the negative sign issue for the azimuth. For example

  • -90 + 360 = 270 ==> 270 %% 360 := (0 * 360) + 270 = 270
  • 30 + 360 = 30 ==> 30 %% 360 := (0 * 360) + 30 = 30
  • for math-purists re the modulo, any number of full circles can be added, e.g. 2* 360 degrees = 720. This will yield: -30 + 720 = 690 ==> 690 %% 360 := (1 * 360) + 330 = 330

Use the following in R/RStudio with the geosherepackage loaded. Please note that the geosphere package uses x-y position concept, i.e. longitude before latitude, rather than the navigational practice of latitude-before-longitude (e.g. 43N 3E)!

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

Note 2: if you work with multiple point-to-point relationships. Recode them as matrices using cbind():

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


来源:https://stackoverflow.com/questions/31838855/how-do-i-easily-convert-a-line-angle-to-a-navigational-bearing-scale-i-e-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!