Improved Clip Node
Attached is the demo of a much improved, general purpose clip node.
NOTE: SEE BELOW FOR AN EVEN BETTER VERSION THAT ALLOWS CLIPPING OUTSIDE.
The clip node currently in my library doesn't work very well. My goals for a better node:
- Can clip almost any combination of shapes, paths, and groups
- Works with almost any clipping region, even regions with multiple contours
- Returns an output as close to the input as possible (groups remain grouped, paths intact, colors maintained, etc.)
- Returns unbroken paths whenever possible to be more plotter-friendly
- Work much faster, even with large sets
- No external code required
My improved node is not perfect, but does much better than the old node. PLEASE give it a try. Tell me the kind of things you use the clip node for and how well the new node works. And if fails in some way or is unreasonably slow, please share your NDBX file so I can see where it failed. With your help I can make it even better.
Special note to Floris: In situations where you want to draw straight lines inside a boundary, clip may now work better and faster than mask. Please give it a try. Also let me know if you still have situations where neither mask nor clip works well for you; I may be able to share some variant nodes for special situations.
The mask node is similar to the clip node but has the following differences:
- The mask node only clips open paths or the edges of closed paths; clip handles open paths, closed solid shapes, and lines.
- The mask node is reversible (can return edges inside or outside the boundary); clip only return the inside.
- The mask node requires some approximation (resampling size); the clip node does a near perfect job with no need for fudge factors
- The mask node is slow with larger sets; the clip node runs significantly faster
- The mask node never returns the boundary; the clip node tries never to return the boundary but in some cases may return parts of it (if this happens to you please share it with me)
There are certain cases (e.g. concentric circles) where mask may still be preferred over clip, but these may be relatively few and far between. I'm not 100% sure we need both. If anyone out there has cases where mask works well and clip does not, I'd love to hear about them.
THANKS IN ADVANCE FOR ANYONE RESPONDING TO THIS POST!
Clipping pixels is easy. Clipping vectors is hard. I made a video with my new clip node showing why this is:
Pixels are easy because you just keep the ones inside and drop the ones outside. But with splines (vector paths consisting of line segments and Bézier curves) you actually have to reform the splines whenever they cross a boundary. Even detecting those crossing points is hard. It gets even messier because each spline can be complex, sometimes curving over itself, and the clipping region can also be complex, sometimes containing holes (multiple contours).
So how does Nodebox clip complex drawings to the canvas when you export SVGs, PNGs, PDFs, or movies? It doesn't. Like many vector apps it just waits until the vectors are inevitably converted to pixels (e.g. when displayed on a computer screen) and then clips those pixels. If you look inside an SVG file you will see that your entire drawing is represented with a line at the top listing the canvas size; programs like Preview draw the whole thing as pixels THEN trim away everything outside the canvas boundary.
Nodebox provides only two tools to clip shapes with: compound and delete. Compound only works with solid shapes; open paths will be ignored or treated as solids. Delete has two modes, pixels and paths, but in both cases is all or nothing. It cannot return partial paths. Moreover, both can be flaky. Compound in particular often does strange things to the paths you feed it including changing direction, shifting starting points, causing performance issues only for certain shapes, and adding microscopic points and loops.
The clip node takes a mutifaceted approach. For straight lines it uses the delete node, converting each line to individual points, tossing some, and then recreating the remaining line segments. For solid shapes it uses the compound node plus some extra logic to regroup and recolor. For open paths it first uses the compound node with a slightly shrunken version of the boundary shape to strip away the boundary, then explodes what's left, removes extraneous connecting lines, and then tries to reform remaining segments into continuous paths. There are MANY strange corner cases which it tests for.
Clipping is a surprisingly useful function which can be used to make many strange and wonderful effects. I hope anyone using this node will consider sharing their work on this forum.
- clip_screenshot.png 401 KB
- clip_demo.ndbx.zip 17.6 KB
|?||Show this help|
|ESC||Blurs the current field|
|r||Focus the comment reply box|
|^ + ↩||Submit the comment|
You can use
Command ⌘ instead of
Control ^ on Mac
1 Posted by florisdejonge on 07 Dec, 2022 07:42 PM
Thanks for the post and the new node! I see I have some reading up to do, as well as testing all these new things (I'm also thinking of the updated library). I'll share my experiences both here and on my Instagram as soon as I get back into Nodeboxing and plotting.
Support Staff 2 Posted by john on 25 Jan, 2023 11:18 AM
Attached is an improved version of the clip node.
It now has an "Outside" checkbox. If you check it, it will return everything outside the clipping boundary,
I tested it on a wide variety of shape groups and boundaries, but I may have missed some combination that causes a failure. So PLEASE give this thing a try and report back if it works for you. If you do find a problem, please include a demo of what failed.
Support Staff 3 Posted by john on 26 Jan, 2023 12:48 AM
Attached is an EVEN MORE IMPROVED version of the clip node!
I think this is the final update. It is a very minor improvement over the previous version.
Before, if you fed clip a single path wrapped as a group, it would return one or more paths (whatever parts of it were in or out of the clipping boundary).
Now, the output looks exactly the same, but if you wrap a single path as a group, it will be returned as a group.
The attached demo looks just like the previous one, but has the improved node.
This is a very subtle distinction, but can be important if you want to make sure the output corresponds precisely to the input. So, for example, if you feed a single line through a multi-contoured boundary like, say, a lower case b textpath, you may get multiple segments back. If you need to keep track of the fact that those segments all are associated with the single original line, you can now group that line before feeding it into the clip node and those segments will come out all inside the same group.
If you don't follow that, don't worry. This is an edge case that few people will notice or care about. But I did just notice it and I do care so I fixed it.