64f3f2c391ad01443fc8e6ab890b86ba081e468e
[pspp-builds.git] / src / output / charts / barchart.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <plot.h>
24 #include <stdarg.h>
25 #include <math.h>
26 #include <output/charts/barchart.h>
27 #include <output/chart.h>
28 #include <output/charts/plot-chart.h>
29
30 #define CATAGORIES 6
31 #define SUB_CATAGORIES 3
32
33 static const    double x_min = 0;
34 static const    double x_max = 15.0;
35
36 static const char *cat_labels[] =
37   {
38     "Age",
39     "Intelligence",
40     "Wealth",
41     "Emotional",
42     "cat 5",
43     "cat 6",
44     "cat 7",
45     "cat 8",
46     "cat 9",
47     "cat 10",
48     "cat 11"
49   };
50
51
52
53
54 /* Subcatagories */
55 static const double data1[] =
56 {
57   28,83,
58   34,
59   29,13,
60    9,4,
61    3,3,
62    2,0,
63    1,0,
64    0,
65    1,1
66 };
67
68
69 static const double data2[] =
70 {
71   45,13,
72    9,4,
73    3,43,
74    2,0,
75    1,20,
76    0,0,
77   1,1,
78   0,0
79 };
80
81 static const double data3[] =
82   {
83     23,18,
84     0, 45,23, 9, 40, 24,4, 8
85   };
86
87
88 static const char subcat_name[]="Gender";
89
90
91 struct subcat {
92   const double *data;
93   const char *label;
94 };
95
96 static const struct subcat sub_catagory[SUB_CATAGORIES] =
97   {
98     {data1, "male"},
99     {data2, "female"},
100     {data3, "47xxy"}
101   };
102
103
104
105 static const    double y_min = 0;
106 static const    double y_max = 120.0;
107 static const    double y_tick = 20.0;
108
109
110
111 static void write_legend(struct chart *chart) ;
112
113
114 void
115 draw_barchart(struct chart *ch, const char *title,
116               const char *xlabel, const char *ylabel, enum bar_opts opt)
117 {
118   double d;
119   int i;
120
121   double interval_size = fabs(ch->data_right - ch->data_left) / ( CATAGORIES );
122
123   double bar_width = interval_size / 1.1 ;
124
125   double ordinate_scale = fabs(ch->data_top -  ch->data_bottom) /
126     fabs(y_max - y_min) ;
127
128   if ( opt != BAR_STACKED )
129       bar_width /= SUB_CATAGORIES;
130
131   /* Move to data bottom-left */
132   pl_move_r(ch->lp, ch->data_left, ch->data_bottom);
133
134   pl_savestate_r(ch->lp);
135   pl_filltype_r(ch->lp,1);
136
137   /* Draw the data */
138   for (i = 0 ; i < CATAGORIES ; ++i )
139     {
140       int sc;
141       double ystart=0.0;
142       double x = i * interval_size;
143
144       pl_savestate_r(ch->lp);
145
146       draw_tick (ch, TICK_ABSCISSA, x + (interval_size/2 ),
147                  cat_labels[i]);
148
149       for(sc = 0 ; sc < SUB_CATAGORIES ; ++sc )
150         {
151
152           pl_savestate_r(ch->lp);
153           pl_fillcolorname_r(ch->lp,data_colour[sc]);
154
155           switch ( opt )
156             {
157             case BAR_GROUPED:
158               pl_fboxrel_r(ch->lp,
159                            x + (sc * bar_width ), 0,
160                            x + (sc + 1) * bar_width,
161                              sub_catagory[sc].data[i] * ordinate_scale );
162               break;
163
164
165             case BAR_STACKED:
166
167               pl_fboxrel_r(ch->lp,
168                            x, ystart,
169                            x + bar_width,
170                            ystart + sub_catagory[sc].data[i] * ordinate_scale );
171
172               ystart +=    sub_catagory[sc].data[i] * ordinate_scale ;
173
174               break;
175
176             default:
177               break;
178             }
179           pl_restorestate_r(ch->lp);
180         }
181
182       pl_restorestate_r(ch->lp);
183     }
184   pl_restorestate_r(ch->lp);
185
186   for ( d = y_min; d <= y_max ; d += y_tick )
187     {
188
189       draw_tick (ch, TICK_ORDINATE,
190                  (d - y_min ) * ordinate_scale, "%g", d);
191
192     }
193
194   /* Write the abscissa label */
195   pl_move_r(ch->lp,ch->data_left, ch->abscissa_top);
196   pl_alabel_r(ch->lp,0,'t',xlabel);
197
198
199   /* Write the ordinate label */
200   pl_savestate_r(ch->lp);
201   pl_move_r(ch->lp,ch->data_bottom, ch->ordinate_right);
202   pl_textangle_r(ch->lp,90);
203   pl_alabel_r(ch->lp,0,0,ylabel);
204   pl_restorestate_r(ch->lp);
205
206
207   chart_write_title(ch, title);
208
209   write_legend(ch);
210
211
212 }
213
214
215
216
217
218 static void
219 write_legend(struct chart *chart)
220 {
221   int sc;
222
223   pl_savestate_r(chart->lp);
224
225   pl_filltype_r(chart->lp,1);
226
227   pl_move_r(chart->lp, chart->legend_left,
228             chart->data_bottom + chart->font_size * SUB_CATAGORIES * 1.5);
229
230   pl_alabel_r(chart->lp,0,'b',subcat_name);
231
232   for (sc = 0 ; sc < SUB_CATAGORIES ; ++sc )
233     {
234       pl_fmove_r(chart->lp,
235                  chart->legend_left,
236                  chart->data_bottom + chart->font_size * sc  * 1.5);
237
238       pl_savestate_r(chart->lp);
239       pl_fillcolorname_r(chart->lp,data_colour[sc]);
240       pl_fboxrel_r (chart->lp,
241                     0,0,
242                     chart->font_size, chart->font_size);
243       pl_restorestate_r(chart->lp);
244
245       pl_fmove_r(chart->lp,
246                  chart->legend_left + chart->font_size * 1.5,
247                  chart->data_bottom + chart->font_size * sc  * 1.5);
248
249       pl_alabel_r(chart->lp,'l','b',sub_catagory[sc].label);
250     }
251
252
253   pl_restorestate_r(chart->lp);
254 }