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 + -
显示快捷键?