Support mult-data charts and legend.
authorJohn Darrington <john@darrington.wattle.id.au>
Tue, 9 Jun 2009 11:04:25 +0000 (19:04 +0800)
committerJohn Darrington <john@darrington.wattle.id.au>
Tue, 9 Jun 2009 11:04:25 +0000 (19:04 +0800)
Add support for charts to have datasets with seperate
colours, and a legend to indicate them.

src/output/chart.c
src/output/chart.h
src/output/charts/cartesian.c
src/output/charts/cartesian.h
src/output/charts/plot-chart.c
src/output/charts/plot-chart.h

index 49819e9fe03cc4073242ae97d05b77365c7e78a2..e324901cc4df1d445f3fc8c7a4b64296bca55bca 100644 (file)
@@ -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);
 }
 
index 9586eb1e068aba5f480b758a79db4463c8ae465a..4da12ecfe5b0afba3ea7035680fca5b1ea1d9af9 100644 (file)
@@ -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;
 };
 
 
index 75c49aa88c9d4fc84ec56d9439ae8560f3e2a09b..cb2f346b1b4134a0092cb322e3fe2a7a16177c55 100644 (file)
 #include <libpspp/compiler.h>
 
 
-
-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);
-
 }
index 40e3f71455f5886813eee2d3e63e04d55b3fe095..0874b9cc61d4d8f507188a00f07c44ca614176cf 100644 (file)
@@ -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);
 
 
index 3b4f1b377a12a624ceb929d00c617bb4bd581f30..5641db1213be2cd070d66cffb7daf479823076f6 100644 (file)
@@ -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);
+}
index 4a1dc10538d2567b630cca096886c8ca8e5011cd..f4cc5bbf06c3f91650c4988b15e76e36f8efc74a 100644 (file)
@@ -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