Pattern to call a module depending on variable value?

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

Pattern to call a module depending on variable value?

Roel Vanhout
Hi,

As I am learning more about OpenSCAD, I found that building new designs by putting each 'part' into a separate module so that I can export separate STL's for each part is a much more convenient workflow than putting everything into one big design and trying to extract parts later on. I do basically this:

build_config = "clip";
echo("Using build config ", build_config);

if (build_config == "all") {
    all();
} else if (build_config == "body") {
    body();
} else if (build_config == "lid") {
    lid();
} else if (build_config == "screw") {
    screw();
} else if (build_config == "clip") {
    clip();
}

I then have a batch file where I basically pass a value for build_config using -D in a loop, so that all parts are exported. The 'all' module positions the parts in relation to each other, so that it renders an overview of how the parts fit together (and I add some details like screws etc that I don't need to 3d print separately). When in 'development mode' (with the file open in a text editor), I can manually adjust the build_config variable to see a specific component.

As I get more parts in my designs, it becomes more annoying to update this if structure, and sync it with the list of part module names in the batch file. So I'm wondering if there is a way to call modules based on a string value, so that I can do the equivalent of 'build_config();' ?

Ideally, I also want to get rid of the list of parts in the batch file, but I'm not sure how I would go about that as it seems there is no way to iterate and export from within a loop in OpenSCAD.

I would think that this would be a common problem, and maybe I'm barking up the wrong tree completely. How do you all deal with this, writing modular designs but still have a convenient way to export the STLs for the parts separately?

cheers,

Roel



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

Re: Pattern to call a module depending on variable value?

alexgibson

Hi Roel,

 

I don’t know whether this is anything close to good practice, but I have several designs I’ve been evolving for years, which express or do not express features contained in modules or separate files.

 

To enable this to happen as a result of logic, in my parameters I name a value such as:

                dual_z_azis_present = 1;  

(value can be 1 or 0)

 

Then, I can make the module for the Z axis components, including all sorts of variant versions of components – and all I need to do is wrap each component, module, etc, in

scale([dual_z_azis_present, dual_z_azis_present, dual_z_azis_present])

 

This effectively ‘disappears’ the geometry.

 

This absolutely may not be the best way to do things, but I like it because I can make the dependency on some Boolean logic easily using the 1 or 0 value.

 

Cheers,

 

Alex Gibson

 

admg consulting

 

edumaker limited

 

·         Project management

·         Operations & Process improvement

·         3D Printing

 

From: Discuss [mailto:[hidden email]] On Behalf Of Roel Vanhout
Sent: 23 February 2021 10:04
To: OpenSCAD general discussion
Subject: [OpenSCAD] Pattern to call a module depending on variable value?

 

Hi,

 

As I am learning more about OpenSCAD, I found that building new designs by putting each 'part' into a separate module so that I can export separate STL's for each part is a much more convenient workflow than putting everything into one big design and trying to extract parts later on. I do basically this:

 

build_config = "clip";
echo("Using build config ", build_config);

if (build_config == "all") {
    all();
} else if (build_config == "body") {
    body();
} else if (build_config == "lid") {
    lid();
} else if (build_config == "screw") {
    screw();
} else if (build_config == "clip") {
    clip();
}

 

I then have a batch file where I basically pass a value for build_config using -D in a loop, so that all parts are exported. The 'all' module positions the parts in relation to each other, so that it renders an overview of how the parts fit together (and I add some details like screws etc that I don't need to 3d print separately). When in 'development mode' (with the file open in a text editor), I can manually adjust the build_config variable to see a specific component.

 

As I get more parts in my designs, it becomes more annoying to update this if structure, and sync it with the list of part module names in the batch file. So I'm wondering if there is a way to call modules based on a string value, so that I can do the equivalent of 'build_config();' ?

 

Ideally, I also want to get rid of the list of parts in the batch file, but I'm not sure how I would go about that as it seems there is no way to iterate and export from within a loop in OpenSCAD.

 

I would think that this would be a common problem, and maybe I'm barking up the wrong tree completely. How do you all deal with this, writing modular designs but still have a convenient way to export the STLs for the parts separately?

 

cheers,

 

Roel

 

 

 

Virus-free. www.avg.com

 


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

Re: Pattern to call a module depending on variable value?

nophead
If you use the command line you can take advantage of the fact that -D passes a statement. E.g.

openscad -D!lid() -o lid.stl parts.scad

The exclamation mark ensures only the specified module is drawn


On Tue, 23 Feb 2021 at 13:03, Alex Gibson <[hidden email]> wrote:

Hi Roel,

 

I don’t know whether this is anything close to good practice, but I have several designs I’ve been evolving for years, which express or do not express features contained in modules or separate files.

 

To enable this to happen as a result of logic, in my parameters I name a value such as:

                dual_z_azis_present = 1;  

(value can be 1 or 0)

 

Then, I can make the module for the Z axis components, including all sorts of variant versions of components – and all I need to do is wrap each component, module, etc, in

scale([dual_z_azis_present, dual_z_azis_present, dual_z_azis_present])

 

This effectively ‘disappears’ the geometry.

 

This absolutely may not be the best way to do things, but I like it because I can make the dependency on some Boolean logic easily using the 1 or 0 value.

 

Cheers,

 

Alex Gibson

 

admg consulting

 

edumaker limited

 

·         Project management

·         Operations & Process improvement

·         3D Printing

 

From: Discuss [mailto:[hidden email]] On Behalf Of Roel Vanhout
Sent: 23 February 2021 10:04
To: OpenSCAD general discussion
Subject: [OpenSCAD] Pattern to call a module depending on variable value?

 

Hi,

 

As I am learning more about OpenSCAD, I found that building new designs by putting each 'part' into a separate module so that I can export separate STL's for each part is a much more convenient workflow than putting everything into one big design and trying to extract parts later on. I do basically this:

 

build_config = "clip";
echo("Using build config ", build_config);

if (build_config == "all") {
    all();
} else if (build_config == "body") {
    body();
} else if (build_config == "lid") {
    lid();
} else if (build_config == "screw") {
    screw();
} else if (build_config == "clip") {
    clip();
}

 

I then have a batch file where I basically pass a value for build_config using -D in a loop, so that all parts are exported. The 'all' module positions the parts in relation to each other, so that it renders an overview of how the parts fit together (and I add some details like screws etc that I don't need to 3d print separately). When in 'development mode' (with the file open in a text editor), I can manually adjust the build_config variable to see a specific component.

 

As I get more parts in my designs, it becomes more annoying to update this if structure, and sync it with the list of part module names in the batch file. So I'm wondering if there is a way to call modules based on a string value, so that I can do the equivalent of 'build_config();' ?

 

Ideally, I also want to get rid of the list of parts in the batch file, but I'm not sure how I would go about that as it seems there is no way to iterate and export from within a loop in OpenSCAD.

 

I would think that this would be a common problem, and maybe I'm barking up the wrong tree completely. How do you all deal with this, writing modular designs but still have a convenient way to export the STLs for the parts separately?

 

cheers,

 

Roel

 

 

 

Virus-free. www.avg.com

 

_______________________________________________
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: Pattern to call a module depending on variable value?

Troberg
In reply to this post by Roel Vanhout
I use these handy little modules:

module hide(dohide=true){
        if(!dohide){
                children();
        }
}

module show(doshow=true){
        if(doshow){
                children();
        }
}

They allow me to do this simply like this (works excellently with customization as well):

show(showlid)
lid();

show(showbox)
box();

hide(hidesamplecontents)
samplecontents();

Neat, simple, practical. Hide & show are also practical for debugging, as they are simple to use in combination with a debugmode-variable which you can define at the top of your script (and through customizer).

Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Pattern to call a module depending on variable value?

tp3
In reply to this post by nophead
On 23.02.21 14:28, nop head wrote:
> If you use the command line you can take advantage
> of the fact that -D passes a statement. E.g.

While noting this is not how it's documented.

-D [ --D ] arg    var=val -pre-define variables

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: Pattern to call a module depending on variable value?

JordanBrown
In reply to this post by Roel Vanhout
I have a couple of answers to this and related problems, but my basic one looks like this:
// Pick out a particular component
$content_selected="all";    // [all, vanity, cabinet, toilet, mesa-701a, mesa-807a]

contents() {
    item("vanity") vanity();
    item("cabinet") bathcabinet();
    item("toilet", distance=120, zrot=120, z=10) toilet();
    item("mesa-701a", distance=120, zrot=120, z=10) mesa_701a();
    item("mesa-807a", distance=120, zrot=120, z=10) mesa_807a();
}

contents() is responsible for laying out an array of items.  If $content_selected is undefined or "all", then it spreads its children out in an array; if $content_selected is anything else then contents() just renders its children at the origin (on the assumption that item(), below, will only render one of them.)

item() does one of three things:

  • if $content_inventory is defined, echoes a line with information about the particular item - in particular, its name.  This output is used by scripts that generate separate STLs and PNGs for each item.  $content_inventory can be set to "all" to dump information about all items, or to "stl" or "png" to select only those items that have said that they should have STLs or PNGs generated.
  • If $content_selected is undefined, or is "all", or matches the name passed, it renders its child.
  • Otherwise, nothing.

Net, with this infrastructure I can:

  • Display everything, spread out in an array.
  • Display a single item, selected either by Customizer or command line options.
  • Echo information about the items available in the file.

and with the supporting shell scripts:

  • Generate STLs for all items marked for STLs.  (Default is yes.)
  • Generate PNGs for all items marked for PNGs.  (Default is yes.)  Optionally control camera position.

Why the selectivity for STLs and PNGs?  I don't generate PNGs for individual parts of a multi-print assembly.  I don't generate STLs where I want to present a picture of several items together, that wouldn't be printed together.

Here's the implementation:

function default(val, def) = is_undef(val) ? def : val;

module contents(d=100) {
    nx = ceil(sqrt($children));
    ny = ceil($children/nx);
    for (xi=[0:nx-1], yi=[0:ny-1]) {
        i = xi + yi*nx;
        if (i < $children) {
            if (is_undef($content_selected)
                || $content_selected == "all") {
                translate([xi*d, yi*d, 0]) children(i);
            } else {
                children(i);
            }
        }
    }
}

module item(name, png=true, stl=true, distance, xrot, zrot, z) {
    if (is_undef($content_inventory)) {
        if (is_undef($content_selected)
            || $content_selected == "all"
            || $content_selected == name) {
                children();
        }
    } else {
        _distance = default(distance, 150);
        _zrot = default(zrot, 30);
        _xrot = default(xrot, 60);
        _z = default(z, 15);
        camera = is_undef(distance) && is_undef(zrot) && is_undef(z) && is_undef(xrot)
            ? "--viewall"
            : str("--camera 0,0,", _z, ",", _xrot, ",0,", _zrot, ",", _distance);
        if ($content_inventory == "all")
            echo("PART", name);
        else if ($content_inventory == "png" && png)
            echo("PART", name, camera);
        else if ($content_inventory == "stl" && stl)
            echo("PART", name);
    }
}


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

Re: Pattern to call a module depending on variable value?

Roel Vanhout
This is most excellent, thanks, just what I was looking for.

regards

On Tue, Feb 23, 2021 at 4:59 PM Jordan Brown <[hidden email]> wrote:
I have a couple of answers to this and related problems, but my basic one looks like this:
// Pick out a particular component
$content_selected="all";    // [all, vanity, cabinet, toilet, mesa-701a, mesa-807a]

contents() {
    item("vanity") vanity();
    item("cabinet") bathcabinet();
    item("toilet", distance=120, zrot=120, z=10) toilet();
    item("mesa-701a", distance=120, zrot=120, z=10) mesa_701a();
    item("mesa-807a", distance=120, zrot=120, z=10) mesa_807a();
}

contents() is responsible for laying out an array of items.  If $content_selected is undefined or "all", then it spreads its children out in an array; if $content_selected is anything else then contents() just renders its children at the origin (on the assumption that item(), below, will only render one of them.)

item() does one of three things:

  • if $content_inventory is defined, echoes a line with information about the particular item - in particular, its name.  This output is used by scripts that generate separate STLs and PNGs for each item.  $content_inventory can be set to "all" to dump information about all items, or to "stl" or "png" to select only those items that have said that they should have STLs or PNGs generated.
  • If $content_selected is undefined, or is "all", or matches the name passed, it renders its child.
  • Otherwise, nothing.

Net, with this infrastructure I can:

  • Display everything, spread out in an array.
  • Display a single item, selected either by Customizer or command line options.
  • Echo information about the items available in the file.

and with the supporting shell scripts:

  • Generate STLs for all items marked for STLs.  (Default is yes.)
  • Generate PNGs for all items marked for PNGs.  (Default is yes.)  Optionally control camera position.

Why the selectivity for STLs and PNGs?  I don't generate PNGs for individual parts of a multi-print assembly.  I don't generate STLs where I want to present a picture of several items together, that wouldn't be printed together.

Here's the implementation:

function default(val, def) = is_undef(val) ? def : val;

module contents(d=100) {
    nx = ceil(sqrt($children));
    ny = ceil($children/nx);
    for (xi=[0:nx-1], yi=[0:ny-1]) {
        i = xi + yi*nx;
        if (i < $children) {
            if (is_undef($content_selected)
                || $content_selected == "all") {
                translate([xi*d, yi*d, 0]) children(i);
            } else {
                children(i);
            }
        }
    }
}

module item(name, png=true, stl=true, distance, xrot, zrot, z) {
    if (is_undef($content_inventory)) {
        if (is_undef($content_selected)
            || $content_selected == "all"
            || $content_selected == name) {
                children();
        }
    } else {
        _distance = default(distance, 150);
        _zrot = default(zrot, 30);
        _xrot = default(xrot, 60);
        _z = default(z, 15);
        camera = is_undef(distance) && is_undef(zrot) && is_undef(z) && is_undef(xrot)
            ? "--viewall"
            : str("--camera 0,0,", _z, ",", _xrot, ",0,", _zrot, ",", _distance);
        if ($content_inventory == "all")
            echo("PART", name);
        else if ($content_inventory == "png" && png)
            echo("PART", name, camera);
        else if ($content_inventory == "stl" && stl)
            echo("PART", name);
    }
}


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