discuss@lists.openscad.org

OpenSCAD general discussion

View all threads

"for" generates funny intermediate values in polygons

M
mikeonenine@web.de
Sat, Sep 17, 2022 10:30 PM

A polygon with a cosine shape like this

translate([-20,0,0])

polygon([

[0,-5],

[0,5*cos(10*0)],

[3,5*cos(10*3)],

[6,5*cos(10*6)],

[9,5*cos(10*9)],

[12,5*cos(10*12)],

[15,5*cos(10*15)],

[18,-5]

]);

comes out with jagged edges as a result of additional intermediate coordinates if you try to do it like this

for (i = [0:3:18])

for (j = [0:3:18])

polygon([

[0,-5],

[i,5*cos(10*j)],

[18,-5]

]);

I have tried “i“ alone and with “j“ as above, but both give different funny results.

A polygon with a cosine shape like this translate(\[-20,0,0\]) polygon(\[ \[0,-5\], \[0,5\*cos(10\*0)\], \[3,5\*cos(10\*3)\], \[6,5\*cos(10\*6)\], \[9,5\*cos(10\*9)\], \[12,5\*cos(10\*12)\], \[15,5\*cos(10\*15)\], \[18,-5\] \]); comes out with jagged edges as a result of additional intermediate coordinates if you try to do it like this for (i = \[0:3:18\]) for (j = \[0:3:18\]) polygon(\[ \[0,-5\], \[i,5\*cos(10\*j)\], \[18,-5\] \]); I have tried “i“ alone and with “j“ as above, but both give different funny results.
JB
Jordan Brown
Sat, Sep 17, 2022 10:43 PM

I've indented your program for clarity.

On 9/17/2022 3:30 PM, mikeonenine@web.de wrote:

A polygon with a cosine shape like this

translate([-20,0,0])
    polygon([
[0,-5],
[0,5cos(100)],
[3,5cos(103)],
[6,5cos(106)],
[9,5cos(109)],
[12,5cos(1012)],
[15,5cos(1015)],
[18,-5]
]);

comes out with jagged edges as a result of additional intermediate
coordinates if you try to do it like this

for (i = [0:3:18])
for (j = [0:3:18])
polygon([
[0,-5],
[i,5cos(10j)],
[18,-5]
]);

I have tried “i“ alone and with “j“ as above, but both give different
funny results.

You are stepping i from 0 to 18 by 3 (0, 3, 6, 9, 12, 15, 18), and for
each of those you are stepping j from 0 18 by three, for a total of 49
polygons.

The first thing to do is to get rid of j entirely.  You want your points
to have the same value for x as is used to calculate y.

This would be closer (but still isn't right):

for (i = [0:3:18])
    polygon([
        [0,-5],
        [i,5*cos(10*i)],
        [18,-5]
    ]);

But that's still not right.  It's creating 7 overlapping polygons:  one
where i=0, one where i=3, et cetera.

What you want is one polygon with a list comprehension that generates
points:

polygon([
    [0,-5],
    for (i = [0:3:18]) [i,5*cos(10*i)],
    [18,-5]
]);

(You could also do it by creating 6 polygons side-by-side, but that
would be harder and less correct.

I've indented your program for clarity. On 9/17/2022 3:30 PM, mikeonenine@web.de wrote: > > A polygon with a cosine shape like this > > translate([-20,0,0]) >     polygon([ > [0,-5], > [0,5*cos(10*0)], > [3,5*cos(10*3)], > [6,5*cos(10*6)], > [9,5*cos(10*9)], > [12,5*cos(10*12)], > [15,5*cos(10*15)], > [18,-5] > ]); > > comes out with jagged edges as a result of additional intermediate > coordinates if you try to do it like this > > for (i = [0:3:18]) > for (j = [0:3:18]) > polygon([ > [0,-5], > [i,5*cos(10*j)], > [18,-5] > ]); > > I have tried “i“ alone and with “j“ as above, but both give different > funny results. > You are stepping i from 0 to 18 by 3 (0, 3, 6, 9, 12, 15, 18), and for *each* of those you are stepping j from 0 18 by three, for a total of 49 polygons. The first thing to do is to get rid of j entirely.  You want your points to have the same value for x as is used to calculate y. This would be closer (but still isn't right): for (i = [0:3:18]) polygon([ [0,-5], [i,5*cos(10*i)], [18,-5] ]); But that's still not right.  It's creating 7 overlapping polygons:  one where i=0, one where i=3, et cetera. What you want is *one* polygon with a list comprehension that generates points: polygon([ [0,-5], for (i = [0:3:18]) [i,5*cos(10*i)], [18,-5] ]); (You could also do it by creating 6 polygons side-by-side, but that would be harder and less correct.
M
mikeonenine@web.de
Sat, Sep 17, 2022 11:40 PM

Ah, so that’s how you do it!

I thought the “for” had to stay outside the “polgon”. So I was getting multiple polygons?

I had previously built up the shape from a series of bars, but a) that produces steps, moire fringes and stuff and b) my poor old computer struggles to render it.

Thanks.

Ah, so that’s how you do it! I thought the “for” had to stay outside the “polgon”. So I was getting multiple polygons? I had previously built up the shape from a series of bars, but a) that produces steps, moire fringes and stuff and b) my poor old computer struggles to render it. Thanks.
JB
Jordan Brown
Sun, Sep 18, 2022 1:32 AM

On 9/17/2022 4:40 PM, mikeonenine@web.de wrote:

I thought the “for” had to stay outside the “polgon”. So I was getting
multiple polygons?

Yes.

In general,

for (...) something();

makes multiple somethings.  If they are all overlapping, as here, that
may not be obvious.

Documentation: 
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Conditional_and_Iterator_Functions#For_loop

The construct I used, a "list comprehension", is a similar-looking
construct that helps in building lists, generating multiple values.

There are a couple of variations of list comprehensions, but this one
looks like

[
    for (...) expression
]

and generates multiple entries in the list.

Documentation:
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions#for

I had previously built up the shape from a series of bars, but a) that
produces steps, moire fringes and stuff

You can do it, and it's not awful, but it's harder than building it as
one polygon.  You have to have each bar be a polygon with the top
corners at the two different heights.

step = 3;
yscale = 5;
function f(x) = yscale*cos(10*x);
translate([20,0,0]) for (x=[0:step:18-step]) {
    polygon([
        [ x, -yscale ],
        [ x, f(x) ],
        [ x+step, f(x+step) ],
        [ x+step, -yscale ]
    ]);
}

and b) my poor old computer struggles to render it.

There's probably something else going on.  My computer is ten years old
and was only $600 then, and it will do five different variations on this
program in under a tenth of a second - even including your original that
created 49 overlapping polygons.  Even a variation that does it all with
squares, at 0.01 steps so there's 1800 of them, F5 previews in about two
tenths of a second and F6 renders in under four tenths.

If you weren't properly understanding how "for" loops interact, you
could easily have multiplied up the number of polygons to something
unreasonable.

But also:  so far we're talking about 2D figures, and 2D rendering is
enormously faster than 3D rendering.  If I change those 1800 squares to
cubes, it takes almost 7 minutes to render.

On 9/17/2022 4:40 PM, mikeonenine@web.de wrote: > > I thought the “for” had to stay outside the “polgon”. So I was getting > multiple polygons? > Yes. In general, for (...) something(); makes multiple somethings.  If they are all overlapping, as here, that may not be obvious. Documentation:  https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Conditional_and_Iterator_Functions#For_loop The construct I used, a "list comprehension", is a similar-looking construct that helps in building lists, generating multiple values. There are a couple of variations of list comprehensions, but this one looks like [ for (...) expression ] and generates multiple entries in the list. Documentation: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions#for > I had previously built up the shape from a series of bars, but a) that > produces steps, moire fringes and stuff > You can do it, and it's not awful, but it's harder than building it as one polygon.  You have to have each bar be a polygon with the top corners at the two different heights. step = 3; yscale = 5; function f(x) = yscale*cos(10*x); translate([20,0,0]) for (x=[0:step:18-step]) { polygon([ [ x, -yscale ], [ x, f(x) ], [ x+step, f(x+step) ], [ x+step, -yscale ] ]); } > and b) my poor old computer struggles to render it. > There's probably something else going on.  My computer is ten years old and was only $600 then, and it will do five different variations on this program in under a tenth of a second - even including your original that created 49 overlapping polygons.  Even a variation that does it all with squares, at 0.01 steps so there's 1800 of them, F5 previews in about two tenths of a second and F6 renders in under four tenths. If you weren't properly understanding how "for" loops interact, you could easily have multiplied up the number of polygons to something unreasonable. But also:  so far we're talking about 2D figures, and 2D rendering is enormously faster than 3D rendering.  If I change those 1800 squares to cubes, it takes almost 7 minutes to render.
T
terrypingm@gmail.com
Sun, Sep 18, 2022 8:36 AM

Please excuse a purely test reply via Empathy. I find it so much easier to read posts here, in sequence, with minimal superfluous text, neatly presented.

Please excuse a purely test reply via Empathy. I find it so much easier to read posts here, in sequence, with minimal superfluous text, neatly presented.
M
mikeonenine@web.de
Sun, Sep 18, 2022 7:29 PM

This was the original version:

e=10;

for (i = [0:1:180])

rotate_extrude()

translate([i/180*2*(e/2-0.5),3+0.1])

offset(0.1)

square([0.9, 2.5+1.5*sin(i-90)-0.2]);

On its own, it previews instantaneously, so the delay must come from something else, or from the combination of everything else. But the polygon version (after rotate_extrude) looks better without those fringes/interference patterns.

This was the original version: e=10; for (i = \[0:1:180\]) rotate_extrude() translate(\[i/180\*2\*(e/2-0.5),3+0.1\]) offset(0.1) square(\[0.9, 2.5+1.5\*sin(i-90)-0.2\]); On its own, it previews instantaneously, so the delay must come from something else, or from the combination of everything else. But the polygon version (after rotate_extrude) looks better without those fringes/interference patterns.
JB
Jordan Brown
Mon, Sep 19, 2022 1:22 AM

On 9/18/2022 12:29 PM, mikeonenine@web.de wrote:

This was the original version:

e=10;
for (i = [0:1:180])
rotate_extrude()
translate([i/1802(e/2-0.5),3+0.1])
offset(0.1)
square([0.9, 2.5+1.5*sin(i-90)-0.2]);

On its own, it previews instantaneously, so the delay must come from
something else, or from the combination of everything else. But the
polygon version (after rotate_extrude) looks better without those
fringes/interference patterns.

[ Indented your original for clarity ]

You are combining 180 rotate-extruded squares.

Note that the first three cause errors because they extend left of the Y
axis.

On my system, that version previewed in two tenths of a second, and
rendered in 7m30s.

Moving the "for" inside the rotate_extrude, so that you combine the 180
squares and then extrude that, previewed and rendered in about a tenth
of a second.

e=10;

rotate_extrude()
    for (i = [3:1:180])
        translate([i/180*2*(e/2-0.5),3+0.1])
            offset(0.1)
                square([0.9, 2.5+1.5*sin(i-90)-0.2]);

(And I skipped the first three because they caused problems because they
extend left of the Y axis.)

But as you may have figured out, what you really want to do is to build
a single polygon and rotate_extrude it, something like:

e=10;

rotate_extrude()
    polygon([
        [0,0],
        for (i = [0:1:180]) [
            i/180*2*(e/2-0.5),
            2.5+1.5*sin(i-90)-0.2
        ],
        [ e-1, 0 ]
    ]);
On 9/18/2022 12:29 PM, mikeonenine@web.de wrote: > > This was the original version: > > e=10; > for (i = [0:1:180]) > rotate_extrude() > translate([i/180*2*(e/2-0.5),3+0.1]) > offset(0.1) > square([0.9, 2.5+1.5*sin(i-90)-0.2]); > > On its own, it previews instantaneously, so the delay must come from > something else, or from the combination of everything else. But the > polygon version (after rotate_extrude) looks better without those > fringes/interference patterns. > [ Indented your original for clarity ] You are combining 180 rotate-extruded squares. Note that the first three cause errors because they extend left of the Y axis. On my system, that version previewed in two tenths of a second, and rendered in 7m30s. Moving the "for" inside the rotate_extrude, so that you combine the 180 squares and then extrude that, previewed and rendered in about a tenth of a second. e=10; rotate_extrude() for (i = [3:1:180]) translate([i/180*2*(e/2-0.5),3+0.1]) offset(0.1) square([0.9, 2.5+1.5*sin(i-90)-0.2]); (And I skipped the first three because they caused problems because they extend left of the Y axis.) But as you may have figured out, what you really want to do is to build a single polygon and rotate_extrude it, something like: e=10; rotate_extrude() polygon([ [0,0], for (i = [0:1:180]) [ i/180*2*(e/2-0.5), 2.5+1.5*sin(i-90)-0.2 ], [ e-1, 0 ] ]);
MM
Michael Marx
Mon, Sep 19, 2022 8:36 AM

[ Indented your original for clarity ]

Another unfixed problem. Reported. https://gitlab.com/brianemwd/empathy/-/issues/12

AFAIK there is no good way to get nice formats via Empathy posts. Why it is not recommended.

I think I'll I've had my fill on this (Empathy) topic now.


From: Jordan Brown []
Sent: Mon, 19 Sep 2022 11:23
To: OpenSCAD general discussion; mikeonenine@web.de
Subject: [OpenSCAD] Re: "for" generates funny intermediate values in polygons

On 9/18/2022 12:29 PM, mike mailto:mikeonenine@web.de  wrote:

This was the original version:

e=10;
for (i = [0:1:180])
rotate_extrude()
translate([i/1802(e/2-0.5),3+0.1])
offset(0.1)
square([0.9, 2.5+1.5*sin(i-90)-0.2]);

On its own, it previews instantaneously, so the delay must come from something else, or from the combination of everything else. But the polygon version (after rotate_extrude) looks better without those fringes/interference patterns.

[ Indented your original for clarity ]

You are combining 180 rotate-extruded squares.

Note that the first three cause errors because they extend left of the Y axis.

On my system, that version previewed in two tenths of a second, and rendered in 7m30s.

Moving the "for" inside the rotate_extrude, so that you combine the 180 squares and then extrude that, previewed and rendered in about a tenth of a second.

e=10;

rotate_extrude()
for (i = [3:1:180])
translate([i/1802(e/2-0.5),3+0.1])
offset(0.1)
square([0.9, 2.5+1.5*sin(i-90)-0.2]);

(And I skipped the first three because they caused problems because they extend left of the Y axis.)

But as you may have figured out, what you really want to do is to build a single polygon and rotate_extrude it, something like:

e=10;

rotate_extrude()
polygon([
[0,0],
for (i = [0:1:180]) [
i/1802(e/2-0.5),
2.5+1.5*sin(i-90)-0.2
],
[ e-1, 0 ]
]);

--
This email has been checked for viruses by AVG antivirus software.
www.avg.com

> [ Indented your original for clarity ] Another unfixed problem. Reported. https://gitlab.com/brianemwd/empathy/-/issues/12 AFAIK there is no good way to get nice formats via Empathy posts. Why it is not recommended. I think I'll I've had my fill on this (Empathy) topic now. _____ From: Jordan Brown [] Sent: Mon, 19 Sep 2022 11:23 To: OpenSCAD general discussion; mikeonenine@web.de Subject: [OpenSCAD] Re: "for" generates funny intermediate values in polygons On 9/18/2022 12:29 PM, mike <mailto:mikeonenine@web.de> wrote: This was the original version: e=10; for (i = [0:1:180]) rotate_extrude() translate([i/180*2*(e/2-0.5),3+0.1]) offset(0.1) square([0.9, 2.5+1.5*sin(i-90)-0.2]); On its own, it previews instantaneously, so the delay must come from something else, or from the combination of everything else. But the polygon version (after rotate_extrude) looks better without those fringes/interference patterns. [ Indented your original for clarity ] You are combining 180 rotate-extruded squares. Note that the first three cause errors because they extend left of the Y axis. On my system, that version previewed in two tenths of a second, and rendered in 7m30s. Moving the "for" inside the rotate_extrude, so that you combine the 180 squares and then extrude that, previewed and rendered in about a tenth of a second. e=10; rotate_extrude() for (i = [3:1:180]) translate([i/180*2*(e/2-0.5),3+0.1]) offset(0.1) square([0.9, 2.5+1.5*sin(i-90)-0.2]); (And I skipped the first three because they caused problems because they extend left of the Y axis.) But as you may have figured out, what you really want to do is to build a single polygon and rotate_extrude it, something like: e=10; rotate_extrude() polygon([ [0,0], for (i = [0:1:180]) [ i/180*2*(e/2-0.5), 2.5+1.5*sin(i-90)-0.2 ], [ e-1, 0 ] ]); -- This email has been checked for viruses by AVG antivirus software. www.avg.com