PLplot 5.9.6
|
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