Creating fractals in MQL5 using the Iterative Function System (IFS) - MetaTrader 5 Expert
























































There are many programs that allow the creation of self-similar sets, defined as iterative function systems (IFS). See for example Fractint , Fractal Designer or IFS Matlab Generator . Thanks to the speed of the MQL5 language and the possibility of using graphical objects, these beautiful collections are available in the MetaTrader 5 client terminal.
This bone morphogenetic protein library, developed by Dmitri (Integer) provides new graphics opportunities and greatly simplifies the creation of graphic images. This library was awarded and received a special award from MetaQuotes Software Company .
In this publication we will consider an example of collaboration with the Bone Morphogenetic Protein Library. Additionally, we will introduce algorithms for creating fractal sets using iterative function systems.
1. Affine transformation of plane
The affine transformation of the plane is a mapping
. In general, affine 2D transformations can be defined using some
matrix sum
, vector. Transform the point with coordinates (x,y) to other points
Use linear transformation:

The transformation must be non-singular, i.e.
. Affine transformation changes size
Second-rate.
Affine transformations do not change the structure of a geometric object (lines transform into lines), AT allows describing simple "deformations" of objects, such as rotations, scaling and translations.
Example of affine plane transformation:

2) " Plane scaling" and
and
Coefficients (X and Y axes):

3) Translate the aircraft
vector:

This shrinkage mapping is key (see Hutchinson results).
if
and
There are coordinates
and
and
is a metric (for example, the Euclidean metric:
). An affine transformation is called a contraction if
, Where
.
Here is an example of affine transformation:


2. Similarity transformation
A fractal is constructed as follows: some (simple) geometric object (section, triangle, square) is divided into N pieces, of which M are used to further "construct" the set (if N=M, we get integer dimensions of the resulting set). Furthermore, this process is repeated again and again for each piece.
Classic fractal:
part:
Fractal has a self-similar structure, and some fractals can be defined by multiple similar transformations. The structure of the affine transformation depends on the way the fractal is constructed.
As you will see further, it is very simple and the only problem we have to solve is to describe only the first iteration of the fractal construction and find the corresponding set of affine transformations.
Suppose we have some collections. According to the fractal creation algorithm, we need to shrink it, rotate it and "put it somewhere". The problem is to describe this process using affine transformations, i.e. we need to find matrices and vectors.
It is easy to show that it is enough to just take 3 points of the initial set (non-trivial) and transform them into 3 corresponding points of the "reduced" set. This transformation will produce 6 linear equations, allowing us to find a, b, c, d, e, f as solutions.
Let's show it. think
The triangle is transformed into
triangle.
By solving the linear system of equations, we will be able to obtain the a, b, c, d, e and f coefficients:

Example: Sierpinski gasket:

The coordinates of the point are:
We have 3 transformations:
The system of linear equations looks like this:
The solution is:
,
, 
We have found the coefficients of three affine transformations. Furthermore, we will use them to create self-similar sets.
3. Create fractals using an iterative function system
This iterative function system (IFS) is a set of affine contractions
Where
- is "weight". Each IFS function is defined by 7 numbers:
, Where
The weight is used as the probability of the nth transformation during the iteration process. It's better to define their values, proportional to contraction:
.
Let us consider a fractal construction algorithm using iterative function systems (see also Chaos Games ).
We first need to get some initial points with coordinates
. Next, we randomly select some contractions and plot the points
. Again, let's randomly choose an abbreviation
and plot
. Finally we will have
as a set of points.
The choice of shrinkage depends on its "probability". If we repeat this process (for example, about 30000 points) and plot the resulting set, we will see its structure, albeit a stochastic process.
Here is an example of a Sierpinski gasket:

Figure 1. Sierpinski gasket generated using IFS coefficients calculated in Chapter 2
//+------------------------------------------------------------------+ //| IFS_Sierpinski_Gasket.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #propertycopyright "Copyright 2011, MetaQuotes Software Corp." #Attribute link "https://www.mql5.com" #Attribute version "1.00" //-- File containing cIntBMP class #include//-- Sierpinski gasket IFS coefficient //-- (a,b,c,d) matrix Doubled IFS_a[ 3 ] = { 0.50 , 0.50 , 0.50 }; Doubled IFS_b[ 3 ] = { 0.00 , 0.00 , 0.00 }; Doubled IFS_c[ 3 ] = { 0.00 , 0.00 , 0.00 }; Doubled IFS_d[ 3 ] = { 0.50 , 0.50 , 0.50 }; //-- (e,f) vector Doubled IFS_e[ 3 ] = { 0.00 , 0.00 , 0.50 }; Doubled IFS_f[ 3 ] = { 0.00 , 0.50 , 0.50 }; //-- "Probability" of the transformation, multiplied by 1000 Double IFS_p[ 3 ]={ Chapter 333 , Chapter 333 , Chapter 333 }; Double problem [ 3 ]; // Probs array - used to select IFS transform cIntBMP bmp; // cIntBMP class instance integer scale = 350 ; // scale factor //+------------------------------------------------------------------+ //|Expert initialization function | //+------------------------------------------------------------------+ Integer initialization () { //-- Prepare Probs array double m = 0 ; for ( integer i = 0 ; i < array_size (ifs_p); i++) { Probs[i]=IFS_p[i]+m; m=m+IFS_p[i]; } //-- BMP image size integer X size = 500 ; Integer Y size = 400 ; // -- Create BMP image 0 ; Double y0= 0 ; double x,y; //-- number of points to calculate (more points - detailed image) integer points = 1500000 ; //-- calculation set for ( integer i = 0 ; i < points; i++) { // Select an IFS transform with probability, proportional to the defined ratio double prb= 1000 *( rand ()/ 32767.0an>); for ( integer k= 0 ; k< array size (IFS_p); k++) { if (prb<= probability[k]) { // Affine transformation x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k]; y = IFS_c[k] * x0 + IFS_d [k] * y0 + IFS_f [k]; // Coordinates before updating x0 = x ; y0 = y ; // Convert to BMP image coordinates // (note the Y axis in cIntBMP) integer sc 0 && scX = 0 &&scY break; } } } //-- Save the image to the file bmp.save( "bmpimg" , true ); //-- Plot the image on the chart bmp.display( 0 , 0 , "bmpimg" , "ibmpimg" ); //--- Return ( 0 ); } //+--------------------------------------------------------------------------------+ //|Expert de-initialization function | //+------------------------------------------------------------------+ Blank solution initialization ( const integer cause) { //--- Remove the image object from the chart delete( 0 , "IFSA" ); //---Delete the file bmp. delete( "bmpimg" , true ); } //+------------------------------------------------------------------+
If we set the scale to 1350, increase the number of iterations to 15000000, and change the offset of the initial point:
integer scX = math wheel (X size/ 2 + (x- 0.75 )*scale); integer SCY = math wheel (Y size/ 2 + (y- 0.75 )*scale);
We'll be able to see the zoomed area of the collection. As you can see (Figure 2), it has a self-similar structure:

Figure 2. Magnified area of Sierpinski gasket
Let's consider the famous Barnsley's Fern , proposed by Michael Barnsley . The situation is more complicated.

