small fix if error happens inside thread execution, then pass correct error_info to display
command imort_svg was using self instead self.app wrong object Fix in svgparse for rotate regexp and division by zero problem. Linestring need at least 2 points within very small arcs. In svg rect x and y are optional , they are 0 by default. Ignore transformation for unknown kind. Strip spaces for ptliststr In parse_svg_point_list to avoid parsing errors.
This commit is contained in:
parent
611d76e877
commit
96419921e5
71
svgparse.py
71
svgparse.py
|
@ -64,6 +64,7 @@ def path2shapely(path, res=1.0):
|
||||||
:param res: Resolution (minimum step along path)
|
:param res: Resolution (minimum step along path)
|
||||||
:return: Shapely geometry object
|
:return: Shapely geometry object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
points = []
|
points = []
|
||||||
|
|
||||||
for component in path:
|
for component in path:
|
||||||
|
@ -86,10 +87,15 @@ def path2shapely(path, res=1.0):
|
||||||
# How many points to use in the dicrete representation.
|
# How many points to use in the dicrete representation.
|
||||||
length = component.length(res / 10.0)
|
length = component.length(res / 10.0)
|
||||||
steps = int(length / res + 0.5)
|
steps = int(length / res + 0.5)
|
||||||
frac = 1.0 / steps
|
|
||||||
|
# solve error when step is below 1,
|
||||||
|
# it may cause other problems, but LineString needs at least two points
|
||||||
|
if steps == 0:
|
||||||
|
steps = 1
|
||||||
|
|
||||||
# print length, steps, frac
|
# print length, steps, frac
|
||||||
for i in range(steps):
|
for i in range(steps):
|
||||||
|
frac = 1.0 / steps
|
||||||
point = component.point(i * frac)
|
point = component.point(i * frac)
|
||||||
x, y = point.real, point.imag
|
x, y = point.real, point.imag
|
||||||
if len(points) == 0 or points[-1] != (x, y):
|
if len(points) == 0 or points[-1] != (x, y):
|
||||||
|
@ -117,9 +123,16 @@ def svgrect2shapely(rect, n_points=32):
|
||||||
"""
|
"""
|
||||||
w = svgparselength(rect.get('width'))[0]
|
w = svgparselength(rect.get('width'))[0]
|
||||||
h = svgparselength(rect.get('height'))[0]
|
h = svgparselength(rect.get('height'))[0]
|
||||||
x = svgparselength(rect.get('x'))[0]
|
x_obj = rect.get('x')
|
||||||
y = svgparselength(rect.get('y'))[0]
|
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')
|
rxstr = rect.get('rx')
|
||||||
rystr = rect.get('ry')
|
rystr = rect.get('ry')
|
||||||
|
|
||||||
|
@ -305,29 +318,31 @@ def getsvggeo(node):
|
||||||
log.warning("Unknown kind: " + kind)
|
log.warning("Unknown kind: " + kind)
|
||||||
geo = None
|
geo = None
|
||||||
|
|
||||||
# Transformations
|
# ignore transformation for unknown kind
|
||||||
if 'transform' in node.attrib:
|
if geo is not None:
|
||||||
trstr = node.get('transform')
|
# Transformations
|
||||||
trlist = parse_svg_transform(trstr)
|
if 'transform' in node.attrib:
|
||||||
#log.debug(trlist)
|
trstr = node.get('transform')
|
||||||
|
trlist = parse_svg_transform(trstr)
|
||||||
|
#log.debug(trlist)
|
||||||
|
|
||||||
# Transformations are applied in reverse order
|
# Transformations are applied in reverse order
|
||||||
for tr in trlist[::-1]:
|
for tr in trlist[::-1]:
|
||||||
if tr[0] == 'translate':
|
if tr[0] == 'translate':
|
||||||
geo = [translate(geoi, tr[1], tr[2]) for geoi in geo]
|
geo = [translate(geoi, tr[1], tr[2]) for geoi in geo]
|
||||||
elif tr[0] == 'scale':
|
elif tr[0] == 'scale':
|
||||||
geo = [scale(geoi, tr[0], tr[1], origin=(0, 0))
|
geo = [scale(geoi, tr[0], tr[1], origin=(0, 0))
|
||||||
for geoi in geo]
|
for geoi in geo]
|
||||||
elif tr[0] == 'rotate':
|
elif tr[0] == 'rotate':
|
||||||
geo = [rotate(geoi, tr[1], origin=(tr[2], tr[3]))
|
geo = [rotate(geoi, tr[1], origin=(tr[2], tr[3]))
|
||||||
for geoi in geo]
|
for geoi in geo]
|
||||||
elif tr[0] == 'skew':
|
elif tr[0] == 'skew':
|
||||||
geo = [skew(geoi, tr[1], tr[2], origin=(0, 0))
|
geo = [skew(geoi, tr[1], tr[2], origin=(0, 0))
|
||||||
for geoi in geo]
|
for geoi in geo]
|
||||||
elif tr[0] == 'matrix':
|
elif tr[0] == 'matrix':
|
||||||
geo = [affine_transform(geoi, tr[1:]) for geoi in geo]
|
geo = [affine_transform(geoi, tr[1:]) for geoi in geo]
|
||||||
else:
|
else:
|
||||||
raise Exception('Unknown transformation: %s', tr)
|
raise Exception('Unknown transformation: %s', tr)
|
||||||
|
|
||||||
return geo
|
return geo
|
||||||
|
|
||||||
|
@ -346,7 +361,7 @@ def parse_svg_point_list(ptliststr):
|
||||||
pos = 0
|
pos = 0
|
||||||
i = 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()])
|
val = float(ptliststr[pos:match.start()])
|
||||||
|
|
||||||
|
@ -435,7 +450,7 @@ def parse_svg_transform(trstr):
|
||||||
r'(?:' + comma_or_space_re_str + \
|
r'(?:' + comma_or_space_re_str + \
|
||||||
r'(' + number_re_str + r')' + \
|
r'(' + number_re_str + r')' + \
|
||||||
comma_or_space_re_str + \
|
comma_or_space_re_str + \
|
||||||
r'(' + number_re_str + r'))?\*\)'
|
r'(' + number_re_str + r'))?\)'
|
||||||
matrix_re_str = r'matrix\s*\(\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 + \
|
||||||
r'(' + number_re_str + r')' + comma_or_space_re_str + \
|
r'(' + number_re_str + r')' + comma_or_space_re_str + \
|
||||||
|
|
|
@ -388,7 +388,11 @@ class TclCommandSignaled(TclCommand):
|
||||||
return self.output
|
return self.output
|
||||||
|
|
||||||
except Exception as unknown:
|
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.log.error("TCL command '%s' failed." % str(self))
|
||||||
self.app.display_tcl_error(unknown, error_info)
|
self.app.display_tcl_error(unknown, error_info)
|
||||||
self.raise_tcl_unknown_error(unknown)
|
self.raise_tcl_unknown_error(unknown)
|
|
@ -58,14 +58,14 @@ class TclCommandImportSvg(TclCommand.TclCommandSignaled):
|
||||||
else:
|
else:
|
||||||
outname = filename.split('/')[-1].split('\\')[-1]
|
outname = filename.split('/')[-1].split('\\')[-1]
|
||||||
|
|
||||||
with self.app.proc_container.new("Opening Gerber"):
|
with self.app.proc_container.new("Import SVG"):
|
||||||
|
|
||||||
# Object creation
|
# Object creation
|
||||||
self.app.new_object("gerber", outname, obj_init)
|
self.app.new_object("geometry", outname, obj_init)
|
||||||
|
|
||||||
# Register recent file
|
# Register recent file
|
||||||
self.file_opened.emit("svg", filename)
|
self.app.file_opened.emit("svg", filename)
|
||||||
|
|
||||||
# GUI feedback
|
# GUI feedback
|
||||||
self.inform.emit("Opened: " + filename)
|
self.app.inform.emit("Opened: " + filename)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue