Using recursion to create smoothed random variation ("red" noise)

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Using recursion to create smoothed random variation ("red" noise)

amundsen
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

A feature I'd like to see... import png or jpeg

boxcarmib
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?
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Using recursion to create smoothed random variation ("red" noise)

adrianv
In reply to this post by amundsen
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(i*360/polygon_steps),sin(i*360/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

> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org





--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: A feature I'd like to see... import png or jpeg

JordanBrown
In reply to this post by boxcarmib
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.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Using recursion to create smoothed random variation ("red" noise)

JordanBrown
In reply to this post by amundsen
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.)


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Using recursion to create smoothed random variation ("red" noise)

amundsen
In reply to this post by adrianv
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(i*360/polygon_steps),sin(i*360/polygon_steps)]];
> polygon(circ+smoothdata(rdata));





--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: A feature I'd like to see... import png or jpeg

tp3
In reply to this post by boxcarmib
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.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten