Esempio n. 1
0
def ccw(*points, homogeneous=True):
    """tests if triangle a, b, c is oriented counterclockwise.

    Returns 1 if ccw, 0 if colinear, -1 if cw.

    Also does the scary analogous n-dimensional test, which
    essentially tests if, from the perspective of the last point,
    the other points appear to be well-oriented according
    to the (n-1)-dimensional test.
    """
    if not homogeneous:
        mtrx = Matrix(*[pt.lift(lambda v: 1).to_vector() for pt in points])
    else:
        mtrx = None
        for pt in points:
            if pt[-1] == 1:
                # We need at list one non-infinite point
                # for this to work normally
                mtrx = Matrix(*[pt.to_vector() for pt in points])
                break
    if mtrx is not None:
        return mtrx.sign_det()
    # If all points have 0 for extended homogeneous coordinate,
    # win by using the ccw test for one dimension higher:
    return ccw(*points,
               Point(*(0 for i in range(len(points[0]) - 1)), -1),
               homogeneous=False)
Esempio n. 2
0
def circumcenter(*points, homogeneous=True):
    """Computes a circumcenter for a set of n+1 points in n dimensions,
    ignoring the extended homogeneous coordinates.

    Unless you pass homogeneous=False, the last coordinate of each
    point will be lopped off. Behavior may not be defined if
    any of the homogeneous coordinates is not 1.
    """

    if homogeneous:
        if [pt[-1] for pt in points] != [1] * len(points):
            tmp = []
            for v in [p.to_vector() for p in points]:
                if v[-1] == 0:
                    v *= 1000000000
                tmp.append(v)
            # Just strip off the homogeneous coordinates.
            tmp = [v[:-1] for v in tmp]
            points = [Point(*v.to_array()) for v in tmp]
        else:
            points = [pt[:-1] for pt in points]

    vectors = [p - points[0] for p in points[1:]]
    A = Matrix(*vectors).transpose()
    p0_squared = points[0].to_vector().norm_squared()
    b = Vector(*[
        0.5 * (p.to_vector().norm_squared() - p0_squared) for p in points[1:]
    ])
    x = A.inverse() * b
    # If the arguments had homogeneous coordinates, we want to tack the extra
    # coordinate back on:
    return Point(*x, *([1] if homogeneous else []))
Esempio n. 3
0
 def test_subtract_matrix(self):
     """Tests for subtraction of two matrices"""
     result1 = Matrix(Vector(0, 0, 0),
                      Vector(-3, -4, -5),
                      Vector(-1, -1, -1))
     zero_matrix = Matrix(Vector(0, 0, 0), Vector(0, 0, 0), Vector(0, 0, 0))
     self.assertTrue(self.m1 - self.m6 == result1)
     self.assertTrue(self.m1 - self.m1 == zero_matrix)
Esempio n. 4
0
    def test_matrix_init(self):
        """Make sure we cannot initialize matrices that don't make sense"""
        # Make sure the empty matrix can't exist
        with self.assertRaises(ValueError):
            Matrix()

        # Ensure failure if the vectors have different dimensions
        with self.assertRaises(ValueError):
            Matrix(self.v1, self.v2, self.v4)
        with self.assertRaises(ValueError):
            Matrix(self.v4, self.zero)
        with self.assertRaises(ValueError):
            Matrix(self.v1, self.v4, self.zero)
Esempio n. 5
0
def incircle(*points, homogeneous=True):
    """Returns 1 if the last point is inside the circle defined by the other
    three, -1 if outside, and 0 if all cocircular.
    The points are interpreted as having extended homogenious
    coordinates unless homogeneous=False is passed.
    """

    if homogeneous:
        # The points already have homogeneous coordinates
        vectors = [pt.to_vector() for pt in points]
    else:
        # We'll give each point a homogeneous coordinate of 1
        vectors = [(pt.to_vector()).lift() for pt in points]

    tmp = []
    for v in vectors:
        if v[-1] == 0:
            v *= 1000000000
            v += Vector(*([0] * (len(v) - 1)), 1)
        tmp.append(v)
    vectors = tmp

    vectors = [
        vector.lift(lambda v: v[:-1].norm_squared()) for vector in vectors
    ]
    # At this point we could switch the last two elements of each
    # vector to get the matrix we want to test. But we can
    # also just use the fact that if you swap 2 rows of a
    # matrix, the sign of the determinant is flipped. So:
    return -Matrix(*vectors).sign_det()
Esempio n. 6
0
    def test_matrix_inversion(self):
        """Tests to see if matrix inversion works as expected"""
        inv1 = Matrix(Vector(-2, 1), Vector(1.5, -0.5))
        self.assertTrue(Matrix(self.v5, self.v6).inverse() == inv1)
        with self.assertRaises(ValueError):
            Matrix(self.zero, self.v1, self.v2).inverse()
        t1 = Vector(-1, 1, 2)
        t2 = Vector(-1, 3, 2)
        t3 = Vector(-1, 1, 3)
        inv2 = Matrix(Vector(-3.5, 0.5, 2),
                      Vector(-0.5, 0.5, 0),
                      Vector(-1, 0, 1))
        self.assertTrue(inv2 == Matrix(t1, t2, t3).inverse())
        inv3 = Matrix(Vector(-3.5, 2, 0.5),
                      Vector(-0.5, 0, 0.5),
                      Vector(-1, 1, 0))
        self.assertTrue(Matrix(t1, t3, t2).inverse() == inv3)

        self.assertEqual(Matrix(t1, t2, t3).inverse() * Matrix(t1, t2, t3),
                         Matrix(Vector(1, 0, 0),
                                Vector(0, 1, 0),
                                Vector(0, 0, 1)))
Esempio n. 7
0
    def test_matrix_sign_det(self):
        """Tests that sign_det returns the sign of the determinant.

        (Rather, sign_det should return an integer with the same sign as the
        determinant.)
        """
        ident_3 = Matrix(Vector(1, 0, 0),
                         Vector(0, 1, 0),
                         Vector(0, 0, 1))
        # The following are just some cases where it's easy
        # to do the math in your head.
        self.assertEqual(ident_3.sign_det(),
                         1)
        self.assertEqual((ident_3 - ident_3).sign_det(),
                         0)
        # (A lower-triangular matrix. And don't forget it.)
        self.assertEqual(Matrix(Vector(1, 2, 3),
                                Vector(0, -12, 5),
                                Vector(0, 0, 0.001)).sign_det(),
                         -1)

        self.assertIsInstance(Matrix(Vector(1, 2),
                                     Vector(3, 4)).sign_det(),
                              int)
Esempio n. 8
0
 def test_matrix_power(self):
     """Tests for matrices to a power"""
     result1 = Matrix(Vector(3, 4, 5), Vector(2, 3, 4), Vector(0, 0, 0))
     self.assertTrue(self.m1 ** 2 == result1)
     self.assertTrue(self.m1 * self.m1 * self.m1 == self.m1 ** 3)
Esempio n. 9
0
 def test_transpose(self):
     """Tests for transpose of a matrix"""
     result1 = Matrix(Vector(1, 1, 0), Vector(2, 1, 0), Vector(3, 1, 0))
     result2 = Matrix(Vector(1, 4, 1), Vector(2, 5, 1), Vector(3, 6, 1))
     self.assertTrue(self.m1.transpose() == result1)
     self.assertTrue(self.m6.transpose() == result2)
Esempio n. 10
0
 def test_add_matrix(self):
     """Tests for addition of two matrices"""
     result1 = Matrix(Vector(2, 4, 6), Vector(5, 6, 7), Vector(1, 1, 1))
     self.assertTrue(self.m1 + self.m6 == result1)
Esempio n. 11
0
 def test_scalar_multiplication(self):
     """Tests for multiplication of a matrix and a scalar"""
     result1 = Matrix(Vector(2, 4, 6), Vector(2, 2, 2), Vector(0, 0, 0))
     self.assertTrue(2 * self.m1 == result1)
     self.assertTrue(2 * self.m1 == self.m1 * 2)
Esempio n. 12
0
 def test_matrix_multiplication(self):
     """Tests for matrix multiplication"""
     result1 = Matrix(Vector(23, 34), Vector(31, 46))
     self.assertTrue(self.m4 * self.m5 == result1)
     result2 = Matrix(Vector(3, 4, 5), Vector(9, 13, 17), Vector(2, 3, 4))
     self.assertTrue(self.m1 * self.m6 == result2)
