X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcharts%2Fpiechart.c;h=678578fcbd65a1cd3b3d41368eed5323cb57d1fc;hb=29917c4f5908454803e663d2ad78bca4bc35e805;hp=37788380a87ccf5c495cfb71836d138b95544750;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp diff --git a/src/output/charts/piechart.c b/src/output/charts/piechart.c index 37788380a8..678578fcbd 100644 --- a/src/output/charts/piechart.c +++ b/src/output/charts/piechart.c @@ -1,215 +1,87 @@ -/* PSPP - draws pie charts of sample statistics +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2009, 2011 Free Software Foundation, Inc. -Copyright (C) 2004 Free Software Foundation, Inc. -Written by John Darrington + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -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 the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include -#include -#include -#include -#include - +#include "output/charts/piechart.h" -#include -#include +#include -#include -#include -#include -#include +#include "libpspp/cast.h" +#include "libpspp/str.h" +#include "data/variable.h" +#include "output/chart-provider.h" +#include "gl/xalloc.h" -/* Pie charts of course need to know Pi :) */ -#ifndef M_PI -#define M_PI ( 22.0 / 7.0 ) -#endif +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid - -/* Draw a single slice of the pie */ -static void -draw_segment(struct chart *ch, - double centre_x, double centre_y, - double radius, - double start_angle, double segment_angle, - const char *colour) ; - - - -/* Draw a piechart */ -void -piechart_plot(const char *title, const struct slice *slices, int n_slices) +/* Creates and returns a chart that will render a piechart with + the of VAR and the N_SLICES described in SLICES. */ +struct chart * +piechart_create (const struct variable *var, const struct freq *slices, int n_slices) { + struct piechart *pie; int i; - double total_magnetude=0; - - struct chart *ch = chart_create(); - - const double left_label = ch->data_left + - (ch->data_right - ch->data_left)/10.0; - - const double right_label = ch->data_right - - (ch->data_right - ch->data_left)/10.0; - const double centre_x = (ch->data_right + ch->data_left ) / 2.0 ; - const double centre_y = (ch->data_top + ch->data_bottom ) / 2.0 ; - - const double radius = min( - 5.0 / 12.0 * (ch->data_top - ch->data_bottom), - 1.0 / 4.0 * (ch->data_right - ch->data_left) - ); - - - chart_write_title(ch, title); - - for (i = 0 ; i < n_slices ; ++i ) - total_magnetude += slices[i].magnetude; - - for (i = 0 ; i < n_slices ; ++i ) + pie = xmalloc (sizeof *pie); + chart_init (&pie->chart, &piechart_class, var_to_string (var)); + pie->slices = xnmalloc (n_slices, sizeof *pie->slices); + for (i = 0; i < n_slices; i++) { - static double angle=0.0; - - const double segment_angle = - slices[i].magnetude / total_magnetude * 2 * M_PI ; - - const double label_x = centre_x - - radius * sin(angle + segment_angle/2.0); - - const double label_y = centre_y + - radius * cos(angle + segment_angle/2.0); - - /* Fill the segment */ - draw_segment(ch, - centre_x, centre_y, radius, - angle, segment_angle, - data_colour[i]); - - /* Now add the labels */ - if ( label_x < centre_x ) - { - pl_line_r(ch->lp, label_x, label_y, - left_label, label_y ); - pl_moverel_r(ch->lp,0,5); - pl_alabel_r(ch->lp,0,0,slices[i].label); - } - else - { - pl_line_r(ch->lp, - label_x, label_y, - right_label, label_y - ); - pl_moverel_r(ch->lp,0,5); - pl_alabel_r(ch->lp,'r',0,slices[i].label); - } + const struct freq *src = &slices[i]; + struct slice *dst = &pie->slices[i]; - angle += segment_angle; + ds_init_empty (&dst->label); + if (var_is_value_missing (var, &src->values[0], MV_ANY)) + ds_assign_cstr (&dst->label, _("*MISSING*")); + else + var_append_value_name (var, &src->values[0], &dst->label); + + /* Chomp any whitespace from the RHS of the label. + Doing this ensures that those labels to the right + of the pie, appear right justified. */ + ds_rtrim (&dst->label, ss_cstr (" \t")); + ds_ltrim (&dst->label, ss_cstr (" \t")); + dst->magnitude = src->count; } - - /* Draw an outline to the pie */ - pl_filltype_r(ch->lp,0); - pl_fcircle_r (ch->lp, centre_x, centre_y, radius); - - chart_submit(ch); + pie->n_slices = n_slices; + return &pie->chart; } static void -fill_segment(struct chart *ch, - double x0, double y0, - double radius, - double start_angle, double segment_angle) ; - - -/* Fill a segment with the current fill colour */ -static void -fill_segment(struct chart *ch, - double x0, double y0, - double radius, - double start_angle, double segment_angle) +piechart_destroy (struct chart *chart) { + struct piechart *pie = to_piechart (chart); + int i; - const double start_x = x0 - radius * sin(start_angle); - const double start_y = y0 + radius * cos(start_angle); - - const double stop_x = - x0 - radius * sin(start_angle + segment_angle); - - const double stop_y = - y0 + radius * cos(start_angle + segment_angle); - - assert(segment_angle <= 2 * M_PI); - assert(segment_angle >= 0); - - if ( segment_angle > M_PI ) + for (i = 0; i < pie->n_slices; i++) { - /* Then we must draw it in two halves */ - fill_segment(ch, x0, y0, radius, start_angle, segment_angle / 2.0 ); - fill_segment(ch, x0, y0, radius, start_angle + segment_angle / 2.0, - segment_angle / 2.0 ); - } - else - { - pl_move_r(ch->lp, x0, y0); - - pl_cont_r(ch->lp, stop_x, stop_y); - pl_cont_r(ch->lp, start_x, start_y); - - pl_arc_r(ch->lp, - x0, y0, - stop_x, stop_y, - start_x, start_y - ); - - pl_endpath_r(ch->lp); + struct slice *slice = &pie->slices[i]; + ds_destroy (&slice->label); } + free (pie->slices); + free (pie); } - - -/* Draw a single slice of the pie */ -static void -draw_segment(struct chart *ch, - double x0, double y0, - double radius, - double start_angle, double segment_angle, - const char *colour) -{ - const double start_x = x0 - radius * sin(start_angle); - const double start_y = y0 + radius * cos(start_angle); - - pl_savestate_r(ch->lp); - - pl_savestate_r(ch->lp); - pl_colorname_r(ch->lp, colour); - - pl_pentype_r(ch->lp,1); - pl_filltype_r(ch->lp,1); - - fill_segment(ch, x0, y0, radius, start_angle, segment_angle); - pl_restorestate_r(ch->lp); - - /* Draw line dividing segments */ - pl_pentype_r(ch->lp, 1); - pl_fline_r(ch->lp, x0, y0, start_x, start_y); - - - pl_restorestate_r(ch->lp); -} - +const struct chart_class piechart_class = + { + piechart_destroy + };