discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Unusual hull() and minkowski modelling

R
Ronaldo
Fri, Jun 17, 2016 3:54 AM

I have found from a discussion in another thread a whole new set of
possibilities of modelling with hull() and minkowski(). I will present here
some of them.

To start consider the following module definitions:

module square3(a,b) scale([a,b,0]) cube(1,center=true);
module circle3(r=1) scale([1,1,0]) cylinder(r=r);
module point3(p)    translate(p)  scale(0) cube();

Essentially, the first and second are a cube and a cylinder smashed onto the
xy plane, and the third a  cube shrinked to the origin. They don't have
volume and the last one does not have even an area. They are 2D and 0D
"shapes" but they are 3D objects in some sense (the reason I added a 3 in
their names).

If you try to preview any of them you will see nothing. But they are not
empty sets. For instance, you can hull() the point3() with a sphere and get
a drop like model:

hull() { sphere(5); point3([0,0,12]); }

or start the model of a T-joint:

hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10);
cylinder(r=5,h=20,center=true); }

It is possible to do intersections of those shapes with real 3D forms before
the hull:

hull() {
intersection(){ cube(20); circle3(7); }
translate([0,0,20]) sphere(10);}

Or even make the hull() of just those strange forms to make a cone:

translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); }

Let us add one 1D object to the arsenal:

module segment3(p,p0=[0,0,0]) {
q = p-p0;
l = norm(q);
b = acos(q[2]/l);
c = atan2(q[1],q[0]);
translate(p0)
rotate([0, b, c])
scale([0,0,l])
cube(1);
}

Now the cube is smashed to an edge then rotate and scaled in such a way to
bring the edge (a line segment) to lay between the points p and p0. Again
you can't see any preview of segment3(). But it appears when you do the hull
of a set of them:

module tetrahedron(h){
hull() {
segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0]
segment3([h,0,0]);
segment3([0,h,0]);
}
}

Now minkowski. This operator is more restricted. To do a minkowski you need
at least one real 3D object. So when I tried change the hull() in the
tetrahedron() to a minkowski I got a system crash. In other trials, I got
one CGAL error message or nothing at all.

But there is a lot of interesting thing to do with the operator. For
instance, a solid linear extrusion:

module solid_linear_extrude(h=1){
minkowski(){
children();
segment3([0,0,h]);
}
}
solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5,
h=30,center=true); }

This code took a longer time to preview but it worked. It is easy and faster
do it with hull().

But hull() does not solve the sweep operation. Minkowski does with the
module:

module sweep_solid(line) {
for(i=[0:len(line)-2])
minkowski(){
children();
segment3(line[i],line[i+1]);
}
}

We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a
sphere(), a cube or, if you have plenty of time, any 3D model. Note that
this is a translational sweep.

Finally, an interesting approach to morphing using minkowski:

module morphing(t) {
minkowski() {
scale((1-t)) children(0);
scale(t) children(1);
}
}

that is applied here to a sphere and a cylinder in an animation:

morphing(1/2-cos(360*$t)/2) { A(); B(); }
module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true);
module B() translate([20,0,0]) sphere(5);

For any given 0<t<1,  morphing(t) is a blend of the two children.

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I have found from a discussion in another thread a whole new set of possibilities of modelling with hull() and minkowski(). I will present here some of them. To start consider the following module definitions: > module square3(a,b) scale([a,b,0]) cube(1,center=true); > module circle3(r=1) scale([1,1,0]) cylinder(r=r); > module point3(p) translate(p) scale(0) cube(); Essentially, the first and second are a cube and a cylinder smashed onto the xy plane, and the third a cube shrinked to the origin. They don't have volume and the last one does not have even an area. They are 2D and 0D "shapes" but they are 3D objects in some sense (the reason I added a 3 in their names). If you try to preview any of them you will see nothing. But they are not empty sets. For instance, you can hull() the point3() with a sphere and get a drop like model: > hull() { sphere(5); point3([0,0,12]); } or start the model of a T-joint: > hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10); > cylinder(r=5,h=20,center=true); } It is possible to do intersections of those shapes with real 3D forms before the hull: > hull() { > intersection(){ cube(20); circle3(7); } > translate([0,0,20]) sphere(10);} Or even make the hull() of just those strange forms to make a cone: > translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); } Let us add one 1D object to the arsenal: > module segment3(p,p0=[0,0,0]) { > q = p-p0; > l = norm(q); > b = acos(q[2]/l); > c = atan2(q[1],q[0]); > translate(p0) > rotate([0, b, c]) > scale([0,0,l]) > cube(1); > } Now the cube is smashed to an edge then rotate and scaled in such a way to bring the edge (a line segment) to lay between the points p and p0. Again you can't see any preview of segment3(). But it appears when you do the hull of a set of them: > module tetrahedron(h){ > hull() { > segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0] > segment3([h,0,0]); > segment3([0,h,0]); > } > } Now minkowski. This operator is more restricted. To do a minkowski you need at least one real 3D object. So when I tried change the hull() in the tetrahedron() to a minkowski I got a system crash. In other trials, I got one CGAL error message or nothing at all. But there is a lot of interesting thing to do with the operator. For instance, a solid linear extrusion: > module solid_linear_extrude(h=1){ > minkowski(){ > children(); > segment3([0,0,h]); > } > } > solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5, > h=30,center=true); } This code took a longer time to preview but it worked. It is easy and faster do it with hull(). But hull() does not solve the sweep operation. Minkowski does with the module: > module sweep_solid(line) { > for(i=[0:len(line)-2]) > minkowski(){ > children(); > segment3(line[i],line[i+1]); > } > } We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a sphere(), a cube or, if you have plenty of time, any 3D model. Note that this is a translational sweep. Finally, an interesting approach to morphing using minkowski: > module morphing(t) { > minkowski() { > scale((1-t)) children(0); > scale(t) children(1); > } > } that is applied here to a sphere and a cylinder in an animation: > morphing(1/2-cos(360*$t)/2) { A(); B(); } > module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true); > module B() translate([20,0,0]) sphere(5); For any given 0<t<1, morphing(t) is a blend of the two children. -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html Sent from the OpenSCAD mailing list archive at Nabble.com.
P
Parkinbot
Fri, Jun 17, 2016 3:02 PM

