Tests and bugfixes

This commit is contained in:
Hamilton Kibbe 2015-02-15 02:20:02 -05:00
parent 5e23d07bcb
commit 5cf1fa74b4
10 changed files with 391 additions and 61 deletions

View file

@ -21,7 +21,6 @@ CAM File
This module provides common base classes for Excellon/Gerber CNC files
"""
from operator import mul
class FileSettings(object):
""" CAM File Settings
@ -62,14 +61,14 @@ class FileSettings(object):
if units not in ['inch', 'metric']:
raise ValueError('Units must be either inch or metric')
self.units = units
if zero_suppression is None and zeros is None:
self.zero_suppression = 'trailing'
elif zero_suppression == zeros:
raise ValueError('Zeros and Zero Suppression must be different. \
Best practice is to specify only one.')
elif zero_suppression is not None:
if zero_suppression not in ['leading', 'trailing']:
raise ValueError('Zero suppression must be either leading or \

View file

@ -95,11 +95,27 @@ class ExcellonFile(CamFile):
ymax = max(y + radius, ymax)
return ((xmin, xmax), (ymin, ymax))
def report(self):
""" Print drill report
def report(self, filename=None):
""" Print or save drill report
"""
pass
toolfmt = ' T%%02d %%%d.%df %%d\n' % self.settings.format
rprt = 'Excellon Drill Report\n\n'
if self.filename is not None:
rprt += 'NC Drill File: %s\n\n' % self.filename
rprt += 'Drill File Info:\n\n'
rprt += (' Data Mode %s\n' % 'Absolute'
if self.settings.notation == 'absolute' else 'Incremental')
rprt += (' Units %s\n' % 'Inches'
if self.settings.units == 'inch' else 'Millimeters')
rprt += '\nTool List:\n\n'
rprt += ' Code Size Hits\n'
rprt += ' --------------------------\n'
for tool in self.tools.itervalues():
rprt += toolfmt % (tool.number, tool.diameter, tool.hit_count)
if filename is not None:
with open(filename, 'w') as f:
f.write(rprt)
return rprt
def write(self, filename):
with open(filename, 'w') as f:
@ -195,7 +211,7 @@ class ExcellonParser(object):
self.state = 'DRILL'
elif line[:3] == 'M30':
stmt = EndOfProgramStmt.from_excellon(line)
stmt = EndOfProgramStmt.from_excellon(line, self._settings())
self.statements.append(stmt)
elif line[:3] == 'G00':
@ -230,8 +246,9 @@ class ExcellonParser(object):
stmt = FormatStmt.from_excellon(line)
self.statements.append(stmt)
elif line[:4] == 'G90':
elif line[:3] == 'G90':
self.statements.append(AbsoluteModeStmt())
self.notation = 'absolute'
elif line[0] == 'T' and self.state == 'HEADER':
tool = ExcellonTool.from_excellon(line, self._settings())

View file

@ -29,7 +29,7 @@ __all__ = ['ExcellonTool', 'ToolSelectionStmt', 'CoordinateStmt',
'RewindStopStmt', 'EndOfProgramStmt', 'UnitStmt',
'IncrementalModeStmt', 'VersionStmt', 'FormatStmt', 'LinkToolStmt',
'MeasuringModeStmt', 'RouteModeStmt', 'DrillModeStmt', 'AbsoluteModeStmt',
'RepeatHoleStmt', 'UnknownStmt',
'RepeatHoleStmt', 'UnknownStmt', 'ExcellonStatement'
]
@ -38,10 +38,10 @@ class ExcellonStatement(object):
"""
@classmethod
def from_excellon(cls, line):
pass
raise NotImplementedError('`from_excellon` must be implemented in a subclass')
def to_excellon(self, settings=None):
pass
raise NotImplementedError('`to_excellon` must be implemented in a subclass')
class ExcellonTool(ExcellonStatement):
@ -144,7 +144,7 @@ class ExcellonTool(ExcellonStatement):
tool : ExcellonTool
An ExcellonTool initialized with the parameters in tool_dict.
"""
return cls(settings, tool_dict)
return cls(settings, **tool_dict)
def __init__(self, settings, **kwargs):
self.settings = settings
@ -159,7 +159,7 @@ class ExcellonTool(ExcellonStatement):
def to_excellon(self, settings=None):
fmt = self.settings.format
zs = self.settings.format
zs = self.settings.zero_suppression
stmt = 'T%02d' % self.number
if self.retract_rate is not None:
stmt += 'B%s' % write_gerber_value(self.retract_rate, fmt, zs)
@ -171,7 +171,7 @@ class ExcellonTool(ExcellonStatement):
if self.rpm < 100000.:
stmt += 'S%s' % write_gerber_value(self.rpm / 1000., fmt, zs)
else:
stmt += 'S%g' % self.rpm / 1000.
stmt += 'S%g' % (self.rpm / 1000.)
if self.diameter is not None:
stmt += 'C%s' % decimal_string(self.diameter, fmt[1], True)
if self.depth_offset is not None:
@ -191,7 +191,8 @@ class ExcellonTool(ExcellonStatement):
def __repr__(self):
unit = 'in.' if self.settings.units == 'inch' else 'mm'
return '<ExcellonTool %02d: %0.3f%s dia.>' % (self.number, self.diameter, unit)
fmtstr = '<ExcellonTool %%02d: %%%d.%dg%%s dia.>' % self.settings.format
return fmtstr % (self.number, self.diameter, unit)
class ToolSelectionStmt(ExcellonStatement):
@ -273,9 +274,9 @@ class CoordinateStmt(ExcellonStatement):
def __str__(self):
coord_str = ''
if self.x is not None:
coord_str += 'X: %f ' % self.x
coord_str += 'X: %g ' % self.x
if self.y is not None:
coord_str += 'Y: %f ' % self.y
coord_str += 'Y: %g ' % self.y
return '<Coordinate Statement: %s>' % coord_str
@ -284,16 +285,32 @@ class RepeatHoleStmt(ExcellonStatement):
@classmethod
def from_excellon(cls, line, settings):
return cls(line)
match = re.compile(r'R(?P<rcount>[0-9]*)X?(?P<xdelta>\d*\.?\d*)?Y?(?P<ydelta>\d*\.?\d*)?').match(line)
stmt = match.groupdict()
count = int(stmt['rcount'])
xdelta = (parse_gerber_value(stmt['xdelta'], settings.format,
settings.zero_suppression)
if stmt['xdelta'] is not '' else None)
ydelta = (parse_gerber_value(stmt['ydelta'], settings.format,
settings.zero_suppression)
if stmt['ydelta'] is not '' else None)
return cls(count, xdelta, ydelta)
def __init__(self, line):
self.line = line
def __init__(self, count, xdelta=None, ydelta=None):
self.count = count
self.xdelta = xdelta
self.ydelta = ydelta
def to_excellon(self, settings):
return self.line
stmt = 'R%d' % self.count
if self.xdelta is not None:
stmt += 'X%s' % write_gerber_value(self.xdelta, settings.format, settings.zero_suppression)
if self.ydelta is not None:
stmt += 'Y%s' % write_gerber_value(self.ydelta, settings.format, settings.zero_suppression)
return stmt
def __str__(self):
return '<Repeat Hole: %s>' % self.line
return '<Repeat Hole: %d times>' % self.count
class CommentStmt(ExcellonStatement):
@ -339,8 +356,16 @@ class RewindStopStmt(ExcellonStatement):
class EndOfProgramStmt(ExcellonStatement):
@classmethod
def from_excellon(cls, line):
return cls()
def from_excellon(cls, line, settings):
match = re.compile(r'M30X?(?P<x>\d*\.?\d*)?Y?(?P<y>\d*\.?\d*)?').match(line)
stmt = match.groupdict()
x = (parse_gerber_value(stmt['x'], settings.format,
settings.zero_suppression)
if stmt['x'] is not '' else None)
y = (parse_gerber_value(stmt['y'], settings.format,
settings.zero_suppression)
if stmt['y'] is not '' else None)
return cls(x, y)
def __init__(self, x=None, y=None):
self.x = x
@ -495,7 +520,7 @@ class UnknownStmt(ExcellonStatement):
return self.stmt
def __str__(self):
return "<UnknownStmt: %s >" % self.stmt
return "<Unknown Statement: %s>" % self.stmt
def pairwise(iterator):

View file

@ -802,13 +802,13 @@ class CoordStmt(Statement):
if self.function:
coord_str += 'Fn: %s ' % self.function
if self.x is not None:
coord_str += 'X: %f ' % self.x
coord_str += 'X: %g ' % self.x
if self.y is not None:
coord_str += 'Y: %f ' % self.y
coord_str += 'Y: %g ' % self.y
if self.i is not None:
coord_str += 'I: %f ' % self.i
coord_str += 'I: %g ' % self.i
if self.j is not None:
coord_str += 'J: %f ' % self.j
coord_str += 'J: %g ' % self.j
if self.op:
if self.op == 'D01':
op = 'Lights On'
@ -829,7 +829,7 @@ class ApertureStmt(Statement):
def __init__(self, d, deprecated=None):
Statement.__init__(self, "APERTURE")
self.d = int(d)
self.deprecated = True if deprecated is not None else False
self.deprecated = True if deprecated is not None and deprecated is not False else False
def to_gerber(self, settings=None):
if self.deprecated:

View file

@ -200,10 +200,10 @@ class Arc(Primitive):
if theta1 <= math.pi * 1.5 and (theta0 >= math.pi * 1.5 or theta0 < theta1):
points.append((self.center[0], self.center[1] - self.radius ))
x, y = zip(*points)
min_x = min(x)
max_x = max(x)
min_y = min(y)
max_y = max(y)
min_x = min(x) - self.aperture.radius
max_x = max(x) + self.aperture.radius
min_y = min(y) - self.aperture.radius
max_y = max(y) + self.aperture.radius
return ((min_x, max_x), (min_y, max_y))

View file

@ -89,7 +89,7 @@ class GerberSvgContext(GerberContext):
direction = '-' if arc.direction == 'clockwise' else '+'
arc_path.push_arc(end, 0, radius, large_arc, direction, True)
self.dwg.add(arc_path)
def _render_region(self, region, color):
points = [tuple(map(mul, point, self.scale)) for point in region.points]
region_path = self.dwg.path(d='M %f, %f' % points[0],

View file

@ -2,7 +2,8 @@
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from ..excellon import read, detect_excellon_format, ExcellonFile
from ..cam import FileSettings
from ..excellon import read, detect_excellon_format, ExcellonFile, ExcellonParser
from tests import *
import os
@ -25,3 +26,112 @@ def test_read_settings():
ncdrill = read(NCDRILL_FILE)
assert_equal(ncdrill.settings['format'], (2, 4))
assert_equal(ncdrill.settings['zeros'], 'trailing')
def test_bounds():
ncdrill = read(NCDRILL_FILE)
xbound, ybound = ncdrill.bounds
assert_array_almost_equal(xbound, (0.1300, 2.1430))
assert_array_almost_equal(ybound, (0.3946, 1.7164))
def test_report():
ncdrill = read(NCDRILL_FILE)
def test_parser_hole_count():
settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
p = ExcellonParser(settings)
p.parse(NCDRILL_FILE)
assert_equal(p.hole_count, 36)
def test_parser_hole_sizes():
settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
p = ExcellonParser(settings)
p.parse(NCDRILL_FILE)
assert_equal(p.hole_sizes, [0.0236, 0.0354, 0.04, 0.126, 0.128])
def test_parse_whitespace():
p = ExcellonParser(FileSettings())
assert_equal(p._parse(' '), None)
def test_parse_comment():
p = ExcellonParser(FileSettings())
p._parse(';A comment')
assert_equal(p.statements[0].comment, 'A comment')
def test_parse_format_comment():
p = ExcellonParser(FileSettings())
p._parse('; FILE_FORMAT=9:9 ')
assert_equal(p.format, (9, 9))
def test_parse_header():
p = ExcellonParser(FileSettings())
p._parse('M48 ')
assert_equal(p.state, 'HEADER')
p._parse('M95 ')
assert_equal(p.state, 'DRILL')
def test_parse_rout():
p = ExcellonParser(FileSettings())
p._parse('G00 ')
assert_equal(p.state, 'ROUT')
p._parse('G05 ')
assert_equal(p.state, 'DRILL')
def test_parse_version():
p = ExcellonParser(FileSettings())
p._parse('VER,1 ')
assert_equal(p.statements[0].version, 1)
p._parse('VER,2 ')
assert_equal(p.statements[1].version, 2)
def test_parse_format():
p = ExcellonParser(FileSettings())
p._parse('FMAT,1 ')
assert_equal(p.statements[0].format, 1)
p._parse('FMAT,2 ')
assert_equal(p.statements[1].format, 2)
def test_parse_units():
settings = FileSettings(units='inch', zeros='trailing')
p = ExcellonParser(settings)
p._parse(';METRIC,LZ')
assert_equal(p.units, 'inch')
assert_equal(p.zeros, 'trailing')
p._parse('METRIC,LZ')
assert_equal(p.units, 'metric')
assert_equal(p.zeros, 'leading')
def test_parse_incremental_mode():
settings = FileSettings(units='inch', zeros='trailing')
p = ExcellonParser(settings)
assert_equal(p.notation, 'absolute')
p._parse('ICI,ON ')
assert_equal(p.notation, 'incremental')
p._parse('ICI,OFF ')
assert_equal(p.notation, 'absolute')
def test_parse_absolute_mode():
settings = FileSettings(units='inch', zeros='trailing')
p = ExcellonParser(settings)
assert_equal(p.notation, 'absolute')
p._parse('ICI,ON ')
assert_equal(p.notation, 'incremental')
p._parse('G90 ')
assert_equal(p.notation, 'absolute')
def test_parse_repeat_hole():
p = ExcellonParser(FileSettings())
p._parse('R03X1.5Y1.5')
assert_equal(p.statements[0].count, 3)
def test_parse_incremental_position():
p = ExcellonParser(FileSettings(notation='incremental'))
p._parse('X01Y01')
p._parse('X01Y01')
assert_equal(p.pos, [2.,2.])
def test_parse_unknown():
p = ExcellonParser(FileSettings())
p._parse('Not A Valid Statement')
assert_equal(p.statements[0].stmt, 'Not A Valid Statement')

View file

@ -7,17 +7,36 @@ from .tests import assert_equal, assert_raises
from ..excellon_statements import *
from ..cam import FileSettings
def test_excellon_statement_implementation():
stmt = ExcellonStatement()
assert_raises(NotImplementedError, stmt.from_excellon, None)
assert_raises(NotImplementedError, stmt.to_excellon)
def test_excellontool_factory():
""" Test ExcellonTool factory method
""" Test ExcellonTool factory methods
"""
exc_line = 'T8F00S00C0.12500'
exc_line = 'T8F01B02S00003H04Z05C0.12500'
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
units='inch', notation='absolute')
tool = ExcellonTool.from_excellon(exc_line, settings)
assert_equal(tool.number, 8)
assert_equal(tool.diameter, 0.125)
assert_equal(tool.feed_rate, 0)
assert_equal(tool.rpm, 0)
assert_equal(tool.feed_rate, 1)
assert_equal(tool.retract_rate,2)
assert_equal(tool.rpm, 3)
assert_equal(tool.max_hit_count, 4)
assert_equal(tool.depth_offset, 5)
stmt = {'number': 8, 'feed_rate': 1, 'retract_rate': 2, 'rpm': 3,
'diameter': 0.125, 'max_hit_count': 4, 'depth_offset': 5}
tool = ExcellonTool.from_dict(settings, stmt)
assert_equal(tool.number, 8)
assert_equal(tool.diameter, 0.125)
assert_equal(tool.feed_rate, 1)
assert_equal(tool.retract_rate,2)
assert_equal(tool.rpm, 3)
assert_equal(tool.max_hit_count, 4)
assert_equal(tool.depth_offset, 5)
def test_excellontool_dump():
@ -25,7 +44,8 @@ def test_excellontool_dump():
"""
exc_lines = ['T01F0S0C0.01200', 'T02F0S0C0.01500', 'T03F0S0C0.01968',
'T04F0S0C0.02800', 'T05F0S0C0.03300', 'T06F0S0C0.03800',
'T07F0S0C0.04300', 'T08F0S0C0.12500', 'T09F0S0C0.13000', ]
'T07F0S0C0.04300', 'T08F0S0C0.12500', 'T09F0S0C0.13000',
'T08B01F02H03S00003C0.12500Z04', 'T01F0S300.999C0.01200']
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
units='inch', notation='absolute')
for line in exc_lines:
@ -44,6 +64,19 @@ def test_excellontool_order():
assert_equal(tool1.feed_rate, tool2.feed_rate)
assert_equal(tool1.rpm, tool2.rpm)
def test_excellontool_conversion():
tool = ExcellonTool.from_dict(FileSettings(), {'number': 8, 'diameter': 25.4})
tool.to_inch()
assert_equal(tool.diameter, 1.)
tool = ExcellonTool.from_dict(FileSettings(), {'number': 8, 'diameter': 1})
tool.to_metric()
assert_equal(tool.diameter, 25.4)
def test_excellontool_repr():
tool = ExcellonTool.from_dict(FileSettings(), {'number': 8, 'diameter': 0.125})
assert_equal(str(tool), '<ExcellonTool 08: 0.125in. dia.>')
tool = ExcellonTool.from_dict(FileSettings(units='metric'), {'number': 8, 'diameter': 0.125})
assert_equal(str(tool), '<ExcellonTool 08: 0.125mm dia.>')
def test_toolselection_factory():
""" Test ToolSelectionStmt factory method
@ -93,22 +126,49 @@ def test_coordinatestmt_factory():
assert_equal(stmt.y, 0.4639)
assert_equal(stmt.to_excellon(settings), "X9660Y4639")
def test_coordinatestmt_dump():
""" Test CoordinateStmt to_excellon()
"""
lines = ['X278207Y65293', 'X243795', 'Y82528', 'Y86028',
'X251295Y81528', 'X2525Y78', 'X255Y575', 'Y52',
'X2675', 'Y575', 'X2425', 'Y52', 'X23', ]
settings = FileSettings(format=(2, 4), zero_suppression='leading',
units='inch', notation='absolute')
for line in lines:
stmt = CoordinateStmt.from_excellon(line, settings)
assert_equal(stmt.to_excellon(settings), line)
def test_coordinatestmt_conversion():
stmt = CoordinateStmt.from_excellon('X254Y254', FileSettings())
stmt.to_inch()
assert_equal(stmt.x, 1.)
assert_equal(stmt.y, 1.)
stmt = CoordinateStmt.from_excellon('X01Y01', FileSettings())
stmt.to_metric()
assert_equal(stmt.x, 25.4)
assert_equal(stmt.y, 25.4)
def test_coordinatestmt_string():
settings = FileSettings(format=(2, 4), zero_suppression='leading',
units='inch', notation='absolute')
stmt = CoordinateStmt.from_excellon('X9660Y4639', settings)
assert_equal(str(stmt), '<Coordinate Statement: X: 0.966 Y: 0.4639 >')
def test_repeathole_stmt_factory():
stmt = RepeatHoleStmt.from_excellon('R0004X015Y32', FileSettings(zeros='leading'))
assert_equal(stmt.count, 4)
assert_equal(stmt.xdelta, 1.5)
assert_equal(stmt.ydelta, 32)
def test_repeatholestmt_dump():
line = 'R4X015Y32'
stmt = RepeatHoleStmt.from_excellon(line, FileSettings())
assert_equal(stmt.to_excellon(FileSettings()), line)
def test_repeathole_str():
stmt = RepeatHoleStmt.from_excellon('R4X015Y32', FileSettings())
assert_equal(str(stmt), '<Repeat Hole: 4 times>')
def test_commentstmt_factory():
""" Test CommentStmt factory method
@ -134,6 +194,35 @@ def test_commentstmt_dump():
stmt = CommentStmt.from_excellon(line)
assert_equal(stmt.to_excellon(), line)
def test_header_begin_stmt():
stmt = HeaderBeginStmt()
assert_equal(stmt.to_excellon(None), 'M48')
def test_header_end_stmt():
stmt = HeaderEndStmt()
assert_equal(stmt.to_excellon(None), 'M95')
def test_rewindstop_stmt():
stmt = RewindStopStmt()
assert_equal(stmt.to_excellon(None), '%')
def test_endofprogramstmt_factory():
stmt = EndOfProgramStmt.from_excellon('M30X01Y02', FileSettings())
assert_equal(stmt.x, 1.)
assert_equal(stmt.y, 2.)
stmt = EndOfProgramStmt.from_excellon('M30X01', FileSettings())
assert_equal(stmt.x, 1.)
assert_equal(stmt.y, None)
stmt = EndOfProgramStmt.from_excellon('M30Y02', FileSettings())
assert_equal(stmt.x, None)
assert_equal(stmt.y, 2.)
def test_endofprogramStmt_dump():
lines = ['M30X01Y02',]
for line in lines:
stmt = EndOfProgramStmt.from_excellon(line, FileSettings())
assert_equal(stmt.to_excellon(FileSettings()), line)
def test_unitstmt_factory():
""" Test UnitStmt factory method
@ -295,3 +384,25 @@ def test_measmodestmt_validation():
"""
assert_raises(ValueError, MeasuringModeStmt.from_excellon, 'M70')
assert_raises(ValueError, MeasuringModeStmt, 'millimeters')
def test_routemode_stmt():
stmt = RouteModeStmt()
assert_equal(stmt.to_excellon(FileSettings()), 'G00')
def test_drillmode_stmt():
stmt = DrillModeStmt()
assert_equal(stmt.to_excellon(FileSettings()), 'G05')
def test_absolutemode_stmt():
stmt = AbsoluteModeStmt()
assert_equal(stmt.to_excellon(FileSettings()), 'G90')
def test_unknownstmt():
stmt = UnknownStmt('TEST')
assert_equal(stmt.stmt, 'TEST')
assert_equal(str(stmt), '<Unknown Statement: TEST>')
def test_unknownstmt_dump():
stmt = UnknownStmt('TEST')
assert_equal(stmt.to_excellon(FileSettings()), 'TEST')

View file

@ -394,6 +394,10 @@ def test_comment_stmt_dump():
stmt = CommentStmt('A comment')
assert_equal(stmt.to_gerber(), 'G04A comment*')
def test_comment_stmt_string():
stmt = CommentStmt('A comment')
assert_equal(str(stmt), '<Comment: A comment>')
def test_eofstmt():
""" Test EofStmt
"""
@ -406,6 +410,9 @@ def test_eofstmt_dump():
stmt = EofStmt()
assert_equal(stmt.to_gerber(), 'M02*')
def test_eofstmt_string():
assert_equal(str(EofStmt()), '<EOF Statement>')
def test_quadmodestmt_factory():
""" Test QuadrantModeStmt.from_gerber()
"""
@ -572,8 +579,6 @@ def test_MIParamStmt_string():
mi = MIParamStmt.from_dict(stmt)
assert_equal(str(mi), '<Image Mirror: A=1 B=0>')
def test_coordstmt_ctor():
cs = CoordStmt('G04', 0.0, 0.1, 0.2, 0.3, 'D01', FileSettings())
assert_equal(cs.function, 'G04')
@ -583,5 +588,67 @@ def test_coordstmt_ctor():
assert_equal(cs.j, 0.3)
assert_equal(cs.op, 'D01')
def test_coordstmt_factory():
stmt = {'function': 'G04', 'x': '0', 'y': '001', 'i': '002', 'j': '003', 'op': 'D01'}
cs = CoordStmt.from_dict(stmt, FileSettings())
assert_equal(cs.function, 'G04')
assert_equal(cs.x, 0.0)
assert_equal(cs.y, 0.1)
assert_equal(cs.i, 0.2)
assert_equal(cs.j, 0.3)
assert_equal(cs.op, 'D01')
def test_coordstmt_dump():
cs = CoordStmt('G04', 0.0, 0.1, 0.2, 0.3, 'D01', FileSettings())
assert_equal(cs.to_gerber(FileSettings()), 'G04X0Y001I002J003D01*')
def test_coordstmt_conversion():
cs = CoordStmt('G71', 25.4, 25.4, 25.4, 25.4, 'D01', FileSettings())
cs.to_inch()
assert_equal(cs.x, 1.)
assert_equal(cs.y, 1.)
assert_equal(cs.i, 1.)
assert_equal(cs.j, 1.)
assert_equal(cs.function, 'G70')
cs = CoordStmt('G70', 1., 1., 1., 1., 'D01', FileSettings())
cs.to_metric()
assert_equal(cs.x, 25.4)
assert_equal(cs.y, 25.4)
assert_equal(cs.i, 25.4)
assert_equal(cs.j, 25.4)
assert_equal(cs.function, 'G71')
def test_coordstmt_string():
cs = CoordStmt('G04', 0, 1, 2, 3, 'D01', FileSettings())
assert_equal(str(cs), '<Coordinate Statement: Fn: G04 X: 0 Y: 1 I: 2 J: 3 Op: Lights On>')
cs = CoordStmt('G04', None, None, None, None, 'D02', FileSettings())
assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: Lights Off>')
cs = CoordStmt('G04', None, None, None, None, 'D03', FileSettings())
assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: Flash>')
cs = CoordStmt('G04', None, None, None, None, 'TEST', FileSettings())
assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: TEST>')
def test_aperturestmt_ctor():
ast = ApertureStmt(3, False)
assert_equal(ast.d, 3)
assert_equal(ast.deprecated, False)
ast = ApertureStmt(4, True)
assert_equal(ast.d, 4)
assert_equal(ast.deprecated, True)
ast = ApertureStmt(4, 1)
assert_equal(ast.d, 4)
assert_equal(ast.deprecated, True)
ast = ApertureStmt(3)
assert_equal(ast.d, 3)
assert_equal(ast.deprecated, False)
def test_aperturestmt_dump():
ast = ApertureStmt(3, False)
assert_equal(ast.to_gerber(), 'D3*')
ast = ApertureStmt(3, True)
assert_equal(ast.to_gerber(), 'G54D3*')
assert_equal(str(ast), '<Aperture: 3>')

View file

@ -73,20 +73,21 @@ def test_arc_sweep_angle():
((1, 0), (-1, 0), (0, 0), 'counterclockwise', math.radians(180)),]
for start, end, center, direction, sweep in cases:
a = Arc(start, end, center, direction, 0)
c = Circle((0,0), 1)
a = Arc(start, end, center, direction, c)
assert_equal(a.sweep_angle, sweep)
# Need to update bounds calculation using aperture
#def test_arc_bounds():
# """ Test Arc primitive bounding box calculation
# """
# cases = [((1, 0), (0, 1), (0, 0), 'clockwise', ((-1, 1), (-1, 1))),
# ((1, 0), (0, 1), (0, 0), 'counterclockwise', ((0, 1), (0, 1))),
# #TODO: ADD MORE TEST CASES HERE
# ]
# for start, end, center, direction, bounds in cases:
# a = Arc(start, end, center, direction, 0)
# assert_equal(a.bounding_box, bounds)
def test_arc_bounds():
""" Test Arc primitive bounding box calculation
"""
cases = [((1, 0), (0, 1), (0, 0), 'clockwise', ((-1.5, 1.5), (-1.5, 1.5))),
((1, 0), (0, 1), (0, 0), 'counterclockwise', ((-0.5, 1.5), (-0.5, 1.5))),
#TODO: ADD MORE TEST CASES HERE
]
for start, end, center, direction, bounds in cases:
c = Circle((0,0), 1)
a = Arc(start, end, center, direction, c)
assert_equal(a.bounding_box, bounds)
def test_circle_radius():