Commit
·
64b00ed
1
Parent(s):
8949a25
Add edge case for reflectiv when sphere blocks all the light
Browse files
backend/nonreflecting_ray_tracing.py
CHANGED
@@ -26,8 +26,6 @@ def is_angle_between(angle, start, end):
|
|
26 |
|
27 |
|
28 |
def nonreflecting_plotter(a = 20, b = 20, r = 15, ray_count = 50):
|
29 |
-
if a == 0 and b == 0:
|
30 |
-
raise ValueError("Circle center cannot be at the origin (0, 0).")
|
31 |
|
32 |
max_dim = max(abs(a), abs(b), r) * 3
|
33 |
fig, ax = plt.subplots()
|
|
|
26 |
|
27 |
|
28 |
def nonreflecting_plotter(a = 20, b = 20, r = 15, ray_count = 50):
|
|
|
|
|
29 |
|
30 |
max_dim = max(abs(a), abs(b), r) * 3
|
31 |
fig, ax = plt.subplots()
|
backend/reflecting_ray_tracing.py
CHANGED
@@ -5,7 +5,15 @@ import math as mt
|
|
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])
|
@@ -59,13 +67,49 @@ def reflecting_plotter(a = 20, b = 20, r = 15, ray_count = 15):
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
lower_angle = theta_center - delta
|
71 |
upper_angle = theta_center + delta
|
@@ -93,8 +137,8 @@ def reflecting_plotter(a = 20, b = 20, r = 15, ray_count = 15):
|
|
93 |
|
94 |
increment = 2*mt.pi/ray_count
|
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 |
|
|
|
5 |
def reflect_vector(v, n):
|
6 |
n = n / np.linalg.norm(n)
|
7 |
return v - 2 * np.dot(v, n) * n
|
8 |
+
def quad_solver(a, b, c):
|
9 |
+
det = b**2 - 4*a*c
|
10 |
+
if det < 0:
|
11 |
+
raise ValueError("No real roots")
|
12 |
+
elif det == 0:
|
13 |
+
return -b / (2*a), -b / (2*a)
|
14 |
+
else:
|
15 |
+
return (-b - mt.sqrt(det)) / (2*a), (-b + mt.sqrt(det)) / (2*a)
|
16 |
+
|
17 |
def plot_reflection_on_circle(ax, angle, center, radius, ray_length=50, color='blue'):
|
18 |
a, b = center
|
19 |
origin = np.array([0, 0])
|
|
|
67 |
circle = plt.Circle((a, b), r, color='black', fill=False)
|
68 |
ax.add_artist(circle)
|
69 |
|
70 |
+
def inside_circle_plotter():
|
71 |
+
"""Function to plot the rays inside the circle"""
|
72 |
+
increment = 2 * mt.pi / ray_count
|
73 |
+
|
74 |
+
for angle in np.arange(0, 2 * mt.pi, increment):
|
75 |
+
dx = mt.cos(angle)
|
76 |
+
dy = mt.sin(angle)
|
77 |
+
|
78 |
+
A = dx**2 + dy**2
|
79 |
+
B = -2 * (a * dx + b * dy)
|
80 |
+
C = a**2 + b**2 - r**2
|
81 |
+
|
82 |
+
try:
|
83 |
+
t1, t2 = quad_solver(A, B, C)
|
84 |
+
|
85 |
+
valid_ts = [t for t in (t1, t2) if t > 0]
|
86 |
+
if not valid_ts:
|
87 |
+
continue
|
88 |
+
t_hit = min(valid_ts)
|
89 |
+
|
90 |
+
x = [0, t_hit * dx]
|
91 |
+
y = [0, t_hit * dy]
|
92 |
+
ax.plot(x, y, color='orange', lw=1)
|
93 |
+
except ValueError:
|
94 |
+
continue
|
95 |
+
|
96 |
theta_center = mt.atan2(b, a)
|
97 |
d = mt.hypot(a, b)
|
98 |
|
99 |
try:
|
100 |
delta = mt.asin(r / d)
|
101 |
except:
|
102 |
+
inside_circle_plotter()
|
103 |
+
ax.set_title(f'Rays origin - (0,0). From inside a perfectly reflective circle\nCenter - ({a},{b}), Radius {r}')
|
104 |
+
plt.grid(True)
|
105 |
+
plt.show()
|
106 |
+
|
107 |
+
fig.canvas.draw()
|
108 |
+
image_array = np.array(fig.canvas.renderer.buffer_rgba())
|
109 |
+
plt.close(fig)
|
110 |
+
return image_array
|
111 |
+
|
112 |
+
# raise ValueError("Circle radius is too large for the given center coordinates.")
|
113 |
|
114 |
lower_angle = theta_center - delta
|
115 |
upper_angle = theta_center + delta
|
|
|
137 |
|
138 |
increment = 2*mt.pi/ray_count
|
139 |
for angle in np.arange(0, 2 * np.pi, increment):
|
140 |
+
# dx = mt.cos(angle)
|
141 |
+
# dy = mt.sin(angle)
|
142 |
if is_angle_between(angle, lower_angle, upper_angle):
|
143 |
plot_reflection_on_circle(ax, angle, center=(a, b), radius=r)
|
144 |
|