Changed other files back to mathandys master release.
parent
fd3c0091b8
commit
a4b0c7e229
|
@ -5,21 +5,23 @@ The main tool being the svg2paths() function."""
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
from xml.dom.minidom import parse
|
from xml.dom.minidom import parse
|
||||||
from os import path as os_path, getcwd
|
from os import path as os_path, getcwd
|
||||||
import numpy as np
|
from shutil import copyfile
|
||||||
|
|
||||||
# Internal dependencies
|
# Internal dependencies
|
||||||
from .parser import parse_path
|
from .parser import parse_path
|
||||||
from .path import Path, bpoints2bezier
|
|
||||||
|
|
||||||
|
|
||||||
def polyline2pathd(polyline_d):
|
def polyline2pathd(polyline_d):
|
||||||
"""converts the string from a polyline points-attribute to a string for a
|
"""converts the string from a polyline d-attribute to a string for a Path
|
||||||
Path object d-attribute"""
|
object d-attribute"""
|
||||||
points = polyline_d.replace(', ', ',')
|
points = polyline_d.replace(', ', ',')
|
||||||
points = points.replace(' ,', ',')
|
points = points.replace(' ,', ',')
|
||||||
points = points.split()
|
points = points.split()
|
||||||
|
|
||||||
closed = points[0] == points[-1]
|
if points[0] == points[-1]:
|
||||||
|
closed = True
|
||||||
|
else:
|
||||||
|
closed = False
|
||||||
|
|
||||||
d = 'M' + points.pop(0).replace(',', ' ')
|
d = 'M' + points.pop(0).replace(',', ' ')
|
||||||
for p in points:
|
for p in points:
|
||||||
|
@ -29,30 +31,6 @@ def polyline2pathd(polyline_d):
|
||||||
return 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,
|
def svg2paths(svg_file_location,
|
||||||
convert_lines_to_paths=True,
|
convert_lines_to_paths=True,
|
||||||
convert_polylines_to_paths=True,
|
convert_polylines_to_paths=True,
|
||||||
|
@ -84,126 +62,52 @@ def svg2paths(svg_file_location,
|
||||||
# else:
|
# else:
|
||||||
doc = parse(svg_file_location)
|
doc = parse(svg_file_location)
|
||||||
|
|
||||||
# Parse a list of paths
|
|
||||||
def dom2dict(element):
|
def dom2dict(element):
|
||||||
"""Converts DOM elements to dictionaries of attributes."""
|
"""Converts DOM elements to dictionaries of attributes."""
|
||||||
keys = list(element.attributes.keys())
|
keys = list(element.attributes.keys())
|
||||||
values = [val.value for val in list(element.attributes.values())]
|
values = [val.value for val in list(element.attributes.values())]
|
||||||
return dict(list(zip(keys, values)))
|
return dict(list(zip(keys, values)))
|
||||||
|
|
||||||
def parse_trafo(trafo_str):
|
# Use minidom to extract path strings from input SVG
|
||||||
"""Returns six matrix elements for a matrix transformation for any valid SVG transformation string."""
|
paths = [dom2dict(el) for el in doc.getElementsByTagName('path')]
|
||||||
trafos = trafo_str.split(')')[:-1]
|
d_strings = [el['d'] for el in paths]
|
||||||
trafo_matrix = np.array([1., 0., 0., 0., 1., 0., 0., 0., 1.]).reshape((3, 3)) # Start with neutral matrix
|
attribute_dictionary_list = paths
|
||||||
|
# if pathless_svg:
|
||||||
|
# for el in doc.getElementsByTagName('path'):
|
||||||
|
# el.parentNode.removeChild(el)
|
||||||
|
|
||||||
for trafo_sub_str in trafos:
|
# Use minidom to extract polyline strings from input SVG, convert to
|
||||||
trafo_sub_str = trafo_sub_str.lstrip(', ')
|
# path strings, add to list
|
||||||
value_str = trafo_sub_str.split('(')[1]
|
if convert_polylines_to_paths:
|
||||||
values = list(map(float, value_str.split(',')))
|
plins = [dom2dict(el) for el in doc.getElementsByTagName('polyline')]
|
||||||
if 'translate' in trafo_sub_str:
|
d_strings += [polyline2pathd(pl['points']) for pl in plins]
|
||||||
x = values[0]
|
attribute_dictionary_list += plins
|
||||||
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.]]))
|
|
||||||
|
|
||||||
trafo_list = list(trafo_matrix.reshape((9,))[:6])
|
# Use minidom to extract polygon strings from input SVG, convert to
|
||||||
return trafo_list[::3]+trafo_list[1::3]+trafo_list[2::3]
|
# 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
|
||||||
|
|
||||||
def parse_node(node):
|
if convert_lines_to_paths:
|
||||||
"""Recursively iterate over nodes. Parse the groups individually to apply group transformations."""
|
lines = [dom2dict(el) for el in doc.getElementsByTagName('line')]
|
||||||
# Get everything in this tag
|
d_strings += [('M' + l['x1'] + ' ' + l['y1'] +
|
||||||
data = [parse_node(child) for child in node.childNodes]
|
'L' + l['x2'] + ' ' + l['y2']) for l in lines]
|
||||||
if len(data) == 0:
|
attribute_dictionary_list += lines
|
||||||
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.])
|
|
||||||
|
|
||||||
def z(coords):
|
# if pathless_svg:
|
||||||
return coords[0] + 1j*coords[1]
|
# with open(pathless_svg, "wb") as f:
|
||||||
|
# doc.writexml(f)
|
||||||
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:
|
if return_svg_attributes:
|
||||||
svg_attributes = dom2dict(doc.getElementsByTagName('svg')[0])
|
svg_attributes = dom2dict(doc.getElementsByTagName('svg')[0])
|
||||||
doc.unlink()
|
doc.unlink()
|
||||||
|
path_list = [parse_path(d) for d in d_strings]
|
||||||
return path_list, attribute_dictionary_list, svg_attributes
|
return path_list, attribute_dictionary_list, svg_attributes
|
||||||
else:
|
else:
|
||||||
doc.unlink()
|
doc.unlink()
|
||||||
|
path_list = [parse_path(d) for d in d_strings]
|
||||||
return path_list, attribute_dictionary_list
|
return path_list, attribute_dictionary_list
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,10 +15,12 @@ test.svg
|
||||||
vectorframes.svg
|
vectorframes.svg
|
||||||
svgpathtools/__init__.py
|
svgpathtools/__init__.py
|
||||||
svgpathtools/bezier.py
|
svgpathtools/bezier.py
|
||||||
|
svgpathtools/directional_field.py
|
||||||
svgpathtools/misctools.py
|
svgpathtools/misctools.py
|
||||||
svgpathtools/parser.py
|
svgpathtools/parser.py
|
||||||
svgpathtools/path.py
|
svgpathtools/path.py
|
||||||
svgpathtools/paths2svg.py
|
svgpathtools/paths2svg.py
|
||||||
|
svgpathtools/pathtools.py
|
||||||
svgpathtools/polytools.py
|
svgpathtools/polytools.py
|
||||||
svgpathtools/smoothing.py
|
svgpathtools/smoothing.py
|
||||||
svgpathtools/svg2paths.py
|
svgpathtools/svg2paths.py
|
||||||
|
@ -26,13 +28,10 @@ svgpathtools.egg-info/PKG-INFO
|
||||||
svgpathtools.egg-info/SOURCES.txt
|
svgpathtools.egg-info/SOURCES.txt
|
||||||
svgpathtools.egg-info/dependency_links.txt
|
svgpathtools.egg-info/dependency_links.txt
|
||||||
svgpathtools.egg-info/top_level.txt
|
svgpathtools.egg-info/top_level.txt
|
||||||
test/groups.svg
|
|
||||||
test/polygons.svg
|
|
||||||
test/test.svg
|
test/test.svg
|
||||||
test/test_bezier.py
|
test/test_bezier.py
|
||||||
test/test_generation.py
|
test/test_generation.py
|
||||||
test/test_parsing.py
|
test/test_parsing.py
|
||||||
test/test_path.py
|
test/test_path.py
|
||||||
test/test_polytools.py
|
test/test_pathtools.py
|
||||||
test/test_svg2paths.py
|
test/test_polytools.py
|
||||||
test/test_svg2paths_groups.py
|
|
|
@ -97,6 +97,21 @@ def bbox2path(xmin, xmax, ymin, ymax):
|
||||||
return Path(b, r, t.reversed(), l.reversed())
|
return Path(b, r, t.reversed(), l.reversed())
|
||||||
|
|
||||||
|
|
||||||
|
def polyline(*points):
|
||||||
|
"""Converts a list of points to a Path composed of lines connecting those
|
||||||
|
points (i.e. a linear spline or polyline). See also `polygon()`."""
|
||||||
|
return Path(*[Line(points[i], points[i+1])
|
||||||
|
for i in range(len(points) - 1)])
|
||||||
|
|
||||||
|
|
||||||
|
def polygon(*points):
|
||||||
|
"""Converts a list of points to a Path composed of lines connecting those
|
||||||
|
points, then closes the path by connecting the last point to the first.
|
||||||
|
See also `polyline()`."""
|
||||||
|
return Path(*[Line(points[i], points[(i + 1) % len(points)])
|
||||||
|
for i in range(len(points))])
|
||||||
|
|
||||||
|
|
||||||
# Conversion###################################################################
|
# Conversion###################################################################
|
||||||
|
|
||||||
def bpoints2bezier(bpoints):
|
def bpoints2bezier(bpoints):
|
||||||
|
|
Loading…
Reference in New Issue