Keywords: strange attractors
To draw the attractor you will draw pixels one by one. You start with a random (x, y) point, and calculate new coordinates (x', y') using the attractor equation. I suggest to start with a simple attractor with the general form:
where
There are a couple of practical considerations before we start implementing this simple algorithm.
First, how do we choose the parameter values? Unfortunately, not all values will yield a nice-looking attractor. In the next step we will make it easier to explore the parameter
space and find good parameters; for now you can use a=1.19, b=1.195, c=1.4, d=1.365. What about the starting values for x and y? Here the choice is not that important - after all,
we are working with attractors, so our points should eventually converge. Just note that some values (e.g. (0, 0) or (1, 1)) will yield degenerative solution. But as long
as
Secondly, we need to map between our attractor (x, y) values and the rendering window coordinates. Our (x, y) values would be approximately in the (-2, 2) range, so you should ensure that values from this range will be visible in your window.
Lastly, getting a clearly visible attractor pattern may require thousands of points to be drawn. Thus, I suggest drawing O(100s) points in every frame - significantly fewer than that and it will take a long time for the attractor to become clear, significantly more - and it may become oversatured quickly.
The table below shows how the rendering changes with the increasing number of iterations.
Keywords: drag'n'drop
You should be able to get an attractor drawn for specific parameters. To make it easy to explore different shapes yielded by different parameters it will be helpful to be able to modify the params in real time. It would be quite easy to use keyboard or sliders, so we will do something else instead. We'll employ draggable circles to represent pairs of parameters (a, b), positioned at the point (x, y). In this setup, the parameter a (b) will be encoded using the x (y) coordinate of the circle. This will allow us to modify 2 parameters at the same time, and it will make it a bit easier to visualize the change of parameters in time, which we will add in the following steps. Of course, you will need multiple circles to represent your parameters if you have more than 2. Remember to refresh your screen after each parameter adjustment.
Additionally, as in the previous step, you'll need to map values from pixel coordinates to the parameter space.
Keywords: HSV color model
Let's add a few different color modes. For a solid color, let's do black-on-white, white-on-black and color-on-black. How can we expand our color palette further? One approach is to use a point "velocity", which is defined as the distance between the current and previous (x, y) coordinates. This will give you a scalar that can be easily translated into a colorful gradient using the HSV color model.
Keywords: Bezier curve, spline curve, C1 continuity
Now that we've achieved generating appealing static images, our next endeavor is to create smooth animations. This involves rendering a sequence of attractors with slight parameter adjustments and then combining these individual frames into a video. In this step we will work on a smooth parameters change.
The simplest approach would be to change each param by a small constant value. The problem is that eventually the parameters will grow large (in absolute terms), which typically yields less interesting attractors. Ideally, we want the parameters to change smoothly within a reasonable range.
Another approach could be to express parameters as functions of time - for example, one parameter could be defined as
To address these issues we can use geometric shapes like Bezier curves. These curves are defined by a series of points (typically four for cubic curves), where each point influences the shape of the curve. The curve starts at the first point and ends at the last one, with the intermediate points serving as magnets shaping the curve. Each point on the curve can be calculated using a simple formula which depends only on the points themselves and a single parameter
In the previous step we used a circle to represent a pair of parameters. Now, we'll extend this concept by employing Bezier curves. For example, if our attractor has eight parameters, we could define four 2D Bezier curves or a single 8-dimensional curve (and to visualize it you could simply display 4 circles representing pairs of coordinates:
Note: for this step I suggest to start a new sketch instead of expanding the code from the previous step, especially if you haven't worked with Bezier curves before. It will make things simpler, as you will only need to think about the curves, and it will make implementation and debugging easier.
So, let's get to work. First you'd define your curve(s). I suggest to display the control points and lines connecting them, and outline the curve itself (e.g. calculate and draw the points for
We should also allow the curve to "continue" after we reach its end, i.e. when
C0 continuity |
C1 continuity |
And voilà! You now should be able to generate an infinite smooth curve!
infinite.mp4
The last thing to do is to expand your curve to as many dimensions as you have parameters (or simply use multiple 2D curves). At this point the visualization might get somewhat crowded. This is an example of what it might look like with 6 parameters:
final.mp4
Now it is time to combine our single frame drawing with smooth parameter change.
If you are feeling lucky you may use randomized control points, but you are risking getting degenerated attractors for some of the parameters, resulting in a not-that-attractive animation. A better idea might be to provide a series of fixed parameter sets that will guide the animation (you can obtain them by playing with your code from the Step 3 and writing down the parameter values for which you get a nice drawing). You could provide all control points in the successive Bezier curves (which would give you a total control, but would require more work), or just the first and the last ones, randomizing the intermediate ones. In the latter solution you may want to generate random points that are not too far from the end points so that you will obtain a smooth, gently curved line, instead of a "loopy" one.
I suggest to use a "dev" mode, in which you significantly reduce the number of iterations per frame, increase