DebasishDhal99 commited on
Commit
e08e802
·
verified ·
1 Parent(s): 62e245c

Create reflecting_ray_simulation.py

Browse files
Files changed (1) hide show
  1. backend/reflecting_ray_simulation.py +110 -0
backend/reflecting_ray_simulation.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ import math as mt
4
+
5
+ def reflect_vector(v, n):
6
+ n = n / np.linalg.norm(n)
7
+ return v - 2 * np.dot(v, n) * n
8
+
9
+ def plot_reflection_on_circle(ax, angle, center, radius, ray_length=50, color='blue'):
10
+ a, b = center
11
+ origin = np.array([0, 0])
12
+ dx = np.cos(angle)
13
+ dy = np.sin(angle)
14
+
15
+ A = dx**2 + dy**2
16
+ B = -2 * (a * dx + b * dy)
17
+ C = a**2 + b**2 - radius**2
18
+
19
+ roots = np.roots([A, B, C])
20
+ ts = [t for t in roots if t > 0]
21
+ if not ts:
22
+ print(f"No intersection at angle {angle}")
23
+ return
24
+
25
+ t_hit = min(ts)
26
+ x_hit = t_hit * dx
27
+ y_hit = t_hit * dy
28
+ hit_point = np.array([x_hit, y_hit])
29
+
30
+ ax.plot([0, x_hit], [0, y_hit], color='blue', lw=1, zorder=10) # This is the incident ray
31
+
32
+ normal_vector = hit_point - np.array([a, b]) #Normal at point of reflection
33
+ # ax.plot([a, x_hit], [b, y_hit], color='green', lw=1)
34
+
35
+ # Reflection, this is key
36
+ incident_vector = hit_point - origin
37
+ reflected_vector = reflect_vector(incident_vector, normal_vector)
38
+ reflected_unit = 1000* reflected_vector / np.linalg.norm(reflected_vector)
39
+
40
+ ax.arrow(x_hit, y_hit,
41
+ reflected_unit[0] * ray_length,
42
+ reflected_unit[1] * ray_length,
43
+ head_width=1.8, head_length=1.5,
44
+ fc=color, ec=color, zorder=10)
45
+
46
+ return incident_vector, reflected_vector
47
+
48
+
49
+
50
+ def reflecting_ray_simulation(a = 20, b = 20, r = 15, ray_count = 15):
51
+ max_dim = max(abs(a), abs(b), r) * 3
52
+ fig, ax = plt.subplots()
53
+ ax.set_xlim(-max_dim, max_dim)
54
+ ax.set_ylim(-max_dim, max_dim)
55
+ ax.set_aspect('equal', adjustable='box')
56
+ ax.set_xlabel('X-axis')
57
+ ax.set_ylabel('Y-axis')
58
+
59
+ circle = plt.Circle((a, b), r, color='black', fill=False)
60
+ ax.add_artist(circle)
61
+
62
+ theta_center = mt.atan2(b, a)
63
+ d = mt.hypot(a, b)
64
+
65
+ try:
66
+ delta = mt.asin(r / d)
67
+ except:
68
+ raise ValueError("Circle radius is too large for the given center coordinates.")
69
+
70
+ lower_angle = theta_center - delta
71
+ upper_angle = theta_center + delta
72
+
73
+ def normalize(angle):
74
+ return angle % (2 * mt.pi)
75
+
76
+ lower_angle = normalize(lower_angle)
77
+ upper_angle = normalize(upper_angle)
78
+
79
+ def is_angle_between(angle, start, end):
80
+ angle = normalize(angle)
81
+ start = normalize(start)
82
+ end = normalize(end)
83
+ if start < end:
84
+ return start <= angle <= end
85
+ else:
86
+ return angle >= start or angle <= end
87
+
88
+ # Function to generate a line from origin at a given angle
89
+ def draw_line(angle, length=max(max_dim, 500), x_0=0, y_0=0):
90
+ x_1 = length * mt.cos(angle) + x_0
91
+ y_1 = length * mt.sin(angle) + y_0
92
+ return [x_0, x_1], [y_0, y_1]
93
+
94
+ increment = 2*my.pi/increment
95
+ for angle in np.arange(0, 2 * np.pi, increment):
96
+ dx = mt.cos(angle)
97
+ dy = mt.sin(angle)
98
+ if is_angle_between(angle, lower_angle, upper_angle):
99
+ plot_reflection_on_circle(ax, angle, center=(a, b), radius=r)
100
+
101
+ else:
102
+ x, y = draw_line(angle)
103
+ ax.plot(x, y, color='red', lw=1, zorder=5)
104
+ # plot_reflection_on_circle(ax, angle, center=(a, b), radius=r)
105
+
106
+ plt.show()
107
+ fig.canvas.draw()
108
+ image_array = np.array(fig.canvas.renderer.buffer_rgba())
109
+ plt.close(fig)
110
+ return image_array