Welcome! Log In Create A New Profile

Advanced

OFF TOPIC - openscad help

Posted by appjaws1 
OFF TOPIC - openscad help
January 21, 2016 11:22AM
I am changing some parts on my ormerod and am using openscad. I have posted on that forum but have had no replies as yet, so thought I would try the experts on this forum

Is it possible to use an accumulating variable?

I have the following lines as an example.

translate([0,0,0]) cylinder(d=holdupdia, h=holdupht);
acc=acc+holdht;
translate([0,0,acc]) cylinder(d=holdshaftdia, h=holdshaftupperht);
acc=acc+holdshaftupperht;
translate([0,0,acc]) cylinder(d=holdmiddia, h=holdmidht);
acc=acc+holdmidht;
translate([0,0,acc]) cylinder(d=holdshaftdia, h=holdshaftmidht);

acc just shows the last value assigned to it, I need it to accumulate all of the values in the section

Any ideas on how to achieve this?


appjaws - Core XYUV Duet Ethernet Duex5
firmware 3.1.1 Web Interface 3.1.1
Ormerod 1-converted to laser engraver, Duet wifi
OpenSCAD version 2020.07
slic3r-1.3.0, Simplify3D 4.1.2, Cura-4.4.1
Re: OFF TOPIC - openscad help
January 21, 2016 01:35PM
Quote
appjaws1
I am changing some parts on my ormerod and am using openscad. I have posted on that forum but have had no replies as yet, so thought I would try the experts on this forum

Is it possible to use an accumulating variable?

I have the following lines as an example.

translate([0,0,0]) cylinder(d=holdupdia, h=holdupht);
acc=acc+holdht;
translate([0,0,acc]) cylinder(d=holdshaftdia, h=holdshaftupperht);
acc=acc+holdshaftupperht;
translate([0,0,acc]) cylinder(d=holdmiddia, h=holdmidht);
acc=acc+holdmidht;
translate([0,0,acc]) cylinder(d=holdshaftdia, h=holdshaftmidht);

acc just shows the last value assigned to it, I need it to accumulate all of the values in the section

Any ideas on how to achieve this?

OpenSCAD is annoying in that way that it doesn't let you do the "a=a+1" familiar from other programming languages.

In your example I don't quite see a big advantage of using that particular approach though since each "cylinder" statement uses different variables (so it's not like you could set up a loop with just one "translate - cylinder" statement).

You could use a series of acc, acc1, acc2 variables:
acc=...; // initial definition of acc
acc1=acc+holdht;
acc2=acc1+holdshaftupperht;
acc3=acc2+holdmidht;
...then the series of "translate ([0,0,acc/acc1/acc2/acc3]) cylinder()" bits. You would still have to have four of these because the variables used in "cylinder" are different in each instance.

If the acc variable increased by a constant amount, you could use a "for" loop to accumulate it. But because your "cylinder" statements all use different variables, this will not be very useful as you would then have the check the loop counter inside the loop and execute different "translate cylinder" lines depending on its value.

You could use a recursive function to do something akin to accumulating your acc variable ("init" is the initial value of acc):

increment=[init,holdht,holdshaftupperht,holdmidht];
function acc(n)=(n>0)?acc(n-1)+increment[n]:increment[n];

In this case calling "acc(0)" returns the initial value, "acc(1)" returns initial+holdht, "acc(2)" returns initial+holdht+holdshaftupperht", and "acc(3)" returns initial+holdht+holdshaftupperht+holdmidht. So you could use a 0 to 3 loop for the translate statements. But as above, the contents of the counter variable would have to be checked inside the loop to determine which cylinder statement to execute.

Or, if you don't want to have to check the contents of the counter inside the loop, you could do something like this:

increment=[init,holdht,holdshaftupperht,holdmidht];
function acc(n)=(n>0)?acc(n-1)+increment[n]:increment[n];
diameter=[holdupdia,holdshaftdia,holdmiddia,holdshaftdia];
height=[holdupht,holdshaftupperht,holdmidht,holdshaftmidht];
for (loop=[0:1:3])
{
                translate ([0,0,acc(loop)]) cylinder (d=diameter[loop],h=height[loop]);
}

I suppose this has the advantage that it would be easy to add further cylindrical sections to your object. Although if these four sections are all your object will ever have, then I'm not sure the added complexity is worth it!


This is the only way I can think of doing this, although I'd be happy to be told otherwise!