Figure 3. Barnsley ferns
The code is similar, but in this case we have 4 IFS shrinks with different weights.
//+------------------------------------------------------------------+ //| IFS_fern.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #propertycopyright "Copyright 2011, MetaQuotes Software Corp." #Attribute link "https://www.mql5.com" #Attribute version "1.00" #include//-- Barnsley Fern IFS coefficient //-- (a,b,c,d) matrix Doubled IFS_a[ 4 ] = { 0.00 , 0.85 , 0.20 , - 0.15 }; Doubled IFS_b[ 4 ] = { 0.00 , 0.04 , - 0.26 , 0.28 }; Doubled IFS_c[ 4 ] = { 0.00 , - 0.04 , 0.23 , 0.26 }; doubled IFS_d[ 4 ] = { 0.16 , 0.85 , 0.22 , 0.24 }; //-- (e,f) vector Doubled IFS_e[ 4 ] = { 0.00 , 0.00 , 0.00 , 0.00 }; Doubled IFS_f[ 4 ] = { 0.00 , 1.60 , 1.60 , 0.00 }; //-- "Probability" of the transformation, multiplied by 1000 Double IFS_p[ 4 ] = { 10 , 850 , 70 , 70 }; Double problem[ 4 ]; cIntBMP bmp; integer size = 50 ; //+------------------------------------------------------------------+ //|Expert initialization function | //+------------------------------------------------------------------+ Integer initialization () { double meters = 0 ; for ( integer i = 0 ; i < array_size (ifs_p); i++) { Probs[i]=IFS_p[i]+m; m=m+IFS_p[i]; } Integer X size = 600 ; integer Y size = 600 ; bmp.Create(XSize,YSize,clrSeashell); bmp.DrawRectangle( 0 , 0 ,X size- 1 ,Y size- 1 ,clrBlack); Double x0 = 0 ; Double y0= 0 ; Double x, y; Integer points = 250000 ; for ( integer i = 0 ; i < dot; i++) { Double prb = 1000 *( rand ()/ 32767.0 ); for ( integer k = 0 ; k < array size (IFS_p); k++) { if (prb<=probability[k]) { x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k]; y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f [k]; x0 = x ; y0 = y ; integer sc = 0 &&scY rest; } } } bmp.save( "bmpimg" , true ); bmp.display( 0 , 0 , "bmpimg" , "ibmpimg" ); //--- return ( 0 ); } //+------------------------------------------------------------------+ //|Expert de-initialization function | //+------------------------------------------------------------------+ Blank solution initialization ( const integer reason) { object delete ( 0 , "IFSA" ); bmp.delete( "bmpimg" , true ); } //+------------------------------------------------------------------+
Remarkably, such a complex structure can be defined with only 28 numbers.
If we increase the scale to 150 and set the number of iterations to 1250000, we will see the scaled fragment:

Figure 4. Fragment of Barnsley fern
As you can see, the algorithm is general and it allows you to generate different sets of fractals.
The next example is the Sierpinski Carpet, defined by the following IFS coefficients:
//-- Sierpinski gasket IFS coefficient Doubled IFS_a[ 8 ] = { 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 }; Doubled IFS_b[ 8 ] = { 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 }; Double IFS_c[ 8 ] = { 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 }; Double IFS_d[ 8 ] = { 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 , 0.333 }; Double IFS_e[ 8 ] = {- 0.125 , - 3.375 , - 3.375 , 3.125 , 3.125 , - 3.375 , - 0.125 , 3.125 }; doubled IFS_f[ 8 ] = { 6.75 , 0.25 , 6.75 , 0.25 , 6.75 , 3.5 , 0.25 , 3.50 }; //-- "probability", multiplied by 1000 Double IFS_p[ 8 ]={ 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 };

Figure 5. Sierpinski carpet
In Chapter 2 we considered the algorithm for calculating the IFS shrinkage coefficient.
Let's consider how to create "fractal words". In Russian, the word "fractal" looks like:

Figure 6. The word “fractal” in Russian
In order to find the IFS coefficients, we need to solve the corresponding linear system. The solution is:
//-- IFS coefficient of the Russian word "fractal" Double IFS_a[ 28 ]= { 0.00 , 0.03 , 0.00 , 0.09 , 0.00 , 0.03 , - 0.00 , 0.07 , 0.00 , 0.07 , 0.03 , 0.03 , 0.03 , 0.00 , 0.04 , 0.04 , - 0.00 , 0.09 , 0.03 , 0.03 , 0.03 , 0.03 , 0.03 , 0.00 , 0.05 , - 0.00 , 0.05 , 0.00 }; Double IFS_b[ 28 ]= { - 0.11 , 0.00 , 0.07 , 0.00 , - 0.07 , 0.00 , - 0.11 , 0.00 , - 0.07 , 0.00 , - 0.11 , 0.11 , 0.00 , - 0.14 , - 0.12 , 0.12 , - 0.11 , 0.00 , - 0.11 , 0.11 , 0.00 , - 0.11 , 0.11 , - 0.11 , 0.00 , - 0.07 , 0.00 , - 0.07 }; Double IFS_c[ 28 ]= { 0.12 , 0.00 , 0.08 , - 0.00 , 0.08 , 0.00 , 0.12 , 0.00 , 0.04 , 0.00 , 0.12 , - 0.12 , 0.00 , 0.12 , 0.06 , - 0.06 , 0.10 , 0.00 , 0.12 , - 0.12 , 0.00 , 0.12 , - 0.12 , 0.12 , 0.00 , 0.04 , 0.00 , 0.12 }; Double IFS_d[ 28 ]= { 0.00 , 0.05 , 0.00 , 0.07 , 0.00 , 0.05 , 0.00 , 0.07 , 0.00 , 0.07 , 0.00 , 0.00 , 0.07 , 0.00 , 0.00 , 0.00 , 0.00 , 0.07 , 0.00 , 0.00 , 0.07 , 0.00 , 0.00 , 0.00 , 0.07 , 0.00 , 0.07 , 0.00 }; Double IFS_e[ 28 ]= { - 4.58 , - 5.06 , - 5.16 , - 4.70 , -n class="number">4.09 , - 4.35 , - 3.73 , - 3.26 , - 2.76 , - 3.26 , - 2.22 , - 1.86 , - 2.04 , - 0.98 , - 0.46 , - 0.76 , 0.76 , 0.63 , 1.78 , 2.14 , 1.96 , 3.11 , 3.47 , 4.27 , 4.60 , 4.98 , 4.60 , 5.24 }; Double IFS_f[ 28 ]= { 1.26 , 0.89 , 1.52 , 2.00 , 1.52 , 0.89 , 1.43 , 1.96 , 1.69 , 1.24 , 1.43 , 1.41 , 1.11 , 1.43 , 1.79 , 1.05 , 1.32 , 1.96 , 1.43 , 1.41 , 1.11 , 1.43 , 1.41 , 1.43 , 1.42 , 1.16 , 0.71 , 1.43 }; //-- "Probability", multiplied by 1000 double IFS_p[ 28 ]= { 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 , 35 };
As a result, we will get the following image:

Figure 7. Self-similar words
The complete source code can be found in ifs_fractals.mq5.
If we zoom in on the set, we see a self-similar structure:

Figure 8. Zoom area of the collection
IFS-based self-similar sets can use Fractal Designer .
We have already discussed the topic of creating fractal sets using iterative function systems. Thanks to the Bone Morphogenetic Protein Library, the process is very simple. Now it's time to create a class and add some functionality to make the image better.
You may notice that the correct construction of sets is driven by probability. The difference in probabilities means that the set has an irregular structure (see Barnsley Fern IFS for weights). This fact can be used to create beautiful images. We need to set a color proportional to the frequency of points in a certain neighborhood.
If the pixel color depends on the previous value, this can be done using a virtual screen (just an array). Finally, the virtual screen will be rendered to bmp using the palette. The bmp image itself can be drawn as a background image for the chart.
The following is the code of the Expert Advisor based on the CIFS class:
//+------------------------------------------------------------------+ //| IFS_Fern_color.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include//-- Barnsley Fern IFS coefficient Doubled IFS_a[ 4 ] = { 0.00 , 0.85 , 0.20 , - 0.15 }; Doubled IFS_b[ 4 ] = { 0.00 , 0.04 , - 0.26 , 0.28 }; Doubled IFS_c[ 4 ] = { 0.00 , - 0.04 , 0.23 , 0.26 }; Doubled IFS_d[ 4 ] = { 0.16 , 0.85 , 0.22 , 0.24 }; Doubled IFS_e[ 4 ] = { 0.00 , 0.00 , 0.00 , 0.00 }; Doubled IFS_f[ 4 ] = { 0.00 , 1.60 , 1.60 , 0.00 }; double IFS_p[ 4 ] = { 10 , 850 , 70 , 70 }; //-- palette Uchar Palette[ 23 * 3 ]= { 0x00 , 0x00 , 0x00 , 0x02 , 0x0A , 0x06 , 0x03 , 0x11 , 0x0A , 0x0B , 0x1E , 0x0F , 0x0C , 0x4C , 0x2C , 0x1C , 0x50 , 0x28 , 0x2C , 0x54 , 0x24 , 0x3C , 0x58 , 0x20 , 0x4C , 0x5C , 0x1C , 0x70 , 0x98 , 0x6C , 0x38 , 0xBC , 0xB0 , 0x28 , 0xCC , 0xC8 , 0x4C , 0xB0 , 0x98 , 0x5C , 0xA4 , 0x84 , 0xBC , 0x68 , 0x14 , 0xA8 , 0x74 , 0x28 , 0x84 , 0x8C , 0x54 , 0x94 , 0x80 , 0x40 , 0x87 , 0x87 , 0x87 , 0x9F , 0x9F , 0x9F , 0xC7 , 0xC7 , 0xC7 , 0xDF , 0xDF , 0xDF , 0xFC ,0xFC , 0xFC }; //+------------------------------------------------------------------+ //| Class CIFS | //+------------------------------------------------------------------+ class CIFS { protected : cIntBMP m_bmp; integer m_x size; integer m_y size; integer m_virtual_screen[]; double m_scale; double m_probs[ 8 ]; public : ~CIFS() { m_bmp.Delete( "bmpimg" , true ); }; void create( integer x_size, integer y_size, ucchar_pass ); void make( double_scale , boolean_back ); void show_bmp ( boolean_back ); protected : void vs_prepare( integer Er Pass ); blank VS_PutPixel ( integer pixel, integer py, Uchar Pass); Uchar VS_GetPixel ( integer pixel, integer py); integer Get friend color ( Uchar Index); integer RGB256 ( integer , integer gram, integer b) constant { return (r+ { m_bmp.Create ( x_size , y_size ,col); VS_Prepare( x_size ,y_size,col); prepare probability(); } // +------------------------------------------------------------------+ //|Prepare virtual screen | //+------------------------------------------------------------------+ Blank CIFS::VS_Prepare(integer x_size, integer y_size, integer up) { m_x_size = x_size; m_y_size = y_size; array resize(m_virtual screen, m_x_size * m_y_size); VS_Fill(column); } // + ------------------------------------------------------------------ + // | Fill the virtual screen with the specified color | // +------------------------------------------------------------------+ Blank CIFS::VS_Fill( Uchar ) { for ( integer i = 0 ; i //+------------------------------------------------------------------+ //|Return the color in the palette | //+------------------------------------------------------------------+ Integer CIFS::GetPalColor( Uchar Index) { Integerpan>ind=index; if (index <= 0 ) {index = 0 ;} if (industry > 22 ) {index = 22 ;} uchal r = palette [ 3 * (index)]; uchal g = palette [ 3 * (index) + 1 ]; uchal b = palette [ 3 * (index) + 2 ]; return (RGB256(r,g,b)); } //+--------------------------------------------------------------------------------+ //|Draw a pixel on the virtual screen | //+---------------------------------------------------------------------------------+ Blank CIFS::VS_PutPixel( integer pixel, integer py, utchar on) { if (pixel < 0 ) return ; if (py < 0 ) returns ; if (px>m_x size) returns ; if (py>m_ysize) returns ; integer pos=m_xsize*py+px; if (position>= array size (m_virtual_screen)) returns ; m_virtual_screen[pos]=col; } //+--------------------------------------------------------------------------------+ //|Get pixel "color" from virtual screen | //+------------------------------------------------------------------+ Uchar CIFS::VS_GetPixel( integer pixel, integer py) { if (pixel < 0 ) return ( 0 ); if (py < 0 ) return ( 0 ); if (px>m_x size) return ( 0 ); if (py>m_ysize) return ( 0 ) ); integer pos=m_xsize*py+px; if (position >= array size (m_virtual_screen)) return ( 0 ); return (m_virtual_screen[position]); } //+------------------------------------------------------------------+ //| Prepare cumulative probability array | //+------------------------------------------------------------------+ Blank CIFS::prepare probability() { double m = 0 ; for ( integer i = 0 ;i< array size (IFS_p);i++) { m_probs[i]=IFS_p[i]+m; m=m+IFS_p[i]; } } //+------------------------------------------------------------------+ //|Render IFS settings to virtual screen | //+------------------------------------------------------------------+ Blank CIFS::RenderIFSToVirtualScreen() { Double x= 0 , y= 0 ; double x0 = 0 ; double y0 = 0 ; units iterations = units ( mathwheel ( 100000 + 100 * mathpack (meter scale, 2 ))); for ( units i = 0 ; i<iterations; i++) { double prb = 1000 *( rand ()/ 32767.0 ); for ( integer k = <span class="number">0; k< array size (IFS_p); k++) { if (prb<=m_probs[k]) { x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k]; y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f[k]; integer scX = integer ( mathwheel (m_xsize/ 2 + (x- 0 )*m_scale)); integer SCY = integer ( mathwheel (m_ysize/ 2 + (y- 5 )*m_scale)); if (scX>= 0 && scX = 0 &&scY uchal c=VS_GetPixel(scX,scY); if (c< 255 ) c=c+ 1 ; VS_PutPixel(scX,scY,c); } rest ; } x0 = x; y0 = y; } } } //+--------------------------------------------------------------------------------+ //|Copy virtual screen to BMP | //+------------------------------------------------------------------+ Blank CIFS::VirtualScreenToBMP() { order ( integer i = 0 ; i for ( integer j = 0 ; j uchal colind=VS_GetPixel(i,j); integer xcol=GetPalColor(colind); if (colind== 0 ) xcol= 0x00 ; //if (colind==0) xcol=0xFFFFFF; m_bmp.DrawDot(i,j,xcol); } } } //+--------------------------------------------------------------------------------+ //|Display BMP image on chart | //+------------------------------------------------------------------+ Blank CIFS::showBMP ( boolean back) { m_bmp.save( "bmpimg" , true ); m_bmp.display( 0 , 0 , "bmpimg" , "fern" ); object set integer ( 0 , "fern" , OBJPROP_BACK , back); } //+--------------------------------------------------------------------------------+ //| Rendering method | //+------------------------------------------------------------------+ blank CIFS::render( double scale, boolean after) { m_scale = scale; VS_fill( 0 ); RenderIFSToVirtualScreen(); VirtualScreenToBMP(); show BMP(back); } static integer grid mode; CIFS fern; integer current scale = 50 ; //+------------------------------------------------------------------+ //|Expert initialization function | //+------------------------------------------------------------------+ Blank initialize () { //-- get grid mode grid mode = integer ( chart get integer ( 0 , CHART_SHOW_GRID , 0 )); //-- disable grid chart set integer ( 0 , CHART_SHOW_GRID , 0 ); //-- create bmp fern.create( 800 , 800, 800 ,0x00 ); //-- Display as background image fern.render(currentscale, true ); } //+------------------------------------------------------------------+ //|Expert deinitialization function | //+------------------------------------------------------------------+ Blank solution initialization ( const integer r) { //-- Restore grid mode chart set integer ( 0 , CHART_SHOW_GRID , grid mode); //-- Delete Fern object object ( 0 , "Fern" ) ); } //+------------------------------------------------------------------+ //|Expert OnChart Event Handler | //+------------------------------------------------------------------+ Blank chart event ( const integer ID, // event identifier const long &l parameter, // event parameter of type long const double &d parameter, // event parameter of double type const string & spam // event parameter of string type ) { //--- Click on the graph object if (id == CHARTEVENT_OBJECT_CLICK ) { print ( "Click event on graphics object named '" +sparam+ "'" ); if (garbage argument == "fern" ) { // Increase scale factor (scale) currentscale = integer (currentscale * 1.1 ); fern.render(currentscale, true ); } } } //+--------------------------------------------------------------------------------+
turn out:

Figure 9. Barnsley fern image created using CIFS classes

Figure 10. Magnified area of Barnsley's Fern

Figure 11. Magnified area of Barnsley's Fern

Figure 12. Magnified area of Barnsley's Fern
1. There are a large number of IFS fractal Fractints , for example:
//binary Doubled IFS_a[ 3 ] = { 0.5 , 0.5 , 0.0 }; Doubled IFS_b[ 3 ] = { 0.0 , 0.0 , - 0.5 }; Doubled IFS_c[ 4 ] = { 0.0 , 0.0 , 0.5 }; Doubled IFS_d[ 4 ] = { 0.5 , 0.5 , 0.5 }; Double IFS_e[ 4 ] = {- 2.563477 , 2.436544 , 4.873085 }; Double IFS_f[ 4 ] = {- 0.000000 , - 0.000003 , 7.563492 }; Double IFS_p[ 4 ] = { Chapter 333 , Chapter 333 , Chapter 333 }; // Coral Doubled IFS_a[ 3 ] = { 0.307692 , 0.307692 , 0.000000 }; Doubled IFS_b[ 3 ] = {- 0.531469 , - 0.076923 , 0.54545 }; Doubled IFS_c[ 3 ] = {- 0.461538 , 0.153846 , 0.692308 }; Doubled IFS_d[ 3 ] = {- 0.293706 , - 0.447552 , - 0.195804 }; Doubled IFS_e[ 3 ] = { 5.4019537 , - 1.295248 , - 4.893637 }; Doubled IFS_f[ 3 ] = { 8.655175 , 4.152990 , 7.269794 }; Doubled IFS_p[ 3 ] = { 400 , 150 , 450 }; // Crystal Doubled IFS_a[ 2 ] = { 0.696970 , 0.090909 }; Doubled IFS_b[ 2 ] = {- 0.481061 , - 0.443182 }; Doubled IFS_c[ 2 ] = {- 0.393939 , 0.515152 }; Double IFS_d[ 2 ] = {- 0.662879 , - 0.094697 }; Double IFS_e[ 2 ] = { 2.147003 , 4.286558 }; Double IFS_f[ 2 ] = { 10.310288 , 2.925762 }; Double IFS_p[ 2 ] = { 750 , 250 }; // Dragon Doubled IFS_a[ 2 ] = { 0.824074 , 0.088272 }; Doubled IFS_b[ 2 ] = { 0.281482 , 0.520988 }; Doubled IFS_c[ 2 ] = {- 0.212346 , - 0.463889 }; Double IFS_d[ 2 ] = { 0.864198 , - 0.377778 }; Double IFS_e[ 2 ] = {- 1.882290 , 0.785360 };ord">Double IFS_f[ 2 ] = {- 0.110607 , 8.095795 }; Double IFS_p[ 2 ] = { 780 , 220 }; // Double ground IFS_a[ 3 ] = { 0 , 0.52 , 0 }; Double IFS_b[ 3 ] = {- 0.5 , 0 , 0.5 }; Doubled IFS_c[ 3 ] = { 0.5 , 0 , - 0.5 }; Doubled IFS_d[ 3 ] = { 0 , 0.5 , 0 }; Doubled IFS_e[ 3 ] = {- 1.732366 , - 0.027891 , 1.620804 }; Doubled IFS_f[ 3 ] = { 3.366182 , 5.014877 , 3.310401 }; Doubled IFS_p[ 3 ] = { Chapter 333 , Chapter 333 , Chapter 333 }; // Koch 3 Doubled IFS_a[ 5 ] = { 0.307692 , 0.192308 , 0.192308 , 0.307692 , 0.384615 }; Double IFS_b[ 5 ] = { 0 ,- 0.205882 , 0.205882 , 0 , 0 }; Double IFS_c[ 5 ] = { 0 , 0.653846 , - 0.653846 , 0 , 0 }; Double IFS_d[ 5 ] = { 0.294118 , 0.088235 , 0.088235 , 0.294118 , - 0.294118 } ; Double IFS_e[ 5 ] = { 4.119164 ,- 0.688840 , 0.688840 , - 4.136530 , - 0.007718 }; Double IFS_f[ 5 ] = { 1.604278 , 5.978916 , 5.962514 , 1.604278 , 2.941176 }; Doubled IFS_p[ 5 ] = { 151 , Chapter 254 , Chapter 254 , 151 , 190 }; // Spiral doubled IFS_a[ 3 ] = { 0.787879 , - 0.121212 , 0.181818 }; Doubled IFS_b[ 3 ] = {- 0.424242 , 0.257576 , - 0.136364 }; Doubled IFS_c[ 3 ] = { 0.242424 , 0.151515 , 0.090909 }; Doubled IFS_d[ 3 ] = { 0.859848 , 0.053030 , 0.181818 }; Double IFS_e[ 3 ] = { 1.758647 , - 6.721654 , 6.086107 }; Double IFS_f[ 3 ] = { 1.408065 , 1.377236 ,class = "number" 0.065152 }; Doubled IFS_c[ 2 ] = { 0.406061 , - 0.175758 } ; Doubled IFS_d[ 2 ] = { 0.887121 , - 0.218182 }; Doubled IFS_e[ 2 ] = { 1.460279 , 3.809567 }; Doubled IFS_f[ 2 ] = { 0.691072 , 6.741476 }; Doubled IFS_p[ 2 ] = { 920 , 80 }; // Zigzag 2 Doubled IFS_a[ 2 ] = { - 0.632407 , - 0.036111 }; Double IFS_b [ 2 ] = {- 0.614815 , 0.444444 } ; Double IFS_c[ 2 ] = {- 0.545370 , 0.210185 }; Double IFS_d[ 2 ] = { 0.659259 , 0.037037 } ; Double IFS_e [ 2 ] = { 3.840822 , 2.071081 }; Double IFS_f[ 2 ] = { 1.282321 , 8.330552 }; Double IFS_p [ 2 ] = { Chapter 888 , 112 } ;
Draw these sets. How to find initial similarity transformation using IFS coefficients?
2. Create your own set of fractals and calculate their coefficients (Chapter 2).
3. Try using palette colors (uchar Palette array), extend the palette and add gradient colors.
4. What is the fractal (Hausdorf-Bezikovitch) dimension of Barnsley's Fern? Is there a formula to calculate fractal dimension using IFS coefficients*.
5. Add the zoom of a certain area and use the mouse to click the coordinate information chart event :
Blank Chart Event ( const integer ID, // event identifier const long &l parameter, // event parameter of type long const double &d parameter, // event parameter of type double const string & spam // event parameter of type string ) { //--- left click if (id== CHARTEVENT_CLICK ) { Print ( "Coordinates: x=" , l parameter, "y=" , d parameter); } }
in conclusion
We consider algorithms for creating self-similar sets using a system of iterative functions.
Working with graphical images is greatly simplified using the bone morphogenetic protein library. In addition to the DrawDot(x,y,color) method we used, the cIntBMP class contains many other useful methods. But that's another story.
Attachment download
📎 ifs_sierpinski_gasket.mq5 (3.45 KB)
📎 ifs_fern.mq5 (2.67 KB)
📎 ifs_sierpinski_carpet.mq5 (2.8 KB)
📎 ifs_fractals.mq5 (3.82 KB)
📎 ifs_fern_color.mq5 (9.41 KB)
📎 cintbmp.mqh (78.58 KB)
Source: MQL5 #328
💡 Featured Recommendations
✍️ Latest by the author
- •
- •
- •
- •
- •
- •
📌 Popular topics
- •
- •
- •
- •
- •
- •
- •
- •
🔗 You May Be Interested In
- •
- •
- •
- •
- •
- •