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>
29 #include <libpspp/assertion.h>
30 #include <libpspp/str.h>
31 #include <math/chart-geometry.h>
32 #include <output/chart-provider.h>
33 #include <output/manager.h>
34 #include <output/output.h>
38 const char *const data_colour[N_CHART_COLOURS] =
53 /* Draw a tick mark at position
54 If label is non zero, then print it at the tick mark
57 draw_tick (plPlotter *lp, const struct chart_geometry *geom,
58 enum tick_orientation orientation,
60 const char *label, ...)
62 const int tickSize = 10;
65 pl_move_r (lp, geom->data_left, geom->data_bottom);
67 if (orientation == TICK_ABSCISSA)
68 pl_flinerel_r (lp, position, 0, position, -tickSize);
69 else if (orientation == TICK_ORDINATE)
70 pl_flinerel_r (lp, 0, position, -tickSize, position);
80 s = xvasprintf (label, ap);
81 if (orientation == TICK_ABSCISSA)
82 pl_alabel_r (lp, 'c', 't', s);
83 else if (orientation == TICK_ORDINATE)
85 if (fabs (position) < DBL_EPSILON)
86 pl_moverel_r (lp, 0, 10);
87 pl_alabel_r (lp, 'r', 'c', s);
93 pl_restorestate_r (lp);
97 /* Write the title on a chart*/
99 chart_write_title (plPlotter *lp, const struct chart_geometry *geom,
100 const char *title, ...)
106 pl_ffontsize_r (lp, geom->font_size * 1.5);
107 pl_move_r (lp, geom->data_left, geom->title_bottom);
110 s = xvasprintf (title, ap);
111 pl_alabel_r (lp, 0, 0, s);
115 pl_restorestate_r (lp);
119 /* Set the scale for the abscissa */
121 chart_write_xscale (plPlotter *lp, struct chart_geometry *geom,
122 double min, double max, int ticks)
126 const double tick_interval =
127 chart_rounded_tick ((max - min) / (double) ticks);
129 geom->x_max = ceil (max / tick_interval) * tick_interval;
130 geom->x_min = floor (min / tick_interval) * tick_interval;
131 geom->abscissa_scale = fabs(geom->data_right - geom->data_left) /
132 fabs(geom->x_max - geom->x_min);
134 for (x = geom->x_min; x <= geom->x_max; x += tick_interval)
135 draw_tick (lp, geom, TICK_ABSCISSA,
136 (x - geom->x_min) * geom->abscissa_scale, "%g", x);
140 /* Set the scale for the ordinate */
142 chart_write_yscale (plPlotter *lp, struct chart_geometry *geom,
143 double smin, double smax, int ticks)
147 const double tick_interval =
148 chart_rounded_tick ((smax - smin) / (double) ticks);
150 geom->y_max = ceil (smax / tick_interval) * tick_interval;
151 geom->y_min = floor (smin / tick_interval) * tick_interval;
153 geom->ordinate_scale =
154 (fabs (geom->data_top - geom->data_bottom)
155 / fabs (geom->y_max - geom->y_min));
157 for (y = geom->y_min; y <= geom->y_max; y += tick_interval)
158 draw_tick (lp, geom, TICK_ORDINATE,
159 (y - geom->y_min) * geom->ordinate_scale, "%g", y);
162 /* Write the abscissa label */
164 chart_write_xlabel (plPlotter *lp, const struct chart_geometry *geom,
168 pl_move_r (lp, geom->data_left, geom->abscissa_top);
169 pl_alabel_r (lp, 0, 't', label);
170 pl_restorestate_r (lp);
173 /* Write the ordinate label */
175 chart_write_ylabel (plPlotter *lp, const struct chart_geometry *geom,
179 pl_move_r (lp, geom->data_bottom, geom->ordinate_right);
180 pl_textangle_r (lp, 90);
181 pl_alabel_r (lp, 0, 0, label);
182 pl_restorestate_r(lp);