1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2008 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include <libpspp/misc.h>
24 #include <output/charts/box-whisker.h>
25 #include <output/charts/plot-chart.h>
27 #include <output/chart.h>
28 #include <math/chart-geometry.h>
29 #include <math/box-whisker.h>
31 /* Draw a box-and-whiskers plot
34 /* Draw an OUTLIER on the plot CH
38 draw_case (struct chart *ch, double centreline,
39 const struct outlier *outlier)
42 #define MARKER_CIRCLE 4
47 ch->data_bottom + (outlier->value - ch->y_min) * ch->ordinate_scale,
48 outlier->extreme ? MARKER_STAR : MARKER_CIRCLE,
51 pl_moverel_r(ch->lp, 10,0);
53 pl_alabel_r(ch->lp, 'l', 'c', ds_cstr (&outlier->label));
58 boxplot_draw_boxplot (struct chart *ch,
61 const struct box_whisker *bw,
68 const struct ll_list *outliers;
70 const double box_left = box_centre - box_width / 2.0;
72 const double box_right = box_centre + box_width / 2.0;
76 double bottom_whisker ;
79 box_whisker_whiskers (bw, whisker);
80 box_whisker_hinges (bw, hinge);
82 box_bottom = ch->data_bottom + (hinge[0] - ch->y_min ) * ch->ordinate_scale;
84 box_top = ch->data_bottom + (hinge[2] - ch->y_min ) * ch->ordinate_scale;
86 bottom_whisker = ch->data_bottom + (whisker[0] - ch->y_min) *
89 top_whisker = ch->data_bottom + (whisker[1] - ch->y_min) * ch->ordinate_scale;
91 pl_savestate_r(ch->lp);
94 pl_savestate_r (ch->lp);
95 pl_fillcolorname_r (ch->lp, ch->fill_colour);
96 pl_filltype_r (ch->lp,1);
103 pl_restorestate_r (ch->lp);
105 /* Draw the median */
106 pl_savestate_r (ch->lp);
107 pl_linewidth_r (ch->lp, 5);
110 ch->data_bottom + (hinge[1] - ch->y_min) * ch->ordinate_scale,
112 ch->data_bottom + (hinge[1] - ch->y_min) * ch->ordinate_scale);
113 pl_restorestate_r (ch->lp);
115 /* Draw the bottom whisker */
122 /* Draw top whisker */
133 box_centre, bottom_whisker,
134 box_centre, box_bottom);
138 box_centre, top_whisker,
139 box_centre, box_top);
141 outliers = box_whisker_outliers (bw);
142 for (ll = ll_head (outliers);
143 ll != ll_null (outliers); ll = ll_next (ll))
145 const struct outlier *outlier = ll_data (ll, struct outlier, ll);
146 draw_case (ch, box_centre, outlier);
149 /* Draw tick mark on x axis */
150 draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, name);
152 pl_restorestate_r(ch->lp);
156 boxplot_draw_yscale (struct chart *ch, double y_max, double y_min)
167 y_tick = chart_rounded_tick (fabs(ch->y_max - ch->y_min) / 5.0);
169 ch->y_min = (ceil( ch->y_min / y_tick ) - 1.0 ) * y_tick;
171 ch->y_max = ( floor( ch->y_max / y_tick ) + 1.0 ) * y_tick;
173 ch->ordinate_scale = fabs(ch->data_top - ch->data_bottom)
174 / fabs(ch->y_max - ch->y_min) ;
176 /* Move to data bottom-left */
178 ch->data_left, ch->data_bottom);
180 for ( d = ch->y_min; d <= ch->y_max ; d += y_tick )
182 draw_tick (ch, TICK_ORDINATE, (d - ch->y_min ) * ch->ordinate_scale, "%g", d);