discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Rounded Polygon

P
Parkinbot
Thu, Mar 21, 2019 8:15 PM

Ronaldo wrote

As the shape of the corner roundover patch is triangular I am considering
to model it with triangular Bezier patches of degree 6.

No doubt that this can be easily done. I remember an older thread, where you
showed it. But how would you automatically weave in such a patch into a
sweep or polyhedron that coats a larger structure like a roundedCube? Wasn't
that one the problems?
I didn't show it in my code, but it is straightforward if you have a quad
patch (which is squashed at one end).

--
Sent from: http://forum.openscad.org/

Ronaldo wrote > As the shape of the corner roundover patch is triangular I am considering > to model it with triangular Bezier patches of degree 6. No doubt that this can be easily done. I remember an older thread, where you showed it. But how would you automatically weave in such a patch into a sweep or polyhedron that coats a larger structure like a roundedCube? Wasn't that one the problems? I didn't show it in my code, but it is straightforward if you have a quad patch (which is squashed at one end). -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Fri, Mar 22, 2019 1:19 PM

Given two patches joined side by side, to have curvature continuity
between them all that is needed is to satisfy the curvature continuity
condition by the rows of CPs, row by row, as they were CPs of simple
independent curves.
With that in mind, we could devise a patch to roundover a cube corner with
curvature continuity.

Following that line of thought, here is a rectangular patch to provide a
curvature continuity in rounding a corner of a cube.

[image: cornerRoundingI (1).PNG]
The following image shows the mesh of control points (CPs) compared with
with the patch itself.

[image: cornerRounding-CP.PNG]

As can be seen, all CPs rest on the faces of the cube in an array where one
full row of the mesh is collapsed to a point. Some intermediate rows and
columns of the mesh are movable by changing a shape parameter, others CPs
have immutable positions. The mesh of CPs of a corner were computed by the
following code:

function cornerPatchCP(P0,d,r0=0.5) =
let( P1 = P0+d*[1,0,0],
P2 = P0+d*[0,1,0],
P3 = P0+d*[0,0,1] )
[ [for(j=[0:4]) P1+P2],                                  // i=0
let(p0=P1+(1-r0)P2,p1=(P1+P2)(1-r0),p2=P1*(1-r0)+P2) // i=1
[p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2],
let(p0=P1,p1=P0,p2=P2)                                // i=2
[p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2],
let(p0=P1+(1-r0)P3,p1=(1-r0)P3,p2=P2+(1-r0)P3)      // i=3
[p0,p0+r0
(p1-p0),p1,p2+r0
(p1-p2),p2],
let(p0=P1+P3,p1=P3,p2=P2+P3)                          // i=4
[p0,p0+r0
(p1-p0),p1,p2+r0*(p1-p2),p2] ];

Although it is an awkward code, it was easier to be written following the
continuity conditions. The arguments of this function are:

P0 - the coordinates of the corner
d  - the extent of cube corner that will be rounded
r0 - a shape parameter equivalent to the shape parameter of the degree 4
curves with curvature continuity

From the CP matrix, we can sample points on the corner surface by

evaluating BPatchPoint(CPs,u,v) for various values of u and v in the
interval [0,1] and draw isoparametric lines or build a mesh for a
polyhedron call.

I don't like this solution. The collapse of one CP matrix row creates an
inconvenient asymmetry that can be observed by comparing the corner
rounding surface for r0 = 0.073 with the surface of a sphere:

[image: cornerRounding-sphere.PNG]

The image suggests that we have just one symmetry axis instead of 3 as
would be desirable.

Besides, a regular sample of parameters to compute points on the surface
are very irregular with a high concentration of points in the neighborhood
of the point the row was collapsed. That is a reason to pursuit a solution
based on Bezier triangular patches.

The corner surface described above has 25 CPs and a total degree of 8. My
first glance on that indicates that a degree 4 and degree 5 Bezier
triangular patch have not enough degree of freedom to accommodate the
curvature continuity conditions. Possibly a degree 6 triangular patch, with
28 CPs, will have room to satisfy all needed conditions. That will be my
next investigation.

Parkinbot rudolf@digitaldocument.de wrote:

But how would you automatically weave in such a patch into a
sweep or polyhedron that coats a larger structure like a roundedCube?
Wasn't
that one the problems?

I have solved this problem before and reported here. My lazyUnion function
is able to not only union closed manifold but stitch patches. It is
irrelevant for that module whether the patches are manifold or not. The
only condition is that each element of the incoming list is in a polyhedron
data format. And to generate a polyhedron data format for a matrix of
points (a regular mesh) or even a triangular patch is an easy task. To have
a manifold at the end is user responsability. To get it we need that the
points on the border of a patch match the points on border of a patch it
should join to and that the whole model is watertight.

> > Given two patches joined side by side, to have curvature continuity > between them all that is needed is to satisfy the curvature continuity > condition by the rows of CPs, row by row, as they were CPs of simple > independent curves. > With that in mind, we could devise a patch to roundover a cube corner with > curvature continuity. Following that line of thought, here is a rectangular patch to provide a curvature continuity in rounding a corner of a cube. [image: cornerRoundingI (1).PNG] The following image shows the mesh of control points (CPs) compared with with the patch itself. [image: cornerRounding-CP.PNG] As can be seen, all CPs rest on the faces of the cube in an array where one full row of the mesh is collapsed to a point. Some intermediate rows and columns of the mesh are movable by changing a shape parameter, others CPs have immutable positions. The mesh of CPs of a corner were computed by the following code: function cornerPatchCP(P0,d,r0=0.5) = let( P1 = P0+d*[1,0,0], P2 = P0+d*[0,1,0], P3 = P0+d*[0,0,1] ) [ [for(j=[0:4]) P1+P2], // i=0 let(p0=P1+(1-r0)*P2,p1=(P1+P2)*(1-r0),p2=P1*(1-r0)+P2) // i=1 [p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2], let(p0=P1,p1=P0,p2=P2) // i=2 [p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2], let(p0=P1+(1-r0)*P3,p1=(1-r0)*P3,p2=P2+(1-r0)*P3) // i=3 [p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2], let(p0=P1+P3,p1=P3,p2=P2+P3) // i=4 [p0,p0+r0*(p1-p0),p1,p2+r0*(p1-p2),p2] ]; Although it is an awkward code, it was easier to be written following the continuity conditions. The arguments of this function are: P0 - the coordinates of the corner d - the extent of cube corner that will be rounded r0 - a shape parameter equivalent to the shape parameter of the degree 4 curves with curvature continuity >From the CP matrix, we can sample points on the corner surface by evaluating BPatchPoint(CPs,u,v) for various values of u and v in the interval [0,1] and draw isoparametric lines or build a mesh for a polyhedron call. I don't like this solution. The collapse of one CP matrix row creates an inconvenient asymmetry that can be observed by comparing the corner rounding surface for r0 = 0.073 with the surface of a sphere: [image: cornerRounding-sphere.PNG] The image suggests that we have just one symmetry axis instead of 3 as would be desirable. Besides, a regular sample of parameters to compute points on the surface are very irregular with a high concentration of points in the neighborhood of the point the row was collapsed. That is a reason to pursuit a solution based on Bezier triangular patches. The corner surface described above has 25 CPs and a total degree of 8. My first glance on that indicates that a degree 4 and degree 5 Bezier triangular patch have not enough degree of freedom to accommodate the curvature continuity conditions. Possibly a degree 6 triangular patch, with 28 CPs, will have room to satisfy all needed conditions. That will be my next investigation. Parkinbot <rudolf@digitaldocument.de> wrote: > But how would you automatically weave in such a patch into a > sweep or polyhedron that coats a larger structure like a roundedCube? > Wasn't > that one the problems? > I have solved this problem before and reported here. My lazyUnion function is able to not only union closed manifold but stitch patches. It is irrelevant for that module whether the patches are manifold or not. The only condition is that each element of the incoming list is in a polyhedron data format. And to generate a polyhedron data format for a matrix of points (a regular mesh) or even a triangular patch is an easy task. To have a manifold at the end is user responsability. To get it we need that the points on the border of a patch match the points on border of a patch it should join to and that the whole model is watertight.
P
Parkinbot
Sat, Mar 23, 2019 12:43 AM

Ronaldo,

well, the outcome of your solution doesn't look very different to mine. I
had to debug the corner() code a bit to use the correct rotation sequence.
The code for the Bezier triangle is rather simple and moved into the
function corner(). I think it shows a triple symmetrie. I transposed the
vertex matrix which is NxN to get a polygon sequence ordered by z. Therefore
the polygons can easily be extended to prepare a more complex sweep, like a
Bezier cube.

A BezierCube module implementing such a sweep on the basis of your Bezier
functions is shown by the following code. It renders in 0.5s  on my system.
However, the union test with a cube lasts 15s.

http://forum.openscad.org/file/t887/BezierCube2.png

use <Naca_sweep.scad>  // https://www.thingiverse.com/thing:1208001
BezierCube([200, 100, 50], 30, $fn=30, center =true);

module BezierCube(s = 100, r = 30, r0 = 3/4, r1=2/3, center = false)
{
n=$fn?$fn:360/$fa;  // resolution
s=s[0]==undef?[s,s,s]:s; // allow for vector and number
r = abs(r);
if(r==0)
cube(s, center=center);
else
translate(center?[0, 0, 0]:s/2+[r, r, r])
{
q = [[0.001,r], [r,r], [r,0.001]];
b = BZeroCurvature(q[0],q[1],q[2],n=n,r0=r0,r1=r1);
gd = corner(b,r);  // just a corner
sweep(composeCube(s/2, r, data=gd));
}

function composeCube(s, r, data) =
let(upper = [for(j=[0:len(data)-1])
let(S=[[s[0],s[1],0],[-s[0],s[1],0],[-s[0],-s[1],0],[s[0],-s[1], 0]])
[each for(i=[0:3]) Tz(s[2],T(S[i], Rz(90i, data[j])))]])
let(lower = [for(j=[len(data)-1:-1:0])
let(S=[[s[0],s[1],0],[-s[0],s[1],0],[-s[0],-s[1],0],[s[0],-s[1], 0]])
[each for(i=[0:3]) Tz(-s[2],T(S[i], Rz(90
i, Sz(-1, data[j]))))]])
concat(upper, lower) ;

function corner(b,r) = //
let(step = 90/(len(b)-1))
let (m=[for(x=[0: len(b)-1])
let(l = norm(b[x])/r)  // scale by bezier
let(a=atan(b[x][0]/b[x][1])) // get angle
Rz(a, Sx((l), Rx(90, vec3(b))))]) // rotatex, scalex and
rotatez
[for(i=[0:len(m)-1]) [for( j=[0:len(m[0])-1]) m[j][i]]]; // transpose
}

function BezierPoint(p, u) =
(len(p) == 2)?
u*p[1] + (1-u)p[0] :
u
BezierPoint([for(i=[1:len(p)-1]) p[i] ], u)
+ (1-u)*BezierPoint([for(i=[0:len(p)-2]) p[i] ], u);

function BezierCurve(p, n=10) = [for(i=[0:n-1]) BezierPoint(p, i/(n-1)) ];

function BZeroCurvature(p0,p1,p2,n=20,r0=2/3,r1=1/2) =
assert(r0>0 && r0<1 && r1>0 && r1<1, "improper value of r0 or r1")
let( p = [ p0,
p0 + r0*(p1-p0)r1,
p0 + r0
(p1-p0),
p2 + r0*(p1-p2),
p2 + r0*(p1-p2)*r1,
p2 ] )
BezierCurve(p,n);

--
Sent from: http://forum.openscad.org/

Ronaldo, well, the outcome of your solution doesn't look very different to mine. I had to debug the corner() code a bit to use the correct rotation sequence. The code for the Bezier triangle is rather simple and moved into the function corner(). I think it shows a triple symmetrie. I transposed the vertex matrix which is NxN to get a polygon sequence ordered by z. Therefore the polygons can easily be extended to prepare a more complex sweep, like a Bezier cube. A BezierCube module implementing such a sweep on the basis of your Bezier functions is shown by the following code. It renders in 0.5s on my system. However, the union test with a cube lasts 15s. <http://forum.openscad.org/file/t887/BezierCube2.png> use <Naca_sweep.scad> // https://www.thingiverse.com/thing:1208001 BezierCube([200, 100, 50], 30, $fn=30, center =true); module BezierCube(s = 100, r = 30, r0 = 3/4, r1=2/3, center = false) { n=$fn?$fn:360/$fa; // resolution s=s[0]==undef?[s,s,s]:s; // allow for vector and number r = abs(r); if(r==0) cube(s, center=center); else translate(center?[0, 0, 0]:s/2+[r, r, r]) { q = [[0.001,r], [r,r], [r,0.001]]; b = BZeroCurvature(q[0],q[1],q[2],n=n,r0=r0,r1=r1); gd = corner(b,r); // just a corner sweep(composeCube(s/2, r, data=gd)); } function composeCube(s, r, data) = let(upper = [for(j=[0:len(data)-1]) let(S=[[s[0],s[1],0],[-s[0],s[1],0],[-s[0],-s[1],0],[s[0],-s[1], 0]]) [each for(i=[0:3]) Tz(s[2],T(S[i], Rz(90*i, data[j])))]]) let(lower = [for(j=[len(data)-1:-1:0]) let(S=[[s[0],s[1],0],[-s[0],s[1],0],[-s[0],-s[1],0],[s[0],-s[1], 0]]) [each for(i=[0:3]) Tz(-s[2],T(S[i], Rz(90*i, Sz(-1, data[j]))))]]) concat(upper, lower) ; function corner(b,r) = // let(step = 90/(len(b)-1)) let (m=[for(x=[0: len(b)-1]) let(l = norm(b[x])/r) // scale by bezier let(a=atan(b[x][0]/b[x][1])) // get angle Rz(a, Sx((l), Rx(90, vec3(b))))]) // rotatex, scalex and rotatez [for(i=[0:len(m)-1]) [for( j=[0:len(m[0])-1]) m[j][i]]]; // transpose } function BezierPoint(p, u) = (len(p) == 2)? u*p[1] + (1-u)*p[0] : u*BezierPoint([for(i=[1:len(p)-1]) p[i] ], u) + (1-u)*BezierPoint([for(i=[0:len(p)-2]) p[i] ], u); function BezierCurve(p, n=10) = [for(i=[0:n-1]) BezierPoint(p, i/(n-1)) ]; function BZeroCurvature(p0,p1,p2,n=20,r0=2/3,r1=1/2) = assert(r0>0 && r0<1 && r1>0 && r1<1, "improper value of r0 or r1") let( p = [ p0, p0 + r0*(p1-p0)*r1, p0 + r0*(p1-p0), p2 + r0*(p1-p2), p2 + r0*(p1-p2)*r1, p2 ] ) BezierCurve(p,n); -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Sat, Mar 23, 2019 5:14 PM

That seems to be nice (I have not tried yet). However, I have devised what
seems to be a solution simplest than the patchwork I suggested before.

Compute one Bezier corner, lazyUnion() it with its rotation and mirror to
cover all cube vertices roundover and hull() it. As lazyUnion() and hull()
are fast, that may be faster than any other solution.

That seems to be nice (I have not tried yet). However, I have devised what seems to be a solution simplest than the patchwork I suggested before. Compute one Bezier corner, lazyUnion() it with its rotation and mirror to cover all cube vertices roundover and hull() it. As lazyUnion() and hull() are fast, that may be faster than any other solution.
P
Parkinbot
Sat, Mar 23, 2019 6:13 PM

Ronaldo wrote

Compute one Bezier corner, lazyUnion() it with its rotation and mirror to
cover all cube vertices roundover and hull() it. As lazyUnion() and hull()
are fast, that may be faster than any other solution.

Good point and strategy.
That was actually the solution I showed in
http://forum.openscad.org/Rounded-Polygon-tp21897p25905.html where I did a
sweep to create a corner and hulled over 8 instances of this corner.
And it wasn't as fast as the full sweep() (30s vs. 5s), but that was (as I
started to remember), because I had used a for-loop. And a for loop always
implies a union.
I just tried a run for which I put each corner as an explicite instance into
the hull body. It looks like the compile time is indeed even faster than a
full sweep (1s only). This seems to shout for a hull_for() operator that
behaves similar like the intersection_for.

