Passing children in recursive module

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Passing children in recursive module

Gadgetmind
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Passing children in recursive module

Ronaldo
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 <[hidden email]>:
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
[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
Reply | Threaded
Open this post in threaded view
|

Re: Passing children in recursive module

Gadgetmind
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.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org