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
Boolean Path/Region Functions #3288
base: master
Are you sure you want to change the base?
Conversation
…_paths(), offset_paths(), and point_in_paths() builtin functions for 2D boolean path/region manipulation.
…e before committing.
@revarbat It looks like the sort of thing that is potentially very useful, and doing useful things faster is great, but currently I don't understand the exact scope of its usage. Could you provide some specific use case examples here for each of the new features that highlights the intended use and the value of each one? That would help us to evaluate it better. Essentially, it's 5 new specific commands in a language that keeps very few for top-level simplicity, so we need to make sure we understand the applicability, scope, and value before integrating them. |
Some definitions, first:
The basic idea of this PR, is to provide access to the fast 2D boolean geometry functions, for manipulating paths and/or regions.
These all can interchangeably take paths or regions as arguments, and they all return regions. These regions can be manipulated in powerful ways that OpenSCAD does not otherwise provide, such as passing them to common My BOSL2 library has nice documentation for functions in user space almost identical to these, though they are named
For all of the examples below, presume there exist the following functions:
Also presume the existence of the following modules:
my_region = union_paths(
square([40,100], center=true),
square([100,40], center=true)
);
region(my_region); or my_region = union_paths([
square([40,100], center=true),
square([100,40], center=true)
]);
region(my_region); Would generate the same 2D geometry as: union() {
square([40,100], center=true);
square([100,40], center=true);
} Similarly, my_region = difference_paths(
square(100, center=true),
circle(d=40)
);
region(my_region); or my_region = difference_paths([
square(100, center=true),
circle(d=40)
]);
region(my_region); Would generate the same 2D geometry as: difference() {
square(100, center=true);
circle(d=40);
} The You can, of course, pass the output of one to the input of another: my_region = union_paths(
difference_paths(
offset_paths(r=10, square(90, center=true)),
circle(d=50)
),
square([100,20], center=true)
);
region(my_region); The use of for (x = [-50:5:50], y=[-50:5:50])
if (point_in_paths(my_region, [x,y])
translate([x,y]) sphere(d=1, $fn=12); |
I would figure out how 3D shapes would be represented in data, to confirm that they could be unambiguously distinguished from 2D shapes (e.g. by the fact that they have 3 coordinates instead of 2), and then use the obvious I'm not suggesting that you implement 3D variants of these, just that you ensure that they could be implemented. For instance... extending your "paths" and "regions" concepts to 3D, you'd have polyhedra and lists of polyhedra. Extending your "a path could be passed to
and the 3D equivalent of a region would be a vector of those. For reference, your paths are
and your regions are a vector of those. Now, could a function like I was hoping that you could distinguish the four cases just by the structure of the vectors, like you can distinguish paths from regions because a path is a vector of vectors of numbers and a region is a vector of vectors of vectors of numbers. Alas, no, a polyhedron is a vector of vectors of vectors of numbers, and so is a region. However, the dimensionality does save you: for a polyhedron So I think you can distinguish the two cases, and so naming these functions But if one was really concerned, one could name these |
To be more specific, a 2D Path is a list of two or more 2D coordinate vectors like: path = [ [10,-10], [-10,-10], [-10,10], [10,10] ]; And a 3D path is similar, with 3D coordinate points: path = [ [10,-10,0], [-10,-10,10], [-10,10,20], [10,10,10] ]; A region is a list of zero or more paths: region = [
[ [10,-10], [-10,-10], [-10,10], [10,10] ], // path1
[ [5,0], [0,-5], [-5,0], [0,5] ] // path2
]; In the BOSL2 library, the 3D equivalent of a 2D Region structure is called a VNF structure. (Short for Vertices 'N' Faces). It's a two-item list, where the first item is a list of vertices, and the second item is a list of faces, where each face is represented by a list of indices into the vertex list. ie: vnf = [
// Vertices
[ [10,-10,-10], [-10,-10,-10], [-10,10,-10], [10,10,-10], [10,-10,10], [-10,-10,10], [-10,10,10], [10,10,10] ],
// Faces
[ [3,2,1,0], [0,1,5], [0,5,4], /* ... etc ... */ ]
]; You can pass a VNF to Vectors, Paths, Regions, and VNFs are all easily distinguishable from each other:
|
I can easily rename all the functions to remove the |
This came up on the mailing list a few weeks ago, and it seemed numerous people wanted it, so I've implemented it. These are very slow operations to implement in userspace. I know, because I did. They can be quite useful for many things, including
skin()
operations. Theoffset_paths()
operation is especially useful. We've been using userspace versions in our library BOSL2 for a number of complex operations, and the userspace version is slooooooooooooow. OpenSCAD has the ClipperLib linked. It only makes sense to let users use that.I've added the following 2D boolean geometry path/region functions:
union_paths(pathlist, pathlist,...);
orunion_paths(pathlists);
. Returns a pathlist.difference_paths(pathlist, pathlist,...);
ordifference_paths(pathlists);
. Returns a pathlist.intersect_paths(pathlist, pathlist,...);
orpaths_paths(pathlists);
. Returns a pathlist.minkowski_paths(pathlist, pathlist,...);
orminkowski_paths(pathlists);
. Returns a pathlist.offset_paths(pathlist, [r], [delta], (chamfer])
. Returns a pathlist.point_in_paths(pathlist,point)
. Returns -1 if point is on a path, 0 if outside, and 1 if inside.A 2D path, AKA a 2D polygon is a list of 2D points.
A pathlist, AKA a region, is a list of 2D paths.
A pathlists argument is a list of pathlists or paths.
All functions taking one or more pathlist arguments can accept a path instead.