Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Summing from a lists - question #4308

Closed
IraSch opened this issue Jul 26, 2022 · 5 comments
Closed

Summing from a lists - question #4308

IraSch opened this issue Jul 26, 2022 · 5 comments

Comments

@IraSch
Copy link

IraSch commented Jul 26, 2022

There has to be a way to do this, but I'm not seeing how:

I have a list of 10 cylinder diameters and a distance between adjacent cylinders:

Diameters = [1, 3, 2, 7, 3, 4, 9, 8, 4, 5];
Spacing = 5;

I'd like to be able to step through list and create each cylinder. So to find the center of cylinder i, I would need to add up the diameters of all previous cylinders (plus the appropriate spacing, Spacing*(i-1), and then use that for a translate();

However, with immutable variables I can't add things based on a parameter i (for example if I wanted to loop thru the 10 items in the list).

There has to be a way of doing this, but I'm not seeing it, other than a bunch of "if" statements based on a value of i:
if (i==0) { translate([0, ...]) cylinder(d=Diameter[i], h=100); }
if (i==1) { translate([Spacingi+Diameter[0], ...]) cylinder(d=Diameter[i], h=100); }
if (i==2) { translate([Spacing
i+Diameter[0]+Diameter[1], ...]) cylinder(d=Diameter[i], h=100); }
if (i==3) { translate([Spacing*i+Diameter[0]+Diameter[1]+Diameter[2], ...]) cylinder(d=Diameter[i], h=100); }
... etc....

Any ideas?

Thanks!

@jordanbrown0
Copy link
Contributor

The mailing list is a better place to ask a "how to" question.

The answer is recursion.

module row_of_cylinders(h, diameters, spacing, i=0) {
    if (i < len(diameters)) {
        d = diameters[i];
        cylinder(h=h, d=d);
        translate([d+spacing, 0, 0])
            row_of_cylinders(h, diameters, spacing, i+1);
    }
}

Diameters = [1, 3, 2, 7, 3, 4, 9, 8, 4, 5];
spacing = 5;
h = 10;
row_of_cylinders(h=h, diameters=Diameters, spacing=spacing);

Similar techniques can be used, e.g., to construct a new array with the offsets:

function cylinder_offsets(diameters, spacing, i=0, offset = 0, result=[]) =
    i >= len(diameters)
    ? result
    : cylinder_offsets(diameters, spacing, i+1, offset+diameters[i]+spacing, concat(result, offset));

module row_of_cylinders_2(h, diameters, spacing) {
    offsets = cylinder_offsets(diameters=diameters, spacing=spacing);
    for (i = [0:len(diameters)-1]) {
        translate([offsets[i], 0, 0]) cylinder(h=h, d=diameters[i]);
    }
}

translate([0,10,0]) row_of_cylinders_2(h=h, diameters=Diameters, spacing=spacing);

@IraSch
Copy link
Author

IraSch commented Jul 26, 2022

Thank you on both answers.

I was looking for a better place to ask the question and didn't see the alternative.

I was looking for a way to get the translate()'s to "stack up" and recursion didn't occur to me. Very elegant solution.

Thanks again.

@jordanbrown0
Copy link
Contributor

jordanbrown0 commented Jul 26, 2022

Another technique is to use the "C-style for" available in list comprehensions.

module row_of_cylinders_3(h, diameters, spacing) {
    offsets = [
        for(
            i = 0, x=0;
            i < len(diameters);
            x = x + diameters[i] + spacing, i = i + 1
        ) x
    ];
    for (i=[0:len(diameters)-1]) {
        translate([offsets[i],0,0]) cylinder(h=h, d=diameters[i]);
    }
}

translate([0,20,0]) row_of_cylinders_3(h=h, diameters=Diameters, spacing=spacing);

I don't know why "C-style for" is not available for top-level for loops, but it doesn't seem to be.

One might think that this violates the "variables are immutable" rule. I would say that it does not, in the same way that any other for loop does not: it creates new instances of the variable for each iteration. The difference is that with C-style for the new instance can be based on the previous instance.

@thehans thehans closed this as completed Jul 26, 2022
@IraSch
Copy link
Author

IraSch commented Jul 26, 2022

Wow, I didn't know you could do the x=.... as a FOR parameter and have it calculate different x's. I've definitely learned a lot from this question.

Thanks again.

@MichaelAtOz
Copy link
Member

MichaelAtOz commented Jul 26, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants