Ticaret robotlarını ücretsiz olarak nasıl indirebileceğinizi izleyin
Bizi Telegram üzerinde bulun!
Fan sayfamıza katılın
Komut dosyasını ilginç mi buldunuz?
Öyleyse bir link gönderin -
başkalarının da faydalanmasını sağlayın
Komut dosyasını beğendiniz mi? MetaTrader 5 terminalinde deneyin
Uzman Danışmanlar

Yinelenen Fonksiyon Sistemi (IFS) Kullanarak MQL5'te Fraktallar Oluşturma - MetaTrader 5 için Uzman Danışman

Görüntülemeler:
261
Derecelendirme:
(39)
Yayınlandı:
2022.03.21 09:20
Bu koda dayalı bir robota veya göstergeye mi ihtiyacınız var? Freelance üzerinden sipariş edin Freelance'e git

Giriş

Yinelenen Fonksiyon Sistemi (IFS) tarafından tanımlanan kendine benzer kümelerin oluşturulmasına olanak tanıyan birçok program vardır. Örneğin, Fractint, Fractal Designer veya IFS Matlab Generator'a bakın. MQL5 dilinin hızı ve grafik nesneleriyle çalışma imkanı sayesinde bu güzel setlerle MetaTrader 5 müşteri terminalinde de çalışılabilir.

Dmitry (Integer) tarafından geliştirilen cIntBMP kütüphanesi, grafik nesneleriyle çalışmak için yeni olanaklar sunar ve görüntülerin oluşturulmasını büyük ölçüde basitleştirir. Bu kütüphane MetaQuotes Software Corp. tarafından özel ödüle layık görülmüştür.

Bu bölümde, cIntBMP kütüphanesi ile çalışma örnekleri ele alınacak. Ek olarak, Yinelenen Fonksiyon Sistemi kullanılarak fraktal kümeler oluşturma algoritmaları da ele incelenecek.


1. Düzlemin afin dönüşümü

Düzlemin afin dönüşümü bir fonksiyondur. Genel olarak, afin 2-D dönüşümü bazı matrisi ve vektörü ile tanımlanabilir. (x,y) koordinatlarına sahip nokta, lineer dönüşüm kullanılarak başka bir noktasına dönüşür:

Dönüşüm, tekil olmamalıdır, . Afin dönüşüm, boyutu kez değiştirir.

Afin dönüşümler geometrik nesnelerin yapısını değiştirmez (çizgiler çizgilere dönüştürülür) ve nesnelerin döndürülme, ölçeklendirme ve ötelenme gibi basit "deformasyonlarını" tanımlamaya olanak sağlar.

Afin düzlem dönüşümü örnekleri:

1) açısında düzlemin dönüşümü:

2) ve katsayılı düzlemin "ölçeklendirilmesi" (X ve Y eksenleri boyunca):

3) vektörüne göre düzlemin ötelenmesi:

Büzülme fonksiyonları anahtardır (Hutchinson sonuçlarına bakın).

ve , ve koordinatlarına sahipse ve bir metriktir (örneğin, Öklid metriği: ). Afin dönüşüm, olmak üzere eğer ise büzülme olarak adlandırılır.

Bir afin dönüşüm örneği:

Sonuç:


2. Benzerlik dönüşümleri

Fraktallar şu şekilde oluşturulur: bazı (basit) geometrik nesneler (kesit, üçgen, kare) alınır, N adet parçaya bölünür ve bu N parçanın M tanesi kümenin ileri "inşası" için kullanılır (N=M ise, elde edilen kümenin tamsayı boyutu elde edilir). Ayrıca bu işlem her parça için tekrar tekrar tekrarlanır.

Klasik fraktallar:

Kesit:

  • Üçlü Koch eğrisi, N=3, M=4;
  • Cantor tozu, N=3, M=2;

Üçgen:

  • Sierpinski contası, N=4, M=3;

Kare:

  • Sierpinski halısı, N=9, M=8;
  • Vichek fraktalı, N=9, M=5.

vb.

Fraktallar kendine benzer yapıya sahiptir, bazıları birkaç benzerlik dönüşümü ile tanımlanabilir. Afin dönüşümün yapısı, fraktalın nasıl inşa edildiğine bağlıdır.

Fraktal yapıyı tanımlamak için, fraktalın inşasının sadece 1. aşamasını tanımlamamız ve onu afin dönüşümler kümesine yerleştirmemiz yeterlidir.

Varsayalım elimizde başlangıç için küme olsun. Fraktal oluşturma algoritmasına göre onu indirgememiz, döndürmemiz ve "belirli bir yere koymamız" gerekir. Bu işlemi afin dönüşümleri kullanarak tanımlamamız gerekiyor, yani matris ve vektör bulmalıyız.

Başlangıç kümesinin tek bir doğru üzerinde yer almayan 3 noktasını alıp, bunları "indirgenmiş" kümenin karşılık gelen 3 noktasına dönüştürmenin yeterli olduğunu kanıtlamamız kolaydır. Bu dönüşüm, çözüm olarak a,b,c,d,e,f'yi bulmamızı sağlayan 6 lineer denkleme yol açar.

Hadi gösterelim. üçgeninin üçgenine dönüştüğünü varsayalım.

Lineer denklem sistemini çözerek a,b,c,d,e ve f katsayılarını elde edebileceğiz:

Örnek: Sierpinski contası:

Noktaların koordinatları:

  • A (0,0)
  • B (0,1)
  • C (1,1)
  • D(0,1/2)
  • E (1/2,1)
  • F(1/2,1/2)

3 dönüşümümüz var:

  1. ABC -> ADF
  2. ABC -> DBE
  3. ABC -> FEC

Dönüşümlerin her biri için lineer denklemler şu şekilde görünür:




Çözümler: , ,

Böylece, üç afin dönüşümün katsayılarını bulduk. Bunları kendine benzer kümeler oluşturmak için kullanacağız.


3. Yinelenen Fonksiyon Sistemini kullanarak fraktallar oluşturma

Yinelenen Fonksiyon Sistemi (IFS), afin büzülme fonksiyonları kümesidir, burada - "ağırlıklar"dır. IFS fonksiyonlarının her biri 7 sayı ile tanımlanır: , burada ağırlıkları, yineleme işleminde n'inci dönüşüm olasılığı olarak kullanılır. Değerlerini büzülme ile orantılı olarak tanımlamak daha iyidir: .

IFS'i kullanarak fraktal inşasının algoritmasını ele alalım (ayrıca bkz. kaos oyunu).

İlk ihtiyacımız olan, koordinatları olan bir başlangıç noktası almaktır. Ardından, büzülmelerden birini rastgele seçiyoruz ve noktasını çiziyoruz. Ve yine, büzülmelerinden birini rastgele seçiyoruz ve noktasını çiziyoruz. Böylece, nokta kümesine sahip oluruz.

Büzülmenin seçimi "olasılığına" bağlıdır (rastgeledir). İşlemi yeterince uzun süre tekrarlarsak (örneğin ~30000 noktaya kadar) ve ortaya çıkan kümeyi çizersek, rastgele işleme rağmen yapısını görürüz.

Bir Sierpinski contası örneği:

Şekil 1. İkinci alt bölümde hesaplanan IFS katsayılarıyla oluşturulan Sierpinski contası

Şekil 1. İkinci alt bölümde hesaplanan IFS katsayılarıyla oluşturulan Sierpinski contası

Kod:

//+------------------------------------------------------------------+
//|                                        IFS_Sierpinski_Gasket.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

//-- cIntBMP sınıfına sahip dosyayı dahil et
#include <cIntBMP.mqh>

//-- Sierpinski contası IFS katsayıları
//-- (a,b,c,d) matrisleri
double IFS_a[3] = {0.50,  0.50,  0.50};
double IFS_b[3] = {0.00,  0.00,  0.00};
double IFS_c[3] = {0.00,  0.00,  0.00};
double IFS_d[3] = {0.50,  0.50,  0.50};
//-- (e,f) vektörleri
double IFS_e[3] = {0.00,  0.00,  0.50};
double IFS_f[3] = {0.00,  0.50,  0.50};
//-- dönüşümlerin "olasılıkları" (1000 ile çarpılır)
double IFS_p[3]={333,333,333};

double Probs[3]; // Probs dizisi - IFS dönüşümlerini seçmede kolaylık sağlamak için kullanılır
cIntBMP bmp;     // cIntBMP sınıfı örneği
int scale=350;  // ölçek katsayısı
//+------------------------------------------------------------------+
//| Uzman Danışman başlatma fonksiyonu                               |
//+------------------------------------------------------------------+
int OnInit()
  {
//-- Probs dizisini hazırla
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      Probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }
//-- BMP görüntüsünün boyutu
   int XSize=500;
   int YSize=400;
//-- clrSeashell arka plan rengiyle XSizexYSize bmp görüntüsü oluştur
   bmp.Create(XSize,YSize,clrSeashell);
//-- görüntü dikdörtgeni
   bmp.DrawRectangle(0,0,XSize-1,YSize-1,clrBlack);

//-- nokta koordinatları (kümenin inşasında kullanılacak)
   double x0=0;
   double y0=0;
   double x,y;
//-- hesaplanacak nokta sayısı (daha fazla nokta - daha ayrıntılı görüntü)
   int points=1500000;
//-- kümeyi hesapla
   for(int i=0; i<points; i++)
     {
      // IFS_p ile orantılı olasılıklarla dönüşüm seç
      double prb=1000*(rand()/32767.0);
      for(int k=0; k<ArraySize(IFS_p); k++)
        {
         if(prb<=Probs[k])
           {
            // afin dönüşüm
            x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k];
            y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f[k];
            // önceki koordinatları güncelle
            x0 = x;
            y0 = y;
            // BMP görüntüsü koordinatlarına dönüştür
            // (cIntBMP sınıfında Y koordinatının nasıl belirtildiğine dikkat edin)
            int scX = int (MathRound(XSize/2 + (x-0.5)*scale));
            int scY = int (MathRound(YSize/2 + (y-0.5)*scale));
            // nokta görüntünün içindeyse, noktayı çiz
            if(scX>=0 && scX<XSize && scY>=0 && scY<YSize) { bmp.DrawDot(scX,scY,clrDarkBlue); }
            break;
           }
        }
     }
//-- görüntüyü dosyaya kaydet
   bmp.Save("bmpimg",true);
//-- görüntüyü grafik üzerine çiz
   bmp.Show(0,0,"bmpimg","IFS");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Uzman Danışman sonlandırma fonksiyonu                            |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- görüntüyü grafikten sil
   ObjectDelete(0,"IFS");
//--- dosyayı sil
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+

Ölçeği 1350'ye ayarlar, yineleme sayısını 15000000'e yükseltir ve başlangıç noktasını kaydırmayı değiştirirsek:

int scX = MathRound(XSize/2 + (x-0.75)*scale);
int scY = MathRound(YSize/2 + (y-0.75)*scale);

Kümenin yakınlaştırılmış bölümünü elde ederiz. Kendine benzer yapıya sahip olduğu görülebilir (Şekil 2):

Şekil 2. Sierpinski contasının yakınlaştırılmış bölümü

Şekil 2. Sierpinski contasının yakınlaştırılmış bölümü

Michael Barnsley tarafından sunulmuş olan ünlü Barnsley eğrelti otunu ele alalım. Bu daha karmaşıktır.

Şekil 3. Barnsley eğrelti otu

Şekil 3. Barnsley eğrelti otu

Kod benzerdir, ancak burada farklı ağırlıklara sahip 4 IFS bükülmemiz vardır.

//+------------------------------------------------------------------+
//|                                                     IFS_fern.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <cIntBMP.mqh>
//-- Barnsley eğrelti otu IFS katsayıları
//-- (a,b,c,d) matrisleri
double IFS_a[4] = {0.00,  0.85,  0.20,  -0.15};
double IFS_b[4] = {0.00,  0.04, -0.26,   0.28};
double IFS_c[4] = {0.00, -0.04,  0.23,   0.26};
double IFS_d[4] = {0.16,  0.85,  0.22,   0.24};
//-- (e,f) vektörleri
double IFS_e[4] = {0.00,  0.00,  0.00,   0.00};
double IFS_f[4] = {0.00,  1.60,  1.60,   0.00};
//-- dönüşümlerin "olasılıkları" (1000 ile çarpılır)
double IFS_p[4] = {10,     850,    70,     70};

double Probs[4];
cIntBMP bmp;
int scale=50;
//+------------------------------------------------------------------+
//| Uzman Danışman başlatma fonksiyonu                               |
//+------------------------------------------------------------------+
int OnInit()
  {
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      Probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }

   int XSize=600;
   int YSize=600;

   bmp.Create(XSize,YSize,clrSeashell);

   bmp.DrawRectangle(0,0,XSize-1,YSize-1,clrBlack);

   double x0=0;
   double y0=0;
   double x,y;

   int points=250000;

   for(int i=0; i<points; i++)
     {
      double prb=1000*(rand()/32767.0);
      for(int k=0; k<ArraySize(IFS_p); k++)
        {
         if(prb<=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];
            x0 = x;
            y0 = y;
            int scX = int (MathRound(XSize/2 + (x)*scale));
            int scY = int (MathRound(YSize/2 + (y-5)*scale));
            if(scX>=0 && scX<XSize && scY>=0 && scY<YSize) { bmp.DrawDot(scX,scY,clrForestGreen); }
            break;
           }
        }
     }
   bmp.Save("bmpimg",true);
   bmp.Show(0,0,"bmpimg","IFS");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Uzman Danışman sonlandırma fonksiyonu                            |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"IFS");
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+ 

Bu kadar karmaşık bir yapının sadece 28 sayı ile tanımlanabilmesi dikkat çekicidir.

Ölçeği 150'ye yükseltir ve yineleme sayısını 1250000'e ayarlarsak, kümenin yakınlaştırılmış bölümünü elde ederiz:

Şekil 4. Barnsley eğrelti otunun bir bölümü

Şekil 4. Barnsley eğrelti otunun bir bölümü

Algoritmanın evrensel olduğunu görüyoruz, bu bize farklı fraktal kümeleri oluşturmanıza olanak tanır.

Bir sonraki örnek, aşağıdaki IFS katsayıları ile tanımlanan Sierpinski halısıdır:

//-- Sierpinski halısı IFS katsayıları
double IFS_a[8] = {0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333};
double 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};
double IFS_f[8] = {6.75, 0.25, 6.75,  0.25, 6.75, 3.5, 0.25, 3.50};
//-- "olasılıklar" (1000 ile çarpılır)
double IFS_p[8]={125,125,125,125,125,125,125,125};

Şekil 5. Sierpinski halısı

Şekil 5. Sierpinski halısı

İkinci alt bölümde, IFS bükülmelerinin katsayılarının hesaplama algoritmasını ele aldık.

Şimdi de "fraktal kelimeler"in nasıl oluşturulacağını ele alalım. Rusça'da "Fraktallar" kelimesi şu şekile görünür:

Şekil 6. Rusça "Fraktallar" kelimesi

Şekil 6. Rusça "Fraktallar" kelimesi

IFS katsayılarını bulmak için ilgili lineer sistemleri çözmemiz gerekir. Çözümler:

//-- Rusça "Fraktallar" kelimesinin IFS katsayıları
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, -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
  };

//-- "olasılıklar" (1000 ile çarpılır)
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
  };

Sonuç olarak, aşağıdaki görüntüyü elde ederiz:

Şekil 7. Kendine benzer kelime

Şekil 7. Kendine benzer kelime

Tam kaynak kodu ifs_fractals.mq5 dosyasından bulunabilir.

Kümeyi yakınlaştırırsak, kendine benzer yapıyı görürüz:

Şekil 8. Kümenin yakınlaştırılmış bölümü

Şekil 8. Kümenin yakınlaştırılmış bölümü

IFS'ye dayalı kendine benzer kümeler, Fractal Designer kullanılarak oluşturulabilir.

Yinelenen Fonksiyon Sistemini kullanarak fraktal kümeler oluşturma konusunu ele aldık. cIntBMP kütüphanesi sayesinde bu işlem çok basittir. Şimdi ise bu işlevsellikle sınıf oluşturalım ve görüntüleri daha iyi hale getirmek için bazı özellikler ekleyelim.


Olasılıklar tarafından yönlendirilen kümelerin doğru yapılandırılıp yapılandırılmadığını fark edebilirsiniz. Olasılıklardaki fark, kümenin düzensiz yapıya sahip olduğu anlamına gelir (bkz. Barnsley eğrelti otu IFS'in ağırlıkları). Bu gerçek, güzel görüntülerin oluşturulması için kullanılabilir. Noktanın rengi, ilgili komşuluktaki noktanın frekansıyla orantılı olacak şekilde ayarlanabilir.

Piksel rengi önceki değerlere bağlı olacaksa, bu, sanal ekran (sadece bir dizi) kullanılarak gerçekleştirilebilir. Son olarak, sanal ekran palet kullanılarak bmp'ye dönüştürülür. Bmp görüntüsünün kendisi, grafiğin arka plan görüntüsü olarak çizilebilir.

CIFS sınıfına dayalı Uzman Danışmanın kodu:

//+------------------------------------------------------------------+
//|                                               IFS_Fern_color.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include <cIntBMP.mqh>
//-- Barnsley eğrelti otu IFS katsayıları
double IFS_a[4] = {0.00,  0.85,  0.20,  -0.15};
double IFS_b[4] = {0.00,  0.04, -0.26,   0.28};
double IFS_c[4] = {0.00, -0.04,  0.23,   0.26};
double IFS_d[4] = {0.16,  0.85,  0.22,   0.24};
double IFS_e[4] = {0.00,  0.00,  0.00,   0.00};
double IFS_f[4] = {0.00,  1.60,  1.60,   0.00};
double IFS_p[4] = {10,     850,    70,     70};
//-- palet
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
  };
//+------------------------------------------------------------------+
//| CIFS sınıfı                                                      |
//+------------------------------------------------------------------+
class CIFS
  {
protected:
   cIntBMP           m_bmp;
   int               m_xsize;
   int               m_ysize;
   uchar             m_virtual_screen[];
   double            m_scale;
   double            m_probs[8];

public:
                    ~CIFS()                          { m_bmp.Delete("bmpimg",true); };
   void              Create(int x_size,int y_size,uchar col);
   void              Render(double scale,bool back);
   void              ShowBMP(bool back);
protected:
   void              VS_Prepare(int x_size,int y_size,uchar col);
   void              VS_Fill(uchar col);
   void              VS_PutPixel(int px,int py,uchar col);
   uchar             VS_GetPixel(int px,int py);
   int               GetPalColor(uchar index);
   int               RGB256(int r,int g,int b) const {return(r+256*g+65536*b);      }
   void              PrepareProbabilities();
   void              RenderIFSToVirtualScreen();
   void              VirtualScreenToBMP();
  };
//+------------------------------------------------------------------+
//| metot oluştur                                                    |
//+------------------------------------------------------------------+
void CIFS::Create(int x_size,int y_size,uchar col)
  {
   m_bmp.Create(x_size,y_size,col);
   VS_Prepare(x_size,y_size,col);
   PrepareProbabilities();
  }
//+------------------------------------------------------------------+
//| sanal ekran hazırla                                              |
//+------------------------------------------------------------------+
void CIFS::VS_Prepare(int x_size,int y_size,uchar col)
  {
   m_xsize=x_size;
   m_ysize=y_size;
   ArrayResize(m_virtual_screen,m_xsize*m_ysize);
   VS_Fill(col);
  }
//+------------------------------------------------------------------+
//| sanal ekranı belirtilen renkle doldur                            |
//+------------------------------------------------------------------+
void CIFS::VS_Fill(uchar col)
  {
   for(int i=0; i<m_xsize*m_ysize; i++) {m_virtual_screen[i]=col;}
  }
//+------------------------------------------------------------------+
//| paletten rengi geri döndürür                                     |
//+------------------------------------------------------------------+
int CIFS::GetPalColor(uchar index)
  {
   int ind=index;
   if(ind<=0) {ind=0;}
   if(ind>22) {ind=22;}
   uchar r=Palette[3*(ind)];
   uchar g=Palette[3*(ind)+1];
   uchar b=Palette[3*(ind)+2];
   return(RGB256(r,g,b));
  }
//+------------------------------------------------------------------+
//| sanal ekranda piksel çiz                                         |
//+------------------------------------------------------------------+
void CIFS::VS_PutPixel(int px,int py,uchar col)
  {
   if (px<0) return;
   if (py<0) return;
   if (px>m_xsize) return;
   if (py>m_ysize) return;
    int pos=m_xsize*py+px;
   if(pos>=ArraySize(m_virtual_screen)) return;
   m_virtual_screen[pos]=col;
  }
//+------------------------------------------------------------------+
//| Sanal ekrandan piksel "rengini" al                               |
//+------------------------------------------------------------------+
uchar CIFS::VS_GetPixel(int px,int py)
  {
   if (px<0) return(0);
   if (py<0) return(0);
   if (px>m_xsize) return(0);
   if (py>m_ysize) return(0);
    int pos=m_xsize*py+px;
   if(pos>=ArraySize(m_virtual_screen)) return(0);
   return(m_virtual_screen[pos]);
  }
//+------------------------------------------------------------------+
//| kümülatif olasılıklar dizisini hazırla                           |
//+------------------------------------------------------------------+
void CIFS::PrepareProbabilities()
  {
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      m_probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }
  }
//+------------------------------------------------------------------+
//| IFS'i sanal ekrana render et                                     |
//+------------------------------------------------------------------+
void CIFS::RenderIFSToVirtualScreen()
  {
   double x=0,y=0;
   double x0=0;
   double y0=0;
   uint iterations= uint (MathRound(100000+100*MathPow(m_scale,2)));

   for(uint i=0; i<iterations; i++)
     {
      double prb=1000*(rand()/32767.0);

      for(int k=0; k<ArraySize(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];

            int scX = int (MathRound(m_xsize/2 + (x-0)*m_scale));
            int scY = int (MathRound(m_ysize/2 + (y-5)*m_scale));

            if(scX>=0 && scX<m_xsize && scY>=0 && scY<m_ysize)
              {
               uchar c=VS_GetPixel(scX,scY);
               if(c<255) c=c+1;
               VS_PutPixel(scX,scY,c);
              }
            break;
           }
         x0 = x;
         y0 = y;
        }
     }
  }
//+------------------------------------------------------------------+
//| sanal ekranı BMP'ye kopyala                                      |
//+------------------------------------------------------------------+
void CIFS::VirtualScreenToBMP()
  {
   for(int i=0; i<m_xsize; i++)
     {
      for(int j=0; j<m_ysize; j++)
        {
         uchar colind=VS_GetPixel(i,j);
         int xcol=GetPalColor(colind);
         if(colind==0) xcol=0x00;
         //if(colind==0) xcol=0xFFFFFF;
         m_bmp.DrawDot(i,j,xcol);
        }
     }
  }
//+------------------------------------------------------------------+
//| BMP görüntüsünü grafikte göster                                  |
//+------------------------------------------------------------------+
void CIFS::ShowBMP(bool back)
  {
   m_bmp.Save("bmpimg",true);
   m_bmp.Show(0,0,"bmpimg","Fern");
   ObjectSetInteger(0,"Fern",OBJPROP_BACK,back);
  }
//+------------------------------------------------------------------+
//| render etme metodu                                               |     
//+------------------------------------------------------------------+
void CIFS::Render(double scale,bool back)
  {
   m_scale=scale;
   VS_Fill(0);
   RenderIFSToVirtualScreen();
   VirtualScreenToBMP();
   ShowBMP(back);
  }

static int gridmode;
CIFS fern;
int currentscale=50;
//+------------------------------------------------------------------+
//| Uzman Danışman başlatma fonksiyonu                               |
//+------------------------------------------------------------------+
void OnInit()
  {
//-- ızgara modunu al
   gridmode= int (ChartGetInteger(0,CHART_SHOW_GRID,0));
//-- ızgarayı devre dışı bırak
   ChartSetInteger(0,CHART_SHOW_GRID,0);
//-- bmp oluştur
   fern.Create(800,800,0x00);
//-- arka plan görüntüsü olarak göster
   fern.Render(currentscale,true);
  }
//+------------------------------------------------------------------+
//| Uzman Danışman sonlandırma fonksiyonu                            |
//+------------------------------------------------------------------+
void OnDeinit(const int r)
  {
//-- ızgara modunu geri uygula
   ChartSetInteger(0,CHART_SHOW_GRID,gridmode); 
//-- Fern nesnesini sil
   ObjectDelete(0,"Fern");
 }
//+------------------------------------------------------------------+
//| Uzman Danışman OnChart olay yöneticisi                           |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,           // olay tanımlayıcısı
                const long& lparam,   // long türünde olay parametresi
                const double& dparam, // double türünde olay parametresi
                const string& sparam  // string türünde olay parametresi
                )
  {
//--- grafik nesnesine tıkla
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      Print("Şu addaki grafik nesnesindeki olaya tıkla: '"+sparam+"'");
      if(sparam=="Fern")
        {
         // ölçek katsayısını artır (yakınlaştır)
         currentscale=int (currentscale*1.1);
         fern.Render(currentscale,true);
        }
     }
  }
//+------------------------------------------------------------------+

Sonuç:

Şekil 9. CIFS sınıfı ile oluşturulan Barnsley eğrelti otu görüntüsü

Şekil 9. CIFS sınıfı ile oluşturulan Barnsley eğrelti otu görüntüsü


Şekil 10. Barnsley eğrelti otunun yakınlaştırılmış bölümü

Şekil 10. Barnsley eğrelti otunun yakınlaştırılmış bölümü


Şekil 11. Barnsley eğrelti otunun yakınlaştırılmış bölümü

Şekil 11. Barnsley eğrelti otunun yakınlaştırılmış bölümü


Şekil 12. Barnsley eğrelti otunun yakınlaştırılmış bölümü

Şekil 12. Barnsley eğrelti otunun yakınlaştırılmış bölümü

Kendiniz yapın

1. Fractint'te çok sayıda IFS fraktal vardır, örneğin:

// Binary
double IFS_a[3] = { 0.5,  0.5,  0.0};
double IFS_b[3] = { 0.0,  0.0, -0.5};
double IFS_c[4] = { 0.0,  0.0,  0.5};
double 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] = {333, 333, 333};

// Coral
double IFS_a[3] = { 0.307692,  0.307692,  0.000000};
double IFS_b[3] = {-0.531469, -0.076923,  0.54545};
double IFS_c[3] = {-0.461538,  0.153846,  0.692308};
double IFS_d[3] = {-0.293706, -0.447552, -0.195804};
double IFS_e[3] = {5.4019537, -1.295248, -4.893637};
double IFS_f[3] = { 8.6551754.152990,  7.269794};
double IFS_p[3] = {400, 150, 450};

// Crystal
double IFS_a[2] = { 0.696970,  0.090909};
double IFS_b[2] = {-0.481061, -0.443182};
double 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
double IFS_a[2] = { 0.824074,  0.088272};
double IFS_b[2] = { 0.281482,  0.520988};
double IFS_c[2] = {-0.212346, -0.463889};
double IFS_d[2] = { 0.864198, -0.377778};
double IFS_e[2] = {-1.882290,  0.785360};
double IFS_f[2] = {-0.110607,  8.095795};
double IFS_p[2] = {780, 220};

// Floor
double IFS_a[3] = { 0,  0.52,  0};
double IFS_b[3] = {-0.5,   0,  0.5};
double IFS_c[3] = { 0.5,   0, -0.5};
double IFS_d[3] = { 0,   0.5,  0};
double IFS_e[3] = {-1.732366, -0.027891,  1.620804};
double IFS_f[3] = { 3.366182,  5.014877,  3.310401};
double IFS_p[3] = {333, 333, 333};

// Koch3
double 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};
double IFS_p[5] = {151, 254, 254, 151, 190};

// Spiral
double IFS_a[3] = { 0.787879, -0.121212,  0.181818};
double IFS_b[3] = {-0.424242,  0.257576, -0.136364};
double IFS_c[3] = { 0.242424,  0.151515,  0.090909};
double 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,  1.568035};
double IFS_p[3] = {896, 52, 52};

// Swirl5
double IFS_a[2] = {  0.74545, -0.424242};
double IFS_b[2] = {-0.459091, -0.065152};
double IFS_c[2] = { 0.406061, -0.175758};
double IFS_d[2] = { 0.887121, -0.218182};
double IFS_e[2] = { 1.460279,  3.809567};
double IFS_f[2] = { 0.691072,  6.741476};
double IFS_p[2] = {920, 80};

// Zigzag2
double 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] = {888, 112};

Bu kümeleri çizin. IFS katsayılarını kullanarak başlangıç benzerlik dönüşümleri nasıl bulunur?

2. Kendi fraktal kümelerinizi oluşturun ve katsayılarını hesaplayın (alt bölüm 2).

3. Palet renkleriyle (uchar Palette dizisi) oynamayı deneyin, paleti genişletin ve renk gradyanı ekleyin.

4. Barnsley eğrelti otunun fraktal (Hausdorff-Besicovitch) boyutuna ne dersiniz? IFS katsayılarını kullanarak fraktal boyutunun hesaplanması için bir formül var mı?

5. OnChartEvent'teki fare tıklaması koordinatları hakkındaki bilgileri kullanarak belirli bir bölgenin yakınlaştırmasını ekleyin:

void OnChartEvent(const int id,         // olay tanımlayıcısı
                const long& lparam,   // long türünde olay parametresi
                const double& dparam, // double türünde olay parametresi
                const string& sparam  // string türünde olay parametresi
                )
  {
//--- sol düğme tıklaması
   if(id==CHARTEVENT_CLICK)
     {
      Print("Koordinatlar: x=",lparam,"  y=",dparam);
     }
  }

Sonuç

Bu bölümde, Yinelenen Fonksiyon Sistemini (IFS) kullanarak kendine benzer kümeler oluşturma algoritmasını ele aldık.

cIntBMP kütüphanesinin kullanımı, görüntülerle çalışmayı büyük ölçüde basitleştirir. Kullanmış olduğumuz DrawDot(x,y,color) metodunun yanı sıra cIntBMP sınıfı daha birçok faydalı metoda da sahiptir. Bunları da başka bir bölümde ele alacağız.


MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal kod: https://www.mql5.com/ru/code/328

MQL5 Sihirbazı - Stochastic Oscillator Göstergesiyle Onaylı Olarak Tüm Terse Dönüş Mum Modellerinin Kombine Kullanımına Dayalı Ticaret Sinyalleri MQL5 Sihirbazı - Stochastic Oscillator Göstergesiyle Onaylı Olarak Tüm Terse Dönüş Mum Modellerinin Kombine Kullanımına Dayalı Ticaret Sinyalleri

Bu bölümde Stochastic Oscillator göstergesiyle onaylı olarak tüm terse dönüş mum modellerinin kombine kullanımına dayalı ticaret sinyalleri açıklanmaktadır.

Demo_BitmapOffset (OBJPROP_XOFFSET ve OBJPROP_YOFFSET) Demo_BitmapOffset (OBJPROP_XOFFSET ve OBJPROP_YOFFSET)

Varsayalım ki görüntünün şu an için sadece bir bölümünü göstermeniz ve diğer taraflarını gizlemeniz gerekiyor. Bunu yapmak için, görüntünün görünür alanını belirterek kayar pencere kullanabilirsiniz.

DRAW_NONE DRAW_NONE

DRAW_NONE çizim stili, gösterge değerlerinin veri penceresinde hesaplanması ve gösterilmesi ancak grafikte çizilmemesi gerektiğinde kullanılır.

DRAW_LINE DRAW_LINE

DRAW_LINE stili, gösterge arabelleğinin değerlerine göre çizgi çizer.