Support mult-data charts and legend.
[pspp-builds.git] / src / output / charts / cartesian.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17
18 #include <config.h>
19
20 #include <math.h>
21 #include <assert.h>
22
23 #include <output/chart.h>
24
25 #include <output/charts/plot-chart.h>
26 #include <output/charts/cartesian.h>
27 #include <libpspp/compiler.h>
28
29
30 /* Start a new vector called NAME */
31 void
32 chart_vector_start (struct chart *ch, const char *name)
33 {
34   if ( ! ch )
35     return ;
36
37   pl_savestate_r (ch->lp);
38
39   pl_colorname_r (ch->lp, data_colour [ch->n_datasets % N_CHART_COLOURS]);
40
41   ch->n_datasets++;
42   ch->dataset = xrealloc (ch->dataset, ch->n_datasets * sizeof (*ch->dataset));
43
44   ch->dataset[ch->n_datasets - 1] = strdup (name);
45 }
46
47 /* Plot a data point */
48 void
49 chart_datum (struct chart *ch, int dataset UNUSED, double x, double y)
50 {
51   if ( ! ch )
52     return ;
53
54   {
55     const double x_pos =
56       (x - ch->x_min) * ch->abscissa_scale + ch->data_left ;
57
58     const double y_pos =
59       (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
60
61     pl_savestate_r(ch->lp);
62
63     pl_fmarker_r(ch->lp, x_pos, y_pos, 6, 15);
64
65     pl_restorestate_r(ch->lp);
66   }
67 }
68
69 void
70 chart_vector_end (struct chart *ch)
71 {
72   pl_endpath_r (ch->lp);
73   pl_colorname_r (ch->lp, "black");
74   ch->in_path = false;
75   pl_restorestate_r (ch->lp);
76 }
77
78 /* Plot a data point */
79 void
80 chart_vector (struct chart *ch, double x, double y)
81 {
82   if ( ! ch )
83     return ;
84
85   {
86     const double x_pos =
87       (x - ch->x_min) * ch->abscissa_scale + ch->data_left ;
88
89     const double y_pos =
90       (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
91
92     if ( ch->in_path)
93       pl_fcont_r (ch->lp, x_pos, y_pos);
94     else
95       {
96         pl_fmove_r (ch->lp, x_pos, y_pos);
97         ch->in_path = true;
98       }
99   }
100 }
101
102
103
104 /* Draw a line with slope SLOPE and intercept INTERCEPT.
105    between the points limit1 and limit2.
106    If lim_dim is CHART_DIM_Y then the limit{1,2} are on the
107    y axis otherwise the x axis
108 */
109 void
110 chart_line (struct chart *ch, double slope, double intercept,
111            double limit1, double limit2, enum CHART_DIM lim_dim)
112 {
113   double x1, y1;
114   double x2, y2 ;
115
116   if ( ! ch )
117     return ;
118
119
120   if ( lim_dim == CHART_DIM_Y )
121     {
122       x1 = ( limit1 - intercept ) / slope ;
123       x2 = ( limit2 - intercept ) / slope ;
124       y1 = limit1;
125       y2 = limit2;
126     }
127   else
128     {
129       x1 = limit1;
130       x2 = limit2;
131       y1 = slope * x1 + intercept;
132       y2 = slope * x2 + intercept;
133     }
134
135   y1 = (y1 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
136   y2 = (y2 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
137   x1 = (x1 - ch->x_min) * ch->abscissa_scale + ch->data_left ;
138   x2 = (x2 - ch->x_min) * ch->abscissa_scale + ch->data_left ;
139
140   pl_savestate_r(ch->lp);
141
142   pl_fline_r(ch->lp, x1, y1, x2, y2);
143
144   pl_restorestate_r(ch->lp);
145 }