예제 #1
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 []))
    def test_ccw_euclidean(self):
        """Right now this only tests ccw for 1 and 2 dimensions."""
        # one-dimensional test.

        one_dim_high = Point(1)
        one_dim_low = Point(0)
        # I don't much care which way is negative, but one had better be
        # positive and the other negative. And they'd better be ints. (Of
        # course, ccw in 1D is equivalent to numeric comparison.)
        self.assertEqual((ccw(one_dim_high, one_dim_low, homogeneous=False) *
                          ccw(one_dim_low, one_dim_high, homogeneous=False)),
                         -1)
        self.assertIsInstance((ccw(one_dim_high, one_dim_low,
                                   homogeneous=False) *
                               ccw(one_dim_low, one_dim_high,
                                   homogeneous=False)),
                              int)

        # co-hyperplanar --> 0
        self.assertEqual(ccw(one_dim_high, one_dim_high, homogeneous=False), 0)

        # Now for 2D stuff:

        # Invariance under rotation of args
        self.assertEqual(ccw(self.r2north, self.r2east, self.r2south,
                             homogeneous=False),
                         ccw(self.r2south, self.r2north, self.r2east,
                             homogeneous=False))

        self.assertEqual(ccw(self.r2north, self.r2east, self.r2south,
                             homogeneous=False), -1)
        self.assertEqual(ccw(self.r2east, self.r2south, self.r2west,
                             homogeneous=False), -1)
        self.assertEqual(ccw(self.r2south, self.r2north, self.r2orig,
                             homogeneous=False), 0)
        self.assertEqual(ccw(self.r2east, self.r2orig, self.r2east,
                             homogeneous=False), 0)
        self.assertEqual(ccw(self.r2west, self.r2east, self.r2south,
                             homogeneous=False), -1)
        self.assertEqual(ccw(self.r2west, self.r2south, self.r2north,
                             homogeneous=False), 1)

        # Swapping two args flips the sign
        self.assertEqual(ccw(self.r2west, self.r2south, self.r2north,
                             homogeneous=False),
                         -ccw(self.r2south, self.r2west, self.r2north,
                              homogeneous=False))
        self.assertEqual(ccw(self.r2west, self.r2east, self.r2orig,
                             homogeneous=False),
                         -ccw(self.r2east, self.r2west, self.r2orig,
                              homogeneous=False))
        # Warn us when we make non-square matrices
        self.assertRaises(Exception, ccw, self.r2west, self.r2south,
                          self.r2north, self.r2east, homogeneous=False)
        self.assertRaises(Exception, ccw, self.r2orig, self.r2south,
                          homogeneous=False)
예제 #3
0
    def test_lift(self):
        """Make sure lifting works nicely."""

        # Define a function to use for testing
        def f(x):
            return x[0] * 2
        self.assertTrue(self.b.lift(f) == Point(1, 2, 2))
        self.assertFalse(self.c.lift(f) == Point(1, 2, 3, 4))
        self.assertFalse(self.c.lift(f) == Point(1, 2, 3))

        # Make sure that lifting a Point returns a Point
        self.assertIsInstance(self.b.lift(f), Point)
예제 #4
0
    def test_hashing(self):
        """Make sure point hashing works and does not cause collisions"""
        # Add 400 points' hashes to a set and make sure 400 things are in the
        # set
        some_hashes = set()
        for x in range(-10, 10):
            for y in range(-10, 10):
                some_hashes.add(hash(Point(x, y, 1)))
        self.assertEqual(len(some_hashes), 400)

        self.assertEqual(hash(Point(0, 1, 2)),
                         hash(Point(0, 1, 2)))
    def test_in_general_position(self):
        """Test rigorously, but only for nice inputs"""

        points = [
            Point(0.5, -400, 1),
            Point(10, 21, 1),
            Point(-5, 0, 1),
            Point(1, 2, 1),
            Point(2, 1, 1)
        ]
        deltri = DelT(points, randomize=False)
        self.assertTrue(deltri.test_is_delaunay())
    def test_2d_case(self):
        """Test the output for a super simple 2D case"""

        del_tri = DelT([Point(3, 4), Point(-3, 4),
                        Point(0, -5)],
                       homogeneous=False,
                       randomize=False)
        vor = Voronoi(del_tri)
        expected_center = Point(0.0, 0.0, 1.0)

        self.assertTrue(expected_center in vor.points)
        self.assertTrue(len(vor.points) == 1)
        self.assertTrue(len(vor.edges) == 3)
