PEP8 and fix in unittest

pull/23/head
alphanoob1337 2017-05-17 12:26:38 +02:00
parent 77cab1e819
commit ecdade1be3
5 changed files with 808 additions and 699 deletions

View File

@ -2136,7 +2136,13 @@ class Path(MutableSequence):
def cropped(self, T0, T1):
"""returns a cropped copy of the path."""
assert 0 <= T0 <= 1 and 0 <= T1<= 1
assert T0 != T1
assert not (T0 == 1 and T1 == 0)
if T0 == 1 and 0 < T1 < 1 and self.isclosed():
return self.cropped(0, T1)
if T1 == 1:
seg1 = self[-1]
t_seg1 = 1
@ -2171,7 +2177,7 @@ class Path(MutableSequence):
# T1<T0 must cross discontinuity case
if T1 < T0:
if self.isclosed():
if not self.isclosed():
raise ValueError("This path is not closed, thus T0 must "
"be less than T1.")
else:

View File

@ -5,23 +5,21 @@ The main tool being the svg2paths() function."""
from __future__ import division, absolute_import, print_function
from xml.dom.minidom import parse
from os import path as os_path, getcwd
from shutil import copyfile
import numpy as np
# Internal dependencies
from .parser import parse_path
from .path import Path, bpoints2bezier
def polyline2pathd(polyline_d):
"""converts the string from a polyline d-attribute to a string for a Path
object d-attribute"""
"""converts the string from a polyline points-attribute to a string for a
Path object d-attribute"""
points = polyline_d.replace(', ', ',')
points = points.replace(' ,', ',')
points = points.split()
if points[0] == points[-1]:
closed = True
else:
closed = False
closed = points[0] == points[-1]
d = 'M' + points.pop(0).replace(',', ' ')
for p in points:
@ -31,6 +29,30 @@ def polyline2pathd(polyline_d):
return d
def polygon2pathd(polyline_d):
"""converts the string from a polygon points-attribute to a string for a
Path object d-attribute.
Note: For a polygon made from n points, the resulting path will be
composed of n lines (even if some of these lines have length zero)."""
points = polyline_d.replace(', ', ',')
points = points.replace(' ,', ',')
points = points.split()
reduntantly_closed = points[0] == points[-1]
d = 'M' + points[0].replace(',', ' ')
for p in points[1:]:
d += 'L' + p.replace(',', ' ')
# The `parse_path` call ignores redundant 'z' (closure) commands
# e.g. `parse_path('M0 0L100 100Z') == parse_path('M0 0L100 100L0 0Z')`
# This check ensures that an n-point polygon is converted to an n-Line path.
if reduntantly_closed:
d += 'L' + points[0].replace(',', ' ')
return d + 'z'
def svg2paths(svg_file_location,
convert_lines_to_paths=True,
convert_polylines_to_paths=True,
@ -62,52 +84,126 @@ def svg2paths(svg_file_location,
# else:
doc = parse(svg_file_location)
# Parse a list of paths
def dom2dict(element):
"""Converts DOM elements to dictionaries of attributes."""
keys = list(element.attributes.keys())
values = [val.value for val in list(element.attributes.values())]
return dict(list(zip(keys, values)))
# Use minidom to extract path strings from input SVG
paths = [dom2dict(el) for el in doc.getElementsByTagName('path')]
d_strings = [el['d'] for el in paths]
attribute_dictionary_list = paths
# if pathless_svg:
# for el in doc.getElementsByTagName('path'):
# el.parentNode.removeChild(el)
def parse_trafo(trafo_str):
"""Returns six matrix elements for a matrix transformation for any valid SVG transformation string."""
trafos = trafo_str.split(')')[:-1]
trafo_matrix = np.array([1., 0., 0., 0., 1., 0., 0., 0., 1.]).reshape((3, 3)) # Start with neutral matrix
# Use minidom to extract polyline strings from input SVG, convert to
# path strings, add to list
if convert_polylines_to_paths:
plins = [dom2dict(el) for el in doc.getElementsByTagName('polyline')]
d_strings += [polyline2pathd(pl['points']) for pl in plins]
attribute_dictionary_list += plins
for trafo_sub_str in trafos:
trafo_sub_str = trafo_sub_str.lstrip(', ')
value_str = trafo_sub_str.split('(')[1]
values = list(map(float, value_str.split(',')))
if 'translate' in trafo_sub_str:
x = values[0]
y = values[1] if (len(values) > 1) else 0.
trafo_matrix = np.dot(trafo_matrix,
np.array([1., 0., x, 0., 1., y, 0., 0., 1.]).reshape((3, 3)))
elif 'scale' in trafo_sub_str:
x = values[0]
y = values[1] if (len(values) > 1) else 0.
trafo_matrix = np.dot(trafo_matrix,
np.array([x, 0., 0., 0., y, 0., 0., 0., 1.]).reshape((3, 3)))
elif 'rotate' in trafo_sub_str:
a = values[0]*np.pi/180.
x = values[1] if (len(values) > 1) else 0.
y = values[2] if (len(values) > 2) else 0.
am = np.dot(np.array([np.cos(a), -np.sin(a), 0., np.sin(a), np.cos(a), 0., 0., 0., 1.]).reshape((3, 3)),
np.array([1., 0., -x, 0., 1., -y, 0., 0., 1.]).reshape((3, 3)))
am = np.dot(np.array([1., 0., x, 0., 1., y, 0., 0., 1.]).reshape((3, 3)), am)
trafo_matrix = np.dot(trafo_matrix, am)
elif 'skewX' in trafo_sub_str:
a = values[0]*np.pi/180.
trafo_matrix = np.dot(trafo_matrix,
np.array([1., np.tan(a), 0., 0., 1., 0., 0., 0., 1.]).reshape((3, 3)))
elif 'skewY' in trafo_sub_str:
a = values[0]*np.pi/180.
trafo_matrix = np.dot(trafo_matrix,
np.array([1., 0., 0., np.tan(a), 1., 0., 0., 0., 1.]).reshape((3, 3)))
else: # Assume matrix transformation
while len(values) < 6:
values += [0.]
trafo_matrix = np.dot(trafo_matrix,
np.array([values[::2], values[1::2], [0., 0., 1.]]))
# Use minidom to extract polygon strings from input SVG, convert to
# path strings, add to list
if convert_polygons_to_paths:
pgons = [dom2dict(el) for el in doc.getElementsByTagName('polygon')]
d_strings += [polyline2pathd(pg['points']) + 'z' for pg in pgons]
attribute_dictionary_list += pgons
trafo_list = list(trafo_matrix.reshape((9,))[:6])
return trafo_list[::3]+trafo_list[1::3]+trafo_list[2::3]
if convert_lines_to_paths:
lines = [dom2dict(el) for el in doc.getElementsByTagName('line')]
d_strings += [('M' + l['x1'] + ' ' + l['y1'] +
'L' + l['x2'] + ' ' + l['y2']) for l in lines]
attribute_dictionary_list += lines
def parse_node(node):
"""Recursively iterate over nodes. Parse the groups individually to apply group transformations."""
# Get everything in this tag
data = [parse_node(child) for child in node.childNodes]
if len(data) == 0:
ret_list = []
attribute_dictionary_list_int = []
else:
# Flatten the lists
ret_list = []
attribute_dictionary_list_int = []
for item in data:
if type(item) == tuple:
if len(item[0]) > 0:
ret_list += item[0]
attribute_dictionary_list_int += item[1]
if node.nodeName == 'g':
# Group found
# Analyse group properties
group = dom2dict(node)
if 'transform' in group.keys():
trafo = group['transform']
# Convert all transformations into a matrix operation
am = parse_trafo(trafo)
am = np.array([am[::2], am[1::2], [0., 0., 1.]])
# Apply transformation to all elements of the paths
def xy(p):
return np.array([p.real, p.imag, 1.])
# if pathless_svg:
# with open(pathless_svg, "wb") as f:
# doc.writexml(f)
def z(coords):
return coords[0] + 1j*coords[1]
ret_list = [Path(*[bpoints2bezier([z(np.dot(am, xy(pt)))
for pt in seg.bpoints()])
for seg in path])
for path in ret_list]
return ret_list, attribute_dictionary_list_int
elif node.nodeName == 'path':
# Path found; parsing it
path = dom2dict(node)
d_string = path['d']
return [parse_path(d_string)]+ret_list, [path]+attribute_dictionary_list_int
elif convert_polylines_to_paths and node.nodeName == 'polyline':
attrs = dom2dict(node)
path = parse_path(polyline2pathd(node['points']))
return [path]+ret_list, [attrs]+attribute_dictionary_list_int
elif convert_polygons_to_paths and node.nodeName == 'polygon':
attrs = dom2dict(node)
path = parse_path(polygon2pathd(attrs['points']))
return [path]+ret_list, [attrs]+attribute_dictionary_list_int
elif convert_lines_to_paths and node.nodeName == 'line':
line = dom2dict(node)
d_string = ('M' + line['x1'] + ' ' + line['y1'] +
'L' + line['x2'] + ' ' + line['y2'])
path = parse_path(d_string)
return [path]+ret_list, [line]+attribute_dictionary_list_int
else:
return ret_list, attribute_dictionary_list_int
path_list, attribute_dictionary_list = parse_node(doc)
if return_svg_attributes:
svg_attributes = dom2dict(doc.getElementsByTagName('svg')[0])
doc.unlink()
path_list = [parse_path(d) for d in d_strings]
return path_list, attribute_dictionary_list, svg_attributes
else:
doc.unlink()
path_list = [parse_path(d) for d in d_strings]
return path_list, attribute_dictionary_list

File diff suppressed because it is too large Load Diff

View File

@ -15,12 +15,10 @@ test.svg
vectorframes.svg
svgpathtools/__init__.py
svgpathtools/bezier.py
svgpathtools/directional_field.py
svgpathtools/misctools.py
svgpathtools/parser.py
svgpathtools/path.py
svgpathtools/paths2svg.py
svgpathtools/pathtools.py
svgpathtools/polytools.py
svgpathtools/smoothing.py
svgpathtools/svg2paths.py
@ -28,10 +26,13 @@ svgpathtools.egg-info/PKG-INFO
svgpathtools.egg-info/SOURCES.txt
svgpathtools.egg-info/dependency_links.txt
svgpathtools.egg-info/top_level.txt
test/groups.svg
test/polygons.svg
test/test.svg
test/test_bezier.py
test/test_generation.py
test/test_parsing.py
test/test_path.py
test/test_pathtools.py
test/test_polytools.py
test/test_polytools.py
test/test_svg2paths.py
test/test_svg2paths_groups.py

View File

@ -83,7 +83,7 @@
id="p14"
style="stroke:#ff0000;stroke-width:2."
d="m 1100.,100. 100.,0." />
<g id="concatenated" transform="translate(1150.,150.),rotate(-90.)">
<g id="concatenated" transform="translate(1150.,150.) rotate(-90.)">
<path
id="p15"
style="stroke:#ff0000;stroke-width:2."

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB