/* Used by Zero-BC.c and Fric-BC.c */

#include <string.h>

#define ABS(x) ( x < 0 ? -x : x )

void Gr_Disp(REAL T, int Init)
/*
   Borland graphics for display of system.

   Display will be of the y-z plane, with X information used to determine
   bright (positive x) or dim (negative x) in the display.

   To insure that two points differing only in X-coordinate are displayed
   correctly, the array is first SORTED based on the .X value.  A simple
   insertion sort is adequate:  size is probably less than 20, and the
   are will also mostly stay ordered.

   Previous position is blanked, then new position is plotted ---
   and new position is plotted a second time, should any point have been
   masked by an erase for a later point.
*/
{
   int Idx, Jdx;
   int Y, Z, Color;
   /* request auto detection */
   int gdriver = DETECT, gmode, errorcode;
   static int midx, midy,
              Full_radius, radius,
              Mid_size, Del_size;
   static int First = 1;
   static FILE *fp = NULL;
   static int Color_Set[6] = { EGA_LIGHTBLUE, EGA_LIGHTGREEN, EGA_LIGHTCYAN,
                               EGA_LIGHTRED, EGA_LIGHTMAGENTA, EGA_YELLOW };

   if (Init)
   {
/*    Set up for the save file */
      if (First)
      {
         char Line_In[80];

         First = 0;
         do
         {
            fputs ("Output file name:  ", stdout);
            gets  (Line_In);
            if (strcmp("NUL", Line_In) == 0)
               break;
            fp = fopen (Line_In, "w");
         }  while (fp == NULL);
      }
      initgraph(&gdriver, &gmode, "");
/*    read result of initialization */
      errorcode = graphresult();
/*    an error occurred */
      if (errorcode != grOk)
      {
         printf("Graphics error: %s\n", grapherrormsg(errorcode));
         printf("Press any key to halt:");
         getch();
/*       terminate with an error code */
         exit(1);
      }
      midx = getmaxx() / 2;
      midy = getmaxy() / 2;

      Full_radius = midy < midx ? midy : midx;
      Full_radius = 0.75 * Full_radius;
      midx = 2*midx - midy;
      Mid_size = Full_radius / 16;
      Del_size = Mid_size / 2;
   }

   InSort (Point, Size);

/* First, the blank/plot pass:  */
   for (Idx = 0; Idx < Size; Idx++)
   {
      radius = Mid_size + Del_size * Point[Idx].X[0];
      Y = midx + Full_radius * Point[Idx].X[1];
      Z = midy - Full_radius * Point[Idx].X[2];
      setcolor (0);
      setfillstyle(SOLID_FILL, 0);
      fillellipse(Y, Z, radius, radius);

      if (Point[Idx].Color > 0)
         Color = Color_Set[(Point[Idx].Color-1)%6];
      else
         Color = EGA_WHITE;
      radius = Mid_size + Del_size * Point[Idx].Q[0];
      Y = midx + Full_radius * Point[Idx].Q[1];
      Z = midy - Full_radius * Point[Idx].Q[2];
      setcolor (Color);
      setfillstyle(SOLID_FILL, Color);
      fillellipse(Y, Z, radius, radius);
   }

/* Plot the boundary */
   setcolor (7);
   circle(midx, midy, Full_radius);

/* Then replot the new positions */
   for (Idx = 0; Idx < Size; Idx++)
   {
      if (Point[Idx].Color > 0)
         Color = Color_Set[(Point[Idx].Color-1)%6];
      else
         Color = EGA_WHITE;
      radius = Mid_size + Del_size * Point[Idx].Q[0];
      Y = midx + Full_radius * Point[Idx].Q[1];
      Z = midy - Full_radius * Point[Idx].Q[2];
      setcolor (Color);
      setfillstyle(SOLID_FILL, Color);
      fillellipse(Y, Z, radius, radius);
/*    Update "previous" position for the next plot */
      Point[Idx].X[0] = Point[Idx].Q[0];
      Point[Idx].X[1] = Point[Idx].Q[1];
      Point[Idx].X[2] = Point[Idx].Q[2];
      if (fp != NULL)
      {
         for (Jdx = 0; Jdx < 3; Jdx++)
            fprintf (fp, "%5.3f ", Point[Idx].Q[Jdx]);
         fprintf (fp, "%d\n", ABS(Point[Idx].Color));
      }
   }
   if (fp != NULL)
      fputc('\n', fp);    /* Blank line to delimit images */
   gotoxy (1,20);
   printf ("     Time:  %3.3lf   \n", T);
   printf ("  Kinetic:  %7lg   \n", Tot_Kin);
   printf ("Potential:  %7lg   \n", Tot_Pot);
   printf ("    Total:  %7lg   \n", Tot_Kin + Tot_Pot);
}
