l1ellips.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,123 行 · 第 1/3 页
C
1,123 行
// on the width of the x_axis
{
if( x == 0 ) { // check for y_axis
if( y > 0 ) {
if( y_width == 0 ) {
return( 0 );
} else {
return( 1 );
}
} else { // y < 0
return( 3 );
}
} else if( y == 0 ) { // check for x_axis
if( x > 0 ) {
if( x_width == 0 ) {
return( 3 );
} else {
return( 0 );
}
} else { // x < 0
return( 2 );
}
} else if( x > 0 ) {
if( y > 0 ) {
return( 0 );
} else {
return( 3 );
}
} else { // x < 0
if( y > 0 ) {
return( 1 );
} else {
return( 2 );
}
}
}
#endif
#if defined( _DEFAULT_WINDOWS )
#if defined( __OS2__ )
static float GetAngle( short x, short y, short xc, short yc, short a, short b )
//===========================================================
// return the angle between the line from (xc, yc) to (x, y) and the x
// axis.
{
float angle;
float sinval, cosval;
float pie = 3.141592654;
x -= xc;
y -= yc;
sinval = (float)y / (float)b;
if( sinval > 1 ) {
sinval = 1;
} else if( sinval < -1 ) {
sinval = -1;
}
cosval = (float)x / (float)a;
if( cosval > 1 ) {
cosval = 1;
} else if( cosval < -1 ) {
cosval = -1;
}
if( a >= b ) {
angle = asin( sinval );
if( x < 0 ) {
if( sinval > 0 ) {
angle = pie - angle;
} else if( sinval < 0 ) {
angle = -( pie + angle);
} else if( sinval == 0 ) {
angle = pie;
}
}
} else {
angle = acos( cosval );
if( y < 0 ) {
angle = -angle;
}
}
if( angle < 0 ) {
angle += ( 2 * pie);
}
return angle * 180.0 / pie;
}
#endif
static int round( float num )
//==================================================
// This function round off a float in to an interger.
{
short sign;
int floor;
if( num < 0 ) {
sign = -1;
num = -num;
} else {
sign = 1;
}
floor = (int)num;
if( num - floor < 0.5 ) {
return sign * floor;
} else {
return sign * ( floor + 1 );
}
}
#endif
void _L1Arc( short fill, short x1, short y1, short x2, short y2,
/*====================*/ short x3, short y3, short x4, short y4 )
/* This function draws an elliptical arc. The virtual ellipse is defined by
the rectangle whose opposite corners are ( x1, y1 ) and ( x2, y2 ). The
intersections of the vectors from the center of the ellipse to the points
( x3, y3 ) and ( x4, y4 ) define the start and end points respectively
where the arc is drawn in a counter clockwise direction. All values
are in physical coordinates. */
{
short clip1;
short clip2;
short a, b;
short t;
#if defined( _DEFAULT_WINDOWS )
WPI_PRES dc;
HPEN pen;
HPEN old_pen;
HRGN temprgn;
WPI_COLOUR color;
WPI_RECT clip_rect;
short clipy1, clipy2;
#endif
clip1 = _L1OutCode( x1, y1 ); // check for clipping
clip2 = _L1OutCode( x2, y2 );
if( clip1 & clip2 ) {
_ErrorStatus = _GRNOOUTPUT;
return; // trivially outside so quit
}
if( x1 > x2 ) { // ensure x1 < x2
t = x1;
x1 = x2;
x2 = t;
}
if( y1 > y2 ) { // ensure y1 < y2
t = y1;
y1 = y2;
y2 = t;
}
a = ( x2 - x1 + 1 ) / 2 - 1;
b = ( y2 - y1 + 1 ) / 2 - 1;
_ArcInfo.centre.xcoord = x1 + a + 1; // centre of ellipse
_ArcInfo.centre.ycoord = y1 + b + 1;
_ArcInfo.vecta.xcoord = x3 - _ArcInfo.centre.xcoord;
_ArcInfo.vecta.ycoord = _ArcInfo.centre.ycoord - y3; // invert y
_ArcInfo.vectb.xcoord = x4 - _ArcInfo.centre.xcoord;
_ArcInfo.vectb.ycoord = _ArcInfo.centre.ycoord - y4; // invert y
if( _ArcInfo.vecta.xcoord == 0 && _ArcInfo.vecta.ycoord == 0 ||
_ArcInfo.vectb.xcoord == 0 && _ArcInfo.vectb.ycoord == 0 ) {
_ErrorStatus = _GRINVALIDPARAMETER; // zero vector
return;
}
#if defined( _DEFAULT_WINDOWS )
// Calculate end points
_ArcInfo.start = Cal_Coord( x3, y3, a, b );
_ArcInfo.end = Cal_Coord( x4, y4, a, b );
fill = fill; // used to get rid of warnings in windows
dc = _Mem_dc;
// do the clipping
temprgn = _ClipRgn;
clipy1 = _wpi_cvth_y( _CurrState->clip_def.ymin, _GetPresHeight() );
clipy2 = _wpi_cvth_y( _CurrState->clip_def.ymax + 1, _GetPresHeight() );
_wpi_setintwrectvalues( &clip_rect, _CurrState->clip_def.xmin, clipy1,
_CurrState->clip_def.xmax + 1, clipy2 );
_ClipRgn = _wpi_createrectrgn( dc, &clip_rect );
_wpi_getclipbox( dc, &clip_rect);
_wpi_selectcliprgn( dc, _ClipRgn );
_wpi_deletecliprgn( dc, temprgn );
// setup
// Convert our color to RGB values
color = _Col2RGB( _CurrColor );
// Map the line styles
#if defined( __OS2__ )
if( fill != _GFILLINTERIOR ) {
#endif
pen = _MyCreatePen( color );
old_pen = _wpi_selectpen( dc, pen );
#if defined( __OS2__ )
}
OS2_Arc( dc, fill, a, b );
#else
_wpi_arc( dc, x1, y1, x2, y2, x3, y3, x4, y4 );
#endif
// Clean up
#if defined( __OS2__ )
if( fill != _GFILLINTERIOR ) {
#endif
_wpi_getoldpen( dc, old_pen );
_wpi_deletepen( pen );
#if defined( __OS2__ )
}
#endif
temprgn = _ClipRgn;
_ClipRgn = _wpi_createrectrgn( dc, &clip_rect );
_wpi_selectcliprgn( dc, _ClipRgn );
_wpi_deletecliprgn( dc, temprgn );
y1 = _wpi_cvth_y( y1, _GetPresHeight() );
y2 = _wpi_cvth_y( y2, _GetPresHeight() );
// Update the window
_MyInvalidate( x1, y1, x2, y2 );
_RefreshWindow();
#else
_StartDevice();
EllInfo.x_reflect = x1 + x2; // need to reflect to use symmetry
EllInfo.y_reflect = y1 + y2;
if( fill == _GFILLINTERIOR ) {
FilledArc( x1, y1, x2, y2, a, b );
} else {
if( _LineStyle == 0xffff ) {
EllInfo.line_mask[ 0 ] = _LineStyle;
EllInfo.line_mask[ 1 ] = _LineStyle;
EllInfo.line_mask[ 2 ] = _LineStyle;
EllInfo.line_mask[ 3 ] = _LineStyle;
} else {
InitLineMasks( x1, y1, x2, y2 );
}
_ArcInfo.plot = PutDot;
HollowArc( x1, y1, x2, y2, a, b );
}
_ResetDevice();
#endif
}
#if defined( _DEFAULT_WINDOWS )
#if defined( __OS2__ )
static void OS2_Arc( HPS pres, short fill, short a, short b )
/*===========================================================
This function is used to draw an Arc in OS/2. */
{
ARCPARAMS arcp;
POINTL pts, pte, ptc;
float start, end, sweep;
// Use the centre and the two end points to get an intermediate point
pts.x = _ArcInfo.start.xcoord;
pts.y = _wpi_cvth_y( _ArcInfo.start.ycoord, _GetPresHeight() );
pte.x = _ArcInfo.end.xcoord;
pte.y = _wpi_cvth_y( _ArcInfo.end.ycoord, _GetPresHeight() );
ptc.x = _ArcInfo.centre.xcoord;
ptc.y = _wpi_cvth_y( _ArcInfo.centre.ycoord, _GetPresHeight() );
start = GetAngle( pts.x, pts.y, ptc.x, ptc.y, a, b );
end = GetAngle( pte.x, pte.y, ptc.x, ptc.y, a, b );
// Find an intermediate point
sweep = end - start;
if( sweep < 0 ) {
sweep += 360;
}
// Set the size and orientation of the arc.
arcp.lP = a;
arcp.lQ = b;
arcp.lR = 0;
arcp.lS = 0;
GpiSetArcParams( pres, &arcp );
GpiSetDefArcParams( pres, &arcp );
// Draw the arc
if( ( fill == _GFILLINTERIOR ) || ( fill == _GPIEBORDER ) ) {
GpiSetCurrentPosition( pres, &ptc );
if( fill == _GFILLINTERIOR ) {
GpiBeginArea( pres, BA_BOUNDARY | BA_ALTERNATE );
}
GpiPartialArc( pres, &ptc, MAKEFIXED( 1, 0 ),
MAKEFIXED( round( start ), 0 ),
MAKEFIXED( round( sweep ), 0 ) );
GpiLine( pres, &ptc );
if( fill == _GFILLINTERIOR ) {
GpiEndArea( pres );
}
} else {
GpiSetCurrentPosition( pres, &pts );
GpiPartialArc( pres, &ptc, MAKEFIXED( 1, 0 ),
MAKEFIXED( round( start ), 0 ),
MAKEFIXED( round( sweep ), 0 ) );
}
}
#endif
static struct xycoord Cal_Coord( float x, float y, float a, float b )
/*===================================================================
This function calculates the intesection coordinates of a vector, and
an ellipse. */
{
struct xycoord point;
float delta, gamma;
x = x - _ArcInfo.centre.xcoord;
y = y - _ArcInfo.centre.ycoord;
if( ( x == 0 ) && ( y == 0 ) ) {
return _ArcInfo.centre;
}
if( x != 0 ) {
delta = atan2( b * x, a * y );
gamma = delta;
delta = sin( delta );
gamma = cos( gamma );
point.xcoord = round( a * delta ) + _ArcInfo.centre.xcoord;
point.ycoord = round( b * gamma ) + _ArcInfo.centre.ycoord;
} else {
point.xcoord = _ArcInfo.centre.xcoord;
if( y > 0 ) {
point.ycoord = b + _ArcInfo.centre.ycoord;
} else {
point.ycoord = -b + _ArcInfo.centre.ycoord;
}
}
return( point );
}
#else
static void HollowArc( short x1, short y1, short x2, short y2,
short a, short b )
//============================================================
// set up to draw a hollow arc
{
short q;
short q1;
short q2;
short x_axis_width;
short y_axis_width;
long xprod;
for( q = 0; q <= 3; ++q ) { // assume no drawing
_ArcInfo.qinf[ q ] = ARC_EMPTY;
}
x_axis_width = y2 - y1 - 2*b - 1; // either 0 or 1
y_axis_width = x2 - x1 - 2*a - 1;
q1 = Quadrant( _ArcInfo.vecta.xcoord, _ArcInfo.vecta.ycoord,
x_axis_width, y_axis_width );
q2 = Quadrant( _ArcInfo.vectb.xcoord, _ArcInfo.vectb.ycoord,
x_axis_width, y_axis_width );
if( q1 == q2 ) { // check cross product
xprod = (long) _ArcInfo.vecta.xcoord * _ArcInfo.vectb.ycoord -
(long) _ArcInfo.vectb.xcoord * _ArcInfo.vecta.ycoord;
if( xprod == 0 ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?