diff --git a/camlib.py b/camlib.py index 893464f..d7a79df 100644 --- a/camlib.py +++ b/camlib.py @@ -8,6 +8,7 @@ import cairo #import sys from numpy import arctan2, Inf, array +from matplotlib.figure import Figure # See: http://toblerity.org/shapely/manual.html from shapely.geometry import Polygon, LineString, Point @@ -164,7 +165,7 @@ class Gerber (Geometry): "aperture":current_aperture}) continue if indexD3 == 0: # Flash? - print "Warning: Uninplemented flash style:", gline + print "WARNING: Uninplemented flash style:", gline continue if gline.find("G37*") != -1: # end region @@ -192,7 +193,12 @@ class Gerber (Geometry): self.fraction = int(gline[indexX + 2]) continue print "WARNING: Line ignored:", gline - + + if len(path) > 1: + # EOF, create shapely LineString if something in path + self.paths.append({"linestring":LineString(path), + "aperture":last_path_aperture}) + def create_geometry(self): if len(self.buffered_paths) == 0: self.buffer_paths() @@ -241,7 +247,26 @@ class CNCjob(): # Output G-Code self.gcode = "" - def generate_from_geometry(self, geometry, append=True): + # Bounds of geometry given to CNCjob.generate_from_geometry() + self.input_geometry_bounds = None + + # Tool diameter given to CNCjob.generate_from_geometry() + self.tooldia = 0 + + # Output generated by CNCjob.create_gcode_geometry() + self.G_geometry = None + + def generate_from_geometry(self, geometry, append=True, tooldia=None): + ''' + Generates G-Code for geometry (Shapely collection). + ''' + if tooldia == None: + tooldia = self.tooldia + else: + self.tooldia = tooldia + + self.input_geometry_bounds = geometry.bounds + if append == False: self.gcode = "" t = "G0%d X%.4fY%.4f\n" @@ -252,6 +277,7 @@ class CNCjob(): self.gcode += "G00 Z%.4f\n"%self.z_move # Move to travel height self.gcode += "M03\n" # Spindle start self.gcode += self.pausecode + "\n" + for geo in geometry: if type(geo) == Polygon: @@ -291,6 +317,10 @@ class CNCjob(): self.gcode += "M05\n" # Spindle stop def create_gcode_geometry(self): + ''' + G-Code parser. Generates dictionary with single-segment LineString's + and "kind" indicating cut or travel, fast or feedrate speed. + ''' geometry = [] gobjs = gparse1b(self.gcode) @@ -302,7 +332,7 @@ class CNCjob(): for gobj in gobjs: if 'Z' in gobj: if ('X' in gobj or 'Y' in gobj) and gobj['Z'] != current['Z']: - print "WARNING: No orthogonal motion: From", current + print "WARNING: Non-orthogonal motion: From", current print " To:", gobj current['Z'] = gobj['Z'] @@ -332,10 +362,45 @@ class CNCjob(): for code in gobj: current[code] = gobj[code] + self.G_geometry = geometry return geometry + + def plot(self, tooldia=None, dpi=75, margin=0.1, + color={"T":["#F0E24D", "#B5AB3A"], "C":["#5E6CFF", "#4650BD"]}, + alpha={"T":0.3, "C":1.0}): + ''' + Creates a Matplotlib figure with a plot of the + G-code job. + ''' + if tooldia == None: + tooldia = self.tooldia + + fig = Figure(dpi=dpi) + ax = fig.add_subplot(111) + ax.set_aspect(1) + xmin, ymin, xmax, ymax = self.input_geometry_bounds + ax.set_xlim(xmin-margin, xmax+margin) + ax.set_ylim(ymin-margin, ymax+margin) + + if tooldia == 0: + for geo in self.G_geometry: + linespec = '--' + linecolor = color[geo['kind'][0]][1] + if geo['kind'][0] == 'C': + linespec = 'k-' + x, y = geo['geom'].coords.xy + ax.plot(x, y, linespec, color=linecolor) + else: + for geo in self.G_geometry: + poly = geo['geom'].buffer(tooldia/2.0) + patch = PolygonPatch(poly, facecolor=color[geo['kind'][0]][0], + edgecolor=color[geo['kind'][0]][1], + alpha=alpha[geo['kind'][0]], zorder=2) + ax.add_patch(patch) + + return fig + - - def fix_poly(poly): ''' Fixes polygons with internal cutouts by identifying diff --git a/camlib.pyc b/camlib.pyc index 09514b8..05a5333 100644 Binary files a/camlib.pyc and b/camlib.pyc differ