Anyway, "fast" is of course always relative, because any further Boolean
operation will take its time with these vertex monsters.

--
Sent from: http://forum.openscad.org/

Ronaldo wrote > Compute one Bezier corner, lazyUnion() it with its rotation and mirror to > cover all cube vertices roundover and hull() it. As lazyUnion() and hull() > are fast, that may be faster than any other solution. Good point and strategy. That was actually the solution I showed in http://forum.openscad.org/Rounded-Polygon-tp21897p25905.html where I did a sweep to create a corner and hulled over 8 instances of this corner. And it wasn't as fast as the full sweep() (30s vs. 5s), but that was (as I started to remember), because I had used a for-loop. And a for loop always implies a union. I just tried a run for which I put each corner as an explicite instance into the hull body. It looks like the compile time is indeed even faster than a full sweep (1s only). This seems to shout for a hull_for() operator that behaves similar like the intersection_for. Anyway, "fast" is of course always relative, because any further Boolean operation will take its time with these vertex monsters. -- Sent from: http://forum.openscad.org/
A
adrianv
Sat, Mar 23, 2019 11:00 PM

Parkinbot wrote

I just tried a run for which I put each corner as an explicite instance
into
the hull body. It looks like the compile time is indeed even faster than a
full sweep (1s only). This seems to shout for a hull_for() operator that
behaves similar like the intersection_for.

I have not yet had the time to go over what you guys have done, but I will
get to it in a few days.

What would hull_for() do?  And is the real answer not another special
command but rather a way of passing the output of a for command as a set of
children to a calling module?  Because it seems like there are multiple
occasions where you'd like to be able to generate a set of objects with
for() and then pass them to another module that operates on them
individually.  Iff a non-unioning for() command existed then it could
replace intersection_for and would have applications in a variety of places,
I think.  Is this a simpler concept than the idea of generically being able
to return multiple children from a module?

--
Sent from: http://forum.openscad.org/

Parkinbot wrote > I just tried a run for which I put each corner as an explicite instance > into > the hull body. It looks like the compile time is indeed even faster than a > full sweep (1s only). This seems to shout for a hull_for() operator that > behaves similar like the intersection_for. I have not yet had the time to go over what you guys have done, but I will get to it in a few days. What would hull_for() do? And is the real answer not another special command but rather a way of passing the output of a for command as a set of children to a calling module? Because it seems like there are multiple occasions where you'd like to be able to generate a set of objects with for() and then pass them to another module that operates on them individually. Iff a non-unioning for() command existed then it could replace intersection_for and would have applications in a variety of places, I think. Is this a simpler concept than the idea of generically being able to return multiple children from a module? -- Sent from: http://forum.openscad.org/
NH
nop head
Sun, Mar 24, 2019 12:01 AM

There is already a PR for a non-union option for for() as part of a built
in sweep recently. It would make intersection_for() redundant as well I
think.

On Sat, 23 Mar 2019 at 23:01, adrianv avm4@cornell.edu wrote:

Parkinbot wrote

I just tried a run for which I put each corner as an explicite instance
into
the hull body. It looks like the compile time is indeed even faster than

a

full sweep (1s only). This seems to shout for a hull_for() operator that
behaves similar like the intersection_for.

I have not yet had the time to go over what you guys have done, but I will
get to it in a few days.

What would hull_for() do?  And is the real answer not another special
command but rather a way of passing the output of a for command as a set of
children to a calling module?  Because it seems like there are multiple
occasions where you'd like to be able to generate a set of objects with
for() and then pass them to another module that operates on them
individually.  Iff a non-unioning for() command existed then it could
replace intersection_for and would have applications in a variety of
places,
I think.  Is this a simpler concept than the idea of generically being able
to return multiple children from a module?

--
Sent from: http://forum.openscad.org/


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

There is already a PR for a non-union option for for() as part of a built in sweep recently. It would make intersection_for() redundant as well I think. On Sat, 23 Mar 2019 at 23:01, adrianv <avm4@cornell.edu> wrote: > Parkinbot wrote > > I just tried a run for which I put each corner as an explicite instance > > into > > the hull body. It looks like the compile time is indeed even faster than > a > > full sweep (1s only). This seems to shout for a hull_for() operator that > > behaves similar like the intersection_for. > > I have not yet had the time to go over what you guys have done, but I will > get to it in a few days. > > What would hull_for() do? And is the real answer not another special > command but rather a way of passing the output of a for command as a set of > children to a calling module? Because it seems like there are multiple > occasions where you'd like to be able to generate a set of objects with > for() and then pass them to another module that operates on them > individually. Iff a non-unioning for() command existed then it could > replace intersection_for and would have applications in a variety of > places, > I think. Is this a simpler concept than the idea of generically being able > to return multiple children from a module? > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
P
Parkinbot
Sun, Mar 24, 2019 12:30 AM

adrianv wrote

Iff a non-unioning for() command existed then it could
replace intersection_for and would have applications in a variety of
places,
I think.

