📄 guiarc.c
字号:
/*
*********************************************************************************************************
* uC/GUI
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* 礐/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 : GUIARCFloat.C
Purpose : Draw Arc routines based on floating point
----------------------------------------------------------------------
Version-Date---Author-Explanation
----------------------------------------------------------------------
2.00.00 000325 RS First release of the new algorithm
----------------------------------------------------------------------
Known problems or limitations with current version
----------------------------------------------------------------------
None.
----------------------------------------------------------------------
Open issues
----------------------------------------------------------------------
None
---------------------------END-OF-HEADER------------------------------
*/
#include <stddef.h> /* needed for definition of NULL */
#include <math.h>
#include "GUI_Private.h"
static void CalcX(int*px, int y, U32 r2) {
int x =*px;
U32 y2 = (U32)y*(U32)y;
U32 r2y2 = r2-y2;
U32 x2;
if (y2>=r2) {
*px=0;
return;
}
/* x2 = r2-y2 */
do {
x++;
x2 =(U32)x*(U32)x;
} while (x2 < r2y2);
*px = x-1;
}
static float CalcInterSectLin(float y, float y0, float y1, float x0, float x1) {
if (y1==y0) {
return y0;
} else {
float Slope = (x1-x0)/(y1-y0);
return (y-y0)*Slope+x0;
}
}
static void _DrawArc(int x0, int y0, int rx, int ry, int Angle0, int Angle1, int xMul, int yMul) {
float afx[4];
float afy[4];
float ri = rx-(GUI_Context.PenSize+1.5)/2;
float ro = rx+(GUI_Context.PenSize+1.5)/2;
float fAngle0 = Angle0*3.1415926/180;
float fAngle1 = Angle1*3.1415926/180;
float sin0 = sin(fAngle0);
float sin1 = sin(fAngle1);
float cos0 = cos(fAngle0);
float cos1 = cos(fAngle1);
U32 ri2 = ri*ri;
U32 ro2 = ro*ro;
int y, yMax, yMin;
afy[0] = ri*sin0;
afy[1] = ro*sin0;
afy[2] = ri*sin1;
afy[3] = ro*sin1;
afx[0] = ri*cos0;
afx[1] = ro*cos0;
afx[2] = ri*cos1;
afx[3] = ro*cos1;
yMin = ceil(afy[0]);
yMax = floor(afy[3]);
/* Use Clipping rect to reduce calculation (if possible) */
if (GUI_Context.pClipRect_HL) {
if (yMul ==1) {
if (yMax > (GUI_Context.pClipRect_HL->y1 -y0))
yMax = (GUI_Context.pClipRect_HL->y1 -y0);
if (yMin < (GUI_Context.pClipRect_HL->y0 -y0))
yMin = (GUI_Context.pClipRect_HL->y0 -y0);
}
if (yMul == -1) {
if (yMin > (GUI_Context.pClipRect_HL->y1 -y0))
yMin = (GUI_Context.pClipRect_HL->y1 -y0);
if (yMax < (GUI_Context.pClipRect_HL->y0 -y0))
yMax = (GUI_Context.pClipRect_HL->y0 -y0);
}
}
/* Start drawing lines ... */
{
int xMinDisp, xMaxDisp, xMin=0,xMax=0;
for (y=yMax; y>=yMin; y--) {
CalcX(&xMin, y, ri2);
CalcX(&xMax, y, ro2);
if ((float)y< afy[1]) {
xMaxDisp = CalcInterSectLin(y,afy[0], afy[1], afx[0], afx[1]);
} else {
xMaxDisp = xMax;
}
if ((float)y > afy[2]) {
xMinDisp = CalcInterSectLin(y,afy[2], afy[3], afx[2], afx[3]);
} else {
xMinDisp = xMin;
}
if (xMul>0)
LCD_HL_DrawHLine(xMinDisp+x0, yMul*y+y0, xMaxDisp+x0);
else
LCD_HL_DrawHLine(-xMaxDisp+x0, yMul*y+y0, -xMinDisp+x0);
}
}
#if 0 /* Test code */
{
int i;
GUI_SetColor( GUI_WHITE );
for (i=0; i<4; i++)
LCD_HL_DrawPixel(afx[i]+x0, afy[i]+y0);
}
#endif
GUI_USE_PARA(ry);
}
void GL_DrawArc (int x0, int y0, int rx, int ry, int a0, int a1) {
int aEnd;
a0+=360;
a1+=360;
while (a0>=360) {
a0 -= 360;
a1 -= 360;
}
/* Do first quadrant 0-90 degree */
DoFirst:
if (a1<=0)
return;
if (a0<90) {
if (a0<0)
a0=0;
aEnd = (a1<90) ? a1 : 90;
_DrawArc(x0,y0,rx,ry,a0,aEnd, 1, -1);
}
a1-=90;
a0-=90;
/* Do second quadrant 90-180 degree */
if (a1<=0)
return;
if (a0<90) {
if (a0<0)
a0=0;
aEnd = (a1<90) ? a1 : 90;
_DrawArc(x0,y0,rx,ry,90-aEnd, 90-a0,-1,-1);
}
a1-=90;
a0-=90;
/* Do third quadrant 180-270 degree */
if (a1<=0)
return;
if (a0<90) {
if (a0<0)
a0=0;
aEnd = (a1<90) ? a1 : 90;
_DrawArc(x0,y0,rx,ry,a0,aEnd, -1, 1);
}
a1-=90;
a0-=90;
/* Do last quadrant 270-360 degree */
if (a1<=0)
return;
if (a0<90) {
if (a0<0)
a0=0;
aEnd = (a1<90) ? a1 : 90;
_DrawArc(x0,y0,rx,ry,90-aEnd, 90-a0,1,1);
}
a1-=90;
a0-=90;
goto DoFirst;
}
void GUI_DrawArc (int x0, int y0, int rx, int ry, int a0, int a1) {
GUI_LOCK();
#if (GUI_WINSUPPORT)
WM_ADDORG(x0,y0);
WM_ITERATE_START(NULL) {
#endif
GL_DrawArc( x0, y0, rx, ry, a0, a1);
#if (GUI_WINSUPPORT)
} WM_ITERATE_END();
#endif
GUI_UNLOCK();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -