Fan sayfamıza katılın
Öyleyse bir link gönderin -
başkalarının da faydalanmasını sağlayın
Yinelenen Fonksiyon Sistemi (IFS) Kullanarak MQL5'te Fraktallar Oluşturma - MetaTrader 5 için Uzman Danışman
- Görüntülemeler:
- 261
- Derecelendirme:
- 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:
- ABC -> ADF
- ABC -> DBE
- 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ı
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ü
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
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ü
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ı
İ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
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
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ü
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 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 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.655175, 4.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
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)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.