예제 #7
0
    def test_misc_niceties(self):
        """I don't want  the empty point to be a thing. You may disagree."""
        with self.assertRaises(ValueError):
            Point()  # Try to make an empty point.

        # Make sure that we can evaluate a point to True
        self.assertTrue(self.a)
예제 #8
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)
예제 #9
0
 def __init__(self, triangulation):
     self.points = set()
     self.edges = set()
     finite_faces = (f for f in triangulation.faces if self._is_finite(f))
     for face in finite_faces:
         point = circumcenter(*face.points())
         self.points.add(point)
         for half_facet in face.iter_facets():
             if half_facet.twin:
                 adj_point = circumcenter(*half_facet.twin.face.points())
                 if not self._is_finite(half_facet.twin.face):
                     tmp_vec = ((adj_point.to_vector()[:-1]) *
                                (1 / 1000000000))
                     adj_point = Point(*tmp_vec.to_array())
                     adj_point = adj_point.lift(lambda *args: 0)
                 self.edges.add(frozenset([point, adj_point]))
예제 #10
0
 def setUp(self):
     """Make some objects that are useful for most tests."""
     # Make points on the unit circle in the plane
     # North, East, South, and West shouldn't bend your brain
     self.r2north = Point(0, 1)
     self.r2south = Point(0, -1)
     self.r2east = Point(1, 0)
     self.r2west = Point(-1, 0)
     self.r2orig = Point(0, 0)
     # Now the homogeneous version of the same thing (We use the plane z=1
     # to represent the plane R^2 but with a boundary (homeomorphic to a
     # circle). Points with z=0 are essentially infinitely far away. The
     # same idea works in higher dimensions.
     self.homo_north = Point(0, 1, 1)
     self.homo_south = Point(0, -1, 1)
     self.homo_east = Point(1, 0, 1)
     self.homo_west = Point(-1, 0, 1)
     self.homo_orig = Point(0, 0, 1)
예제 #11
0
def outer_face_pts(dimension):
    """Get some points whose simplex contains all of R^{dimension}

    This ought to be a triangulation method, I guess.
    But I'm leaving it here for now.

    (This is all the standard basis vectors, plus the vector of all -1s. Er,
    but points, not vectors.)
    """
    coords = [0] * (dimension + 1)
    results = []
    for i in range(dimension):
        # Generate a standard basis vector
        coords[i] = 1
        results.append(Point(*coords))
        coords[i] = 0
    results.append(Point(*(-1 for i in range(dimension)), 0))
    return results
 def test_vertex_compare(self):
     """Make sure vertices have an order that's reasonable."""
     verts = []
     for i in range(-5, 5):
         for j in range(-5, 5):
             verts.append(DelT.Vertex(Point(i, j, 1)))
     self.assertEqual(sorted(verts), sorted(verts[::-1]))  # consistency
     self.assertEqual(sorted(verts), sorted(verts))
     self.assertLess(sorted(verts)[0], sorted(verts)[1])
     self.assertNotEqual(verts[0], verts[1])
     self.assertEqual(verts[0], verts[0])
예제 #13
0
    def test_point_equal(self):
        """Tests if comparison of points for equality works"""
        self.assertTrue(Point(0, -9, 11.2) == Point(0, -9, 11.2))
        self.assertFalse(Point(0, -9, 1600002) == Point(0, -8, 1600002))
        # Different location
        self.assertFalse(Point(1, 4) == Point(1, 4, 5))

        # Drew's tests:
        self.assertFalse(self.a == self.b)
        self.assertTrue(self.b == self.b)
        self.assertTrue(Point(1, 2, 3) == Point(1, 2, 3))
        self.assertFalse(self.b == self.c)
        self.assertFalse(self.b == (1, 2))
