Test update

This commit is contained in:
Hamilton Kibbe 2014-10-19 22:23:00 -04:00
parent 6d2db67e6d
commit 18e3b87625
21 changed files with 14343 additions and 69 deletions

View file

@ -23,3 +23,4 @@ gerber-tools provides utilities for working with Gerber (RS-274X) and Excellon
files in python.
"""
from .common import read

View file

@ -29,14 +29,13 @@ if __name__ == '__main__':
for filename in sys.argv[1:]:
print "parsing %s" % filename
if 'GTO' in filename or 'GBO' in filename:
ctx.set_color((1,1,1))
ctx.set_color((1, 1, 1))
ctx.set_alpha(0.8)
elif 'GTS' in filename or 'GBS' in filename:
ctx.set_color((0.2,0.2,0.75))
ctx.set_color((0.2, 0.2, 0.75))
ctx.set_alpha(0.8)
gerberfile = read(filename)
gerberfile.render(ctx)
print('Saving image to test.svg')
ctx.dump('test.svg')

View file

@ -59,6 +59,33 @@ class FileSettings(object):
else:
raise KeyError()
def __setitem__(self, key, value):
if key == 'notation':
if value not in ['absolute', 'incremental']:
raise ValueError('Notation must be either \
absolute or incremental')
self.notation = value
elif key == 'units':
if value not in ['inch', 'metric']:
raise ValueError('Units must be either inch or metric')
self.units = value
elif key == 'zero_suppression':
if value not in ['leading', 'trailing']:
raise ValueError('Zero suppression must be either leading or \
trailling')
self.zero_suppression = value
elif key == 'format':
if len(value) != 2:
raise ValueError('Format must be a tuple(n=2) of integers')
self.format = value
def __eq__(self, other):
return (self.notation == other.notation and
self.units == other.units and
self.zero_suppression == other.zero_suppression and
self.format == other.format)
class CamFile(object):
""" Base class for Gerber/Excellon files.
@ -127,6 +154,12 @@ class CamFile(object):
return FileSettings(self.notation, self.units, self.zero_suppression,
self.format)
@property
def bounds(self):
""" File baundaries
"""
pass
def render(self, ctx, filename=None):
""" Generate image of layer.

View file

@ -44,8 +44,6 @@ def read(filename):
detected_settings = detect_excellon_format(filename)
settings = FileSettings(**detected_settings)
zeros = ''
print('Detected %d:%d format with %s zero suppression' %
(settings.format[0], settings.format[1], settings.zero_suppression))
return ExcellonParser(settings).parse(filename)
@ -108,7 +106,6 @@ class ExcellonFile(CamFile):
f.write(statement.to_excellon() + '\n')
class ExcellonParser(object):
""" Excellon File Parser
@ -129,10 +126,10 @@ class ExcellonParser(object):
self.active_tool = None
self.pos = [0., 0.]
if settings is not None:
self.units = settings['units']
self.zero_suppression = settings['zero_suppression']
self.notation = settings['notation']
self.format = settings['format']
self.units = settings.units
self.zero_suppression = settings.zero_suppression
self.notation = settings.notation
self.format = settings.format
@property
@ -163,14 +160,14 @@ class ExcellonParser(object):
def parse(self, filename):
with open(filename, 'r') as f:
for line in f:
self._parse(line)
self._parse(line.strip())
return ExcellonFile(self.statements, self.tools, self.hits,
self._settings(), filename)
def _parse(self, line):
line = line.strip()
zs = self._settings()['zero_suppression']
fmt = self._settings()['format']
#line = line.strip()
zs = self._settings().zero_suppression
fmt = self._settings().format
if line[0] == ';':
self.statements.append(CommentStmt.from_excellon(line))

View file

@ -107,8 +107,8 @@ class ExcellonTool(ExcellonStatement):
commands = re.split('([BCFHSTZ])', line)[1:]
commands = [(command, value) for command, value in pairwise(commands)]
args = {}
nformat = settings['format']
zero_suppression = settings['zero_suppression']
nformat = settings.format
zero_suppression = settings.zero_suppression
for cmd, val in commands:
if cmd == 'B':
args['retract_rate'] = parse_gerber_value(val, nformat, zero_suppression)
@ -157,8 +157,8 @@ class ExcellonTool(ExcellonStatement):
self.hit_count = 0
def to_excellon(self):
fmt = self.settings['format']
zs = self.settings['zero_suppression']
fmt = self.settings.format
zs = self.settings.format
stmt = 'T%d' % self.number
if self.retract_rate is not None:
stmt += 'B%s' % write_gerber_value(self.retract_rate, fmt, zs)
@ -201,7 +201,7 @@ class ToolSelectionStmt(ExcellonStatement):
tool_statement : ToolSelectionStmt
ToolSelectionStmt representation of `line.`
"""
line = line.strip()[1:]
line = line[1:]
compensation_index = None
tool = int(line[:2])
if len(line) > 2:
@ -230,10 +230,10 @@ class CoordinateStmt(ExcellonStatement):
y_coord = None
if line[0] == 'X':
splitline = line.strip('X').split('Y')
x_coord = parse_gerber_value(splitline[0].strip(), nformat,
x_coord = parse_gerber_value(splitline[0], nformat,
zero_suppression)
if len(splitline) == 2:
y_coord = parse_gerber_value(splitline[1].strip(), nformat,
y_coord = parse_gerber_value(splitline[1], nformat,
zero_suppression)
else:
y_coord = parse_gerber_value(line.strip(' Y'), nformat,
@ -257,7 +257,7 @@ class CommentStmt(ExcellonStatement):
@classmethod
def from_excellon(cls, line):
return cls(line.strip().lstrip(';'))
return cls(line.lstrip(';'))
def __init__(self, comment):
self.comment = comment
@ -380,7 +380,7 @@ class LinkToolStmt(ExcellonStatement):
@classmethod
def from_excellon(cls, line):
linked = [int(tool) for tool in line.strip().split('/')]
linked = [int(tool) for tool in line.split('/')]
return cls(linked)
def __init__(self, linked_tools):

View file

@ -72,10 +72,10 @@ class FSParamStmt(ParamStmt):
def from_dict(cls, stmt_dict):
"""
"""
param = stmt_dict.get('param').strip()
param = stmt_dict.get('param')
zeros = 'leading' if stmt_dict.get('zero') == 'L' else 'trailing'
notation = 'absolute' if stmt_dict.get('notation') == 'A' else 'incremental'
x = map(int, stmt_dict.get('x').strip())
x = map(int, stmt_dict.get('x'))
fmt = (x[0], x[1])
return cls(param, zeros, notation, fmt)
@ -471,9 +471,9 @@ class CoordStmt(Statement):
@classmethod
def from_dict(cls, stmt_dict, settings):
zeros = settings['zero_suppression']
format = settings['format']
function = stmt_dict.get('function')
zeros = settings.zero_suppression
format = settings.format
function = stmt_dict['function']
x = stmt_dict.get('x')
y = stmt_dict.get('y')
i = stmt_dict.get('i')
@ -527,8 +527,8 @@ class CoordStmt(Statement):
"""
Statement.__init__(self, "COORD")
self.zero_suppression = settings['zero_suppression']
self.format = settings['format']
self.zero_suppression = settings.zero_suppression
self.format = settings.format
self.function = function
self.x = x
self.y = y
@ -628,7 +628,6 @@ class QuadrantModeStmt(Statement):
@classmethod
def from_gerber(cls, line):
line = line.strip()
if 'G74' not in line and 'G75' not in line:
raise ValueError('%s is not a valid quadrant mode statement'
% line)
@ -651,7 +650,6 @@ class RegionModeStmt(Statement):
@classmethod
def from_gerber(cls, line):
line = line.strip()
if 'G36' not in line and 'G37' not in line:
raise ValueError('%s is not a valid region mode statement' % line)
return (cls('on') if line[:3] == 'G36' else cls('off'))

View file

