Animation of fractal Lozi map
![Lozi map: B = -1.0, C = 0.5 Lozi map: B = -1.0, C = 0.5](https://habrastorage.org/webt/fj/gl/zp/fjglzpyg88mnb1z-cgzzae2mto0.png)
The previous article gave me the idea to write another program that generates image sequences with a different type of fractal. It involved using more complex coefficient animation.
Introduction
The previous article presented a C++ program that generates sequences of fractal images and saves them to PNG files. Let me remind you that each image is created as a result of multiple calls to transform the coordinates of a point {x, y} into new ones using two coefficients coef1 and coef2:
double coef1 = 1.0, coef2 = 0.0; //коэффициенты со значениями по умолчанию 1.0 и 0.0
double fx, fy;
uint32_t col;
for (int j = 0; j < 500; j++) {
fx <- поместить случайное число от 0.0 до 1.0
fy <- поместить случайное число от 0.0 до 1.0
col <- поместить случайный цвет из фиксированной таблицы в 8 цветов
for (int i = 0; i < 1000; i++) {
// получить целочисленные координаты точки {x, y},
// поместить пиксел в выходное изображение с цветом col, затем:
fx = frac(fx + sin(fy - coef2));
fy = frac(fy + cos(fx * coef1));
}
}
As a result of experiments, it turned out that generating image sequences using such an algorithm with a smooth change in the values of the coefficients gives interesting results. For example, if the value of the coefficient is smoothly changed over 2000 steps coef1 in the range from 1.0 before 5.0the picture changes as follows (when viewing, it is better to force the 4K resolution):
In the comments to the article I was kindly provided with examples of images of other fractals with different attractors. I decided to look for algorithms implementing some of them.
Lozi map
In the process of searching I found resourcewhere an example of Python code is given for generating an image using Lozi map. The iterative formula for it looks like this:
![](https://habrastorage.org/webt/it/q2/3f/itq23fnmjbs9i7iqy0xma2opgq0.png)
Based on the program from the previous article, I implemented image generation using a similar algorithm in C++. As in the previous program, each pixel with coordinates {x, y} obtained by the algorithm is not simply placed in the output image buffer, but is mixed with the background color. At the same time, for each point, the number of times each color hit its coordinates is calculated, and when mixing with the background, the weight of each color is taken into account. This gives a “softer” and more pleasing to the eye image.
Example Imagesobtained by such an algorithm, is placed in the title of the article. The values of the coefficients for it are: B = -1.0, C = 0.5. It is possible to obtain completely different images, for example (B = 1.0, C = 1.0):
![Lozi map: B = -1.0, C = 1.0 Lozi map: B = -1.0, C = 1.0](https://habrastorage.org/webt/0q/z9/q7/0qz9q7wsyobkl38ladlxmfmmhmo.png)
Next, I became interested in how the image changes when the coefficient values change smoothly.
Animation Samples
First, I decided to check how the picture changes when the coefficient B changes from 0 to -1 in 20 steps:
![](https://habrastorage.org/webt/9g/-j/ix/9g-jix7xg4iuwvsyn_rzacno_du.gif)
From a thin horizontal line on a black background, the picture gradually turns into the image shown in the header. It is clear that at the beginning of the range, the picture changes more slowly than at the end. Let's see how the coefficient B changes from -0.9 to -1 in the same 20 steps:
![](https://habrastorage.org/webt/rg/7d/n_/rg7dn_gcmbqxgoyk2wln2a03ala.gif)
Here it is already better visible that the image goes to the final one from a picture similar to a spiral galaxy (interestingly, in the article where the example is given, it is written that the Lozi map is a simplified version Henon mapwhich is related to the motion of stars in galaxies). Obviously, the closer the value of the coefficient B is to -1.0, the smaller the step it needs to be changed in order to properly examine the “evolution” of the picture. I came to the idea that it is necessary to break the range of change of the coefficient B from 0 to -1 into several sub-ranges, each of which is smaller than the previous one.
Multiple animation ranges
As a result of my experiments, I compiled a table that shows how many steps and in what range the coefficient B needs to be changed to obtain an interesting change in the image (the value of the coefficient C is constant and equal to 0.5):
Number of steps | Coefficient B (from) | Coefficient B (before) |
250 | -0.01 | -0.6 |
514 | -0.6 | -0.75 |
500 | -0.75 | -0.95 |
500 | -0.95 | -0.99 |
500 | -0.99 | -1.0 |
That is, now the program should change the coefficient not in one pass, but in several successive ones. I have changed the algorithm accordingly, and also added the ability to specify a text file in the command line, each line in which specifies the number of steps in the range and the initial/final values of the coefficients B and C, separated by spaces. File format:
{количество шагов} {значение B от} {значение B до} {значение C от} {значение C до}
пример (изменение B от -0.01 до -0.6 за 250 шагов, значение C равно 0.5):
250 -0.01 -0.6 0.5 0.5
Let's say that coefficient B can now be left at -1.0, and then only coefficient C can be changed. Here, too, after a series of experiments, I got the following table:
Number of steps | Coefficient C (from) | Coefficient C (up to) |
500 | 0.5 | 0.1 |
250 | 0.1 | 0.01 |
500 | 0.01 | 0 |
The full contents of the text file that specifies all the above ranges of changes in the coefficients B and C:
250 -0.01 -0.6 0.5 0.5
514 -0.6 -0.75 0.5 0.5
500 -0.75 -0.95 0.5 0.5
500 -0.95 -0.99 0.5 0.5
500 -0.99 -1.0 0.5 0.5
500 -1.0 -1.0 0.5 0.1
250 -1.0 -1.0 0.1 0.01
500 -1.0 -1.0 0.01 0
1 -1.0 -1.0 0 0
I will write below about where the value 514 came from. The last line, which has only one coefficient value (B = -1, C = 0), generates the last image, in which a rather complex picture degenerates into something that was somewhat unexpected for me (as, incidentally, was the example above with a right triangle):
![Lozi map: B = -1, C = 0 Lozi map: B = -1, C = 0](https://habrastorage.org/webt/w9/nn/ae/w9nnaedjsz3wiq5josv15xzkxrw.png)
It all looks more interesting in motion. When viewing, I recommend forcibly turning on the 4K resolution:
I wasn't interested in posting a silent video. In order to more accurately match some moments in the image changes to the music, I had to select the number of steps in the coefficient animation. That's where the “strange” value 514 in the text file describing the animation ranges came from.
As with the previous program, it is best to watch the original sequence of generated PNG files rather than the YouTube video. For this, it is best to use a fast image viewer FastStone Image Viewer.
Additional acceleration of the program
In the previous article I said that to speed up the program's work a multi-threaded algorithm is implemented, allowing parallel generation of the image sequence in several threads simultaneously. In the comments to the previous article I was rightly pointed out that using an associative container to store pairs of values ”point coordinates -> set of colors” is somewhat redundant.
Instead of placing a pair of coordinates {x, y} and the point color in a container, you can immediately mix the point color with the background in the output image buffer using some weight coefficient. Profiling the program showed that placing in a container really takes a lot of time. I tried to implement a variant of the algorithm in which the point color is immediately mixed with the background. This really speeds up the work several times, but personally I can't say that I like this variant more in terms of the resulting image. Therefore, I left the ability to generate images both with and without an associative container – this is specified by an additional parameter in the command line: -mix – see below.
Ready-made program
I posted the C++ program code in repository. Created for Windows in Microsoft Visual Studio 2019, also successfully built and tested in Ubuntu 22.04.4 LTS (under WSL). Requires C++20 and a library for assembly libpng.
Run from the command line with the following parameters:
lozianim.exe [опции]
-help | show hint for command line options | |
-width {N} | output image width in pixels (1280 by default) | |
-height {N} | output image height in pixels (720 by default) | |
-mix | if this parameter is set, then when generating an image, the color of the point is immediately mixed with the background color, and not placed in an associative container (speeds up the program) | |
-outfolder {path} | path to output folder for saving images | |
-steps {N} | number of output images/animation steps, 1 by default | |
-coef1 {v} | value (float) of coefficient B, -1.0 by default | |
-coef2 {v} | value (float) of coefficient C, 0.5 by default | |
-coef1end {v} | final value (float) of coefficient B, -1.0 by default | |
-coef2end {v} | final value (float) of coefficient C, 1.0 by default | |
-coefin {file} | take the ranges of coefficient changes from the specified text file | |
-threads {N} | number of program execution threads | |
-threads half | use half the number of CPU cores as the number of threads (default) | |
-threads half | use full number of CPU cores | |
When calling help -help the total number of available CPU cores is also shown |
Examples of call:
lozianim.exe -outfolder D:\tmp\png -coef1 -1.0 -coef2 0.1
Creates a single image 'D:\tmp\png\image.png' of size 1280×720 using coefficients: B=-1.0 and C=0.1
lozianim.exe -outfolder D:\tmp\png -steps 1000 -width 1920 -height 1080 -coef1 -0.9 -coef1end -1.0 -coef2 0.5 -coef2end 0.5 -threads max
Creates 1000 images of 1920×1080 size in the folder 'D:\tmp\png' with execution on maximum number of CPU cores. Only animation of B coefficient from -0.1 to -1.0 is used, coefficient C is set to 0.5.
There is a file in the repository lozi.txt – it specifies the animation of the B/C parameters used to generate the sequence of images from which the video is assembled. Running with this file creates images with dimensions of 1920×1080:
lozianim.exe -outfolder D:\tmp\png -width 1920 -height 1080 -coefin lozi.txt
During execution, the program shows which image is currently being generated:
![](https://habrastorage.org/webt/xl/ym/vs/xlymvsfmanzepwlqvs6joqd72h8.png)
Pressing 'q' interrupts the program execution. This will also end saving of the images that are already being generated, so exiting may take some time.
In the same folder in the repository there is a file lozi.html – if you save it and open it in the browser, the generation of one image starts using the same algorithm:
![](https://habrastorage.org/webt/pi/gc/zx/pigczx5mjrio8o8n54qeg6-1l2c.png)
Values of the coefficients B And C can be changed. It should be noted that in the browser the images look somewhat different from those generated by the program.
In the subfolder win There is an archive with a compiled program for Windows, so that those who wish can run it themselves without compilation.