discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

enabling/disabling code

J
jon
Sun, Sep 6, 2020 7:11 PM

I sometimes run an OpenSCAD program in more than one mode, to create
more than one variant of an object.

Sometimes I can do something like this

// variant 1

rotate(...)

    translate(...)

        cube(...);

// variant 2

*rotate(...)

    translate(...)

        cube(...);

and use a leading "*" to control which code section I want to be
active.  This is annoying, but tolerable, if the number or such code
sections is small.

But sometimes it looks like this:

rotate(...)

//    translate(...)        // variant 1

    translate(...)        // variant 2

        cube(...);

and I end up commenting out a single line.  This approach is much more
error prone and annoying

Am I missing a language feature that would help in the 2nd case? In the
1st case I know I can use if() statements, but sometimes that makes the
code more obscure.

Thanks!

Jon

I sometimes run an OpenSCAD program in more than one mode, to create more than one variant of an object. Sometimes I can do something like this // variant 1 rotate(...)     translate(...)         cube(...); // variant 2 *rotate(...)     translate(...)         cube(...); and use a leading "*" to control which code section I want to be active.  This is annoying, but tolerable, if the number or such code sections is small. But sometimes it looks like this: rotate(...) //    translate(...)        // variant 1     translate(...)        // variant 2         cube(...); and I end up commenting out a single line.  This approach is much more error prone and annoying Am I missing a language feature that would help in the 2nd case? In the 1st case I know I can use if() statements, but sometimes that makes the code more obscure. Thanks! Jon
NH
nop head
Sun, Sep 6, 2020 8:28 PM

rotate(...)
translate(condition ? [ ... ] : [ ... ])
cube();

On Sun, 6 Sep 2020 at 20:11, jon jon@jonbondy.com wrote:

I sometimes run an OpenSCAD program in more than one mode, to create
more than one variant of an object.

Sometimes I can do something like this

// variant 1

rotate(...)

  translate(...)

      cube(...);

// variant 2

*rotate(...)

  translate(...)

      cube(...);

and use a leading "*" to control which code section I want to be
active.  This is annoying, but tolerable, if the number or such code
sections is small.

But sometimes it looks like this:

rotate(...)

//    translate(...)        // variant 1

  translate(...)        // variant 2

      cube(...);

and I end up commenting out a single line.  This approach is much more
error prone and annoying

Am I missing a language feature that would help in the 2nd case? In the
1st case I know I can use if() statements, but sometimes that makes the
code more obscure.

Thanks!

Jon


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

rotate(...) translate(condition ? [ ... ] : [ ... ]) cube(); On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com> wrote: > I sometimes run an OpenSCAD program in more than one mode, to create > more than one variant of an object. > > Sometimes I can do something like this > > // variant 1 > > rotate(...) > > translate(...) > > cube(...); > > // variant 2 > > *rotate(...) > > translate(...) > > cube(...); > > and use a leading "*" to control which code section I want to be > active. This is annoying, but tolerable, if the number or such code > sections is small. > > > But sometimes it looks like this: > > rotate(...) > > // translate(...) // variant 1 > > translate(...) // variant 2 > > cube(...); > > and I end up commenting out a single line. This approach is much more > error prone and annoying > > > Am I missing a language feature that would help in the 2nd case? In the > 1st case I know I can use if() statements, but sometimes that makes the > code more obscure. > > Thanks! > > Jon > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
J
jon
Sun, Sep 6, 2020 10:07 PM

Thanks!  That is a big help if you have 2 versions!

On 9/6/2020 4:28 PM, nop head wrote:

rotate(...)
      translate(condition ? [ ... ] : [ ... ])
           cube();

On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com
mailto:jon@jonbondy.com> wrote:

 I sometimes run an OpenSCAD program in more than one mode, to create
 more than one variant of an object.

 Sometimes I can do something like this

 // variant 1

 rotate(...)

      translate(...)

          cube(...);

 // variant 2

 *rotate(...)

      translate(...)

          cube(...);

 and use a leading "*" to control which code section I want to be
 active.  This is annoying, but tolerable, if the number or such code
 sections is small.


 But sometimes it looks like this:

 rotate(...)

 //    translate(...)        // variant 1

      translate(...)        // variant 2

          cube(...);

 and I end up commenting out a single line.  This approach is much
 more
 error prone and annoying


 Am I missing a language feature that would help in the 2nd case?
 In the
 1st case I know I can use if() statements, but sometimes that
 makes the
 code more obscure.

 Thanks!

 Jon


 _______________________________________________
 OpenSCAD mailing list
 Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org>
 http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

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

