Posted by dmould

Accumulating parameters August 07, 2015 08:57AM |
Registered: 8 years ago Posts: 2,472 |

I often have parameter driven designs that have a variable number of objects, the positions of which I define as an array. e.g. (copy to OpenScad between the ** marks if you want to try)

**

MountPositions=[

[0,-3.2],

[8,-3.2],

[0,5.8],

[8,5.8],

[3,2],

[7,3.5]

// Add or remove positions at will

];

//This array can be used in a "for" loop e.g.

for (Mnt=MountPositions)

{

translate([Mnt[0],Mnt[1],0])

cylinder(r=1,h=5,$fn=20);

translate([Mnt[0],Mnt[1],5])

cylinder(r=.5,h=2,$fn=20);

}

**

Which automatically executes the number of times that there are variables in the array. This is really great for designs where different variations will have a different number of objects in different places - maybe box dividers, support fixtures etc.

My problem is that I often need a variable that is the number of objects that there are, or variables containing the max and min extents of the objects, or find the total or average of all the variables. e.g. let's say that I want to make a box or baseplate for all the cylinders in the above example, the size of which depends on the extent of the objects and so will change if I alter, add or remove values in the array. In that case I need to define variables of the min and max X & Y positions. Or maybe I need the average X or Y spacing, in which case I need to add all the parameters and divide by the number of parameters. Is there any way in OpenScad of automatically defining a variable that is the number of parameters, or a variable that is an arithmetic function of the variables?

Because while the "for" loop will automatically go through the array the right number of times to draw things, variables cannot be redefined within a module so I cannot accumulate with a line such as, "Total=Total+Mnt[0];" or "MaxX=max(MaxX,Mnt[0]);" in the "for" loop.

e.g. the following does not work if I need to know the number of variables that have been defined:

NumberOfMounts=0;

for (Mnt=MountPositions)

{

NumberOfMounts=NumberOfMounts+1;

}

echo(NumberOfMounts);

Can anyone figure out a solution?

Dave

**

MountPositions=[

[0,-3.2],

[8,-3.2],

[0,5.8],

[8,5.8],

[3,2],

[7,3.5]

// Add or remove positions at will

];

//This array can be used in a "for" loop e.g.

for (Mnt=MountPositions)

{

translate([Mnt[0],Mnt[1],0])

cylinder(r=1,h=5,$fn=20);

translate([Mnt[0],Mnt[1],5])

cylinder(r=.5,h=2,$fn=20);

}

**

Which automatically executes the number of times that there are variables in the array. This is really great for designs where different variations will have a different number of objects in different places - maybe box dividers, support fixtures etc.

My problem is that I often need a variable that is the number of objects that there are, or variables containing the max and min extents of the objects, or find the total or average of all the variables. e.g. let's say that I want to make a box or baseplate for all the cylinders in the above example, the size of which depends on the extent of the objects and so will change if I alter, add or remove values in the array. In that case I need to define variables of the min and max X & Y positions. Or maybe I need the average X or Y spacing, in which case I need to add all the parameters and divide by the number of parameters. Is there any way in OpenScad of automatically defining a variable that is the number of parameters, or a variable that is an arithmetic function of the variables?

Because while the "for" loop will automatically go through the array the right number of times to draw things, variables cannot be redefined within a module so I cannot accumulate with a line such as, "Total=Total+Mnt[0];" or "MaxX=max(MaxX,Mnt[0]);" in the "for" loop.

e.g. the following does not work if I need to know the number of variables that have been defined:

NumberOfMounts=0;

for (Mnt=MountPositions)

{

NumberOfMounts=NumberOfMounts+1;

}

echo(NumberOfMounts);

Can anyone figure out a solution?

Dave

Re: Accumulating parameters August 07, 2015 12:31PM |
Registered: 8 years ago Posts: 118 |

Re: Accumulating parameters August 07, 2015 04:38PM |
Registered: 8 years ago Posts: 590 |

The len() function is indeed the simplest solution for getting the length of an array. However, this solves only one special case of dmould's more general problem...

For solving things like sum, minimum or maximum, you could use recursive functions. To illustrate the idea, you could e.g. use something like the following for computing the minimum and maximum [x,y,z] of an array of points:

Edited 6 time(s). Last edit at 08/08/2015 06:38AM by enif.

For solving things like sum, minimum or maximum, you could use recursive functions. To illustrate the idea, you could e.g. use something like the following for computing the minimum and maximum [x,y,z] of an array of points:

function minxyz(array,J = 0) = [( J < len(array)?min(array [J] [0],minxyz(array,J +1)[0]):99999999) , ( J < len(array)?min(array [J] [1],minxyz(array, J +1)[1]):99999999),( J < len(array)?min(array [J] [2],minxyz(array,J +1)[2]):99999999)]; function maxxyz(array,J = 0) = [( J < len(array)?max(array [J] [0],maxxyz(array, J +1)[0]):0),( J < len(array)?max(array [J] [1],maxxyz(array, J +1)[1]):0),( J < len(array)?max(array [J] [2],maxxyz(array, J +1)[2]):0)]; pts=[[6,5,7],[8,5,8],[7,1,6],[11,4,7]]; // list of points echo(minxyz(pts),maxxyz(pts)); for(p = pts) translate(p)cube([1,1,1]); // draw points color("red",0.5) translate(minxyz(pts))cube(maxxyz(pts)-minxyz(pts)+[1,1,1]); // draw englobing cube

Edited 6 time(s). Last edit at 08/08/2015 06:38AM by enif.

Re: Accumulating parameters August 08, 2015 01:56AM |
Registered: 8 years ago Posts: 590 |

And here a more efficient and cleaner version, which can easily be adapted for any dimension of the array, e.g. just [x,y] as in the original question...

Edited 4 time(s). Last edit at 08/08/2015 06:19AM by enif.

function mina(array,ind,J=0) = ( J < len(array)?min(array [J] [ind],mina(array,ind,J+1)):99999999); function maxa(array,ind,J=0) = ( J < len(array)?max(array [J] [ind],maxa(array,ind,J+1)):0); function minxyz(array,i=0) = [mina(array,0),mina(array,1),mina(array,2)]; function maxxyz(array,i=0) = [maxa(array,0),maxa(array,1),maxa(array,2)]; function minxy(array,i=0) = [mina(array,0),mina(array,1)]; function maxxy(array,i=0) = [maxa(array,0),maxa(array,1)]; pts=[[6,5,7],[8,5,8],[7,1,6],[4,8,5],[3,3,3],[11,4,7]];// point list echo("minxyz=",minxyz(pts)); echo("maxxyz=",maxxyz(pts)); // show points as little cubes for(p = pts) translate(p)cube([1,1,1]); // show englobing cube of all points color("red",0.5)translate(minxyz(pts))cube(maxxyz(pts)-minxyz(pts)+[1,1,1]);

Edited 4 time(s). Last edit at 08/08/2015 06:19AM by enif.

Re: Accumulating parameters August 10, 2015 08:31AM |
Registered: 8 years ago Posts: 2,472 |

Sorry, only registered users may post in this forum.