meerk40t / svgelements

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

Flatten or apply clip-path to svg path #204

Open manishprasadthapliyal opened 1 year ago

manishprasadthapliyal commented 1 year ago

Hi, Thanks for this fantastic library, I am working on a problem where I want to flatten or add the clip-path to the SVG path itself or find a way to apply to the path how we can apply transformations to the SVG path.

Thank you.

tatarize commented 1 year ago

First, let me say currently this is not done by the library. The clip-paths are not actually clips they are rendered clips. So effectively the geometry within the clip-path is actually not split and disposed of, it exists but it's not technically rastered/rendered. Which means they exist, but aren't drawn. Which is how I've tended to view this problem historically.

I am however somewhat working on this same problem with regards to patterns within a closed shape. There's a lot of useful things with filling a shape with a bunch easily defined vectors that come up in lasers and embroidery.

The actual required geometry functions here are find all the intersections between different segments in the clip polygon and different segments in the subject paths.

210 -- Here's a PR to make that possible.

However, it gets a bit more difficult as you need to actually call a .split() on the different paths. There's currently not code that would support doing that within svgelements. Though it isn't difficult code and I'll need it for my other project. Splitting is just a midpoint for lines, De Casteljau for the bezier curves. And basically duplicating the parameters and giving a different value for sweep for the arcs.

Assuming that's exists you finally need to be able to tell which segments are inside and which segments are outside the clip-path. We'd be able to find all the intersections. Split everything that intersected the path but then we'd need a reasonably fast method of determining whether a point is inside a polygon. Historically I've done this with setting up a scanbeam and finding the active segments within that scanbeam but there might be need to speed up the checks there. This is where we're somewhat stuck on the pattern problem.

Point in polygon isn't a hard algorithm, but unlike a simple 30 line bit of code I'm proud of for the intersections of arbitrary segments it might be a bit outside the realm of this project, even though the goal is clearly well within that realm. I might need to finish the other bits first. But, I'll add the intersections thing and I'll look into adding splits. The API might be a bit weird since you're returning a second line segment from a first and clearly you'd want to call that on a Path() object and just have it take effect within the Path(). So there's some api work to think through.