DebasishDhal99 commited on
Commit
8afc52f
·
verified ·
1 Parent(s): fc47ca3

Create nonreflecting_ray_tracing.py

Browse files
Files changed (1) hide show
  1. backend/nonreflecting_ray_tracing.py +109 -0
backend/nonreflecting_ray_tracing.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ import math as mt
4
+
5
+ def quad_solver(a, b, c):
6
+ det = b**2 - 4*a*c
7
+ if det < 0:
8
+ raise ValueError("No real roots")
9
+ elif det == 0:
10
+ return -b / (2*a), -b / (2*a)
11
+ else:
12
+ return (-b - mt.sqrt(det)) / (2*a), (-b + mt.sqrt(det)) / (2*a)
13
+
14
+
15
+ def normalize(angle):
16
+ return angle % (2 * mt.pi)
17
+
18
+ def is_angle_between(angle, start, end):
19
+ angle = normalize(angle)
20
+ start = normalize(start)
21
+ end = normalize(end)
22
+ if start < end:
23
+ return start <= angle <= end
24
+ else:
25
+ return angle >= start or angle <= end
26
+
27
+
28
+ def draw_line(angle, length=max(max_dim, 500), x_0=0, y_0=0):
29
+ x_1 = length * mt.cos(angle) + x_0
30
+ y_1 = length * mt.sin(angle) + y_0
31
+ return [x_0, x_1], [y_0, y_1]
32
+
33
+
34
+ def nonreflecting_plotter(a = 20, b = 20, r = 15, ray_count = 50):
35
+ if a == 0 and b == 0:
36
+ raise ValueError("Circle center cannot be at the origin (0, 0).")
37
+
38
+ max_dim = max(abs(a), abs(b), r) * 3
39
+ fig, ax = plt.subplots()
40
+ ax.set_xlim(-max_dim, max_dim)
41
+ ax.set_ylim(-max_dim, max_dim)
42
+ ax.set_aspect('equal', adjustable='box')
43
+ ax.set_xlabel('X-axis')
44
+ ax.set_ylabel('Y-axis')
45
+
46
+ ax.axhline(0, color='black', lw=1)
47
+ ax.axvline(0, color='black', lw=1)
48
+
49
+ circle = plt.Circle((a, b), r, color='blue', fill=False)
50
+ ax.add_artist(circle)
51
+
52
+ theta_center = mt.atan2(b, a)
53
+ d = mt.hypot(a, b)
54
+
55
+ try:
56
+ delta = mt.asin(r / d)
57
+ except:
58
+ raise ValueError("Circle radius is too large for the given center coordinates.")
59
+
60
+ lower_angle = theta_center - delta
61
+ upper_angle = theta_center + delta
62
+
63
+ lower_angle = normalize(lower_angle)
64
+ upper_angle = normalize(upper_angle)
65
+
66
+ increment = 2*mt.pi/ray_count
67
+
68
+ for angle in np.arange(0, 2 * mt.pi, mt.pi / 180): # 1° steps
69
+ dx = mt.cos(angle)
70
+ dy = mt.sin(angle)
71
+ if is_angle_between(angle, lower_angle, upper_angle):
72
+ # continue
73
+ A = dx**2 + dy**2
74
+ B = -2 * (a * dx + b * dy)
75
+ C = a**2 + b**2 - r**2
76
+
77
+ try:
78
+ t1, t2 = quad_solver(A, B, C)
79
+ if abs(t1) < abs(t2):
80
+ t_hit = t1
81
+ else:
82
+ t_hit = t2
83
+ # t_hit = min(t1, t2)
84
+ if t_hit < 0:
85
+ continue
86
+ x = [0, t_hit * dx]
87
+ y = [0, t_hit * dy]
88
+ ax.plot(x, y, color='orange', lw=1)
89
+ except ValueError:
90
+ continue
91
+ else:
92
+ x, y = draw_line(angle)
93
+ ax.plot(x, y, color='red', lw=1)
94
+
95
+ x1, y1 = draw_line(lower_angle)
96
+ x2, y2 = draw_line(upper_angle)
97
+
98
+ ax.plot(x1, y1, color='green', lw=2, linestyle='--')
99
+ ax.plot(x2, y2, color='green', lw=2, linestyle='--')
100
+
101
+ # Label + show
102
+ ax.set_title(f'Rays with shadow from circle at ({a},{b}) radius {r}')
103
+ plt.grid(True)
104
+ plt.show()
105
+
106
+ fig.canvas.draw()
107
+ image_array = np.array(fig.canvas.renderer.buffer_rgba())
108
+ plt.close(fig)
109
+ return image_array