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 |
|