Ronaldo,

there are people shuffling eggs with wheel loaders ... ;-)
Others find themselves using  Mathematica
https://de.wikipedia.org/wiki/Mathematica  sooner or later.

For a Mathematician it can be fun to study this degenerate stuff, and it can
indeed discover some crash scenarios in OpenSCAD.
But to be honest, I don't see any practical use in working with pathological
constructs, beyond curiosity. Implementation will change over time, and any
of this code might be broken sooner or later.

Again, F5 uses your graphics system for rendering. OpenSCAD 'calculates' its
stuff by feeding proper representations into subsystems, which are supposed
to do the dirty work. It might be enough to install a new OpenGL driver to
change CSG view results. And finally CGAL's Nef polyhedra implementation
might have its own 'opinion' about these things and also change it some day.

As I understand it, OpenSCAD currently bypasses CGAL for 2D shapes and does
some own (fast) calculations on them. So, there are at least three worlds -
and representations - involved ...

I would always decide (and advise) to use a more common or 'straight'
solution instead of 'peek and poke' for robustness and execution time.
Instead of

hull() { sphere(5); point3([0,0,12]);

I'd always apply 'Occam's razor' and simply write:

hull() { sphere(5); cylinder(12, 0.1, 0); }

And everybody (including myself even after a year) will be able to read it.

What do you think, will be gained? More language expressiblity?

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17745.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Ronaldo, there are people shuffling eggs with wheel loaders ... ;-) Others find themselves using Mathematica <https://de.wikipedia.org/wiki/Mathematica> sooner or later. For a Mathematician it can be fun to study this degenerate stuff, and it can indeed discover some crash scenarios in OpenSCAD. But to be honest, I don't see any practical use in working with pathological constructs, beyond curiosity. Implementation will change over time, and any of this code might be broken sooner or later. Again, F5 uses your graphics system for rendering. OpenSCAD 'calculates' its stuff by feeding proper representations into subsystems, which are supposed to do the dirty work. It might be enough to install a new OpenGL driver to change CSG view results. And finally CGAL's Nef polyhedra implementation might have its own 'opinion' about these things and also change it some day. As I understand it, OpenSCAD currently bypasses CGAL for 2D shapes and does some own (fast) calculations on them. So, there are at least three worlds - and representations - involved ... I would always decide (and advise) to use a more common or 'straight' solution instead of 'peek and poke' for *robustness* and execution time. Instead of > hull() { sphere(5); point3([0,0,12]); I'd always apply 'Occam's razor' and simply write: > hull() { sphere(5); cylinder(12, 0.1, 0); } And everybody (including myself even after a year) will be able to read it. What do you think, will be gained? More language expressiblity? -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17745.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
Ronaldo
Fri, Jun 17, 2016 5:18 PM

Rudolf,

I usually like your approach, your way of thinking, and certainly the
experience you bring to the discussions. For me, it is like a counterpoint
to mine ways. And I like diversity.

I agree that the ideas I expressed will have a short live. May be in the
next version. My intention however was to show the gain in expressiveness
when you mix 3D objects with lower dimension ones. I can't see anything
clearer then express a sweep as a minkowski of a solid with a curve or
polyline. And it would be a gain to express the sweep as such. I am not
saying that it should be done that way now because minkowski is lot
expensive yet. May be in the future.

I disagree however that your 'Occam's razor' solution to the drop code is
clearer then mine. I agree that the definition point3() is polemics due to
its use of degenerescence but the drop code is clearer then using a almost
degenerated cylinder. The ideal would be to have primitives point(), edge(),
polygon(), etc that were mixable with 3D solids in a proper way. In that
case, who would code a drop like yours?

Observe that minkowski is processed by CGAL and the library accepts and
process correctly the mix of 3D with lower dimension figures. There is no
real complexities or break in robustness in those mixing. Neither
theoretically nor in the algorithms. What is missing is a way to express
this without to resort to degenerated codes.

Ronaldo

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17747.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Rudolf, I usually like your approach, your way of thinking, and certainly the experience you bring to the discussions. For me, it is like a counterpoint to mine ways. And I like diversity. I agree that the ideas I expressed will have a short live. May be in the next version. My intention however was to show the gain in expressiveness when you mix 3D objects with lower dimension ones. I can't see anything clearer then express a sweep as a minkowski of a solid with a curve or polyline. And it would be a gain to express the sweep as such. I am not saying that it should be done that way now because minkowski is lot expensive yet. May be in the future. I disagree however that your 'Occam's razor' solution to the drop code is clearer then mine. I agree that the definition point3() is polemics due to its use of degenerescence but the drop code is clearer then using a almost degenerated cylinder. The ideal would be to have primitives point(), edge(), polygon(), etc that were mixable with 3D solids in a proper way. In that case, who would code a drop like yours? Observe that minkowski is processed by CGAL and the library accepts and process correctly the mix of 3D with lower dimension figures. There is no real complexities or break in robustness in those mixing. Neither theoretically nor in the algorithms. What is missing is a way to express this without to resort to degenerated codes. Ronaldo -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17747.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Fri, Jun 17, 2016 5:29 PM

Is 3D Minkowski still processed with CGAL? I think there was some work to
bypass CGAL for hull and minkowski to speed them up in the convex case,
which is simple and in the concave case I think it now does a convex
decomposition and unions the results. The union will be done in CGAL and
hence slow. Not sure as my memory is failing.

On 17 June 2016 at 18:18, Ronaldo rcmpersiano@gmail.com wrote:

Rudolf,

I usually like your approach, your way of thinking, and certainly the
experience you bring to the discussions. For me, it is like a counterpoint
to mine ways. And I like diversity.

I agree that the ideas I expressed will have a short live. May be in the
next version. My intention however was to show the gain in expressiveness
when you mix 3D objects with lower dimension ones. I can't see anything
clearer then express a sweep as a minkowski of a solid with a curve or
polyline. And it would be a gain to express the sweep as such. I am not
saying that it should be done that way now because minkowski is lot
expensive yet. May be in the future.

I disagree however that your 'Occam's razor' solution to the drop code is
clearer then mine. I agree that the definition point3() is polemics due to
its use of degenerescence but the drop code is clearer then using a almost
degenerated cylinder. The ideal would be to have primitives point(),
edge(),
polygon(), etc that were mixable with 3D solids in a proper way. In that
case, who would code a drop like yours?

Observe that minkowski is processed by CGAL and the library accepts and
process correctly the mix of 3D with lower dimension figures. There is no
real complexities or break in robustness in those mixing. Neither
theoretically nor in the algorithms. What is missing is a way to express
this without to resort to degenerated codes.

Ronaldo

--
View this message in context:
http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17747.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Is 3D Minkowski still processed with CGAL? I think there was some work to bypass CGAL for hull and minkowski to speed them up in the convex case, which is simple and in the concave case I think it now does a convex decomposition and unions the results. The union will be done in CGAL and hence slow. Not sure as my memory is failing. On 17 June 2016 at 18:18, Ronaldo <rcmpersiano@gmail.com> wrote: > Rudolf, > > I usually like your approach, your way of thinking, and certainly the > experience you bring to the discussions. For me, it is like a counterpoint > to mine ways. And I like diversity. > > I agree that the ideas I expressed will have a short live. May be in the > next version. My intention however was to show the gain in expressiveness > when you mix 3D objects with lower dimension ones. I can't see anything > clearer then express a sweep as a minkowski of a solid with a curve or > polyline. And it would be a gain to express the sweep as such. I am not > saying that it should be done that way now because minkowski is lot > expensive yet. May be in the future. > > I disagree however that your 'Occam's razor' solution to the drop code is > clearer then mine. I agree that the definition point3() is polemics due to > its use of degenerescence but the drop code is clearer then using a almost > degenerated cylinder. The ideal would be to have primitives point(), > edge(), > polygon(), etc that were mixable with 3D solids in a proper way. In that > case, who would code a drop like yours? > > Observe that minkowski is processed by CGAL and the library accepts and > process correctly the mix of 3D with lower dimension figures. There is no > real complexities or break in robustness in those mixing. Neither > theoretically nor in the algorithms. What is missing is a way to express > this without to resort to degenerated codes. > > Ronaldo > > > > -- > View this message in context: > http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17747.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
MK
Marius Kintel
Fri, Jun 17, 2016 7:57 PM

On Jun 17, 2016, at 13:29 PM, nop head nop.head@gmail.com wrote:

Is 3D Minkowski still processed with CGAL? I think there was some work to bypass CGAL for hull and minkowski to speed them up in the convex case, which is simple and in the concave case I think it now does a convex decomposition and unions the results. The union will be done in CGAL and hence slow. Not sure as my memory is failing.

We try to process 3D minkowski using convex hulls and convex decomposition. The hulls themselves are processed using CGAL (although not using Nef polyhedrons, it’s pretty performant). This is an optimization that ideally should already be done within CGAL.
Yes, unions are still slow.

-Marius

> On Jun 17, 2016, at 13:29 PM, nop head <nop.head@gmail.com> wrote: > > Is 3D Minkowski still processed with CGAL? I think there was some work to bypass CGAL for hull and minkowski to speed them up in the convex case, which is simple and in the concave case I think it now does a convex decomposition and unions the results. The union will be done in CGAL and hence slow. Not sure as my memory is failing. > We try to process 3D minkowski using convex hulls and convex decomposition. The hulls themselves are processed using CGAL (although not using Nef polyhedrons, it’s pretty performant). This is an optimization that ideally should already be done within CGAL. Yes, unions are still slow. -Marius
P
Parkinbot
Fri, Jun 17, 2016 11:34 PM

It's also allowed to code the drop without the typo! Sorry, about that.

hull() { sphere(5); cylinder(12, 5, 0); }

I agree, that it would be nice to have a mixed 0D, 1D, 2D, 3D world instead
of only 2D and 3D - which already comes along with a lot of crudities. But
this needs a well thought out approach and would be a step of very high
impact, also with respect to backward compatibility and general language
design. It needs all constructors, all operators, actually the whole
language revised. Possible, but who will work it out, who will implement it.
Maybe there are reasons, why it wasn't been done. One of it definitely might
have been simplicty.

