/*
 * Author:       Simon Dexter
 * Source:       Unit1.cpp
 * Project:      Vladimir Arnold's Cat Map
 * Name:         Unit 1
 * Description:  Main source file
 * Date started: 04/07/08
 * Date modified:
 *               01/14/09 11:54 pm
 *               01/15/09 11:06 pm
 *               modified the debugging options in Tools->Debugger Options
 *               removed "Integrated Debugging" option to allow for inbuilt
 *               try-catch block mechanisms to work in debugging mode
 *               03/01/09 01:14 pm
 *                  added the call to yield processing time which allows for
 *                  morphing like effect
 */

#include    <vcl.h>
#pragma     hdrstop
#include    "Unit1.h"
#include    <math.h>
#include    <exception>
#pragma     package(smart_init)
#pragma     resource "*.dfm"

using namespace std;
                         
TForm1 * Form1;

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {}

// subroutine for drawing a point on the cartesian plane
void CartesianPlane::drawPoint (double x, double y){
        int x1 = 0, x2 = 0, y1 = 0 , y2 = 0;
        if (x < xmin || x > xmax || y < ymin || y > ymax)
                return;
        if (xmax - xmin == 0 || ymax - ymin == 0)
                return;
        x1 =  (int) ( (x - xmin) * ((double) this->length) / ((double) (xmax-xmin)));
        y1 =  (int) ( (ymax -y) * ((double) this->height) / ((double) (ymax-ymin)));

        if (x1 > this->length || x1 < 0 || y1 > this->height || y1 < 0)
                return;
        x2 = x1 + 2;
        y2 = y1 + 2;
        this->canvas->Ellipse (x1, y1, x2, y2);
};

// subroutine for clearing cartesian plane
void CartesianPlane::clear(){
        TRect * rect = new TRect(0,0, length, height);
        this->canvas->FillRect( *rect);
};

// constructor
CartesianPlane::CartesianPlane (TCanvas * canvas, int length, int height, int xmin, int xmax, int ymin, int ymax){
        this->length = length;
        this->height = height;
        this->xmax = xmax;
        this->xmin = xmin;
        this->ymax = ymax;
        this->ymin = ymin;
        this->canvas = canvas;
};

void __fastcall TForm1::BitBtn1Click(TObject *Sender){
        this->OpenDialog1->Execute();
        TPicture * picture = new TPicture();
        try {
                picture->LoadFromFile( this->OpenDialog1->FileName );
        } catch (...){
                ShowMessage ("Unable to open specified file");
                return;
        }
        if (picture->Width != picture->Height ) {
                ShowMessage ("Picture is not of square dimensions. Cat map is unable to proceed.");
                return;
        }
        this->Image1->Picture = picture;

        int w = this->Image1->Picture->Width;
        int h = this->Image1->Picture->Height;

        this->Label4->Caption = w;
        this->Label5->Caption = h;

        this->pointArray = new MapPoint * * [w];
        for (int i = 0; i < w; i++){
                this->pointArray [i] = new  MapPoint * [h];
                for (int j = 0; j < h; j++){
                        this->pointArray [i][j] = new MapPoint();
                        this->pointArray [i][j]->x = i;
                        this->pointArray [i][j]->y = j;
                        this->pointArray [i][j]->color = this->Image1->Canvas->Pixels[i][j];
                }
        }
}

//---------------------------------------------------------------------------
// main cat map algorithm
void __fastcall TForm1::BitBtn3Click(TObject *Sender) {
        int w = this->Image1->Picture->Width;
        int h = this->Image1->Picture->Height;
        long double wd = w;
        long double hd = h;
        int iterations = this->Edit1->Text.ToInt(); // taking specified number of iterations
        long double xt, yt, xp, yp;
        this->ProgressBar1->Min = 0;
        this->ProgressBar1->Max = w;
        for (int x = 0; x < w; x++){
                for (int y = 0; y < h; y++){
                        xp = this->pointArray [x][y]->x;
                        yp = this->pointArray [x][y]->y;
                        for (int i = 0; i < iterations; i++){
                                xt = fmod( xp + yp, wd);
                                yt = fmod(xp + 2.0 * yp, hd);
                                xp = xt;
                                yp = yt;
                        }
                        this->pointArray [x][y]->x = xt;
                        this->pointArray [x][y]->y = yt;
                        this->Image1->Canvas->Pixels [ xt ][yt ] = this->pointArray [x][y]->color;
                }
                this->ProgressBar1->StepBy(1);
                // added on 03/01/09
                // makes the image morph
                Application->ProcessMessages();
                Sleep(1);

        }
        ShowMessage ("Cat map completed");
        this->ProgressBar1->Position = 0;
        // resetting number of iterations
        this->Edit1->Text = 1;
};

// saving resultant picture
void __fastcall TForm1::Button1Click(TObject *Sender) {
    this->SaveDialog1->Execute();
    this->Image1->Picture->SaveToFile(this->SaveDialog1->FileName );
}
//---------------------------------------------------------------------------

