1 /* PSPP - draws pie charts of sample statistics
3 Copyright (C) 2004 Free Software Foundation, Inc.
4 Written by John Darrington <john@darrington.wattle.id.au>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29 #include "value-labels.h"
33 /* Pie charts of course need to know Pi :) */
35 #define M_PI ( 22.0 / 7.0 )
40 /* Draw a single slice of the pie */
42 draw_segment(struct chart *ch,
43 double centre_x, double centre_y,
45 double start_angle, double segment_angle,
52 piechart_plot(const char *title, const struct slice *slices, int n_slices)
55 double total_magnetude=0;
59 chart_initialise(&ch);
61 const double left_label = ch.data_left +
62 (ch.data_right - ch.data_left)/10.0;
64 const double right_label = ch.data_right -
65 (ch.data_right - ch.data_left)/10.0;
67 const double centre_x = (ch.data_right + ch.data_left ) / 2.0 ;
68 const double centre_y = (ch.data_top + ch.data_bottom ) / 2.0 ;
70 const double radius = min(
71 5.0 / 12.0 * (ch.data_top - ch.data_bottom),
72 1.0 / 4.0 * (ch.data_right - ch.data_left)
76 chart_write_title(&ch, title);
78 for (i = 0 ; i < n_slices ; ++i )
79 total_magnetude += slices[i].magnetude;
81 for (i = 0 ; i < n_slices ; ++i )
83 static double angle=0.0;
85 const double segment_angle =
86 slices[i].magnetude / total_magnetude * 2 * M_PI ;
88 const double label_x = centre_x -
89 radius * sin(angle + segment_angle/2.0);
91 const double label_y = centre_y +
92 radius * cos(angle + segment_angle/2.0);
94 /* Fill the segment */
96 centre_x, centre_y, radius,
100 /* Now add the labels */
101 if ( label_x < centre_x )
103 pl_line_r(ch.lp, label_x, label_y,
104 left_label, label_y );
105 pl_moverel_r(ch.lp,0,5);
106 pl_alabel_r(ch.lp,0,0,slices[i].label);
114 pl_moverel_r(ch.lp,0,5);
115 pl_alabel_r(ch.lp,'r',0,slices[i].label);
118 angle += segment_angle;
122 /* Draw an outline to the pie */
123 pl_filltype_r(ch.lp,0);
124 pl_fcircle_r (ch.lp, centre_x, centre_y, radius);
130 fill_segment(struct chart *ch,
131 double x0, double y0,
133 double start_angle, double segment_angle) ;
136 /* Fill a segment with the current fill colour */
138 fill_segment(struct chart *ch,
139 double x0, double y0,
141 double start_angle, double segment_angle)
144 const double start_x = x0 - radius * sin(start_angle);
145 const double start_y = y0 + radius * cos(start_angle);
147 const double stop_x =
148 x0 - radius * sin(start_angle + segment_angle);
150 const double stop_y =
151 y0 + radius * cos(start_angle + segment_angle);
153 assert(segment_angle <= 2 * M_PI);
154 assert(segment_angle >= 0);
156 if ( segment_angle > M_PI )
158 /* Then we must draw it in two halves */
159 fill_segment(ch, x0, y0, radius, start_angle, segment_angle / 2.0 );
160 fill_segment(ch, x0, y0, radius, start_angle + segment_angle / 2.0,
161 segment_angle / 2.0 );
165 pl_move_r(ch->lp, x0, y0);
167 pl_cont_r(ch->lp, stop_x, stop_y);
168 pl_cont_r(ch->lp, start_x, start_y);
176 pl_endpath_r(ch->lp);
182 /* Draw a single slice of the pie */
184 draw_segment(struct chart *ch,
185 double x0, double y0,
187 double start_angle, double segment_angle,
190 const double start_x = x0 - radius * sin(start_angle);
191 const double start_y = y0 + radius * cos(start_angle);
193 pl_savestate_r(ch->lp);
195 pl_savestate_r(ch->lp);
196 pl_colorname_r(ch->lp, colour);
198 pl_pentype_r(ch->lp,1);
199 pl_filltype_r(ch->lp,1);
201 fill_segment(ch, x0, y0, radius, start_angle, segment_angle);
202 pl_restorestate_r(ch->lp);
204 /* Draw line dividing segments */
205 pl_pentype_r(ch->lp, 1);
206 pl_fline_r(ch->lp, x0, y0, start_x, start_y);
209 pl_restorestate_r(ch->lp);