But I perfectly well understand your point. No doubt, it has charming side:

You feed a hull with a couple of points, lines, 2D shapes and get a convex
3D shape hulling all of them.
You feed a minkowski with two polygons - a nonclosed one and closed one - or
a polygon and a 2D shape and get a sweep.
You feed an intersection with a 2D shape living in 3D and get a projection
and so on.

This might gain something, especially the sweep, but I doubt, we will ever
see it this way. Personally I would be happy with much less (get hands on
the f***g points and faces of an OpenSCAD shape, be it only 2D, or minimum
of imported STL and DXF), because I doubt, Minkowski will ever be fast
enough for somebody, who knows what he is doing.

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17752.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

It's also allowed to code the drop without the typo! Sorry, about that. > hull() { sphere(5); cylinder(12, 5, 0); } I agree, that it would be nice to have a mixed 0D, 1D, 2D, 3D world instead of only 2D and 3D - which already comes along with a lot of crudities. But this needs a well thought out approach and would be a step of very high impact, also with respect to backward compatibility and general language design. It needs all constructors, all operators, actually the whole language revised. Possible, but who will work it out, who will implement it. Maybe there are reasons, why it wasn't been done. One of it definitely might have been simplicty. But I perfectly well understand your point. No doubt, it has charming side: You feed a hull with a couple of points, lines, 2D shapes and get a convex 3D shape hulling all of them. You feed a minkowski with two polygons - a nonclosed one and closed one - or a polygon and a 2D shape and get a sweep. You feed an intersection with a 2D shape living in 3D and get a projection and so on. This might gain something, especially the sweep, but I doubt, we will ever see it this way. Personally I would be happy with much less (get hands on the f***g points and faces of an OpenSCAD shape, be it only 2D, or minimum of imported STL and DXF), because I doubt, Minkowski will ever be fast enough for somebody, who knows what he is doing. -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17752.html Sent from the OpenSCAD mailing list archive at Nabble.com.
DM
doug moen
Fri, Jun 17, 2016 11:53 PM

This stuff is really cool, Ronaldo.

I was familiar with the morph() operation from other CSG systems, but I
just assumed it was impossible in OpenSCAD. So I'm impressed. I notice it
only works correctly if scale(0) returns a 0D point (as opposed to
returning nothing).

On 16 June 2016 at 23:54, Ronaldo rcmpersiano@gmail.com wrote:

I have found from a discussion in another thread a whole new set of
possibilities of modelling with hull() and minkowski(). I will present here
some of them.

To start consider the following module definitions:

module square3(a,b) scale([a,b,0]) cube(1,center=true);
module circle3(r=1) scale([1,1,0]) cylinder(r=r);
module point3(p)    translate(p)  scale(0) cube();

Essentially, the first and second are a cube and a cylinder smashed onto
the
xy plane, and the third a  cube shrinked to the origin. They don't have
volume and the last one does not have even an area. They are 2D and 0D
"shapes" but they are 3D objects in some sense (the reason I added a 3 in
their names).

If you try to preview any of them you will see nothing. But they are not
empty sets. For instance, you can hull() the point3() with a sphere and get
a drop like model:

hull() { sphere(5); point3([0,0,12]); }

or start the model of a T-joint:

hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10);
cylinder(r=5,h=20,center=true); }

It is possible to do intersections of those shapes with real 3D forms
before
the hull:

hull() {
intersection(){ cube(20); circle3(7); }
translate([0,0,20]) sphere(10);}

Or even make the hull() of just those strange forms to make a cone:

translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); }

Let us add one 1D object to the arsenal:

module segment3(p,p0=[0,0,0]) {
q = p-p0;
l = norm(q);
b = acos(q[2]/l);
c = atan2(q[1],q[0]);
translate(p0)
rotate([0, b, c])
scale([0,0,l])
cube(1);
}

Now the cube is smashed to an edge then rotate and scaled in such a way to
bring the edge (a line segment) to lay between the points p and p0. Again
you can't see any preview of segment3(). But it appears when you do the
hull
of a set of them:

module tetrahedron(h){
hull() {
segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0]
segment3([h,0,0]);
segment3([0,h,0]);
}
}

Now minkowski. This operator is more restricted. To do a minkowski you need
at least one real 3D object. So when I tried change the hull() in the
tetrahedron() to a minkowski I got a system crash. In other trials, I got
one CGAL error message or nothing at all.

But there is a lot of interesting thing to do with the operator. For
instance, a solid linear extrusion:

module solid_linear_extrude(h=1){
minkowski(){
children();
segment3([0,0,h]);
}
}
solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5,
h=30,center=true); }

This code took a longer time to preview but it worked. It is easy and
faster
do it with hull().

But hull() does not solve the sweep operation. Minkowski does with the
module:

module sweep_solid(line) {
for(i=[0:len(line)-2])
minkowski(){
children();
segment3(line[i],line[i+1]);
}
}

We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a
sphere(), a cube or, if you have plenty of time, any 3D model. Note that
this is a translational sweep.

Finally, an interesting approach to morphing using minkowski:

module morphing(t) {
minkowski() {
scale((1-t)) children(0);
scale(t) children(1);
}
}

that is applied here to a sphere and a cylinder in an animation:

morphing(1/2-cos(360*$t)/2) { A(); B(); }
module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true);
module B() translate([20,0,0]) sphere(5);

For any given 0<t<1,  morphing(t) is a blend of the two children.

--
View this message in context:
http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