Esempio n. 13
0
 def setUp(self):
     """Set up some Vectors and Matrices"""
     self.v1 = Vector(1, 2, 3)
     self.v2 = Vector(1, 1, 1)
     self.v3 = Vector(9, 9)
     self.v4 = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
     self.zero = Vector(0, 0, 0)
     self.v5 = Vector(1, 2)
     self.v6 = Vector(3, 4)
     self.v7 = Vector(5, 6)
     self.v8 = Vector(7, 8)
     self.v9 = Vector(4, 5, 6)
     self.m1 = Matrix(self.v1, self.v2, self.zero)
     self.m2 = Matrix(self.v1, self.v2)
     self.m3 = Matrix(self.v3, self.v3)
     self.m4 = Matrix(self.v5, self.v6)
     self.m5 = Matrix(self.v7, self.v8)
     self.m6 = Matrix(self.v1, self.v9, self.v2)
     self.I = Matrix(Vector(1, 0, 0), Vector(0, 1, 0), Vector(0, 0, 1))
Esempio n. 14
0
class MatrixTestCase(unittest.TestCase):
    """Unit tests for the Matrix class"""

    def setUp(self):
        """Set up some Vectors and Matrices"""
        self.v1 = Vector(1, 2, 3)
        self.v2 = Vector(1, 1, 1)
        self.v3 = Vector(9, 9)
        self.v4 = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        self.zero = Vector(0, 0, 0)
        self.v5 = Vector(1, 2)
        self.v6 = Vector(3, 4)
        self.v7 = Vector(5, 6)
        self.v8 = Vector(7, 8)
        self.v9 = Vector(4, 5, 6)
        self.m1 = Matrix(self.v1, self.v2, self.zero)
        self.m2 = Matrix(self.v1, self.v2)
        self.m3 = Matrix(self.v3, self.v3)
        self.m4 = Matrix(self.v5, self.v6)
        self.m5 = Matrix(self.v7, self.v8)
        self.m6 = Matrix(self.v1, self.v9, self.v2)
        self.I = Matrix(Vector(1, 0, 0), Vector(0, 1, 0), Vector(0, 0, 1))

    def test_matrix_init(self):
        """Make sure we cannot initialize matrices that don't make sense"""
        # Make sure the empty matrix can't exist
        with self.assertRaises(ValueError):
            Matrix()

        # Ensure failure if the vectors have different dimensions
        with self.assertRaises(ValueError):
            Matrix(self.v1, self.v2, self.v4)
        with self.assertRaises(ValueError):
            Matrix(self.v4, self.zero)
        with self.assertRaises(ValueError):
            Matrix(self.v1, self.v4, self.zero)

    def test_matrix_width(self):
        """Tests for matrix width"""
        self.assertTrue(self.m1.width() == 3)
        self.assertTrue(self.m2.width() == 2)

    def test_matrix_height(self):
        """Tests for matrix height"""
        self.assertTrue(self.m1.height() == 3)
        self.assertTrue(self.m2.height() == 3)
        self.assertTrue(self.m3.height() == 2)

    def test_matrix_get(self):
        """Test for getting vectors of a matrix"""
        self.assertTrue(self.m1[0] == self.v1)
        self.assertTrue(self.m1[1] == self.v2)
        self.assertTrue(self.m1[2] == self.zero)

    def test_matrix_iteration(self):
        """Test iteration of a matrix"""
        orig_list = [self.v1, self.v2, self.zero]
        other_list = [vector for vector in self.m1]
        self.assertTrue(orig_list == other_list)

    def test_matrix_multiplication(self):
        """Tests for matrix multiplication"""
        result1 = Matrix(Vector(23, 34), Vector(31, 46))
        self.assertTrue(self.m4 * self.m5 == result1)
        result2 = Matrix(Vector(3, 4, 5), Vector(9, 13, 17), Vector(2, 3, 4))
        self.assertTrue(self.m1 * self.m6 == result2)

    def test_vector_multiplication(self):
        """Tests for matrix, vector multiplication"""
        self.assertTrue(self.I*self.v1 == self.v1)
        result1 = Vector(7, 10)
        self.assertTrue(self.m4 * self.v5 == result1)

    def test_scalar_multiplication(self):
        """Tests for multiplication of a matrix and a scalar"""
        result1 = Matrix(Vector(2, 4, 6), Vector(2, 2, 2), Vector(0, 0, 0))
        self.assertTrue(2 * self.m1 == result1)
        self.assertTrue(2 * self.m1 == self.m1 * 2)

    def test_determinant(self):
        """Tests for calculating determinant of matrix"""
        self.assertTrue(self.m1.det() == 0)
        self.assertAlmostEqual(self.m5.det(), -2.0)
        # almostEqual to account for floating point

    def test_add_matrix(self):
        """Tests for addition of two matrices"""
        result1 = Matrix(Vector(2, 4, 6), Vector(5, 6, 7), Vector(1, 1, 1))
        self.assertTrue(self.m1 + self.m6 == result1)

    def test_subtract_matrix(self):
        """Tests for subtraction of two matrices"""
        result1 = Matrix(Vector(0, 0, 0),
                         Vector(-3, -4, -5),
                         Vector(-1, -1, -1))
        zero_matrix = Matrix(Vector(0, 0, 0), Vector(0, 0, 0), Vector(0, 0, 0))
        self.assertTrue(self.m1 - self.m6 == result1)
        self.assertTrue(self.m1 - self.m1 == zero_matrix)

    def test_equal(self):
        """Tests for equality of matrices"""
        self.assertTrue(self.m1 == self.m1)
        self.assertFalse(self.m1 == self.m6)
        self.assertFalse(self.m1 == self.m2)

    def test_transpose(self):
        """Tests for transpose of a matrix"""
        result1 = Matrix(Vector(1, 1, 0), Vector(2, 1, 0), Vector(3, 1, 0))
        result2 = Matrix(Vector(1, 4, 1), Vector(2, 5, 1), Vector(3, 6, 1))
        self.assertTrue(self.m1.transpose() == result1)
        self.assertTrue(self.m6.transpose() == result2)

    def test_matrix_power(self):
        """Tests for matrices to a power"""
        result1 = Matrix(Vector(3, 4, 5), Vector(2, 3, 4), Vector(0, 0, 0))
        self.assertTrue(self.m1 ** 2 == result1)
        self.assertTrue(self.m1 * self.m1 * self.m1 == self.m1 ** 3)

    def test_matrix_inversion(self):
        """Tests to see if matrix inversion works as expected"""
        inv1 = Matrix(Vector(-2, 1), Vector(1.5, -0.5))
        self.assertTrue(Matrix(self.v5, self.v6).inverse() == inv1)
        with self.assertRaises(ValueError):
            Matrix(self.zero, self.v1, self.v2).inverse()
        t1 = Vector(-1, 1, 2)
        t2 = Vector(-1, 3, 2)
        t3 = Vector(-1, 1, 3)
        inv2 = Matrix(Vector(-3.5, 0.5, 2),
                      Vector(-0.5, 0.5, 0),
                      Vector(-1, 0, 1))
        self.assertTrue(inv2 == Matrix(t1, t2, t3).inverse())
        inv3 = Matrix(Vector(-3.5, 2, 0.5),
                      Vector(-0.5, 0, 0.5),
                      Vector(-1, 1, 0))
        self.assertTrue(Matrix(t1, t3, t2).inverse() == inv3)

        self.assertEqual(Matrix(t1, t2, t3).inverse() * Matrix(t1, t2, t3),
                         Matrix(Vector(1, 0, 0),
                                Vector(0, 1, 0),
                                Vector(0, 0, 1)))

    def test_matrix_sign_det(self):
        """Tests that sign_det returns the sign of the determinant.

        (Rather, sign_det should return an integer with the same sign as the
        determinant.)
        """
        ident_3 = Matrix(Vector(1, 0, 0),
                         Vector(0, 1, 0),
                         Vector(0, 0, 1))
        # The following are just some cases where it's easy
        # to do the math in your head.
        self.assertEqual(ident_3.sign_det(),
                         1)
        self.assertEqual((ident_3 - ident_3).sign_det(),
                         0)
        # (A lower-triangular matrix. And don't forget it.)
        self.assertEqual(Matrix(Vector(1, 2, 3),
                                Vector(0, -12, 5),
                                Vector(0, 0, 0.001)).sign_det(),
                         -1)

        self.assertIsInstance(Matrix(Vector(1, 2),
                                     Vector(3, 4)).sign_det(),
                              int)