Intersection with only one argument returns that argument. Previously a second argument guarded by a false if was ignored but with the latest snapshot it seems to be counted as and empty argument giving an empty result.
intersection() { cube(); if(false) sphere(); } I.e. this gives a cube with the last release but the latest snapshot gives nothing. Again this has broken my library as I made use of it. For example this code: module shape() intersection() { hull() { circle(boss_r); translate([boss_r + extension  eps, 0]) square([eps, 2 * boss_r], center = true); } if(corner_r) translate([boss_r + extension  corner_r, 0]) rotate(45) quadrant(w = 100, r = corner_r  eps, center = true); } Now has to be written like this: module shape() { module _shape() hull() { circle(boss_r); translate([boss_r + extension  eps, 0]) square([eps, 2 * boss_r], center = true); } if(corner_r) intersection() { _shape(); translate([boss_r + extension  corner_r, 0]) rotate(45) quadrant(w = 100, r = corner_r  eps, center = true); } else _shape(); } Again is this an intentional change? Should a false if be treated as nothing at all or an empty object? I do this a lot with difference but that still works because no second argument is the same as an empty second argument with difference. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
On 02.10.20 12:37, nop head wrote:
> Intersection with only one argument returns that argument. > Again is this an intentional change? Should a false if be > treated as nothing at all or an empty object? So that's probably due to the fix for https://github.com/openscad/openscad/issues/3312 I'm not sure there's a way to fix the bug and also keep the behavior with if(false). ciao, Torsten. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
 Torsten

I think cube(0) and a nonoverlapping intersection or any other csg operation that results in an empty object is different from a false if, which is no object at all. On Fri, 2 Oct 2020 at 14:08, Torsten Paul <[hidden email]> wrote: On 02.10.20 12:37, nop head wrote: _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
On 02.10.20 15:17, nop head wrote:
> I think cube(0) and a nonoverlapping intersection or any > other csg operation that results in an empty object is > different from a false if, which is no object at all. Right, it sounds sensible that if(false) would remove the object completely. I guess we have to see if that would affect anything where the if is used as first part of a difference(). ciao, Torsten. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
 Torsten

In reply to this post by nophead
You could supply cube(0) if you want an empty object and wrap it in module called empty() for readability. I notice now there is an empty() node in the csg products tree. echo() doesn't seem to add an empty group now, so if (false) could do the same. if(false) has always added an empty group() before but that now seems to get changed into an empty() node, which has changed the behaviour of intersection. I don't know how often that will break existing code and the workaround is messy. On Fri, 2 Oct 2020 at 15:55, Jordan Brown <[hidden email]> wrote:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by tp3
Is intersection not a logical AND operation? So what should you expect
if you say 1 AND 0 ? On 10/2/20 6:07 AM, Torsten Paul wrote: > On 02.10.20 12:37, nop head wrote: >> Intersection with only one argument returns that argument. >> Again is this an intentional change? Should a false if be >> treated as nothing at all or an empty object? > So that's probably due to the fix for > https://github.com/openscad/openscad/issues/3312 > > I'm not sure there's a way to fix the bug and also keep the > behavior with if(false). > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > [hidden email] > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
If the second operand is empty geometry I expect an empty result. If the second object is missing I expect the first object, as it has always done, just as difference() with one child. Intersection still does that. What has changed is if(false) now produces an empty() node equivalent to empty geometry, whereas before it returned an empty group() node, which must have been ignored by intersection(). On Fri, 2 Oct 2020 at 16:33, William W Martin <[hidden email]> wrote: Is intersection not a logical AND operation? So what should you expect _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by William W Martin
On 02.10.20 17:33, William W Martin wrote:
> Is intersection not a logical AND operation? So what > should you expect if you say 1 AND 0 ? That's not the point, the question is if this: intersection() { cube(); if (false) sphere(); } is equal to intersection() { cube(); } => result expectation is a cube or intersection() { cube(); *emptygeometry* } => result expectation is empty geometry ciao, Torsten. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
 Torsten

On 10/2/20 8:47 AM, Torsten Paul wrote: > On 02.10.20 17:33, William W Martin wrote: >> Is intersection not a logical AND operation? So what >> should you expect if you say 1 AND 0 ? > That's not the point, the question is if this: > > intersection() { > cube(); > if (false) sphere(); > } > > is equal to > > intersection() { > cube(); > } > > => result expectation is a cube > > or > > intersection() { > cube(); > *emptygeometry* > } > > => result expectation is empty geometry > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > [hidden email] > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > in spite of how many are used to it working that way. Something AND nothing, no matter how you name "nothing", should always be nothing. Try doing a VEN diagram... regards, Bill _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by nophead
On 20201002 17:45, nop head wrote:
> What has changed is if(false) now produces an empty() node equivalent > to empty geometry, whereas before it returned an empty group() node, > which must have been ignored by intersection(). what is the significance between a "group()" node that is empty and an "empty()" node that is empty? One may also ask what is the significance between a "group()" that contains something and a "union()" that contains something? Carsten Arholm _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by William W Martin
Yes an intersection between two operands works like that but what about an intersection with one operand? There is no such thing in maths but the OpenSCAD has had the convention of being a NOP in that case and so is union and difference. On Fri, 2 Oct 2020 at 17:11, William W Martin <[hidden email]> wrote:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
On 20201002 18:13, nop head wrote:
> Yes an intersection between two operands works like that but what > about an intersection with one operand? That's a syntax error and should fail. Carsten Arnholm _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by cacb
The problem is OpenSCAD previously had no distinction between an empty geometry node and a missing operand. So in some cases it ignored an empty geometry first operand and used the second operand as the first. Now that has been fixed it has changed the behaviour of if(false) in an intersection. I can live with it because it only changes two modules in my library and the change is backwards compatible. Will it break more things in the wild though? Does it make logical sense that if(false) creates empty geometry rather than nothing at all. It would be a syntax error if intersection was a binary operator but when it is just a builtin module with children() the syntax is correct as in general you can pass any number of children() to a module. On Fri, 2 Oct 2020 at 17:13, <[hidden email]> wrote: On 20201002 17:45, nop head wrote: _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by cacb
On 10/2/2020 9:22 AM,
[hidden email] wrote:
On 20201002 18:13, nop head wrote: No. Operators like intersection() should take all of their arguments and process them, and should handle the degenerate cases of one and zero arguments if they make any sense at all. That's doubly true if things are changed so that a failing "if" generates nothing, instead of generating an emptygeometry argument. You might say that difference() { cube(); } is an error, but what about difference() { cube(); if (optionA) thingA(); if (optionB) thinkB(); } ? I have exactly that construct in a project I recently did, where
I have a module that models a piece of lumber and optionally
subtracts off bevels. I could have done the same thing with
intersection instead of difference. The use case is less obvious if failing "if" yields an empty object (as it does today), but even then one might imagine cases that involve programs that generate OpenSCAD source.
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by nophead
Well, there may not be an intersection explicitly with one operand in math,
but there is certainly an intersection with n operands where n may happen to be one. This is arguably the exact semantics of the intersection module in OpenSCAD. <http://forum.openscad.org/file/t2477/int.png> It would be an odd choice to do as as suggested elsewhere and make it an error to pass one argument to intersection(). It seems to me that if it's possible to make "if (false) {....}" return nothing that this makes more sense than having it return empty geometry, both for compatibility reasons and also because it's more useful. I also find it more intuitively consistent with the behavior in lists where [a,b,if(false) c] produces [a,b] and not [a,b,<some null representation>]. nophead wrote > Yes an intersection between two operands works like that but what about an > intersection with one operand? There is no such thing in maths but the > OpenSCAD has had the convention of being a NOP in that case and so is > union > and difference.  Sent from: http://forum.openscad.org/ _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by nophead
First, Torsten: was the change to
"if", that it would generate an empty object instead of no object,
or vice versa, or was it a change to what intersection did with an
empty object?
On 10/2/2020 9:24 AM, nop head wrote:
Not true, in the general case. An empty geometry node is a child and has an index. Some operators might treat an emptygeometrynode child specially, but that's that particular operator. difference() also seems to ignore empty groups; if you have a failing "if" as the first argument then that first argument is ignored. Not that I think that's a useful semantic. yields a sphere.difference() { if (false) cube(); sphere(); } Offhand, for the other builtin modules you can't tell whether it processes or ignores an empty group, since the effect is the same. But a general module will count an empty child as a child.
Also the interaction between intersection() and "for" that yields no objects, or more complex empty constructs: yields a cube in 2019.05, and nothing in 2020.10.02.intersection() { cube(); for(i=[1,2,3]) if (false) sphere(); }
My impression  from outside the black box  is that every module invocation, including builtins like "if", "for", and "echo", yields exactly one geometry object. That's a simple rule, although it can yield some unobvious results. There could be a different rule, so that "if" might yield either one or zero objects, but with that rule then I would also expect that "for" would yield any number (zero or more) objects. if (something) { cube(); sphere(); } currently yields one object, but if a module invocation doesn't
always yield exactly one object, I'd say it should yield *two*
objects. Similarly, a module that adds two objects should yield two
objects. The only time that objects would be combined is when
they are processed by a module (like union) that combines them. (This seems related to the "lazy union" question, but I got the impression that that only affected when the actual rendering happened, not how many children there are.) Here's a related tidbit. In both 2019.05 and 2020.10.02, this yields a cube: intersection() { cube(); echo("hello"); } but in 2019.05 the CSG tree has an empty group() for the echo(), and in 2020.10.02 it does not. That kind of demonstrates the danger in trying to be clever. module myecho(s) { echo(s); } intersection() { cube(); myecho("hello"); } is superficially similar, but in 2019.05 yields a cube (because
echo yields an empty object, and myecho yields an empty object,
and intersection ignores the empty object), and in 2020.10.02
yields nothing (because echo yields nothing, and myecho yields an
empty object, and the intersection of an empty object with
anything is the empty object.). It seems surprising that wrapping
the echo() in a module changes the behavior. Anyhow, again, it seems like there are two possible consistent rules:
Both are consistent rules. The "zero or more" rule is arguably more useful, because it eliminates the need for "intersection_for", and because it would allow for generating multiple children with a for(), but it's not compatible with existing practice. Net, I'd probably stick with the "exactly one" rule.
My next question is: What should intersection() (and perhaps others) do with children that are empty geometry? I'd say that empty geometry, like the empty set, is a real thing and should interact "naturally" with the various operators.intersection() { cube(); intersection() { translate([10,10,10]) cube(); translate([10,10,10]) cube(); } } Note that the second intersection yields nothing, because the cubes do not overlap. This yields a cube in 2019.05 and nothing in 2020.10.02. I'd say that 2019.05 is clearly wrong and 2020.10.02 is clearly right. My final question is: What should cube(0) yield? In all versions, the answer is and in my opinion should be "a zerosized cube"... which is still another kind of "nothing". Presumably will yield an empty object indistinguishable fromunion() cube(0); union(); _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
On 10/2/2020 2:15 PM, Jordan Brown
wrote:
Sorry, ignore that. While writing that message I did some experiments and went back to correct the message, but I failed to get this bit right at the top of the message. The answer is that it's a change to what intersection() does with an empty object. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by nophead
On Fri, Oct 02, 2020 at 05:13:26PM +0100, nop head wrote:
> Yes an intersection between two operands works like that but what about an > intersection with one operand? There is no such thing in maths but the > OpenSCAD has had the convention of being a NOP in that case and so is union > and difference. I disagree with "there is no such thing... " Lots of things are extensible. x * y * z = x * y * z * 1 this means that x = x * 1 So multiplying a list of numbers gives just the first number if the list has just one member. Adding has the same mathematical property with the number being 0 this time. Adding a list of numbers will give just the one number when the list has length one. It is precisely the same for the boolean AND and OR operations. And it remains the same for the CSG AND and OR operations (intersection resp union) The odd one out is difference: Not all arguments to a function like difference (numbersmath: Subtraction, division etc) are symmetric. It is PLUS the first object, MINUS all the rest. But again there is an item you can add to the listofalltherest that has no effect. This time the empty object. So again: for consistency difference ([something]) = difference ([something], <empty>) And this holds when [something] is A, B or when [something] is only A. So again for consistency, difference (objectA) should equal objectA. It is not some arbitrary choice, it makes the system "work". All this doesn't help with the orignal question: does: "if (false) objectB" evaluate to an object of nothing (a noop for union, hull , so noboby cares there), or nothing at all (no object). I think there is no good mathematical background to argue either way. But looking at the target use I can imagine people making a cube with an optional hole with: difference () { cube (20, center=true); if (needhole) cylinder (d=7, h=22, center=true); } Here nobody cares if the if evaluates to an empty object or no object at all, because the empty object is the NULL (does nothing) argument to the "difference" fucntion (in the second or any further position). Similarly, an object might be optionally restricted by a second object: intersection () { cube (20, center=true); if (needs_to_fit_in_hole) cylinder (r=10, h=22, center=true); } so evaluating to "<empty object>" now gives something entirely different because it is no longer the NULL argument to the operation being done. A workaround would be: bigenough=50; intersection () { cube (20, center=true); if (needs_to_fit_in_hole) cylinder (r=11, h=22, center=true); else cube (bigenough,center=true); } Imho, this clutters the code and the "evaluates to nothing" situation is preferred: It allows conditional objects in situations where the empty object is not the NULL operation. Roger. > > On Fri, 2 Oct 2020 at 17:11, William W Martin <[hidden email]> wrote: > > > > > On 10/2/20 8:47 AM, Torsten Paul wrote: > > > On 02.10.20 17:33, William W Martin wrote: > > >> Is intersection not a logical AND operation? So what > > >> should you expect if you say 1 AND 0 ? > > > That's not the point, the question is if this: > > > > > > intersection() { > > > cube(); > > > if (false) sphere(); > > > } > > > > > > is equal to > > > > > > intersection() { > > > cube(); > > > } > > > > > > => result expectation is a cube > > > > > > or > > > > > > intersection() { > > > cube(); > > > *emptygeometry* > > > } > > > > > > => result expectation is empty geometry > > > > > > ciao, > > > Torsten. > > > > > > _______________________________________________ > > > OpenSCAD mailing list > > > [hidden email] > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > All I am pointing out is that the "old" result has been wrong all along, > > in spite of how many are used to it working that way. Something AND > > nothing, no matter how you name "nothing", should always be nothing. Try > > doing a VEN diagram... > > > > regards, > > > > Bill > > > > > > _______________________________________________ > > OpenSCAD mailing list > > [hidden email] > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > [hidden email] > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org  ** [hidden email] ** https://www.BitWizard.nl/ ** +31152049110 ** ** Delftechpark 11 2628 XJ Delft, The Netherlands. KVK: 27239233 ** f equals m times a. When your f is steady, and your m is going down your a is going up.  Chris Hadfield about flying up the space shuttle. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
On 10/4/2020 1:35 AM, Rogier Wolff
wrote:
intersection () { cube (20, center=true); if (needs_to_fit_in_hole) cylinder (r=10, h=22, center=true); } I'd do this as something like: module intersection_if(flags) { assert(len(flags) == $children); intersection_for(i = [ for (j=[0:$children1]) if (flags[j]) j]) { children(i); } } intersection_if([true,true,true]) { cube(15,center=true); sphere(10); cylinder(h=15,d=17,center=true); } so the argument is a vector of flags saying whether or not to include the particular child in the intersection.  I kind of think that the "modules return zero or more objects" model would be better overall, but it's not what we have now and would be a significant compatibility issue. I suspect that it would need to be a mode.
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
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); This advantage is so huge I can't imagine wanting to turn it off. If it somehow broke my code I'd fix the code. (Consider the case where you have 50 cubes.) JordanBrown wrote > On 10/4/2020 1:35 AM, Rogier Wolff wrote: >> intersection () { >> cube (20, center=true); >> if (needs_to_fit_in_hole) cylinder (r=10, h=22, center=true); >> } > > I'd do this as something like: > > module intersection_if(flags) { > assert(len(flags) == $children); > intersection_for(i = [ for (j=[0:$children1]) if (flags[j]) j]) { > children(i); > } > } > > intersection_if([true,true,true]) { > cube(15,center=true); > sphere(10); > cylinder(h=15,d=17,center=true); > } > > so the argument is a vector of flags saying whether or not to include > the particular child in the intersection. > >  > > I kind of think that the "modules return zero or more objects" model > would be better overall, but it's not what we have now and would be a > significant compatibility issue. I suspect that it would need to be a > mode. > > > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org  Sent from: http://forum.openscad.org/ _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
Free forum by Nabble  Edit this page 