Skip to content

Commit a9c55cf

Browse files
committed
Finding the closest sphere
1 parent 8e27e37 commit a9c55cf

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

geometry.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,17 @@ def __init__(self, center, radius, color):
4141
self.color = color
4242

4343
def intersect(self, line):
44-
if line.distanceToPoint(self.center) <= self.radius:
45-
return self.color
46-
else:
47-
return (255, 255, 255)
44+
return line.distanceToPoint(self.center) <= self.radius
45+
46+
def intersection_value(self, line):
47+
v = Vector(line.slope)
48+
s = Vector(line.start)
49+
c = Vector(self.center)
50+
q = s.subtract(c)
51+
A = sum(x*x for x in v.coords)
52+
B = sum(-2*x*y for (x, y) in zip(v.coords, q.coords))
53+
C = sum(y*y for y in q.coords) - self.radius**2
54+
return solve_quadradic((A, B, C))
4855

4956
class Vector():
5057
def __init__(self, coords):
@@ -77,3 +84,15 @@ def mul_by_number(self, num):
7784
def project(self, v2):
7885
n = float(self.scalar_product(v2))/v2.scalar_product(v2)
7986
return v2.mul_by_number(n)
87+
88+
def solve_quadradic(coef):
89+
a = coef[0]
90+
b = coef[1]
91+
c = coef[2]
92+
delta = b**2 - 4*a*c
93+
ans = []
94+
ans.append(-b + sqrt(delta)/2.0*a)
95+
x = -b - sqrt(delta)/2.0*a
96+
if x >= 0:
97+
ans.append(x)
98+
return min(ans)

render.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,37 @@
22
from PIL import Image
33

44
path = "./rays.png"
5-
6-
tmp = Image.new('RGB', (200, 200), "white")
5+
size = 300
6+
tmp = Image.new('RGB', (size, size), "white")
77
rays = tmp.load()
88

9-
def coordinates(num):
9+
def coordinates(num, sz = size):
1010
"""
11-
Take a number between 0 and 199 and returns the proportional value between -2 and 2
11+
Take a number in range(size) and returns the proportional value between -2 and 2
1212
"""
13-
return 8.0*num/199.0 - 2.0
14-
15-
16-
S = Sphere((0, 0, 0), 0.5, (0, 0, 0))
17-
origin = (-10, 0, 0)
13+
return 4.0*num/(sz - 1) - 2.0
1814

15+
# Creating the world
16+
S1 = Sphere((1, 0, 0), 0.5, (10, 220, 0))
17+
S2 = Sphere((0.6, 0, 0), 0.5, (200, 10, 200))
18+
camera = (0, 0, -8)
19+
world = [S1, S2]
1920

20-
for i in range(200):
21+
# Colouring each pixel
22+
for i in range(size):
2123
x0 = coordinates(i)
22-
for j in range(200):
24+
for j in range(size):
2325
y0 = coordinates(j)
24-
l = Line.throughPoints(origin, (x0, y0, -5))
25-
rays[i, j] = S.intersect(l)
26+
l = Line.throughPoints(camera, (x0, y0, -5))
27+
ans = []
28+
for S in world:
29+
if S.intersect(l):
30+
ans.append((S.intersection_value(l), S))
31+
if not ans:
32+
rays[i, j] = (255, 255, 255)
33+
else:
34+
ans.sort()
35+
rays[i, j] = ans[0][1].color
36+
2637

2738
tmp.save(path)

testing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
def test_intersect_True():
44
S = Sphere((0, 0, 0), 1, (10, 200, 20))
55
l = Line.throughPoints((0, 1, 0), (0, 1, 1))
6-
assert S.intersect(l) == (10, 200, 20)
6+
assert S.intersect(l)
77

88
def test_intersect_False():
99
S = Sphere((100, 100, 100), 0.1, (10, 200, 20))
1010
l = Line.throughPoints((0, 0, 1), (0, 0, 2))
11-
assert S.intersect(l) == (255, 255, 255)
11+
assert S.intersect(l) == False
1212

1313
# Testing vector methods
1414

0 commit comments

Comments
 (0)