algorithmically building children

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

algorithmically building children

AKADAP
I am attempting to use the library function "distribute()" on an algorithmically generated set of children. I get the impression
that I do not properly comprehend the concept of children.

Example code here:

include <../Libraries/BOSL-master/constants.scad>
use <../Libraries/BOSL-master/transforms.scad>

Drivers=[
        [3.81,34.55,7.18,13.9],//Largest Philips Jewlers Screwdriver
        [2.98,30.02,6.19,12.81],
        [2.38,25,5.52,11.62],
        [1.97,20.85,4.5,10.49],
        [1.57,18.47,3.85,9.46],
        [1.37,17.35,3.27,8.53] //Smallest Philips Jewlers Screwdriver
        ];

distribute(spacing=10,sizes=[for (Driver=Drivers) Driver[3]]){
/*    DriverHole(Driver=Drivers[0]);
    DriverHole(Driver=Drivers[1]);
    DriverHole(Driver=Drivers[2]);
    DriverHole(Driver=Drivers[3]);
    DriverHole(Driver=Drivers[4]);
    DriverHole(Driver=Drivers[5]);*/
    for(Driver=Drivers) DriverHole(Driver=Driver);
}

module DriverHole(Driver=[1,20,4,6],HeightOfRow=25,HandleHoleDepth=30){
    translate([0,0,-1])cylinder(d=Driver[0],h=HeightOfRow+1);
        //Transition to make it easier to put the screwdriver in the hole
    translate([0,0,HeightOfRow-.1])cylinder(d1=Driver[0],d2=Driver[2],h=(Driver[2]-Driver[0])/2+.2);
    translate([0,0,HeightOfRow+(Driver[2]-Driver[0])/2])cylinder(d=Driver[2],h=HandleHoleDepth+1);
}

The distribute function works when the commented lines are uncommented and the for statement line is commented out, but as is,
only a single one of the six objects appears.

I do not understand how to make the for statement generate the six children.

What is it I am not understanding about children? How do I algorithmically generate children?

Thanks.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

nophead
You can't because for implicitly unions it results, so only ever makes one child.


On Wed, 25 Mar 2020 at 04:27, Douglas Peale <[hidden email]> wrote:
I am attempting to use the library function "distribute()" on an algorithmically generated set of children. I get the impression
that I do not properly comprehend the concept of children.

Example code here:

include <../Libraries/BOSL-master/constants.scad>
use <../Libraries/BOSL-master/transforms.scad>

Drivers=[
        [3.81,34.55,7.18,13.9],//Largest Philips Jewlers Screwdriver
        [2.98,30.02,6.19,12.81],
        [2.38,25,5.52,11.62],
        [1.97,20.85,4.5,10.49],
        [1.57,18.47,3.85,9.46],
        [1.37,17.35,3.27,8.53] //Smallest Philips Jewlers Screwdriver
        ];

distribute(spacing=10,sizes=[for (Driver=Drivers) Driver[3]]){
/*    DriverHole(Driver=Drivers[0]);
    DriverHole(Driver=Drivers[1]);
    DriverHole(Driver=Drivers[2]);
    DriverHole(Driver=Drivers[3]);
    DriverHole(Driver=Drivers[4]);
    DriverHole(Driver=Drivers[5]);*/
    for(Driver=Drivers) DriverHole(Driver=Driver);
}

module DriverHole(Driver=[1,20,4,6],HeightOfRow=25,HandleHoleDepth=30){
    translate([0,0,-1])cylinder(d=Driver[0],h=HeightOfRow+1);
        //Transition to make it easier to put the screwdriver in the hole
    translate([0,0,HeightOfRow-.1])cylinder(d1=Driver[0],d2=Driver[2],h=(Driver[2]-Driver[0])/2+.2);
    translate([0,0,HeightOfRow+(Driver[2]-Driver[0])/2])cylinder(d=Driver[2],h=HandleHoleDepth+1);
}

The distribute function works when the commented lines are uncommented and the for statement line is commented out, but as is,
only a single one of the six objects appears.

I do not understand how to make the for statement generate the six children.

What is it I am not understanding about children? How do I algorithmically generate children?

Thanks.



_______________________________________________
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
tp3
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

tp3
On 25.03.20 08:25, nop head wrote:
> You can't because /*for*/ implicitly unions it results, so
> only ever makes one child.

That is correct if you need to rely on the release version.

If you are ok with using the development snapshot, you can
enable the experimental feature "lazy union".

ciao,
  Torsten.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

JordanBrown
In reply to this post by nophead
On 3/25/2020 12:25 AM, nop head wrote:
You can't because for implicitly unions it results, so only ever makes one child.

