diff --git a/camlib.py b/camlib.py index 67389085..9a4d57b6 100644 --- a/camlib.py +++ b/camlib.py @@ -665,6 +665,22 @@ def get_bounds(geometry_set): def arc(center, radius, start, stop, direction, steps_per_circ): + """ + Creates a Shapely.LineString for the specified arc. + @param center: Coordinates of the center [x, y] + @type center: list + @param radius: Radius of the arc. + @type radius: float + @param start: Starting angle in radians + @type start: float + @param stop: End angle in radians + @type stop: float + @param direction: Orientation of the arc, "CW" or "CCW" + @type direction: string + @param steps_per_circ: Number of straight line segments to + represent a circle. + @type steps_per_circ: int + """ da_sign = {"cw": -1.0, "ccw": 1.0} points = [] if direction == "ccw" and stop <= start: @@ -683,6 +699,41 @@ def arc(center, radius, start, stop, direction, steps_per_circ): return LineString(points) +def clear_poly(poly, tooldia, overlap = 0.1): + """ + Creates a list of Shapely geometry objects covering the inside + of a Shapely.Polygon. Use for removing all the copper in a region + or bed flattening. + @param poly: Target polygon + @type poly: Shapely.Polygon + @param tooldia: Diameter of the tool + @type tooldia: float + @param overlap: Fraction of the tool diameter to overlap + in each pass. + @type overlap: float + @return list of Shapely.Polygon + """ + poly_cuts = [poly.buffer(-tooldia/2.0)] + while True: + poly = poly_cuts[-1].buffer(-tooldia*(1-overlap)) + if poly.area > 0: + poly_cuts.append(poly) + else: + break + return poly_cuts + + +def find_polygon(poly_set, point): + """ + Return the first polygon in the list of polygons poly_set + that contains the given point. + """ + p = Point(point) + for poly in poly_set: + if poly.contains(p): + return poly + return None + ############### cam.py #################### def coord(gstr, digits, fraction): """ diff --git a/cirkuix.py b/cirkuix.py index 3a6f0f76..2fa6574d 100644 --- a/cirkuix.py +++ b/cirkuix.py @@ -278,7 +278,9 @@ class CirkuixGeometry(CirkuixObj, Geometry): "multicolored": False, "cutz": -0.002, "travelz": 0.1, - "feedrate": 5.0 + "feedrate": 5.0, + "painttooldia": 0.0625, + "paintoverlap": 0.15 }) self.form_kinds.update({ @@ -287,7 +289,9 @@ class CirkuixGeometry(CirkuixObj, Geometry): "multicolored": "cb", "cutz": "entry_eval", "travelz": "entry_eval", - "feedrate": "entry_eval" + "feedrate": "entry_eval", + "painttooldia": "entry_eval", + "paintoverlap": "entry_eval" }) def plot(self, figure): @@ -366,6 +370,8 @@ class App: # a key if self.stuff self.selected_item_name = None + self.plot_click_subscribers = {} + # For debugging only def someThreadFunc(self): print "Hello World!" @@ -707,7 +713,6 @@ class App: # TODO: Do something if this is None. Offer changing name? self.new_object("geometry", iso_name, iso_init) - def on_generate_cncjob(self, widget): print "Generating CNC job" @@ -731,6 +736,30 @@ class App: self.new_object("cncjob", job_name, job_init) + def on_generate_paintarea(self, widget): + self.info("Click inside the desired polygon.") + geo = self.stuff[self.selected_item_name] + geo.read_form() + tooldia = geo.options["painttooldia"] + overlap = geo.options["paintoverlap"] + + def doit(event): + self.plot_click_subscribers.pop("generate_paintarea") + self.info("") + point = [event.xdata, event.ydata] + poly = find_polygon(geo.solid_geometry, point) + + def gen_paintarea(geo_obj, app_obj): + assert isinstance(geo_obj, CirkuixGeometry) + assert isinstance(app_obj, App) + cp = clear_poly(poly, tooldia, overlap) + geo_obj.solid_geometry = cp + + name = self.selected_item_name + "_paint" + self.new_object("geometry", name, gen_paintarea) + + self.plot_click_subscribers["generate_paintarea"] = doit + def on_cncjob_tooldia_activate(self, widget): job = self.stuff[self.selected_item_name] tooldia = self.get_eval("entry_eval_cncjob_tooldia") @@ -947,6 +976,9 @@ class App: try: print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%( event.button, event.x, event.y, event.xdata, event.ydata) + + for subscriber in self.plot_click_subscribers: + self.plot_click_subscribers[subscriber](event) except: print "Outside plot!" diff --git a/cirkuix.ui b/cirkuix.ui index 84b7d981..c900cf21 100644 --- a/cirkuix.ui +++ b/cirkuix.ui @@ -661,6 +661,111 @@ 8 + + + True + False + 5 + 0 + 3 + Paint Area: + + + + + + False + True + 9 + + + + + True + False + 2 + 5 + + + True + False + 1 + Tool diam: + + + 0 + 0 + 1 + 1 + + + + + True + True + + True + + + 1 + 0 + 1 + 1 + + + + + True + False + 1 + Overlap: + + + 0 + 1 + 1 + 1 + + + + + True + True + + True + + + 1 + 1 + 1 + 1 + + + + + False + True + 10 + + + + + Generate + True + True + True + + + + + False + True + 11 + + + + +