/* PSPP - a program for statistical analysis.
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2011 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
#include <config.h>
-#include <output/cairo-chart.h>
+#include "output/cairo-chart.h"
#include <math.h>
-#include <output/charts/boxplot.h>
-#include <math/box-whisker.h>
-#include <math/chart-geometry.h>
+#include "math/box-whisker.h"
+#include "math/chart-geometry.h"
+#include "output/charts/boxplot.h"
/* Draw an OUTLIER on the plot CH
* at CENTRELINE
draw_case (cairo_t *cr, const struct xrchart_geometry *geom, double centreline,
const struct outlier *outlier)
{
- double y = geom->data_bottom + (outlier->value - geom->y_min) * geom->ordinate_scale;
+ double y = geom->axis[SCALE_ORDINATE].data_min + (outlier->value - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
xrchart_draw_marker (cr, centreline, y,
outlier->extreme ? XRMARKER_ASTERISK : XRMARKER_CIRCLE,
20);
const double box_right = box_centre + box_width / 2.0;
- double box_bottom ;
- double box_top ;
- double bottom_whisker ;
- double top_whisker ;
+ double box_bottom;
+ double box_top;
+ double bottom_whisker;
+ double top_whisker;
box_whisker_whiskers (bw, whisker);
box_whisker_hinges (bw, hinge);
- box_bottom = geom->data_bottom + (hinge[0] - geom->y_min ) * geom->ordinate_scale;
+ box_bottom = geom->axis[SCALE_ORDINATE].data_min + (hinge[0] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
- box_top = geom->data_bottom + (hinge[2] - geom->y_min ) * geom->ordinate_scale;
+ box_top = geom->axis[SCALE_ORDINATE].data_min + (hinge[2] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
- bottom_whisker = geom->data_bottom + (whisker[0] - geom->y_min) *
- geom->ordinate_scale;
+ bottom_whisker = geom->axis[SCALE_ORDINATE].data_min + (whisker[0] - geom->axis[SCALE_ORDINATE].min) *
+ geom->axis[SCALE_ORDINATE].scale;
- top_whisker = geom->data_bottom + (whisker[1] - geom->y_min) * geom->ordinate_scale;
+ top_whisker = geom->axis[SCALE_ORDINATE].data_min + (whisker[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
/* Draw the box */
cairo_rectangle (cr,
cairo_set_line_width (cr, cairo_get_line_width (cr) * 5);
cairo_move_to (cr,
box_left,
- geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale);
+ geom->axis[SCALE_ORDINATE].data_min + (hinge[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale);
cairo_line_to (cr,
box_right,
- geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale);
+ geom->axis[SCALE_ORDINATE].data_min + (hinge[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale);
cairo_stroke (cr);
cairo_restore (cr);
cairo_stroke (cr);
/* Draw top whisker */
- cairo_move_to (cr, box_left, top_whisker);
- cairo_line_to (cr, box_right, top_whisker);
- cairo_stroke (cr);
+ if (! isnan (top_whisker))
+ {
+ cairo_move_to (cr, box_left, top_whisker);
+ cairo_line_to (cr, box_right, top_whisker);
+ cairo_stroke (cr);
+ }
- /* Draw centre line.
- (bottom half) */
- cairo_move_to (cr, box_centre, bottom_whisker);
- cairo_line_to (cr, box_centre, box_bottom);
- cairo_stroke (cr);
+ /* Draw centre line. */
+ if (! isnan (bottom_whisker) && ! isnan (box_bottom))
+ {
+ /* (bottom half) */
+ cairo_move_to (cr, box_centre, bottom_whisker);
+ cairo_line_to (cr, box_centre, box_bottom);
+ cairo_stroke (cr);
+ }
- /* (top half) */
- cairo_move_to (cr, box_centre, top_whisker);
- cairo_line_to (cr, box_centre, box_top);
- cairo_stroke (cr);
+ if (! isnan (top_whisker) && ! isnan (box_top))
+ {
+ /* (top half) */
+ cairo_move_to (cr, box_centre, top_whisker);
+ cairo_line_to (cr, box_centre, box_top);
+ cairo_stroke (cr);
+ }
outliers = box_whisker_outliers (bw);
for (ll = ll_head (outliers);
}
/* Draw tick mark on x axis */
- draw_tick(cr, geom, TICK_ABSCISSA, box_centre - geom->data_left, "%s", name);
-}
-
-static void
-boxplot_draw_yscale (cairo_t *cr, struct xrchart_geometry *geom,
- double y_max, double y_min)
-{
- double y_tick;
- double d;
-
- geom->y_max = y_max;
- geom->y_min = y_min;
-
- y_tick = chart_rounded_tick (fabs (geom->y_max - geom->y_min) / 5.0);
-
- geom->y_min = (ceil (geom->y_min / y_tick) - 1.0) * y_tick;
-
- geom->y_max = (floor (geom->y_max / y_tick) + 1.0) * y_tick;
-
- geom->ordinate_scale = (fabs (geom->data_top - geom->data_bottom)
- / fabs (geom->y_max - geom->y_min));
-
- for (d = geom->y_min; d <= geom->y_max; d += y_tick)
- draw_tick (cr, geom, TICK_ORDINATE,
- (d - geom->y_min) * geom->ordinate_scale, "%g", d);
+ draw_tick (cr, geom, SCALE_ABSCISSA, false,
+ box_centre - geom->axis[SCALE_ABSCISSA].data_min, "%s", name);
}
void
double box_width;
size_t i;
- boxplot_draw_yscale (cr, geom, boxplot->y_max, boxplot->y_min);
+ if (! xrchart_write_yscale (cr, geom, boxplot->y_min, boxplot->y_max))
+ return;
+
xrchart_write_title (cr, geom, "%s", chart_item->title);
- box_width = (geom->data_right - geom->data_left) / boxplot->n_boxes / 2.0;
+ box_width = (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / boxplot->n_boxes / 2.0;
for (i = 0; i < boxplot->n_boxes; i++)
{
const struct boxplot_box *box = &boxplot->boxes[i];
- const double box_centre = (i * 2 + 1) * box_width + geom->data_left;
+ const double box_centre = (i * 2 + 1) * box_width + geom->axis[SCALE_ABSCISSA].data_min;
boxplot_draw_box (cr, geom, box_centre, box_width, box->bw, box->label);
}
}