def test_resolve_ball_ball_collision_2d_two_moving(self):
        # Initialize ball objects
        ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)
        ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)

        # A enters from W (270 degrees), contacts B on its left (180 degrees)
        # A enters from E (0 degrees), contacts A on its right (0 degrees)
        # A and B should both reverse their direction
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-0.5, 0.0), Vector(1.0, 0.0), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.5, 0.0), Vector(-1.0, 0.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(-1.0, 0.0)
        b_vel_new = Vector(1.0, 0.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)

        # A enters from W (270 degrees), contacts B on its left (180 degrees)
        # A enters from E (0 degrees), contacts A on its right (0 degrees)
        # A and B should both reverse their direction
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-0.5, 0.0), Vector(1.0, 0.0), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.5, 0.0), Vector(-1.0, 0.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(-1.0, 0.0)
        b_vel_new = Vector(1.0, 0.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)

        """
    def test_resolve_ball_ball_collision_1d_diagonal(self):
        # Initialize ball objects
        ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)
        ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)

        # 2-D, stationary target ball
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, -1.0), Vector(2.0, 2.0), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(0.0, 0.0)
        b_vel_new = Vector(2.0, 2.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)

        # 2-D, head-on collision, same speeds
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, -1.0), Vector(2.0, 2.0), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(-2.0, -2.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(-2.0, -2.0)
        b_vel_new = Vector(2.0, 2.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)
    def test_resolve_ball_ball_collision_2d_one_moving(self):
        # Initialize ball objects
        ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)
        ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)

        # A enters from NW (135 degrees), contacts B on its left (180 degrees)
        # B is stationary, located at origin
        # A should exit S (270 degrees)
        # B should exit E (0 degrees)
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, 0.0), Vector(1.0, -1.0), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(0.0, -1.0)
        b_vel_new = Vector(1.0, 0.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)

        # A enters from 122.3 degrees, contacts B on its left (180 degrees)
        # B is stationary, located at origin
        # A should exit S (270 degrees), with y-component of initial magnitude
        # B should exit E (0 degrees), with x-component of initial magnitude
        mag = 7.14
        ang = 32.3
        ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, 0.0), Vector(mag * np.cos(ang), -mag * np.sin(ang)), 3.0
        ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0

        resolve_ball_ball_collision(ball_a, ball_b)

        a_vel_new = Vector(0.0, -mag * np.sin(ang))
        b_vel_new = Vector(mag * np.cos(ang), 0.0)

        self.assertVectorAlmostEqual(ball_a.vel, a_vel_new)
        self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)
    def test_check_ball_ball_collision_y_axis(self):
        # Initialize ball objects
        ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)
        ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5)

        # On x-axis, not touching
        ball_a.pos = Coordinates(0.0, 2.01)
        ball_b.pos = Coordinates(0.0, 0.0)
        result = check_ball_ball_collision(ball_a, ball_b)
        self.assertFalse(result)

        # On x-axis, touching
        ball_a.pos = Coordinates(0.0, 1.00)
        ball_b.pos = Coordinates(0.0, 0.0)
        result = check_ball_ball_collision(ball_a, ball_b)
        self.assertTrue(result)

        # On x-axis, overlapping
        ball_a.pos = Coordinates(0.0, 0.99)
        ball_b.pos = Coordinates(0.0, 0.0)
        result = check_ball_ball_collision(ball_a, ball_b)
        self.assertTrue(result)