home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PJ8_3.ZIP / ELLIPSE1.C < prev    next >
Text File  |  1990-02-13  |  5KB  |  139 lines

  1. /* *** Listing 1 ***
  2.  *
  3.  * Draws an ellipse of the specified X and Y axis radii and color,
  4.  * using floating-point calculations.
  5.  * Compiles with either Turbo C 2.0 or MSC 5.0.
  6.  * VGA or EGA.
  7.  */
  8.  
  9. #include <math.h>
  10. #include <dos.h>
  11.  
  12. /* Turbo C accepts outp for outportb, but not outpw for outport */
  13. #ifdef __TURBOC__
  14. #define outpw  outport
  15. #endif
  16.  
  17. #define SCREEN_WIDTH_IN_BYTES 80    /* # of bytes across one scan
  18.                                        line in modes 10h and 12h */
  19. #define SCREEN_SEGMENT        0xA000 /* mode 10h/12h display memory seg */
  20. #define GC_INDEX              0x3CE /* Graphics Controller Index port */
  21. #define SET_RESET_INDEX       0     /* Set/Reset reg index in GC */
  22. #define SET_RESET_ENABLE_INDEX 1    /* Set/Reset Enable reg index in GC */
  23. #define BIT_MASK_INDEX        8     /* Bit Mask reg index in GC */
  24.  
  25. /* Draws a pixel at screen coordinate (X,Y) */
  26. void DrawDot(int X, int Y) {
  27.    unsigned char far *ScreenPtr;
  28.  
  29.    /* Point to the byte the pixel is in */
  30. #ifdef __TURBOC__
  31.    ScreenPtr = MK_FP(SCREEN_SEGMENT, (Y*SCREEN_WIDTH_IN_BYTES) + (X/8));
  32. #else
  33.    FP_SEG(ScreenPtr) = SCREEN_SEGMENT;
  34.    FP_OFF(ScreenPtr) = (Y * SCREEN_WIDTH_IN_BYTES) + (X / 8);
  35. #endif
  36.  
  37.    /* Set the bit mask within the byte for the pixel */
  38.    outp(GC_INDEX + 1, 0x80 >> (X & 0x07));
  39.  
  40.    /* Draw the pixel. ORed to force read/write to load latches.
  41.       Data written doesn't matter, because set/reset is enabled
  42.       for all planes. Note: don't OR with 0; MSC optimizes that
  43.       statement to no operation */
  44.    *ScreenPtr |= 0xFF;
  45. }
  46.  
  47. /* Draws an ellipse of X axis radius A and Y axis radius B in
  48.  * color Color centered at screen coordinate (X,Y). Radii must
  49.  * both be non-zero */
  50. void DrawEllipse(int X, int Y, int A, int B, int Color) {
  51.    int WorkingX, WorkingY;
  52.    double ASquared = (double) A * A;
  53.    double BSquared = (double) B * B;
  54.    double Temp;
  55.  
  56.    /* Set drawing color via set/reset */
  57.    outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX);
  58.                                  /* enable set/reset for all planes */
  59.    outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX);
  60.                                  /* set set/reset (drawing) color */
  61.    outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC Index reg pointing
  62.                                        to the Bit Mask reg */
  63.  
  64.    /* Draw the four symmetric arcs for which X advances faster (that is,
  65.       for which X is the major axis) */
  66.    /* Draw the initial top & bottom points */
  67.    DrawDot(X, Y+B);
  68.    DrawDot(X, Y-B);
  69.  
  70.    /* Draw the four arcs */
  71.    for (WorkingX = 0; ; ) {
  72.       /* Advance one pixel along the X axis */
  73.       WorkingX++;
  74.  
  75.       /* Calculate the corresponding point along the Y axis. Guard
  76.          against floating-point roundoff making the intermediate term
  77.          less than 0 */
  78.       Temp = BSquared - (BSquared *
  79.          (double)WorkingX * (double)WorkingX / ASquared);
  80.       if ( Temp >= 0 ) {
  81.          WorkingY = sqrt(Temp) + 0.5;
  82.       } else {
  83.          WorkingY = 0;
  84.       }
  85.  
  86.       /* Stop if X is no longer the major axis (the arc has passed the
  87.          45-degree point) */
  88.       if (((double)WorkingY/BSquared) <= ((double)WorkingX/ASquared))
  89.          break;
  90.  
  91.       /* Draw the 4 symmetries of the current point */
  92.       DrawDot(X+WorkingX, Y-WorkingY);
  93.       DrawDot(X-WorkingX, Y-WorkingY);
  94.       DrawDot(X+WorkingX, Y+WorkingY);
  95.       DrawDot(X-WorkingX, Y+WorkingY);
  96.    }
  97.  
  98.    /* Draw the four symmetric arcs for which Y advances faster (that is,
  99.       for which Y is the major axis) */
  100.    /* Draw the initial left & right points */
  101.    DrawDot(X+A, Y);
  102.    DrawDot(X-A, Y);
  103.  
  104.    /* Draw the four arcs */
  105.    for (WorkingY = 0; ; ) {
  106.       /* Advance one pixel along the Y axis */
  107.       WorkingY++;
  108.  
  109.       /* Calculate the corresponding point along the X axis. Guard
  110.          against floating-point roundoff making the intermediate term
  111.          less than 0 */
  112.       Temp = ASquared - (ASquared *
  113.          (double)WorkingY * (double)WorkingY / BSquared);
  114.       if ( Temp >= 0 ) {
  115.          WorkingX = sqrt(Temp) + 0.5;
  116.       } else {
  117.          WorkingX = 0;           /* floating-point roundoff */
  118.       }
  119.  
  120.       /* Stop if Y is no longer the major axis (the arc has passed the
  121.          45-degree point) */
  122.       if (((double)WorkingX/ASquared) < ((double)WorkingY/BSquared))
  123.          break;
  124.  
  125.       /* Draw the 4 symmetries of the current point */
  126.       DrawDot(X+WorkingX, Y-WorkingY);
  127.       DrawDot(X-WorkingX, Y-WorkingY);
  128.       DrawDot(X+WorkingX, Y+WorkingY);
  129.       DrawDot(X-WorkingX, Y+WorkingY);
  130.    }
  131.  
  132.    /* Reset the Bit Mask register to normal */
  133.    outp(GC_INDEX + 1, 0xFF);
  134.  
  135.    /* Turn off set/reset enable */
  136.    outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX);
  137. }
  138.  
  139.