More generally, all modules/operators make one child.

A "for" always makes one child.
An "if" always makes one child (even if it's false).
A module always makes one child (even if it doesn't generate any geometry).
module how_many(label, ) {
    echo(label, $children);
}

how_many("if") {
    if (true) cube();
    if (false) sphere();
}

how_many("for") {
    for (i=[0:10:20]) translate([i,i,i]) cube();
}

module empty() {
}

how_many("empty") {
    empty();
}

yields

ECHO: "if", 2
ECHO: "for", 1
ECHO: "empty", 1

I don't know the rules for the new lazy union mode that Paul describes.

(Note:  One might think that an empty module should yield no children, but then you couldn't have a "placeholder" child in an invocation of a module that takes multiple children with different purposes, where children[1] and children[2] are not treated the same.)



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
rew
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

rew
On Wed, Mar 25, 2020 at 03:58:31PM +0000, Jordan Brown wrote:
> but then you couldn't have a "placeholder" child in an invocation of a
> module that takes multiple children with different purposes, where
> children[1] and children[2] are not treated the same.)

Like for example: "difference ()". Here the first and second (and
further) children are treated different.... Now in this specific case
it doesn't make sense for the first argument to be "null", but imagine
a reverse_difference () that unionizes all children2+ and subtracts
the first. Now having an if (we_need_the_hole) cylinder (); as the
first argument and the things where the axle needs to go through as
second third, etc aguments...

        Roger.

--
** [hidden email] ** https://www.BitWizard.nl/ ** +31-15-2049110 **
**    Delftechpark 11 2628 XJ  Delft, The Netherlands.  KVK: 27239233    **
The plan was simple, like my brother-in-law Phil. But unlike
Phil, this plan just might work.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

AKADAP
From the responses I am getting, it looks to me that I can't do what I want
with the release version of OpenSCAD, and must use the unreleased version.
Is this a correct assumption?

Thanks.



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

tp3
On 25.03.20 18:04, AKADAP wrote:
> From the responses I am getting, it looks to me that I can't
> do what I want with the release version of OpenSCAD, and must
> use the unreleased version. Is this a correct assumption?

Correct. It's available in the development snapshots which can be
found at https://www.openscad.org/downloads.html#snapshots

Enable via Preferences->Features "lazy-union"

It's still experimental as there are a couple of things that need
to be clarified, so comments and suggestions are welcome. That
also means the behavior might change.

As the next release is supposed to be mostly bugfixes, it's
probably not going to include that change.

ciao,
  Torsten.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

jon_bondy
Does the compiler have source code pragmas, so that you can say "this
code uses lazy unions"?  This statement would both enable lazy unions
without having to go into the preferences/features, and document the
code so that users are not caught off guard.  If the requested feature
is not available, then a compile-time error could occur

Jon

On 3/25/2020 2:28 PM, Torsten Paul wrote:
> Enable via Preferences->Features "lazy-union"

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

acwest
In reply to this post by JordanBrown
Are you sure about the if (false) case? I'm sure I've used that successfully to avoid creating a child

On Wed, 25 Mar 2020, 11:59 Jordan Brown, <[hidden email]> wrote:
On 3/25/2020 12:25 AM, nop head wrote:
You can't because for implicitly unions it results, so only ever makes one child.

More generally, all modules/operators make one child.

A "for" always makes one child.
An "if" always makes one child (even if it's false).
A module always makes one child (even if it doesn't generate any geometry).
module how_many(label, ) {
    echo(label, $children);
}

how_many("if") {
    if (true) cube();
    if (false) sphere();
}

how_many("for") {
    for (i=[0:10:20]) translate([i,i,i]) cube();
}

module empty() {
}

how_many("empty") {
    empty();
}

yields

ECHO: "if", 2
ECHO: "for", 1
ECHO: "empty", 1

I don't know the rules for the new lazy union mode that Paul describes.

(Note:  One might think that an empty module should yield no children, but then you couldn't have a "placeholder" child in an invocation of a module that takes multiple children with different purposes, where children[1] and children[2] are not treated the same.)


_______________________________________________
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
tp3
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

tp3
In reply to this post by jon_bondy
On 25.03.20 19:37, jon wrote:
> Does the compiler have source code pragmas, so that you can
> say "this code uses lazy unions"?

No, and I don't think it should have one.

ciao,
  Torsten.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

jon_bondy
Torsten:

I explained why I think they are useful; you just said "no". Please
explain yourself

Jon

On 3/25/2020 2:43 PM, Torsten Paul wrote:

> On 25.03.20 19:37, jon wrote:
>> Does the compiler have source code pragmas, so that you can
>> say "this code uses lazy unions"?
> No, and I don't think it should have one.
>
> 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
tp3
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

tp3
On 25.03.20 20:11, jon wrote:
> I explained why I think they are useful; you just
> said "no". Please explain yourself

Please see that issue for the discussion:
https://github.com/openscad/openscad/issues/3142

ciao,
  Torsten.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

AKADAP
In reply to this post by tp3
Thank you for the confirmation.

Since my original path is blocked, and I would prefer not to use a solution
that will be broken in the future, I have found an alternate way forward.
The attached code shows an alternate, working solution to the problem I was
trying to solve:

Drivers=[
        [3.81,34.55,7.18,13.9],//Largest Philips Jewelers Screwdriver
        [2.98,30.02,6.19,12.81],
        [2.38,25,5.52,11.62],
        [1.97,20.85,4.5,10.49],
        [1.57,18.47,3.85,9.46],
        [1.37,17.35,3.27,8.53] //Smallest Philips Jewelers Screwdriver
        ];

Disperse(n=len(Drivers)-1,Drivers=Drivers,Position=5);

module Disperse(n=3,Index=0,Drivers,Position=0){
    translate([Position,0,0])DriverHole(Driver=Drivers[Index]);
    if(n>0){
       
Disperse(n=n-1,Index=Index+1,Drivers=Drivers,Position=Position+10+Drivers[Index][3]);
    }
}

module DriverHole(Driver=[1,20,4,6],HeightOfRow=25,HandleHoleDepth=30){
    translate([0,0,-1])cylinder(d=Driver[0],h=HeightOfRow+1);
        //Transition to make it easier to put the screwdriver in the hole
   
translate([0,0,HeightOfRow-.1])cylinder(d1=Driver[0],d2=Driver[2],h=(Driver[2]-Driver[0])/2+.2);
   
translate([0,0,HeightOfRow+(Driver[2]-Driver[0])/2])cylinder(d=Driver[2],h=HandleHoleDepth+1);
}



--
Sent from: http://forum.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: algorithmically building children

JordanBrown
In reply to this post by acwest
On 3/25/2020 11:39 AM, A. Craig West wrote:
Are you sure about the if (false) case? I'm sure I've used that successfully to avoid creating a child

Well, check out the output that I included, where the "if" case said it had two children (one for the if(true) and one for the if(false)).

Consider also:
union() {
    if (true) sphere();
    if (false) cube();
}

where the CSG tree is (slightly reformatted for readability):

union() {
    group() {
        sphere($fn = 0, $fa = 12, $fs = 2, r = 1);
    }
    group();
}


On Wed, 25 Mar 2020, 11:59 Jordan Brown, <[hidden email]> wrote:
On 3/25/2020 12:25 AM, nop head wrote:
You can't because for implicitly unions it results, so only ever makes one child.

More generally, all modules/operators make one child.

A "for" always makes one child.
An "if" always makes one child (even if it's false).
A module always makes one child (even if it doesn't generate any geometry).
module how_many(label, ) {
    echo(label, $children);
}

how_many("if") {
    if (true) cube();
    if (false) sphere();
}

how_many("for") {
    for (i=[0:10:20]) translate([i,i,i]) cube();
}

module empty() {
}

how_many("empty") {
    empty();
}

yields

ECHO: "if", 2
ECHO: "for", 1
ECHO: "empty", 1

I don't know the rules for the new lazy union mode that Paul describes.

(Note:  One might think that an empty module should yield no children, but then you couldn't have a "placeholder" child in an invocation of a module that takes multiple children with different purposes, where children[1] and children[2] are not treated the same.)


_______________________________________________
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


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: algorithmically building children

JordanBrown
In reply to this post by AKADAP
You can do something kind of similar using $ variables to communicate with the children.

Your top-level module would repeatedly invoke the children, with different values of a $ variable, and the children would behave differently depending on the values.

For instance:
module foreach(list) {
    for ($i=[0:len(list)-1]) {
        $val = list[$i];
        children();
    }
}

module mychild() {
    translate([0,$i*20,0]) text($val);
}

foreach(["alpha","beta","gamma"])
    mychild();
Here's one that's a bit more similar to your example:
module distribute(separation, list) {
    for ($i=[0:len(list)-1]) {
        $val = list[$i];
        translate($i * separation)
            children();
    }
}

module mychild() {
    text($val);
}

distribute([0,20,0], ["alpha","beta","gamma", "delta"])
    mychild();

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