符号&公式
符号 | 意义 |
---|---|
α |
角度 |
rad |
弧度 |
k |
斜率 |
x | 点的x轴坐标 |
y | 点的y轴坐标 |
- 角度与弧度的关系公式:
α=(rad*180)/π
- 直线斜率
k=(y2-y1)/(x2-x1)
- 正切
tan(α)=|k₁-k₂/(1+k₁k₂)|
反切函数
无论计算角度还是弧度,始终绕不开的就是正切函数tanα
三角函数中,正切 tanA = a / b= tanθ = y / x
以typescript
为例,提供两个反切函数atan()
和atan2()
用于返回夹角的弧度值,进而得到角度。
atan | atan2 | |
---|---|---|
入参 | 斜率k | y坐标(对边边长)和x坐标(邻边边长) |
值域 | (-π/2, π/2) |
(-π, π) |
返回值 | 弧度值 | 弧度值 |
了解公式和对比两个反切函数后,我们可以得出结论:
- 实际场景中
atan2
更符合需求,且计算更方便 - 两点确定一条直线。因此根据两点就确定,直线与
x轴正方向夹角
的弧度值,进而计算角度。 - 两条直线的夹角。我们可以分别计算他们
交点的x轴正方向夹角
的弧度值,然后相减即可。
实战
Cocos画圆弧
:屏幕上取三个点p1,p2,p3
;p1
作为圆心,p1p2
,p1p3
的较短的作为半径,p1p2
,p1p3
圆弧的两边。
dealArc() {
if (this._points.length < 3) return;
const ponits = this._points.slice(this._points.length - 3, this._points.length);
//辅助线
this.drawGuideLine(ponits[0], ponits[1]);
this.drawGuideLine(ponits[0], ponits[2]);
//第1个点到第2个点到距离为半径
const r1 = ponits[0].sub(ponits[1]).mag();
//第1个点到第3个点到距离为半径
const r2 = ponits[0].sub(ponits[2]).mag();
//选小的作为半径
const r = r1 > r2 ? r2 : r1;
const sAngle = LineUtils.getXRadian(ponits[0], ponits[1]);
const eAngle = LineUtils.getXRadian(ponits[0], ponits[2]);
CC_DEBUG && cc.log("GraphicsView " + sAngle + " " + eAngle);
CC_DEBUG &&
cc.log(
"GraphicsView " +
LineUtils.getXAngle(ponits[0], ponits[1]) +
" " +
LineUtils.getXAngle(ponits[0], ponits[2])
);
this.drawArc(ponits[0], r, sAngle, eAngle, false);
}
drawArc(
point: cc.Vec2,
r: number,
sAngle: number,
eAngle: number,
counterclockwise: boolean,
lineWidth: number = this.lineWidth,
lineClolor: cc.Color = this.lineClolor
) {
this.graphics.lineWidth = lineWidth;
this.graphics.strokeColor = lineClolor;
this.graphics.arc(point.x, point.y, r, sAngle, eAngle, counterclockwise);
this.graphics.stroke();
}
export namespace LineUtils {
//两个点计算与X轴正方向的夹角
export function getXAngle(point1: cc.Vec2, point2: cc.Vec2) {
//const k = Math.abs((point2.y - point1.y) / (point2.x - point1.x));
const angle = (Math.atan2(point2.y - point1.y, point2.x - point1.x) * 180) / Math.PI;
return angle > 0 ? angle : 360 + angle;
}
//两个点计算与X轴正方向的弧度
export function getXRadian(point1: cc.Vec2, point2: cc.Vec2) {
return (getXAngle(point1, point2) / 180) * Math.PI;
}
}
参考
https://blog.csdn.net/qq_43413788/article/details/108247240
https://www.jianshu.com/p/7c6a4f3021a1