Merged in sopak/flatcam/tcl-commands (pull request #40)

Tcl commands - import_svg
This commit is contained in:
jpcgt 2016-04-18 14:47:42 -04:00
commit b5162b502f
8 changed files with 777 additions and 29 deletions

View File

@ -64,6 +64,7 @@ def path2shapely(path, res=1.0):
:param res: Resolution (minimum step along path)
:return: Shapely geometry object
"""
points = []
for component in path:
@ -86,6 +87,12 @@ def path2shapely(path, res=1.0):
# How many points to use in the dicrete representation.
length = component.length(res / 10.0)
steps = int(length / res + 0.5)
# solve error when step is below 1,
# it may cause other problems, but LineString needs at least two points
if steps == 0:
steps = 1
frac = 1.0 / steps
# print length, steps, frac
@ -117,9 +124,16 @@ def svgrect2shapely(rect, n_points=32):
"""
w = svgparselength(rect.get('width'))[0]
h = svgparselength(rect.get('height'))[0]
x = svgparselength(rect.get('x'))[0]
y = svgparselength(rect.get('y'))[0]
x_obj = rect.get('x')
if x_obj is not None:
x = svgparselength(x_obj)[0]
else:
x = 0
y_obj = rect.get('y')
if y_obj is not None:
y = svgparselength(y_obj)[0]
else:
y = 0
rxstr = rect.get('rx')
rystr = rect.get('ry')
@ -305,29 +319,31 @@ def getsvggeo(node):
log.warning("Unknown kind: " + kind)
geo = None
# Transformations
if 'transform' in node.attrib:
trstr = node.get('transform')
trlist = parse_svg_transform(trstr)
#log.debug(trlist)
# ignore transformation for unknown kind
if geo is not None:
# Transformations
if 'transform' in node.attrib:
trstr = node.get('transform')
trlist = parse_svg_transform(trstr)
#log.debug(trlist)
# Transformations are applied in reverse order
for tr in trlist[::-1]:
if tr[0] == 'translate':
geo = [translate(geoi, tr[1], tr[2]) for geoi in geo]
elif tr[0] == 'scale':
geo = [scale(geoi, tr[0], tr[1], origin=(0, 0))
for geoi in geo]
elif tr[0] == 'rotate':
geo = [rotate(geoi, tr[1], origin=(tr[2], tr[3]))
for geoi in geo]
elif tr[0] == 'skew':
geo = [skew(geoi, tr[1], tr[2], origin=(0, 0))
for geoi in geo]
elif tr[0] == 'matrix':
geo = [affine_transform(geoi, tr[1:]) for geoi in geo]
else:
raise Exception('Unknown transformation: %s', tr)
# Transformations are applied in reverse order
for tr in trlist[::-1]:
if tr[0] == 'translate':
geo = [translate(geoi, tr[1], tr[2]) for geoi in geo]
elif tr[0] == 'scale':
geo = [scale(geoi, tr[0], tr[1], origin=(0, 0))
for geoi in geo]
elif tr[0] == 'rotate':
geo = [rotate(geoi, tr[1], origin=(tr[2], tr[3]))
for geoi in geo]
elif tr[0] == 'skew':
geo = [skew(geoi, tr[1], tr[2], origin=(0, 0))
for geoi in geo]
elif tr[0] == 'matrix':
geo = [affine_transform(geoi, tr[1:]) for geoi in geo]
else:
raise Exception('Unknown transformation: %s', tr)
return geo
@ -346,7 +362,7 @@ def parse_svg_point_list(ptliststr):
pos = 0
i = 0
for match in re.finditer(r'(\s*,\s*)|(\s+)', ptliststr):
for match in re.finditer(r'(\s*,\s*)|(\s+)', ptliststr.strip(' ')):
val = float(ptliststr[pos:match.start()])
@ -435,7 +451,7 @@ def parse_svg_transform(trstr):
r'(?:' + comma_or_space_re_str + \
r'(' + number_re_str + r')' + \
comma_or_space_re_str + \
r'(' + number_re_str + r'))?\*\)'
r'(' + number_re_str + r'))?\s*\)'
matrix_re_str = r'matrix\s*\(\s*' + \
r'(' + number_re_str + r')' + comma_or_space_re_str + \
r'(' + number_re_str + r')' + comma_or_space_re_str + \

View File

@ -388,7 +388,11 @@ class TclCommandSignaled(TclCommand):
return self.output
except Exception as unknown:
error_info=sys.exc_info()
# if error happens inside thread execution, then pass correct error_info to display
if self.error_info is not None:
error_info = self.error_info
else:
error_info=sys.exc_info()
self.log.error("TCL command '%s' failed." % str(self))
self.app.display_tcl_error(unknown, error_info)
self.raise_tcl_unknown_error(unknown)

View File

@ -0,0 +1,81 @@
from ObjectCollection import *
import TclCommand
class TclCommandImportSvg(TclCommand.TclCommandSignaled):
"""
Tcl shell command to import an SVG file as a Geometry Object.
"""
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
aliases = ['import_svg']
# dictionary of types from Tcl command, needs to be ordered
arg_names = collections.OrderedDict([
('filename', str)
])
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
option_types = collections.OrderedDict([
('type', str),
('outname', str)
])
# array of mandatory options for current Tcl command: required = {'name','outname'}
required = ['filename']
# structured help for current command, args needs to be ordered
help = {
'main': "Import an SVG file as a Geometry Object..",
'args': collections.OrderedDict([
('filename', 'Path to file to open.'),
('type', 'Import as gerber or geometry(default).'),
('outname', 'Name of the resulting Geometry object.')
]),
'examples': []
}
def execute(self, args, unnamed_args):
"""
execute current TCL shell command
:param args: array of known named arguments and options
:param unnamed_args: array of other values which were passed into command
without -somename and we do not have them in known arg_names
:return: None or exception
"""
# How the object should be initialized
def obj_init(geo_obj, app_obj):
if not isinstance(geo_obj, Geometry):
self.raise_tcl_error('Expected Geometry or Gerber, got %s %s.' % (outname, type(geo_obj)))
geo_obj.import_svg(filename)
filename = args['filename']
if 'outname' in args:
outname = args['outname']
else:
outname = filename.split('/')[-1].split('\\')[-1]
if 'type' in args:
obj_type = args['type']
else:
obj_type = 'geometry'
if obj_type != "geometry" and obj_type != "gerber":
self.raise_tcl_error("Option type can be 'geopmetry' or 'gerber' only, got '%s'." % obj_type)
with self.app.proc_container.new("Import SVG"):
# Object creation
self.app.new_object(obj_type, outname, obj_init)
# Register recent file
self.app.file_opened.emit("svg", filename)
# GUI feedback
self.app.inform.emit("Opened: " + filename)

View File

@ -8,6 +8,7 @@ import tclCommands.TclCommandCncjob
import tclCommands.TclCommandDrillcncjob
import tclCommands.TclCommandExportGcode
import tclCommands.TclCommandExteriors
import tclCommands.TclCommandImportSvg
import tclCommands.TclCommandInteriors
import tclCommands.TclCommandIsolate
import tclCommands.TclCommandNew

View File

@ -0,0 +1,34 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE svg>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In -->
<svg xmlns="http://www.w3.org/2000/svg" width="0.402778in" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace" x="0px" version="1.2" y="0px" height="0.527778in" viewBox="0 0 29 38" baseProfile="tiny">
<g id="copper0">
<g id="copper1">
<rect x="1.362" y="2.091" fill="none" stroke="#F7BD13" stroke-width="1.224" width="4.104" height="4.104"/>
<circle fill="none" cx="3.362" cy="4.091" stroke="#F7BD13" id="connector1pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="11.29" stroke="#F7BD13" id="connector2pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="18.491" stroke="#F7BD13" id="connector3pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="25.69" stroke="#F7BD13" id="connector4pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.365" cy="32.81" stroke="#F7BD13" id="connector5pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="25.001" cy="32.821" stroke="#F7BD13" id="connector6pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="25.702" stroke="#F7BD13" id="connector7pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="18.503" stroke="#F7BD13" id="connector8pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="11.302" stroke="#F7BD13" id="connector9pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="25.029" cy="4.077" stroke="#F7BD13" id="connector10pin" r="2.052" stroke-width="1.224"/>
</g>
<circle fill="none" cx="3.362" cy="4.091" stroke="#F7BD13" id="connector1pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="11.29" stroke="#F7BD13" id="connector2pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="18.491" stroke="#F7BD13" id="connector3pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.362" cy="25.69" stroke="#F7BD13" id="connector4pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="3.365" cy="32.81" stroke="#F7BD13" id="connector5pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="25.001" cy="32.821" stroke="#F7BD13" id="connector6pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="25.702" stroke="#F7BD13" id="connector7pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="18.503" stroke="#F7BD13" id="connector8pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="24.999" cy="11.302" stroke="#F7BD13" id="connector9pin" r="2.052" stroke-width="1.224"/>
<circle fill="none" cx="25.029" cy="4.077" stroke="#F7BD13" id="connector10pin" r="2.052" stroke-width="1.224"/>
</g>
<g id="silkscreen">
<rect width="28.347" x="0.024" y="0.024" height="36.851" fill="none" stroke="#FFFFFF" stroke-width="0.7087"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,468 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50.4px" height="122.448px" viewBox="0 0 50.4 122.448" enable-background="new 0 0 50.4 122.448" xml:space="preserve">
<desc>Fritzing footprint generated by brd2svg</desc>
<g id="silkscreen">
<path fill="none" stroke="#FFFFFF" stroke-width="0.576" d="M0.288,122.136h49.824V0.288H0.288V122.136"/>
<g>
<title>element:J1</title>
<g>
<title>package:HEAD15-NOSS</title>
</g>
</g>
<g>
<title>element:J2</title>
<g>
<title>package:HEAD15-NOSS-1</title>
</g>
</g>
<g>
<title>element:U2</title>
<g>
<title>package:SSOP28</title>
</g>
</g>
<g>
<title>element:U3</title>
<g>
<title>package:SOT223</title>
</g>
</g>
</g>
<g id="copper1">
<g id="copper0">
<circle id="connector16pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="10.8" r="1.908"/>
<rect x="1.692" y="8.892" fill="none" stroke="#F7BD13" stroke-width="1.224" width="3.814" height="3.816"/>
<circle id="connector17pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="18" r="1.908"/>
<circle id="connector18pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="25.2" r="1.908"/>
<circle id="connector19pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="32.4" r="1.908"/>
<circle id="connector20pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="39.6" r="1.908"/>
<circle id="connector21pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="46.8" r="1.908"/>
<circle id="connector22pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="54" r="1.908"/>
<circle id="connector23pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="61.2" r="1.908"/>
<circle id="connector24pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="68.4" r="1.908"/>
<circle id="connector25pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="75.6" r="1.908"/>
<circle id="connector26pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="82.8" r="1.908"/>
<circle id="connector27pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="90" r="1.908"/>
<circle id="connector28pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="97.2" r="1.908"/>
<circle id="connector29pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="104.4" r="1.908"/>
<circle id="connector30pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="111.6" r="1.908"/>
<circle id="connector31pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="10.8" r="1.908"/>
<circle id="connector32pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="18" r="1.908"/>
<circle id="connector33pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="25.2" r="1.908"/>
<circle id="connector34pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="32.4" r="1.908"/>
<circle id="connector35pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="39.6" r="1.908"/>
<circle id="connector36pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="46.8" r="1.908"/>
<circle id="connector37pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="54" r="1.908"/>
<circle id="connector38pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="61.2" r="1.908"/>
<circle id="connector39pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="68.4" r="1.908"/>
<circle id="connector40pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="75.6" r="1.908"/>
<circle id="connector41pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="82.8" r="1.908"/>
<circle id="connector42pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="90" r="1.908"/>
<circle id="connector43pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="97.2" r="1.908"/>
<circle id="connector44pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="104.4" r="1.908"/>
<circle id="connector45pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="111.6" r="1.908"/>
</g>
</g>
<g>
<title>layer 21</title>
<g>
<title>text:TX1</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 13.68)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -6.713867e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">TX1</text>
</g>
</g>
</g>
<g>
<title>text:RX0</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 20.88)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 1.220703e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RX0</text>
</g>
</g>
</g>
<g>
<title>text:RST</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 28.008)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -7.934570e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RST</text>
</g>
</g>
</g>
<g>
<title>text:GND</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 35.208)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 0 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">GND</text>
</g>
</g>
</g>
<g>
<title>text:D2</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 41.544)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D2</text>
</g>
</g>
</g>
<g>
<title>text:D3</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 48.6)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -5.798340e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D3</text>
</g>
</g>
</g>
<g>
<title>text:D4</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 55.872)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D4</text>
</g>
</g>
</g>
<g>
<title>text:D5</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 62.928)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -7.019043e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D5</text>
</g>
</g>
</g>
<g>
<title>text:D6</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 70.272)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -4.577637e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D6</text>
</g>
</g>
</g>
<g>
<title>text:D7</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 77.544)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D7</text>
</g>
</g>
</g>
<g>
<title>text:D8</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 84.6)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -5.798340e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D8</text>
</g>
</g>
</g>
<g>
<title>text:D9</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 91.872)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D9</text>
</g>
</g>
</g>
<g>
<title>text:D10</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 100.224)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0016 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D10</text>
</g>
</g>
</g>
<g>
<title>text:D11</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 107.352)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -5.493164e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D11</text>
</g>
</g>
</g>
<g>
<title>text:D12</title>
<g transform="matrix(1, 0, 0, 1, 9.216, 114.552)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0017 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D12</text>
</g>
</g>
</g>
<g>
<title>text:D13</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 114.552)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0017 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D13</text>
</g>
</g>
</g>
<g>
<title>text:3V3</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 107.28)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -2.746582e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">3V3</text>
</g>
</g>
</g>
<g>
<title>text:REF</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 100.152)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0013 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">REF</text>
</g>
</g>
</g>
<g>
<title>text:A0</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 91.944)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -3.356934e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A0</text>
</g>
</g>
</g>
<g>
<title>text:A1</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 84.672)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -8.544922e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A1</text>
</g>
</g>
</g>
<g>
<title>text:A2</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 77.544)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 6.103516e-005 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A2</text>
</g>
</g>
</g>
<g>
<title>text:A3</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 70.344)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -7.324219e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A3</text>
</g>
</g>
</g>
<g>
<title>text:A4</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 63.216)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A4</text>
</g>
</g>
</g>
<g>
<title>text:A5</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 55.944)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -3.356934e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A5</text>
</g>
</g>
</g>
<g>
<title>text:A6</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 48.744)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0011 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A6</text>
</g>
</g>
</g>
<g>
<title>text:A7</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 41.616)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -2.136230e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A7</text>
</g>
</g>
</g>
<g>
<title>text:5V</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 34.416)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -9.765625e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">5V</text>
</g>
</g>
</g>
<g>
<title>text:RST</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 27.216)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RST</text>
</g>
</g>
</g>
<g>
<title>text:GND</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 19.8)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">GND</text>
</g>
</g>
</g>
<g>
<title>text:VIN</title>
<g transform="matrix(1, 0, 0, 1, 43.488, 12.672)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -8.544922e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">VIN</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 92.664)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.001 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 99.936)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -5.187988e-004 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 107.064)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0014 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 71.064)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 -0.0014 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 63.792)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 0 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>text:*</title>
<g transform="matrix(1, 0, 0, 1, 7.056, 49.464)">
<g transform="rotate(270)">
<text transform="matrix(1 0 0 1 1.220703e-004 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
</g>
</g>
</g>
<g>
<title>element:C1</title>
<g>
<title>package:CAP0805-NP</title>
</g>
</g>
<g>
<title>element:C2</title>
<g>
<title>package:TAN-A</title>
</g>
</g>
<g>
<title>element:C3</title>
<g>
<title>package:CAP0805-NP</title>
</g>
</g>
<g>
<title>element:C4</title>
<g>
<title>package:CAP0805-NP</title>
</g>
</g>
<g>
<title>element:C7</title>
<g>
<title>package:CAP0805-NP</title>
</g>
</g>
<g>
<title>element:C8</title>
<g>
<title>package:TAN-A</title>
</g>
</g>
<g>
<title>element:C9</title>
<g>
<title>package:CAP0805-NP</title>
</g>
</g>
<g>
<title>element:D1</title>
<g>
<title>package:SOD-123</title>
</g>
</g>
<g>
<title>element:J1</title>
<g>
<title>package:HEAD15-NOSS</title>
</g>
</g>
<g>
<title>element:J2</title>
<g>
<title>package:HEAD15-NOSS-1</title>
</g>
</g>
<g>
<title>element:RP1</title>
<g>
<title>package:RES4NT</title>
</g>
</g>
<g>
<title>element:RP2</title>
<g>
<title>package:RES4NT</title>
</g>
</g>
<g>
<title>element:U$4</title>
<g>
<title>package:FIDUCIAL-1X2</title>
</g>
</g>
<g>
<title>element:U$37</title>
<g>
<title>package:FIDUCIAL-1X2</title>
</g>
</g>
<g>
<title>element:U$53</title>
<g>
<title>package:FIDUCIAL-1X2</title>
</g>
</g>
<g>
<title>element:U$54</title>
<g>
<title>package:FIDUCIAL-1X2</title>
</g>
</g>
<g>
<title>element:U2</title>
<g>
<title>package:SSOP28</title>
</g>
</g>
<g>
<title>element:U3</title>
<g>
<title>package:SOT223</title>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1 Basic//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd'><svg baseProfile="basic" height="0.59in" id="svg" version="1.1" viewBox="0 0 67.502 42.52" width="0.94in" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">
<g id="breadboard">
<rect fill="none" height="5.372" id="connector0pin" width="2.16" x="60.644" y="32.178"/>
<rect fill="none" height="5.309" id="connector1pin" width="2.16" x="53.496" y="5.002"/>
<rect fill="none" height="5.309" id="connector2pin" width="2.16" x="60.644" y="5.002"/>
<rect fill="none" height="5.372" id="connector3pin" width="2.159" x="53.506" y="32.178"/>
<rect fill="none" height="5.372" id="connector5pin" width="2.159" x="53.506" y="32.178"/>
<rect fill="none" height="5.372" id="connector4pin" width="2.159" x="53.506" y="32.178"/>
<rect fill="none" height="3.714" id="connector0terminal" width="2.16" x="60.644" y="33.836"/>
<rect fill="none" height="3.669" id="connector1terminal" width="2.16" x="53.496" y="5.002"/>
<rect fill="none" height="3.669" id="connector2terminal" width="2.16" x="60.644" y="5.002"/>
<rect fill="none" height="3.714" id="connector3terminal" width="2.159" x="53.506" y="33.836"/>
<rect fill="none" height="3.714" id="connector5terminal" width="2.159" x="53.506" y="33.836"/>
<rect fill="none" height="3.714" id="connector4terminal" width="2.159" x="53.506" y="33.836"/>
<g>
<polygon fill="#1F7A34" points="49.528,34.417 67.502,34.417 67.502,8.102 49.528,8.102 49.528,0 20.776,0 20.776,42.52 49.528,42.52 "/>
</g>
<g>
<g>
<path d="M30.783,4.96c0-1.988-1.609-3.598-3.598-3.598c-1.985,0-3.598,1.609-3.598,3.598 c0,1.985,1.612,3.598,3.598,3.598C29.173,8.558,30.783,6.945,30.783,4.96z" fill="#9A916C"/>
</g>
<g>
<circle cx="27.182" cy="4.96" fill="#3A3A3A" r="2.708"/>
</g>
</g>
<g>
<g>
<path d="M30.783,37.56c0-1.988-1.609-3.598-3.598-3.598c-1.985,0-3.598,1.609-3.598,3.598 c0,1.985,1.612,3.598,3.598,3.598C29.173,41.157,30.783,39.545,30.783,37.56z" fill="#9A916C"/>
</g>
<g>
<circle cx="27.182" cy="37.56" fill="#3A3A3A" r="2.708"/>
</g>
</g>
<g>
<rect fill="#898989" height="34.016" width="45.355" x="0.001" y="4.252"/>
</g>
<g>
<rect fill="#DDDDDD" height="0.743" width="45.355" x="0.001" y="4.252"/>
</g>
<g>
<rect fill="#C6C6C6" height="0.889" width="45.355" x="0.001" y="4.991"/>
</g>
<g>
<rect fill="#ADADAD" height="31.342" width="45.356" y="5.88"/>
</g>
<g>
<line fill="#919191" stroke="#4D4D4D" stroke-width="0.1" x1="34.173" x2="34.173" y1="4.252" y2="38.268"/>
</g>
<g>
<rect fill="#8C8C8C" height="5.349" width="4.667" x="52.252" y="4.961"/>
</g>
<g>
<rect fill="#8C8C8C" height="5.349" width="4.668" x="59.418" y="4.961"/>
</g>
<g>
<rect fill="#8C8C8C" height="5.349" width="4.667" x="52.252" y="32.177"/>
</g>
<g>
<rect fill="#8C8C8C" height="5.349" width="4.668" x="59.418" y="32.177"/>
</g>
<g>
<path d="M30.074,21.386l-2.64-1.524v1.134H13.468c0.515-0.416,1.008-0.965,1.493-1.505 c0.802-0.894,1.631-1.819,2.338-1.819h2.277c0.141,0.521,0.597,0.913,1.163,0.913c0.677,0,1.226-0.548,1.226-1.225 s-0.549-1.226-1.226-1.226c-0.566,0-1.022,0.392-1.163,0.914h-2.277c-0.985,0-1.868,0.984-2.803,2.026 c-0.744,0.83-1.509,1.675-2.255,1.922h-1.82c-0.185-1.02-1.073-1.794-2.145-1.794c-1.206,0-2.184,0.978-2.184,2.184 c0,1.207,0.978,2.184,2.184,2.184c1.072,0,1.96-0.774,2.145-1.794h5.196c0.746,0.247,1.511,1.093,2.254,1.922 c0.934,1.043,1.817,2.026,2.802,2.026h2.142v0.985h2.595v-2.595h-2.595v0.985h-2.142c-0.707,0-1.536-0.925-2.337-1.818 c-0.485-0.541-0.978-1.09-1.493-1.506h10.592v1.134L30.074,21.386z" fill="#4D4D4D"/>
</g>
<g>
<polyline fill="none" points="54.586,10.31 54.586,17.006 45.357,17.006 " stroke="#8C8C8C" stroke-width="1"/>
</g>
<g>
<polyline fill="none" points="61.732,10.31 61.732,19.841 45.357,19.841 " stroke="#8C8C8C" stroke-width="1"/>
</g>
<g>
<polyline fill="none" points="54.586,32.177 54.586,25.479 45.357,25.479 " stroke="#8C8C8C" stroke-width="1"/>
</g>
<g>
<polyline fill="none" points="61.732,32.177 61.732,22.646 45.357,22.646 " stroke="#8C8C8C" stroke-width="1"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -4,6 +4,8 @@ from PyQt4 import QtGui
from PyQt4.QtCore import QThread
from FlatCAMApp import App
from os import listdir
from os.path import isfile
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMCNCjob, FlatCAMExcellon
from ObjectUI import GerberObjectUI, GeometryObjectUI
from time import sleep
@ -12,11 +14,15 @@ import tempfile
class TclShellTest(unittest.TestCase):
svg_files = 'tests/svg'
svg_filename = 'Arduino Nano3_pcb.svg'
gerber_files = 'tests/gerber_files'
copper_bottom_filename = 'detector_copper_bottom.gbr'
copper_top_filename = 'detector_copper_top.gbr'
cutout_filename = 'detector_contour.gbr'
excellon_filename = 'detector_drill.txt'
gerber_name = "gerber"
geometry_name = "geometry"
excellon_name = "excellon"
gerber_top_name = "top"
gerber_bottom_name = "bottom"
@ -177,4 +183,65 @@ class TclShellTest(unittest.TestCase):
# mirror bottom excellon
self.fc.exec_command_test('mirror %s -box %s -axis X' % (self.excellon_name, self.gerber_cutout_name))
# TODO: tests for tcl
# TODO: tests for tcl
def test_import_svg(self):
"""
Test all SVG files inside svg directory.
Problematic SVG files shold be put there as test reference.
:return:
"""
self.fc.exec_command_test('set_sys units MM')
self.fc.exec_command_test('new')
file_list = listdir(self.svg_files)
for svg_file in file_list:
# import without outname
self.fc.exec_command_test('import_svg "%s/%s"' % (self.svg_files, svg_file))
obj = self.fc.collection.get_by_name(svg_file)
self.assertTrue(isinstance(obj, FlatCAMGeometry),
"Expected FlatCAMGeometry, instead, %s is %s" %
(svg_file, type(obj)))
# import with outname
outname='%s-%s' % (self.geometry_name, svg_file)
self.fc.exec_command_test('import_svg "%s/%s" -outname "%s"' % (self.svg_files, svg_file, outname))
obj = self.fc.collection.get_by_name(outname)
self.assertTrue(isinstance(obj, FlatCAMGeometry),
"Expected FlatCAMGeometry, instead, %s is %s" %
(outname, type(obj)))
names = self.fc.collection.get_names()
self.assertEqual(len(names), len(file_list)*2,
"Expected %d objects, found %d" % (len(file_list)*2, len(file_list)))
def test_import_svg_as_geometry(self):
self.fc.exec_command_test('set_sys units MM')
self.fc.exec_command_test('new')
self.fc.exec_command_test('import_svg "%s/%s" -type geometry -outname "%s"' % (self.svg_files, self.svg_filename, self.geometry_name))
obj = self.fc.collection.get_by_name(self.geometry_name)
self.assertTrue(isinstance(obj, FlatCAMGeometry) and not isinstance(obj, FlatCAMGerber),
"Expected FlatCAMGeometry, instead, %s is %s" %
(self.geometry_name, type(obj)))
def test_import_svg_as_gerber(self):
self.fc.exec_command_test('set_sys units MM')
self.fc.exec_command_test('new')
self.fc.exec_command_test('import_svg "%s/%s" -type gerber -outname "%s"' % (self.svg_files, self.svg_filename, self.gerber_name))
obj = self.fc.collection.get_by_name(self.gerber_name)
self.assertTrue(isinstance(obj, FlatCAMGerber),
"Expected FlatCAMGerber, instead, %s is %s" %
(self.gerber_name, type(obj)))
self.fc.exec_command_test('isolate "%s"' % self.gerber_name)
obj = self.fc.collection.get_by_name(self.gerber_name+'_iso')
self.assertTrue(isinstance(obj, FlatCAMGeometry),
"Expected FlatCAMGeometry, instead, %s is %s" %
(self.gerber_name+'_iso', type(obj)))