【问题标题】:finding angles 0-360寻找角度 0-360
【发布时间】:2009-11-10 11:03:39
【问题描述】:

在数学问题上需要帮助: 我需要使用 x 和 y 坐标从 0 度获得真实角度 我现在正在使用这个:

Math.atan((x2-x1)/(y1-y2))/(Math.PI/180)

/(Math.PI/180) 将结果限制在 -90 到 90 我需要 0-360

注意:我用角度来表示方向:

  • 0=向上
  • 90=正确
  • 135=45 度右+下
  • 180=下
  • 270=左

【问题讨论】:

    标签: javascript


    【解决方案1】:

    atan 函数只给出 -pi/2 和 +pi/2 之间的一半单位圆(x 轴上的 0),还有另一个库函数可以给出 -pi 和 + pi 之间的整个单位圆,atan2

    我认为您最好使用 atan2 来获得正确的象限,而不是自己分支,然后像以前一样扩展,例如

    Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI + 180
    

    在 pi 上乘以 180 只是问题中从弧度到度数的比例(但除以简化的除法),+180 确保其始终为正,即 0-360 度而不是 -180 到180度

    【讨论】:

    【解决方案2】:

    Math.atan 将您限制在单位圆上最右边的两个象限内。要获得完整的 0-360 度:

    if x < 0 add 180 to the angle
    else if y < 0 add 360 to the angle. 
    

    您的坐标系与我的相比(与惯例相比)是旋转和倒置的。正 x 向右,正 y 向上。 0 度向右 (x>0, y=0, 90 度向上 (x=0,y>0) 135 度向上和向左 (y>0, x=-y) 等等。你的 x 轴和 y 轴指向吗?

    【讨论】:

    • 这样? var add=0 var x=x2-x1 var y=y2-y1 if(x
    • 更正:var add=0 var x=x2-x1 var y=y2-y1 if(x
    • 不,除以 (pi/180) 后加上数字,否则 add 应该是 math.PI 而不是 180 和 2*Math.PI 而不是 360
    【解决方案3】:

    @jilles de wit 和 @jk 的答案。引导我走上了正确的道路,但由于某种原因没有为我认为与原始问题非常相似的问题提供正确的解决方案。

    我想起床 = 0°,右 = 90°,下 = 180°,左 = 270°,就像在航空导航系统中一样。

    假设问题是指画布绘图,我达到了这个解决方案:

    我首先使用ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2) 翻译了画布原点。我还将从画布上的鼠标事件中获得的 e.offsetX 和 e.offsedY 减半,以获得与画布具有相同坐标系的 x 和 y。

    let radianAngle = Math.atan2(y, x);    // x has the range [-canvas.width/2 ... +canvas.width/2], y is similar
    let northUpAngle = radianAngle * 180 / PI + 90;    // convert to degrees and add 90 to shift the angle counterclockwise from it's default "left" = 0°
    if (x < 0 && y < 0) {    // check for the top left quadrant
        northUpAngle += 360;    // add 360 to convert the range of the quadrant from [-90...0] to [270...360] (actual ranges may vary due to the way atan2 handles quadrant boundaries)
    }
    northUpAngle.toFixed(2)    // to avoid getting 360° near the "up" position
    

    使用模运算可能有更简洁的解决方案,但我找不到。

    【讨论】:

    • 不是加 90,而是加 450,然后使用模数:(Math.atan2(y, x) * 180 / Math.PI + 450) % 360
    • 为什么向上=0°?不应该是0°吗?我在基于矢量的坐标系中工作
    • @JasonFB 我正在创建一个交互式航向仪表,所以我想显示角度值。旋转坐标系来实现这一点。
    • 对对对。我只是问是否有不同的领域/部门在旋转坐标系? (我认为 0° = 'to the right' 是标准的,直到我遇到其他人将它实现为 0° ='to the top')
    【解决方案4】:

    另请注意:

    if (y1==y2) {
        if (x1>x2)
            angle = 90;
        else if (x1<x2)
            angle = 270;
        else
            angle = 0;
    }
    

    【讨论】:

      【解决方案5】:

      这应该可以解决问题:

      1. 如果 y2
      2. 如果

      例子:

      (x1,y1) = 0

      (x2,y2) = (-1,1), atan() = -45, [add 360], 270
      (x2,y2) = (1,1), atan() = 45
      (x2,y2) = (1,-1), atan() = -45, [add 180], 135
      (x2 ,y2) = (-1,-1), atan() = 45, [add 180], 225
      

      【讨论】:

        【解决方案6】:
        angle = Math.atan(this.k) * 180 / Math.PI;
        angle = 180 - (angle < 0 ? 180 + angle : angle);
        angle = p2.Y > p1.Y || (p2.Y == p1.Y && p2.X > p1.X) ? 180 + angle : angle;
        

        【讨论】:

          【解决方案7】:

          这里有两个解决方案,一个是 Math.atan(它需要一个分数相反/相邻),一个是 Math.atan2(它需要两个参数)

          具有讽刺意味的是,解决方案是用 ES6 (ES2015+) 语法编写的,因为这个问题早于这个 javascript。

          请注意,“向右”为 0°(=0 弧度);向上为 90° (= PI/2);左为 180° (PI),下为 270° (PI*1.5)

          angleGivenCoords(coord1,coord2) {
              // given two coords {x,y}, calculate the angle in radians with
              // right being 0° (0 radians)
          
              if (coord1.x === coord2.x) return (coord1.y > coord2.y ? Math.PI * 0.5 : Math.PI * 1.5)
              if (coord1.y === coord2.y) return (coord1.x > coord2.x ? Math.PI : 0 )
          
              let opposite = coord2.x - coord1.x
              let adjacent = coord1.y - coord2.y
              let adjustor = ((coord2.x < coord1.x && coord2.y < coord1.y) || (coord2.x < coord1.x && coord2.y > coord1.y)) ?  Math.PI : 0
          
              let res = Math.atan(opposite/adjacent) + adjustor
          
              if (res < 0) { res = res + Math.PI*2  }
              return res ;
            }
          

          现在使用 Math.atan2。请注意,使用此解决方案不需要顶部的保护子句 (coord1.x === coord2.x, (coord1.y === coord2.y))

            angleGivenCoords(coord1,coord2) {
              // given two coords {x,y}, calculate the angle in radians with
              // left being 0° (0 radians)
              let opposite = coord2.x - coord1.x
              let adjacent = coord1.y - coord2.y
              let res = Math.atan2(adjacent, opposite)
              if (res < 0) { res = res + Math.PI*2  }
              return res ;
            }
          

          (我试图保留“相反”和“相邻”变量名以尊重三角函数)

          请注意,这是我用 Jest 编写的测试套件。还要注意我上面的函数返回弧度,我的代码(这里没有显示)有一个简单的 Trig.degreesToRadians() 正如你所期望的那样

           it('for right 0°', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 600, y: 500}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(0))
            })
          
          
            it('for up-right 45°', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 600, y: 400}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(45))
            })
          
            it('for 90° up', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 500, y: 400}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(90))
            })
          
          
            it('for 135° up to left', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 400, y: 400}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(135))
            })
          
            it('for 180° to left', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 400, y: 500}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(180))
            })
          
          
            it('for 225° to to bottom left', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 400, y: 600}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(225))
            })
          
            it('for 270° to the bottom', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 500, y: 600}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(270))
            })
          
            it('for 315° to the bottom', () => {
              let coord1 = {x: 500, y: 500},
                coord2 = {x: 600, y: 600}
              expect(Trig.angleGivenCoords(coord1,coord2)).toEqual(Trig.degreesToRadians(315))
            })
          

          【讨论】:

          • 我认为正确的术语可能是“轨迹”而不是“角度”
          【解决方案8】:

          对于 0=up,90=right,180=down,270=left 等 (x=x2-x1,y=y2-y1)

          你可以使用公式:

          f(x,y)=180-90*(1+sign(y))* (1-sign(x^2))-45*(2+sign(y))*sign(x)
          
          -(180/pi())*sign(x*y)*atan((abs(y)-abs(x))/(abs(y)+abs(x)))
          

          【讨论】:

            【解决方案9】:

            所以只有一个决定(我希望这个丑陋的基本符号可以解释它):

            如果 x = 0 那么

            360 度 = 270 - (SIGN(x) + 1) * 90

            否则

            360 度 = MOD(180 + (SIGN(y) + 1) * 90 + ATAN(x/y) , 360)

            ENDIF

            从北 0 度到 360 度顺时针画一个完整的圆:

            x=SIN(0to360) y=COS(0to360)

            干杯,列夫

            【讨论】:

              【解决方案10】:
              function angle(x1,y1,x2,y2)
              {
              eangle = Math.atan((x2-x1)/(y1-y2))/(Math.PI/180)
              if ( angle > 0 )
              {
                if (y1 < y2)
                  return angle;
                else
                  return 180 + angle;
              } else {
                if (x1 < x2)
                  return 180 + angle;
                else
                  return 360 + angle;
              }
              }
              

              【讨论】:

              • 尽管被否决,但这个解决方案解决了象限问题
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多