def test_scaling_matrix_applied_to_point(self): transform = scaling(2, 3, 4) point = Coordinates.point(-4, 6, 8) result = transform * point assert result == Coordinates.point(-8, 18, 32)
def test_reflection_is_scaling_by_a_negative_value(self): transform = scaling(-1, 1, 1) point = Coordinates.point(2, 3, 4) result = transform * point assert result == Coordinates.point(-2, 3, 4)
def test_multiplying_translation_matrix(self): transform = translation(5, -3, 2) point = Coordinates.point(-3, 4, 5) result = transform * point assert result == Coordinates.point(2, 1, 7)
def test_shearing_transformation_moves_x_in_proportion_to_z(self): transform = shearing(0, 0, 0, 0, 0, 1) point = Coordinates.point(2, 3, 4) result = transform * point assert result == Coordinates.point(2, 3, 7)
def test_multiplying_by_inverse_of_translation_matrix(self): transform = translation(5, -3, 2) inverse = transform.inverse() point = Coordinates.point(-3, 4, 5) result = inverse * point assert result == Coordinates.point(-8, 7, 3)
def test_subtract_vector_from_point(self): point = Coordinates.point(3, 2, 1) vector = Coordinates.vector(5, 6, 7) result = point - vector assert result == Coordinates.point(-2, -4, -6) assert result.is_point()
def test_subtract_points(self): p1 = Coordinates.point(x=3, y=2, z=1) p2 = Coordinates.point(x=5, y=6, z=7) result = p1 - p2 assert result == Coordinates.vector(x=-2, y=-4, z=-6) assert result.is_vector()
def test_chaining_transformations_must_be_applied_in_reverse_order(self): point = Coordinates.point(1, 0, 1) rotate = rotation_x(radians(90)) scale = scaling(5, 5, 5) translate = translation(10, 5, 7) transforms = translate * scale * rotate result = transforms * point assert result == Coordinates.point(15, 0, 7)
def test_rotating_a_point_around_x_axis(self): point = Coordinates.point(0, 1, 0) half_quarter = rotation_x(radians(45)) full_quarter = rotation_x(radians(90)) half_quarter_rotation = half_quarter * point full_quarter_rotaton = full_quarter * point assert rounded(half_quarter_rotation) == rounded( [0, sqrt(2) / 2, sqrt(2) / 2, 1]) assert rounded(full_quarter_rotaton) == rounded( Coordinates.point(0, 0, 1))
def test_individual_transformations_are_applied_in_sequence(self): point = Coordinates.point(1, 0, 1) rotate = rotation_x(radians(90)) scale = scaling(5, 5, 5) translate = translation(10, 5, 7) rotated_point = rotate * point scaled_point = scale * rotated_point translated_point = translate * scaled_point assert rounded(rotated_point) == rounded(Coordinates.point(1, -1, 0)) assert rounded(scaled_point) == rounded(Coordinates.point(5, -5, 0)) assert translated_point == Coordinates.point(15, 0, 7)
def test_inverse_of_x_rotation_goes_in_opposite_direction(self): point = Coordinates.point(0, 1, 0) half_quarter = rotation_x(radians(45)).inverse() half_quarter_rotation = half_quarter * point assert rounded(half_quarter_rotation) == rounded([ 0, sqrt(2) / 2, -(sqrt(2) / 2), 1, ])
from data_structures import Coordinates from data_structures import Color from drawing import Canvas from drawing.formats import PPMFormat # Challenge for end of chapter 1 projectile = { "position": Coordinates.point(0, 1, 0), "velocity": Coordinates.vector(1, 1.8, 0).normalize() * 11.25, } environment = { "gravity": Coordinates.vector(0, -0.1, 0), "wind": Coordinates.vector(-0.01, 0, 0), } def tick(projectile, environment): position = projectile["position"] + projectile["velocity"] velocity = projectile["velocity"] + environment["gravity"] + environment["wind"] return {"position": position, "velocity": velocity} projectiles = [projectile] while projectile["position"].y > 0: projectile = tick(projectile, environment) projectiles.append(projectile) red = Color(1, 0, 0)
from math import radians from drawing import Canvas from drawing.formats import PPMFormat from drawing.transformations import translation, rotation_z, rotation_y, rotation_x from data_structures import Coordinates, Color width = 900 height = 900 canvas = Canvas(width, height) degrees_of_rotations = 360 / 12 radius = (height / 2) * 0.8 point = Coordinates.point(0, 0, 0) translate = translation(width / 2, height / 2, 0) for i in range(12): colors = [Color(1, 0, 0), Color(0, 1, 0), Color(0, 0, 1)] degrees = i * degrees_of_rotations print(f"degrees: {degrees}") rotate = rotation_z(radians(degrees)) rotated_point = rotate * (translate * point) print( f"rotated_point: {rotated_point.x} {rotated_point.y} {rotated_point.z}" ) canvas.write_pixel(int(rotated_point.x), int(rotated_point.y), colors[i % 3])
def test_point_conveniece_constructor(self): coordinates = Coordinates.point(1, 2, 3) assert coordinates.is_point() assert not coordinates.is_vector()