This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/lib/lcd/gui/Core/GUIArc.c

263 lines
6.5 KiB
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 : 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 "arm_math.h"
#include "GUI_Protected.h"
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _CalcX
*/
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;
}
/*********************************************************************
*
* _CalcInterSectLin
*/
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;
}
}
/*********************************************************************
*
* _DrawArc
*/
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 = arm_sin_f32(fAngle0);
float sin1 = arm_sin_f32(fAngle1);
float cos0 = arm_cos_f32(fAngle0);
float cos1 = arm_cos_f32(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);
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* GL_DrawArc
*/
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;
}
/*********************************************************************
*
* GUI_DrawArc
*/
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();
}
/*************************** End of file ****************************/