小技巧之两点间的旋转角度

计算两点间的旋转角度


方法1

原理

用正切函数 tanα = y / x, 正切函数定义域并非是R,所以需要特殊处理 pi/2+k(k为整数集合)


步骤

  1. 以point1为原点生成坐标系,
  2. 先处理坐标轴上的点
  3. 再处理各象限上的点

    实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
--[[
​ describe:
​ 获取point2相对于point1的夹角,
​ x轴正向为0度的,顺时针/逆时针 角度
​ [point1]: cc.p
​ 源点,默认(0, 0)
​ point2: cc.p
​ 目标点
​ [isClockWise]: boolean
​ 是否是顺时针,默认false
​ return: float
​ float - 角度
​ ]]
function getPointAngle(point1, point2, isClockWise)
​ point1 = point1 or {x = 0, y = 0}
​ isClockWise = isClockWise or false

if point2.y == point1.y then
if point2.x >= point1.x then
return 0
else
return 180
end
elseif point2.x == point1.x then
if point2.y > point1.y then
return isClockWise and 90 or 270
else
return isClockWise and 270 or 90
end
else
local dertaX, dertaY = point2.x - point1.x, point2.y - point1.y
local rad = math.atan(dertaY / dertaX)
local angle = math.deg(rad)

-- first quadrant
if point2.x > point1.x and point2.y > point1.y then
angle = isClockWise and angle or (360 - angle)

-- second quadrant
elseif point2.x < point1.x and point2.y > point1.y then
angle = isClockWise and (180 + angle) or (180 - angle)

-- third quadrant
elseif point2.x < point1.x and point2.y < point1.y then
angle = isClockWise and (180 + angle) or (180 - angle)

-- fourth quadrant
elseif point2.x > point1.x and point2.y < point1.y then
angle = isClockWise and (360 + angle) or (-angle)
end
return angle
end
end




方法2

原理

用反正切函数处理,反正切函数定义域为R,但是值域为(-pi/2, pi/2)

步骤

  1. 计算出角度, (-pi/2, pi/2)
  2. 求出实际角度

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
--[[
​ describe:
​ 获取point2相对于point1的夹角,
​ x轴正向为0度的,顺时针/逆时针 角度
​ [point1]: cc.p
​ 源点,默认(0, 0)
​ point2: cc.p
​ 目标点
​ [isClockWise]: boolean
​ 是否是顺时针,默认false
​ return: float
​ float - 角度
​ ]]
function getPointAngle(point1, point2, isClockWise)
​ point1 = point1 or {x = 0, y = 0}
​ isClockWise = isClockWise or false

local dertaX, dertaY = point2.x - point1.x, point2.y - point1.y
local rad = math.atan2(dertaY, dertaX)
local angle = math.deg(rad)
if not isClockWise then
​ angle = 360 - angle
​ angle = (angle >= 360) and (angle - 360) or angle
end

return angle
end