This stuff is really cool, Ronaldo. I was familiar with the morph() operation from other CSG systems, but I just assumed it was impossible in OpenSCAD. So I'm impressed. I notice it only works correctly if scale(0) returns a 0D point (as opposed to returning nothing). On 16 June 2016 at 23:54, Ronaldo <rcmpersiano@gmail.com> wrote: > I have found from a discussion in another thread a whole new set of > possibilities of modelling with hull() and minkowski(). I will present here > some of them. > > To start consider the following module definitions: > > > module square3(a,b) scale([a,b,0]) cube(1,center=true); > > module circle3(r=1) scale([1,1,0]) cylinder(r=r); > > module point3(p) translate(p) scale(0) cube(); > > Essentially, the first and second are a cube and a cylinder smashed onto > the > xy plane, and the third a cube shrinked to the origin. They don't have > volume and the last one does not have even an area. They are 2D and 0D > "shapes" but they are 3D objects in some sense (the reason I added a 3 in > their names). > > If you try to preview any of them you will see nothing. But they are not > empty sets. For instance, you can hull() the point3() with a sphere and get > a drop like model: > > > hull() { sphere(5); point3([0,0,12]); } > > or start the model of a T-joint: > > > hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10); > > cylinder(r=5,h=20,center=true); } > > It is possible to do intersections of those shapes with real 3D forms > before > the hull: > > > hull() { > > intersection(){ cube(20); circle3(7); } > > translate([0,0,20]) sphere(10);} > > Or even make the hull() of just those strange forms to make a cone: > > > translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); } > > Let us add one 1D object to the arsenal: > > > module segment3(p,p0=[0,0,0]) { > > q = p-p0; > > l = norm(q); > > b = acos(q[2]/l); > > c = atan2(q[1],q[0]); > > translate(p0) > > rotate([0, b, c]) > > scale([0,0,l]) > > cube(1); > > } > > Now the cube is smashed to an edge then rotate and scaled in such a way to > bring the edge (a line segment) to lay between the points p and p0. Again > you can't see any preview of segment3(). But it appears when you do the > hull > of a set of them: > > > module tetrahedron(h){ > > hull() { > > segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0] > > segment3([h,0,0]); > > segment3([0,h,0]); > > } > > } > > Now minkowski. This operator is more restricted. To do a minkowski you need > at least one real 3D object. So when I tried change the hull() in the > tetrahedron() to a minkowski I got a system crash. In other trials, I got > one CGAL error message or nothing at all. > > But there is a lot of interesting thing to do with the operator. For > instance, a solid linear extrusion: > > > module solid_linear_extrude(h=1){ > > minkowski(){ > > children(); > > segment3([0,0,h]); > > } > > } > > solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5, > > h=30,center=true); } > > This code took a longer time to preview but it worked. It is easy and > faster > do it with hull(). > > But hull() does not solve the sweep operation. Minkowski does with the > module: > > > module sweep_solid(line) { > > for(i=[0:len(line)-2]) > > minkowski(){ > > children(); > > segment3(line[i],line[i+1]); > > } > > } > > We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a > sphere(), a cube or, if you have plenty of time, any 3D model. Note that > this is a translational sweep. > > Finally, an interesting approach to morphing using minkowski: > > > module morphing(t) { > > minkowski() { > > scale((1-t)) children(0); > > scale(t) children(1); > > } > > } > > that is applied here to a sphere and a cylinder in an animation: > > > morphing(1/2-cos(360*$t)/2) { A(); B(); } > > module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true); > > module B() translate([20,0,0]) sphere(5); > > For any given 0<t<1, morphing(t) is a blend of the two children. > > > > -- > View this message in context: > http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
DM
doug moen
Sat, Jun 18, 2016 3:24 AM

There are some open issues requesting point, line segment and path objects
in the 2D plane, for the purpose of DXF export for laser cutting. Eg,
https://github.com/openscad/openscad/issues/508

I don't consider laser cutting a good enough reason by itself to add these
features. However, if these features are important for supporting solid
sweep, morph, and other modelling operations, then it looks more
worthwhile, and laser cutter support is just an added bonus.

Proper support for these kinds of objects would obviously include being
able to see them in preview, and having well defined semantics when used
with all geometric operations (eg, CGAL doesn't crash).

In the 2D subsystem, a reasonable set of degenerate shape constructors
might be

  • point([x,y])
  • path([[x1,y1], [x2,y2], ...], open=true)
  • boundary() 2dShape

A path is a connected series of line segments. An open path has a start and
end point, while a closed path is a loop where the start and end are
connected. So, you can sweep along a path. The boundary() operation
converts a proper 2D shape into the closed path representing its perimeter.

In 3D, we'd have the same primitives, plus a mesh primitive for
constructing a surface, with the same arguments as polyhedron, but the mesh
wouldn't have to be manifold. The boundary() operation on a 3D object would
also return a surface.

Plus, of course, we add some special rules, eg so that scale(0) shape
returns a point.

On 16 June 2016 at 23:54, Ronaldo rcmpersiano@gmail.com wrote:

I have found from a discussion in another thread a whole new set of
possibilities of modelling with hull() and minkowski(). I will present here
some of them.

To start consider the following module definitions:

module square3(a,b) scale([a,b,0]) cube(1,center=true);
module circle3(r=1) scale([1,1,0]) cylinder(r=r);
module point3(p)    translate(p)  scale(0) cube();

Essentially, the first and second are a cube and a cylinder smashed onto
the
xy plane, and the third a  cube shrinked to the origin. They don't have
volume and the last one does not have even an area. They are 2D and 0D
"shapes" but they are 3D objects in some sense (the reason I added a 3 in
their names).

If you try to preview any of them you will see nothing. But they are not
empty sets. For instance, you can hull() the point3() with a sphere and get
a drop like model:

hull() { sphere(5); point3([0,0,12]); }

or start the model of a T-joint:

hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10);
cylinder(r=5,h=20,center=true); }

