X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcharts%2Fboxplot.c;h=7e9248004b3c2b2662f684241e55ab06b865b0c4;hb=dfd1972f7bcb550a4fc3b05dbe7e71d12334b0a7;hp=015385e74cd0ddbada68dfbf3fd2ea9f8b8df24d;hpb=c9a3c45e44c1c03d13d4eb186e3817bc836f75f8;p=pspp-builds.git diff --git a/src/output/charts/boxplot.c b/src/output/charts/boxplot.c index 015385e7..7e924800 100644 --- a/src/output/charts/boxplot.c +++ b/src/output/charts/boxplot.c @@ -19,47 +19,16 @@ #include -#include -#include -#include - -#include -#include -#include #include -#include -#include -#include - -/* Draw a box-and-whiskers plot -*/ - -struct box - { - struct box_whisker *bw; - char *label; - }; - -struct boxplot - { - struct chart chart; - double y_min; - double y_max; - char *title; - struct box *boxes; - size_t n_boxes, boxes_allocated; - }; - -static const struct chart_class boxplot_chart_class; +#include struct boxplot * boxplot_create (double y_min, double y_max, const char *title) { struct boxplot *boxplot = xmalloc (sizeof *boxplot); - chart_init (&boxplot->chart, &boxplot_chart_class); + chart_item_init (&boxplot->chart_item, &boxplot_class, title); boxplot->y_min = y_min; boxplot->y_max = y_max; - boxplot->title = xstrdup (title); boxplot->boxes = NULL; boxplot->n_boxes = boxplot->boxes_allocated = 0; return boxplot; @@ -69,7 +38,7 @@ void boxplot_add_box (struct boxplot *boxplot, struct box_whisker *bw, const char *label) { - struct box *box; + struct boxplot_box *box; if (boxplot->n_boxes >= boxplot->boxes_allocated) boxplot->boxes = x2nrealloc (boxplot->boxes, &boxplot->boxes_allocated, sizeof *boxplot->boxes); @@ -78,176 +47,15 @@ boxplot_add_box (struct boxplot *boxplot, box->label = xstrdup (label); } -struct chart * -boxplot_get_chart (struct boxplot *boxplot) -{ - return &boxplot->chart; -} - -/* Draw an OUTLIER on the plot CH - * at CENTRELINE - */ -static void -draw_case (cairo_t *cr, const struct chart_geometry *geom, double centreline, - const struct outlier *outlier) -{ - double y = geom->data_bottom + (outlier->value - geom->y_min) * geom->ordinate_scale; - chart_draw_marker (cr, centreline, y, - outlier->extreme ? MARKER_ASTERISK : MARKER_CIRCLE, - 20); - - cairo_move_to (cr, centreline + 10, y); - chart_label (cr, 'l', 'c', geom->font_size, ds_cstr (&outlier->label)); -} - -static void -boxplot_draw_box (cairo_t *cr, const struct chart_geometry *geom, - double box_centre, - double box_width, - const struct box_whisker *bw, - const char *name) -{ - double whisker[2]; - double hinge[3]; - struct ll *ll; - - const struct ll_list *outliers; - - const double box_left = box_centre - box_width / 2.0; - - const double box_right = box_centre + box_width / 2.0; - - 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_top = geom->data_bottom + (hinge[2] - geom->y_min ) * geom->ordinate_scale; - - bottom_whisker = geom->data_bottom + (whisker[0] - geom->y_min) * - geom->ordinate_scale; - - top_whisker = geom->data_bottom + (whisker[1] - geom->y_min) * geom->ordinate_scale; - - /* Draw the box */ - cairo_rectangle (cr, - box_left, - box_bottom, - box_right - box_left, - box_top - box_bottom); - cairo_save (cr); - cairo_set_source_rgb (cr, - geom->fill_colour.red / 255.0, - geom->fill_colour.green / 255.0, - geom->fill_colour.blue / 255.0); - cairo_fill (cr); - cairo_restore (cr); - cairo_stroke (cr); - - /* Draw the median */ - cairo_save (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); - cairo_line_to (cr, - box_right, - geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale); - cairo_stroke (cr); - cairo_restore (cr); - - /* Draw the bottom whisker */ - cairo_move_to (cr, box_left, bottom_whisker); - cairo_line_to (cr, box_right, bottom_whisker); - 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); - - /* Draw centre line. - (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); - - outliers = box_whisker_outliers (bw); - for (ll = ll_head (outliers); - ll != ll_null (outliers); ll = ll_next (ll)) - { - const struct outlier *outlier = ll_data (ll, struct outlier, ll); - draw_case (cr, geom, box_centre, outlier); - } - - /* 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 chart_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); -} - -static void -boxplot_chart_draw (const struct chart *chart, cairo_t *cr, - struct chart_geometry *geom) -{ - const struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); - double box_width; - size_t i; - - boxplot_draw_yscale (cr, geom, boxplot->y_max, boxplot->y_min); - chart_write_title (cr, geom, "%s", boxplot->title); - - box_width = (geom->data_right - geom->data_left) / boxplot->n_boxes / 2.0; - for (i = 0; i < boxplot->n_boxes; i++) - { - const struct box *box = &boxplot->boxes[i]; - const double box_centre = (i * 2 + 1) * box_width + geom->data_left; - boxplot_draw_box (cr, geom, box_centre, box_width, box->bw, box->label); - } -} - static void -boxplot_chart_destroy (struct chart *chart) +boxplot_chart_destroy (struct chart_item *chart_item) { - struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); + struct boxplot *boxplot = to_boxplot (chart_item); size_t i; - free (boxplot->title); for (i = 0; i < boxplot->n_boxes; i++) { - struct box *box = &boxplot->boxes[i]; + struct boxplot_box *box = &boxplot->boxes[i]; struct statistic *statistic = &box->bw->parent.parent; statistic->destroy (statistic); free (box->label); @@ -256,8 +64,7 @@ boxplot_chart_destroy (struct chart *chart) free (boxplot); } -static const struct chart_class boxplot_chart_class = +const struct chart_item_class boxplot_class = { - boxplot_chart_draw, boxplot_chart_destroy };