//=========================================================================== // LORENZ ATTRACTOR // Nicholas Gessler // July 2006 // http://www.zeuscat.com/andrew/chaos/lorenz.html // http://www.planetmath.org/ehcyclopeda/LorenzEquation.html // dx/dt = p * (y - x) // dy/dt = r * x - y - x * 2 // dz/dt = x * y - b * z //=========================================================================== #include #pragma hdrstop #include "Unit1.h" #define BLACK 0 #define RED 1 #define CYAN 2 #define WHITE 3 #define COLOR 0 #define ANAGLYPH 1 //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- //=========================================================================== // VARIABLES //=========================================================================== double x = 3; double dx; double p = 10; // Prandt number double y = 15; double dy; double r = 28; // Rayleigh Number double z = 1; double dz; double b = 8 / 3; // Height to width ratio of box double dt = .0001; int i; int times = 1200000; bool stop = false; int array[1000][880]; int xx, yy, zz; //=========================================================================== // FUNCTIONS //=========================================================================== int colorRamp(int value, int maximum) { int pixelDistanceAlongPath = float(value) / float(maximum) * 1792; int red, green, blue; // Which edge of the color cube are we on? if (pixelDistanceAlongPath < 256) { // Edge 1 from BLACK to BLUE red=0; green=0; blue=pixelDistanceAlongPath; } else if (pixelDistanceAlongPath < 512) { // Edge 2 from BLUE to CYAN red =0; green=pixelDistanceAlongPath-256; blue=255; } else if (pixelDistanceAlongPath < 768) { // Edge 3 from CYAN to GREEN red =0; green =255; blue= 255-(pixelDistanceAlongPath-512); } else if (pixelDistanceAlongPath < 1024) { // Edge 4 from GREEN to YELLOW red= (pixelDistanceAlongPath-768); green =255; blue =0; } else if (pixelDistanceAlongPath <1280) { // Edge 5 from YELLOW to RED red =255; green=255-(pixelDistanceAlongPath-1024); blue =0; } else if (pixelDistanceAlongPath < 1536) { // Edge 6 from RED to MAGENTA red =255; green=0; blue=pixelDistanceAlongPath -1280; } else { // Edge 7 from MAGENTA to WHITE red =255; green=pixelDistanceAlongPath-1536; blue =255; } return (RGB(red, green, blue)); } void step (void) { i++; dx = (p * (y - x)); dy = ((r * x) - y - (x * z)); dz = ((x * y) - (b * z)); x = x + dx * dt; y = y + dy * dt; z = z + dz * dt; xx = Int(x * 1.5); // scaling for plot yy = Int(y * 16 + 450); zz = Int(z * 16 - 10); if (Form1->RadioGroup1->ItemIndex == COLOR) { // colorRamp // draw color Form1->PaintBoxYZ->Canvas->Pixels[yy][zz] = static_cast(colorRamp(i + 100000, 1300000)); if (yy > 0 && yy < 1000 && zz > 0 && zz < 880) { array[yy][zz] = i; } } if (Form1->RadioGroup1->ItemIndex == ANAGLYPH) { // 3D anaglyph // draw pure color if (clBlack == Form1->PaintBoxYZ->Canvas->Pixels[yy][zz]) { Form1->PaintBoxYZ->Canvas->Pixels[yy][zz] = clRed; } if (clBlack == Form1->PaintBoxYZ->Canvas->Pixels[yy + xx][zz]) { Form1->PaintBoxYZ->Canvas->Pixels[yy + xx][zz] = clAqua; } // draw corrected color if (clAqua == Form1->PaintBoxYZ->Canvas->Pixels[yy][zz]) { Form1->PaintBoxYZ->Canvas->Pixels[yy][zz] = clWhite; } if (clRed == Form1->PaintBoxYZ->Canvas->Pixels[yy + xx][zz]) { Form1->PaintBoxYZ->Canvas->Pixels[yy + xx][zz] = clWhite; } // record pure color if (array[yy][zz] == BLACK) { array[yy][zz] = RED; } if (array[yy + xx][zz] == BLACK) { array[yy + xx][zz] = CYAN; } // record corrected color if (array[yy][zz] == CYAN) { array[yy][zz] = WHITE; } if (array[yy + xx][zz] == RED) { array[yy + xx][zz] = WHITE; } } Form1->EditIterations->Text = i; } void run (void) { while (!stop) { step(); Application->ProcessMessages(); if (i >= times) stop = true; } } void reDraw (void) { if (Form1->RadioGroup1->ItemIndex == COLOR) { for (int i = 0; i < 1000; i++) { for (int j = 0; j < 880; j++) { if (array[i][j] == 0) { Form1->PaintBoxYZ->Canvas->Pixels[i][j] = clBlack; } else Form1->PaintBoxYZ->Canvas->Pixels[i][j] = static_cast (colorRamp(array[i][j] + 100000, 1300000)); } } } if (Form1->RadioGroup1->ItemIndex == ANAGLYPH) { for (int i = 0; i < 1000; i++) { for (int j = 0; j < 880; j++) { if (array[i][j] == BLACK) { Form1->PaintBoxYZ->Canvas->Pixels[i][j] = clBlack; } if (array[i][j] == RED) { Form1->PaintBoxYZ->Canvas->Pixels[i][j] = clRed; } if (array[i][j] == CYAN) { Form1->PaintBoxYZ->Canvas->Pixels[i][j] = clAqua; } if (array[i][j] == WHITE) { Form1->PaintBoxYZ->Canvas->Pixels[i][j] = clWhite; } } } } } //=========================================================================== // EVENT HANDLERS //=========================================================================== void __fastcall TForm1::ButtonRunClick(TObject *Sender) { stop = false; run(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonStepClick(TObject *Sender) { step(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonResetClick(TObject *Sender) { for (int i = 0; i < 1000; i++) { for (int j = 0; j < 880; j++) { array[i][j] = 0; } } Form1->Refresh(); i = 0; x = 3; y = 15; z = 1; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarDTChange(TObject *Sender) { switch (TrackBarDT->Position) { case 0: { dt = .02; //times = 500000; //500; break; } case 1: { dt = .01; //times = 500000; //1000; break; } case 2: { dt = .001; //times = 500000; //10000; break; } case 3: { dt = .0001; //times = 500000; //100000; break; } } Form1->EditDT->Text = dt; } //--------------------------------------------------------------------------- void __fastcall TForm1::ComboBoxRayleighChange(TObject *Sender) { switch (ComboBoxRayleigh->ItemIndex) { case 0: { r = 28; break; } case 1: { r = 15; break; } case 2: { r = 14; break; } case 3: { r = 13; break; } } p=10; Form1->TrackBarR->Position = r; Form1->EditR->Text = r; Form1->TrackBarP->Position = p; Form1->EditP->Text = p; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonStopClick(TObject *Sender) { stop = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { reDraw(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarRChange(TObject *Sender) { r = TrackBarR->Position; Form1->EditR->Text = r; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarPChange(TObject *Sender) { p = TrackBarP->Position; Form1->EditP->Text = p; } //---------------------------------------------------------------------------