It is possible to do intersections of those shapes with real 3D forms
before
the hull:

hull() {
intersection(){ cube(20); circle3(7); }
translate([0,0,20]) sphere(10);}

Or even make the hull() of just those strange forms to make a cone:

translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); }

Let us add one 1D object to the arsenal:

module segment3(p,p0=[0,0,0]) {
q = p-p0;
l = norm(q);
b = acos(q[2]/l);
c = atan2(q[1],q[0]);
translate(p0)
rotate([0, b, c])
scale([0,0,l])
cube(1);
}

Now the cube is smashed to an edge then rotate and scaled in such a way to
bring the edge (a line segment) to lay between the points p and p0. Again
you can't see any preview of segment3(). But it appears when you do the
hull
of a set of them:

module tetrahedron(h){
hull() {
segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0]
segment3([h,0,0]);
segment3([0,h,0]);
}
}

Now minkowski. This operator is more restricted. To do a minkowski you need
at least one real 3D object. So when I tried change the hull() in the
tetrahedron() to a minkowski I got a system crash. In other trials, I got
one CGAL error message or nothing at all.

But there is a lot of interesting thing to do with the operator. For
instance, a solid linear extrusion:

module solid_linear_extrude(h=1){
minkowski(){
children();
segment3([0,0,h]);
}
}
solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5,
h=30,center=true); }

This code took a longer time to preview but it worked. It is easy and
faster
do it with hull().

But hull() does not solve the sweep operation. Minkowski does with the
module:

module sweep_solid(line) {
for(i=[0:len(line)-2])
minkowski(){
children();
segment3(line[i],line[i+1]);
}
}

We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a
sphere(), a cube or, if you have plenty of time, any 3D model. Note that
this is a translational sweep.

Finally, an interesting approach to morphing using minkowski:

module morphing(t) {
minkowski() {
scale((1-t)) children(0);
scale(t) children(1);
}
}

that is applied here to a sphere and a cylinder in an animation:

morphing(1/2-cos(360*$t)/2) { A(); B(); }
module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true);
module B() translate([20,0,0]) sphere(5);

For any given 0<t<1,  morphing(t) is a blend of the two children.

--
View this message in context:
http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

There are some open issues requesting point, line segment and path objects in the 2D plane, for the purpose of DXF export for laser cutting. Eg, https://github.com/openscad/openscad/issues/508 I don't consider laser cutting a good enough reason by itself to add these features. However, if these features are important for supporting solid sweep, morph, and other modelling operations, then it looks more worthwhile, and laser cutter support is just an added bonus. Proper support for these kinds of objects would obviously include being able to see them in preview, and having well defined semantics when used with all geometric operations (eg, CGAL doesn't crash). In the 2D subsystem, a reasonable set of degenerate shape constructors might be * point([x,y]) * path([[x1,y1], [x2,y2], ...], open=true) * boundary() 2dShape A path is a connected series of line segments. An open path has a start and end point, while a closed path is a loop where the start and end are connected. So, you can sweep along a path. The boundary() operation converts a proper 2D shape into the closed path representing its perimeter. In 3D, we'd have the same primitives, plus a mesh primitive for constructing a surface, with the same arguments as polyhedron, but the mesh wouldn't have to be manifold. The boundary() operation on a 3D object would also return a surface. Plus, of course, we add some special rules, eg so that scale(0) shape returns a point. On 16 June 2016 at 23:54, Ronaldo <rcmpersiano@gmail.com> wrote: > I have found from a discussion in another thread a whole new set of > possibilities of modelling with hull() and minkowski(). I will present here > some of them. > > To start consider the following module definitions: > > > module square3(a,b) scale([a,b,0]) cube(1,center=true); > > module circle3(r=1) scale([1,1,0]) cylinder(r=r); > > module point3(p) translate(p) scale(0) cube(); > > Essentially, the first and second are a cube and a cylinder smashed onto > the > xy plane, and the third a cube shrinked to the origin. They don't have > volume and the last one does not have even an area. They are 2D and 0D > "shapes" but they are 3D objects in some sense (the reason I added a 3 in > their names). > > If you try to preview any of them you will see nothing. But they are not > empty sets. For instance, you can hull() the point3() with a sphere and get > a drop like model: > > > hull() { sphere(5); point3([0,0,12]); } > > or start the model of a T-joint: > > > hull() { translate([0,-10,0]) rotate([90,0,0]) circle3(5,10); > > cylinder(r=5,h=20,center=true); } > > It is possible to do intersections of those shapes with real 3D forms > before > the hull: > > > hull() { > > intersection(){ cube(20); circle3(7); } > > translate([0,0,20]) sphere(10);} > > Or even make the hull() of just those strange forms to make a cone: > > > translate([0,-20,0]) hull() { circle3(5); point3([0,0,10]); } > > Let us add one 1D object to the arsenal: > > > module segment3(p,p0=[0,0,0]) { > > q = p-p0; > > l = norm(q); > > b = acos(q[2]/l); > > c = atan2(q[1],q[0]); > > translate(p0) > > rotate([0, b, c]) > > scale([0,0,l]) > > cube(1); > > } > > Now the cube is smashed to an edge then rotate and scaled in such a way to > bring the edge (a line segment) to lay between the points p and p0. Again > you can't see any preview of segment3(). But it appears when you do the > hull > of a set of them: > > > module tetrahedron(h){ > > hull() { > > segment3([0,0,h]); // a segment from [0,0,h] to [0,0,0] > > segment3([h,0,0]); > > segment3([0,h,0]); > > } > > } > > Now minkowski. This operator is more restricted. To do a minkowski you need > at least one real 3D object. So when I tried change the hull() in the > tetrahedron() to a minkowski I got a system crash. In other trials, I got > one CGAL error message or nothing at all. > > But there is a lot of interesting thing to do with the operator. For > instance, a solid linear extrusion: > > > module solid_linear_extrude(h=1){ > > minkowski(){ > > children(); > > segment3([0,0,h]); > > } > > } > > solid_linear_extrude(20) difference(){ sphere(10); cylinder(r=5, > > h=30,center=true); } > > This code took a longer time to preview but it worked. It is easy and > faster > do it with hull(). > > But hull() does not solve the sweep operation. Minkowski does with the > module: > > > module sweep_solid(line) { > > for(i=[0:len(line)-2]) > > minkowski(){ > > children(); > > segment3(line[i],line[i+1]); > > } > > } > > We cannot sweep a 2D shape with sweep_solid() but it is possible to sweep a > sphere(), a cube or, if you have plenty of time, any 3D model. Note that > this is a translational sweep. > > Finally, an interesting approach to morphing using minkowski: > > > module morphing(t) { > > minkowski() { > > scale((1-t)) children(0); > > scale(t) children(1); > > } > > } > > that is applied here to a sphere and a cylinder in an animation: > > > morphing(1/2-cos(360*$t)/2) { A(); B(); } > > module A() rotate([90,0,0]) cylinder(r=3,h=15,center=true); > > module B() translate([20,0,0]) sphere(5); > > For any given 0<t<1, morphing(t) is a blend of the two children. > > > > -- > View this message in context: > http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
P
Parkinbot
Sat, Jun 18, 2016 2:23 PM

