mathandy / svgpathtools

A collection of tools for manipulating and analyzing SVG Path objects and Bezier curves.
MIT License
557 stars 142 forks source link

closed paths d() method does not write a final "z" #197

Open xmarduel opened 1 year ago

xmarduel commented 1 year ago

for a closed path

   path1 = parse_path('M 300 100 C 100 100 200 200 200 300 L 250 350 Z')
   path1.isclosed()  # is True
   d = path1.d() # 'M 300.0,100.0 C 100.0,100.0 200.0,200.0 200.0,300.0 L 250.0,350.0 L 300.0,100.0'   -> should have a "Z"

   path2 = parse_path(d)
   path2.isclosed() # is True  # actually should be False, d does not have a "Z" and is thus not closed even if first pt == last pt

the method path.d() does not write a "Z" in the string. But even if the last point is equal to the first point, a "Z" is necessary, because this is not the same, as stated in the svg docs:

''' 9.3.4. The "closepath" command The "closepath" (Z or z) ends the current subpath by connecting it back to its initial point. An automatic straight line is drawn from the current point to the initial point of the current subpath. This path segment may be of zero length. ... A closed subpath differs in behavior from an open subpath whose final coordinate is the initial point of the subpath. The first and last path segments of an open subpath will not be joined, even when the final coordinate of the last path segment is the initial point of the subpath. This will result in the first and last path segments being capped using the current value of stroke-linecap rather than joined using the current value of stroke-linejoin. '''

Finally, defining a new path like the following:

seg1 = CubicBezier(300+100j, 100+100j, 200+200j, 200+300j)  # A cubic beginning at (300, 100) and ending at (200, 300)
seg2 = Line(200+300j, 250+350j)  # A line beginning at (200, 300) and ending at (250, 350)
path = Path(seg1, seg2)  # A path traversing the cubic and then the line

how can we close the path ? (because the condition first pt == last point) is not a suffisant condition. Something like

seg1 = CubicBezier(300+100j, 100+100j, 200+200j, 200+300j)  # A cubic beginning at (300, 100) and ending at (200, 300)
seg2 = Line(200+300j, 250+350j)  # A line beginning at (200, 300) and ending at (250, 350)
zzz z= Z()
path = Path(seg1, seg2, zzzz)  # A path traversing the cubic and then the line

is needed, or whatever else.

Humm, I just, see, there is the "setter": path.closed = True And also I just see d(use_closed_attrib=True) , but which does not help when last_pt != first_pt

hariharan382 commented 1 year ago

Hi i am reading svg file , i could get svg paths but i want to segment the all vlosed paths how do i do that.. please help me out