需要数学问题的帮助: 我需要使用x和y坐标从0度获得真正的角度 我现在正在使用这个:
Math.atan((x2-x1)/(y1-y2))/(Math.PI/180)
但/(Math.PI/180)
将结果限制在-90到90之间
我需要0-360
注意:我正在使用角度来指示方向:
答案 0 :(得分:33)
atan函数只给出-pi / 2和+ pi / 2之间的单位圆的一半(x轴上为0),还有另一个库函数可以给出-pi和+ pi之间的整个单位圆,atan2 < / p>
我认为你最好使用atan2来获得正确的象限而不是自己分支,然后像你一样扩展,比如
Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI + 180
在pi上乘以180就是在问题中从弧度到度数的比例(但是通过简化划分除以),+180确保它始终为正,即0-360度而不是-180到180度
答案 1 :(得分:11)
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,9度是向上(x = 0,y> 0)135度是向上和向左(y> 0,x = -y)等。你的x轴和y轴指向?
答案 2 :(得分:2)
@ 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
使用模运算可能会有更简洁的解决方案,但我找不到它。
答案 3 :(得分:1)
另请注意:
if (y1==y2) {
if (x1>x2)
angle = 90;
else if (x1<x2)
angle = 270;
else
angle = 0;
}
答案 4 :(得分:1)
这里有两种解决方案,一种是使用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))
})
答案 5 :(得分:0)
这应该可以解决问题:
示例:
(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 :(得分:0)
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 :(得分:0)
对于0 =向上,90 =向右,180 =向下,270 =向左等(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)))
答案 8 :(得分:0)
所以只有一个决定(我希望这个丑陋的基本符号能解释它):
如果x = 0,然后
360度= 270-(SIGN(x)+1)* 90
ELSE
360度= MOD(180 +(SIGN(y)+1)* 90 + ATAN(x / y),360)
ENDIF
沿顺时针方向从北0度到360度画一个完整的圆:
x = SIN(0to360)y = COS(0to360)
欢呼,列夫
答案 9 :(得分:-2)
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;
}
}