Thanks!  That is a big help if you have 2 versions! On 9/6/2020 4:28 PM, nop head wrote: > rotate(...) >       translate(condition ? [ ... ] : [ ... ]) >            cube(); > > On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com > <mailto:jon@jonbondy.com>> wrote: > > I sometimes run an OpenSCAD program in more than one mode, to create > more than one variant of an object. > > Sometimes I can do something like this > > // variant 1 > > rotate(...) > >      translate(...) > >          cube(...); > > // variant 2 > > *rotate(...) > >      translate(...) > >          cube(...); > > and use a leading "*" to control which code section I want to be > active.  This is annoying, but tolerable, if the number or such code > sections is small. > > > But sometimes it looks like this: > > rotate(...) > > //    translate(...)        // variant 1 > >      translate(...)        // variant 2 > >          cube(...); > > and I end up commenting out a single line.  This approach is much > more > error prone and annoying > > > Am I missing a language feature that would help in the 2nd case? > In the > 1st case I know I can use if() statements, but sometimes that > makes the > code more obscure. > > Thanks! > > Jon > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
AC
A. Craig West
Sun, Sep 6, 2020 10:45 PM

You can extend it to as many conditions as you want, to:
rotate(...)
translate(
condition ?
[ ... ]
: condition2 ?
[ ... ]
:
[...]
)
cube();

On Sun, 6 Sep 2020, 18:38 jon, jon@jonbondy.com wrote:

Thanks!  That is a big help if you have 2 versions!
On 9/6/2020 4:28 PM, nop head wrote:

rotate(...)
translate(condition ? [ ... ] : [ ... ])
cube();

On Sun, 6 Sep 2020 at 20:11, jon jon@jonbondy.com wrote:

I sometimes run an OpenSCAD program in more than one mode, to create
more than one variant of an object.

Sometimes I can do something like this

// variant 1

rotate(...)

  translate(...)

      cube(...);

// variant 2

*rotate(...)

  translate(...)

      cube(...);

and use a leading "*" to control which code section I want to be
active.  This is annoying, but tolerable, if the number or such code
sections is small.

But sometimes it looks like this:

rotate(...)

//    translate(...)        // variant 1

  translate(...)        // variant 2

      cube(...);

and I end up commenting out a single line.  This approach is much more
error prone and annoying

Am I missing a language feature that would help in the 2nd case? In the
1st case I know I can use if() statements, but sometimes that makes the
code more obscure.

Thanks!

Jon


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


OpenSCAD mailing listDiscuss@lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


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

You can extend it to as many conditions as you want, to: rotate(...) translate( condition ? [ ... ] : condition2 ? [ ... ] : [...] ) cube(); On Sun, 6 Sep 2020, 18:38 jon, <jon@jonbondy.com> wrote: > Thanks! That is a big help if you have 2 versions! > On 9/6/2020 4:28 PM, nop head wrote: > > rotate(...) > translate(condition ? [ ... ] : [ ... ]) > cube(); > > On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com> wrote: > >> I sometimes run an OpenSCAD program in more than one mode, to create >> more than one variant of an object. >> >> Sometimes I can do something like this >> >> // variant 1 >> >> rotate(...) >> >> translate(...) >> >> cube(...); >> >> // variant 2 >> >> *rotate(...) >> >> translate(...) >> >> cube(...); >> >> and use a leading "*" to control which code section I want to be >> active. This is annoying, but tolerable, if the number or such code >> sections is small. >> >> >> But sometimes it looks like this: >> >> rotate(...) >> >> // translate(...) // variant 1 >> >> translate(...) // variant 2 >> >> cube(...); >> >> and I end up commenting out a single line. This approach is much more >> error prone and annoying >> >> >> Am I missing a language feature that would help in the 2nd case? In the >> 1st case I know I can use if() statements, but sometimes that makes the >> code more obscure. >> >> Thanks! >> >> Jon >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > > _______________________________________________ > OpenSCAD mailing listDiscuss@lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
AG
Alex Gibson
Sun, Sep 6, 2020 10:58 PM

I have multiple designs like this where I need to enable/disable sometimes complex sets of features.

My current method is to set a variable to 1 (true) or 2 (false) and scale the feature by this number:

is_version_1 = 1;

            scale([is_version_1, is_version_1, is_version_1])

                            {

                            …

                            }

This is very easy to do and can be done inline in lots of code just by multiplying the feature – this is very useful where dimensions vary between versions:

is_version_1 = 1;

is_version_2 =0;

is_version_2 = 0;

            translate([is_version_1*50+ is_version_2*60+ is_version_3*70, 0,0])

                            {

                            …

                            }

                            

I’m not sure I understand nop head’s ‘condition’ – will look this up, it might be the correct way to do what I’m hacking here – but it works well.

Alex Gibson

admg consulting

edumaker limited

·        Project management

·        Operations & Process improvement

·        3D Printing

From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of nop head
Sent: 06 September 2020 21:28
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] enabling/disabling code

rotate(...)

  translate(condition ? [ ... ] : [ ... ]) 

       cube();

On Sun, 6 Sep 2020 at 20:11, jon jon@jonbondy.com wrote:

I sometimes run an OpenSCAD program in more than one mode, to create
more than one variant of an object.

Sometimes I can do something like this

// variant 1

rotate(...)

 translate(...)

     cube(...);

// variant 2

*rotate(...)

 translate(...)

     cube(...);

and use a leading "*" to control which code section I want to be
active.  This is annoying, but tolerable, if the number or such code
sections is small.

But sometimes it looks like this:

rotate(...)

//    translate(...)        // variant 1

 translate(...)        // variant 2

     cube(...);

and I end up commenting out a single line.  This approach is much more
error prone and annoying

Am I missing a language feature that would help in the 2nd case? In the
1st case I know I can use if() statements, but sometimes that makes the
code more obscure.

Thanks!

Jon


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

http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient

Virus-free.  http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient www.avg.com

I have multiple designs like this where I need to enable/disable sometimes complex sets of features. My current method is to set a variable to 1 (true) or 2 (false) and scale the feature by this number: is_version_1 = 1; scale([is_version_1, is_version_1, is_version_1]) { … } This is very easy to do and can be done inline in lots of code just by multiplying the feature – this is very useful where dimensions vary between versions: is_version_1 = 1; is_version_2 =0; is_version_2 = 0; translate([is_version_1*50+ is_version_2*60+ is_version_3*70, 0,0]) { … } I’m not sure I understand nop head’s ‘condition’ – will look this up, it might be the correct way to do what I’m hacking here – but it works well. Alex Gibson admg consulting edumaker limited · Project management · Operations & Process improvement · 3D Printing From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of nop head Sent: 06 September 2020 21:28 To: OpenSCAD general discussion Subject: Re: [OpenSCAD] enabling/disabling code rotate(...) translate(condition ? [ ... ] : [ ... ]) cube(); On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com> wrote: I sometimes run an OpenSCAD program in more than one mode, to create more than one variant of an object. Sometimes I can do something like this // variant 1 rotate(...) translate(...) cube(...); // variant 2 *rotate(...) translate(...) cube(...); and use a leading "*" to control which code section I want to be active. This is annoying, but tolerable, if the number or such code sections is small. But sometimes it looks like this: rotate(...) // translate(...) // variant 1 translate(...) // variant 2 cube(...); and I end up commenting out a single line. This approach is much more error prone and annoying Am I missing a language feature that would help in the 2nd case? In the 1st case I know I can use if() statements, but sometimes that makes the code more obscure. Thanks! Jon _______________________________________________ OpenSCAD mailing list Discuss@lists.openscad.org http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org <http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> Virus-free. <http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> www.avg.com
NY
Ned Young
Mon, Sep 7, 2020 12:14 AM

Rather than embed the variants in the code, create a group of named variables (to be used as constants) at the beginning of your program. Create a duplicate group of variables of the same names but with different values for another configuration, and a third, and so on. You can enable a particular set of values  by commenting out the sets not to be used.

I have a program that produces 3D-printed fastener test blocks, each block with a number of holes to test sizes for M6 or 10-32. I think it has 10 configurations so far.

On Sep 6, 2020, at 4:00 PM, Alex Gibson alex@alexgibson.net wrote:


I have multiple designs like this where I need to enable/disable sometimes complex sets of features.

My current method is to set a variable to 1 (true) or 2 (false) and scale the feature by this number:

is_version_1 = 1;

             scale([is_version_1, is_version_1, is_version_1])
                             {
                             …
                             }

This is very easy to do and can be done inline in lots of code just by multiplying the feature – this is very useful where dimensions vary between versions:

is_version_1 = 1;
is_version_2 =0;
is_version_2 = 0;

             translate([is_version_1*50+ is_version_2*60+ is_version_3*70, 0,0])
                             {
                             …
                             }
                            

I’m not sure I understand nop head’s ‘condition’ – will look this up, it might be the correct way to do what I’m hacking here – but it works well.

Alex Gibson

admg consulting

edumaker limited

·        Project management
·        Operations & Process improvement
·        3D Printing

From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of nop head
Sent: 06 September 2020 21:28
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] enabling/disabling code

rotate(...)
translate(condition ? [ ... ] : [ ... ])
cube();

On Sun, 6 Sep 2020 at 20:11, jon jon@jonbondy.com wrote:
I sometimes run an OpenSCAD program in more than one mode, to create
more than one variant of an object.

Sometimes I can do something like this

// variant 1

rotate(...)

  translate(...)

      cube(...);

// variant 2

*rotate(...)

  translate(...)

      cube(...);

and use a leading "*" to control which code section I want to be
active.  This is annoying, but tolerable, if the number or such code
sections is small.

But sometimes it looks like this:

rotate(...)

//    translate(...)        // variant 1

  translate(...)        // variant 2

      cube(...);

and I end up commenting out a single line.  This approach is much more
error prone and annoying

Am I missing a language feature that would help in the 2nd case? In the
1st case I know I can use if() statements, but sometimes that makes the
code more obscure.

Thanks!

