def test_two_segments(): pt = PathCanvas() pt.move_to(100, 100) pt.line_to(150, 200) pt.move_to(17, 17) pt.rel_line_to(100, 200) pt.close_path() assert pt.paths == [ Path([Point(100.0, 100.0), Point(150.0, 200.0)]), Path([Point(17.0, 17.0), Point(117.0, 217.0), Point(17.0, 17.0)]), ]
def combinable_paths_maybe_loops(draw): """Makes single-segment paths, with loops a possibility.""" endpoints = draw(lists(ipoints, min_size=2, max_size=200, unique_by=tuple)) rand = draw(randoms()) paths = set() point_use = collections.defaultdict(int) target_number = len(endpoints) / 3 if target_number < 1: target_number = 1 while len(paths) < target_number: # Choose two points at random from the possible endpoints, and make a # segment. a, b = rand.sample(endpoints, k=2) if (a, b) in paths: continue paths.add((a, b)) # Track how many times the points have been used. point_use[a] += 1 point_use[b] += 1 # Any point in two segments is no longer a candidate as an endpoint. if point_use[a] == 2: endpoints.remove(a) if point_use[b] == 2: endpoints.remove(b) return [Path(p) for p in paths]
def test_reflect_xy(): pt = PathCanvas() pt.move_to(100, 100) pt.reflect_xy(1000, 2000) pt.line_to(200, 200) assert pt.paths == [ Path([Point(100.0, 100.0), Point(1800, 3800)]), ]
def test_translation(): pt = PathCanvas() pt.move_to(100, 100) pt.translate(1000, 2000) pt.line_to(10, 20) assert pt.paths == [ Path([Point(100.0, 100.0), Point(1010.0, 2020.0)]), ]
def test_rel_line_to(): pt = PathCanvas() pt.translate(1000, 2000) pt.move_to(0, 0) pt.rel_line_to(100, 200) assert pt.paths == [ Path([Point(1000.0, 2000.0), Point(1100.0, 2200.0)]), ]
def test_save_restore(): pt = PathCanvas() pt.move_to(100, 100) pt.translate(1000, 2000) pt.line_to(10, 20) pt.save() pt.translate(1, 2) pt.move_to(1, 2) pt.line_to(2, 4) pt.restore() pt.move_to(1, 2) pt.line_to(2, 4) assert pt.paths == [ Path([Point(100.0, 100.0), Point(1010.0, 2020.0)]), Path([Point(1002.0, 2004.0), Point(1003.0, 2006.0)]), Path([Point(1001.0, 2002.0), Point(1002.0, 2004.0)]), ]
def test_reflect_line(): pt = PathCanvas() pt.move_to(100, 100) pt.reflect_line(Point(50, -50), Point(150, 50)) pt.line_to(100, 50) pt.line_to(100, 100) assert pt.paths == [ Path([Point(100.0, 100.0), Point(150, 0), Point(200, 0)]), ]
def path_pieces(path, segs_to_points): """Produce a new series of paths, split at intersection points. Yields a series of pieces (paths). The pieces trace the same line as the original path. The endpoints of the pieces are all intersection points in `segs_to_points`, or the endpoints of the original path, if it isn't circular. The pieces are in order along `path`, so consecutive pieces end and begin at the same point. If `path` is closed, then the first piece returned will begin at the first cut, not at the path's first point. """ # If path is circular, then the first piece we collect has to be added to # the last piece, so save it for later. collecting_head = path.closed head = None piece = [] for pt in path: if not piece: piece.append(pt) else: seg = Segment(piece[-1], pt) cuts = segs_to_points.get(seg) if cuts is not None: cuts = seg.sort_along(cuts) for cut in cuts: ptcut = Point(*cut) piece.append(ptcut) if collecting_head: head = piece collecting_head = False else: yield Path(piece) piece = [ptcut] piece.append(pt) piece = Path(piece) if head: piece = piece.join(Path(head)) yield piece
def combinable_paths_no_loops(draw): """Makes varying-length paths, but no loops.""" path_points = draw( lists(ipoints, min_size=2, max_size=200, unique_by=tuple)) rand = draw(randoms()) paths = [[]] length = rand.randint(2, 4) for pt in path_points: paths[-1].append(pt) length -= 1 if length == 0: paths.append([]) length = rand.randint(2, 4) joinable = (rand.random() > .5) if joinable: paths[-1].append(pt) if len(paths[-1]) < 2: paths.pop() rand.shuffle(paths) return [Path(p) for p in paths]
def test_clean_path(path, result): assert equal_path(Path(path).clean(), Path(result))
def test_join_paths(p1, p2, result): pth1, pth2 = Path(p1), Path(p2) pth1r, pth2r = Path(p1[::-1]), Path(p2[::-1]) if result is not None: result = Path(result) def same(p1, p2): if p1 is None and p2 is None: return True elif p1 is None or p2 is None: return False else: return equal_path(p1, p2) assert same(pth1.join(pth2), result) assert same(pth1r.join(pth2), result) assert same(pth1.join(pth2r), result) assert same(pth1r.join(pth2r), result)
def test_equal_path(p1, p2, result): assert equal_path(Path(p1), Path(p2)) == result
def test_any_collinear(points, result): assert Path(points).any_collinear() == result