예제 #1
0
    def test_dot_product(self):
        v1 = Coordinates.vector(1, 2, 3)
        v2 = Coordinates.vector(2, 3, 4)

        result = v1.dot_product(v2)

        assert result == 20
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
0
    def test_subtracting_vector_from_zero(self):
        v1 = Coordinates.vector(0, 0, 0)
        v2 = Coordinates.vector(1, -2, 3)

        result = v1 - v2

        assert result == Coordinates.vector(-1, 2, -3)
예제 #7
0
    def test_scaling_matrix_applied_to_vector(self):
        transform = scaling(2, 3, 4)
        vector = Coordinates.vector(-4, 6, 8)

        result = transform * vector

        assert result == Coordinates.vector(-8, 18, 32)
예제 #8
0
    def test_coordinates_addition(self):
        coord_1 = Coordinates(x=3, y=-2, z=5, w=1)
        coord_2 = Coordinates(x=-2, y=3, z=1, w=0)

        result = coord_1 + coord_2

        assert result == Coordinates(x=1, y=1, z=6, w=1)
예제 #9
0
    def test_multiply_by_inverse_of_scaling_matrix(self):
        transform = scaling(2, 3, 4).inverse()
        vector = Coordinates.vector(-4, 6, 8)

        result = transform * vector

        assert result == Coordinates.vector(-2, 2, 2)
예제 #10
0
    def test_subtract_vectors(self):
        v1 = Coordinates.vector(3, 2, 1)
        v2 = Coordinates.vector(5, 6, 7)

        result = v1 - v2

        assert result == Coordinates.vector(-2, -4, -6)
        assert result.is_vector()
예제 #11
0
    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)
예제 #12
0
    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()
예제 #13
0
    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()
예제 #14
0
    def test_matrix_multiplication_to_coordinate(self):
        matrix = Matrix([[1, 2, 3, 4], [2, 4, 4, 2], [8, 6, 4, 1],
                         [0, 0, 0, 1]])
        coord = Coordinates(1, 2, 3, 1)

        result = matrix * coord

        assert result == Coordinates(18, 24, 33, 1)
예제 #15
0
    def test_cross_product(self):
        v1 = Coordinates.vector(1, 2, 3)
        v2 = Coordinates.vector(2, 3, 4)

        result1 = v1.cross_product(v2)
        result2 = v2.cross_product(v1)

        assert result1 == Coordinates.vector(-1, 2, -1)
        assert result2 == Coordinates.vector(1, -2, 1)
예제 #16
0
    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)
예제 #17
0
    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))
예제 #18
0
    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)
예제 #19
0
    def test_translation_does_not_affect_vectors(self):
        transform = translation(5, -3, 2)
        vector = Coordinates.vector(-3, 4, 5)

        result = transform * vector

        assert result == vector
예제 #20
0
    def test_initialization(self):
        coordinates = Coordinates(x=1, y=2, z=3, w=4)

        assert coordinates.x == 1
        assert coordinates.y == 2
        assert coordinates.z == 3
        assert coordinates.w == 4
예제 #21
0
    def test_idenity_matrix_mul_by_coordinates(self):
        identity_matrix = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                                  [0, 0, 0, 1]])
        coord = Coordinates(1, 2, 3, 4)

        result = identity_matrix * coord

        assert result == coord
예제 #22
0
    def test_normalize_vector_1_2_3(self):
        v = Coordinates.vector(1, 2, 3)

        result = v.normalize()

        assert round(result.x, 5) == 0.26726
        assert round(result.y, 5) == 0.53452
        assert round(result.z, 5) == 0.80178
예제 #23
0
    def _mul_matrix_by_coordinates(self, coord):
        data = []
        for row in self.data:
            total = reduce(
                lambda prev, curr: prev + curr[0] * curr[1],
                zip(row, coord),
                0,
            )
            data.append(total)

        return Coordinates(*data)
예제 #24
0
    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,
        ])
예제 #25
0
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)
예제 #26
0
    def test_vector_conveniece_constructor(self):
        coordinates = Coordinates.vector(1, 2, 3)

        assert not coordinates.is_point()
        assert coordinates.is_vector()
예제 #27
0
    def test_negating_coordinates(self):
        coord = Coordinates(x=1, y=-2, z=3, w=-4)

        result = -coord

        assert result == Coordinates(x=-1, y=2, z=-3, w=4)
예제 #28
0
    def test_multiplying_coordinate_by_scalar(self):
        coord = Coordinates(1, -2, 3, -4)

        result = coord * 3.5

        assert result == Coordinates(3.5, -7.0, 10.5, -14.0)
예제 #29
0
    def test_multiplying_coordinates_by_fraction(self):
        coord = Coordinates(1, -2, 3, -4)

        result = coord * 0.5

        assert result == Coordinates(0.5, -1.0, 1.5, -2.0)
예제 #30
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])