//---------------------------------------------------------------------------
// Interferencja światła
//
#include <vcl\vcl.h>
#pragma hdrstop

#include "fprzesl.h"
#include "fekran.h"
#include "math.h"
#include "skala.h"
//---------------------------------------------------------------------------
#pragma link "Grids"
#pragma resource "*.dfm"
TPrzeslona *Przeslona;
//---------------------------------------------------------------------------
__fastcall TPrzeslona::TPrzeslona(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Inicjowanie parametrów.
// Wpisanie okrągłego otworka w tablicę P.
//  Odczyt wstępnego pliku
void __fastcall TPrzeslona::FormShow(TObject *Sender)
{
 inicjuj_parametry();
                            //pojedynczy otworek na środku
 int i, j, a = IL_PODZ / 2;

 for( i = 0; i < IL_PODZ; i ++)
    for( j = 0; j < IL_PODZ; j ++)
        P[ i][ j] = 0;      //nie ma dziurek

 Graphics::TBitmap *Bitmap1 = new Graphics::TBitmap();
 try
 {
    Bitmap1->LoadFromFile( "D:\\Helion\\litera.bmp");
    for( int i = 0; i < IL_PODZ; i ++)
        for( int j = 0; j < IL_PODZ; j ++)
            P[i][j] = GetRValue( Bitmap1 -> Canvas -> Pixels[i][j])/255.;
 }
  catch (...)
  {
    MessageBeep(0);
  }
  delete Bitmap1;
}
//---------------------------------------------------------------------------
//  Wyodrębniony algorytm sczytywania nastaw interfejsu.
void TPrzeslona::inicjuj_parametry( void)
{
 try                        //spodziewamy się różnych błędów w danych
 {
    rozm_p = 0.001*Edit1 -> Text.ToDouble();   //szerokość przesłony
    rozm_e = 0.001 * Edit2 -> Text.ToDouble(); //szerokość ekranu
    odl = Edit3 -> Text.ToDouble();            //odległość ekran-przesłona
    L = 1e-6 * Edit4 -> Text.ToDouble();       //dłg. fali światła
 }
 catch(...)                 //nie zmienione wartości parametrów
 {
 }
}
//---------------------------------------------------------------------------
// Wyświetlenie przesłony
void __fastcall TPrzeslona::DrawGrid1DrawCell(TObject *Sender, int Col,
	int Row, TRect &Rect, TGridDrawState State)
{
 int a;
 TColor kolor;                      //do syntezy barwy fizycznej

 a = 240 * P[Col][Row] * P[Col][Row];

 kolor = RGB( a, a, a);

 DrawGrid1 -> Canvas -> Brush -> Color = kolor; //z uzyskanych amplitud złożenie koloru windowsowego
 DrawGrid1 -> Canvas -> FillRect( Rect);
}
//---------------------------------------------------------------------------
// Zbuduj obraz amplitud fal w tablicy E (ekran).
void TPrzeslona :: interferuj( void)
{
 int i, j, m, n;
 double x_p, y_p, x_e, y_e;   //bieżąca pozycja na przesł. i ekr.
 double r;                    //odległość bieżących pozycji przysł. - ekr.
 double odl2 = odl*odl;       //pomocnicze - kwadrat odległości przysł.-ekr.
 double k = 2 * M_PI/L;       //pomocnicze - tzw. liczba falowa
 double suma_fal;             //amplituda złożenia fal ze wszystkich otworków
 double min_suma_fal=0, max_suma_fal=0;	//wartości skrajne do unormowania amplitud na ekranie
 TSkalowanie s_p( 0, 0, IL_PODZ-1, IL_PODZ-1, 0, 0, rozm_p, rozm_p);
 TSkalowanie s_e( 0, 0, IL_PODZ-1, IL_PODZ-1, 0, 0, rozm_e, rozm_e);

 for( i = 0; i < IL_PODZ; i++)
 {
    x_e = s_e.daj_real_x( i);
    for( j = 0; j < IL_PODZ; j++)
    {
        y_e = s_e.daj_real_y( j);
        suma_fal = 0.0;             //ważne. Za chwilę zbierzemy tutaj amplitudy
        for( m = 0; m < IL_PODZ; m++)
        {
            x_p = s_p.daj_real_x( m);
            for( n = 0; n < IL_PODZ; n++)
            {
                if( P[m][n]!=0)    //jest dziurka?
                {
                    y_p = s_p.daj_real_y( n);
                    r = sqrt((x_e-x_p) * (x_e-x_p) + (y_e-y_p) * (y_e-y_p) + odl2);
                    suma_fal += P[m][n] * sin( k*r);
                }
            }
        }
        Ekran -> E[i][j] = suma_fal; //przechowanie wyliczonej amplitudy
        if( suma_fal < min_suma_fal)
       	    min_suma_fal = suma_fal; //wyłapanie najmniejszej amplitudy
        if( suma_fal > max_suma_fal)
       	    max_suma_fal = suma_fal; //wyłapanie największej amplitudy
    }
 }
 if( max_suma_fal < -min_suma_fal)   //która ze skrajnych wartości jest bezwzględnie większa?
    max_suma_fal = - min_suma_fal;
 if( max_suma_fal != 0)
 {
    for( i = 0; i < IL_PODZ; i ++)   //zawartość tablicy unormuj do zakresu -1 ...+1
	    for( j = 0; j < IL_PODZ; j ++)
            Ekran -> E[i][j] = Ekran -> E[i][j] / max_suma_fal;
 }
}
//---------------------------------------------------------------------------
// Odśwież ekran
void __fastcall TPrzeslona::Button1Click(TObject *Sender)
{
 inicjuj_parametry();
 interferuj();
 Ekran -> Show();
 Ekran -> DrawGrid1 -> Refresh();       //pokaż ekran
}
//---------------------------------------------------------------------------
//  Odczytaj obraz
void __fastcall TPrzeslona::Button3Click(TObject *Sender)
{
 int i, j;
 Graphics::TBitmap *Bitmap1 = new Graphics::TBitmap();
 try
 {
   Bitmap1->LoadFromFile( "D:\\Helion\\litera.bmp");
   for( i = 0; i < IL_PODZ; i ++)
      for( j = 0; j < IL_PODZ; j ++)
          P[i][j] = GetRValue( Bitmap1 -> Canvas -> Pixels[i][j])/255.;
 }
 catch (...)
 {
   MessageBeep(0);
 }
 delete Bitmap1;
}
//---------------------------------------------------------------------------
//  Zapisz obraz na dysku
void __fastcall TPrzeslona::Button4Click(TObject *Sender)
{
 int i, j, a;
 Graphics::TBitmap *Bitmap1 = new Graphics::TBitmap();
 try
 {
   for( i = 0; i < IL_PODZ; i ++)
   {
      for( j = 0; j < IL_PODZ; j ++)
      {
          a = P[i][j] * 255;
          Bitmap1 -> Canvas -> Pixels[i][j] = RGB( a, a, a);
      }
   }
   Bitmap1->SaveToFile( "D:\\Helion\\litera.bmp");
 }
 catch (...)
 {
   MessageBeep(0);
 }
 delete Bitmap1;
}
//---------------------------------------------------------------------------
// Zakończ
void __fastcall TPrzeslona::Button2Click(TObject *Sender)
{
 Close();
}
//---------------------------------------------------------------------------
// Naciśnięto myszkę na przesłonie
void __fastcall TPrzeslona::DrawGrid1MouseDown(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
 start_zaznacz_x = DrawGrid1 -> Col;    //początek zaznaczania
 start_zaznacz_y = DrawGrid1 -> Row;
}
//---------------------------------------------------------------------------
// Puszczono myszkę
// Zmień stan otworków między tą pozycją myszki a miejscem jej naciśnięcia
void __fastcall TPrzeslona::DrawGrid1MouseUp(TObject *Sender,
	TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int i, j, a, b, c, d;

 if( start_zaznacz_x < DrawGrid1 -> Col)
 {
    a = start_zaznacz_x;
    b = DrawGrid1 -> Col;
 }
 else
 {
    a = DrawGrid1 -> Col;
    b = start_zaznacz_x;
 }

 if( start_zaznacz_y < DrawGrid1 -> Row)
 {
    c = start_zaznacz_y;
    d = DrawGrid1 -> Row;
 }
 else
 {
    c = DrawGrid1 -> Row;
    d = start_zaznacz_y;
 }

 for( i = a; i <= b; i ++)
    for( j = c; j <= d; j ++)
        P[i][j] = P[i][j] == 0? 1 : 0;   //negacja układu dziurek

 DrawGrid1 -> Refresh();
}
//---------------------------------------------------------------------------
void __fastcall TPrzeslona::FormKeyPress(TObject *Sender, char &Key)
{
 if( Key == VK_ESCAPE)
    Close();
}
//---------------------------------------------------------------------------