Ronaldo,

Parkinbot wrote

You feed a minkowski with two polygons - a nonclosed one and closed one -
or a polygon and a 2D shape and get a sweep.
...
because I doubt, Minkowski will ever be fast enough for somebody, who
knows what he is doing.

here is your Minkowski-tweaked sweep() using a path and a 3D shape, which I
called extrude() - also allowing for self-intersection. It is a 'weak'
peek&poke solution, because hull() insists on some 'flesh' in the Z
direction (crashes OpenSCAD otherwise). Also not all Z-trajectories seem to
be 'allowed'.

http://forum.openscad.org/file/n17756/sweep.png

p =  [for (x=[0:10:360]) 30*[cos(x), sin(2x), x/100]];
p1 =  [for (x=[0:4:360]) 30
[cos(x), sin(4*x), -cos(x)]];

extrude(p) cylinder(3);
extrude(p1) sphere(3);

module extrude(p)  minkowski() {polygon2path(p); children();}

module polygon2path(p) for(i=[0:len(p)-2]) line(p[i], p[i+1]);
module line(a, b) hull(){ point(a); point(b);}
module point(t) translate(t) scale([0, 0, 0.0001]) cube([]);

Of course, either polygon2path() could get a built-in operator (avoiding
hull()), or minkowski() could be overloaded to directly accept and process a
vec3D set.

BTW, this is an old solution of mine, the only difference, I used
non-degenerate 'sufficiently small' shapes to hull the path into a solid
then.

Anyway you put it, degenrate or not, I don't see much progress because the
approach is expectedly very slow. Therefore I'd always opt for a dedicated
extrude() operator that could internally use minkowski PLUS some shortcuts
if boundingbox checks allow for them, to speed up things dramatically.

Concerning runtime, don't try the following one. Looks harmless, but I guess
it takes hours to process, due to its convexity.

extrude(p) {sphere(3);translate([2,0,0]) sphere(3);}

I also guess a render() will speed it up a bit to several minutes, but to
get the 'hires' shot (step=2) I preferred to use a convex decomposition,
which tweaked it down to a minute.

extrude(p) sphere(3);
translate([2,0,0])
extrude(p) sphere(3);

Top level object is a 3D object:
Simple:        yes
Vertices:     3027
Halfedges:   14294
Edges:        7147
Halffacets:   8244
Facets:       4122
Volumes:         2

Therefore, I really don't see much chance for the minkowski approach when
implementing extrude().

@Marius
aren't you always looking for some compact crasher code? I never encountered
a higher crash rate before writing this post ;-)

