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 "n1" 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(n1) * 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 
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 
In reply to this post by amundsen
First of all, n1 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 nonrecursively. 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 npoint 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:L1]) (data[(i1+L)%L]+data[i]+data[(i+1)%L])/3]; rdata = [for(i=[0:1:polygon_steps1]) rands(0.1,0.1,2)]; circ = [for(i=[0:1:polygon_steps1]) [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 "n1" 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(n1) * 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 
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 wildassed 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 
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:
"n1" means "subtract 1 from n". Always. "smoothrand(n1)" 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 
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, n1 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 nonrecursively. 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 npoint 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:L1]) (data[(i1+L)%L]+data[i]+data[(i+1)%L])/3]; > > rdata = [for(i=[0:1:polygon_steps1]) rands(0.1,0.1,2)]; > circ = [for(i=[0:1:polygon_steps1]) > [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 
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

Free forum by Nabble  Edit this page 