/* Used by Movie.C */

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

void Graphic_Display(int Size, int Init)
/*
   Borland graphics for display of system.

   Includes the option of generating a RUN file for later animation.

   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;
   int Y, Z;
   int Color;
   /* request auto detection */
   int gdriver = DETECT, gmode, errorcode;
   static int midx, midy,
              Full_radius, radius,
              Mid_size, Del_size;
   static int Color_Set[6] = { EGA_LIGHTBLUE, EGA_LIGHTGREEN, EGA_LIGHTCYAN,
                               EGA_LIGHTRED, EGA_LIGHTMAGENTA, EGA_YELLOW };

   if (Init)
   {
      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:");
         getchar();
/*       terminate with an error code */
         exit(1);
      }
      midx = getmaxx() / 2;
      midy = getmaxy() / 2;

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

/* First, the blank 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 plot 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];
   }
}
