guicirc.c

来自「uCGUI」· C语言 代码 · 共 237 行

C
237
字号
/*************************************************************************************************************
                                                   uC/GUI
                                               嵌入式通用图形软件
File        : GUICirc.C
Purpose     : Circle and ellipse drawing functions
************************************************************************************************************/
#include <stddef.h>           /* 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();
}














⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?