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 setUp(self) -> None: self.v1 = Vertex(0, 0, 3, 0) self.v2 = Vertex(1, 0, 4, 0) self.v3 = Vertex(2, 0, 3, 1) self.face1 = Face(0, self.v1, self.v2, self.v3) self.face2 = Face(1, self.v3, self.v2, self.v1)
class TestBeamForce(unittest.TestCase): def setUp(self) -> None: self.v1 = Vertex(0, 0, 0, 0) self.v2 = Vertex(1, 2, 0, 0) self.edge = Edge(0, self.v1, self.v2, EDGE_BOUNDARY) def test_is_zero_if_position_did_not_change(self): set_all_beam_forces([self.edge]) self.assertEqual(self.v1.total_force(), Vector3(0, 0, 0)) def test_creates_shrinking_force(self): self.v2.x = 4 set_all_beam_forces([self.edge]) self.assertTrue( same_direction_vec(self.v1.total_force(), Vector3(1, 0, 0))) self.assertTrue( same_direction_vec(self.v2.total_force(), Vector3(-1, 0, 0))) def test_creates_expanding_force(self): self.v2.x = 1 set_all_beam_forces([self.edge]) self.assertTrue( same_direction_vec(self.v1.total_force(), Vector3(-1, 0, 0))) self.assertTrue( same_direction_vec(self.v2.total_force(), Vector3(1, 0, 0)))
def setUp(self) -> None: self.v1 = Vertex(0, 0, 0, 0) self.v2 = Vertex(1, 1, 0, 0) self.v3 = Vertex(2, 0, 1, 0) self.v4 = Vertex(0, 0, 0, 1) self.edge = Edge(0, self.v1, self.v3, EDGE_VALLEY) self.face1 = Face(1, self.v1, self.v2, self.v3) self.face2 = Face(2, self.v1, self.v3, self.v4)
def test_normalize_bounding(self): verts = [Vertex(0, 1.0, 1.0, 1.0), Vertex(1, -20.0, -20.0, -20.0)] scale_fac = verts[1].pos.length / 5.0 normalized = normalize_bounding_box(verts, 10) self.assertEqual( normalized[0].pos, Vector3(1.0 / scale_fac, 1.0 / scale_fac, 1.0 / scale_fac)) self.assertEqual( normalized[1].pos, Vector3(-20.0 / scale_fac, -20.0 / scale_fac, -20.0 / scale_fac))
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 setUp(self) -> None: self.v1 = Vertex(0, 1, -1, 0) self.v2 = Vertex(1, 1, 1, 0) self.v3 = Vertex(2, -1, 1, 0) self.v4 = Vertex(3, -1, -1, 0) self.face1 = Face(0, self.v1, self.v2, self.v4) self.face2 = Face(1, self.v2, self.v3, self.v4) self.edge = Edge(2, self.v4, self.v2, EDGE_UNKNOWN) self.edge.face_right = self.face1 self.edge.face_left = self.face2
def test_does_nothing_for_already_translated(self): verts = [ Vertex(1, 1.0, 1.0, 1.0), Vertex(2, 1.0, 1.0, -1.0), Vertex(4, 1.0, -1.0, 1.0), Vertex(5, -1.0, 1.0, 1.0), Vertex(6, -1.0, -1.0, 1.0), Vertex(7, 1.0, -1.0, -1.0), Vertex(8, -1.0, 1.0, -1.0), Vertex(9, -1.0, -1.0, -1.0), ] initial_positions = list(map(lambda v: v.pos, verts)) trans = list(translate_to_origin(verts)) self.assertEqual(initial_positions, list(map(lambda v: v.pos, trans)))
class TestFaceForce(unittest.TestCase): def setUp(self) -> None: self.v1 = Vertex(0, 1, 0, 0) self.v2 = Vertex(1, -1, 0, 0) self.v3 = Vertex(2, 0, 2, 0) self.face = Face(0, self.v1, self.v2, self.v3) def test_is_zero_if_no_position_changed(self): set_all_face_forces([self.face]) self.assertEqual(self.v1.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v2.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v3.total_force(), Vector3(0, 0, 0)) def test_creates_pulling_force_if_face_is_squished(self): self.v3.y = 1 set_all_face_forces([self.face]) self.assertTrue(same_direction_vec(self.v3.total_force(), Vector3(0, 1, 0))) def test_creates_pushing_force_if_face_is_expanded(self): self.v3.y = 3 set_all_face_forces([self.face]) self.assertTrue(same_direction_vec(self.v3.total_force(), Vector3(0, -1, 0)))
def test_does_nothing_for_vertices_on_the_edge(self): verts = [ Vertex(1, 1.0, 1.0, 1.0), Vertex(2, 1.0, 1.0, -1.0), Vertex(4, 1.0, -1.0, 1.0), Vertex(5, -1.0, 1.0, 1.0), Vertex(6, -1.0, -1.0, 1.0), Vertex(7, 1.0, -1.0, -1.0), Vertex(8, -1.0, 1.0, -1.0), Vertex(9, -1.0, -1.0, -1.0), ] initial_positions = list(map(lambda v: v.pos, verts)) normalized = normalize_bounding_box(verts, 2 * math.sqrt(3)) self.assertEqual(initial_positions, list(map(lambda v: v.pos, normalized)))
class TestDampingForce(unittest.TestCase): def setUp(self) -> None: self.v1 = Vertex(0, 0, 0, 0) self.v2 = Vertex(1, 1, 1, 0) self.edge = Edge(0, self.v1, self.v2, EDGE_FLAT) def test_is_zero_if_velocity_is_zero(self): set_all_damping_forces([self.edge]) self.assertEqual(self.v1.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v2.total_force(), Vector3(0, 0, 0)) def test_creates_equal_forces_when_velocity_changes(self): self.v1.velocity = Vector3(-1, 0, 0) self.v2.velocity = Vector3(1, 0, 0) set_all_damping_forces([self.edge]) self.assertEqual(self.v1.total_force(), -self.v2.total_force()) self.assertTrue( same_direction_vec(self.v1.total_force(), Vector3(1, 0, 0))) self.assertTrue( same_direction_vec(self.v2.total_force(), Vector3(-1, 0, 0)))
class TestCreaseForce(unittest.TestCase): def setUp(self) -> None: self.v1 = Vertex(0, 1, -1, 0) self.v2 = Vertex(1, 1, 1, 0) self.v3 = Vertex(2, -1, 1, 0) self.v4 = Vertex(3, -1, -1, 0) self.face1 = Face(0, self.v1, self.v2, self.v4) self.face2 = Face(1, self.v2, self.v3, self.v4) self.edge = Edge(2, self.v4, self.v2, EDGE_UNKNOWN) self.edge.face_right = self.face1 self.edge.face_left = self.face2 def test_is_zero_if_is_not_being_folded(self): set_all_crease_forces([self.edge]) self.assertEqual(self.v1.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v2.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v3.total_force(), Vector3(0, 0, 0)) self.assertEqual(self.v4.total_force(), Vector3(0, 0, 0)) def test_creates_upward_force_for_valley_assignment(self): self.edge.assignment = EDGE_VALLEY self.edge.target_angle = angle_from_assignment(self.edge.assignment) set_all_crease_forces([self.edge]) self.assertTrue( same_direction_vec(self.v1.total_force(), Vector3(0, 0, 1))) self.assertTrue( same_direction_vec(self.v2.total_force(), Vector3(0, 0, -1))) self.assertTrue( same_direction_vec(self.v3.total_force(), Vector3(0, 0, 1))) self.assertTrue( same_direction_vec(self.v4.total_force(), Vector3(0, 0, -1))) def test_creates_downwards_force_for_mountain_assignment(self): self.edge.assignment = EDGE_MOUNTAIN self.edge.target_angle = angle_from_assignment(self.edge.assignment) set_all_crease_forces([self.edge]) self.assertTrue( same_direction_vec(self.v1.total_force(), Vector3(0, 0, -1))) self.assertTrue( same_direction_vec(self.v2.total_force(), Vector3(0, 0, 1))) self.assertTrue( same_direction_vec(self.v3.total_force(), Vector3(0, 0, -1))) self.assertTrue( same_direction_vec(self.v4.total_force(), Vector3(0, 0, 1)))
def test_does_nothing_when_all_correctly_bound(self): verts = [Vertex(0, 0.0, 0.0, 0.0), Vertex(1, 1.0, 1.0, 1.0)] normalized = normalize_bounding_box(verts, 2 * math.sqrt(3)) self.assertEqual(list(map(lambda vert: vert.pos, normalized)), [Vector3(0, 0, 0), Vector3(1, 1, 1)])
def test_translates_to_origin(self): verts = [ Vertex(1, 2.0, 2.0, 1.0), Vertex(2, 2.0, 2.0, -1.0), Vertex(4, 2.0, 0.0, 1.0), Vertex(5, -0.0, 2.0, 1.0), Vertex(6, -0.0, 0.0, 1.0), Vertex(7, 2.0, 0.0, -1.0), Vertex(8, -0.0, 2.0, -1.0), Vertex(9, -0.0, 0.0, -1.0), ] trans = list(map(lambda v: v.pos, translate_to_origin(verts))) expected_trans = list( map(lambda v: v.pos, [ Vertex(1, 1.0, 1.0, 1.0), Vertex(2, 1.0, 1.0, -1.0), Vertex(4, 1.0, -1.0, 1.0), Vertex(5, -1.0, 1.0, 1.0), Vertex(6, -1.0, -1.0, 1.0), Vertex(7, 1.0, -1.0, -1.0), Vertex(8, -1.0, 1.0, -1.0), Vertex(9, -1.0, -1.0, -1.0), ])) self.assertEqual(trans, expected_trans)
def test_zero_division_does_not_throw(self): verts = [Vertex(0, 0, 0, 0)] normalize_bounding_box(verts, 10)
def test_returns_zero_length(self): edge = Edge(0, Vertex(0, 0, 0, 0), Vertex(1, 0, 0, 0), EDGE_VALLEY) self.assertEqual(edge.length, 0)
def setUp(self) -> None: self.v1 = Vertex(0, 0, 0, 0) self.v2 = Vertex(1, 1, 1, 0) self.edge = Edge(0, self.v1, self.v2, EDGE_FLAT)
def setUp(self) -> None: self.v1 = Vertex(0, 0, 0, 0) self.v2 = Vertex(1, 2, 0, 0) self.edge = Edge(0, self.v1, self.v2, EDGE_BOUNDARY)
def setUp(self) -> None: self.v1 = Vertex(0, 1, 0, 0) self.v2 = Vertex(1, -1, 0, 0) self.v3 = Vertex(2, 0, 2, 0) self.face = Face(0, self.v1, self.v2, self.v3)
def setUp(self) -> None: self.v = Vertex(0, 0, 0, 0)
class TestVertexForces(unittest.TestCase): def setUp(self) -> None: self.v = Vertex(0, 0, 0, 0) def test_forces_manipulation(self): self.v.set_force(ForceName.BEAM, Vector3(1, 1, 0)) self.v.set_force(ForceName.DAMPING, Vector3(1, 1, 0)) self.v.set_force(ForceName.CREASE, Vector3(1, 1, 0)) self.v.set_force(ForceName.FACE, Vector3(1, 1, -1)) self.assertEqual(self.v.total_force(), Vector3(4, 4, -1)) self.v.reset_forces() self.assertEqual(self.v.total_force(), Vector3(0, 0, 0))