home *** CD-ROM | disk | FTP | other *** search
Wrap
/*-------------------------------------------------------------------- * The GMT-system: @(#)psrose.c 2.19 3/13/95 * * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith * See README file for copying and redistribution conditions. *--------------------------------------------------------------------*/ /* * psrose reads a file [or standard input] with azimuth and length information * and draws a sector or rose diagram. Several options for plot layout are available. * 2 diagrams are possible: Full circle (360) or half circle (180). In the * latter case azimuths > 180 are reversed (-= 180). psrose are fully * compatible with other gmtsystem v2.0 plot files and overlays. * * To be compatible with GMT, I assume radial distance to be "x" * and azimuth to be "y". Hence, west = 0.0 and east = max_radius * south/north is -90,90 for halfcircle and 0,360 for full circle * * Author: Paul Wessel * Date: 20-JAN-1995 * Version: 3.0 */ #include "gmt.h" int n_alloc = GMT_CHUNK; double *xx, *yy, *sum; double *azimuth, *length; double mode_direction[50]; /* Max 50 modes allowed */ double mode_length[50]; main (argc, argv) int argc; char **argv; { int i, n_bins, bin, n_anot, n = 0, ar = 0, ag = 0, ab = 0; int status, n_alpha, n_modes, ix, iy; BOOLEAN error = FALSE, inquire = FALSE, outline = FALSE, find_mean = FALSE, normalize = FALSE; BOOLEAN half_only = FALSE, rose = FALSE, windrose = TRUE, sector_plot = FALSE; BOOLEAN eq_area = FALSE, draw_modes = FALSE, automatic = FALSE; double scale = 3.0, max = 0.0, sector = 0.0, radius, az, x_origin, y_origin, tmp; double angle1, angle2, angle, x, y, mean_theta, mean_radius, xr = 0.0, yr = 0.0; double x1, x2, y1, y2, total = 0.0, total_arc, off, max_radius, az_offset; double tailwidth = 0.02, headlength = 0.2, headwidth = 0.08, xy[2]; double west = 0.0, east = 0.0, south = 0.0, north = 0.0, asize, lsize, zscale = 1.0; char text[512], lw[10], le[10], ln[10], format[20], file[80]; FILE *fp = NULL, *fpm = NULL; struct PEN pen; struct FILL fill; argc = gmt_begin (argc, argv); if (gmtdefs.measure_unit) { scale = 7.5; } gmt_init_fill (&fill, 0, 0, 0); gmt_init_pen (&pen, 1); asize = gmtdefs.anot_font_size / gmt_ppu[gmtdefs.measure_unit]; lsize = gmtdefs.label_font_size / gmt_ppu[gmtdefs.measure_unit]; strcpy (lw, "WEST"); strcpy (le, "EAST"); strcpy (ln, "NORTH"); strcpy (file, "(stdin)"); /* Check and interpret the command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { /* Common parameters */ case 'B': case 'H': case 'K': case 'O': case 'P': case 'R': case 'U': case 'V': case 'X': case 'x': case 'Y': case 'y': case 'c': case ':': case '\0': error += get_common_args (argv[i], &west, &east, &south, &north); west = 0.0; break; /* Supplemental options */ case 'A': /* Get Sector angle in degrees */ sector = atof (&argv[i][2]); if (argv[i][strlen (argv[i])-1] == 'r') rose = TRUE; break; case 'C': /* Read mode file and plot directions */ draw_modes = TRUE; if ((fpm = fopen (&argv[i][2], "r")) == NULL) find_mean = TRUE; break; case 'E': sscanf (&argv[i][2], "%lf/%lf", &z_project.view_azimuth, &z_project.view_elevation); break; case 'F': if (gmt_getrgb (&argv[i][2], &gmtdefs.basemap_frame_rgb[0], &gmtdefs.basemap_frame_rgb[1], &gmtdefs.basemap_frame_rgb[2])) { gmt_pen_syntax ('F'); error++; } break; case 'G': /* Set Gray shade */ if (gmt_getfill (&argv[i][2], &fill)) { gmt_fill_syntax ('G'); error++; } break; case 'I': /* Compute statistics only - no plot */ inquire = TRUE; break; case 'M': /* Get arrow parameters */ if (argv[i][2]) { n = sscanf (&argv[i][2], "%lf/%lf/%lf/%d/%d/%d", &tailwidth, &headlength, &headwidth, &ar, &ag, &ab); if (n != 6) { fprintf (stderr, "%s: GMT SYNTAX ERROR -M option. Correct syntax:\n", gmt_program); fprintf (stderr, "\t-M<tailwidth/headlength/headwidth/r/g/b>\n"); error = TRUE; } else if (check_rgb (ar, ag, ab)) { fprintf (stderr, "%s: GMT SYNTAX ERROR -M option. RGB must all be in 0-255 range\n", gmt_program); error = TRUE; } } break; case 'N': /* Make sectors area be proportional to frequency instead of radius */ eq_area = TRUE; break; case 'S': /* Get radius of unit circle in inches */ scale = atof (&argv[i][2]); if (argv[i][strlen (argv[i])-1] == 'n') normalize = TRUE; break; case 'W': /* Get pen width for outline */ if (gmt_getpen (&argv[i][2], &pen)) { gmt_pen_syntax ('W'); error++; } outline = TRUE; break; case 'Z': /* Scale radii before using data */ zscale = atof (&argv[i][2]); break; default: /* Options not recognized */ error = TRUE; gmt_default_error (argv[i][1]); break; } } else { strcpy (file, argv[i]); if ((fp = fopen (file, "r")) == NULL) { fprintf (stderr, "psrose: Cannot open file %s\n", file); exit (-1); } } } if (argc == 1 || gmt_quick) { fprintf (stderr,"psrose %s - Polar histogram (rose diagram) plotter\n\n", GMT_VERSION); fprintf (stderr, "usage: psrose <infile> [-A<sector_angle>[r]] [-B<tickinfo>] \n"); fprintf (stderr, " [-C[<modes>]] [-Eaz/el] [-F<r/g/b>] [-G<fill>] [-H] [-I] [-K] [-M<parameters>]\n"); fprintf (stderr, " [-N] [-O] [-P] [-R<r0/r1/theta0/theta1>] [-Sscale[n]] [-U[label]] [-V] [-:]\n"); fprintf (stderr, " [-Wpen] [-Xx_shift] [-Yy_shift] [-Zscale] [-cncopies]\n\n"); if (gmt_quick) exit (-1); fprintf (stderr, " <infile> has (length,azimuth) pairs. If not given read standard input\n"); fprintf (stderr, "\n\tOPTIONS:\n"); fprintf (stderr, " -A sector width in degrees for sector diagram [Default is windrose]\n"); fprintf (stderr, " append r to get rose diagram\n"); explain_option ('B'); fprintf (stderr, " (Remember: radial is x-direction, azimuthal is y-direction)\n"); fprintf (stderr, " -C plot vectors listed in the <modes> file. If no file, use mean direction\n"); fprintf (stderr, " -D for inquire. Only compute statistics - no plot is created\n"); fprintf (stderr, " -E set azimuth and elevation of viewpoint for 3-D perspective [180/90]\n"); fprintf (stderr, " -F Set color used for Frame and anotation [%d/%d/%d]\n", gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]); fprintf (stderr, " -G <fill> specify color for diagram. Default is 0/0/0 (black)\n"); explain_option ('H'); explain_option ('K'); fprintf (stderr, " -M Append tailwidth/headlength/headwidth/r/g/b to set arrow attributes [0.02/0.2/0.8/0/0/0\n"); fprintf (stderr, " -N normalizes rose plots for area, i.e. takes sqrt(r) before plotting [FALSE]\n"); fprintf (stderr, " Only applicable if normalization has been specified with -S<radius>n\n"); explain_option ('O'); explain_option ('P'); fprintf (stderr, " -R specifies the region. (r0 = 0, r1 = max_radius. For azimuth:\n"); fprintf (stderr, " Specify theta0/theta1 = -90/90 (half-circle) or 0/360 only)\n"); fprintf (stderr, " If r0 = r1 = 0, psrose will compute reasonable a r1 value.\n"); fprintf (stderr, " -S specifies the radius of the unit circle in %s [%lg]. Normalize r if n is appended\n", gmt_unit_names[gmtdefs.measure_unit], scale); explain_option ('U'); explain_option ('V'); fprintf (stderr, " -W sets pen attributes for outline of rose. [Default is no outline]\n"); explain_option ('X'); fprintf (stderr, " -Z multiply the radii by scale before plotting\n"); explain_option ('c'); fprintf (stderr, " -: Expect (azimuth,radius) input rather than (radius,azimuth) [%s]\n", gmt_choice[gmtdefs.xy_toggle]); fprintf (stderr, " (See man page for gmtdefaults to set these and other defaults to ON or OFF)\n"); exit (-1); } /* Check that the options selected are mutually consistant */ if (z_project.view_azimuth > 360.0 || z_project.view_elevation <= 0.0 || z_project.view_elevation > 90.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -E option: Enter azimuth in 0-360 range, elevation in 0-90 range\n", gmt_program); error++; } if (scale <= 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -S option: radius must be nonzero\n", gmt_program); error++; } if (zscale == 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -Z option: factor must be nonzero\n", gmt_program); error++; } if (sector < 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -A option: sector width must be positive\n", gmt_program); error++; } if (!((south == -90.0 && north == 90.0) || (south == 0.0 && north == 360.0))) { fprintf (stderr, "%s: GMT SYNTAX ERROR -R option: theta0/theta1 must be either -90/90 or 0/360\n", gmt_program); error++; } if (error) exit (-1); if (fp == NULL) fp = stdin; max_radius = east; half_only = (south == -90.0); if (rose) windrose = FALSE; sector_plot = (sector > 0.0); if (sector_plot) windrose = FALSE; /* Draw rose diagram instead of sector diagram */ if (!normalize) eq_area = FALSE; /* Only do this is data is normalized for length also */ if (!inquire && west == east) automatic = TRUE; if (half_only) { total_arc = 180.0; az_offset = 90.0; } else { total_arc = 360.0; az_offset = 0.0; } n_bins = (sector <= 0.0) ? 1 : total_arc / sector; sum = (double *) memory (CNULL, n_bins, sizeof (double), "psrose"); xx = (double *) memory (CNULL, n_bins+2, sizeof (double), "psrose"); yy = (double *) memory (CNULL, n_bins+2, sizeof (double), "psrose"); azimuth = (double *) memory (CNULL, n_alloc, sizeof (double), "psrose"); length = (double *) memory (CNULL, n_alloc, sizeof (double), "psrose"); if (gmtdefs.io_header) fscanf (fp, "%[^\n]\n", text); /* Read data and do some stats */ n = 0; ix = gmtdefs.xy_toggle; iy = 1 - ix; while (fscanf (fp, "%lf %lf", &xy[ix], &xy[iy]) != EOF) { length[n] = xy[0]; azimuth[n] = xy[1]; if (zscale != 1.0) length[n] *= zscale; /* Make sure azimuth is in 0 <= az < 360 range */ while (azimuth[n] < 0.0) azimuth[n] += 360.0; while (azimuth[n] >= 360.0) azimuth[n] -= 360.0; if (half_only) { /* Flip azimuths about E-W line i.e. -90 < az <= 90 */ if (azimuth[n] > 90.0 && azimuth[n] <= 270.0) azimuth[n] -= 180.0; if (azimuth[n] > 270.0) azimuth[n] -= 360.0; } /* Double angle to find mean azimuth */ xr += length[n] * cos (2.0 * azimuth[n] * D2R); yr += length[n] * sin (2.0 * azimuth[n] * D2R); total += length[n]; n++; if (n == n_alloc) { /* Get more memory */ n_alloc += GMT_CHUNK; azimuth = (double *) memory ((char *)azimuth, n_alloc, sizeof (double), "psrose"); length = (double *) memory ((char *)length, n_alloc, sizeof (double), "psrose"); } } if (fp != stdin) fclose (fp); if (sector > 0.0) { /* Sum up sector diagram info */ for (i = 0; i < n; i++) { bin = (azimuth[i] + az_offset) / sector; sum[bin] += length[i]; } } mean_theta = 0.5 * R2D * d_atan2 (yr, xr); if (mean_theta < 0.0) mean_theta += 360.0; mean_radius = hypot (xr, yr) / total; if (!normalize) mean_radius *= max_radius; if (sector > 0.0) { /* Find max of the bins */ for (bin = 0; bin < n_bins; bin++) if (sum[bin] > max) max = sum[bin]; if (normalize) for (bin = 0; bin < n_bins; bin++) sum[bin] /= max; if (eq_area) for (bin = 0; bin < n_bins; bin++) sum[bin] = sqrt (sum[bin]); } else { for (i = 0; i < n; i++) if (length[i] > max) max = length[i]; if (normalize) { max = 1.0 / max; for (i = 0; i < n; i++) length[i] *= max; max = 1.0 / max; } } if (inquire || gmtdefs.verbose) { fprintf (stderr, "Info for %s: n = %d rmax = %lg mean r/az = (%lg/%lg) totlength = %lg\n", file, n, max, mean_radius, mean_theta, total); if (inquire) { free ((char *)sum); free ((char *)xx); free ((char *)yy); free ((char *)azimuth); free ((char *)length); exit (-1); } } if (automatic) { if (frame_info.anot_int[0] == 0.0) { tmp = pow (10.0, floor (d_log10 (max))); if ((max / tmp) < 3.0) tmp *= 0.5; } else tmp = frame_info.anot_int[0]; max_radius = ceil (max / tmp) * tmp; if (frame_info.anot_int[0] == 0.0 || frame_info.grid_int[0]) { /* Tickmarks not set */ frame_info.anot_int[0] = frame_info.grid_int[0] = tmp; frame_info.plot = TRUE; } } if (frame_info.plot && frame_info.anot_int[1] == 0.0) frame_info.anot_int[1] = frame_info.grid_int[1] = 30.0; /* Ready to plot */ project_info.projection = LINEAR; project_info.region = TRUE; project_info.pars[0] = project_info.pars[1] = (normalize) ? 1.0 : scale / max_radius; map_setup (-scale, scale, -scale, scale); ps_plotinit (NULL, gmtdefs.overlay, gmtdefs.page_orientation, gmtdefs.x_origin, gmtdefs.y_origin, gmtdefs.global_x_scale, gmtdefs.global_y_scale, gmtdefs.n_copies, gmtdefs.dpi, gmtdefs.measure_unit, gmtdefs.paper_width, gmtdefs.page_rgb, gmt_epsinfo (argv[0])); echo_command (argc, argv); if (gmtdefs.unix_time) timestamp (argc, argv); x_origin = scale; y_origin = ((half_only) ? 0.0 : scale); ps_transrotate (x_origin, y_origin, 0.0); if (project_info.three_D) ps_transrotate (-z_project.xmin, -z_project.ymin - y_origin, 0.0); if (!normalize) scale /= max_radius; ps_setline (pen.width); ps_setpaint (pen.r, pen.g, pen.b); if (windrose) { for (i = 0; i < n; i++) { angle = (90.0 - azimuth[i]) * D2R; radius = length[i] * scale; x = radius * cos (angle); y = radius * sin (angle); plot3d (0.0, 0.0, 3); plot3d (x, y, 2); } } if (sector_plot && !rose) { /* Draw pie slices for sector plot */ for (bin = 0; bin < n_bins; bin++) { az = bin * sector - az_offset; angle1 = (90.0 - az - sector); angle2 = angle1 + sector; pie3d (0.0, 0.0, sum[bin] * scale, angle1, angle2, fill.r, fill.g, fill.b, FALSE); } } else if (rose) { /* Draw rose diagram */ for (bin = i = 0; bin < n_bins; bin++, i++) { az = bin * sector - az_offset + 0.5 * sector; angle = 90.0 - az; xx[i] = scale * sum[bin] * cos (D2R * angle); yy[i] = scale * sum[bin] * sin (D2R * angle); } if (half_only) { xx[i] = scale * 0.5 * (sum[0] + sum[n_bins-1]); yy[i] = 0.0; i++; xx[i] = -xx[i-1]; yy[i] = 0.0; i++; } if (project_info.three_D) two_d_to_three_d (xx, yy, i); ps_polygon (xx, yy, i, fill.r, fill.g, fill.b, outline); } if (sector_plot && outline && !rose) { /* Draw a line outlining the pie slices */ ps_setpaint (pen.r, pen.g, pen.b); angle1 = (half_only) ? 180.0 : 90.0; angle2 = (half_only) ? 0.0 : 90.0; angle1 *= D2R; angle2 *= D2R; x1 = (sum[0] * scale) * cos (angle1); y1 = (sum[0] * scale) * sin (angle1); x2 = (sum[n_bins-1] * scale) * cos (angle2); y2 = (sum[n_bins-1] * scale) * sin (angle2); plot3d (x1, y1, 3); plot3d (x2, y2, 2); for (bin = n_bins-1; bin >= 0; bin--) { status = (bin == 0) ? 2 : 0; az = bin * sector - az_offset; angle1 = 90.0 - az - sector; angle2 = angle1 + sector; arc3d (0.0, 0.0, sum[bin] * scale, angle1, angle2, status); angle1 *= D2R; } } if (draw_modes) { if (find_mean) { /* Use the mean direction only */ n_modes = 1; mode_direction[0] = mean_theta; mode_length[0] = mean_radius; } else { /* Get mode parameters from separate file */ n_modes = 0; while (fgets (text, 512, fpm)) { sscanf (text, "%lf %lf", &mode_direction[n_modes], &mode_length[n_modes]); n_modes++; } fclose (fpm); } for (i = 0; i < n_modes; i++) { if (eq_area) mode_length[i] = sqrt (mode_length[i]); if (half_only && mode_direction[i] > 90.0 && mode_direction[i] <= 270.0) mode_direction[i] -= 180.0; angle = D2R * (90.0 - mode_direction[i]); xr = scale * mode_length[i] * cos (angle); yr = scale * mode_length[i] * sin (angle); gmt_vector3d (0.0, 0.0, xr, yr, project_info.z_level, tailwidth, headlength, headwidth, gmtdefs.vector_shape, ar, ag, ab, TRUE); } } if (frame_info.plot) { /* Draw grid lines etc */ ps_setline (gmtdefs.grid_pen); off = max_radius * scale; ps_setpaint (gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]); n_alpha = (frame_info.grid_int[1] > 0.0) ? total_arc / frame_info.grid_int[1] : -1; for (i = 0; i <= n_alpha; i++) { angle = D2R * i * frame_info.grid_int[1]; x = max_radius * scale * cos (angle); y = max_radius * scale * sin (angle); plot3d (0.0, 0.0, 3); plot3d (x, y, 2); } n_bins = (frame_info.grid_int[0] > 0.0) ? rint (max_radius / frame_info.grid_int[0]) : -1; for (i = 1; i <= n_bins; i++) arc3d (0.0, 0.0, i * frame_info.grid_int[0] * scale, 0.0, total_arc, 3); y = lsize + 6.0 * gmtdefs.anot_offset; gmt_text3d (0.0, off + y, project_info.z_level, gmtdefs.header_font_size, gmtdefs.header_font, frame_info.header, 0.0, 2, 0); get_format (frame_info.anot_int[0], format); if (half_only) { strcpy (lw, "90\\312W"); strcpy (le, "90\\312E"); strcpy (ln, "0\\312"); y = -(3.0 * gmtdefs.anot_offset + font_height[gmtdefs.anot_font] * asize); if (frame_info.label[0][0]) gmt_text3d (0.0, y, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, frame_info.label[0], 0.0, 10, 0); y = -(5.0 * gmtdefs.anot_offset + font_height[gmtdefs.anot_font] * lsize + font_height[gmtdefs.label_font] * lsize); if (frame_info.label[1][0]) gmt_text3d (0.0, y, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, frame_info.label[1], 0.0, 10, 0); gmt_text3d (0.0, -gmtdefs.anot_offset, project_info.z_level, gmtdefs.anot_font_size, gmtdefs.anot_font, "0", 0.0, 10, 0); n_anot = (frame_info.anot_int[0] > 0.0) ? rint (max_radius / frame_info.anot_int[0]) : -1; for (i = 1; i <= n_anot; i++) { x = i * frame_info.anot_int[0]; sprintf (text, format, x); x *= scale; gmt_text3d (x, -gmtdefs.anot_offset, project_info.z_level, gmtdefs.anot_font_size, gmtdefs.anot_font, text, 0.0, 10, 0); gmt_text3d (-x, -gmtdefs.anot_offset, project_info.z_level, gmtdefs.anot_font_size, gmtdefs.anot_font, text, 0.0, 10, 0); } } else { gmt_text3d (0.0, -off - 2.0 * gmtdefs.anot_offset, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, "SOUTH", 0.0, 10, 0); plot3d (off, -off, 3); plot3d ((max_radius - frame_info.grid_int[0]) * scale, -off, 2); plot3d (off, -off, 3); plot3d (off, gmtdefs.tick_length - off, 2); plot3d ((max_radius - frame_info.grid_int[0]) * scale, -off, 3); plot3d ((max_radius - frame_info.grid_int[0]) * scale, gmtdefs.tick_length - off, 2); y = -(off + 5.0 * gmtdefs.anot_offset + font_height[gmtdefs.anot_font] * lsize + font_height[gmtdefs.label_font] * lsize); if (frame_info.label[1][0]) gmt_text3d (0.0, y, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, frame_info.label[1], 0.0, 10, 0); if (frame_info.label[0][0]) { strcat (format, " %s"); sprintf (text, format, frame_info.grid_int[0], frame_info.label[0]); } else sprintf (text, format, frame_info.grid_int[0]); gmt_text3d ((max_radius - 0.5 * frame_info.grid_int[0]) * scale, -(off + gmtdefs.anot_offset), project_info.z_level, gmtdefs.anot_font_size, gmtdefs.anot_font, text, 0.0, 10, 0); } gmt_text3d (off + 2.0 * gmtdefs.anot_offset, 0.0, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, le, 0.0, 5, 0); gmt_text3d (-off - 2.0 * gmtdefs.anot_offset, 0.0, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, lw, 0.0, 7, 0); gmt_text3d (0.0, off + 2.0 * gmtdefs.anot_offset, project_info.z_level, gmtdefs.label_font_size, gmtdefs.label_font, ln, 0.0, 2, 0); ps_setpaint (gmtdefs.background_rgb[0], gmtdefs.background_rgb[1], gmtdefs.background_rgb[2]); } if (project_info.three_D) ps_rotatetrans (z_project.xmin, z_project.ymin + y_origin, 0.0); ps_rotatetrans (-x_origin, -y_origin, 0.0); ps_plotend (gmtdefs.last_page); gmt_end (argc, argv); free ((char *)sum); free ((char *)xx); free ((char *)yy); free ((char *)azimuth); free ((char *)length); exit (0); } int arc3d (x, y, r, a1, a2, status) double x, y, r, a1, a2; int status; { int i, n; double da, a, *xx, *yy; if (project_info.three_D) { /* Must project and draw line segments */ n = ceil (a2 - a1); xx = (double *) memory (CNULL, n + 1, sizeof (double), "arc3d"); yy = (double *) memory (CNULL, n + 1, sizeof (double), "arc3d"); da = (a2 - a1) / n; for (i = 0; i <= n; i++) { a = (i == n) ? a2 : a1 + da * i; xx[i] = x + r * cosd (a); yy[i] = y + r * sind (a); } n++; two_d_to_three_d (xx, yy, n); ps_line (xx, yy, n, status, FALSE, TRUE); free ((char *)xx); free ((char *)yy); } else ps_arc (x, y, r, a1, a2, status); } int plot3d (x, y, pen) double x, y; int pen; { if (project_info.three_D) xyz_to_xy (x, y, project_info.z_level, &x, &y); ps_plot (x, y, pen); } int pie3d (x, y, rad, a1, a2, r, g, b, outline) double x, y, rad, a1, a2; int r, g, b; BOOLEAN outline; { int i, n; double da, a, *xx, *yy; if (project_info.three_D) { /* Must project and draw line segments */ n = ceil (a2 - a1); xx = (double *) memory (CNULL, n + 2, sizeof (double), "arc3d"); yy = (double *) memory (CNULL, n + 2, sizeof (double), "arc3d"); da = (a2 - a1) / n; for (i = 0; i <= n; i++) { a = (i == n) ? a2 : a1 + da * i; xx[i] = x + rad * cosd (a); yy[i] = y + rad * sind (a); } xx[i] = x; yy[i] = y; n += 2; two_d_to_three_d (xx, yy, n); ps_polygon (xx, yy, n, r, g, b, outline); free ((char *)xx); free ((char *)yy); } else ps_pie (x, y, rad, a1, a2, r, g, b, outline); }