#include <graphics.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
struct bod3D {double x,y,z;};
struct bod2D {double x,y;};
int xmin=10,xmax=630,ymin=0,ymax=445;
double umin=0,umax=3.14,vmin=0,vmax=100;
int ake_zobrazenie=1,aka_plocha=1;
typedef char *str;
div_t pom;
int n=20,m=20,delenie=10;
double f(double x)    /*definicia f*/
{
double y=50*x;
return y;
}

double g(double x)    /*def g*/
{
double y=0;
return y;
}

double h(double x)   /*def h*/
{
double y=50*cos(x)+50;
return y;
}

bod3D plocha(double u,double v)  /*vypocet 3dbodu z parametrov*/
{
bod3D p;
switch (aka_plocha)
   {
  case 1:      /*rotacna plocha*/
      {
    p.x=f(u)*cos(v)-g(u)*sin(v);
    p.y=f(u)*sin(v)+g(u)*cos(v);
    p.z=h(u);
    break;
      }
  case 2:      /*skrutkova plocha*/
      {
    double parameter=10;
    p.x=f(u)*cos(v)-g(u)*sin(v);
    p.y=f(u)*sin(v)+g(u)*cos(v);
    p.z=h(u)+parameter*v;
    break;
      }
  case 3:      /*konoidna plocha*/
      {
    double c=100,d=0;
    p.x=f(u);
    p.y=c*(1-v);
    p.z=d*(1-v)+v*h(u);
    break;
      }
  case 4:      /*translacna plocha*/
      {
    p.x=f(u);
    p.y=g(u)+v;
    p.z=h(u)+(100-v*v/100)-100;
    break;
      }
  case 5:      /*klinova plocha*/
      {
    p.x=f(u);
    p.y=g(u)+v;
    p.z=h(u)*(100-v*v/100)/100;
      }
   }
return p;
}
bod2D zobrazenie(bod3D moj)  /*vypocet 2dbodu vo vybranom zobrazeni*/
{
bod2D p;
switch (ake_zobrazenie)
   {
 case 1:                     /*bodove premietanie so stredom s1,s2,s3*/
     {
    int s1=100,s2=100,s3=100;
    double uu=sqrt(s1*s1+s2*s2);
    double tt=(-1)*(sqrt(s1*s1+s2*s2+s3*s3))/(moj.x*s1+moj.y*s2+moj.z*s3-s1*s1-s2*s2-s3*s3);
    p.y=tt*(moj.z*(s1*s1+s2*s2)-moj.x*s1*s3-moj.y*s2*s3)/uu;
    p.x=(sqrt(s1*s1+s2*s2+s3*s3))*tt*(s1*moj.y-s2*moj.x)/uu;
    break;
     }
 case 2:                     /*vojenska projekcia*/
     {
    double alfa=3.14/4;
    p.x=-moj.x*cos(alfa)+moj.y*sin(alfa);
    p.y=-moj.x*sin(alfa)-moj.y*cos(alfa)+moj.z;
    break;
     }
  case 3:                   /*kavalierna perspektiva*/
     {
    double beta=1*3.14/4;
    p.x=moj.y*cos(beta)-moj.x;
    p.y=moj.z-moj.y*sin(beta);
    break;
     }
  case 4:                   /*pravouhla axonometria*/
     {
    double alfa=3.14/5,beta=3.12/6;
    double ex=sqrt(sin(beta)/cos(alfa)/sin(alfa+beta));
    double ey=sqrt(sin(alfa)/cos(beta)/sin(alfa+beta));
    double ez=sqrt(cos(alfa+beta)/cos(alfa)/cos(beta));
    p.x=moj.y*ey*cos(beta)-moj.x*ex*cos(alfa);
    p.y=moj.z*ez-moj.x*ex*sin(alfa)-moj.y*ey*sin(beta);
    break;
     }
  case 5:                   /*kosouhla axonometria*/
     {
    double alfa=10*3.14/180,beta=3.14/4;
    double ex=2,ey=1.5,ez=2;
    p.x=moj.y*ey*cos(beta)-moj.x*ex*cos(alfa);
    p.y=moj.z*ez-moj.x*ex*sin(alfa)-moj.y*ey*sin(beta);
    break;
     }
  case 6:                   /*kosouhle premietanie*/
     {
    double koef=.5;
    double beta=3.14/4;
    p.x=moj.y*koef*cos(beta)-moj.x;
    p.y=moj.z-moj.y*koef*sin(beta);
    break;
     }
  case 7:                   /*monge xy*/
     {
    p.x=moj.x;
    p.y=moj.y;
    break;
     }
  case 8:                   /*monge xz*/
     {
    p.x=moj.x;
    p.y=moj.z;
    break;
     }
  case 9:                   /*monge yz*/
     {
    p.x=moj.y;
    p.y=moj.z;
    break;
     }
   }
return p;
}
int max(int m,int a,int b,int c,int d,int e) /*hlada maximum*/
{
 int po[6]={m,a,b,c,d,e};
 int vysl=po[0];
 for (int i=0;i<5;i++) if (po[i+1]>vysl) vysl=po[i+1];
 return vysl;
}
int menu(int pocetp,str meno,str a,str b,str c,str d,str e) /*MENU*/
{
 settextstyle(6,0,3);
 setfillstyle(1,0);
 setcolor(15);
 int vyska=(textheight(a))*(pocetp+1)+25;
 int sirka=20+max(textwidth(meno),textwidth(a),textwidth(b),textwidth(c),textwidth(d),textwidth(e));
 pom=div((getmaxx()-sirka),2);int x=pom.quot;
 pom=div((getmaxy()-vyska-50),2);int y=pom.quot;
 int aktual=1;
 unsigned size=imagesize(x,y,x+sirka,y+vyska);
 void *imag;
 imag = malloc(size);
 getimage(x,y,x+sirka,y+vyska,imag);
 str pole[5]={a,b,c,d,e};
 bar(x,y,x+sirka,y+vyska);
 rectangle(x+2,y+2,x+sirka-2,y+vyska-2);
 pom=div(sirka-textwidth(meno),2);
 rectangle(x+5,y+5,x+sirka-5,y+5+textheight(meno)+10);
 setcolor(2);
 outtextxy(x+pom.quot,y+5,meno);
 int klav=0;
 while(klav !=13)
    {
 for(int i=1;i<pocetp+1;i++)
       {
      setcolor(4);
      if (i==aktual) setcolor(9);
      pom=div(sirka-textwidth(pole[i-1]),2);
      outtextxy(x+pom.quot,y+10+textheight(meno)+(textheight(a))*(i-1),pole[i-1]);
       }
  klav=getch();
  if (klav==80) aktual++;
  if (klav==72) aktual--;
  if (aktual==0) aktual=pocetp;
  pom=div(aktual,pocetp);
  if (pom.rem==0) aktual=pocetp;
     else aktual=pom.rem;
   }
 putimage(x,y,imag,0);
 free(imag);
 return aktual;
}

void main(void)
{
int vrat;
bod3D pom3D1,pom3D2;
bod2D pom2D1,pom2D2;
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "c:\\BORLANDC\\BGI");
errorcode = graphresult();
if (errorcode != grOk)
{
   printf("Graphics error: %s\n", grapherrormsg(errorcode));
   printf("Press any key to halt:");
   getch();
   exit(1);
}
while (vrat!=4)
    {
 setviewport(0,0,639,479,1);
 cleardevice();
 settextstyle(6,0,7);
 setcolor(12);
 outtextxy(40,0,"Zobrazovacie metody");
 settextstyle(6,0,1);
 setcolor(14);
 outtextxy(450,420,"Vyrobil : Samo 1999");
 str txt1,txt2;
 switch (ake_zobrazenie)
	{
     case 1:
	  {
	 txt1="Bodove premietanie";
	 break;
	  }
     case 2:
	  {
	 txt1="Vojenska perspektiva";
	 break;
	  }
     case 3:
	  {
	 txt1="Kavalierna projekcia";
	 break;
	  }
     case 4:
	  {
	 txt1="Pravouhla axonometria";
	 break;
	  }
     case 5:
	  {
	 txt1="Kosouhla axonometria";
	 break;
	  }
     case 6:
	  {
	 txt1="Kosouhle premietanie";
	 break;
	  }
     case 7:
	  {
	 txt1="Monge xy";
	 break;
	  }
     case 8:
	  {
	 txt1="Monge xz";
	 break;
	  }
     case 9:
	  {
	 txt1="Monge yz";
	 break;
	  }
       }
 switch (aka_plocha)
       {
     case 1:
	 {
	txt2="Rotacna plocha";
        vmin=0;vmax=2*3.14;
	break;
	 }
     case 2:
	 {
	txt2="Skrutkova plocha";
	vmin=0;vmax=4*3.14;
	break;
	 }
     case 3:
	 {
	txt2="Konoidna plocha";
	vmin=0;vmax=1;
	break;
	 }
     case 4:
	 {
	txt2="Translacna plocha";
	vmin=0;vmax=100;
	break;
	 }
     case 5:
	 {
	txt2="Klinova plocha";
        vmin=0;vmax=100;
	break;
	 }
       }
 settextstyle(6,0,4);
 setcolor(11);
 outtextxy(100,300,"Zobrazenie:");
 outtextxy(250,300,txt1);
 outtextxy(100,340,"Plocha:");
 outtextxy(250,340,txt2);
 vrat=menu(4,"Hlavny vyber","Vyber zobrazenie","Vyber plochu","Zobraz","Koniec","");
 if (vrat==1)
	   {
	ake_zobrazenie=menu(3,"Vyber zobrazenie","Bodove premietanie","Axonometria","Mongeova projekcia","","");
	switch (ake_zobrazenie)
		     {
		     case 2:
			 {
		       ake_zobrazenie=1+menu(5,"Axonometria","Vojenska projekcia","Kavalierna perspektiva","Pravouhla axonometria","Kosouhla axonometria","Kosouhle premietanie");
		       break;
			 }
		     case 3:
			 {
		       ake_zobrazenie=6+menu(3,"Mongeova projekcia","do xy","do xz","do yz","","");
		       break;
			 }
		     }
	   }
 if (vrat==2) aka_plocha=menu(5,"Vyber plochu","Rotacna","Skrutkova","Konoidna","Translacna","Klinova");
 if (vrat==3)
   {
 cleardevice();
 setcolor(WHITE);
 double stx=(xmax-xmin)/2,sty=(ymax-ymin)/2;  /*Kde bude (0,0)*/
 double par=.45;     /*na zobrazenie nazvu osy*/
 rectangle(xmin,ymin,xmax,ymax);
 settextstyle(6,0,3);
 setcolor(11);
 outtextxy(10,ymax+2,txt1);
 outtextxy(350,ymax+2,txt2);
 settextstyle(6,0,1);
 setviewport(xmin,ymin,xmax,ymax,1);
 setcolor(RED);
 pom3D1.x=200;pom3D1.y=0;pom3D1.z=0;
 pom2D1=zobrazenie(pom3D1);
 line(stx,sty,stx+pom2D1.x,sty-pom2D1.y);
 outtextxy(stx+par*pom2D1.x+1,sty-par*pom2D1.y,"x");
 setcolor(GREEN);
 pom3D1.x=0;pom3D1.y=200;pom3D1.z=0;
 pom2D1=zobrazenie(pom3D1);
 line(stx,sty,stx+pom2D1.x,sty-pom2D1.y);
 outtextxy(stx+par*pom2D1.x-1,sty-par*pom2D1.y,"y");
 setcolor(BLUE);
 pom3D1.x=0;pom3D1.y=0;pom3D1.z=200;
 pom2D1=zobrazenie(pom3D1);
 line(stx,sty,stx+pom2D1.x,sty-pom2D1.y);
 outtextxy(stx+par*pom2D1.x+2,sty-par*pom2D1.y,"z");
 setcolor(YELLOW);
 for (int i=0;i<=n;i++) for (int j=0;j<delenie*m;j++)
	    {
	  pom3D1=plocha(umin+(umax-umin)*i/n,vmin+(vmax-vmin)*j/delenie/m);
	  pom3D2=plocha(umin+(umax-umin)*i/n,vmin+(vmax-vmin)*(j+1)/delenie/m);
	  pom2D1=zobrazenie(pom3D1);
	  pom2D2=zobrazenie(pom3D2);
	  line(stx+pom2D1.x,sty-pom2D1.y,stx+pom2D2.x,sty-pom2D2.y);
	    }
 for (int j=0;j<=m;j++) for (int i=0;i<delenie*n;i++)
	    {
	  pom3D1=plocha(umin+(umax-umin)*i/n/delenie,vmin+(vmax-vmin)*j/m);
	  pom3D2=plocha(umin+(umax-umin)*(i+1)/delenie/n,vmin+(vmax-vmin)*j/m);
	  pom2D1=zobrazenie(pom3D1);
	  pom2D2=zobrazenie(pom3D2);
	  line(stx+pom2D1.x,sty-pom2D1.y,stx+pom2D2.x,sty-pom2D2.y);
	    }
 setcolor(WHITE);
 setviewport(0,0,639,479,1);
 rectangle(xmin,ymin,xmax,ymax);
 int k=getch();
   }
    }
}