Bug fix: missing path in gerber, feature: Gcode parse/plot
This commit is contained in:
77
camlib.py
77
camlib.py
@@ -8,6 +8,7 @@ import cairo
|
|||||||
#import sys
|
#import sys
|
||||||
|
|
||||||
from numpy import arctan2, Inf, array
|
from numpy import arctan2, Inf, array
|
||||||
|
from matplotlib.figure import Figure
|
||||||
|
|
||||||
# See: http://toblerity.org/shapely/manual.html
|
# See: http://toblerity.org/shapely/manual.html
|
||||||
from shapely.geometry import Polygon, LineString, Point
|
from shapely.geometry import Polygon, LineString, Point
|
||||||
@@ -164,7 +165,7 @@ class Gerber (Geometry):
|
|||||||
"aperture":current_aperture})
|
"aperture":current_aperture})
|
||||||
continue
|
continue
|
||||||
if indexD3 == 0: # Flash?
|
if indexD3 == 0: # Flash?
|
||||||
print "Warning: Uninplemented flash style:", gline
|
print "WARNING: Uninplemented flash style:", gline
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if gline.find("G37*") != -1: # end region
|
if gline.find("G37*") != -1: # end region
|
||||||
@@ -192,7 +193,12 @@ class Gerber (Geometry):
|
|||||||
self.fraction = int(gline[indexX + 2])
|
self.fraction = int(gline[indexX + 2])
|
||||||
continue
|
continue
|
||||||
print "WARNING: Line ignored:", gline
|
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):
|
def create_geometry(self):
|
||||||
if len(self.buffered_paths) == 0:
|
if len(self.buffered_paths) == 0:
|
||||||
self.buffer_paths()
|
self.buffer_paths()
|
||||||
@@ -241,7 +247,26 @@ class CNCjob():
|
|||||||
# Output G-Code
|
# Output G-Code
|
||||||
self.gcode = ""
|
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:
|
if append == False:
|
||||||
self.gcode = ""
|
self.gcode = ""
|
||||||
t = "G0%d X%.4fY%.4f\n"
|
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 += "G00 Z%.4f\n"%self.z_move # Move to travel height
|
||||||
self.gcode += "M03\n" # Spindle start
|
self.gcode += "M03\n" # Spindle start
|
||||||
self.gcode += self.pausecode + "\n"
|
self.gcode += self.pausecode + "\n"
|
||||||
|
|
||||||
for geo in geometry:
|
for geo in geometry:
|
||||||
|
|
||||||
if type(geo) == Polygon:
|
if type(geo) == Polygon:
|
||||||
@@ -291,6 +317,10 @@ class CNCjob():
|
|||||||
self.gcode += "M05\n" # Spindle stop
|
self.gcode += "M05\n" # Spindle stop
|
||||||
|
|
||||||
def create_gcode_geometry(self):
|
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 = []
|
geometry = []
|
||||||
|
|
||||||
gobjs = gparse1b(self.gcode)
|
gobjs = gparse1b(self.gcode)
|
||||||
@@ -302,7 +332,7 @@ class CNCjob():
|
|||||||
for gobj in gobjs:
|
for gobj in gobjs:
|
||||||
if 'Z' in gobj:
|
if 'Z' in gobj:
|
||||||
if ('X' in gobj or 'Y' in gobj) and gobj['Z'] != current['Z']:
|
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
|
print " To:", gobj
|
||||||
current['Z'] = gobj['Z']
|
current['Z'] = gobj['Z']
|
||||||
|
|
||||||
@@ -332,10 +362,45 @@ class CNCjob():
|
|||||||
for code in gobj:
|
for code in gobj:
|
||||||
current[code] = gobj[code]
|
current[code] = gobj[code]
|
||||||
|
|
||||||
|
self.G_geometry = geometry
|
||||||
return 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):
|
def fix_poly(poly):
|
||||||
'''
|
'''
|
||||||
Fixes polygons with internal cutouts by identifying
|
Fixes polygons with internal cutouts by identifying
|
||||||
|
|||||||
BIN
camlib.pyc
BIN
camlib.pyc
Binary file not shown.
Reference in New Issue
Block a user