This is correct. And it has been discussed several times before. I think a
practical solution would be to introduce an ungroup() operator that cancels
out a following group(){} clause in the csg file, which implicitly forces a
union.

hull() for(i=[10,20]) cube(i);

translates into the CSG tree:

hull() {
group() {
cube(size = [10, 10, 10], center = false);
cube(size = [20, 20, 20], center = false);
}
}

If you edit the CSG file to

hull() {
cube(size = [10, 10, 10], center = false);
cube(size = [20, 20, 20], center = false);
}

you obviously get the desired result. Therefore

hull() ungroup() for(i=[10,20]) cube(i);

would translate into

hull() {
ungroup{
group() {
cube(size = [10, 10, 10], center = false);
cube(size = [20, 20, 20], center = false);
}
}
}

and ungroup() would inhibit the immediately following group() clause. If no
immediate group() follows, ungroup() will be ignored or cancelled out. But,
I guess there might be also semantical implications.

@thehans, what do you think?

--
Sent from: http://forum.openscad.org/

adrianv wrote > Iff a non-unioning for() command existed then it could > replace intersection_for and would have applications in a variety of > places, > I think. This is correct. And it has been discussed several times before. I think a practical solution would be to introduce an ungroup() operator that cancels out a following group(){} clause in the csg file, which implicitly forces a union. hull() for(i=[10,20]) cube(i); translates into the CSG tree: hull() { group() { cube(size = [10, 10, 10], center = false); cube(size = [20, 20, 20], center = false); } } If you edit the CSG file to hull() { cube(size = [10, 10, 10], center = false); cube(size = [20, 20, 20], center = false); } you obviously get the desired result. Therefore hull() ungroup() for(i=[10,20]) cube(i); would translate into hull() { ungroup{ group() { cube(size = [10, 10, 10], center = false); cube(size = [20, 20, 20], center = false); } } } and ungroup() would inhibit the immediately following group() clause. If no immediate group() follows, ungroup() will be ignored or cancelled out. But, I guess there might be also semantical implications. @thehans, what do you think? -- Sent from: http://forum.openscad.org/
TP
Torsten Paul
Sun, Mar 24, 2019 12:49 AM

It's not a problem of the language description, it's the internal
processing logic that currently forces each node to return a single
geometry object.
Changing that should open up further options. So basically right
now, every node has to do the implicit union regardless of the
actual need for that. Pushing the responsibility of the to the
level above should help improving a couple of cases, like hull()
with children generated with for(), translate() just translating
the list of children separately or doing an intersection() on
multiple volumes imported from a single 3MF file.

ciao,
Torsten.

It's not a problem of the language description, it's the internal processing logic that currently forces each node to return a single geometry object. Changing that should open up further options. So basically right now, every node has to do the implicit union regardless of the actual need for that. Pushing the responsibility of the to the level above should help improving a couple of cases, like hull() with children generated with for(), translate() just translating the list of children separately or doing an intersection() on multiple volumes imported from a single 3MF file. ciao, Torsten.
NH
nop head
Sun, Mar 24, 2019 12:58 AM

Somehow this PR gets around the problem with hull() for( ..., union=false).
See https://github.com/openscad/openscad/pull/2796#issuecomment-466836941

On Sun, 24 Mar 2019 at 00:50, Torsten Paul Torsten.Paul@gmx.de wrote:

It's not a problem of the language description, it's the internal
processing logic that currently forces each node to return a single
geometry object.
Changing that should open up further options. So basically right
now, every node has to do the implicit union regardless of the
actual need for that. Pushing the responsibility of the to the
level above should help improving a couple of cases, like hull()
with children generated with for(), translate() just translating
the list of children separately or doing an intersection() on
multiple volumes imported from a single 3MF file.

ciao,
Torsten.


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

Somehow this PR gets around the problem with hull() for( ..., union=false). See https://github.com/openscad/openscad/pull/2796#issuecomment-466836941 On Sun, 24 Mar 2019 at 00:50, Torsten Paul <Torsten.Paul@gmx.de> wrote: > It's not a problem of the language description, it's the internal > processing logic that currently forces each node to return a single > geometry object. > Changing that should open up further options. So basically right > now, every node has to do the implicit union regardless of the > actual need for that. Pushing the responsibility of the to the > level above should help improving a couple of cases, like hull() > with children generated with for(), translate() just translating > the list of children separately or doing an intersection() on > multiple volumes imported from a single 3MF file. > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >