Hello,
I am trying to use a recursive function within a list comprehension to add
some random component to both x and y coordinates of each point in a polygon
(a circle actually). However I want each random component to be based on the
previous random value in order to smooth the random component (and get some
king of brownian/red noise).
Obviously there are a few things which I don't understand because my code
doesn't provide the expected results : the noise component is not smoothed.
For instance, I am not sure if "n-1" in the function definition means using
the results of the previous iteration in the current one or substracting 1
from n.
Any help would be appreciated!
/
polygon_steps = 100;
random_range = 10;
function smoothrand(n = 0, range = 1) = ( n == 0 ? rands(-range, range,
1)[0] : smoothrand(n-1) * 0.9 + rands(-range * 0.1, range * 0.1, 1)[0] );
start_points = [for(i=[0:polygon_steps])
let(a = smoothrand(1, random_range), b = smoothrand(1, random_range))
[cos(i/polygon_steps * 360) * (0.4 * a + 10), sin(i/polygon_steps * 360) *
(0.4 * b + 10)]
];
polygon(start_points);/
--
Sent from: http://forum.openscad.org/
Have no idea how difficult this would be, but it would be helpful for some projects to be able to import an image file like a png or jpg as a 2 dimensional object, be able to scale and rotate and set luminance. It could then be used for more rapid prototyping of an existing object, or getting things like thread pitch correct… that kind of thing. Anyone else think this worthwhile?
First of all, n-1 means 1 subtracted from n. Why would it mean something
else?
To write a function like this you need to pass the list of all previous
values and then append to it in the recursion.
But I would probably approach this problem differently. The exact details
aren't clear to me for what you're trying to do, but I'd start by
constructing a list of random perturbations. And then I'd write a function
that performs smoothing, which you can do non-recursively. One major fault
(I think) of your idea is that it will have a discontinuity at the start of
the list. To do this right the smoothing needs to wrap around the polygon.
Doing that recursively will be messy. So something along the lines of the
code below which does a 3 point window. An n-point window is going to
require writing a sum function and a function for extracting a sublist from
data, the former which can be done with a matrix vector product and the
latter which can be done with a carefully written loop.
function smoothdata(data) =
let(L=len(data))
[for(i=[0:1:L-1]) (data[(i-1+L)%L]+data[i]+data[(i+1)%L])/3];
rdata = [for(i=[0:1:polygon_steps-1]) rands(-0.1,0.1,2)];
circ = [for(i=[0:1:polygon_steps-1])
[cos(i360/polygon_steps),sin(i360/polygon_steps)]];
polygon(circ+smoothdata(rdata));
amundsen wrote
Hello,
I am trying to use a recursive function within a list comprehension to add
some random component to both x and y coordinates of each point in a
polygon
(a circle actually). However I want each random component to be based on
the
previous random value in order to smooth the random component (and get
some
king of brownian/red noise).
Obviously there are a few things which I don't understand because my code
doesn't provide the expected results : the noise component is not
smoothed.
For instance, I am not sure if "n-1" in the function definition means
using
the results of the previous iteration in the current one or substracting 1
from n.
Any help would be appreciated!
/
polygon_steps = 100;
random_range = 10;
function smoothrand(n = 0, range = 1) = ( n == 0 ? rands(-range, range,
1)[0] : smoothrand(n-1) * 0.9 + rands(-range * 0.1, range * 0.1, 1)[0] );
start_points = [for(i=[0:polygon_steps])
let(a = smoothrand(1, random_range), b = smoothrand(1, random_range))
[cos(i/polygon_steps * 360) * (0.4 * a + 10), sin(i/polygon_steps * 360)
*
(0.4 * b + 10)]
];
polygon(start_points);/
--
Sent from: http://forum.openscad.org/
OpenSCAD mailing list
Discuss@.openscad
--
Sent from: http://forum.openscad.org/
On 10/20/2020 5:34 PM, Hugo Jackson wrote:
Have no idea how difficult this would be, but it would be helpful for some projects to be able to import an image file like a png or jpg as a 2 dimensional object, be able to scale and rotate and set luminance. It could then be used for more rapid prototyping of an existing object, or getting things like thread pitch correct… that kind of thing. Anyone else think this worthwhile?
Are you expecting it to contribute to the geometry, or just to be sort
of a backdrop that you could then line things up with?
One wild-assed thought along those lines would be to import it as the
texture of a 2D object, or even as the texture of a face of a 3D object.
Adrian gave a good idea on how to accomplish your goal.
Here are some thoughts on why what you tried didn't work, in the hopes
of helping you to better understand recursive functions.
On 10/20/2020 5:22 PM, amundsen wrote:
Obviously there are a few things which I don't understand because my
code doesn't provide the expected results : the noise component is not
smoothed.
For instance, I am not sure if "n-1" in the function definition means
using the results of the previous iteration in the current one or
substracting 1 from n.
/
polygon_steps = 100;
random_range = 10;
function smoothrand(n = 0, range = 1) = ( n == 0 ? rands(-range, range,
1)[0] : smoothrand(n-1) * 0.9 + rands(-range * 0.1, range * 0.1, 1)[0] );
start_points = [for(i=[0:polygon_steps])
let(a = smoothrand(1, random_range), b = smoothrand(1, random_range))
[cos(i/polygon_steps * 360) * (0.4 * a + 10), sin(i/polygon_steps * 360) *
(0.4 * b + 10)]
];
polygon(start_points);/
"n-1" means "subtract 1 from n". Always.
"smoothrand(n-1)" means "call smoothrand with one less than n". The
fact that it's being called from inside smoothrand() is irrelevant,
except that you have to ensure that the recursion eventually
terminates. (Which you did.)
First, you're calling smoothrand with n=1, which means that you'll
always get exactly one recursion: once with n=1 and once with n=0. You
might have been thinking of calling it with n=i, so that each call would
recursively calculate the previous value and base its result on that value.
However, second, you're talking about random numbers. If you called
smoothrand(0) and it gave you some number, and then called
smoothrand(1), the two numbers would be unrelated to one another because
when the smoothrand(1) internally called smoothrand(0), it would be
using different random numbers than the first call.
Also, it would be really expensive. I believe you'd have 10,100 calls
to smoothrand. The first point, i=0, would be one call: smoothrand(0).
The second point, i=1, would be two calls: smoothrand(1) and
smoothrand(0). The third point, i=2, three. (That's six so far.) The
100th point would require 100 calls to smoothrand. The total, the sum
of all of the numbers from 1 to 100, is (n²+n)/2, or 5050. Doubled,
because you call it twice. (That's (n^2+n)/2 if you can't see the
superscript properly.)
Thank you @adrianv for this clear and clever solution!
On my way to try some window with 5 points or more...
I was aware of the discontinuity at the start but had no idea on how to
solve this.
Also, it's great to learn that one can combine two sets of values by virtue
of a simple addition in order to set the edges of a polygon, as you do with
the deterministic and the random parts.
adrianv wrote
First of all, n-1 means 1 subtracted from n. Why would it mean something
else?
To write a function like this you need to pass the list of all previous
values and then append to it in the recursion.
But I would probably approach this problem differently. The exact details
aren't clear to me for what you're trying to do, but I'd start by
constructing a list of random perturbations. And then I'd write a
function
that performs smoothing, which you can do non-recursively. One major
fault
(I think) of your idea is that it will have a discontinuity at the start
of
the list. To do this right the smoothing needs to wrap around the
polygon.
Doing that recursively will be messy. So something along the lines of the
code below which does a 3 point window. An n-point window is going to
require writing a sum function and a function for extracting a sublist
from
data, the former which can be done with a matrix vector product and the
latter which can be done with a carefully written loop.
function smoothdata(data) =
let(L=len(data))
[for(i=[0:1:L-1]) (data[(i-1+L)%L]+data[i]+data[(i+1)%L])/3];
rdata = [for(i=[0:1:polygon_steps-1]) rands(-0.1,0.1,2)];
circ = [for(i=[0:1:polygon_steps-1])
[cos(i360/polygon_steps),sin(i360/polygon_steps)]];
polygon(circ+smoothdata(rdata));
--
Sent from: http://forum.openscad.org/
On 21.10.20 02:34, Hugo Jackson wrote:
Have no idea how difficult this would be, but it would be
helpful for some projects to be able to import an image
file like a png or jpg as a 2 dimensional object, be able
to scale and rotate and set luminance.
Sounds like https://github.com/openscad/openscad/issues/194
I suppose it could be quite useful. As mentioned in one of
the notes the Blender feature might be a good reference.
ciao,
Torsten.