//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "math.h"
#include "wykr3d.h"
//---------------------------------------------------------------------------
//	Konstruktor główny, inicjujący wszystkie parametry wykresu.
//	Posługuje się konstruktorem odziedziczonym z T3d.
TWykres3d :: TWykres3d(
    TPunkt obs,                             //pozycja obserwatora
    TPunkt osw,                             //pozycja punktu oświetlającego
    double xr0, double yr0, double rszer, double rwys,//obszar funkcji
    int il_x, int il_y,                     //dokładność kreślenia - liczba podziałów dziedziny
    int xe0, int ye0, int eszer, int ewys,  //okno ekranowe
    double odl_ekr/*=0.5*/,
    double szer_ekr/*=0*/, double wys_ekr/*=0*/)//fizyczny opis ekranu
    : T3d(  obs,
            xe0, ye0, eszer, ewys,
            odl_ekr, szer_ekr, wys_ekr)
{
 double r;

 fil_x = il_x;                              //udostępnienie (poprzez zmienne prywatne) innym funkcjom
 fil_y = il_y;

 r = sqrt( osw.x*osw.x+osw.y*osw.y+osw.z*osw.z);//długość wektora wskazującego oświetlenie
 vxosw = osw.x / r;                         //unormowane składowe wektora wskazującego oświetlenie
 vyosw = osw.y / r;
 vzosw = osw.z / r;

 if( obs.x > 0)                              //kierunek kreślenia - od fragmentów najdalszych
 {
    xstart  = xr0 - rszer / 2.;
    xkoniec = xr0 + rszer / 2.;
    dx = rszer / (double) il_x;
 }
 else
 {
    xstart  = xr0 + rszer / 2.;
    xkoniec = xr0 - rszer / 2.;
    dx = -rszer / (double) il_x;
 }

 if( obs.y > 0)
 {
    ystart  = yr0 - rwys / 2.;
    ykoniec = yr0 + rwys / 2.;
    dy = rwys / (double) il_y;
 }
 else
 {
    ystart  = yr0 + rwys / 2.;
    ykoniec = yr0 - rwys / 2.;
    dy = -rwys / (double) il_y;
 }
}
//---------------------------------------------------------------------------
//	Opis kreślonej płachty funkcyjnej.
//	Użytkownik obiektu TWykres3d musi przedefiniować tą funkcję,
//	wprowadzając do gry własną formułę.
double TWykres3d :: fun( double x, double y)
{
 return 0;
}
//---------------------------------------------------------------------------
//	zapoczątkowanie procesu przeglądania obszaru funkcji
void TWykres3d :: inicjuj_iterator( void)
{
 i = j = 0;								//start dla funkcji iterator()
}
//---------------------------------------------------------------------------
//	Gdy true, dostarcza punktów do kreślenia czworokątnych elementów wykresu.
//	false - koniec kreślenia.
//	jasnosc jest unormowana od 0 do 100 (jasnosc procentowa).
bool TWykres3d :: iterator( int &xe1, int &ye1, int &xe2, int &ye2,
							 int &xe3, int &ye3, int &xe4, int &ye4,
                            int &jasnosc)
{
 TPunkt p1, p2, p3, p4;
 double ax, ay, az, bx, by, bz;         //wektory rozpinające element
 double cx, cy, cz;                     //iloczyn wektorowy wektorów a i b
 double r;

 while( i < fil_y)                      //kontynuuj, gdy nie koniec wykresu
 {
    p1.y = p4.y = ystart + (double)i * dy;
    p2.y = p3.y = p1.y + dy;

    while( j < fil_x)                   //kontynuuj, nie koniec linii w poziomie
    {
        p1.x = p2.x = xstart + (double)j * dx;
        p3.x = p4.x = p1.x + dx;

        p1.z = fun( p1.x, p1.y);
        p2.z = fun( p2.x, p2.y);
        p3.z = fun( p3.x, p3.y);
        p4.z = fun( p4.x, p4.y);

        punkt_3d( xe1, ye1, p1);        //ta funkcja jest w obiekcie odziedziczonym (bazowym)
        punkt_3d( xe2, ye2, p2);
        punkt_3d( xe3, ye3, p3);
        punkt_3d( xe4, ye4, p4);

        ax = dx;                        //jeden wektor rozpinający element wykresu
        ay = 0;
        az = p4.z - p1.z;

        bx = 0;                         //drugi
        by = dy;
        bz = p2.z - p1.z;

        cx = ay * bz - az * by;         //iloczyn wektorowy wektorów rozpinających
        cy = az * bx - ax * bz;
        cz = ax * by - ay * bx;

        r = sqrt( cx * cx + cy * cy + cz * cz);
        cx = cx / r;                    //unormowanie do długości = 1.
        cy = cy / r;
        cz = cz / r;

        jasnosc = (int)(50. * (1. + vxosw * cx + vyosw * cy + vzosw * cz));

        j ++;

        return true;
    }
    if( j >= fil_x)
        j = 0;
    i ++;
 }
 return false;                          //koniec przeglądania obszaru wykresu
}