예제 #14
0
    def test_incircle_euclidean(self):
        """Test the incircle predicate in the plane."""

        a = Point(1, 0)
        b = Point(0, 1)
        c = Point(-1, 0)
        d = Point(0, 0)
        self.assertTrue(incircle(a, b, c, d, homogeneous=False) == 1)
        self.assertTrue(incircle(a, b, d, c, homogeneous=False) == -1)
        self.assertTrue(incircle(a, b, c, c, homogeneous=False) == 0)

        r2far_east = Point(50, -0.5)

        # circle of radius 0... ought to be 0 (co-circular)
        self.assertEqual(incircle(self.r2east, self.r2east, self.r2east,
                                  self.r2east, homogeneous=False), 0)

        # The origin is in fact inside the (counterclockwise) unit circle
        self.assertEqual(incircle(self.r2east, self.r2north, self.r2west,
                                  self.r2orig, homogeneous=False), 1)

        # SHOULD depend on orientation of circle, so we can
        # have stuff like inside-out circles
        self.assertNotEqual(incircle(self.r2east, self.r2west, self.r2north,
                                     self.r2orig, homogeneous=False),
                            incircle(self.r2west, self.r2east, self.r2north,
                                     self.r2orig, homogeneous=False))
        self.assertNotEqual(incircle(self.r2east, self.r2north, self.r2west,
                                     self.r2orig, homogeneous=False),
                            incircle(self.r2north, self.r2east, self.r2west,
                                     self.r2orig, homogeneous=False))

        # Finitely faraway pt not in (counterclockwise) unit circle
        self.assertEqual(incircle(self.r2north, self.r2west, self.r2east,
                                  r2far_east, homogeneous=False), -1)
        # Finitely faraway pt is in the clockwise (inside-out) unit circle
        self.assertEqual(incircle(self.r2west, self.r2north, self.r2east,
                                  r2far_east, homogeneous=False), 1)
 def test_easy_peasy_case(self):
     """Test with one point and see if the structure makes sense."""
     point = Point(-3, 2, 1)
     deltri = DelT([point])
     self.assertEqual(len(deltri.faces), 3)
     for face in deltri.faces:
         self.assertIn(point, face.points())
         for hafacet in face.half_facets.values():
             self.assertNotIn(hafacet.opposite, hafacet.points())
     null_twin_count = 0
     for face in deltri.faces:
         self.assertEqual(len(face.vertices), 3)
         for halffacet in face.half_facets.values():
             if halffacet.twin is None:
                 null_twin_count += 1
             else:
                 self.assertIs(halffacet.twin.twin, halffacet)
     self.assertEqual(null_twin_count, 3)
     self.assertTrue(deltri.test_is_delaunay())
    def test_convex_hull_bug(self):
        """Eliminate bugs where the the convex hull becomes concave."""

        # This case is prohibitively big to test properly
        # points = [Point(*coords) for coords in [
        #     (248, 508, 1), (709, 346, 1), (820, 535, 1), (427, 274, 1),
        #     (671, 220, 1), (927, 342, 1), (612, 627, 1), (762, 633, 1),
        #     (161, 238, 1), (71, 102, 1), (185, 25, 1), (233, 6, 1)]]
        # del_tri = DelT(points, homogeneous=True, randomize=False)
        # self.assertTrue(del_tri.test_is_delaunay())

        # A nice clean 4 points that caused a bug.
        points = [
            Point(*coords)
            for coords in [(582, 245, 1), (649, 400, 1), (854, 279,
                                                          1), (411, 176, 1)]
        ]
        del_tri = DelT(points, homogeneous=True, randomize=False)
        self.assertEqual(len(del_tri.face_point_sets()), 3)
 def test_3d_case(self):
     fn = os.path.join(os.path.dirname(__file__), 'data/points.csv')
     f = open(fn)
     points = csv.reader(f)
     points = list(points)
     points = [[float(y) for y in x] for x in points]
     point_array = [Point(*point) for point in points]
     del_tri = DelT(point_array, homogeneous=False, randomize=False)
     self.assertTrue(del_tri.test_is_delaunay())
     face_sets = set([
         frozenset(face)
         for face in del_tri.face_point_sets(homogeneous=False)
     ])
     fn = os.path.join(os.path.dirname(__file__), 'data/dt.csv')
     with open(fn, 'r') as f:
         triangles = list(csv.reader(f))
         triangles = [[int(y) for y in x] for x in triangles]
         expected_face_sets = set([
             frozenset([point_array[y - 1] for y in x]) for x in triangles
         ])
         for face_set in face_sets:
             self.assertEqual(len(face_set), 4)
     self.assertEqual(face_sets, expected_face_sets)
    def test_2d_case(self):
        """Test the output for a 2D case transfered from a notebook"""

        # First just make sure face equality works like I hope:
        self.assertEqual(set(frozenset([Point(0, 3.7)])),
                         set(frozenset([Point(0, 3.7)])))

        del_tri = DelT([
            Point(-0.6, 3.2),
            Point(3.2, 2.1),
            Point(-2, 0),
            Point(1, -0.2),
            Point(3.6, -0.3),
            Point(-1.4, -2.1),
            Point(2.5, -1.7)
        ],
                       homogeneous=False,
                       randomize=False)
        self.assertTrue(del_tri.test_is_delaunay())
        face_sets = set([
            frozenset(face)
            for face in del_tri.face_point_sets(homogeneous=False)
        ])
        expected_face_sets = set([
            frozenset([Point(-2, 0),
                       Point(-0.6, 3.2),
                       Point(1, -0.2)]),
            frozenset([Point(3.2, 2.1),
                       Point(-0.6, 3.2),
                       Point(1, -0.2)]),
            frozenset([Point(3.2, 2.1),
                       Point(3.6, -0.3),
                       Point(1, -0.2)]),
            frozenset([Point(2.5, -1.7),
                       Point(3.6, -0.3),
                       Point(1, -0.2)]),
            frozenset([Point(2.5, -1.7),
                       Point(-1.4, -2.1),
                       Point(1, -0.2)]),
            frozenset([Point(-1.4, -2.1),
                       Point(-2, 0),
                       Point(1, -0.2)])
        ])
        # Note that equality of faces works exactly like you'd want.  The test
        # even nicely tells you the differences between the sets, if it fails.
        for face_set in face_sets:
            self.assertEqual(len(face_set), 3)  # triangles have 3 vertices
        self.assertEqual(face_sets, expected_face_sets)
