def test_handles_convex_polygons(self): """ The original Delaunay algorithm always outputs a convex polygon so, let us make sure that the boundary stays the same if it is concave """ v1 = Vertex(0, 0, 10, 0) v2 = Vertex(1, 10, 0, 0) v3 = Vertex(2, 4, 0, 0) v4 = Vertex(3, 4, 4, 0) face = [v1, v2, v3, v4] triangles = triangulate(face) self.assertEqual(len(triangles), 2) # There is only one way to triangulate this polygon, so that it preserves the boundary tri1 = [v1, v2, v4] tri2 = [v2, v3, v4] tri1_present = False if self.isTrianglesEqual(tri1, triangles[0]): tri1_present = True elif self.isTrianglesEqual(tri1, triangles[1]): tri1_present = True tri2_present = False if self.isTrianglesEqual(tri2, triangles[0]): tri2_present = True elif self.isTrianglesEqual(tri2, triangles[1]): tri2_present = True self.assertTrue(tri1_present) self.assertTrue(tri2_present)
def test_does_not_change_triangular_face(self): face = [Vertex(0, 1, 0, 0), Vertex(1, 2, 0, 0), Vertex(2, 0, 2, 0)] triangulated = triangulate(face) self.assertEqual(len(triangulated), 1) triangulated_pos_set = set(map(lambda v: v.pos, triangulated[0])) pos_set = set(map(lambda v: v.pos, face)) self.assertEqual(pos_set, triangulated_pos_set)
def test_triangulates_square_along_yz_plane(self): face = [ Vertex(0, 0, 0, 0), Vertex(1, 0, 1, 0), Vertex(2, 0, 1, 1), Vertex(3, 0, 0, 1), ] triangulated = triangulate(face) diagonal1 = np.array([0, 1, 1]) diagonal2 = np.array([0, -1, 1]) self.assertTriangulatesSquare(triangulated, diagonal1, diagonal2)
def test_handles_numerical_stability_in_disjoint_check(self): """ Looks strange, this test case is a real-life scenario that happened. Disjointness check is "too-precise", sometimes even for convex polygons, it would return too little triangles from the triangulation """ v1 = Vertex(0, 3, 0, 0) v2 = Vertex(1, 4, 0, 0) v3 = Vertex(2, 4.571428571428572, 1.428571428571428, 0) v4 = Vertex(3, 3.047619047619047, 0.9523809523809523, 0) face = [v1, v2, v3, v4] triangles = triangulate(face) self.assertEqual(len(triangles), 2)
def create_faces(vertices, edges, faces_vertices): edges_bag = {} # TODO: Think of a better solution for this edges_bag for e in edges: edges_bag[(e.v1.id, e.v2.id)] = e faces = [] for i, vertices_index in enumerate(faces_vertices): face_to_triangulate = list(map(lambda x: vertices[x], vertices_index)) triangles = triangulate(face_to_triangulate) for face_vertices in triangles: face = Face(i, *face_vertices) # TODO: ? This makes id in Face not unique (which might not be a problem) face_edges = zip(face_vertices, face_vertices[1:] + [face_vertices[0]]) for p in face_edges: v1 = p[0].id v2 = p[1].id # Introduce new edges if (v1, v2) not in edges_bag and (v2, v1) not in edges_bag: edge = Edge(-1, p[0], p[1], EDGE_FLAT) edges.append(edge) edges_bag[(v1, v2)] = edge if (v1, v2) in edges_bag: edges_bag[(v1, v2)].face_left = face elif (v2, v1) in edges_bag: edges_bag[(v2, v1)].face_right = face else: raise RuntimeError("Impossible. You messed up edges map. ") faces.append(face) return faces