#include <stdio.h>
#include <math.h>
#include <functions.h>
#include <exec/types.h>
#include <intuition/intuition.h>

#define INTUITION_REV 0L  /* You must be sure this is correct */
#define GRAPHICS_REV 0L
#define RP Window->RPort

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct NewWindow NewWindow;
struct Window *Window;

float hi,xx,yy,lo,xd,yd,y0,s,x0,x1;
float xb,yb,ys,xa,ya,xs,lz,y1,z0,z1,x,y,z;
float p1,p2,p3,p4,p5;

#define lz 20           /*  Linienzahl  */
#define hh 192          /*  Vielfaches von 8  */
#define br 384          /*     -"-         6  */

int o[br+1],u[br+1],px[lz+1][lz+1],py[lz+1][lz+1];
int xp,yp,i,nx,ny,az,ph;
char *klx,*grx,*kly,*gry,*klz,*grz;
FILE *rwp;

main()
{
   IntuitionBase = (struct IntuitionBase *)
      OpenLibrary("intuition.library",INTUITION_REV);
   if(IntuitionBase == NULL)
      exit(FALSE);

   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",GRAPHICS_REV);
   if(GfxBase == NULL)
      exit(FALSE);

   /* Initialize the NewWindow structure for the call to OpenWindow() */

   NewWindow.LeftEdge = 0;
   NewWindow.TopEdge = 0;
   NewWindow.Width = 400;
   NewWindow.Height = 200;
   NewWindow.DetailPen = 0;
   NewWindow.BlockPen = 1;
   NewWindow.Title = NULL;
   NewWindow.Flags = SMART_REFRESH;
   NewWindow.IDCMPFlags = NULL;   /* Tell us about CLOSEWINDOW events */
   NewWindow.Type = WBENCHSCREEN;
   NewWindow.FirstGadget = NULL;
   NewWindow.CheckMark = NULL;
   NewWindow.Screen = NULL;
   NewWindow.BitMap = NULL;
   NewWindow.MinWidth = 100;
   NewWindow.MinHeight = 25;
   NewWindow.MaxWidth = 640;
   NewWindow.MaxHeight = 200;

   klx = "Kleinstes x : " ; grx = "Größtes x : ";
   kly = "Kleinstes y : " ; gry = "Größtes y : ";
   klz = "KLeinstes z : " ; grz = "Größtes z : ";

/*    Eröffnen eines CON-Windows zur Eingabe  */

   rwp = fopen("CON:0/0/640/200/3D-Plot","w+");
   Cbuffs[0]._unit = rwp->_unit;
   Cbuffs[1]._unit = rwp->_unit;

Schleife:
   printf("\f\n\n3D-Funktionen\n");

   for (i=0 ; i<=br-1 ; i++ )
      o[i] = -1;

   printf("\n  Eingabe des Definitionsbereichs :\n");
   printf("\n%s",klx) ; scanf("%f",&x0);
   printf("%s",grx) ; scanf("%f",&x1);
   printf("\n%s",kly) ; scanf("%f",&y0);
   printf("%s",gry) ; scanf("%f",&y1);
   printf("\nBetrachtungswinkel von der Seite:");
   printf("\n(Azimut 0-80) ") ; scanf("%d",&az);
   printf("\nBetrachtungswinkel Höhe (0-90): ") ; scanf("%d",&ph);

   p1=cos((float)(az*PI/180.0));
   p2=sin((float)(az*PI/180.0));
   p3=cos((float)(ph*PI/180.0));
   p4=p1*sin((float)(ph*PI/180.0));
   p5=p2*sin((float)(ph*PI/180.0));

   printf("\nIch suche nun Maximum und Minimum.\n");
   xs=(x1-x0)/(float)lz ;
   ys=(y1-y0)/(float)lz;
   x=x0 ;
   y=y0;

   Funktion();
   xx=x*p4+y*p5-p3*z;
   yy=y*p1-x*p2;

   z0=z ;
   xa=xx ;
   ya=yy;
   z1=z ;
   xb=xx ;
   yb=yy;

   x=x0-xs;

   for (nx=0 ; nx<=lz ; nx++) {
      x=x+xs ;
      y=y0-ys;
      for (ny=0 ; ny<=lz ; ny++) {
         y=y+ys;

         Funktion();
         xx=x*p4+y*p5-p3*z;
         yy=y*p1-x*p2;

         if (z>z1)
            z1=z;
         else if (z<z0)
            z0=z;

         if (xx<xa)
            xa=xx;
         else if (xx>xb)
            xb=xx;

         if (yy<ya)
            ya=yy;
         else if (yy>yb)
            yb=yy;

      }
   }

   xd=(xb-xa)/(float)(hh-1) ;
   yd=(yb-ya)/(float)(br-1);
   x=x0-xs;

   for (nx=0 ; nx<=lz ; nx++) {
      x=x+xs ;
      y=y0-ys;
      for (ny=0 ; ny<=lz ; ny++) {
         y=y+ys;

         Funktion();
         xx=x*p4+y*p5-p3*z;
         yy=y*p1-x*p2;

         px[nx][ny]=(int)((xx-xa)/xd+.5);
         py[nx][ny]=(int)((yy-ya)/yd+.5);

      }
   }

   if (( Window=(struct Window *)OpenWindow(&NewWindow)) == NULL)
      exit (FALSE);

   locate (5,52);printf("%s %f",klx,x0);
   locate (6,52);printf("%s   %f",grx,x1);
   locate (8,52);printf("%s %f",kly,y0);
   locate (9,52);printf("%s   %f",gry,y1);
   locate (11,52);printf("%s %f",klz,z0);
   locate (12,52);printf("%s   %f",grz,z1);
   locate (14,52);printf("Azimutwinkel : %d",az);
   locate (15,52);printf("Höhe         : %d",ph);

   for (ny=lz-1 ; ny>=0 ; ny--) {
      xa=(float)px[lz][ny+1] ; ya=(float)py[lz][ny+1];
      xb=(float)px[lz][ny] ; yb=(float)py[lz][ny];
      Ausgabe();
   }

   for (nx=lz-1 ; nx>=0 ; nx--) {
      xa=px[nx+1][lz] ; ya=py[nx+1][lz];
      xb=px[nx][lz] ; yb=py[nx][lz];
      Ausgabe();
      for (ny=lz-1 ; ny>=0 ; ny--) {
         xa=px[nx+1][ny] ; ya=py[nx+1][ny];
         xb=px[nx][ny] ; yb=py[nx][ny];
         xd=xb-xa ; yd=yb-ya;
         s=sqrt((xd*xd+yd*yd)/2.0);

         if (s!=0.0) {
            xb=round(xb-xd/s) ; yb=round(yb-yd/s);
            Ausgabe();
         }

         xa=px[nx][ny+1] ; ya=py[nx][ny+1];
         xb=px[nx][ny] ; yb=py[nx][ny];
         Ausgabe();
      }
   }

   locate (17,60);printf("Fertig !!!");
   locate (19,60);printf("nochmal (j,n) ");
   do
      i = getchar();
   while ( i== '\n' );
   if (i=='j' || i=='y') {
      CloseWindow(Window);
      goto Schleife;
   }
   Ende();
}