@ -112,8 +112,6 @@ class GerberFile(CamFile):
f.write(statement.to_gerber())
class GerberParser(object):
""" GerberParser
"""
@ -324,21 +322,21 @@ class GerberParser(object):
Gerber/Excellon statement to evaluate.
"""
if isinstance(stmt, (CommentStmt, UnknownStmt, EofStmt)):
return
if isinstance(stmt, CoordStmt):
self._evaluate_coord(stmt)
elif isinstance(stmt, ParamStmt):
self._evaluate_param(stmt)
elif isinstance(stmt, CoordStmt):
self._evaluate_coord(stmt)
elif isinstance(stmt, ApertureStmt):
self._evaluate_aperture(stmt)
elif isinstance(stmt, (RegionModeStmt, QuadrantModeStmt)):
self._evaluate_mode(stmt)
elif isinstance(stmt, (CommentStmt, UnknownStmt, EofStmt)):
return
else:
raise Exception("Invalid statement to evaluate")

View file

@ -0,0 +1,503 @@
G75*
%MOIN*%
%OFA0B0*%
%FSLAX24Y24*%
%IPPOS*%
%LPD*%
%AMOC8*
5,1,8,0,0,1.08239X$1,22.5*
%
%ADD10C,0.0000*%
%ADD11C,0.0004*%
D10*
X000300Y003064D02*
X000300Y018064D01*
X022800Y018064D01*
X022800Y003064D01*
X000300Y003064D01*
X001720Y005114D02*
X001722Y005164D01*
X001728Y005214D01*
X001738Y005263D01*
X001752Y005311D01*
X001769Y005358D01*
X001790Y005403D01*
X001815Y005447D01*
X001843Y005488D01*
X001875Y005527D01*
X001909Y005564D01*
X001946Y005598D01*
X001986Y005628D01*
X002028Y005655D01*
X002072Y005679D01*
X002118Y005700D01*
X002165Y005716D01*
X002213Y005729D01*
X002263Y005738D01*
X002312Y005743D01*
X002363Y005744D01*
X002413Y005741D01*
X002462Y005734D01*
X002511Y005723D01*
X002559Y005708D01*
X002605Y005690D01*
X002650Y005668D01*
X002693Y005642D01*
X002734Y005613D01*
X002773Y005581D01*
X002809Y005546D01*
X002841Y005508D01*
X002871Y005468D01*
X002898Y005425D01*
X002921Y005381D01*
X002940Y005335D01*
X002956Y005287D01*
X002968Y005238D01*
X002976Y005189D01*
X002980Y005139D01*
X002980Y005089D01*
X002976Y005039D01*
X002968Y004990D01*
X002956Y004941D01*
X002940Y004893D01*
X002921Y004847D01*
X002898Y004803D01*
X002871Y004760D01*
X002841Y004720D01*
X002809Y004682D01*
X002773Y004647D01*
X002734Y004615D01*
X002693Y004586D01*
X002650Y004560D01*
X002605Y004538D01*
X002559Y004520D01*
X002511Y004505D01*
X002462Y004494D01*
X002413Y004487D01*
X002363Y004484D01*
X002312Y004485D01*
X002263Y004490D01*
X002213Y004499D01*
X002165Y004512D01*
X002118Y004528D01*
X002072Y004549D01*
X002028Y004573D01*
X001986Y004600D01*
X001946Y004630D01*
X001909Y004664D01*
X001875Y004701D01*
X001843Y004740D01*
X001815Y004781D01*
X001790Y004825D01*
X001769Y004870D01*
X001752Y004917D01*
X001738Y004965D01*
X001728Y005014D01*
X001722Y005064D01*
X001720Y005114D01*
X001670Y016064D02*
X001672Y016114D01*
X001678Y016164D01*
X001688Y016213D01*
X001702Y016261D01*
X001719Y016308D01*
X001740Y016353D01*
X001765Y016397D01*
X001793Y016438D01*
X001825Y016477D01*
X001859Y016514D01*
X001896Y016548D01*
X001936Y016578D01*
X001978Y016605D01*
X002022Y016629D01*
X002068Y016650D01*
X002115Y016666D01*
X002163Y016679D01*
X002213Y016688D01*
X002262Y016693D01*
X002313Y016694D01*
X002363Y016691D01*
X002412Y016684D01*
X002461Y016673D01*
X002509Y016658D01*
X002555Y016640D01*
X002600Y016618D01*
X002643Y016592D01*
X002684Y016563D01*
X002723Y016531D01*
X002759Y016496D01*
X002791Y016458D01*
X002821Y016418D01*
X002848Y016375D01*
X002871Y016331D01*
X002890Y016285D01*
X002906Y016237D01*
X002918Y016188D01*
X002926Y016139D01*
X002930Y016089D01*
X002930Y016039D01*
X002926Y015989D01*
X002918Y015940D01*
X002906Y015891D01*
X002890Y015843D01*
X002871Y015797D01*
X002848Y015753D01*
X002821Y015710D01*
X002791Y015670D01*
X002759Y015632D01*
X002723Y015597D01*
X002684Y015565D01*
X002643Y015536D01*
X002600Y015510D01*
X002555Y015488D01*
X002509Y015470D01*
X002461Y015455D01*
X002412Y015444D01*
X002363Y015437D01*
X002313Y015434D01*
X002262Y015435D01*
X002213Y015440D01*
X002163Y015449D01*
X002115Y015462D01*
X002068Y015478D01*
X002022Y015499D01*
X001978Y015523D01*
X001936Y015550D01*
X001896Y015580D01*
X001859Y015614D01*
X001825Y015651D01*
X001793Y015690D01*
X001765Y015731D01*
X001740Y015775D01*
X001719Y015820D01*
X001702Y015867D01*
X001688Y015915D01*
X001678Y015964D01*
X001672Y016014D01*
X001670Y016064D01*
X020060Y012714D02*
X020062Y012764D01*
X020068Y012814D01*
X020078Y012863D01*
X020091Y012912D01*
X020109Y012959D01*
X020130Y013005D01*
X020154Y013048D01*
X020182Y013090D01*
X020213Y013130D01*
X020247Y013167D01*
X020284Y013201D01*
X020324Y013232D01*
X020366Y013260D01*
X020409Y013284D01*
X020455Y013305D01*
X020502Y013323D01*
X020551Y013336D01*
X020600Y013346D01*
X020650Y013352D01*
X020700Y013354D01*
X020750Y013352D01*
X020800Y013346D01*
X020849Y013336D01*
X020898Y013323D01*
X020945Y013305D01*
X020991Y013284D01*
X021034Y013260D01*
X021076Y013232D01*
X021116Y013201D01*
X021153Y013167D01*
X021187Y013130D01*
X021218Y013090D01*
X021246Y013048D01*
X021270Y013005D01*
X021291Y012959D01*
X021309Y012912D01*
X021322Y012863D01*
X021332Y012814D01*
X021338Y012764D01*
X021340Y012714D01*
X021338Y012664D01*
X021332Y012614D01*
X021322Y012565D01*
X021309Y012516D01*
X021291Y012469D01*
X021270Y012423D01*
X021246Y012380D01*
X021218Y012338D01*
X021187Y012298D01*
X021153Y012261D01*
X021116Y012227D01*
X021076Y012196D01*
X021034Y012168D01*
X020991Y012144D01*
X020945Y012123D01*
X020898Y012105D01*
X020849Y012092D01*
X020800Y012082D01*
X020750Y012076D01*
X020700Y012074D01*
X020650Y012076D01*
X020600Y012082D01*
X020551Y012092D01*
X020502Y012105D01*
X020455Y012123D01*
X020409Y012144D01*
X020366Y012168D01*
X020324Y012196D01*
X020284Y012227D01*
X020247Y012261D01*
X020213Y012298D01*
X020182Y012338D01*
X020154Y012380D01*
X020130Y012423D01*
X020109Y012469D01*
X020091Y012516D01*
X020078Y012565D01*
X020068Y012614D01*
X020062Y012664D01*
X020060Y012714D01*
X020170Y016064D02*
X020172Y016114D01*
X020178Y016164D01*
X020188Y016213D01*
X020202Y016261D01*
X020219Y016308D01*
X020240Y016353D01*
X020265Y016397D01*
X020293Y016438D01*
X020325Y016477D01*
X020359Y016514D01*
X020396Y016548D01*
X020436Y016578D01*
X020478Y016605D01*
X020522Y016629D01*
X020568Y016650D01*
X020615Y016666D01*
X020663Y016679D01*
X020713Y016688D01*
X020762Y016693D01*
X020813Y016694D01*
X020863Y016691D01*
X020912Y016684D01*
X020961Y016673D01*
X021009Y016658D01*
X021055Y016640D01*
X021100Y016618D01*
X021143Y016592D01*
X021184Y016563D01*
X021223Y016531D01*
X021259Y016496D01*
X021291Y016458D01*
X021321Y016418D01*
X021348Y016375D01*
X021371Y016331D01*
X021390Y016285D01*
X021406Y016237D01*
X021418Y016188D01*
X021426Y016139D01*
X021430Y016089D01*
X021430Y016039D01*
X021426Y015989D01*
X021418Y015940D01*
X021406Y015891D01*
X021390Y015843D01*
X021371Y015797D01*
X021348Y015753D01*
X021321Y015710D01*
X021291Y015670D01*
X021259Y015632D01*
X021223Y015597D01*
X021184Y015565D01*
X021143Y015536D01*
X021100Y015510D01*
X021055Y015488D01*
X021009Y015470D01*
X020961Y015455D01*
X020912Y015444D01*
X020863Y015437D01*
X020813Y015434D01*
X020762Y015435D01*
X020713Y015440D01*
X020663Y015449D01*
X020615Y015462D01*
X020568Y015478D01*
X020522Y015499D01*
X020478Y015523D01*
X020436Y015550D01*
X020396Y015580D01*
X020359Y015614D01*
X020325Y015651D01*
X020293Y015690D01*
X020265Y015731D01*
X020240Y015775D01*
X020219Y015820D01*
X020202Y015867D01*
X020188Y015915D01*
X020178Y015964D01*
X020172Y016014D01*
X020170Y016064D01*
X020060Y008714D02*
X020062Y008764D01*
X020068Y008814D01*
X020078Y008863D01*
X020091Y008912D01*
X020109Y008959D01*
X020130Y009005D01*
X020154Y009048D01*
X020182Y009090D01*
X020213Y009130D01*
X020247Y009167D01*
X020284Y009201D01*
X020324Y009232D01*
X020366Y009260D01*
X020409Y009284D01*
X020455Y009305D01*
X020502Y009323D01*
X020551Y009336D01*
X020600Y009346D01*
X020650Y009352D01*
X020700Y009354D01*
X020750Y009352D01*
X020800Y009346D01*
X020849Y009336D01*
X020898Y009323D01*
X020945Y009305D01*
X020991Y009284D01*
X021034Y009260D01*
X021076Y009232D01*
X021116Y009201D01*
X021153Y009167D01*
X021187Y009130D01*
X021218Y009090D01*
X021246Y009048D01*
X021270Y009005D01*
X021291Y008959D01*
X021309Y008912D01*
X021322Y008863D01*
X021332Y008814D01*
X021338Y008764D01*
X021340Y008714D01*
X021338Y008664D01*
X021332Y008614D01*
X021322Y008565D01*
X021309Y008516D01*
X021291Y008469D01*
X021270Y008423D01*
X021246Y008380D01*
X021218Y008338D01*
X021187Y008298D01*
X021153Y008261D01*
X021116Y008227D01*
X021076Y008196D01*
X021034Y008168D01*
X020991Y008144D01*
X020945Y008123D01*
X020898Y008105D01*
X020849Y008092D01*
X020800Y008082D01*
X020750Y008076D01*
X020700Y008074D01*
X020650Y008076D01*
X020600Y008082D01*
X020551Y008092D01*
X020502Y008105D01*
X020455Y008123D01*
X020409Y008144D01*
X020366Y008168D01*
X020324Y008196D01*
X020284Y008227D01*
X020247Y008261D01*
X020213Y008298D01*
X020182Y008338D01*
X020154Y008380D01*
X020130Y008423D01*
X020109Y008469D01*
X020091Y008516D01*
X020078Y008565D01*
X020068Y008614D01*
X020062Y008664D01*
X020060Y008714D01*
X020170Y005064D02*
X020172Y005114D01*
X020178Y005164D01*
X020188Y005213D01*
X020202Y005261D01*
X020219Y005308D01*
X020240Y005353D01*
X020265Y005397D01*
X020293Y005438D01*
X020325Y005477D01*
X020359Y005514D01*
X020396Y005548D01*
X020436Y005578D01*
X020478Y005605D01*
X020522Y005629D01*
X020568Y005650D01*
X020615Y005666D01*
X020663Y005679D01*
X020713Y005688D01*
X020762Y005693D01*
X020813Y005694D01*
X020863Y005691D01*
X020912Y005684D01*
X020961Y005673D01*
X021009Y005658D01*
X021055Y005640D01*
X021100Y005618D01*
X021143Y005592D01*
X021184Y005563D01*
X021223Y005531D01*
X021259Y005496D01*
X021291Y005458D01*
X021321Y005418D01*
X021348Y005375D01*
X021371Y005331D01*
X021390Y005285D01*
X021406Y005237D01*
X021418Y005188D01*
X021426Y005139D01*
X021430Y005089D01*
X021430Y005039D01*
X021426Y004989D01*
X021418Y004940D01*
X021406Y004891D01*
X021390Y004843D01*
X021371Y004797D01*
X021348Y004753D01*
X021321Y004710D01*
X021291Y004670D01*
X021259Y004632D01*
X021223Y004597D01*
X021184Y004565D01*
X021143Y004536D01*
X021100Y004510D01*
X021055Y004488D01*
X021009Y004470D01*
X020961Y004455D01*
X020912Y004444D01*
X020863Y004437D01*
X020813Y004434D01*
X020762Y004435D01*
X020713Y004440D01*
X020663Y004449D01*
X020615Y004462D01*
X020568Y004478D01*
X020522Y004499D01*
X020478Y004523D01*
X020436Y004550D01*
X020396Y004580D01*
X020359Y004614D01*
X020325Y004651D01*
X020293Y004690D01*
X020265Y004731D01*
X020240Y004775D01*
X020219Y004820D01*
X020202Y004867D01*
X020188Y004915D01*
X020178Y004964D01*
X020172Y005014D01*
X020170Y005064D01*
D11*
X022869Y007639D02*
X022869Y013789D01*
M02*

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,66 @@
G75*
%MOIN*%
%OFA0B0*%
%FSLAX24Y24*%
%IPPOS*%
%LPD*%
%AMOC8*
5,1,8,0,0,1.08239X$1,22.5*
%
%ADD10C,0.0634*%
%ADD11C,0.1360*%
%ADD12C,0.0680*%
%ADD13C,0.1340*%
%ADD14C,0.0476*%
D10*
X017200Y009464D03*
X018200Y009964D03*
X018200Y010964D03*
X017200Y010464D03*
X017200Y011464D03*
X018200Y011964D03*
D11*
X020700Y012714D03*
X020700Y008714D03*
D12*
X018350Y016514D02*
X018350Y017114D01*
X017350Y017114D02*
X017350Y016514D01*
X007350Y016664D02*
X007350Y017264D01*
X006350Y017264D02*
X006350Y016664D01*
X005350Y016664D02*
X005350Y017264D01*
X001800Y012564D02*
X001200Y012564D01*
X001200Y011564D02*
X001800Y011564D01*
X001800Y010564D02*
X001200Y010564D01*
X001200Y009564D02*
X001800Y009564D01*
X001800Y008564D02*
X001200Y008564D01*
D13*
X002350Y005114D03*
X002300Y016064D03*
X020800Y016064D03*
X020800Y005064D03*
D14*
X015650Y006264D03*
X013500Y006864D03*
X012100Y005314D03*
X009250Y004064D03*
X015200Y004514D03*
X013550Y008764D03*
X013350Y010114D03*
X013300Y011464D03*
X011650Y013164D03*
X010000Y015114D03*
X006500Y013714D03*
X004150Y011564D03*
X014250Y014964D03*
X015850Y009914D03*
M02*

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
%
M48
M72
T01C0.0236
T02C0.0354
T03C0.0400
T04C0.1260
T05C0.1280
%
T01
X9250Y4064
X12100Y5314
X13500Y6864
X15650Y6264
X15200Y4514
X13550Y8764
X13350Y10114
X13300Y11464
X11650Y13164
X10000Y15114
X6500Y13714
X4150Y11564
X14250Y14964
X15850Y9914
T02
X17200Y9464
X18200Y9964
X18200Y10964
X17200Y10464
X17200Y11464
X18200Y11964
T03
X18350Y16814
X17350Y16814
X7350Y16964
X6350Y16964
X5350Y16964
X1500Y12564
X1500Y11564
X1500Y10564
X1500Y9564
X1500Y8564
T04
X2350Y5114
X2300Y16064
X20800Y16064
X20800Y5064
T05
X20700Y8714
X20700Y12714
M30

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,162 @@
G75*
%MOIN*%
%OFA0B0*%
%FSLAX24Y24*%
%IPPOS*%
%LPD*%
%AMOC8*
5,1,8,0,0,1.08239X$1,22.5*
%
%ADD10R,0.0340X0.0880*%
%ADD11R,0.0671X0.0237*%
%ADD12R,0.4178X0.4332*%
%ADD13R,0.0930X0.0500*%
%ADD14R,0.0710X0.1655*%
%ADD15R,0.0671X0.0592*%
%ADD16R,0.0592X0.0671*%
%ADD17R,0.0710X0.1615*%
%ADD18R,0.1419X0.0828*%
%ADD19C,0.0634*%
%ADD20C,0.1360*%
%ADD21R,0.0474X0.0580*%
%ADD22C,0.0680*%
%ADD23R,0.0552X0.0552*%
%ADD24C,0.1340*%
%ADD25C,0.0476*%
D10*
X005000Y010604D03*
X005500Y010604D03*
X006000Y010604D03*
X006500Y010604D03*
X006500Y013024D03*
X006000Y013024D03*
X005500Y013024D03*
X005000Y013024D03*
D11*
X011423Y007128D03*
X011423Y006872D03*
X011423Y006616D03*
X011423Y006360D03*
X011423Y006104D03*
X011423Y005848D03*
X011423Y005592D03*
X011423Y005336D03*
X011423Y005080D03*
X011423Y004825D03*
X011423Y004569D03*
X011423Y004313D03*
X011423Y004057D03*
X011423Y003801D03*
X014277Y003801D03*
X014277Y004057D03*
X014277Y004313D03*
X014277Y004569D03*
X014277Y004825D03*
X014277Y005080D03*
X014277Y005336D03*
X014277Y005592D03*
X014277Y005848D03*
X014277Y006104D03*
X014277Y006360D03*
X014277Y006616D03*
X014277Y006872D03*
X014277Y007128D03*
D12*
X009350Y010114D03*
D13*
X012630Y010114D03*
X012630Y010784D03*
X012630Y011454D03*
X012630Y009444D03*
X012630Y008774D03*
D14*
X010000Y013467D03*
X010000Y016262D03*
D15*
X004150Y012988D03*
X004150Y012240D03*
X009900Y005688D03*
X009900Y004940D03*
X015000Y006240D03*
X015000Y006988D03*
D16*
X014676Y008364D03*
X015424Y008364D03*
X017526Y004514D03*
X018274Y004514D03*
X010674Y004064D03*
X009926Y004064D03*
X004174Y009564D03*
X003426Y009564D03*
X005376Y014564D03*
X006124Y014564D03*
D17*
X014250Y016088D03*
X014250Y012741D03*
D18*
X014250Y010982D03*
X014250Y009447D03*
D19*
X017200Y009464D03*
X018200Y009964D03*
X018200Y010964D03*
X017200Y010464D03*
X017200Y011464D03*
X018200Y011964D03*
D20*
X020700Y012714D03*
X020700Y008714D03*
D21*
X005004Y003814D03*
X005004Y004864D03*
X005004Y005864D03*
X005004Y006914D03*
X008696Y006914D03*
X008696Y005864D03*
X008696Y004864D03*
X008696Y003814D03*
D22*
X001800Y008564D02*
X001200Y008564D01*
X001200Y009564D02*
X001800Y009564D01*
X001800Y010564D02*
X001200Y010564D01*
X001200Y011564D02*
X001800Y011564D01*
X001800Y012564D02*
X001200Y012564D01*
X005350Y016664D02*
X005350Y017264D01*
X006350Y017264D02*
X006350Y016664D01*
X007350Y016664D02*
X007350Y017264D01*
X017350Y017114D02*
X017350Y016514D01*
X018350Y016514D02*
X018350Y017114D01*
D23*
X016613Y004514D03*
X015787Y004514D03*
D24*
X020800Y005064D03*
X020800Y016064D03*
X002300Y016064D03*
X002350Y005114D03*
D25*
X009250Y004064D03*
X012100Y005314D03*
X013500Y006864D03*
X015650Y006264D03*
X015200Y004514D03*
X013550Y008764D03*
X013350Y010114D03*
X013300Y011464D03*
X011650Y013164D03*
X010000Y015114D03*
X006500Y013714D03*
X004150Y011564D03*
X014250Y014964D03*
X015850Y009914D03*
M02*

File diff suppressed because it is too large Load diff

View file

@ -7,12 +7,6 @@ from ..cam import CamFile, FileSettings
from tests import *
def test_smoke_filesettings():
""" Smoke test FileSettings class
"""
fs = FileSettings()
def test_filesettings_defaults():
""" Test FileSettings default values
"""
@ -37,14 +31,38 @@ def test_filesettings_assign():
""" Test FileSettings attribute assignment
"""
fs = FileSettings()
fs.units = 'test'
fs.notation = 'test'
fs.zero_suppression = 'test'
fs.format = 'test'
assert_equal(fs.units, 'test')
assert_equal(fs.notation, 'test')
assert_equal(fs.zero_suppression, 'test')
assert_equal(fs.format, 'test')
fs.units = 'test1'
fs.notation = 'test2'
fs.zero_suppression = 'test3'
fs.format = 'test4'
assert_equal(fs.units, 'test1')
assert_equal(fs.notation, 'test2')
assert_equal(fs.zero_suppression, 'test3')
assert_equal(fs.format, 'test4')
def test_smoke_camfile():
cf = CamFile
def test_filesettings_dict_assign():
""" Test FileSettings dict-style attribute assignment
"""
fs = FileSettings()
fs['units'] = 'metric'
fs['notation'] = 'incremental'
fs['zero_suppression'] = 'leading'
fs['format'] = (1, 2)
assert_equal(fs.units, 'metric')
assert_equal(fs.notation, 'incremental')
assert_equal(fs.zero_suppression, 'leading')
assert_equal(fs.format, (1, 2))
def test_camfile_init():
""" Smoke test CamFile test
"""
cf = CamFile()
def test_camfile_settings():
""" Test CamFile Default Settings
"""
cf = CamFile()
assert_equal(cf.settings, FileSettings())

View file

@ -0,0 +1,24 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from ..common import read
from ..excellon import ExcellonFile
from ..rs274x import GerberFile
from tests import *
import os
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
'resources/ncdrill.DRD')
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
'resources/top_copper.GTL')
def test_file_type_detection():
""" Test file type detection
"""
ncdrill = read(NCDRILL_FILE)
top_copper = read(TOP_COPPER_FILE)
assert(isinstance(ncdrill, ExcellonFile))
assert(isinstance(top_copper, GerberFile))

View file

@ -0,0 +1,32 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from ..excellon import read, detect_excellon_format, ExcellonFile
from tests import *
import os
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
'resources/ncdrill.DRD')
def test_format_detection():
""" Test file type detection
"""
settings = detect_excellon_format(NCDRILL_FILE)
assert_equal(settings['format'], (2, 4))
assert_equal(settings['zero_suppression'], 'leading')
def test_read():
ncdrill = read(NCDRILL_FILE)
assert(isinstance(ncdrill, ExcellonFile))
def test_read_settings():
ncdrill = read(NCDRILL_FILE)
assert_equal(ncdrill.settings.format, (2, 4))
assert_equal(ncdrill.settings.zero_suppression, 'leading')

View file

@ -5,14 +5,15 @@
from .tests import assert_equal, assert_raises
from ..excellon_statements import *
from ..cam import FileSettings
def test_excellontool_factory():
""" Test ExcellonTool factory method
"""
exc_line = 'T8F00S00C0.12500'
settings = {'format': (2, 5), 'zero_suppression': 'trailing',
'units': 'inch', 'notation': 'absolute'}
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
units='inch', notation='absolute')
tool = ExcellonTool.from_excellon(exc_line, settings)
assert_equal(tool.diameter, 0.125)
assert_equal(tool.feed_rate, 0)
@ -25,16 +26,16 @@ def test_excellontool_dump():
exc_lines = ['T1F00S00C0.01200', 'T2F00S00C0.01500', 'T3F00S00C0.01968',
'T4F00S00C0.02800', 'T5F00S00C0.03300', 'T6F00S00C0.03800',
'T7F00S00C0.04300', 'T8F00S00C0.12500', 'T9F00S00C0.13000', ]
settings = {'format': (2, 5), 'zero_suppression': 'trailing',
'units': 'inch', 'notation': 'absolute'}
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
units='inch', notation='absolute')
for line in exc_lines:
tool = ExcellonTool.from_excellon(line, settings)
assert_equal(tool.to_excellon(), line)
def test_excellontool_order():
settings = {'format': (2, 5), 'zero_suppression': 'trailing',
'units': 'inch', 'notation': 'absolute'}
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
units='inch', notation='absolute')
line = 'T8F00S00C0.12500'
tool1 = ExcellonTool.from_excellon(line, settings)
line = 'T8C0.12500F00S00'

View file

@ -0,0 +1,16 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from ..rs274x import read, GerberFile
from tests import *
import os
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
'resources/top_copper.GTL')
def test_read():
top_copper = read(TOP_COPPER_FILE)
assert(isinstance(top_copper, GerberFile))

View file

@ -44,6 +44,10 @@ def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
The specified value as a floating-point number.
"""
# Handle excellon edge case with explicit decimal. "That was easy!"
if '.' in value:
return float(value)
# Format precision
integer_digits, decimal_digits = format
MAX_DIGITS = integer_digits + decimal_digits
@ -55,23 +59,20 @@ def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
raise ValueError('Parser only supports precision up to 6:7 format')
# Remove extraneous information
value = value.strip()
value = value.strip(' +')
#value = value.strip()
value = value.lstrip('+')
negative = '-' in value
if negative:
value = value.strip(' -')
value = value.lstrip('-')
# Handle excellon edge case with explicit decimal. "That was easy!"
if '.' in value:
return float(value)
digits = [digit for digit in '0' * MAX_DIGITS]
digits = list('0' * MAX_DIGITS)
offset = 0 if zero_suppression == 'trailing' else (MAX_DIGITS - len(value))
for i, digit in enumerate(value):
digits[i + offset] = digit
result = float(''.join(digits[:integer_digits] + ['.'] + digits[integer_digits:]))
return -1.0 * result if negative else result
return -result if negative else result
def write_gerber_value(value, format=(2, 5), zero_suppression='trailing'):