예제 #19
0
    def testCircumCenter(self):
        """Tests for the circumcenter utility"""

        # Make sure the unit circle is centered at the origin
        center1 = circumcenter(Point(1, 0),
                               Point(0, 1),
                               Point(0, -1),
                               homogeneous=False)
        self.assertIsInstance(center1, Point)
        self.assertEqual(center1, Point(0, 0))

        # Do the same but with the unit sphere in R^3
        center2 = circumcenter(Point(1, 0, 0),
                               Point(0, 1, 0),
                               Point(0, -1, 0),
                               Point(0, 0, 1),
                               homogeneous=False)
        self.assertIsInstance(center2, Point)
        self.assertEqual(center2, Point(0, 0, 0))

        # Make sure it isn't just returning zero all the time
        center3 = circumcenter(Point(1, 2),
                               Point(2, 1),
                               Point(1, 0),
                               homogeneous=False)
        self.assertEqual(center3, Point(1.0, 1.0))

        # Now let's see how it deals with homogeneous coordinates

        # Now make sure homogeneous coordinates are properly ignored
        # if they are all 1. (But the point returned should be
        # of the same dimension as the input.)
        self.assertEqual(
            circumcenter(Point(2, 3, 1), Point(3, 2, 1), Point(2, 1, 1)),
            Point(2, 2, 1))
