Minimal Excellon class and test script
This commit is contained in:
123
camlib.py
123
camlib.py
@@ -228,7 +228,7 @@ class Gerber (Geometry):
|
|||||||
[poly['polygon'] for poly in self.regions] +
|
[poly['polygon'] for poly in self.regions] +
|
||||||
flash_polys)
|
flash_polys)
|
||||||
|
|
||||||
class CNCjob():
|
class CNCjob:
|
||||||
def __init__(self, units="in", kind="generic", z_move = 0.1,
|
def __init__(self, units="in", kind="generic", z_move = 0.1,
|
||||||
feedrate = 3.0, z_cut = -0.002):
|
feedrate = 3.0, z_cut = -0.002):
|
||||||
# Options
|
# Options
|
||||||
@@ -256,6 +256,45 @@ class CNCjob():
|
|||||||
# Output generated by CNCjob.create_gcode_geometry()
|
# Output generated by CNCjob.create_gcode_geometry()
|
||||||
self.G_geometry = None
|
self.G_geometry = None
|
||||||
|
|
||||||
|
def generate_from_excellon(self, exobj):
|
||||||
|
'''
|
||||||
|
Generates G-code for drilling from excellon text.
|
||||||
|
self.gcode becomes a list, each element is a
|
||||||
|
different job for each tool in the excellon code.
|
||||||
|
'''
|
||||||
|
self.kind = "drill"
|
||||||
|
self.gcode = []
|
||||||
|
|
||||||
|
t = "G00 X%.4fY%.4f\n"
|
||||||
|
down = "G01 Z%.4f\n"%self.z_cut
|
||||||
|
up = "G01 Z%.4f\n"%self.z_move
|
||||||
|
|
||||||
|
for tool in exobj.tools:
|
||||||
|
|
||||||
|
points = []
|
||||||
|
gcode = ""
|
||||||
|
|
||||||
|
for drill in exobj.drill:
|
||||||
|
if drill['tool'] == tool:
|
||||||
|
points.append(drill['point'])
|
||||||
|
|
||||||
|
gcode = self.unitcode[self.units] + "\n"
|
||||||
|
gcode += self.absolutecode + "\n"
|
||||||
|
gcode += self.feedminutecode + "\n"
|
||||||
|
gcode += "F%.2f\n"%self.feedrate
|
||||||
|
gcode += "G00 Z%.4f\n"%self.z_move # Move to travel height
|
||||||
|
gcode += "M03\n" # Spindle start
|
||||||
|
gcode += self.pausecode + "\n"
|
||||||
|
|
||||||
|
for point in points:
|
||||||
|
gcode += t%point
|
||||||
|
gcode += down + up
|
||||||
|
|
||||||
|
gcode += t%(0,0)
|
||||||
|
gcode += "M05\n" # Spindle stop
|
||||||
|
|
||||||
|
self.gcode.append(gcode)
|
||||||
|
|
||||||
def generate_from_geometry(self, geometry, append=True, tooldia=None):
|
def generate_from_geometry(self, geometry, append=True, tooldia=None):
|
||||||
'''
|
'''
|
||||||
Generates G-Code for geometry (Shapely collection).
|
Generates G-Code for geometry (Shapely collection).
|
||||||
@@ -314,15 +353,19 @@ class CNCjob():
|
|||||||
|
|
||||||
print "WARNING: G-code generation not implemented for %s"%(str(type(geo)))
|
print "WARNING: G-code generation not implemented for %s"%(str(type(geo)))
|
||||||
|
|
||||||
|
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
||||||
|
self.gcode += "G00 X0Y0\n"
|
||||||
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
|
G-Code parser (from self.gcode). Generates dictionary with
|
||||||
and "kind" indicating cut or travel, fast or feedrate speed.
|
single-segment LineString's and "kind" indicating cut or travel,
|
||||||
|
fast or feedrate speed.
|
||||||
'''
|
'''
|
||||||
geometry = []
|
geometry = []
|
||||||
|
|
||||||
|
# TODO: ???? bring this into the class??
|
||||||
gobjs = gparse1b(self.gcode)
|
gobjs = gparse1b(self.gcode)
|
||||||
|
|
||||||
# Last known instruction
|
# Last known instruction
|
||||||
@@ -401,6 +444,80 @@ class CNCjob():
|
|||||||
return fig
|
return fig
|
||||||
|
|
||||||
|
|
||||||
|
class Excellon(Geometry):
|
||||||
|
def __init__(self):
|
||||||
|
Geometry.__init__(self)
|
||||||
|
|
||||||
|
self.tools = {}
|
||||||
|
|
||||||
|
self.drills = []
|
||||||
|
|
||||||
|
def parse_file(self, filename):
|
||||||
|
efile = open(filename, 'r')
|
||||||
|
estr = efile.readlines()
|
||||||
|
efile.close()
|
||||||
|
self.parse_lines(estr)
|
||||||
|
|
||||||
|
def parse_lines(self, elines):
|
||||||
|
'''
|
||||||
|
Main Excellon parser.
|
||||||
|
'''
|
||||||
|
current_tool = ""
|
||||||
|
|
||||||
|
for eline in elines:
|
||||||
|
|
||||||
|
## Tool definitions ##
|
||||||
|
# TODO: Verify all this
|
||||||
|
indexT = eline.find("T")
|
||||||
|
indexC = eline.find("C")
|
||||||
|
indexF = eline.find("F")
|
||||||
|
# Type 1
|
||||||
|
if indexT != -1 and indexC > indexT and indexF > indexF:
|
||||||
|
tool = eline[1:indexC]
|
||||||
|
spec = eline[indexC+1:indexF]
|
||||||
|
self.tools[tool] = spec
|
||||||
|
continue
|
||||||
|
# Type 2
|
||||||
|
# TODO: Is this inches?
|
||||||
|
#indexsp = eline.find(" ")
|
||||||
|
#indexin = eline.find("in")
|
||||||
|
#if indexT != -1 and indexsp > indexT and indexin > indexsp:
|
||||||
|
# tool = eline[1:indexsp]
|
||||||
|
# spec = eline[indexsp+1:indexin]
|
||||||
|
# self.tools[tool] = spec
|
||||||
|
# continue
|
||||||
|
# Type 3
|
||||||
|
if indexT != -1 and indexC > indexT:
|
||||||
|
tool = eline[1:indexC]
|
||||||
|
spec = eline[indexC+1:-1]
|
||||||
|
self.tools[tool] = spec
|
||||||
|
continue
|
||||||
|
|
||||||
|
## Tool change
|
||||||
|
if indexT == 0:
|
||||||
|
current_tool = eline[1:-1]
|
||||||
|
continue
|
||||||
|
|
||||||
|
## Drill
|
||||||
|
indexX = eline.find("X")
|
||||||
|
indexY = eline.find("Y")
|
||||||
|
if indexX != -1 and indexY != -1:
|
||||||
|
x = float(int(eline[indexX+1:indexY])/10000.0)
|
||||||
|
y = float(int(eline[indexY+1:-1])/10000.0)
|
||||||
|
self.drills.append({'point':Point((x,y)), 'tool':current_tool})
|
||||||
|
continue
|
||||||
|
|
||||||
|
print "WARNING: Line ignored:", eline
|
||||||
|
|
||||||
|
def create_geometry(self):
|
||||||
|
self.solid_geometry = []
|
||||||
|
sizes = {}
|
||||||
|
for tool in self.tools:
|
||||||
|
sizes[tool] = float(self.tools[tool])
|
||||||
|
for drill in self.drills:
|
||||||
|
poly = Point(drill['point']).buffer(sizes[drill['tool']]/2.0)
|
||||||
|
self.solid_geometry.append(poly)
|
||||||
|
|
||||||
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.
45
test_excellon_1.py
Normal file
45
test_excellon_1.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on Sun Jan 05 13:30:47 2014
|
||||||
|
|
||||||
|
@author: jpcaram
|
||||||
|
"""
|
||||||
|
|
||||||
|
from camlib import *
|
||||||
|
#from matplotlib.figure import Figure
|
||||||
|
from matplotlib import pyplot
|
||||||
|
|
||||||
|
# Gerber. To see if the Excellon is correct
|
||||||
|
project_dir = "C:/Users/jpcaram/Dropbox/VNA/KiCad_Squarer/"
|
||||||
|
gerber_filename = project_dir + "KiCad_Squarer-F_Cu.gtl"
|
||||||
|
g = Gerber()
|
||||||
|
g.parse_file(gerber_filename)
|
||||||
|
g.create_geometry()
|
||||||
|
|
||||||
|
excellon_filename = project_dir + "KiCad_Squarer.drl"
|
||||||
|
ex = Excellon()
|
||||||
|
ex.parse_file(excellon_filename)
|
||||||
|
ex.create_geometry()
|
||||||
|
|
||||||
|
#fig = Figure()
|
||||||
|
fig = pyplot.figure()
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_aspect(1)
|
||||||
|
|
||||||
|
# Plot gerber
|
||||||
|
for geo in g.solid_geometry:
|
||||||
|
x, y = geo.exterior.coords.xy
|
||||||
|
plot(x, y, 'k-')
|
||||||
|
for ints in geo.interiors:
|
||||||
|
x, y = ints.coords.xy
|
||||||
|
ax.plot(x, y, 'k-')
|
||||||
|
|
||||||
|
# Plot excellon
|
||||||
|
for geo in ex.solid_geometry:
|
||||||
|
x, y = geo.exterior.coords.xy
|
||||||
|
plot(x, y, 'r-')
|
||||||
|
for ints in geo.interiors:
|
||||||
|
x, y = ints.coords.xy
|
||||||
|
ax.plot(x, y, 'g-')
|
||||||
|
|
||||||
|
fig.show()
|
||||||
Reference in New Issue
Block a user