Context Free Art
Contents |
Random walks are a useful tool for placing objects at random locations and for drawing random paths, hair, grass, etc. Random walks can be thought of as a sequence of steps with some randomness to the direction of each step and/or the number of steps.
As seen in the examples below, random walks are implemented in Context Free via one or more step rules. These rules can be seen as continuation and termination rules.
Random walks may draw objects along the path of the walk, via objects drawn within the continuation rules, or only at the end of the walk, via objects drawn within the terminal rules.
As well as random walks being used in the xy coordinate plane, random walks can also be used in the parameter spaces of Context Free. For instance, a random walk on the "hue" parameter will result in a sequence of hues that move in steps away from a particular value, and the hue in the terminal rule will have a degree of randomness to it.
There are several different techniques that can be used when creating random walks. In this section we'll take a look at each of them.
Probably the easiest way of generating a random walk is moving up, down, left and right randomly:
The color commands (h, sat, b) are just for visualization, of course.
The walk starts at the black dot in the red area and ends at the black dot in the green area. It works by randomly moving either up, down, left or right after placing a sphere on the canvas to mark the trail. With a certain (small) probability the last rule is called, which stops the recursion since it does not include a call to the walk rule.
There are two ways to tweak this technique to suit your needs: To increase the length of the trail (i.e. the number of steps) simply reduce the probability of the last rule. Increasing its probability will, in contrast, make the paths shorter. It is also possible to change the size of the step we make at each call of walk (which is .25 in the code above). That way you can make the path spread more in the x direction, etc. Note that if you make the step size too big then each single circle will be distinguishable. This may or may not be what you're looking for.
You don't need to ouput any trail if you don't want to: The following code uses several random walks to randomly place some circles on the canvas.
Note that the probability of the last rule has been increased. This means that the random walks stop earlier and thus are shorter.
Trails produced by this technique usually look rather irregular and not as clean as those produced by the techniques below. But since the technique is so simple and easily adapted to other needs (e.g. to random walks which are more spread out in the x than in the y direction) it is still a handy tool, especially for random placement of objects.
|
|
|
Random walks can also be constructed using random directions. A nice example is Random Walk by Pakin. For this technique we need to be able to choose a random angle at each step -- take a look at the "rotating by random angles" tutorial" if you're not sure how to do this. Using the random angle technique, the code is straightforward:
At each step, we first draw an arrow, and then call random_rotate_1, offset by a certain distance in the x direction. The random rotate technique will always call random_rotate_7 at the end, and that is where we continue our walk by calling walk again.
In this basic form there's not much room for modifications. You can certainly tweak the random rotation code, e.g. to only rotate from -45 to 45 degrees each time. A nice twist would be to add a random step length, too: You can use a similar technique as for the random rotation, and then first rotate by a random angle, then step forward by a random length. As before, the length of the whole trail can be changed by modifiying the probability of the empty walk rule.
Another possibility is to use rotations for a random walk. The idea is to walk forward in a curve to the left, as if you wanted to walk in a circle or spiral. Then, after some time, you turn right and break out of your circle/spiral. Obviously after some time of walking to the right we change direction again, etc. Ribbons 2 by epmoyer is a beautiful example of this technique, and the following code is largely based on it:
Each direction (clockwise and counterclockwise) consists of three rules: The first simply keeps on walking in the same direction after leaving a trail. The second switches to the other direction, and the last stops the recursion.
If you decrease the probabilities of the second rules, then directions won't switch that often. If you decrease the angle of the rotation, then the trail will become straighter. As always, changing the probability of the empty rules changes the length of the walk.
|
|
|
|
It is sometimes useful to include reflections in random walks. Rules with reflections in them remove the need for separate rules for turning left and turning right (or curving clockwise or counterclockwise). For instance, in the above example, the first walk_clockwise rule draws a dot, and then creates a new instance of itself moves .25 unit to the right (in current coordinates) and rotated 5 degrees downwards. The corresponding rule in walk_counterclockwise has a 5 degree upward rotation. These are the mirror images of each other in the x-axis. Since the "flip θ" transformation reflects in a line at angle θ to the x-axis, we use "flip 0" for the flip in the x-axis. Consequently, we can replace the second walk_clockwise rule with a rule that invokes a "flip 0" transformation. Then the walk_counterclockwise rules are not required.
startshape walk rule walk { dot { } walk { x .25 r 5 z 1 } } rule walk 0.1 { walk { flip 0} } rule walk 0.001 { } rule dot { CIRCLE { } CIRCLE { s .9 sat -1 b 1 z .1 } }
|
|
|
|
When using random walks for random object placement, one problem is that the distribution of objects is difficult to control: more objects will be placed close to the initial point, since short random walks are more likely than long ones. This creates a central cluster. Moreover there will be occasional "outlier" objects where a long random walk has placed an object far from its intended location. Theoretically, the terminal points of these random walks such will approximately follow a Gaussian distribution.
startshape S rule S{ SQUARE { s 10 b 1 sat 0.5} 100*{} walk{} } rule walk{ walk { x 1} } rule walk{ walk{ r 223}} rule walk 0.1{ payload {} } rule payload{ CIRCLE { a -0.7 }} |
The central cluster can be broadened using a larger step size and smaller termination probability, but at the expense of more spread outside the target region.
startshape S rule S{ SQUARE { s 10 b 1 sat 0.5} 100*{} walk{} } rule walk{ walk { x 3} } rule walk{ walk{ r 223}} rule walk 0.03{ payload {} } rule payload{ CIRCLE { a -0.7 }} |
Both issues can be addressed by tiling the design. This method can create a distribution of terminal points that is not discernibly different from a uniform distribution of points.
startshape S tile{ s 10 } rule S{ SQUARE { s 9.9 b 1 sat 0.5} 100*{} walk{} } rule walk{ walk { x 3} } rule walk{ walk{ r 223}} rule walk 0.01{ payload {} } rule payload{ CIRCLE { a -0.7 }} |
|
|
|
|
|
|