discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

The behaviour if intersection has changed.

AC
A. Craig West
Sun, Oct 4, 2020 6:25 PM

As explicit unions can always be added, but unioned objects can't be easily
unioned, it is definitely a more flexible solution. Breaking compatibility
is the only good reason to ever disable it

On Sun, 4 Oct 2020, 14:19 Jordan Brown, openscad@jordan.maileater.net
wrote:

On 10/4/2020 10:41 AM, adrianv wrote:

Isn't the new lazy union mode already doing the "modules return multiple
objects" behavior?  Or is there some subtle distinction here?

I don't know exactly what lazy-union does, but for programmatic purposes
it does not appear to implement "modules return multiple objects".  It
produces a different CSG tree, but doesn't seem to affect the number of
objects visible to the program.

module howmany() {
echo($children);
}

howmany() {
for(i=[1:10])
translate([i*10,0,0]) cube();
}

echoes "1" whether or not lazy unions are enabled.

Similarly:

module two() {
cube();
translate([2,0,0]) cube();
}

howmany() two();

always echoes "1".

[...] I seem to recall there being talk about having for() return its objects separately, and hence not needing intersection_for.

That would be the "modules return multiple objects" behavior - or, as I
would say it, the "modules return zero or more objects" behavior.
Eliminating intersection_for would be one of the advantages.  Similarly, if
you had a spread() module that spaced its children out, you could say:

spread() {
for(i=[1:10]) cube();
}

However, it would lead to a need for more explicit unions:

module spherecube() {
sphere(10);
cube(15, center=true);
}

spread() spherecube();

would not do what you would expect; you would need

module spherecube() {
union() {
sphere(10);
cube(15, center=true);
}
}


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

As explicit unions can always be added, but unioned objects can't be easily unioned, it is definitely a more flexible solution. Breaking compatibility is the only good reason to ever disable it On Sun, 4 Oct 2020, 14:19 Jordan Brown, <openscad@jordan.maileater.net> wrote: > On 10/4/2020 10:41 AM, adrianv wrote: > > Isn't the new lazy union mode already doing the "modules return multiple > objects" behavior? Or is there some subtle distinction here? > > > I don't know exactly what lazy-union does, but for programmatic purposes > it does not appear to implement "modules return multiple objects". It > produces a different CSG tree, but doesn't seem to affect the number of > objects visible to the program. > > module howmany() { > echo($children); > } > > howmany() { > for(i=[1:10]) > translate([i*10,0,0]) cube(); > } > > echoes "1" whether or not lazy unions are enabled. > > Similarly: > > module two() { > cube(); > translate([2,0,0]) cube(); > } > > howmany() two(); > > always echoes "1". > > [...] I seem to recall there being talk about having for() return its objects separately, and hence not needing intersection_for. > > > That would be the "modules return multiple objects" behavior - or, as I > would say it, the "modules return zero or more objects" behavior. > Eliminating intersection_for would be one of the advantages. Similarly, if > you had a spread() module that spaced its children out, you could say: > > spread() { > for(i=[1:10]) cube(); > } > > However, it would lead to a need for more explicit unions: > > module spherecube() { > sphere(10); > cube(15, center=true); > } > > spread() spherecube(); > > would not do what you would expect; you would need > > module spherecube() { > union() { > sphere(10); > cube(15, center=true); > } > } > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Sun, Oct 4, 2020 6:51 PM

Here's the forum post about lazy unions:

http://forum.openscad.org/quot-Lazy-union-quot-is-now-experimental-in-snapshots-td27991.html

I have to admit I don't quite understand the workings of the change because
it seems like a half-way change where sometimes objects are passed
separately and sometimes not.  As you note, if you write your own module a
union gets applied.  But if you use difference() or intersection() applied
to a for() you get the behavior of individual objects without a union.  (So
intersection_for is already unnecessary with this change.)

Try this one with and without lazy union:

difference() {
for(i=[-1,1], j=[-1,1], k=[-1,1])
translate([i,j,k])
sphere(r=.1,$fn=32);
translate([1,1,1])sphere(r=.15,$fn=32);
}

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

Here's the forum post about lazy unions: http://forum.openscad.org/quot-Lazy-union-quot-is-now-experimental-in-snapshots-td27991.html I have to admit I don't quite understand the workings of the change because it seems like a half-way change where sometimes objects are passed separately and sometimes not. As you note, if you write your own module a union gets applied. But if you use difference() or intersection() applied to a for() you get the behavior of individual objects without a union. (So intersection_for is already unnecessary with this change.) Try this one with and without lazy union: difference() { for(i=[-1,1], j=[-1,1], k=[-1,1]) translate([i,j,k]) sphere(r=.1,$fn=32); translate([1,1,1])sphere(r=.15,$fn=32); } -- Sent from: http://forum.openscad.org/
CA
Carsten Arnholm
Sun, Oct 4, 2020 6:59 PM

On 04.10.2020 19:41, adrianv wrote:

Isn't the new lazy union mode already doing the "modules return multiple
objects" behavior?  Or is there some subtle distinction here?  It at least
seems like a step in that direction, and I seem to recall there being talk
about having for() return its objects separately, and hence not needing
intersection_for.

For anybody who hasn't paid attention, I found that if I make a rounded cube
as the hull of 8 spheres it takes 9.5 seconds to preview without lazy union
and 0.2 seconds to preview with lazy union.

hull()
for(i=[-1,1], j=[-1,1], k=[-1,1])
translate([i,j,k])
sphere(r=.1,$fn=32);

There is really no need for a union in this case, so "lazy union" looks
like a fancy name for no implicit union. The difference between 9.5
seconds and 0.2 seconds is an unnecessary union vs. no union. You are
essentially creating an array of spheres and computing the convex hull
from them directly instead of first unioning them and then computing the
hull, much like

https://gist.github.com/arnholm/eda3f740da4f101421a8141b2446a4df

Carsten Arnholm

On 04.10.2020 19:41, adrianv wrote: > Isn't the new lazy union mode already doing the "modules return multiple > objects" behavior? Or is there some subtle distinction here? It at least > seems like a step in that direction, and I seem to recall there being talk > about having for() return its objects separately, and hence not needing > intersection_for. > > For anybody who hasn't paid attention, I found that if I make a rounded cube > as the hull of 8 spheres it takes 9.5 seconds to preview without lazy union > and 0.2 seconds to preview with lazy union. > > hull() > for(i=[-1,1], j=[-1,1], k=[-1,1]) > translate([i,j,k]) > sphere(r=.1,$fn=32); There is really no need for a union in this case, so "lazy union" looks like a fancy name for no implicit union. The difference between 9.5 seconds and 0.2 seconds is an unnecessary union vs. no union. You are essentially creating an array of spheres and computing the convex hull from them directly instead of first unioning them and then computing the hull, much like https://gist.github.com/arnholm/eda3f740da4f101421a8141b2446a4df Carsten Arnholm
JB
Jordan Brown
Sun, Oct 4, 2020 8:32 PM

On 10/4/2020 11:51 AM, adrianv wrote:

I have to admit I don't quite understand the workings of the change because
it seems like a half-way change where sometimes objects are passed
separately and sometimes not.

Ugh.  And a particular module (say, "for") sometimes yields multiple
objects and sometimes does not.  It appears to yield multiple objects
when its parent is "intersection", but a single object when its parent
is a user-defined module.

I like either answer better than an (apparently) inconsistent answer.

On 10/4/2020 11:51 AM, adrianv wrote: > I have to admit I don't quite understand the workings of the change because > it seems like a half-way change where sometimes objects are passed > separately and sometimes not. Ugh.  And a particular module (say, "for") sometimes yields multiple objects and sometimes does not.  It appears to yield multiple objects when its parent is "intersection", but a single object when its parent is a user-defined module. I like either answer better than an (apparently) inconsistent answer.
A
adrianv
Sun, Oct 4, 2020 9:05 PM

Based on the quoted forum post it sounded like this was an initial step with
the intent of eliminating the implicit union everywhere, so an inconsistent
intermediate state with a consistent destination.

JordanBrown wrote

On 10/4/2020 11:51 AM, adrianv wrote:

I have to admit I don't quite understand the workings of the change
because
it seems like a half-way change where sometimes objects are passed
separately and sometimes not.

Ugh.  And a particular module (say, "for") sometimes yields multiple
objects and sometimes does not.  It appears to yield multiple objects
when its parent is "intersection", but a single object when its parent
is a user-defined module.

I like either answer better than an (apparently) inconsistent answer.


OpenSCAD mailing list

Discuss@.openscad

Based on the quoted forum post it sounded like this was an initial step with the intent of eliminating the implicit union everywhere, so an inconsistent intermediate state with a consistent destination. JordanBrown wrote > On 10/4/2020 11:51 AM, adrianv wrote: >> I have to admit I don't quite understand the workings of the change >> because >> it seems like a half-way change where sometimes objects are passed >> separately and sometimes not. > > Ugh.  And a particular module (say, "for") sometimes yields multiple > objects and sometimes does not.  It appears to yield multiple objects > when its parent is "intersection", but a single object when its parent > is a user-defined module. > > I like either answer better than an (apparently) inconsistent answer. > > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
NH
nop head
Mon, Oct 5, 2020 9:09 AM

A place where lazy union breaks my code is with an intersection again. If
you have a for loop as the second argument it changes the result because
each interaction of the for makes a new argument.

    color(gold)
         linear_extrude(size.z)
            intersection() {
                square([size.x, size.y], center = true);

                for(end = [-1, 1])
                    translate([end * size.x / 2, 0])
                        ring(or = r, ir = r / 2);
            }

Easy to fix by adding explicit union() but not easy to spot without
regression tests.

On Sun, 4 Oct 2020 at 22:06, adrianv avm4@cornell.edu wrote:

Based on the quoted forum post it sounded like this was an initial step
with
the intent of eliminating the implicit union everywhere, so an inconsistent
intermediate state with a consistent destination.

JordanBrown wrote

On 10/4/2020 11:51 AM, adrianv wrote:

I have to admit I don't quite understand the workings of the change
because
it seems like a half-way change where sometimes objects are passed
separately and sometimes not.

Ugh.  And a particular module (say, "for") sometimes yields multiple
objects and sometimes does not.  It appears to yield multiple objects
when its parent is "intersection", but a single object when its parent
is a user-defined module.

I like either answer better than an (apparently) inconsistent answer.


OpenSCAD mailing list

Discuss@.openscad

A place where lazy union breaks my code is with an intersection again. If you have a for loop as the second argument it changes the result because each interaction of the for makes a new argument. color(gold) linear_extrude(size.z) intersection() { square([size.x, size.y], center = true); for(end = [-1, 1]) translate([end * size.x / 2, 0]) ring(or = r, ir = r / 2); } Easy to fix by adding explicit union() but not easy to spot without regression tests. On Sun, 4 Oct 2020 at 22:06, adrianv <avm4@cornell.edu> wrote: > Based on the quoted forum post it sounded like this was an initial step > with > the intent of eliminating the implicit union everywhere, so an inconsistent > intermediate state with a consistent destination. > > > JordanBrown wrote > > On 10/4/2020 11:51 AM, adrianv wrote: > >> I have to admit I don't quite understand the workings of the change > >> because > >> it seems like a half-way change where sometimes objects are passed > >> separately and sometimes not. > > > > Ugh. And a particular module (say, "for") sometimes yields multiple > > objects and sometimes does not. It appears to yield multiple objects > > when its parent is "intersection", but a single object when its parent > > is a user-defined module. > > > > I like either answer better than an (apparently) inconsistent answer. > > > > > > _______________________________________________ > > OpenSCAD mailing list > > > Discuss@.openscad > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TP
Torsten Paul
Mon, Oct 5, 2020 12:12 PM

On 05.10.20 11:09, nop head wrote:

 A place where lazy union breaks my code is with an
intersection again. If you have a for loop as the second
argument it changes the result because each interaction
of the for makes a new argument.

I think that relates to the question how to handle
$children. I would assume this needs to be calculated
in a way so the behavior does not change depending on
the number of child objects returned.

ciao,
Torsten.

On 05.10.20 11:09, nop head wrote: >  A place where lazy union breaks my code is with an > intersection again. If you have a for loop as the second > argument it changes the result because each interaction > of the for makes a new argument. I think that relates to the question how to handle $children. I would assume this needs to be calculated in a way so the behavior does not change depending on the number of child objects returned. ciao, Torsten.
NH
nop head
Mon, Oct 5, 2020 1:20 PM

Lazy union also breaks difference when the first argument is a for loop.
Anything after the first iteration gets subtracted, so another case where
explicit union is needed. As far as I can tell only two unions() needed
adding to my library to fix it.

Speed doesn't seem much different, two seconds slower for a 20 minute
build, which is just noise. Some things get faster and some slower.

On Mon, 5 Oct 2020 at 13:13, Torsten Paul Torsten.Paul@gmx.de wrote:

On 05.10.20 11:09, nop head wrote:

A place where lazy union breaks my code is with an
intersection again. If you have a for loop as the second
argument it changes the result because each interaction
of the for makes a new argument.

I think that relates to the question how to handle
$children. I would assume this needs to be calculated
in a way so the behavior does not change depending on
the number of child objects returned.

ciao,
Torsten.


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

Lazy union also breaks difference when the first argument is a for loop. Anything after the first iteration gets subtracted, so another case where explicit union is needed. As far as I can tell only two unions() needed adding to my library to fix it. Speed doesn't seem much different, two seconds slower for a 20 minute build, which is just noise. Some things get faster and some slower. On Mon, 5 Oct 2020 at 13:13, Torsten Paul <Torsten.Paul@gmx.de> wrote: > On 05.10.20 11:09, nop head wrote: > > A place where lazy union breaks my code is with an > > intersection again. If you have a for loop as the second > > argument it changes the result because each interaction > > of the for makes a new argument. > > I think that relates to the question how to handle > $children. I would assume this needs to be calculated > in a way so the behavior does not change depending on > the number of child objects returned. > > ciao, > Torsten. > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TP
Torsten Paul
Mon, Oct 5, 2020 1:53 PM

