From fb49d5b752f26f1cfdf11f0c9b5ab6c53e92bd1e Mon Sep 17 00:00:00 2001 From: alphanoob1337 Date: Mon, 10 Apr 2017 09:19:14 +0200 Subject: [PATCH] List of transformations in transform attribute are now parsed correctly. --- svgpathtools/svg2paths.py | 70 ++++++++++++++++++++--------------- test/groups.svg | 13 ++++++- test/test_svg2paths_groups.py | 1 + 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/svgpathtools/svg2paths.py b/svgpathtools/svg2paths.py index e0602b1..fc3a42b 100644 --- a/svgpathtools/svg2paths.py +++ b/svgpathtools/svg2paths.py @@ -93,35 +93,47 @@ def svg2paths(svg_file_location, def parse_trafo(trafo_str): """Returns six matrix elements for a matrix transformation for any valid SVG transformation string.""" - value_str = trafo_str.split('(')[1].split(')')[0] - values = list(map(float, value_str.split(','))) - if 'translate' in trafo_str: - x = values[0] - y = values[1] if (len(values) > 1) else 0. - return [1., 0., 0., 1., x, y] - elif 'scale' in trafo_str: - x = values[0] - y = values[1] if (len(values) > 1) else 0. - return [x, 0., 0., y, 0., 0.] - elif 'rotate' in trafo_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 = list(np.dot(np.array([1., 0., x, 0., 1., y, 0., 0., 1.]).reshape((3, 3)), am).reshape((9, ))[:6]) - am = am[::3]+am[1::3]+am[2::3] - return am - elif 'skewX' in trafo_str: - a = values[0]*np.pi/180. - return [1., 0., np.tan(a), 1., 0., 0.] - elif 'skewY' in trafo_str: - a = values[0]*np.pi/180. - return [1., np.tan(a), 0., 1., 0., 0.] - else: - while len(values) < 6: - values += [0.] - return values + 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 + + 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.]])) + + trafo_list = list(trafo_matrix.reshape((9,))[:6]) + return trafo_list[::3]+trafo_list[1::3]+trafo_list[2::3] def parse_node(node): """Recursively iterate over nodes. Parse the groups individually to apply group transformations.""" diff --git a/test/groups.svg b/test/groups.svg index 1b31c7a..2d35114 100644 --- a/test/groups.svg +++ b/test/groups.svg @@ -1,5 +1,5 @@ - + + + + + + diff --git a/test/test_svg2paths_groups.py b/test/test_svg2paths_groups.py index c548bac..acbdbda 100644 --- a/test/test_svg2paths_groups.py +++ b/test/test_svg2paths_groups.py @@ -11,4 +11,5 @@ class TestSvg2pathsGroups(TestCase): self.assertTrue((len(paths) % 2) == 0) for i in range(len(paths)//2): + print(i * 2) self.assertTrue(len(paths[i * 2].intersect(paths[i * 2 + 1])) > 0, 'Path '+str(i * 2)+' does not intersect path '+str(i * 2 + 1)+'!') \ No newline at end of file