From: John Darrington Date: Tue, 9 Jun 2009 11:04:25 +0000 (+0800) Subject: Support mult-data charts and legend. X-Git-Tag: build37~50^2~29 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=f7db18ef6a7e50bda368cf9a9288db58446f04c2 Support mult-data charts and legend. Add support for charts to have datasets with seperate colours, and a legend to indicate them. --- diff --git a/src/output/chart.c b/src/output/chart.c index 49819e9f..e324901c 100644 --- a/src/output/chart.c +++ b/src/output/chart.c @@ -83,6 +83,9 @@ chart_create(void) chart->legend_left = 810; chart->legend_right = 1000; chart->font_size = 0; + chart->in_path = false; + chart->dataset = NULL; + chart->n_datasets = 0; strcpy(chart->fill_colour,"red"); /* Get default font size */ @@ -100,6 +103,7 @@ chart_create(void) void chart_submit(struct chart *chart) { + int i; struct som_entity s; struct outp_driver *d; @@ -124,6 +128,11 @@ chart_submit(struct chart *chart) d = outp_drivers (NULL); d->class->finalise_chart(d, chart); + + for (i = 0 ; i < chart->n_datasets; ++i) + free (chart->dataset[i]); + free (chart->dataset); + free(chart); } diff --git a/src/output/chart.h b/src/output/chart.h index 9586eb1e..4da12ecf 100644 --- a/src/output/chart.h +++ b/src/output/chart.h @@ -64,6 +64,8 @@ struct chart { int legend_left ; int legend_right ; + const char **dataset; + int n_datasets; /* Default font size for the plot (if zero, then use plotter default) */ @@ -78,6 +80,7 @@ struct chart { double x_max; double y_min; double y_max; + bool in_path; }; diff --git a/src/output/charts/cartesian.c b/src/output/charts/cartesian.c index 75c49aa8..cb2f346b 100644 --- a/src/output/charts/cartesian.c +++ b/src/output/charts/cartesian.c @@ -27,26 +27,26 @@ #include - -struct dataset +/* Start a new vector called NAME */ +void +chart_vector_start (struct chart *ch, const char *name) { - int n_data; - const char *label; -}; + if ( ! ch ) + return ; + pl_savestate_r (ch->lp); -#define DATASETS 2 + pl_colorname_r (ch->lp, data_colour [ch->n_datasets % N_CHART_COLOURS]); -static const struct dataset dataset[DATASETS] = - { - { 13, "male"}, - { 11, "female"}, - }; + ch->n_datasets++; + ch->dataset = xrealloc (ch->dataset, ch->n_datasets * sizeof (*ch->dataset)); + ch->dataset[ch->n_datasets - 1] = strdup (name); +} /* Plot a data point */ void -chart_datum(struct chart *ch, int dataset UNUSED, double x, double y) +chart_datum (struct chart *ch, int dataset UNUSED, double x, double y) { if ( ! ch ) return ; @@ -66,13 +66,48 @@ chart_datum(struct chart *ch, int dataset UNUSED, double x, double y) } } +void +chart_vector_end (struct chart *ch) +{ + pl_endpath_r (ch->lp); + pl_colorname_r (ch->lp, "black"); + ch->in_path = false; + pl_restorestate_r (ch->lp); +} + +/* Plot a data point */ +void +chart_vector (struct chart *ch, double x, double y) +{ + if ( ! ch ) + return ; + + { + const double x_pos = + (x - ch->x_min) * ch->abscissa_scale + ch->data_left ; + + const double y_pos = + (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ; + + if ( ch->in_path) + pl_fcont_r (ch->lp, x_pos, y_pos); + else + { + pl_fmove_r (ch->lp, x_pos, y_pos); + ch->in_path = true; + } + } +} + + + /* Draw a line with slope SLOPE and intercept INTERCEPT. between the points limit1 and limit2. If lim_dim is CHART_DIM_Y then the limit{1,2} are on the y axis otherwise the x axis */ void -chart_line(struct chart *ch, double slope, double intercept, +chart_line (struct chart *ch, double slope, double intercept, double limit1, double limit2, enum CHART_DIM lim_dim) { double x1, y1; @@ -107,5 +142,4 @@ chart_line(struct chart *ch, double slope, double intercept, pl_fline_r(ch->lp, x1, y1, x2, y2); pl_restorestate_r(ch->lp); - } diff --git a/src/output/charts/cartesian.h b/src/output/charts/cartesian.h index 40e3f714..0874b9cc 100644 --- a/src/output/charts/cartesian.h +++ b/src/output/charts/cartesian.h @@ -27,16 +27,19 @@ enum CHART_DIM }; +void chart_vector_start (struct chart *ch, const char *name); +void chart_vector (struct chart *ch, double x, double y); +void chart_vector_end (struct chart *ch); /* Plot a data point */ -void chart_datum(struct chart *ch, int dataset UNUSED, double x, double y); +void chart_datum (struct chart *ch, int dataset UNUSED, double x, double y); /* Draw a line with slope SLOPE and intercept INTERCEPT. between the points limit1 and limit2. If lim_dim is CHART_DIM_Y then the limit{1,2} are on the y axis otherwise the x axis */ -void chart_line(struct chart *ch, double slope, double intercept, +void chart_line (struct chart *ch, double slope, double intercept, double limit1, double limit2, enum CHART_DIM lim_dim); diff --git a/src/output/charts/plot-chart.c b/src/output/charts/plot-chart.c index 3b4f1b37..5641db12 100644 --- a/src/output/charts/plot-chart.c +++ b/src/output/charts/plot-chart.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -210,3 +210,47 @@ chart_write_ylabel(struct chart *ch, const char *label) pl_restorestate_r(ch->lp); } + + +void +chart_write_legend (struct chart *ch) +{ + int i; + const int vstep = ch->font_size * 2; + const int xpad = 10; + const int ypad = 10; + const int swatch = 20; + const int legend_top = ch->data_top; + const int legend_bottom = legend_top - + (vstep * ch->n_datasets + 2 * ypad ); + + if ( ! ch ) + return ; + + pl_savestate_r (ch->lp); + + pl_box_r (ch->lp, ch->legend_left, legend_top, + ch->legend_right - xpad, legend_bottom); + + for (i = 0 ; i < ch->n_datasets ; ++i ) + { + const int ypos = vstep * (i + 1); + const int xpos = ch->legend_left + xpad; + pl_move_r (ch->lp, xpos, legend_top - ypos); + + pl_savestate_r(ch->lp); + pl_fillcolorname_r (ch->lp, data_colour [ i % N_CHART_COLOURS]); + + pl_pentype_r (ch->lp, 1); + pl_filltype_r (ch->lp, 1); + pl_boxrel_r (ch->lp, 0, 0, swatch, swatch); + + + pl_moverel_r (ch->lp, swatch, 0); + pl_alabel_r (ch->lp, 0, 0, ch->dataset[i]); + + pl_restorestate_r (ch->lp); + } + + pl_restorestate_r (ch->lp); +} diff --git a/src/output/charts/plot-chart.h b/src/output/charts/plot-chart.h index 4a1dc105..f4cc5bbf 100644 --- a/src/output/charts/plot-chart.h +++ b/src/output/charts/plot-chart.h @@ -70,4 +70,6 @@ void chart_write_xlabel(struct chart *ch, const char *label) ; /* Write the ordinate label */ void chart_write_ylabel(struct chart *ch, const char *label); +void chart_write_legend (struct chart *ch); + #endif