On 05.10.20 15:20, nop head wrote:

Lazy union also breaks difference when the first argument
is a for loop. Anything after the first iteration gets
subtracted, so another case where explicit union is needed.
As far as I can tell only two unions() needed adding to my
library to fix it.

My preference would be to have it unchanged in behavior, but
maybe with deprecation warnings where needed.

As already mentioned, I think the only way to handle those
cases is to keep the implicit union / child() selection based
on static "slots". So if the first "slot" of the union is
a for(), it will still do the union, or if that "slot" is
accessed via child() then that will return the list of objects
that for() generated.

Speed doesn't seem much different, two seconds slower
for a 20 minute build, which is just noise. Some things
get faster and some slower.

If I remember correctly, it's not yet available in all places
so it might not reach the full potential. At this point it's
probably affecting mostly cases where the top level union is
the big slow operation.

ciao,
Torsten.

On 05.10.20 15:20, nop head wrote: > Lazy union also breaks difference when the first argument > is a for loop. Anything after the first iteration gets > subtracted, so another case where explicit union is needed. > As far as I can tell only two unions() needed adding to my > library to fix it. My preference would be to have it unchanged in behavior, but maybe with deprecation warnings where needed. As already mentioned, I think the only way to handle those cases is to keep the implicit union / child() selection based on static "slots". So if the first "slot" of the union is a for(), it will still do the union, or if that "slot" is accessed via child() then that will return the list of objects that for() generated. > Speed doesn't seem much different, two seconds slower > for a 20 minute build, which is just noise. Some things > get faster and some slower. If I remember correctly, it's not yet available in all places so it might not reach the full potential. At this point it's probably affecting mostly cases where the top level union is the big slow operation. ciao, Torsten.
NH
nop head
Mon, Oct 5, 2020 2:14 PM

My tests are all preview mode, so there is no top level union. Union is
free in OpenCSG anyway. It might speed up STL generation but I don't do
that inside the library.

Also a lot of my code is optimised to avoid unions inside hulls, etc. For
the cube example above I would make a nested module that placed the sphere
at a specified x,y,x and then call it 8 times to avoid a for loop.

On Mon, 5 Oct 2020 at 14:53, Torsten Paul Torsten.Paul@gmx.de wrote:

On 05.10.20 15:20, nop head wrote:

Lazy union also breaks difference when the first argument
is a for loop. Anything after the first iteration gets
subtracted, so another case where explicit union is needed.
As far as I can tell only two unions() needed adding to my
library to fix it.

My preference would be to have it unchanged in behavior, but
maybe with deprecation warnings where needed.

As already mentioned, I think the only way to handle those
cases is to keep the implicit union / child() selection based
on static "slots". So if the first "slot" of the union is
a for(), it will still do the union, or if that "slot" is
accessed via child() then that will return the list of objects
that for() generated.

Speed doesn't seem much different, two seconds slower
for a 20 minute build, which is just noise. Some things
get faster and some slower.

If I remember correctly, it's not yet available in all places
so it might not reach the full potential. At this point it's
probably affecting mostly cases where the top level union is
the big slow operation.

ciao,
Torsten.


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

My tests are all preview mode, so there is no top level union. Union is free in OpenCSG anyway. It might speed up STL generation but I don't do that inside the library. Also a lot of my code is optimised to avoid unions inside hulls, etc. For the cube example above I would make a nested module that placed the sphere at a specified x,y,x and then call it 8 times to avoid a for loop. On Mon, 5 Oct 2020 at 14:53, Torsten Paul <Torsten.Paul@gmx.de> wrote: > On 05.10.20 15:20, nop head wrote: > > Lazy union also breaks difference when the first argument > > is a for loop. Anything after the first iteration gets > > subtracted, so another case where explicit union is needed. > > As far as I can tell only two unions() needed adding to my > > library to fix it. > > My preference would be to have it unchanged in behavior, but > maybe with deprecation warnings where needed. > > As already mentioned, I think the only way to handle those > cases is to keep the implicit union / child() selection based > on static "slots". So if the first "slot" of the union is > a for(), it will still do the union, or if that "slot" is > accessed via child() then that will return the list of objects > that for() generated. > > > Speed doesn't seem much different, two seconds slower > > for a 20 minute build, which is just noise. Some things > > get faster and some slower. > > If I remember correctly, it's not yet available in all places > so it might not reach the full potential. At this point it's > probably affecting mostly cases where the top level union is > the big slow operation. > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >