PLplot 5.9.6
plarc.c
00001 /* plarc()
00002  *
00003  * Copyright (C) 2009  Hezekiah M. Carty
00004  *
00005  * This file is part of PLplot.
00006  *
00007  * PLplot is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Library Public License as published
00009  * by the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * PLplot is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public License
00018  * along with PLplot; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "plplotP.h"
00023 
00024 #define CIRCLE_SEGMENTS    PL_MAXPOLY
00025 #define DEG_TO_RAD( x )                    ( ( x ) * M_PI / 180.0 )
00026 
00027 #define PLARC_POINT_X( x, a, b, theta )    ( ( x ) + ( ( a ) * cos( theta ) ) )
00028 #define PLARC_POINT_Y( y, a, b, theta )    ( ( y ) + ( ( b ) * sin( theta ) ) )
00029 
00030 /*-------------------------------------------------------------------------
00031  * plarc_approx : Plot an approximated arc with a series of lines
00032  *
00033  * Takes the same arguments, with the same units, as c_plarc below.
00034  *
00035  *-------------------------------------------------------------------------*/
00036 void
00037 plarc_approx( PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLBOOL fill )
00038 {
00039     PLINT i;
00040     PLFLT theta0, theta_step, theta, d_angle;
00041     PLINT segments;
00042     PLFLT xs[CIRCLE_SEGMENTS], ys[CIRCLE_SEGMENTS];
00043 
00044     /* The difference between the start and end angles */
00045     d_angle = DEG_TO_RAD( angle2 - angle1 );
00046     if ( fabs( d_angle ) > M_PI * 2.0 )
00047         d_angle = M_PI * 2.0;
00048 
00049     /* The number of line segments used to approximate the arc */
00050     segments = d_angle / ( 2.0 * M_PI ) * CIRCLE_SEGMENTS;
00051     /* Always use at least 2 arc points, otherwise fills will break. */
00052     if ( segments < 2 )
00053         segments = 2;
00054     /* The start angle in radians and number of radians in each approximating
00055      * segment. */
00056     theta0 = DEG_TO_RAD( angle1 );
00057 
00058     theta_step = d_angle / ( segments - 1 );
00059 
00060     /* The coordinates for the circle outline */
00061     for ( i = 0; i < segments; i++ )
00062     {
00063         theta = theta0 + theta_step * (PLFLT) i;
00064         xs[i] = PLARC_POINT_X( x, a, b, theta );
00065         ys[i] = PLARC_POINT_Y( y, a, b, theta );
00066     }
00067 
00068     if ( fill )
00069     {
00070         /* Add the center point if we aren't drawing a circle */
00071         if ( fabs( d_angle ) < M_PI * 2.0 )
00072         {
00073             xs[segments - 1] = x;
00074             ys[segments - 1] = y;
00075         }
00076         /* Draw a filled arc */
00077         plfill( segments, xs, ys );
00078     }
00079     else
00080     {
00081         /* Draw the arc outline */
00082         plline( segments, xs, ys );
00083     }
00084 }
00085 
00086 /*-------------------------------------------------------------------------
00087  * plarc : Plot an arc
00088  *
00089  * Takes the following arguments:
00090  *
00091  *   x, y:
00092  *      x and y coordinates for the center of the arc
00093  *
00094  *   a, b:
00095  *      Radius of the arc's major and minor axes
00096  *
00097  *   angle1:
00098  *      Start angle (degrees)
00099  *
00100  *   angle2:
00101  *      End angle (degrees)
00102  *
00103  *   fill:
00104  *      Should the arc be filled?
00105  *
00106  *-------------------------------------------------------------------------*/
00107 void
00108 c_plarc( PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLBOOL fill )
00109 {
00110     PLINT      xscl[2], yscl[2];
00111     PLINT      clpxmi, clpxma, clpymi, clpyma;
00112     arc_struct *arc_info;
00113 
00114     /* TODO: For now, only unrotated plots use the driver-accelerated path. */
00115     if ( plsc->dev_arc && plsc->diorot == 0 )
00116     {
00117         arc_info = (arc_struct *) malloc( (size_t) sizeof ( arc_struct ) );
00118 
00119         xscl[0] = plP_wcpcx( x - a );
00120         xscl[1] = plP_wcpcx( x + a );
00121         yscl[0] = plP_wcpcy( y - b );
00122         yscl[1] = plP_wcpcy( y + b );
00123         difilt( xscl, yscl, 2, &clpxmi, &clpxma, &clpymi, &clpyma );
00124 
00125         arc_info->x = 0.5 * ( xscl[1] + xscl[0] );
00126         arc_info->y = 0.5 * ( yscl[1] + yscl[0] );
00127         arc_info->a = 0.5 * ( xscl[1] - xscl[0] );
00128         arc_info->b = 0.5 * ( yscl[1] - yscl[0] );
00129 
00130         arc_info->angle1 = angle1;
00131         arc_info->angle2 = angle2;
00132         arc_info->fill   = fill;
00133 
00134         plP_esc( PLESC_ARC, arc_info );
00135 
00136         free( arc_info );
00137     }
00138     else
00139     {
00140         plarc_approx( x, y, a, b, angle1, angle2, fill );
00141     }
00142 }
00143 
 All Data Structures Files Functions