//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
#include "Unit2.h"
#include "nic_all.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graph wykres;
int MouseX, MouseY;
bool LMB,RMB;
DataFile testee,target,destination,MDdata;
CMDS cs(MDdata,testee);
Procrust pa(testee, target,destination);
Graphics::TBitmap *hidden;
bool autoscale;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
DecimalSeparator='.';

autoscale=false;
this->CheckBox6Click(this);

hidden=new Graphics::TBitmap;
hidden->Height=this->PaintBox1->Height;
hidden->Width=this->PaintBox1->Width;

wykres.Init(hidden);

wykres.SetRange(-10,10,-10,10);
wykres.SetScale(0,this->Edit1->Text.ToDouble(),0,this->Edit2->Text.ToDouble());
wykres.SetDots(this->CheckBox4->Checked);
wykres.SetTags(this->CheckBox5->Checked,this->ComboBox1->ItemIndex,this->ComboBox2->ItemIndex);
Form1->Edit7Change(this);

OpenDialog1->Filter = "Data files (*.dat)|*.DAT";

int fcol=43,vcol=75;
this->StringGrid1->ColWidths[0]=fcol;
this->StringGrid2->ColWidths[0]=fcol;
this->StringGrid3->ColWidths[0]=fcol;
this->StringGrid4->ColWidths[0]=fcol;
this->StringGrid5->ColWidths[0]=fcol;
this->StringGrid6->ColWidths[0]=fcol;
this->StringGrid7->ColWidths[0]=2*fcol;

}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
if (Shift.Contains(ssLeft))
  {
  wykres.Pan(X-MouseX,Y-MouseY);
  ImageCopy();
  MouseX=X;
  MouseY=Y;
  }
  else
    if (Shift.Contains(ssRight))
      {
      //wykres.DrawFrameOnTop(MouseX,X,MouseY,Y);
      ImageCopy();

      TColor pcol=this->PaintBox1->Canvas->Pen->Color;
      TBrushStyle bstyl=this->PaintBox1->Canvas->Brush->Style;

      this->PaintBox1->Canvas->Pen->Color=clBlue;
      this->PaintBox1->Canvas->Brush->Style=bsClear;

      TPoint points[4];
      points[0] = Point(X,Y);
      points[1] = Point(MouseX,Y);
      points[2] = Point(MouseX,MouseY);
      points[3] = Point(X,MouseY);
      this->PaintBox1->Canvas->Polygon(points, 3);

      this->PaintBox1->Canvas->Pen->Color=pcol;
      this->PaintBox1->Canvas->Brush->Style=bstyl;
      }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
MouseX=X;
MouseY=Y;
if ((Shift.Contains(ssLeft)) && !(Shift.Contains(ssRight)) && !(Shift.Contains(ssShift)))
  {
  LMB=true;
  RMB=false;
  }
if ((Shift.Contains(ssRight)) && !(Shift.Contains(ssLeft)) && !(Shift.Contains(ssShift)))
  {
  RMB=true;
  LMB=false;
  }
if ((Shift.Contains(ssDouble)) && (Shift.Contains(ssLeft)))
  {
  wykres.ZoomIn(X,Y);
  ImageCopy();

  double hgrad,vgrad;
  wykres.GetGraduation(&hgrad,&vgrad);
  autoscale=true;
  this->Edit1->Text=hgrad;
  this->Edit2->Text=vgrad;
  autoscale=false;
  }
if ((Shift.Contains(ssDouble)) && (Shift.Contains(ssRight)))
  {
  wykres.ZoomOut(X,Y);
  ImageCopy();

  double hgrad,vgrad;
  wykres.GetGraduation(&hgrad,&vgrad);
  autoscale=true;
  this->Edit1->Text=hgrad;
  this->Edit2->Text=vgrad;
  autoscale=false;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
if (RMB)
  {
  if ((MouseX!=X) && (MouseY!=Y))
    {
    wykres.Zoom(MouseX<X?MouseX:X, MouseX>X?MouseX:X, MouseY<Y?MouseY:Y, MouseY>Y?MouseY:Y);
    ImageCopy();

    double hgrad,vgrad;
    wykres.GetGraduation(&hgrad,&vgrad);
    autoscale=true;
    this->Edit1->Text=hgrad;
    this->Edit2->Text=vgrad;
    autoscale=false;
    }
    else
      {
      wykres.Plot();
      ImageCopy();
      }
  }
}
//---------------------------------------------------------------------------



