meerk40t / svgelements

SVG Parsing for Elements, Paths, and other SVG Objects.
MIT License
127 stars 28 forks source link

[Bug]: nested tag groups transformation applied each time #169

Closed Chomucho closed 1 year ago

Chomucho commented 2 years ago

Contact Details

No response

Summary Description

I'm testing with SVG logo file, and there is nested 'g' tag with translate transform. This translate applied at the first time and later the file call 'use' than applied once more.

Additional Details

import numpy as np
import matplotlib.pyplot as plt
from svgelements import *

svg_file = './SVG_Logo.svg'

svg = SVG.parse(svg_file)
svg_elements = list(svg.elements())
poly_n = 0
svg_polygon_arr = []
for i in range(len(svg_elements)):
    if (svg_elements[i].values['tag'] == 'path'):
        temp_poly = np.array([svg_elements[i][0].end.x, svg_elements[i][0].end.y])
        for j in range(1, len(svg_elements[i])):
            temp_curve = svg_elements[i][j].npoint(np.linspace(0, 1, 11))
            temp_poly = np.vstack((temp_poly, temp_curve[1:]))
        svg_polygon_arr.append(temp_poly)
        poly_n += 1

for i in range(len(svg_polygon_arr)):
    plt.plot(svg_polygon_arr[i][:, 0], svg_polygon_arr[i][:, 1])

plt.show()

I checked one of the 'svgbar' and find out that translate transform applied twice. I guess it's because of nested g tag.

svg_elements[43].values {'color': 'black', 'fill': '#ffb13b', 'stroke': 'none', '': 'http://www.w3.org/2000/svg', 'xlink': 'http://www.w3.org/1999/xlink', 'width': '100%', 'height': '100%', 'tag': 'path', 'attributes': {'id': 'svgbar', 'fill': '#ffb13b', 'd': 'M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z', 'tag': 'path'}, 'transform': ' translate(150, 150) translate(150, 150) rotate(135)', '{http://www.w3.org/1999/xlink}href': '#svgbar', 'id': 'svgbar', 'd': 'M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z', 'pathd_loaded': True}

Here's the section using 'svgbar'.

   <g stroke-width="38.0086" stroke="#000">
     <g id="svgstar" transform="translate(150, 150)">
       <path id="svgbar" fill="#ffb13b" d="M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z"/>
       <use xlink:href="#svgbar" transform="rotate(45)"/>
       <use xlink:href="#svgbar" transform="rotate(90)"/>
       <use xlink:href="#svgbar" transform="rotate(135)"/>
     </g>
   </g>
   <use xlink:href="#svgstar"/>

As you can see the picture below, first 'svgbar' of second 'svgstar' (generate by use) doesn't affected. This may happens beacuse first 'svgbar' defined as path.

tatarize commented 2 years ago

svg-logo

While some of the fills are wrong in meerk40t there, the positions are actually spot on.

tatarize commented 2 years ago
import numpy as np
import matplotlib.pyplot as plt
from svgelements import *

svg_file = './SVG_Logo.svg'

svg = SVG.parse(svg_file)
svg_elements = list(svg.elements())

plt.gca().invert_yaxis()
for e in svg_elements:
    if isinstance(e, Shape):
        pts = e.npoint(np.linspace(0,1,100))
        plt.plot(pts[:,0], pts[:,1])
plt.show()
tatarize commented 2 years ago

The other bits in the image were there but way zoomed out. Found them. Yeah, matplotlib is displaying things correctly, svgelements is rendering it wrongly. Likely due to the use nodes there.

tatarize commented 1 year ago

This was fixed in #160 svgelements 1.8.0

image