Jon


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

Virus-free. www.avg.com


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

Rather than embed the variants in the code, create a group of named variables (to be used as constants) at the beginning of your program. Create a duplicate group of variables of the same names but with different values for another configuration, and a third, and so on. You can enable a particular set of values by commenting out the sets not to be used. I have a program that produces 3D-printed fastener test blocks, each block with a number of holes to test sizes for M6 or 10-32. I think it has 10 configurations so far. > On Sep 6, 2020, at 4:00 PM, Alex Gibson <alex@alexgibson.net> wrote: > >  > I have multiple designs like this where I need to enable/disable sometimes complex sets of features. > > My current method is to set a variable to 1 (true) or 2 (false) and scale the feature by this number: > > is_version_1 = 1; > > scale([is_version_1, is_version_1, is_version_1]) > { > … > } > > This is very easy to do and can be done inline in lots of code just by multiplying the feature – this is very useful where dimensions vary between versions: > > > > is_version_1 = 1; > is_version_2 =0; > is_version_2 = 0; > > translate([is_version_1*50+ is_version_2*60+ is_version_3*70, 0,0]) > { > … > } > > I’m not sure I understand nop head’s ‘condition’ – will look this up, it might be the correct way to do what I’m hacking here – but it works well. > > > Alex Gibson > > admg consulting > > edumaker limited > > · Project management > · Operations & Process improvement > · 3D Printing > > From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of nop head > Sent: 06 September 2020 21:28 > To: OpenSCAD general discussion > Subject: Re: [OpenSCAD] enabling/disabling code > > rotate(...) > translate(condition ? [ ... ] : [ ... ]) > cube(); > > On Sun, 6 Sep 2020 at 20:11, jon <jon@jonbondy.com> wrote: > I sometimes run an OpenSCAD program in more than one mode, to create > more than one variant of an object. > > Sometimes I can do something like this > > // variant 1 > > rotate(...) > > translate(...) > > cube(...); > > // variant 2 > > *rotate(...) > > translate(...) > > cube(...); > > and use a leading "*" to control which code section I want to be > active. This is annoying, but tolerable, if the number or such code > sections is small. > > > But sometimes it looks like this: > > rotate(...) > > // translate(...) // variant 1 > > translate(...) // variant 2 > > cube(...); > > and I end up commenting out a single line. This approach is much more > error prone and annoying > > > Am I missing a language feature that would help in the 2nd case? In the > 1st case I know I can use if() statements, but sometimes that makes the > code more obscure. > > Thanks! > > Jon > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > Virus-free. www.avg.com > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
JB
Jordan Brown
Tue, Sep 8, 2020 8:02 PM

For the case of translating or rotating differently, I would think in
terms of setting a variable to the desired translation.

// Pick one of these two somehow.
origin = [0,0,0];
// origin = [100,100,100];

rotate(...)
    translate(origin)
        cube(...);

For the problem of selecting individual components out of a model, I
have had two approaches:

One was where I had an object that was built out of multiple individual
printed components.  I wanted to be able to display it either assembled
(for design) or pluck out an individual component (for printing).

I used these modules:

module ifpart(p) {
    if (is_undef($part) || $part == p) {
        children();
    }
}

module ifpartonly(p) {
    if (!is_undef($part) && $part == p) {
        children();
    }
}

module ifpartall() {
    if (is_undef($part)) {
        children();
    }
}

Setting $part would let you select a particular component, and then
inside the model

ifpart("a") { ... part A ... }

Executes if part A is selected, or if everything is selected.

ifpartonly("a") { ... }

Executes if part A is explicitly selected.  (For instance, for
printing a component that occurs multiple times in the full model.)

ifpartall() { ... }

Executes if everything is selected.  (Complementary to ifpartonly(),
for the repetitions of a component that need to be displayed in the
full assembly.)

A related set was intended for managing multiple models in a single file:

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) {
            $content_origin=[xi*d, yi*d];
            children(i);
        }
    }
}

module item(name, png=true, stl=true, distance, xrot, zrot, z) {
    if (!is_undef($content_inventory)) {
        _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);
    } else {
        if (is_undef($content_selected)) {
            translate($content_origin)
                children();
        } else if ($content_selected == name) {
                children();
        }
    }
}

This is used like so:

contents() {
    item("piano") rotate(180) piano();
    item("console") dining_console();
    item("chair1") drchair();
    item("chair2") drchair2();
    item("silverwarechest", distance=120) silverwarechest();
    item("pianobench") pianobench();
    item("pianobench_top", png=false) pianobench($part="top");
    item("pianobench_leg", png=false) pianobench($part="leg");
    item("table") drtable();
    item("table_frame", png=false) drtable($part="frame");
    item("table_center", png=false) drtable($part="center");
    item("table_top", png=false) drtable($part="top");
    item("table_leaves", png=false) drtable_leaves();
    item("bookshelves") bookshelves();
}

