discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Passing children in recursive module

IO
Ian Oliver
Sat, Jun 17, 2017 10:08 PM

I've got some geometry that I'm wanting to slice into 8+ parts on
various planes, and to add fixing holes to, and I'm wanting to make life
easier than loads of nested difference() and intersection() operations.

I'm using a "BinOps" module that takes an argument saying which binary
to use, and then wanted to wrap this in another module that lets me
specify multiple operations to apply to variable numbers of children.

I first coded non-recursive with fixed depth (but null() module to let
me still use it) and then struggled to code recursively as children()
always seem to be unioned.

Is there a better work around?

module sphere1 () sphere (r=5);

module slicer () translate ([-10,-10,-10]) cube ([10, 20, 20]);

module sliceu () translate ([-10,-10,-10]) cube ([20, 20, 10]);

module null();

// Applies operator to children(0) and children(1:last)
// n=nop, d=difference, u=union, i=intersection
module BinOp (Op) {
if (Op == "n") children(0);
else    if (Op == "d") difference () {children(0);
children([1:$children-1]);}
else    if (Op == "u") union () {children(0);
children([1:$children-1]);}
else    if (Op == "i") intersection () {children(0);
children([1:$children-1]);}
}

// Make this recursive!
// Applies children(1) to children(0) first using first operator, and
then works along
module MultiOpOld (OpStr) {
BinOp (OpStr[3]) {
BinOp (OpStr[2]) {
BinOp (OpStr[1]) {
BinOp (OpStr[0]) {
children(0);
children(1);
}
children(2);
}
children(3);
}
children(4);
}

}

// Apply all operations to children(0) with one operation per child
after children(1)
module MultiOp (OpStr, opnum = undef) {
opnum = opnum==undef ? len(OpStr) : opnum;
BinOp (OpStr[opnum-1]) {
if (opnum==1)
children(0);
else
MultiOp (OpStr, opnum=opnum-1)  {
// Would like to pass down all children except last
one, but ...
children(0);
children(1);
if ($children>3) children(2);
if ($children>4) children(3);
if ($children>5) children(4);
}
children(opnum);
}
}

// Change the control string to slice in different ways. Will have 4-5
slice planes eventually.
MultiOp ("ddnn") {
sphere1();
slicer();
sliceu();
null();
null();
}

I've got some geometry that I'm wanting to slice into 8+ parts on various planes, and to add fixing holes to, and I'm wanting to make life easier than loads of nested difference() and intersection() operations. I'm using a "BinOps" module that takes an argument saying which binary to use, and then wanted to wrap this in another module that lets me specify multiple operations to apply to variable numbers of children. I first coded non-recursive with fixed depth (but null() module to let me still use it) and then struggled to code recursively as children() always seem to be unioned. Is there a better work around? module sphere1 () sphere (r=5); module slicer () translate ([-10,-10,-10]) cube ([10, 20, 20]); module sliceu () translate ([-10,-10,-10]) cube ([20, 20, 10]); module null(); // Applies operator to children(0) and children(1:last) // n=nop, d=difference, u=union, i=intersection module BinOp (Op) { if (Op == "n") children(0); else if (Op == "d") difference () {children(0); children([1:$children-1]);} else if (Op == "u") union () {children(0); children([1:$children-1]);} else if (Op == "i") intersection () {children(0); children([1:$children-1]);} } // Make this recursive! // Applies children(1) to children(0) first using first operator, and then works along module MultiOpOld (OpStr) { BinOp (OpStr[3]) { BinOp (OpStr[2]) { BinOp (OpStr[1]) { BinOp (OpStr[0]) { children(0); children(1); } children(2); } children(3); } children(4); } } // Apply all operations to children(0) with one operation per child after children(1) module MultiOp (OpStr, opnum = undef) { opnum = opnum==undef ? len(OpStr) : opnum; BinOp (OpStr[opnum-1]) { if (opnum==1) children(0); else MultiOp (OpStr, opnum=opnum-1) { // Would like to pass down all children except last one, but ... children(0); children(1); if ($children>3) children(2); if ($children>4) children(3); if ($children>5) children(4); } children(opnum); } } // Change the control string to slice in different ways. Will have 4-5 slice planes eventually. MultiOp ("ddnn") { sphere1(); slicer(); sliceu(); null(); null(); }
RP
Ronaldo Persiano
Sat, Jun 17, 2017 11:55 PM

Nice strategy. However I am afraid there is no way to get it recursive
because I guess the only way to pass down a subset of children is
by  explicitly enumerating it as you have done. Iterations either by for or
by the form children(<index list>) returns the children union. For this
reason, the intersection in BinOp may not give you what you intend. You
might use intersection_for().

2017-06-17 19:08 GMT-03:00 Ian Oliver lists@foxhill.co.uk:

I've got some geometry that I'm wanting to slice into 8+ parts on various
planes, and to add fixing holes to, and I'm wanting to make life easier
than loads of nested difference() and intersection() operations.

I'm using a "BinOps" module that takes an argument saying which binary to
use, and then wanted to wrap this in another module that lets me specify
multiple operations to apply to variable numbers of children.

I first coded non-recursive with fixed depth (but null() module to let me
still use it) and then struggled to code recursively as children() always
seem to be unioned.

Is there a better work around?

module sphere1 () sphere (r=5);

module slicer () translate ([-10,-10,-10]) cube ([10, 20, 20]);

module sliceu () translate ([-10,-10,-10]) cube ([20, 20, 10]);

module null();