예제 #20
0
    def test_incircle_homogeneous(self):
        """Tests incircle on points with homogeneous coordinates
        (representing points in R^d but with a boundary)
        """
        far_east_finite = Point(50, 0, 1)
        far_east_infinite = Point(1, 0, 0)

        # Counterclockwise circle around origin contains origin:
        self.assertEqual(incircle(self.homo_east, self.homo_north,
                                  self.homo_south, self.homo_orig), 1)
        # But it shouldn't contain any faraway point:
        self.assertEqual(incircle(self.homo_east, self.homo_north,
                                  self.homo_south, far_east_finite), -1)
        self.assertEqual(incircle(self.homo_east, self.homo_north,
                                  self.homo_south, far_east_infinite), -1)
        # And of course, another point on the unit circle should be cocircular:
        self.assertEqual(incircle(self.homo_east, self.homo_north,
                                  self.homo_south, self.homo_west), 0)

        # Clockwise circle around origin does not contain origin:
        self.assertEqual(incircle(self.homo_north, self.homo_east,
                                  self.homo_south, self.homo_orig), -1)
        # But it SHOULD contain faraway points:
        self.assertEqual(incircle(self.homo_north, self.homo_east,
                                  self.homo_south, far_east_finite), 1)
        self.assertEqual(incircle(self.homo_north, self.homo_east,
                                  self.homo_south, far_east_infinite), 1)
        # Cocircular stuff should still be cocircular:
        self.assertEqual(incircle(self.homo_north, self.homo_east,
                                  self.homo_south, self.homo_west), 0)

        # Check for subtle arithmetic errors:
        self.assertEqual(incircle(Point(0, -10, 1),
                                  Point(0, 0, 1),
                                  Point(-0.001, 10, 1),
                                  Point(-0.0005, 10, 1)),
                         -1)

        # Counterclockwise infinite triangle contains everything
        inf_triangle = [Point(1, 0, 0), Point(-1, 1, 0), Point(-1, -1, 0)]

        self.assertEqual(incircle(*inf_triangle, Point(12, -14, 1)),
                         1)
        self.assertEqual(incircle(*inf_triangle, Point(-1, 1, 1)),
                         1)

        # Clockwise infinite triangle contains nothing
        self.assertEqual(incircle(*inf_triangle[::-1], Point(12, -14, 1)),
                         -1)
        self.assertEqual(incircle(*inf_triangle[::-1], Point(-1, 1, 1)),
                         -1)

        # Tricky cases:
        self.assertEqual(incircle(
            Point(-1, -1, 0), Point(-3, 2, 1), Point(1, 0, 0), Point(0, 1, 0)),
                         1)
        self.assertEqual(incircle(
            Point(-3, 2, 1), Point(-1, -1, 0), Point(1, 0, 0), Point(0, 1, 0)),
                         -1)

        # The following tests are based on pencil-and-paper drawings
        # as well as hours spent debugging the DelaunayTriangulation.

        self.assertEqual(incircle(
            Point(1, 0, 0), Point(-0.6, 3.2, 1), Point(3.2, 2.1, 1),
            Point(-2, 0, 1)),
                         -1)

        self.assertEqual(incircle(
                                  Point(-2, 0, 1),
                                  Point(-0.6, 3.2, 1),
                                  Point(0, 1, 0),
                                  Point(1, 0, 0)),
                         -1)
예제 #21
0
 def setUp(self):
     """Make some objects that are useful for most tests."""
     self.a = Point(0, 0)
     self.b = Point(1, 2)
     self.c = Point(1, 2, 3)
    def test_locally_delaunay(self):
        """Make sure that the locally delaunay test works."""
        def quick_delaunay_test(*points, expectation=True):
            """Tests that the faces defined by points[:-1] and points[1:] share
            an edge that is locally delaunay iff we expect it to be so.
            """
            vertices = [DelT.Vertex(point) for point in points]
            face_1 = DelT.Face(vertices[:-1])
            face_2 = DelT.Face(vertices[1:])
            facet_1 = face_1.half_facets[vertices[0]]
            facet_2 = face_2.half_facets[vertices[-1]]
            facet_1.twin = facet_2
            facet_2.twin = facet_1

            self.assertEqual(facet_1.lineside(facet_1.opposite.point), 1)
            self.assertEqual(facet_1.lineside(facet_1.opposite.point), 1)

            self.assertEqual(facet_1.locally_delaunay(), expectation)
            self.assertEqual(facet_1.locally_delaunay(),
                             facet_2.locally_delaunay())

        # Test for one dimension first.
        quick_delaunay_test(Point(-1, 1),
                            Point(2, 1),
                            Point(3, 1),
                            expectation=True)
        # points_1 = [Point(-1, 1), Point(2, 1), Point(3, 1)]
        # vertices_1 = [DelT.Vertex(point) for point in points_1]
        # half_facet_1 = DelT.HalfFacet(vertices_1[0], vertices_1[1:2],
        #                              None)
        # Basic cases in 2 dimensions
        quick_delaunay_test(Point(0, 2, 1),
                            Point(-1, 0, 1),
                            Point(1, 0, 1),
                            Point(0, -1, 1),
                            expectation=True)
        quick_delaunay_test(Point(0, 2, 1),
                            Point(-1, 0, 1),
                            Point(1, 0, 1),
                            Point(0, -0.3, 1),
                            expectation=False)
        # Similar basic 3D cases
        unit_circle_pts_3d = [
            Point(0, 0, -1, 1),
            Point(0, 1, 0, 1),
            Point(0, -1, 0, 1),
            Point(1, 0, 0, 1)
        ]
        quick_delaunay_test(*unit_circle_pts_3d,
                            Point(0, 0, 1.5, 1),
                            expectation=True)
        quick_delaunay_test(*unit_circle_pts_3d,
                            Point(0, 0, 0.5, 1),
                            expectation=False)

        # Cases with infinite points in the plane:
        quick_delaunay_test(Point(0, 1, 0),
                            Point(0.5, -400, 1),
                            Point(0, 0, 1),
                            Point(-1, -1, 0),
                            expectation=True)

        quick_delaunay_test(Point(-2, 0, 1),
                            Point(-0.6, 3.2, 1),
                            Point(3.2, 2.1, 1),
                            Point(1, 0, 0),
                            expectation=True)
