#include #include #include #include #include #include #include "global.h" #define PI M_PI static int init = 0; static double sa = 0.0; static double ca = 1.0; /* rotates x and y about the origin (xo,yo) by angle radians */ static void rotate(double *x, double *y, double xo, double yo, int do3d) { double tmpx, tmpy; if (!do3d) return; /* first translate */ tmpx = *x - xo; tmpy = *y - yo; /* now rotate */ *x = tmpx * ca - tmpy * sa; *y = tmpx * sa + tmpy * ca; /* now translate back */ *x += xo; *y += yo; return; } int pie(double cx, double cy, int size, double *val, int ncols, COLOR * ocolor, COLOR * colors, int do3d) { int i, j, n; double a, end_ang, ang, tot_sum, sum, step, r, rminor; double x, y; struct line_pnts *Points; G_debug(4, "pie(): cx = %f cy = %f", cx, cy); Points = Vect_new_line_struct(); if (!init) { sa = sin(-6 / 180.0 * PI); ca = cos(-6 / 180.0 * PI); init = 1; } /* Calc sum */ tot_sum = 0; for (i = 0; i < ncols; i++) tot_sum += val[i]; if (tot_sum == 0) { Vect_destroy_line_struct(Points); return 0; /* nothing to draw */ } step = PI / 180; r = (D_d_to_u_col(2) - D_d_to_u_col(1)) * size / 2; /* do it better */ rminor = r; if (do3d) { int first, np; rminor = r * 2.0 / 3.0; /* Draw lower polygon for each value */ sum = 0; ang = 0; for (i = 0; i < ncols; i++) { if (val[i] == 0) continue; sum += val[i]; end_ang = 2 * PI * sum / tot_sum; if (end_ang <= PI) { ang = end_ang; continue; } Vect_reset_line(Points); n = (int)ceil((end_ang - ang) / step); /* upper -> lower */ a = ang; if (ang < PI) a = PI; x = cx + r * cos(a); y = cy + rminor * sin(a); rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); /* lower */ first = ang < PI ? 1 : 0; for (j = 0, a = ang; j <= n; j++, a += step) { if (j == n) a = end_ang; if (a > PI) { if (first) { x = cx + r * cos(PI); y = cy + rminor * sin(PI) - r / 5; rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); first = 0; } x = cx + r * cos(a); y = cy + rminor * sin(a) - r / 5; rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); } } np = Points->n_points + 1; /* upper */ first = end_ang > PI ? 1 : 0; for (j = 0, a = end_ang; j <= n; j++, a -= step) { if (j == n) a = ang; if (a > PI) { x = cx + r * cos(a); y = cy + rminor * sin(a); rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); } else if (first) { x = cx + r * cos(PI); y = cy + rminor * sin(PI); rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); first = 0; } } ang = end_ang; if (Points->n_points == 0) continue; if (!colors[i].none) { D_RGB_color(colors[i].r, colors[i].g, colors[i].b); D_polygon_abs(Points->x, Points->y, Points->n_points); } D_RGB_color(ocolor->r, ocolor->g, ocolor->b); Points->n_points = np; D_polyline_abs(Points->x, Points->y, Points->n_points); } } /* Draw polygon for each value */ sum = 0; ang = 0; for (i = 0; i < ncols; i++) { if (val[i] == 0) continue; sum += val[i]; end_ang = 2 * PI * sum / tot_sum; Vect_reset_line(Points); if (val[i] != tot_sum) { /* all in one slice, don't draw line to center */ x = cx; y = cy; rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); } n = (int)ceil((end_ang - ang) / step); for (j = 0, a = ang; j <= n; j++, a += step) { if (a > end_ang) a = end_ang; x = cx + r * cos(a); y = cy + rminor * sin(a); rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); } ang = end_ang; if (val[i] != tot_sum) { /* all in one slice, don't draw line to center */ x = cx; y = cy; rotate(&x, &y, cx, cy, do3d); Vect_append_point(Points, x, y, 0); } if (!colors[i].none) { D_RGB_color(colors[i].r, colors[i].g, colors[i].b); D_polygon_abs(Points->x, Points->y, Points->n_points); } D_RGB_color(ocolor->r, ocolor->g, ocolor->b); D_polyline_abs(Points->x, Points->y, Points->n_points); } Vect_destroy_line_struct(Points); return 0; }