PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plarc.c
Go to the documentation of this file.
1 // plarc()
2 //
3 // Copyright (C) 2009 Hezekiah M. Carty
4 //
5 // This file is part of PLplot.
6 //
7 // PLplot is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU Library General Public License as published
9 // by the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // PLplot is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with PLplot; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 
25 
26 #include "plplotP.h"
27 
28 #define CIRCLE_SEGMENTS ( PL_MAXPOLY - 1 )
29 #define DEG_TO_RAD( x ) ( ( x ) * M_PI / 180.0 )
30 
31 void plarc_approx( PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLFLT rotate, PLBOOL fill );
32 
33 //--------------------------------------------------------------------------
34 // plarc_approx : Plot an approximated arc with a series of lines
35 //
49 //--------------------------------------------------------------------------
50 void
51 plarc_approx( PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLFLT rotate, PLBOOL fill )
52 {
53  PLINT i;
54  PLFLT theta0, theta_step, theta, d_angle;
55  PLINT segments;
56  PLFLT xs[CIRCLE_SEGMENTS + 1], ys[CIRCLE_SEGMENTS + 1];
57  PLFLT cphi, sphi, ctheta, stheta;
58 
59  // The difference between the start and end angles
60  d_angle = DEG_TO_RAD( angle2 - angle1 );
61  if ( fabs( d_angle ) > M_PI * 2.0 )
62  d_angle = M_PI * 2.0;
63 
64  // Calculate cosine and sine of angle of major axis wrt the x axis
65  cphi = cos( DEG_TO_RAD( rotate ) );
66  sphi = sin( DEG_TO_RAD( rotate ) );
67 
68  // The number of line segments used to approximate the arc
69  segments = (PLINT) ( fabs( d_angle ) / ( 2.0 * M_PI ) * CIRCLE_SEGMENTS );
70  // Always use at least 2 arc points, otherwise fills will break.
71  if ( segments < 2 )
72  segments = 2;
73  // The start angle in radians and number of radians in each approximating
74  // segment.
75  theta0 = DEG_TO_RAD( angle1 );
76 
77  theta_step = d_angle / ( segments - 1 );
78 
79  // The coordinates for the circle outline
80  for ( i = 0; i < segments; i++ )
81  {
82  theta = theta0 + theta_step * (PLFLT) i;
83  ctheta = cos( theta );
84  stheta = sin( theta );
85  xs[i] = x + a * ctheta * cphi - b * stheta * sphi;
86  ys[i] = y + a * ctheta * sphi + b * stheta * cphi;
87  }
88 
89  if ( fill )
90  {
91  // Add the center point if we aren't drawing a circle
92  if ( fabs( d_angle ) < M_PI * 2.0 )
93  {
94  xs[segments] = x;
95  ys[segments] = y;
96  segments++;
97  }
98  // Draw a filled arc
99  plfill( segments, xs, ys );
100  }
101  else
102  {
103  // Draw the arc outline
104  plline( segments, xs, ys );
105  }
106 }
107 
108 //--------------------------------------------------------------------------
109 // plarc : Plot an arc
110 //
138 //
139 //--------------------------------------------------------------------------
140 void
141 c_plarc( PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLFLT rotate, PLBOOL fill )
142 {
143  PLINT xscl[2], yscl[2];
144  PLINT clpxmi, clpxma, clpymi, clpyma;
145  arc_struct *arc_info;
146 
147  // TODO: For now, only unrotated plots use the driver-accelerated path.
148  if ( plsc->dev_arc && plsc->diorot == 0 )
149  {
150  arc_info = (arc_struct *) malloc( (size_t) sizeof ( arc_struct ) );
151 
152  xscl[0] = plP_wcpcx( x - a );
153  xscl[1] = plP_wcpcx( x + a );
154  yscl[0] = plP_wcpcy( y - b );
155  yscl[1] = plP_wcpcy( y + b );
156  difilt( xscl, yscl, 2, &clpxmi, &clpxma, &clpymi, &clpyma );
157 
158  arc_info->x = 0.5 * ( xscl[1] + xscl[0] );
159  arc_info->y = 0.5 * ( yscl[1] + yscl[0] );
160  arc_info->a = 0.5 * ( xscl[1] - xscl[0] );
161  arc_info->b = 0.5 * ( yscl[1] - yscl[0] );
162 
163  arc_info->angle1 = angle1;
164  arc_info->angle2 = angle2;
165  arc_info->rotate = rotate;
166  arc_info->fill = fill;
167 
168  plP_esc( PLESC_ARC, arc_info );
169 
170  free( arc_info );
171  }
172  else
173  {
174  plarc_approx( x, y, a, b, angle1, angle2, rotate, fill );
175  }
176 }
177