www.pudn.com > ucosv2(GUI).rar > GUICirc.c


/*
*********************************************************************************************************
*                                                uC/GUI
*                        Universal graphic software for embedded applications
*
*                       (c) Copyright 2002, Micrium Inc., Weston, FL
*                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
*              µC/GUI is protected by international copyright laws. Knowledge of the
*              source code may not be used to write a similar product. This file may
*              only be used in accordance with a license and should not be redistributed
*              in any way. We appreciate your understanding and fairness.
*
---------------------------------------------------------------------- 
File        : GUICirc.C 
Purpose     : Circle and ellipse drawing functions 
---------------------------------------------------------------------- 
Version-Date---Author-Explanation 
---------------------------------------------------------------------- 
1.00.02 011115 JE     a) GL_FillEllipse, GL_FillCircle, GL_DrawCircle changed 
1.00.01 011113 JE     a) GL_DrawEllipse changed 
1.00.00 991206 RS     First release 
---------------------------------------------------------------------- 
Known problems or limitations with current version 
---------------------------------------------------------------------- 
None. 
---------------------------------------------------------------------- 
Open issues 
---------------------------------------------------------------------- 
None 
---------------------------END-OF-HEADER------------------------------ 
*/ 
 
 
#include            /* needed for definition of NULL */ 
#include "GUI_Private.H" 
 
 
/* 
      ************************************************* 
      *                                               * 
      *            Draw Circle                        * 
      *                                               * 
      ************************************************* 
*/ 
 
static  void Draw8Point(int x0,int y0, int xoff, int yoff) { 
  LCD_HL_DrawPixel(x0+xoff,y0+yoff); 
  LCD_HL_DrawPixel(x0-xoff,y0+yoff); 
  LCD_HL_DrawPixel(x0+yoff,y0+xoff); 
  LCD_HL_DrawPixel(x0+yoff,y0-xoff); 
  if (yoff) { 
    LCD_HL_DrawPixel(x0+xoff,y0-yoff); 
    LCD_HL_DrawPixel(x0-xoff,y0-yoff); 
    LCD_HL_DrawPixel(x0-yoff,y0+xoff); 
    LCD_HL_DrawPixel(x0-yoff,y0-xoff); 
  } 
} 
 
 
void GL_DrawCircle(int x0, int y0, int r) { 
  I32 i; 
  int imax = ((I32)((I32)r*707))/1000+1; 
  I32 sqmax = (I32)r*(I32)r+(I32)r/2; 
  I32 y=r; 
  Draw8Point(x0,y0,r,0); 
  for (i=1; i<= imax; i++) { 
    if ((i*i+y*y) >sqmax) { 
      Draw8Point(x0,y0,i,y); 
      y--; 
    } 
    Draw8Point(x0,y0,i,y); 
  } 
} 
 
void GUI_DrawCircle       (int x0, int y0, int r) { 
  #if (GUI_WINSUPPORT) 
    GUI_RECT Rect; 
  #endif 
  GUI_LOCK(); 
  #if (GUI_WINSUPPORT) 
    WM_ADDORG(x0,y0); 
    Rect.x0 = x0-r; 
    Rect.x1 = x0+r; 
    Rect.y0 = y0-r; 
    Rect.y1 = y0+r; 
    WM_ITERATE_START(&Rect); { 
  #endif 
    GL_DrawCircle( x0, y0, r); 
  #if (GUI_WINSUPPORT) 
    } WM_ITERATE_END(); 
  #endif 
  GUI_UNLOCK(); 
} 
 
 
/* 
      ************************************************* 
      *                                               * 
      *            Fill Circle                        * 
      *                                               * 
      ************************************************* 
*/ 
void GL_FillCircle       (int x0, int y0, int r) { 
  I32 i; 
  int imax = ((I32)((I32)r*707))/1000+1; 
  I32 sqmax = (I32)r*(I32)r+(I32)r/2; 
  I32 x=r; 
  LCD_HL_DrawHLine(x0-r,y0,x0+r); 
  for (i=1; i<= imax; i++) { 
    if ((i*i+x*x) >sqmax) { 
      /* draw lines from outside */ 
      if (x>imax) { 
        LCD_HL_DrawHLine (x0-i+1,y0+x, x0+i-1); 
        LCD_HL_DrawHLine (x0-i+1,y0-x, x0+i-1); 
      } 
      x--; 
    } 
    /* draw lines from inside (center) */ 
    LCD_HL_DrawHLine(x0-x,y0+i, x0+x); 
    LCD_HL_DrawHLine(x0-x,y0-i, x0+x); 
  } 
} 
 
void GUI_FillCircle       (int x0, int y0, int r) { 
  GUI_LOCK(); 
  #if (GUI_WINSUPPORT) 
    WM_ADDORG(x0,y0); 
    WM_ITERATE_START(NULL); { 
  #endif 
  GL_FillCircle(x0,y0,r); 
  #if (GUI_WINSUPPORT) 
    } WM_ITERATE_END(); 
  #endif 
  GUI_UNLOCK(); 
} 
 
 
 
/* 
        ********************************************************* 
        *                                                       * 
        *               Ellipse drawing / filling               * 
        *                                                       * 
        ********************************************************* 
 
The most efficient way to calculate the ellipse positions 
is using the knowledge that the ellipse is just circle which has 
compressed (or stretched) in one direction. For a circle, the 
following equation holds true for all points located on the border of 
it: 
               x^2 + y(x)^2 = r^2 = const 
 
Therefor, for an ellipse we can make use of the following equation: 
 
               (ry*x)^2 + (rx*y(x))^2 = (ry*rx)^2 = const 
 
*/ 
 
void GL_FillEllipse      (int x0, int y0, int rx, int ry) { 
  I32 OutConst, Sum, SumY; 
  int x,y; 
  U32 _rx = rx; 
  U32 _ry = ry; 
  OutConst = _rx*_rx*_ry*_ry  /* Constant as explaint above */ 
            +(_rx*_rx*_ry>>1); /* To compensate for rounding */ 
  x = rx; 
  for (y=0; y<=ry; y++) { 
    SumY =((I32)(rx*rx))*((I32)(y*y)); /* Does not change in loop */ 
    while (Sum = SumY + ((I32)(ry*ry))*((I32)(x*x)), 
           (x>0) && (Sum>OutConst)) 
    { 
      x--; 
    } 
    LCD_HL_DrawHLine(x0-x, y0+y, x0+x); 
    if (y) 
      LCD_HL_DrawHLine(x0-x, y0-y, x0+x); 
  } 
} 
 
void GUI_FillEllipse      (int x0, int y0, int rx, int ry) { 
  #if (GUI_WINSUPPORT) 
    GUI_RECT r; 
  #endif 
  GUI_LOCK(); 
  #if (GUI_WINSUPPORT) 
    WM_ADDORG(x0,y0); 
    /* Calc rectangle in order to avoid unnecessary drawing ops. */ 
    r.x0 = x0-rx; r.x1 = x0+rx; r.y0 = y0-ry; r.y1 = y0+ry; 
    WM_ITERATE_START(&r); { 
  #endif 
  GL_FillEllipse (x0,y0, rx, ry); 
  #if (GUI_WINSUPPORT) 
    } WM_ITERATE_END(); 
  #endif 
  GUI_UNLOCK(); 
} 
 
void GL_DrawEllipse      (int x0, int y0, int rx, int ry) { 
  I32 OutConst, Sum, SumY; 
  int x,y; 
  int xOld; 
  U32 _rx = rx; 
  U32 _ry = ry; 
  OutConst = _rx*_rx*_ry*_ry  /* Constant as explaint above */ 
            +(_rx*_rx*_ry>>1); /* To compensate for rounding */ 
  xOld = x = rx; 
  for (y=0; y<=ry; y++) { 
    if (y==ry) { 
      x=0; 
    } else { 
      SumY =((I32)(rx*rx))*((I32)(y*y)); /* Does not change in loop */ 
      while (Sum = SumY + ((I32)(ry*ry))*((I32)(x*x)), 
             (x>0) && (Sum>OutConst)) x--; 
    } 
/* Since we draw lines, we can not draw on the first 
    iteration 
*/ 
    if (y) { 
      GL_DrawLine1(x0-xOld,y0-y+1,x0-x,y0-y); 
      GL_DrawLine1(x0-xOld,y0+y-1,x0-x,y0+y); 
      GL_DrawLine1(x0+xOld,y0-y+1,x0+x,y0-y); 
      GL_DrawLine1(x0+xOld,y0+y-1,x0+x,y0+y); 
    } 
    xOld = x; 
  } 
} 
 
void GUI_DrawEllipse      (int x0, int y0, int rx, int ry) { 
  #if (GUI_WINSUPPORT) 
    GUI_RECT r; 
  #endif 
  GUI_LOCK(); 
  #if (GUI_WINSUPPORT) 
    WM_ADDORG(x0,y0); 
  /* Calc rectangle in order to avoid unnecessary drawing ops. */ 
    r.x0 = x0-rx; r.x1 = x0+rx; r.y0 = y0-ry; r.y1 = y0+ry; 
    WM_ITERATE_START(&r); { 
  #endif 
  GL_DrawEllipse(x0, y0, rx, ry); 
  #if (GUI_WINSUPPORT) 
    } WM_ITERATE_END(); 
  #endif 
  GUI_UNLOCK(); 
}