// Applies operator to children(0) and children(1:last)
// n=nop, d=difference, u=union, i=intersection
module BinOp (Op) {
if (Op == "n") children(0);
else    if (Op == "d") difference () {children(0);
children([1:$children-1]);}
else    if (Op == "u") union () {children(0);
children([1:$children-1]);}
else    if (Op == "i") intersection () {children(0);
children([1:$children-1]);}
}

// Make this recursive!
// Applies children(1) to children(0) first using first operator, and then
works along
module MultiOpOld (OpStr) {
BinOp (OpStr[3]) {
BinOp (OpStr[2]) {
BinOp (OpStr[1]) {
BinOp (OpStr[0]) {
children(0);
children(1);
}
children(2);
}
children(3);
}
children(4);
}

}

// Apply all operations to children(0) with one operation per child after
children(1)
module MultiOp (OpStr, opnum = undef) {
opnum = opnum==undef ? len(OpStr) : opnum;
BinOp (OpStr[opnum-1]) {
if (opnum==1)
children(0);
else
MultiOp (OpStr, opnum=opnum-1)  {
// Would like to pass down all children except last
one, but ...
children(0);
children(1);
if ($children>3) children(2);
if ($children>4) children(3);
if ($children>5) children(4);
}
children(opnum);
}
}

// Change the control string to slice in different ways. Will have 4-5
slice planes eventually.
MultiOp ("ddnn") {
sphere1();
slicer();
sliceu();
null();
null();
}


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

Nice strategy. However I am afraid there is no way to get it recursive because I guess the only way to pass down a subset of children is by explicitly enumerating it as you have done. Iterations either by for or by the form children(<index list>) returns the children union. For this reason, the intersection in BinOp may not give you what you intend. You might use intersection_for(). 2017-06-17 19:08 GMT-03:00 Ian Oliver <lists@foxhill.co.uk>: > I've got some geometry that I'm wanting to slice into 8+ parts on various > planes, and to add fixing holes to, and I'm wanting to make life easier > than loads of nested difference() and intersection() operations. > > I'm using a "BinOps" module that takes an argument saying which binary to > use, and then wanted to wrap this in another module that lets me specify > multiple operations to apply to variable numbers of children. > > I first coded non-recursive with fixed depth (but null() module to let me > still use it) and then struggled to code recursively as children() always > seem to be unioned. > > Is there a better work around? > > module sphere1 () sphere (r=5); > > module slicer () translate ([-10,-10,-10]) cube ([10, 20, 20]); > > module sliceu () translate ([-10,-10,-10]) cube ([20, 20, 10]); > > module null(); > > // Applies operator to children(0) and children(1:last) > // n=nop, d=difference, u=union, i=intersection > module BinOp (Op) { > if (Op == "n") children(0); > else if (Op == "d") difference () {children(0); > children([1:$children-1]);} > else if (Op == "u") union () {children(0); > children([1:$children-1]);} > else if (Op == "i") intersection () {children(0); > children([1:$children-1]);} > } > > // Make this recursive! > // Applies children(1) to children(0) first using first operator, and then > works along > module MultiOpOld (OpStr) { > BinOp (OpStr[3]) { > BinOp (OpStr[2]) { > BinOp (OpStr[1]) { > BinOp (OpStr[0]) { > children(0); > children(1); > } > children(2); > } > children(3); > } > children(4); > } > > } > > // Apply all operations to children(0) with one operation per child after > children(1) > module MultiOp (OpStr, opnum = undef) { > opnum = opnum==undef ? len(OpStr) : opnum; > BinOp (OpStr[opnum-1]) { > if (opnum==1) > children(0); > else > MultiOp (OpStr, opnum=opnum-1) { > // Would like to pass down all children except last > one, but ... > children(0); > children(1); > if ($children>3) children(2); > if ($children>4) children(3); > if ($children>5) children(4); > } > children(opnum); > } > } > > // Change the control string to slice in different ways. Will have 4-5 > slice planes eventually. > MultiOp ("ddnn") { > sphere1(); > slicer(); > sliceu(); > null(); > null(); > } > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
IO
Ian Oliver
Sun, Jun 18, 2017 1:10 AM

On 2017-06-17 16:55, Ronaldo Persiano wrote:

Iterations either by for or by the form children(<index list>) returns
the children union.

Shame as this prevents them being "passed down" as separate children
other than by using specific enumeration. This is OK as I just add as
many "if .. children()" as I need and the extras don't cause issues
other than looking messy.

For this reason, the intersection in BinOp may not give you what you
intend. You might use intersection_for().

I'm not sure what you mean. By this stage I don't mind the implicit
union, and the ability of BinOp to take more than two children isn't
actually used by MultiOp.

I've set my OpStr to "iinn", "idnn", "dinn" and "ddnn" and all seem to
work, and I can't see why using it for the extra "slices" won't work.
I'm not sure whether to use the "union" capability of BinOp as I'll
usually by using geometry than does this already.

On 2017-06-17 16:55, Ronaldo Persiano wrote: > Iterations either by for or by the form children(<index list>) returns > the children union. Shame as this prevents them being "passed down" as separate children other than by using specific enumeration. This is OK as I just add as many "if .. children()" as I need and the extras don't cause issues other than looking messy. > For this reason, the intersection in BinOp may not give you what you > intend. You might use intersection_for(). I'm not sure what you mean. By this stage I don't mind the implicit union, and the ability of BinOp to take more than two children isn't actually used by MultiOp. I've set my OpStr to "iinn", "idnn", "dinn" and "ddnn" and all seem to work, and I can't see why using it for the extra "slices" won't work. I'm not sure whether to use the "union" capability of BinOp as I'll usually by using geometry than does this already.