예제 #23
0
 def test_length(self):
     """Test to see if length of a point makes sense"""
     self.assertTrue(len(self.c) == 3)
     self.assertTrue(len(Point(1, 2, 3, 4)) == 4)
     self.assertFalse(len(self.b) == 3)
예제 #24
0
 def test_subtraction(self):
     """Test point subtraction"""
     self.assertIsInstance(self.b - self.a, Vector)
     self.assertTrue(self.b - self.b == Vector(0, 0))
     self.assertTrue(self.b - self.a == Vector(1, 2))
     self.assertFalse(self.b - self.b == Point(0, 0))
예제 #25
0
    def test_ccw_homogeneous(self):
        """Tests ccw with extended homogeneous coordinates"""
        # One dimensional case:

        # Basic, hair-not-on-fire requirement
        self.assertNotEqual(ccw(Point(0, 1), Point(1, 1)), 0)
        self.assertEqual(ccw(Point(0, 1), Point(1, 1)),
                         ccw(Point(0), Point(1), homogeneous=False))

        # With one homogeneous coordinate
        self.assertEqual(ccw(Point(0, 1), Point(1, 1)),
                         ccw(Point(-1, 0), Point(2, 1)))

        # With two homogeneous coordinates
        self.assertEqual(ccw(Point(0, 1), Point(1, 1)),
                         ccw(Point(-10, 0), Point(5, 0)))

        # Make sure simple stuff works
        # Should be counterclockwise:
        self.assertEqual(ccw(self.homo_north, self.homo_south, self.homo_east),
                         1)
        # Should be colinear:
        self.assertEqual(ccw(Point(1, 0, 1), Point(0, 0, 1), Point(-1, 0, 1)),
                         0)
        # Should be clockwise:
        self.assertEqual(ccw(self.homo_north, self.homo_east, self.homo_south),
                         -1)

        # Now try some weird stuff

        # Tests involving one infinitely distance point:
        self.assertEqual(ccw(Point(1, 0, 1), Point(0, 0, 1), Point(0, 1, 0)),
                         -1)

        # Tests involving two infinitely distance points:
        self.assertEqual(ccw(Point(1, 0, 0), Point(0, 0, 1), Point(0, 1, 0)),
                         -1)
        self.assertEqual(ccw(Point(0, 1, 0), Point(0, 0, 1), Point(1, 0, 0)),
                         1)

        # Test with three points on the "boundary of the plane"
        self.assertEqual(ccw(Point(0, 1, 0), Point(-1, 0, 0), Point(0, -1, 0)),
                         1)
        self.assertEqual(ccw(Point(0, 1, 0), Point(1, 0, 0), Point(0, -1, 0)),
                         -1)
        # Same but with weirder points
        self.assertEqual(ccw(Point(1.8, 19, 0),
                             Point(309.7, 1, 0),
                             Point(-0.05, -10, 0)),
                         -1)

        # ANY finite point must satisfy this:
        queries = [Point(0, 0, 1), Point(1232, 4, 1),
                   Point(-320, -0.0, 1), Point(-1, -1, 1),
                   Point(1, 0, 1), Point(0, 1, 1)]
        for query in queries:
            self.assertEqual(ccw(Point(0, 1, 0), Point(-1, -1, 0), query), 1)
            self.assertEqual(ccw(Point(1, 0, 0), Point(0, 1, 0), query), 1)
