#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <time.h>

void DrawScreen( int(*GetDepth)(int, int) );
int Square(int, int);
int Windows(int, int);
int HemiSphere(int, int);
int SinRdivR(int, int);

int EggBox(int, int);

int (*Functions[])(int,int) = {
				Square,
				Windows,
				HemiSphere,
				SinRdivR,
				EggBox
			      };


int iXMax, iYMax, iXMid, iYMid, iX1K, iY1K, iColorMax;// Global variables...

int main(void)
{
  /* request auto detection */
  int gdriver = DETECT, gmode, errorcode;
  /* initialize graphics mode */
  initgraph(&gdriver, &gmode, "C:\\TC\\BGI\\");
  /* read result of initialization */
  errorcode = graphresult();
  if (errorcode != grOk)  /* an error occurred */
  {
     printf("Graphics error: %s\n", grapherrormsg(errorcode));
     printf("Press any key to halt:");
     getch();
     exit(1);             /* return with error code */
  }
  iColorMax=getmaxcolor()+1;
  iXMax = getmaxx()+1;
  iYMax = getmaxy()+1;
  iXMid = iXMax/2;
  iYMid = iYMax/2;
  iX1K = (int)(iXMax*10/6.4);
  iY1K = iYMax*5;

  time_t t;
  srand((unsigned) time(&t));

  restorecrtmode();

  char chWhich;
  do
  {
    restorecrtmode();
    printf("\nPlease press the number of your choice:\n");
    printf("\t1> Square\n");
    printf("\t2> Windows\n");
    printf("\t3> Half Sphere\n");
    printf("\t4> Sin(r)/r pattern\n");
    printf("\t5> Sin(x)*sin(r) eggbox\n");
    printf("\t0> Quit\n");

    chWhich=getch();

    if ((chWhich>='1') && (chWhich<='5'))
    {
      setgraphmode(getgraphmode());
      DrawScreen(Functions[chWhich-'1']);
      getch();
      restorecrtmode;
    }
  } while (chWhich!='0');


  closegraph();
  return 0;
}

void DrawScreen( int(*GetDepth)(int, int) )
{
  int iXLoop, iYLoop, iDepth;

  for (iYLoop=0; iYLoop<(iYMax-iY1K/50); iYLoop++)
  {
    for (iXLoop=0; iXLoop<iXMax; iXLoop++)
    {
      iDepth = GetDepth(iXLoop, iYLoop);

      if (iXLoop<iDepth)
//	putpixel( iXLoop, iYLoop, ((rand()%2)==1)?WHITE:BLACK); // Want B&W?
	putpixel( iXLoop, iYLoop, rand()%iColorMax ); // Want COLOR?
      else
	putpixel( iXLoop, iYLoop, getpixel(iXLoop-iDepth,iYLoop) );
    }
  }

  line( iXMid-iDepth/2, iYMax-iY1K/200,
	iXMid-iDepth/2, iYMax-iY1K/67);
  line( iXMid-iDepth/2-iXMax/64, iYMax-iY1K/100,
	iXMid-iDepth/2+iXMax/64, iYMax-iY1K/100 );
  line( iXMid+iDepth/2, iYMax-iY1K/200,
	iXMid+iDepth/2, iYMax-iY1K/67);
  line( iXMid+iDepth/2-iXMax/64, iYMax-iY1K/100,
	iXMid+iDepth/2+iXMax/64, iYMax-iY1K/100 );
}

int Square(int iX, int iY)
{
  if ( (abs(iX-iXMid)<(iX1K/10)) && (abs(iY-iYMid)<(iY1K/20)) )
    return (iX1K/14);
  else
    return (iX1K/13);
}

int Windows(int iX, int iY)
{
  if ( (((iX-iX1K/13)%((iXMax-iX1K/10)/4))<iX1K/40) ||
       ((iY%((iYMax-iY1K/33)/3))<iY1K/100) )
    return (iX1K/13);
  else
    return (iX1K/12);
}

int HemiSphere(int iX, int iY)
{
  float fR2, fZ;

  fR2 = ((iX-iXMid)/(iX1K/7.8125)) * ((iX-iXMid)/(iX1K/7.8125)) +
	((iY-iYMid)/(iY1K/20.0)) * ((iY-iYMid)/(iY1K/20.0));
  if (fR2<1.5)
    fZ = sqrt(1.5-fR2);
  else
    fZ = 0;
  return ( (int)(iX1K/12.5 - iX1K/100.0*fZ) );
}

int SinRdivR(int iX, int iY)
{
 float fR, fZ;

  fR = 10 * sqrt( ((iX-iXMid)/(iX1K/7.8125)) * ((iX-iXMid)/(iX1K/7.8125)) +
		  ((iY-iYMid)/(iY1K/20.0)) * ((iY-iYMid)/(iY1K/20.0))       );
  if (fR>0)
    fZ=(sin(fR)/fR);
  else
    fZ=1;
  return ( (int)(iX1K/12.5 - iX1K/50.0*fZ) );
}

int EggBox(int iX, int iY)
{
 return( iX1K/13.3333+(iX1K/200.0)*
	 sin((iX-iXMid)/(iX1K/33.3333))*
	 sin((iY-iYMid)/(iY1K/100.0)) );
}
