Added functionality to process both circles and ellipses.

Added tests related to the functionality.
pull/21/head
Juan Pablo Contreras 2017-04-07 09:12:04 +02:00
parent 7be111bba8
commit 2a24cf640d
4 changed files with 68 additions and 3 deletions

View File

@ -27,8 +27,34 @@ def polyline2pathd(polyline_d):
return d return d
def ellipse2pathd(ellipse):
"""converts the parameters from an ellipse or a circle to a string for a Path
object d-attribute"""
cx = ellipse.get('cx', None)
cy = ellipse.get('cy', None)
rx = ellipse.get('rx', None)
ry = ellipse.get('ry', None)
r = ellipse.get('r', None)
if r is not None:
rx = ry = float(r)
else:
rx = float(rx)
ry = float(ry)
cx = float(cx)
cy = float(cy)
d = ''
d += 'M' + str(cx - rx) + ',' + str(cy)
d += 'a' + str(rx) + ',' + str(ry) + ' 0 1,0 ' + str(2 * rx) + ',0'
d += 'a' + str(rx) + ',' + str(ry) + ' 0 1,0 ' + str(-2 * rx) + ',0'
return d
def polygon2pathd(polyline_d): def polygon2pathd(polyline_d):
"""converts the string from a polygon points-attribute to a string for a
Path object d-attribute. Path object d-attribute.
Note: For a polygon made from n points, the resulting path will be 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).""" composed of n lines (even if some of these lines have length zero)."""
@ -55,11 +81,12 @@ 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,
convert_polygons_to_paths=True, convert_polygons_to_paths=True,
return_svg_attributes=False): return_svg_attributes=False,
convert_ellipses_to_paths=True):
""" """
Converts an SVG file into a list of Path objects and a list of Converts an SVG file into a list of Path objects and a list of
dictionaries containing their attributes. This currently supports dictionaries containing their attributes. This currently supports
SVG Path, Line, Polyline, and Polygon elements. SVG Path, Line, Polyline, Circle and Ellipse, and Polygon elements.
:param svg_file_location: the location of the svg file :param svg_file_location: the location of the svg file
:param convert_lines_to_paths: Set to False to disclude SVG-Line objects :param convert_lines_to_paths: Set to False to disclude SVG-Line objects
(converted to Paths) (converted to Paths)
@ -69,6 +96,8 @@ def svg2paths(svg_file_location,
objects (converted to Paths) objects (converted to Paths)
:param return_svg_attributes: Set to True and a dictionary of :param return_svg_attributes: Set to True and a dictionary of
svg-attributes will be extracted and returned svg-attributes will be extracted and returned
:param convert_ellipses_to_paths: Set to False to disclude SVG-Ellipse
objects (converted to Paths). Circles are treated as ellipses.
:return: list of Path objects, list of path attribute dictionaries, and :return: list of Path objects, list of path attribute dictionaries, and
(optionally) a dictionary of svg-attributes (optionally) a dictionary of svg-attributes
""" """
@ -108,6 +137,12 @@ def svg2paths(svg_file_location,
'L' + l['x2'] + ' ' + l['y2']) for l in lines] 'L' + l['x2'] + ' ' + l['y2']) for l in lines]
attribute_dictionary_list += lines attribute_dictionary_list += lines
if convert_ellipses_to_paths:
ellipses = [dom2dict(el) for el in doc.getElementsByTagName('ellipse')]
ellipses += [dom2dict(el) for el in doc.getElementsByTagName('circle')]
d_strings += [ellipse2pathd(e) for e in ellipses]
attribute_dictionary_list += ellipses
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()

4
test/circle.svg Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<svg baseProfile="full" height="600px" version="1.1" viewBox="-10.05 -10.05 120.1 120.1" width="600px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="100" cy="100" r="50"/>
</svg>

After

Width:  |  Height:  |  Size: 294 B

4
test/ellipse.svg Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<svg baseProfile="full" height="600px" version="1.1" viewBox="-10.05 -10.05 120.1 120.1" width="600px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<ellipse cx="100" cy="100" rx="50" ry="50"/>
</svg>

After

Width:  |  Height:  |  Size: 304 B

View File

@ -28,3 +28,25 @@ class TestSVG2Paths(unittest.TestCase):
self.assertTrue(path.isclosed()) self.assertTrue(path.isclosed())
self.assertTrue(len(path)==4) self.assertTrue(len(path)==4)
self.assertTrue(path==path_correct) self.assertTrue(path==path_correct)
def test_svg2paths_ellipses(self):
paths, _ = svg2paths(join(dirname(__file__), 'ellipse.svg'))
# ellipse tests
path_ellipse = paths[0]
path_ellipse_correct = Path(Arc(50+100j, 50+50j, 0.0, True, False, 150+100j),
Arc(150+100j, 50+50j, 0.0, True, False, 50+100j))
self.assertTrue(len(path_ellipse)==2)
self.assertTrue(path_ellipse==path_ellipse_correct)
self.assertTrue(path_ellipse.isclosed())
# circle tests
paths, _ = svg2paths(join(dirname(__file__), 'circle.svg'))
path_circle = paths[0]
path_circle_correct = Path(Arc(50+100j, 50+50j, 0.0, True, False, 150+100j),
Arc(150+100j, 50+50j, 0.0, True, False, 50+100j))
self.assertTrue(len(path_circle)==2)
self.assertTrue(path_circle==path_circle_correct)
self.assertTrue(path_circle.isclosed())