예제 #26
0
class PointTestCase(unittest.TestCase):
    """Unit tests for the Point class."""

    def setUp(self):
        """Make some objects that are useful for most tests."""
        self.a = Point(0, 0)
        self.b = Point(1, 2)
        self.c = Point(1, 2, 3)

    def test_point_equal(self):
        """Tests if comparison of points for equality works"""
        self.assertTrue(Point(0, -9, 11.2) == Point(0, -9, 11.2))
        self.assertFalse(Point(0, -9, 1600002) == Point(0, -8, 1600002))
        # Different location
        self.assertFalse(Point(1, 4) == Point(1, 4, 5))

        # Drew's tests:
        self.assertFalse(self.a == self.b)
        self.assertTrue(self.b == self.b)
        self.assertTrue(Point(1, 2, 3) == Point(1, 2, 3))
        self.assertFalse(self.b == self.c)
        self.assertFalse(self.b == (1, 2))

    def test_misc_niceties(self):
        """I don't want  the empty point to be a thing. You may disagree."""
        with self.assertRaises(ValueError):
            Point()  # Try to make an empty point.

        # Make sure that we can evaluate a point to True
        self.assertTrue(self.a)

    def test_lift(self):
        """Make sure lifting works nicely."""

        # Define a function to use for testing
        def f(x):
            return x[0] * 2
        self.assertTrue(self.b.lift(f) == Point(1, 2, 2))
        self.assertFalse(self.c.lift(f) == Point(1, 2, 3, 4))
        self.assertFalse(self.c.lift(f) == Point(1, 2, 3))

        # Make sure that lifting a Point returns a Point
        self.assertIsInstance(self.b.lift(f), Point)

    def test_length(self):
        """Test to see if length of a point makes sense"""
        self.assertTrue(len(self.c) == 3)
        self.assertTrue(len(Point(1, 2, 3, 4)) == 4)
        self.assertFalse(len(self.b) == 3)

    def test_indexing(self):
        """Make sure that we can access elements of a point by index"""
        self.assertTrue(self.a[0] == 0)
        self.assertTrue(self.c[2] == 3)
        self.assertFalse(self.b[-1] == 10)

        with self.assertRaises(Exception):
            # I want a warning when I accidentally try to set values:
            self.b[-1] = 10

        self.assertIsInstance(self.a[:-1], Point)

    def test_subtraction(self):
        """Test point subtraction"""
        self.assertIsInstance(self.b - self.a, Vector)
        self.assertTrue(self.b - self.b == Vector(0, 0))
        self.assertTrue(self.b - self.a == Vector(1, 2))
        self.assertFalse(self.b - self.b == Point(0, 0))

    def test_to_vector(self):
        """Test turning points into vectors"""
        self.assertEqual(self.c.to_vector(), Vector(1, 2, 3))
        self.assertEqual(self.a.to_vector(), Vector(0, 0))
        self.assertEqual(self.b.to_vector(), Vector(1, 2))
        self.assertNotEqual(self.b.to_vector(), Vector(1, 2, 0))

    def test_hashing(self):
        """Make sure point hashing works and does not cause collisions"""
        # Add 400 points' hashes to a set and make sure 400 things are in the
        # set
        some_hashes = set()
        for x in range(-10, 10):
            for y in range(-10, 10):
                some_hashes.add(hash(Point(x, y, 1)))
        self.assertEqual(len(some_hashes), 400)

        self.assertEqual(hash(Point(0, 1, 2)),
                         hash(Point(0, 1, 2)))