http://forum.openscad.org/file/n17756/sweep2.png

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17756.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Ronaldo, Parkinbot wrote > You feed a minkowski with two polygons - a nonclosed one and closed one - > or a polygon and a 2D shape and get a sweep. > ... > because I doubt, Minkowski will ever be fast enough for somebody, who > knows what he is doing. here is your Minkowski-tweaked sweep() using a path and a 3D shape, which I called extrude() - also allowing for self-intersection. It is a 'weak' peek&poke solution, because hull() insists on some 'flesh' in the Z direction (crashes OpenSCAD otherwise). Also not all Z-trajectories seem to be 'allowed'. <http://forum.openscad.org/file/n17756/sweep.png> > p = [for (x=[0:10:360]) 30*[cos(x), sin(2*x), x/100]]; > p1 = [for (x=[0:4:360]) 30*[cos(x), sin(4*x), -cos(x)]]; > > extrude(p) cylinder(3); > extrude(p1) sphere(3); > > module extrude(p) minkowski() {polygon2path(p); children();} > > module polygon2path(p) for(i=[0:len(p)-2]) line(p[i], p[i+1]); > module line(a, b) hull(){ point(a); point(b);} > module point(t) translate(t) scale([0, 0, 0.0001]) cube([]); Of course, either polygon2path() could get a built-in operator (avoiding hull()), or minkowski() could be overloaded to directly accept and process a vec3D set. BTW, this is an old solution of mine, the only difference, I used non-degenerate 'sufficiently small' shapes to hull the path into a solid then. Anyway you put it, degenrate or not, I don't see much progress because the approach is expectedly very slow. Therefore I'd always opt for a dedicated extrude() operator that could internally use minkowski PLUS some shortcuts if boundingbox checks allow for them, to speed up things dramatically. Concerning runtime, don't try the following one. Looks harmless, but I guess it takes hours to process, due to its convexity. > extrude(p) {sphere(3);translate([2,0,0]) sphere(3);} I also guess a render() will speed it up a bit to several minutes, but to get the 'hires' shot (step=2) I preferred to use a convex decomposition, which tweaked it down to a minute. > extrude(p) sphere(3); > translate([2,0,0]) > extrude(p) sphere(3); > > Top level object is a 3D object: > Simple: yes > Vertices: 3027 > Halfedges: 14294 > Edges: 7147 > Halffacets: 8244 > Facets: 4122 > Volumes: 2 Therefore, I really don't see much chance for the minkowski approach when implementing extrude(). @Marius aren't you always looking for some compact crasher code? I never encountered a higher crash rate before writing this post ;-) <http://forum.openscad.org/file/n17756/sweep2.png> -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17756.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
Ronaldo
Sat, Jun 18, 2016 9:27 PM

Rudolf,

We have two different tricks to do the same thing. In mine, I hack the
system to generate a path that is not provided by the language. In yours, a
very thin polyhedron takes the place of my hack. I agree that my hack has a
short live and your trick should be valid in the future, but that is the
only advantage of it.

I have compared the running time of my sweep with yours. The preview of your
paths with my sweep took less than a second and the render spent 4min. I
gave up to preview that paths with your sweep in my old machine so I
shortened the paths. With a 16 segment path, the preview of your sweep took
more than 6min. On the other hand, the double sphere sweep with my hack took
13min to preview. I didn't try render any of them.

So, your robust trick is a lot slower than doing the right thing: minkowski
the solid with a real line. The reasons are clear to me. The path simulated
by thin polyhedron is a non-convex polyhedron with a lot of vertices. Even
if you do a convex decomposition of the solid to be swept, the path remains
non convex and it will require a lot of effort to be decomposed and
processed. If you have a real polyline, its convex decomposition is trivial.
So, the main effort will be the convex decomposition of the solid and the
union of the extrusions.

I insist that the main point is not the particular hack I devised but the
simplicity and efficiency of mixing 3D objects with lower dimension ones in
some cases. I see no additional complexity in mixing different dimensions in
OpenSCAD. It is enough not to send lower dimension shapes to CGAL and ignore
them in STL generation. The lower dimension objects would be used only for
display purposes and as input of some operations. Observe that the object
circle3() I defined above is able to be boolean operated with real 3D
solids. They seems to be witchcraft but they are real!

I miss lower dimension primitives like segment() in OpenSCAD from my first
experience with the system. So I created my own library to draw them in a
similar way you did. I use them a lot to display lines and facets during
model building debugging. But I cannot render them because the time CGAL
requires to union them is
unaffordable.

--
View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17758.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Rudolf, We have two different tricks to do the same thing. In mine, I hack the system to generate a path that is not provided by the language. In yours, a very thin polyhedron takes the place of my hack. I agree that my hack has a short live and your trick should be valid in the future, but that is the only advantage of it. I have compared the running time of my sweep with yours. The preview of your paths with my sweep took less than a second and the render spent 4min. I gave up to preview that paths with your sweep in my old machine so I shortened the paths. With a 16 segment path, the preview of your sweep took more than 6min. On the other hand, the double sphere sweep with my hack took 13min to preview. I didn't try render any of them. So, your robust trick is a lot slower than doing the right thing: minkowski the solid with a real line. The reasons are clear to me. The path simulated by thin polyhedron is a non-convex polyhedron with a lot of vertices. Even if you do a convex decomposition of the solid to be swept, the path remains non convex and it will require a lot of effort to be decomposed and processed. If you have a real polyline, its convex decomposition is trivial. So, the main effort will be the convex decomposition of the solid and the union of the extrusions. I insist that the main point is not the particular hack I devised but the simplicity and efficiency of mixing 3D objects with lower dimension ones in some cases. I see no additional complexity in mixing different dimensions in OpenSCAD. It is enough not to send lower dimension shapes to CGAL and ignore them in STL generation. The lower dimension objects would be used only for display purposes and as input of some operations. Observe that the object circle3() I defined above is able to be boolean operated with real 3D solids. They seems to be witchcraft but they are real! I miss lower dimension primitives like segment() in OpenSCAD from my first experience with the system. So I created my own library to draw them in a similar way you did. I use them a lot to display lines and facets during model building debugging. But I cannot render them because the time CGAL requires to union them is unaffordable. -- View this message in context: http://forum.openscad.org/Unusual-hull-and-minkowski-modelling-tp17730p17758.html Sent from the OpenSCAD mailing list archive at Nabble.com.