def test_plotplanner_flush(self): """ Intro test for plotplanner. This is needlessly complex. final value is "on", and provides commands. 128 means settings were changed. 64 indicates x_axis major 32 indicates x_dir, y_dir 256 indicates ended. 1 means cut. 0 means move. :return: """ settings = {"power": 1000} plan = PlotPlanner(settings) for i in range(211): plan.push(LineCut(Point(0, 0), Point(5, 100), settings=settings)) plan.push(LineCut(Point(100, 50), Point(0, 0), settings=settings)) plan.push( LineCut(Point(50, -50), Point(100, -100), settings={"power": 0})) q = 0 for x, y, on in plan.gen(): # print(x, y, on) if q == i: # for x, y, on in plan.process_plots(None): # print("FLUSH!", x, y, on) plan.clear() break q += 1
def test_cutcode(self): """ Test intro to Cutcode. :return: """ cutcode = CutCode() settings = dict() cutcode.append(LineCut(Point(0, 0), Point(100, 100), settings=settings)) cutcode.append(LineCut(Point(100, 100), Point(0, 0), settings=settings)) cutcode.append(LineCut(Point(50, -50), Point(100, -100), settings=settings)) cutcode.append( QuadCut(Point(0, 0), Point(100, 100), Point(200, 0), settings=settings) ) path = Path(*list(cutcode.as_elements())) self.assertEqual( path, "M 0,0 L 100,100 L 0,0 M 50,-50 L 100,-100 M 0,0 Q 100,100 200,0" )
def test_plotplanner_constant_move_xy_rect(self): """ With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs. @return: """ settings = { "power": 1000, "constant_move_x": True, "constant_move_y": True } plan = PlotPlanner(settings) plan.push(LineCut(Point(0, 0), Point(0, 100), settings=settings)) plan.push(LineCut(Point(0, 100), Point(100, 100), settings=settings)) plan.push(LineCut(Point(100, 100), Point(100, 0), settings=settings)) plan.push(LineCut(Point(100, 0), Point(0, 0), settings=settings)) last_x = None last_y = None for x, y, on in plan.gen(): if on == 4: last_x = x last_y = y if on > 1: continue cx = x cy = y if cx is None: continue if last_x is not None: total_dx = cx - last_x total_dy = cy - last_y dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1 dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1 for i in range(1, max(abs(total_dx), abs(total_dy)) + 1): nx = last_x + (i * dx) ny = last_y + (i * dy) # print(nx, ny, on) # print(x, y, on) last_x = cx last_y = cy print(f"Moving to {x} {y}")
def test_plotplanner_constant_move_x_ppi(self): """ With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs. @return: """ settings = {"power": 500, "constant_move_x": True} plan = PlotPlanner(settings) plan.push(LineCut(Point(0, 0), Point(20, 2), settings=settings)) plan.push(LineCut(Point(20, 2), Point(20, 5), settings=settings)) plan.push(LineCut(Point(20, 5), Point(100, 10), settings=settings)) last_x = None last_y = None last_on = None for x, y, on in plan.gen(): if on == 4: last_x = x last_y = y if on > 1: continue if last_on is not None: self.assertNotEqual(last_on, on) last_on = on cx = x cy = y if cx is None: continue if last_x is not None: total_dx = cx - last_x total_dy = cy - last_y dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1 dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1 self.assertFalse(dx == 0) for i in range(1, max(abs(total_dx), abs(total_dy)) + 1): nx = last_x + (i * dx) ny = last_y + (i * dy) # print(nx, ny, on) # print(x, y, on) last_x = cx last_y = cy
def test_plotplanner_constant_move_y(self): """ With smooth_raster set to 2 we should never have x = 0. The x should *always* be in motion. @return: """ settings = {"power": 1000, "constant_move_y": True} plan = PlotPlanner(settings) plan.push(LineCut(Point(0, 0), Point(2, 20), settings=settings)) plan.push(LineCut(Point(2, 20), Point(5, 20), settings=settings)) plan.push(LineCut(Point(5, 20), Point(10, 100), settings=settings)) last_x = None last_y = None for x, y, on in plan.gen(): if on == 4: last_x = x last_y = y if on > 1: continue cx = x cy = y if cx is None: continue if last_x is not None: total_dx = cx - last_x total_dy = cy - last_y dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1 dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1 self.assertFalse(dy == 0) for i in range(0, max(abs(total_dx), abs(total_dy))): nx = last_x + (i * dx) ny = last_y + (i * dy) # print(nx, ny, on) last_x = cx last_y = cy print(f"Moving to {x} {y}")
def test_plotplanner_constant_xy_end(self): """ With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs. @return: """ for q in range(100): settings = { "power": 1000, "constant_move_x": bool(random.randint(0, 1)), "constant_move_y": bool(random.randint(0, 1)), } plan = PlotPlanner(settings) goal_x = None goal_y = None for i in range(10): goal_x = random.randint(0, 100) goal_y = random.randint(0, 100) plan.push( LineCut( Point(random.randint(0, 100), random.randint(0, 100)), Point(goal_x, goal_y), settings=settings, )) break_list = list(plan.queue) last_x = None last_y = None for x, y, on in plan.gen(): if on == 4: last_x = x last_y = y if on > 1: continue last_x = x last_y = y if last_x != goal_x: print(settings.get("constant_move_x")) print(settings.get("constant_move_y")) for seg in break_list: print(repr(seg)) self.assertEqual(last_x, goal_x) if last_y != goal_y: print(settings.get("constant_move_x")) print(settings.get("constant_move_y")) for seg in break_list: print(repr(seg)) self.assertEqual(last_y, goal_y)
def test_plotplanner_static_issue(self): settings = { "power": 1000, "constant_move_x": True, "constant_move_y": False, } plan = PlotPlanner(settings) plan.debug = True lines = ( ((41, 45), (14, 43)), ((32, 67), (32, 61)), ) for line in lines: plan.push( LineCut( Point(line[0][0], line[0][1]), Point(line[1][0], line[1][1]), settings=settings, )) goal_x = lines[-1][-1][0] goal_y = lines[-1][-1][1] break_list = list(plan.queue) last_x = None last_y = None for x, y, on in plan.gen(): if on == 4: last_x = x last_y = y if on > 1: continue last_x = x last_y = y if last_x != goal_x: for seg in break_list: print(repr(seg)) self.assertEqual(last_x, goal_x) if last_y != goal_y: for seg in break_list: print(repr(seg)) self.assertEqual(last_y, goal_y)
def as_cutobjects(self, closed_distance=15, passes=1): """Generator of cutobjects for a particular operation.""" settings = self.derive() for node in self.children: if node.type == "reference": node = node.node if node.type == "elem image": object_path = node.image box = object_path.bbox() path = Path( Polygon( (box[0], box[1]), (box[0], box[3]), (box[2], box[3]), (box[2], box[1]), )) elif node.type == "elem path": path = abs(node.path) path.approximate_arcs_with_cubics() else: path = abs(Path(node.shape)) path.approximate_arcs_with_cubics() settings["line_color"] = path.stroke for subpath in path.as_subpaths(): sp = Path(subpath) if len(sp) == 0: continue closed = ( isinstance(sp[-1], Close) or abs(sp.z_point - sp.current_point) <= closed_distance) group = CutGroup( None, closed=closed, settings=settings, passes=passes, ) group.path = Path(subpath) group.original_op = self.type for seg in subpath: if isinstance(seg, Move): pass # Move operations are ignored. elif isinstance(seg, Close): if seg.start != seg.end: group.append( LineCut( seg.start, seg.end, settings=settings, passes=passes, parent=group, )) elif isinstance(seg, Line): if seg.start != seg.end: group.append( LineCut( seg.start, seg.end, settings=settings, passes=passes, parent=group, )) elif isinstance(seg, QuadraticBezier): group.append( QuadCut( seg.start, seg.control, seg.end, settings=settings, passes=passes, parent=group, )) elif isinstance(seg, CubicBezier): group.append( CubicCut( seg.start, seg.control1, seg.control2, seg.end, settings=settings, passes=passes, parent=group, )) if len(group) > 0: group[0].first = True for i, cut_obj in enumerate(group): cut_obj.closed = closed try: cut_obj.next = group[i + 1] except IndexError: cut_obj.last = True cut_obj.next = group[0] cut_obj.previous = group[i - 1] yield group