void __fastcall TForm1::UpDown1Click(TObject *Sender, TUDBtnType Button)
{
this->Edit4->Text=this->UpDown1->Position;
this->CheckBox1Click(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::UpDown2Click(TObject *Sender, TUDBtnType Button)
{
this->Edit5->Text=this->UpDown2->Position;
this->CheckBox1Click(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::UpDown3Click(TObject *Sender, TUDBtnType Button)
{
this->Edit6->Text=this->UpDown3->Position;
this->CheckBox1Click(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit4Change(TObject *Sender)
{
this->UpDown1->Position=this->Edit4->Text.ToInt();
this->CheckBox1Click(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
wykres.ErasePoints();
if (this->CheckBox1->Checked)
  wykres.AddMatrix(pa.pTestee()->rData(),this->Edit4->Text.ToInt(),this->ColorBox1->Selected,pa.pTestee()->rClasses());
if (this->CheckBox2->Checked)
  wykres.AddMatrix(pa.pTarget()->rData(),this->Edit5->Text.ToInt(),this->ColorBox2->Selected,pa.pTarget()->rClasses());
if (this->CheckBox3->Checked)
  wykres.AddMatrix(pa.pDestination()->rData(),this->Edit6->Text.ToInt(),this->ColorBox3->Selected,pa.pDestination()->rClasses());

wykres.Plot();
ImageCopy();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
delete hidden;
}
//---------------------------------------------------------------------------



void __fastcall TForm1::Edit7Change(TObject *Sender)
{
wykres.SetLabels(Edit7->Text,Edit8->Text,Edit9->Text);
wykres.Plot();
ImageCopy();
}
//---------------------------------------------------------------------------



void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{

this->Panel1->Visible=true;
this->Panel2->Visible=false;
this->Panel3->Visible=false;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{

this->Panel2->Visible=true;
this->Panel1->Visible=false;
this->Panel3->Visible=false;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
this->CheckBox1Click(Sender);

this->Panel3->Visible=true;
this->Panel2->Visible=false;
this->Panel1->Visible=false;

//this->Repaint();

}
//---------------------------------------------------------------------------

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
ImageCopy();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ImageCopy()
  {
  PaintBox1->Canvas->CopyRect(PaintBox1->ClientRect, hidden->Canvas, Rect(0,0,hidden->Width,hidden->Height));
  }

//---------------------------------------------------------------------------

void __fastcall TForm1::Message(AnsiString message)
  {
  this->Memo1->Lines->Add(DateTimeToStr(Now())+": "+message);
  }

//---------------------------------------------------------------------------

void __fastcall TForm1::Label11Click(TObject *Sender)
{
if (pa.pDestination()->rData().nrows()!=0)
  {
  SaveDialog1->Filter = "Data files (*.dat)|*.DAT";
  if (SaveDialog1->Execute())
    {
    AnsiString filename=SaveDialog1->FileName+(ExtractFileExt(SaveDialog1->FileName)==".dat"?"":".dat");
    pa.pDestination()->SaveFile(filename);

    this->Message("File "+filename+" saved successfully");

    this->Label11->Caption="  File: "+ExtractFileName(filename);
    this->Label12->Caption="  File Saved";
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton4Click(TObject *Sender)
{
if (this->OpenDialog1->Execute())
  {
  pa.pTestee()->LoadFile(this->OpenDialog1->FileName);
  if ((pa.pTestee()->RegValue("GENERAL","NRFEATURES").ToInt()==2) && (pa.pTestee()->rData().nrows()!=0))
    {
    this->Label7->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
    this->Label8->Caption="  Number of objects: "+IntToStr(pa.pTestee()->rData().nrows());

    this->Message("File "+this->OpenDialog1->FileName+" loaded successfully");
    pa.pTestee()->PrintSection("COMMENTS",Memo1);
    this->SpeedButton5->Enabled=true;
    if (pa.pTestee()->rData().nrows()!=pa.pTarget()->rData().nrows())
      {
      pa.pTarget()->Clear();
      MatrixToStringGrid(pa.pTarget()->rData(),this->StringGrid2);
      this->Label9->Caption="";
      this->Label10->Caption="";
      this->SpeedButton6->Enabled=false;
      }
      else
        this->SpeedButton6->Enabled=true;
    }
    else
      {
      this->Message("Loading file "+this->OpenDialog1->FileName+" unsuccessful: Incorrect number of features");
      pa.pTestee()->Clear();
      this->Label7->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
      this->Label8->Caption="  Incorrect number of features";

      this->SpeedButton5->Enabled=false;
      this->SpeedButton6->Enabled=false;
      }
  MatrixToStringGrid(pa.pTestee()->rData(),this->StringGrid1);
  this->Label1->Caption="";

  pa.pDestination()->Clear();
  MatrixToStringGrid(pa.pDestination()->rData(),this->StringGrid3);
  this->Label11->Caption="";
  this->Label12->Caption="";
  this->SpeedButton7->Enabled=false;
  MatrixToStringGrid(Matrix(0,0),this->StringGrid4);
  this->Label13->Caption="";
  this->Label14->Caption="";
  }        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton5Click(TObject *Sender)
{
if (this->OpenDialog1->Execute())
  {
  pa.pTarget()->LoadFile(this->OpenDialog1->FileName);
  if (pa.pTarget()->RegValue("GENERAL","NRFEATURES")==2)
    {
    if (pa.pTarget()->rData().nrows()==pa.pTestee()->rData().nrows())
      {
      this->Label9->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
      this->Label10->Caption="  Number of objects: "+IntToStr(pa.pTarget()->rData().nrows());

      this->Message("File "+this->OpenDialog1->FileName+" loaded successfully");

      pa.pTarget()->PrintSection("COMMENTS",Memo1);
      this->SpeedButton6->Enabled=true;
      }
      else
        {
        pa.pTarget()->Clear();

        this->Message("Loading file "+this->OpenDialog1->FileName+" unsuccessful: Incorrect number of objects");

        this->Label9->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
        this->Label10->Caption="  Incorrect number of objects";

        this->SpeedButton6->Enabled=false;
        }
    }
    else
      {
      pa.pTarget()->Clear();

      this->Message("Loading file "+this->OpenDialog1->FileName+" unsuccessful: Incorrect number of features");

      this->Label9->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
      this->Label10->Caption="  Incorrect number of features";

      this->SpeedButton6->Enabled=false;
      }
  MatrixToStringGrid(pa.pTarget()->rData(),this->StringGrid2);

  pa.pDestination()->Clear();
  MatrixToStringGrid(pa.pDestination()->rData(),this->StringGrid3);
  this->Label11->Caption="";
  this->Label12->Caption="";
  this->SpeedButton7->Enabled=false;
  MatrixToStringGrid(Matrix(0,0),this->StringGrid4);
  this->Label13->Caption="";
  this->Label14->Caption="";
  }        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton6Click(TObject *Sender)
{
this->Message("PROCRUSTES ANALYSIS...");
TDateTime t1=Now();
pa.ProcrustesAnalysis();
MatrixToStringGrid(pa.pDestination()->rData(),this->StringGrid3);
if (pa.ProcError=="OK")
  {
  this->Label11->Caption="  File Not Saved";
  this->Label12->Caption="  Click to Save";
  this->SpeedButton7->Enabled=true;
  }
  else
    {
    this->Label11->Caption="  Procrustes Analysis Error";
    this->Label12->Caption="  "+pa.ProcError;
    }
this->Message("Finished in "+FloatToStrF(MilliSecondsBetween(Now(),t1)/1000.0,ffFixed,15,3)+" seconds");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton7Click(TObject *Sender)
{
if (pa.ProcError=="OK")
  {
  Matrix *tmp=new Matrix(pa.pTarget()->rData()-pa.pDestination()->rData());
  MatrixToStringGrid(*tmp,this->StringGrid4);
  delete tmp;

  this->Label13->Caption="  Transformation Accuracy: "+FloatToStrF(pa.Accuracy,ffExponent,4,2);
  this->Label14->Caption="";
  }

}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton8Click(TObject *Sender)
{
this->Message("CLASSICAL SCALING...");
TDateTime t1=Now();
unsigned int iterations;
try
  {
  iterations=this->Edit3->Text.ToInt();        //Add a conversion error handling
  if (iterations <= 0)
    {
    this->Edit3->Text="100";
    iterations=100;
    }
  }
  catch(EConvertError &)
    {
    this->Edit3->Text="100";
    iterations=100;
    }

double accuracy=cs.ClassicalScaling(this->CheckBox6->Checked,iterations,this->CheckBox7->Checked);

MatrixToStringGrid(cs.pOUTfile()->rData(),this->StringGrid6);
MatrixToStringGrid(cs.pOUTfile()->rData(),this->StringGrid1);
this->Label15->Caption="  Classical Scaling Accuracy: "+FloatToStrF(accuracy,ffExponent,4,2);
this->Label1->Caption="  File Not Saved";

this->Label7->Caption="  File Not Saved";
this->Label8->Caption="  Number of objects: "+IntToStr(pa.pTestee()->rData().nrows());
this->SpeedButton5->Enabled=true;
if (pa.pTarget()->rData().nrows()==pa.pTestee()->rData().nrows())
  {
  this->SpeedButton6->Enabled=true;
  }
  else
    {
    pa.pTarget()->Clear();
    MatrixToStringGrid(pa.pTarget()->rData(),this->StringGrid2);
    this->Label9->Caption="";
    this->Label10->Caption="";
    this->SpeedButton6->Enabled=false;
    }

pa.pDestination()->Clear();
MatrixToStringGrid(pa.pDestination()->rData(),this->StringGrid3);
this->Label11->Caption="";
this->Label12->Caption="";
this->SpeedButton7->Enabled=false;
MatrixToStringGrid(Matrix(0,0),this->StringGrid4);
this->Label13->Caption="";
this->Label14->Caption="";
this->Message("Finished in "+FloatToStrF(MilliSecondsBetween(Now(),t1)/1000.0,ffFixed,15,3)+" seconds");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton9Click(TObject *Sender)
{
if (this->OpenDialog1->Execute())
  {
  cs.pMDfile()->LoadFile(this->OpenDialog1->FileName);
  if (cs.pMDfile()->rData().nrows()!=0)
    {
    this->Message("File "+this->OpenDialog1->FileName+" loaded successfully");

    this->Label16->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
    this->Label17->Caption="  Number of objects: "+IntToStr(cs.pMDfile()->rData().nrows());
    this->Label18->Caption="  Number of features: "+cs.pMDfile()->RegValue("GENERAL","NRFEATURES")+"  ";
    this->SpeedButton8->Enabled=true;

    Label2->Caption="  Number of features descriptions: "+IntToStr(cs.pMDfile()->PrintFeatures(this->StringGrid7));
    cs.pMDfile()->PrintSection("COMMENTS",Memo1);
    }
    else
      {
      cs.pMDfile()->Clear();

      this->Message("Loading file "+this->OpenDialog1->FileName+" unsuccessful: Incorrect number of objects");

      this->SpeedButton8->Enabled=false;
      this->Label16->Caption="  File: "+ExtractFileName(this->OpenDialog1->FileName);
      this->Label17->Caption="  Incorrect number of objects";
      this->Label18->Caption="";

      this->Label2->Caption="";
      //MDdata.PrintFeatures(this->StringGrid7);
      }
  MatrixToStringGrid(Matrix(0,0),this->StringGrid6);
  this->Label15->Caption="";
  this->Label1->Caption="";
  MatrixToStringGrid(cs.pMDfile()->rData(),this->StringGrid5);

  if ((cs.pMDfile()->rData().nrows() > 0) && (cs.pMDfile()->rData().nrows() == cs.pMDfile()->rData().ncols()))
    {
    this->CheckBox7->Enabled=true;
    //this->CheckBox7->Checked=false;
    }
    else
      {
      this->CheckBox7->Enabled=false;
      this->CheckBox7->Checked=false;
      }

  /*
  for (int i=0; i<cs.pMDfile()->rData().nrows(); i++)
    for (int j=i; j<cs.pMDfile()->rData().ncols();j++)
      if (cs.pMDfile()->rData()[i][j]!=cs.pMDfile()->rData()[j][i])
        this->Message(FloatToStr(cs.pMDfile()->rData()[i][j])+"  "+FloatToStr(cs.pMDfile()->rData()[j][i]));
  */
  //MDdata.PrintSection("COMMENTS",Memo1);
  //MDdata.PrintSection("FEATURES",Memo1);
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Label1Click(TObject *Sender)
{
if ((pa.pTestee()->rData().nrows()!=0) && (this->Label7->Caption=="  File Not Saved") && (this->Label1->Caption=="  File Not Saved"))
  {
  SaveDialog1->Filter = "Data files (*.dat)|*.DAT";
  if (SaveDialog1->Execute())
    {
    AnsiString filename=SaveDialog1->FileName+(ExtractFileExt(SaveDialog1->FileName)==".dat"?"":".dat");
    pa.pTestee()->SaveFile(filename);

    this->Message("File "+filename+" saved successfully");

    this->Label1->Caption="  File: "+ExtractFileName(filename);
    this->Label7->Caption=this->Label1->Caption;
    }
  }
}
//---------------------------------------------------------------------------




void __fastcall TForm1::SpeedButton11Click(TObject *Sender)
{
wykres.AutoScale();
wykres.Plot();

ImageCopy();
double hgrad,vgrad;
wykres.GetGraduation(&hgrad,&vgrad);
autoscale=true;
this->Edit1->Text=hgrad;
this->Edit2->Text=vgrad;
autoscale=false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton12Click(TObject *Sender)
{
SaveDialog1->Filter = "JPEG files (*.jpg)|*.JPG";
if (SaveDialog1->Execute())
  {
  AnsiString filename=SaveDialog1->FileName+(ExtractFileExt(SaveDialog1->FileName)==".jpg"?"":".jpg");
  wykres.ToFile(filename);
  this->Message("File "+filename+" saved successfully");
  }        
}
//---------------------------------------------------------------------------



void __fastcall TForm1::Edit1Change(TObject *Sender)
{
if (autoscale==false)
  {
  double HGrad,VGrad;
  try
    {
    HGrad=this->Edit1->Text.ToDouble();
    }
    catch(EConvertError &)
      {
      this->Edit1->Text="2";
      HGrad=2;
      }
  try
    {
    VGrad=this->Edit2->Text.ToDouble();
    }
    catch(EConvertError &)
      {
      this->Edit2->Text="2";
      VGrad=2;
      }
  wykres.SetScale(0,HGrad,0,VGrad);
  wykres.Plot();
  ImageCopy();
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton13Click(TObject *Sender)
{
Form2->ShowModal();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton14Click(TObject *Sender)
{
if (this->Label4->Visible==true)
  {
  this->Label5->Visible=true;
  this->Edit8->Visible=true;
  this->Label4->Visible=false;
  this->Edit7->Visible=false;
  }
  else
    if (this->Label5->Visible==true)
      {
      this->Label6->Visible=true;
      this->Edit9->Visible=true;
      this->Label5->Visible=false;
      this->Edit8->Visible=false;
      }
      else
        if (this->Label6->Visible==true)
          {
          this->Label4->Visible=true;
          this->Edit7->Visible=true;
          this->Label6->Visible=false;
          this->Edit9->Visible=false;
          }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::CheckBox4Click(TObject *Sender)
{

wykres.SetDots(this->CheckBox4->Checked);
wykres.SetTags(this->CheckBox5->Checked,this->ComboBox1->ItemIndex,this->ComboBox2->ItemIndex);

wykres.Plot();
ImageCopy();

if (this->CheckBox5->Checked)
  {
  this->ComboBox2->Visible=true;
  this->Label21->Visible=true;
  this->Label22->Visible=false;

  if (this->CheckBox4->Checked)
    this->ComboBox1->Visible=true;
    else
      this->ComboBox1->Visible=false;
  }
  else
    {
    this->ComboBox2->Visible=false;
    this->Label21->Visible=false;
    this->Label22->Visible=true;

    this->ComboBox1->Visible=false;
    }
//this->Repaint();

}
//---------------------------------------------------------------------------



void __fastcall TForm1::CheckBox6Click(TObject *Sender)
{
if (this->CheckBox6->Checked)
  {
  this->Label3->Caption="  Maximum Number of Iterations";
  this->Edit3->Text="300";
  }
  else
    {
    this->Label3->Caption="  Number of Iterations";
    this->Edit3->Text="100";
    }
}
//---------------------------------------------------------------------------





void __fastcall TForm1::SpeedButton15Click(TObject *Sender)
{
wykres.Proportional();
wykres.Plot();

ImageCopy();
double hgrad,vgrad;
wykres.GetGraduation(&hgrad,&vgrad);
autoscale=true;
this->Edit1->Text=hgrad;
this->Edit2->Text=vgrad;
autoscale=false;
}
//---------------------------------------------------------------------------