Note that the default is to render all of the components, spread in a
grid, but you can ask for an inventory (with no rendering) or that only
a particular component be rendered, or an inventory of those components
that I want a PNG for, or that I want an STL for.

and I have a script that runs OpenSCAD in batch mode with various
settings, first to get the list of parts and then to render STL and PNG
files for each:

#! /bin/sh

case $# in
0|1)
    echo "usage: $0 outdir file.scad ..." >&2
    exit 1
    ;;
esac

d="$1"
shift

function parts()
{
    openscad -D "\$content_inventory=\"$2\"" -o junk.stl "$1" 2>&1 |
        tr -d '\r' |
        sed -n -e 's/^ECHO: "PART", "\(.*\)"$/\1/p' |
        sed 's/", "/ /g'
}

for i; do
    base=$(basename "$i" .scad)
    parts $i png |
        while read part camera; do
            def="\$content_selected=\"$part\""
            printf "%s %s png...\n" "$base" "$part"
            openscad -D "$def" $camera -o "$d/$base.$part.png" "$i"
        done
    parts $i stl |
        while read part; do
            def="\$content_selected=\"$part\""
            printf "%s %s stl...\n" "$base" "$part"
            openscad -D "$def" -o "$d/$base.$part.stl" "$i"
        done
done

I could probably have solved both problems with a single set of
modules... but I didn't.

While I'm mentioning it, for the "assembled or printable" question, one
scheme that I played with that was kind of fun was to have an animation
that would switch between assembled form and printable form.

// Given a value and a table of value/position pairs, interpolate a
// position for that value.
// It seems like lookup() should do this sort of vector interpolation
// on its own, but it doesn't seem to.
function xyzinterp(v, table) =
    let (x= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][0]]])
    let (y= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][1]]])
    let (z= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][2]]])
        [lookup(v, x), lookup(v, y), lookup(v,z)];

// Given a table of animation time values (from zero to one) and
// positions for each of those time values, translate the children
// to the appropriate position.
module atranslate(table) {
    translate(xyzinterp($t, table)) children();
}

// Given a table of animation time values (from zero to one) and
// rotations for each of those time values, rotate the children
// to the appropriate position.
module arotate(table) {
    rotate(xyzinterp($t, table)) children();
}

// Given a start point and an end point, translate the children
// from the start to the end and back in each animation cycle.
// Pause briefly at the start and end.
module a2translate(p1, p2) {
    atranslate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children();
}

// Given a start rotation and an end rotation, rotate the children
// from the start to the end and back in each animation cycle.
// Pause briefly at the start and end.
module a2rotate(p1, p2) {
    arotate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children();
}

Like so:

a2translate([0,0,0], [0,0,0])
    cube(10);
a2translate([5,5,10], [20,0,10])
    a2rotate([0,0,0], [180,0,0])
    cylinder(h=10, d1=5, d2=10);
a2translate([5,5,20], [32,0,0])
    cylinder(h=10, d1=10, d2=5);

There you can set $t to 0 to get one form, and to 0.5 to get the other form.

For the case of translating or rotating differently, I would think in terms of setting a variable to the desired translation. // Pick one of these two somehow. origin = [0,0,0]; // origin = [100,100,100]; rotate(...)     translate(origin)         cube(...); For the problem of selecting individual components out of a model, I have had two approaches: One was where I had an object that was built out of multiple individual printed components.  I wanted to be able to display it either assembled (for design) or pluck out an individual component (for printing). I used these modules: module ifpart(p) { if (is_undef($part) || $part == p) { children(); } } module ifpartonly(p) { if (!is_undef($part) && $part == p) { children(); } } module ifpartall() { if (is_undef($part)) { children(); } } Setting $part would let you select a particular component, and then inside the model ifpart("a") { ... part A ... } Executes if part A is selected, or if everything is selected. ifpartonly("a") { ... } Executes if part A is explicitly selected.  (For instance, for printing a component that occurs multiple times in the full model.) ifpartall() { ... } Executes if everything is selected.  (Complementary to ifpartonly(), for the repetitions of a component that need to be displayed in the full assembly.) A related set was intended for managing multiple models in a single file: 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) { $content_origin=[xi*d, yi*d]; children(i); } } } module item(name, png=true, stl=true, distance, xrot, zrot, z) { if (!is_undef($content_inventory)) { _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); } else { if (is_undef($content_selected)) { translate($content_origin) children(); } else if ($content_selected == name) { children(); } } } This is used like so: contents() { item("piano") rotate(180) piano(); item("console") dining_console(); item("chair1") drchair(); item("chair2") drchair2(); item("silverwarechest", distance=120) silverwarechest(); item("pianobench") pianobench(); item("pianobench_top", png=false) pianobench($part="top"); item("pianobench_leg", png=false) pianobench($part="leg"); item("table") drtable(); item("table_frame", png=false) drtable($part="frame"); item("table_center", png=false) drtable($part="center"); item("table_top", png=false) drtable($part="top"); item("table_leaves", png=false) drtable_leaves(); item("bookshelves") bookshelves(); } Note that the default is to render all of the components, spread in a grid, but you can ask for an inventory (with no rendering) or that only a particular component be rendered, or an inventory of those components that I want a PNG for, or that I want an STL for. and I have a script that runs OpenSCAD in batch mode with various settings, first to get the list of parts and then to render STL and PNG files for each: #! /bin/sh case $# in 0|1) echo "usage: $0 outdir file.scad ..." >&2 exit 1 ;; esac d="$1" shift function parts() { openscad -D "\$content_inventory=\"$2\"" -o junk.stl "$1" 2>&1 | tr -d '\r' | sed -n -e 's/^ECHO: "PART", "\(.*\)"$/\1/p' | sed 's/", "/ /g' } for i; do base=$(basename "$i" .scad) parts $i png | while read part camera; do def="\$content_selected=\"$part\"" printf "%s %s png...\n" "$base" "$part" openscad -D "$def" $camera -o "$d/$base.$part.png" "$i" done parts $i stl | while read part; do def="\$content_selected=\"$part\"" printf "%s %s stl...\n" "$base" "$part" openscad -D "$def" -o "$d/$base.$part.stl" "$i" done done I could probably have solved both problems with a single set of modules... but I didn't. While I'm mentioning it, for the "assembled or printable" question, one scheme that I played with that was kind of fun was to have an animation that would switch between assembled form and printable form. // Given a value and a table of value/position pairs, interpolate a // position for that value. // It seems like lookup() should do this sort of vector interpolation // on its own, but it doesn't seem to. function xyzinterp(v, table) = let (x= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][0]]]) let (y= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][1]]]) let (z= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][2]]]) [lookup(v, x), lookup(v, y), lookup(v,z)]; // Given a table of animation time values (from zero to one) and // positions for each of those time values, translate the children // to the appropriate position. module atranslate(table) { translate(xyzinterp($t, table)) children(); } // Given a table of animation time values (from zero to one) and // rotations for each of those time values, rotate the children // to the appropriate position. module arotate(table) { rotate(xyzinterp($t, table)) children(); } // Given a start point and an end point, translate the children // from the start to the end and back in each animation cycle. // Pause briefly at the start and end. module a2translate(p1, p2) { atranslate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children(); } // Given a start rotation and an end rotation, rotate the children // from the start to the end and back in each animation cycle. // Pause briefly at the start and end. module a2rotate(p1, p2) { arotate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children(); } Like so: a2translate([0,0,0], [0,0,0]) cube(10); a2translate([5,5,10], [20,0,10])  a2rotate([0,0,0], [180,0,0])  cylinder(h=10, d1=5, d2=10); a2translate([5,5,20], [32,0,0])  cylinder(h=10, d1=10, d2=5); There you can set $t to 0 to get one form, and to 0.5 to get the other form.
NH
nop head
Tue, Sep 8, 2020 8:55 PM

I use the customiser to control which parts of my model to display, i.e. to
customise its pose, rather than its intended use: to vary model parameters.
I just test the variables it sets with if or use them to translate and
rotate.

[image: image.png]

In this case I also can cross section the parts with sliders to see inside.

[image: image.png]

And I use $preview to switch between the assembly view with F5 and the laid
out for printing view with F6

[image: image.png]

On Tue, 8 Sep 2020 at 21:03, Jordan Brown openscad@jordan.maileater.net
wrote:

For the case of translating or rotating differently, I would think in
terms of setting a variable to the desired translation.

// Pick one of these two somehow.
origin = [0,0,0];
// origin = [100,100,100];

rotate(...)
translate(origin)
cube(...);

For the problem of selecting individual components out of a model, I have
had two approaches:

One was where I had an object that was built out of multiple individual
printed components.  I wanted to be able to display it either assembled
(for design) or pluck out an individual component (for printing).

I used these modules:

module ifpart(p) {
if (is_undef($part) || $part == p) {
children();
}
}

module ifpartonly(p) {
if (!is_undef($part) && $part == p) {
children();
}
}

module ifpartall() {
if (is_undef($part)) {
children();
}
}

Setting $part would let you select a particular component, and then
inside the model

ifpart("a") { ... part A ... }

Executes if part A is selected, or if everything is selected.

ifpartonly("a") { ... }

Executes if part A is explicitly selected.  (For instance, for printing a
component that occurs multiple times in the full model.)

ifpartall() { ... }

Executes if everything is selected.  (Complementary to ifpartonly(), for
the repetitions of a component that need to be displayed in the full
assembly.)

A related set was intended for managing multiple models in a single file:

module contents(d=100) {
nx = ceil(sqrt($children));
ny = ceil($children/nx);
for (xi=[0:nx-1], yi=[0:ny-1]) {
i = xi + yinx;
if (i < $children) {
$content_origin=[xi
d, yi*d];
children(i);
}
}
}

module item(name, png=true, stl=true, distance, xrot, zrot, z) {
if (!is_undef($content_inventory)) {
_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);
} else {
if (is_undef($content_selected)) {
translate($content_origin)
children();
} else if ($content_selected == name) {
children();
}
}
}

This is used like so:

contents() {
item("piano") rotate(180) piano();
item("console") dining_console();
item("chair1") drchair();
item("chair2") drchair2();
item("silverwarechest", distance=120) silverwarechest();
item("pianobench") pianobench();
item("pianobench_top", png=false) pianobench($part="top");
item("pianobench_leg", png=false) pianobench($part="leg");
item("table") drtable();
item("table_frame", png=false) drtable($part="frame");
item("table_center", png=false) drtable($part="center");
item("table_top", png=false) drtable($part="top");
item("table_leaves", png=false) drtable_leaves();
item("bookshelves") bookshelves();
}

Note that the default is to render all of the components, spread in a
grid, but you can ask for an inventory (with no rendering) or that only a
particular component be rendered, or an inventory of those components that
I want a PNG for, or that I want an STL for.

and I have a script that runs OpenSCAD in batch mode with various
settings, first to get the list of parts and then to render STL and PNG
files for each:

#! /bin/sh

case $# in
0|1)
echo "usage: $0 outdir file.scad ..." >&2
exit 1
;;
esac

d="$1"
shift

function parts()
{
openscad -D "$content_inventory="$2"" -o junk.stl "$1" 2>&1 |
tr -d '\r' |
sed -n -e 's/^ECHO: "PART", "(.*)"$/\1/p' |
sed 's/", "/ /g'
}

for i; do
base=$(basename "$i" .scad)
parts $i png |
while read part camera; do
def="$content_selected="$part""
printf "%s %s png...\n" "$base" "$part"
openscad -D "$def" $camera -o "$d/$base.$part.png" "$i"
done
parts $i stl |
while read part; do
def="$content_selected="$part""
printf "%s %s stl...\n" "$base" "$part"
openscad -D "$def" -o "$d/$base.$part.stl" "$i"
done
done

I could probably have solved both problems with a single set of modules...
but I didn't.

While I'm mentioning it, for the "assembled or printable" question, one
scheme that I played with that was kind of fun was to have an animation
that would switch between assembled form and printable form.

// Given a value and a table of value/position pairs, interpolate a
// position for that value.
// It seems like lookup() should do this sort of vector interpolation
// on its own, but it doesn't seem to.
function xyzinterp(v, table) =
let (x= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][0]]])
let (y= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][1]]])
let (z= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][2]]])
[lookup(v, x), lookup(v, y), lookup(v,z)];

// Given a table of animation time values (from zero to one) and
// positions for each of those time values, translate the children
// to the appropriate position.
module atranslate(table) {
translate(xyzinterp($t, table)) children();
}

// Given a table of animation time values (from zero to one) and
// rotations for each of those time values, rotate the children
// to the appropriate position.
module arotate(table) {
rotate(xyzinterp($t, table)) children();
}

// Given a start point and an end point, translate the children
// from the start to the end and back in each animation cycle.
// Pause briefly at the start and end.
module a2translate(p1, p2) {
atranslate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children();
}

// Given a start rotation and an end rotation, rotate the children
// from the start to the end and back in each animation cycle.
// Pause briefly at the start and end.
module a2rotate(p1, p2) {
arotate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children();
}

Like so:

a2translate([0,0,0], [0,0,0])
cube(10);
a2translate([5,5,10], [20,0,10])
a2rotate([0,0,0], [180,0,0])
cylinder(h=10, d1=5, d2=10);
a2translate([5,5,20], [32,0,0])
cylinder(h=10, d1=10, d2=5);

There you can set $t to 0 to get one form, and to 0.5 to get the other
form.


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

I use the customiser to control which parts of my model to display, i.e. to customise its pose, rather than its intended use: to vary model parameters. I just test the variables it sets with if or use them to translate and rotate. [image: image.png] In this case I also can cross section the parts with sliders to see inside. [image: image.png] And I use $preview to switch between the assembly view with F5 and the laid out for printing view with F6 [image: image.png] On Tue, 8 Sep 2020 at 21:03, Jordan Brown <openscad@jordan.maileater.net> wrote: > For the case of translating or rotating differently, I would think in > terms of setting a variable to the desired translation. > > // Pick one of these two somehow. > origin = [0,0,0]; > // origin = [100,100,100]; > > rotate(...) > translate(origin) > cube(...); > > > For the problem of selecting individual components out of a model, I have > had two approaches: > > One was where I had an object that was built out of multiple individual > printed components. I wanted to be able to display it either assembled > (for design) or pluck out an individual component (for printing). > > I used these modules: > > module ifpart(p) { > if (is_undef($part) || $part == p) { > children(); > } > } > > module ifpartonly(p) { > if (!is_undef($part) && $part == p) { > children(); > } > } > > module ifpartall() { > if (is_undef($part)) { > children(); > } > } > > Setting $part would let you select a particular component, and then > inside the model > > ifpart("a") { ... part A ... } > > Executes if part A is selected, or if everything is selected. > > ifpartonly("a") { ... } > > Executes if part A is explicitly selected. (For instance, for printing a > component that occurs multiple times in the full model.) > > ifpartall() { ... } > > Executes if everything is selected. (Complementary to ifpartonly(), for > the repetitions of a component that need to be displayed in the full > assembly.) > > > A related set was intended for managing multiple models in a single file: > > 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) { > $content_origin=[xi*d, yi*d]; > children(i); > } > } > } > > module item(name, png=true, stl=true, distance, xrot, zrot, z) { > if (!is_undef($content_inventory)) { > _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); > } else { > if (is_undef($content_selected)) { > translate($content_origin) > children(); > } else if ($content_selected == name) { > children(); > } > } > } > > > This is used like so: > > contents() { > item("piano") rotate(180) piano(); > item("console") dining_console(); > item("chair1") drchair(); > item("chair2") drchair2(); > item("silverwarechest", distance=120) silverwarechest(); > item("pianobench") pianobench(); > item("pianobench_top", png=false) pianobench($part="top"); > item("pianobench_leg", png=false) pianobench($part="leg"); > item("table") drtable(); > item("table_frame", png=false) drtable($part="frame"); > item("table_center", png=false) drtable($part="center"); > item("table_top", png=false) drtable($part="top"); > item("table_leaves", png=false) drtable_leaves(); > item("bookshelves") bookshelves(); > } > > Note that the default is to render all of the components, spread in a > grid, but you can ask for an inventory (with no rendering) or that only a > particular component be rendered, or an inventory of those components that > I want a PNG for, or that I want an STL for. > > and I have a script that runs OpenSCAD in batch mode with various > settings, first to get the list of parts and then to render STL and PNG > files for each: > > #! /bin/sh > > case $# in > 0|1) > echo "usage: $0 outdir file.scad ..." >&2 > exit 1 > ;; > esac > > d="$1" > shift > > function parts() > { > openscad -D "\$content_inventory=\"$2\"" -o junk.stl "$1" 2>&1 | > tr -d '\r' | > sed -n -e 's/^ECHO: "PART", "\(.*\)"$/\1/p' | > sed 's/", "/ /g' > } > > for i; do > base=$(basename "$i" .scad) > parts $i png | > while read part camera; do > def="\$content_selected=\"$part\"" > printf "%s %s png...\n" "$base" "$part" > openscad -D "$def" $camera -o "$d/$base.$part.png" "$i" > done > parts $i stl | > while read part; do > def="\$content_selected=\"$part\"" > printf "%s %s stl...\n" "$base" "$part" > openscad -D "$def" -o "$d/$base.$part.stl" "$i" > done > done > > > I could probably have solved both problems with a single set of modules... > but I didn't. > > > While I'm mentioning it, for the "assembled or printable" question, one > scheme that I played with that was kind of fun was to have an animation > that would switch between assembled form and printable form. > > // Given a value and a table of value/position pairs, interpolate a > // position for that value. > // It seems like lookup() should do this sort of vector interpolation > // on its own, but it doesn't seem to. > function xyzinterp(v, table) = > let (x= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][0]]]) > let (y= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][1]]]) > let (z= [for (i=[0:len(table)-1]) [table[i][0], table[i][1][2]]]) > [lookup(v, x), lookup(v, y), lookup(v,z)]; > > // Given a table of animation time values (from zero to one) and > // positions for each of those time values, translate the children > // to the appropriate position. > module atranslate(table) { > translate(xyzinterp($t, table)) children(); > } > > // Given a table of animation time values (from zero to one) and > // rotations for each of those time values, rotate the children > // to the appropriate position. > module arotate(table) { > rotate(xyzinterp($t, table)) children(); > } > > // Given a start point and an end point, translate the children > // from the start to the end and back in each animation cycle. > // Pause briefly at the start and end. > module a2translate(p1, p2) { > atranslate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children(); > } > > // Given a start rotation and an end rotation, rotate the children > // from the start to the end and back in each animation cycle. > // Pause briefly at the start and end. > module a2rotate(p1, p2) { > arotate([[0.05, p1], [0.45, p2], [0.55, p2], [0.95, p1]]) children(); > } > > > Like so: > > a2translate([0,0,0], [0,0,0]) > cube(10); > a2translate([5,5,10], [20,0,10]) > a2rotate([0,0,0], [180,0,0]) > cylinder(h=10, d1=5, d2=10); > a2translate([5,5,20], [32,0,0]) > cylinder(h=10, d1=10, d2=5); > > There you can set $t to 0 to get one form, and to 0.5 to get the other > form. > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >