-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] Add Sweep Operation #636
Conversation
This PR is an attempt to break out a successful experiment from Python. Does this make sense to move to Impl?
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #636 +/- ##
==========================================
- Coverage 91.40% 91.36% -0.05%
==========================================
Files 35 36 +1
Lines 4514 4700 +186
==========================================
+ Hits 4126 4294 +168
- Misses 388 406 +18 ☔ View full report in Codecov by Sentry. |
Hmm, I've never head of an operation like this - how would you use it in practice? Might be nice to add a pretty Sample demonstrating its usefulness. When I think of Sweep, I think of taking a |
I think Swept profiles are called "Pipe"s in CAD; having a sweep on the Swept Volumes aren't used suuper often, but there also aren't many libraries that can do them (I think Siemens NX is the only CAD package with it). Like, cutting funny shaped gears: Or, sometimes it's used as shorthand for the hull operation with spheres for making capsules. It seems like the interesting stuff requires full transform support, so I'll see about adding that... Sweeps are just the minkowski sums of shapes with lines or paths, so that would still be the ideal 😅 |
Based on your examples, it sounds like another way to achieve this is through #426 - particularly if we support both of OpenSCAD's options. For a sliding part, you could extrude the projection with cut = false. This feels like a more intuitive and flexible API to me, which is part of why I think this is a rare function. I'm thinking we'd probably make this two functions: |
But if |
Oh right, I didn't think about that long enough. Hmm, I know how to do a slice, but what's the algorithm for a projection? |
I think openscad just project every triangle into 2D and union them. |
@zalo I don't mean to be discouraging - that video is cool. Still, for |
I feel that the idea of using 2D projection for sweep, union that with the initial and final position should be faster. |
2D projection + Extrude won’t work, see linked comment gif for counter example shape: Also, I’m not familiar enough with Manifold’s internals to implement project and slice operators efficiently 😅 Like Minkowski Sums, this might be part of a class of more expensive mesh algorithms… Though (save for the morphological ops), they tend to veer away from the “Exactish-CSG” spirit of the library (“does simple things fast”?), so I’d understand if you’d rather tell users to use a different library, or write their own extension kernels in the client bindings languages… |
@zalo I am deep inside a debug session of something else, will response later tmr about the slice thing. I think slower operation is fine, we just want to make sure we are not missing some obvious better implementation. |
Project: Just iterate over the halfedges (https://github.com/elalish/manifold/blob/master/src/manifold/src/impl.h#L50) to get the triangles, maybe flip them so they are in the correct winding direction. Slicing: Also iterate over those triangles, get the ones that intersect with the plane? I was thinking about using the halfedge connection for recovering the winding direction, get the next triangle, convert it into intersection line, add it to the polygon, and repeat... Something like that (hand waiving here) |
And I see why this sweep is not that simple now. Thanks. |
Thinking about it, I think we can have a fast and simple algorithm for this. Say the direction is v, for every face we compute the dot product of its normal with v, positive means that we should offset the face, and negative means that it should stay. To avoid self-intersection, we use the collider to compute if the swept volume of a face (positive dot product) will intersect with another face, mark them and do not move them. After moving the faces, we stitch the gaps by checking the neighbors of the moved faces. Because the marked faces have a positive dot product with v, we can compute the sweep result of each connected component of marked faces and union with the previous result. Just thought of this, not sure if it makes sense. |
@pca006132 I came to a similar conclusion about slice and project, though I believe with project you only need to project edges that are between triangles with normals that point up and those that point down. Those should already assemble into closed (self-intersecting) polygons, which we can then run through CrossSection to get the strictly positive winding number part. Do you want to attack those or should I? I also have an idea for offset I want to try out. |
@zalo Yeah, this particular op feels like a combination of too specialized and not really any slower to implement outside of the core library. I think a polygon-sweep-along-path op will be more generally useful, but I want to achieve this via #289, because then it will be very fast and that will also solve a number of other important problems. |
This actually sounds pretty good (though, I’m not sure it’ll work for the more general Translation+Rotation+Scale Matrix Sweep…) My mesh-fu is a little weak… if we delete the backwards triangles, and isolate just the connected component regions, is there a straight-forward way to step along the component boundary? I guess the boundary edges can be marked and remembered during the “backwards triangle deleting” process… That could work! I’ll think about this a little more… |
Oh, there's a couple more use-cases for sweeps that might be really fun:
|
From these examples it seems clear that to be useful, this object-sweep needs to handle rotation as well as translation. @pca006132 I think that means you'll have another category of triangles: those who have some verts with a positive motion dot product, and some with negative. Sounds tricky, but there might be something there. Still, those tool-path problems look like convex solids: for those you can just hull for each step and then union the steps together to make a sweep. That should be doable without any new API. |
you duplicate the verts and stitch them back later but yeah, rotation is hard... |
You can do it. I am working on other stuff right now and don't have enough time for this. |
|
Alright; I'll close for now since the 90% use-case is on Convex Tools/Solids, which can just be Hulled. |
This PR is an attempt to break out a successful experiment from Python.
#192 (comment)
$fn
for more interesting sweep trajectories?