1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2009 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/>. */
19 #include <output/charts/plot-chart.h>
30 #include <libpspp/assertion.h>
31 #include <libpspp/str.h>
32 #include <math/chart-geometry.h>
33 #include <output/chart-provider.h>
34 #include <output/manager.h>
35 #include <output/output.h>
39 const char *const data_colour[N_CHART_COLOURS] =
54 /* Draw a tick mark at position
55 If label is non zero, then print it at the tick mark
58 draw_tick (plPlotter *lp, const struct chart_geometry *geom,
59 enum tick_orientation orientation,
61 const char *label, ...)
63 const int tickSize = 10;
66 pl_move_r (lp, geom->data_left, geom->data_bottom);
68 if (orientation == TICK_ABSCISSA)
69 pl_flinerel_r (lp, position, 0, position, -tickSize);
70 else if (orientation == TICK_ORDINATE)
71 pl_flinerel_r (lp, 0, position, -tickSize, position);
81 s = xvasprintf (label, ap);
82 if (orientation == TICK_ABSCISSA)
83 pl_alabel_r (lp, 'c', 't', s);
84 else if (orientation == TICK_ORDINATE)
86 if (fabs (position) < DBL_EPSILON)
87 pl_moverel_r (lp, 0, 10);
88 pl_alabel_r (lp, 'r', 'c', s);
94 pl_restorestate_r (lp);
98 /* Write the title on a chart*/
100 chart_write_title (plPlotter *lp, const struct chart_geometry *geom,
101 const char *title, ...)
107 pl_ffontsize_r (lp, geom->font_size * 1.5);
108 pl_move_r (lp, geom->data_left, geom->title_bottom);
111 s = xvasprintf (title, ap);
112 pl_alabel_r (lp, 0, 0, s);
116 pl_restorestate_r (lp);
120 /* Set the scale for the abscissa */
122 chart_write_xscale (plPlotter *lp, struct chart_geometry *geom,
123 double min, double max, int ticks)
127 const double tick_interval =
128 chart_rounded_tick ((max - min) / (double) ticks);
130 geom->x_max = ceil (max / tick_interval) * tick_interval;
131 geom->x_min = floor (min / tick_interval) * tick_interval;
132 geom->abscissa_scale = fabs(geom->data_right - geom->data_left) /
133 fabs(geom->x_max - geom->x_min);
135 for (x = geom->x_min; x <= geom->x_max; x += tick_interval)
136 draw_tick (lp, geom, TICK_ABSCISSA,
137 (x - geom->x_min) * geom->abscissa_scale, "%g", x);
141 /* Set the scale for the ordinate */
143 chart_write_yscale (plPlotter *lp, struct chart_geometry *geom,
144 double smin, double smax, int ticks)
148 const double tick_interval =
149 chart_rounded_tick ((smax - smin) / (double) ticks);
151 geom->y_max = ceil (smax / tick_interval) * tick_interval;
152 geom->y_min = floor (smin / tick_interval) * tick_interval;
154 geom->ordinate_scale =
155 (fabs (geom->data_top - geom->data_bottom)
156 / fabs (geom->y_max - geom->y_min));
158 for (y = geom->y_min; y <= geom->y_max; y += tick_interval)
159 draw_tick (lp, geom, TICK_ORDINATE,
160 (y - geom->y_min) * geom->ordinate_scale, "%g", y);
163 /* Write the abscissa label */
165 chart_write_xlabel (plPlotter *lp, const struct chart_geometry *geom,
169 pl_move_r (lp, geom->data_left, geom->abscissa_top);
170 pl_alabel_r (lp, 0, 't', label);
171 pl_restorestate_r (lp);
174 /* Write the ordinate label */
176 chart_write_ylabel (plPlotter *lp, const struct chart_geometry *geom,
180 pl_move_r (lp, geom->data_bottom, geom->ordinate_right);
181 pl_textangle_r (lp, 90);
182 pl_alabel_r (lp, 0, 0, label);
183 pl_restorestate_r(lp);