Cheers,

Bart
Re: OFF TOPIC - openscad help
January 21, 2016 01:50PM
Thank you Bart, nothing is easy is it.

All I want to do is increase "Z" by the height of the previous item, so then I could have a routine that just took the heights as parameters. I wanted to parameterise this so that I could use it for different item heights and diameters in the future

Of course the added problem is the different diameters of the cylinders.

I wonder if I should use an array but I think I would have to calculate all values of Z, so I may as well enter them in the script.


appjaws - Core XYUV Duet Ethernet Duex5
firmware 3.1.1 Web Interface 3.1.1
Ormerod 1-converted to laser engraver, Duet wifi
OpenSCAD version 2020.07
slic3r-1.3.0, Simplify3D 4.1.2, Cura-4.4.1
Re: OFF TOPIC - openscad help
January 21, 2016 04:01PM
Quote
appjaws1
Thank you Bart, nothing is easy is it.

All I want to do is increase "Z" by the height of the previous item, so then I could have a routine that just took the heights as parameters. I wanted to parameterise this so that I could use it for different item heights and diameters in the future

Of course the added problem is the different diameters of the cylinders.

I wonder if I should use an array but I think I would have to calculate all values of Z, so I may as well enter them in the script.

I think I know what you want to do but I don't think there is a way of doing this since all variables in OpenSCAD are essentially constants (except for loop counters). This is quite annoying I must say but I've learnt to live (just about) with it. :-)

Another variation on the theme:
acc=initial value
translate ([0,0,acc]) union ()
{    cylinder (d=holdupdia,h=holdupht);
     translate ([0,0,holdht]) union ()
    {    cylinder (d=holdshaftdia,h=holdshaftupperht);
         translate ([0,0,holdshaftupperht]) union ()
        {    cylinder (d=holdmiddia,h=holdmidht);
             translate ([0,0,holdmidht]) union ()
            {    cylinder (d=holdshaftdia,h=holdshaftmidht);
            }
        }
    }
}
The last union() is not necessary but is added here for consistency with the preceding code. This is a bit like a series of recursive function calls (in terms of the z coordinate in "translate") but written out in its entirety. Each translate builds on the previous one.

Cheers,
Bart

Edited 1 time(s). Last edit at 01/21/2016 04:07PM by bartdietrich.
Re: OFF TOPIC - openscad help
January 21, 2016 06:12PM
Actually, just had another think about this and you could do it the following way:

sections=4; // number of cylindrical sections
heights=[3,5,3,2]; // heights of consecutive sections
diameters=[5,2,8,7]; // diameters of consecutive sections

module draw_section (iter=sections)
{
    cylinder (h=heights[sections-iter],d=diameters[sections-iter]);
    if (iter>1)
        translate ([0,0,heights[sections-iter]]) draw_section (iter-1);
}

draw_section ();

This combines the arrays and recursivity of my previous examples, but uses a recursive module call instead. To do different objects composed of successive cylinders you would just need to update the number of sections (sections variable) and update the two arrays with the heights and diameters of successive sections (making sure each array has a number of elements equal to the sections variable).
The module "draw_section", if called with an empty parameter list ("draw_section ()", probably its most useful form), calls itself iteratively as many times as there are sections and each instance of translate builds on the one in the previous iteration. If desired, you can specify the number of sections to draw (actually sections plus one). So if you call "draw_section (1)" it will draw only two sections of your object. These will be the last two sections in the arrays because of how this example is coded but hopefully you can make your own modifications from here.

Hope this is useful!

Cheers,
Bart

Edited 1 time(s). Last edit at 01/21/2016 06:15PM by bartdietrich.
Re: OFF TOPIC - openscad help
January 22, 2016 06:05AM
Thanks again Bart,

This works well but I suppose I may as well enter the values in the script in the normal way because once the script is constructed, to change all values will take the same time.

I wonder if openscad will ever have the full rages of programming functions. I would have thought that including a=a+1 would be straight forward and very useful. Perhaps it's more complicated to include that I think.

Paul


appjaws - Core XYUV Duet Ethernet Duex5
firmware 3.1.1 Web Interface 3.1.1
Ormerod 1-converted to laser engraver, Duet wifi
OpenSCAD version 2020.07
slic3r-1.3.0, Simplify3D 4.1.2, Cura-4.4.1
Sorry, only registered users may post in this forum.

Click here to login