Ende()
{
   CloseWindow(Window);   /* Close the Window */
   fclose (rwp);
   exit(TRUE);            /* Exit */
}

locate (x,y)
int x,y;
{
   printf("\x1b[%d;%dH",x,y);
}

Ausgabe()
{
   if (o[(int)yb] >= 0)
      if (xb > o[(int)yb])
         goto weiter1;

   if (xb > xa) {
      x=xa;xa=xb;xb=x;y=ya;ya=yb;yb=y;
   }

   goto weiter2;

weiter1:
   if (xb < xa) {
      x=xa;xa=xb;xb=x;y=ya;ya=yb;yb=y;
   }

weiter2:
   xd=xb-xa ; yd=yb-ya;
   s=abs(xd);

   if (abs(yd) > s)
      s=abs(yd);

   if (s == 0.0)
      return();

   xd=xd/s ; yd=yd/s;
   xx=xa-xd ; yy=ya-yd;

   for (i=0 ; i<=s ; i++) {
      xx+=xd ; yy+=yd;
      xp=(round(xx)) ; yp=(round(yy));
      if (o[yp] < 0) {
         o[yp]=xp;
         u[yp]=xp;
         SetAPen(RP,3L);
         WritePixel(RP,(long)yp,(long)xp);
      }
      else if (xp > o[yp]) {
         o[yp]=xp;
         SetAPen(RP,2L);
         WritePixel(RP,(long)yp,(long)xp);
      }
      else if (xp < u[yp]) {
         u[yp]=xp;
         SetAPen(RP,1L);
         WritePixel(RP,(long)yp,(long)xp);
      }
   }
}

