-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtorus_calculations.py
89 lines (73 loc) · 2.6 KB
/
torus_calculations.py
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import math
from common.point import Point
from calculations import solve_quadratic
def intersect_circle_line(radius, dx, angle, dy):
'''Find the point where a circle intersects a line.
The circle is centered at (dx, 0) and has radius 'radius'.
The line has slope 'angle' in radians, and y-intercept dy.
Returns a Point(x, y) where x is non-negative.
'''
# The circle's equation is (x - dx)^2 + y^2 = radius^2
#
# The line's equation is y = tan(angle) * x + dy
#
# Substitute:
# (x - dx)^2 + (tan(angle) * x + dy)^2 = radius^2
# x^2 - 2*dx*x + dx^2 +
# (tan(angle) * x)^2 + 2 * tan(angle) * dy * x + dy^2 =
# radius^2
# x^2 - 2*dx*x + dx^2 +
# tan(angle)^2 * x^2 + 2*tan(angle) * dy * x + dy^2 =
# radius^2
# x^2 + tan(angle)^2 * x^2 +
# -2*dx*x + 2*tan(angle) * dy * x +
# dx^2 + dy^2 - radius^2= 0
# (1 + tan(angle)^2) * x^2 +
# (-2*dx + 2*tan(angle) * dy) * x +
# dx^2 + dy^2 - radius^2= 0
#
# Solve quadratic equation (a * x^2 + b * x + c = 0) with:
# a = 1 + tan(angle)^2
# b = -2*dx + 2*tan(angle) * dy
# c = dx^2 + dy^2 - radius^2
a = 1 + math.pow(math.tan(angle), 2)
b = -2 * dx + 2 * math.tan(angle) * dy
c = dx * dx + dy * dy - radius * radius
x = solve_quadratic(a, b, c)
y = math.tan(angle) * x + dy
return Point(x, y)
def slot_corners(radius, dx, width, angle):
'''Calculate slot corner coordinates.
'angle' is the slot's angle, and 'width' is the slot's width.
Returns a pair of Points (first, second) that identify a slot's
corners. The origin is vertically centered between the slot's top-left and
bottom-right corners.
▏
▏first
╱
╱
╱ second
╱ ╱▏
╱ ╱ ▏
╱ ╱
╱ ╱ angle
▔▔▔▔
╱━━╱
width
The vertical line in the diagram above is actually a circular arc centered
at (dx, 0), with radius 'radius'.
'''
# Vertical distance from a slot wall to the center of the slot.
# ▁▁
# ▏ ╱ ╱
# dy ▏ ╱▕ ╱
# ▁▏ ╱ ▕ ╱
# ▏ ╱ ▕ ╱
# dy ▏ ╱ ▕ ╱
# ▏ ╱ ▕╱ angle
# ▔▔ ▔▔▔▔
# ╱━━━━━╱
# width
dy = (width / 2) / math.sin(math.pi / 2 - angle)
return [intersect_circle_line(radius, dx, angle, dy),
intersect_circle_line(radius, dx, angle, -dy)]