home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)psxyz.c 2.35 4/11/95
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * psxyz will read <x,y,z> triplets from stdin and plot
- * the positions in 3-D using symbols selected by the user. If no
- * symbol size is specified, psxyz expects <x,y,z,size> as input, where
- * size is the symbol size. Several map projections are supported.
- * For linear projections a 3-D basemap is provided. All symbols are
- * projected onto the xy plane (so that circles becomes ellipses) except
- * BAR and CUBE which is fully 3-D.
- * PostScript code is then written to stdout.
- *
- * Author: Paul Wessel
- * Date: 15-JAN-1991-1995
- * Version: 2.0, based on old v1.1
- *
- */
-
- #include "gmt.h"
-
- #define LINE 0
- #define BAR 1
- #define CROSS 2
- #define POINT 3
- #define CIRCLE 4
- #define SQUARE 5
- #define TRIANGLE 6
- #define DIAMOND 7
- #define CUBE 8
- #define COLUMN 9
- #define VECTOR 10
- #define VECTOR2 11
-
- #define POINTSIZE 0.005
-
- double *xp, *yp;
-
- int compare();
-
- struct DATA1 {
- double x, y, z, value, dist;
- float x_size, y_size;
- } *data1;
-
- struct DATA2 {
- double x, y, z;
- } *data2;
-
- main (argc, argv)
- int argc;
- char **argv; {
- int i, j, symbol = 0, n, ix = 0, iy = 1, n_files = 0, fno, red[3], green[3], blue[3];
- int n_alloc = GMT_CHUNK, n_read, n_col, n_args, three, four, five, bset = -1, n_expected = 3;
-
- BOOLEAN error = FALSE, nofile = TRUE, polygon = FALSE, done, read_vector = FALSE;
- BOOLEAN read_size = FALSE, outline = FALSE, multi_segments = FALSE, get_rgb = FALSE;
- BOOLEAN convert_angles = FALSE, skip_if_outside = TRUE;
-
- double xy[2], west = 0.0, east = 0.0, south = 0.0, north = 0.0, new_z_level = 0.0;
- double symbol_size_x = 0.0, symbol_size_y = 0.0, lux[3], x, y, z, tmp, base;
- double x2, y2, v_width = 0.03, h_length = 0.12, h_width = 0.1, v_w, h_l, h_w, v_shrink, v_norm;
-
- char line[512], symbol_type, col[7][100], *cpt, *more, EOL_flag = '>';
-
- FILE *fp = NULL;
-
- struct PEN pen;
- struct FILL fill;
-
- argc = gmt_begin (argc, argv);
-
- gmt_init_pen (&pen, 1);
- gmt_init_fill (&fill, -1, -1, -1); /* Default is no fill */
-
- for (i = 0; i < 3; i++) red[i] = green[i] = blue[i] = -1;
- base = gmt_NaN;
-
- /* Check and interpret the command line arguments */
-
- if (gmtdefs.measure_unit) {
- v_width = 0.075; h_length = 0.3; h_width = 0.25;
- }
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch(argv[i][1]) {
- /* Common parameters */
-
- case 'B':
- case 'H':
- case 'J':
- 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);
- break;
-
- /* Supplemental parameters */
-
- case 'C':
- cpt = &argv[i][2];
- get_rgb = 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 color for polygon */
- if (gmt_getfill (&argv[i][2], &fill)) {
- gmt_fill_syntax ('G');
- error++;
- }
- polygon = TRUE;
- break;
- case 'L': /* Draw the outline */
- outline = TRUE;
- break;
- case 'M': /* Multiple line segments */
- multi_segments = TRUE;
- if (argv[i][2]) EOL_flag = argv[i][2];
- break;
- case 'N': /* Do not clip to map */
- skip_if_outside = FALSE;
- break;
- case 'S': /* Get symbol [and size] */
- sscanf (&argv[i][2], "%c%lf/%lf", &symbol_type, &symbol_size_x, &symbol_size_y);
- if (symbol_size_y == 0.0) symbol_size_y = symbol_size_x;
- if (symbol_size_x == 0.0 && symbol != POINT) read_size = TRUE;
- symbol_size_x *= 0.5;
- symbol_size_y *= 0.5;
- switch (symbol_type) {
- case 'b':
- symbol = BAR;
- for (j = 3; argv[i][j] && bset < 0; j++) if (argv[i][j] == 'b') bset = j;
- if (bset > 0) base = atof (&argv[i][j]);
- break;
- case 'c':
- symbol = CIRCLE;
- symbol_size_x *= 2.0;
- break;
- case 'd':
- symbol = DIAMOND;
- break;
- case 'o':
- symbol = COLUMN;
- for (j = 3, bset = -1; argv[i][j] && bset < 0; j++) if (argv[i][j] == 'b') bset = j;
- if (bset > 0) base = atof (&argv[i][j]);
- break;
- case 'p':
- symbol = POINT;
- break;
- case 's':
- symbol = SQUARE;
- break;
- case 't':
- symbol = TRIANGLE;
- break;
- case 'u':
- symbol = CUBE;
- break;
- case 'V':
- convert_angles = TRUE;
- case 'v':
- symbol = VECTOR;
- read_size = FALSE;
- n_expected += 2;
- if (argv[i][3]) sscanf (&argv[i][3], "%lf/%lf/%lf", &v_width, &h_length, &h_width);
- for (j = 3; argv[i][j] && argv[i][j] != 'n'; j++);
- if (argv[i][j]) { /* Normalize option used */
- v_norm = atof (&argv[i][j+1]);
- if (v_norm > 0.0) {
- v_shrink = 1.0 / v_norm;
- symbol = VECTOR2;
- }
- }
- read_vector = TRUE;
- break;
- case 'x':
- symbol = CROSS;
- break;
- default:
- error = TRUE;
- fprintf (stderr, "%s: GMT SYNTAX ERROR -S option: Unrecognized symbol type %c\n", gmt_program, symbol_type);
- break;
- }
- if (read_size) n_expected++;
- break;
- case 'W': /* Set line attributes */
- if (gmt_getpen (&argv[i][2], &pen)) {
- gmt_pen_syntax ('W');
- error++;
- }
- break;
- case 'Z':
- new_z_level = atof (&argv[i][2]);
- break;
-
- default: /* Options not recognized */
- error = TRUE;
- gmt_default_error (argv[i][1]);
- break;
- }
- }
- else
- n_files++;
- }
-
- if (argc == 1 || gmt_quick) { /* Display usage */
- fprintf (stderr,"psxyz %s - Plot lines, polygons, and symbols in 3-D\n\n", GMT_VERSION);
- fprintf(stderr,"usage: psxyz <xyzfiles> -R<west/east/south/north/zmin/zmax> -J<params>\n");
- fprintf(stderr, " -Jz<params> [-B<tickinfo>] [-C<cpt>] [-E<az/el>] [-F<r/g/b>] [-G<fill>] [-H] [-K] [-L]\n");
- fprintf(stderr, " [-M[<flag>]] [-N] [-O] [-P] [-S<symbol><size>[/size_y]] [-U] [-V] [-W<pen>] [-X<x_shift>]\n");
- fprintf(stderr, " [-Y<y_shift>] [-c<ncopies>]\n");
-
- if (gmt_quick) exit(-1);
-
- fprintf (stderr, " <xyzfiles> is one or more files. If none, read standard input\n");
- explain_option ('j');
- explain_option ('Z');
- explain_option ('r');
- fprintf (stderr, "\n\tOPTIONS:\n");
- explain_option ('b');
- fprintf (stderr, " -C Use cpt-file to assign colors based on z-value in 3rd column\n");
- fprintf (stderr, " Must be used with -S\n");
- fprintf (stderr, " -E set user viewpoint azimuth and elevation [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 Specify color (for symbols/polygons) or pattern (for polygons). fill can be either\n");
- fprintf (stderr, " 1) <r/g/b> (each 0-255) for color or <gray> (0-255) for gray-shade [0].\n");
- fprintf (stderr, " 2) p[or P]<iconsize>/<pattern> for predefined patterns (0-31).\n");
- fprintf (stderr, " If -G is specified but not -S, psxyz draws a filled polygon.\n");
- fprintf (stderr, " Default is no fill (transparent symbols or polygons)\n");
- explain_option ('H');
- explain_option ('K');
- fprintf (stderr, " -L close polygon OR draw symbol outline with current pen (see -W).\n");
- fprintf (stderr, " -M Input files each consist of multiple segments separated by one record\n");
- fprintf (stderr, " whose first character is <flag> [>].\n");
- fprintf (stderr, " -N Do Not skip symbols that fall outside map border [Default will ignore those outside]\n");
- explain_option ('O');
- explain_option ('P');
- fprintf (stderr, " -S to select symbol type and symbol size (in %s). Choose between\n", gmt_unit_names[gmtdefs.measure_unit]);
- fprintf (stderr, " (b)ar, (c)ircle, (d)iamond, c(o)lumn, (p)oint, (s)quare, (t)riangle, c(u)be, (v)ector, (x)cross\n");
- fprintf (stderr, " If no size is specified, psxyz expects the 4th column to have sizes.\n");
- fprintf (stderr, " [Note: if -C is selected then 4th means 5th column, etc.]\n");
- fprintf (stderr, " column and cube are true 3-D objects (give size as xsize/ysize), the rest is 2-D perspective only.\n");
- fprintf (stderr, " Bar (or Column): Append b<base> to give the y- (or z-) value of the base [Default = 0 (1 for log-scales)]\n");
- fprintf (stderr, " Vectors: the direction and length must be in input columns 4 and 5.\n");
- fprintf (stderr, " Furthermore, <size> means arrowwidth/headlength/headwith [Default is %lg/%lg/%lg]\n", v_width, h_length, h_width);
- fprintf (stderr, " If -SV rather than -Sv is selected, psxy will expect azimuth and length\n");
- fprintf (stderr, " and convert azimuths based on the chosen map projection\n"); explain_option ('U');
- explain_option ('V');
- fprintf (stderr, " -W sets pen attributes [width = %d, color = (%d/%d/%d), solid line].\n",
- pen.width, pen.r, pen.g, pen.b);
- explain_option ('X');
- explain_option ('c');
- explain_option (':');
- explain_option ('.');
- exit(-1);
- }
-
- /* Check that the options selected are mutually consistant */
-
- if (!project_info.region_supplied) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify -R option\n", gmt_program);
- error++;
- }
- 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 (get_rgb && symbol == 0) {
- error++;
- fprintf (stderr, "%s: GMT SYNTAX ERROR -C option: Must also specify a symbol (see -S)\n", gmt_program);
- }
-
- if (error) exit (-1);
-
- if (get_rgb) read_cpt (cpt);
-
- if (symbol == 0 && outline) polygon = TRUE;
-
- if (bset < 0) base = (project_info.xyz_projection[2] == LOG10) ? 1.0 : 0.0;
-
- if (n_files > 0)
- nofile = FALSE;
- else
- n_files = 1;
- n_args = (argc > 1) ? argc : 2;
-
- map_setup (west, east, south, north);
-
- if (fill.r >= 0 && (symbol == COLUMN || symbol == CUBE)) { /* Modify the color for each facet */
- lux[0] = fabs (z_project.sin_az * z_project.cos_el);
- lux[1] = fabs (z_project.cos_az * z_project.cos_el);
- lux[2] = fabs (z_project.sin_el);
- tmp = MAX (lux[0], MAX (lux[1], lux[2]));
- for (i = 0; i < 3; i++) {
- lux[i] = (lux[i] / tmp) - 0.5;
- red[i] = fill.r;
- green[i] = fill.g;
- blue[i] = fill.b;
- illuminate (lux[i], &red[i], &green[i], &blue[i]);
- }
- }
-
- ps_plotinit (CNULL, 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);
-
- ps_transrotate (-z_project.xmin, -z_project.ymin, 0.0);
-
- if (new_z_level != 0.0) project_info.z_level = new_z_level;
- z_to_zz (base, &tmp); base = tmp;
-
- if (frame_info.plot) { /* First plot background axes */
- frame_info.header[0] = 0; /* No header for grdview and psxyz */
- ps_setpaint (gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]);
- map_basemap ();
- ps_setpaint (gmtdefs.background_rgb[0], gmtdefs.background_rgb[1], gmtdefs.background_rgb[2]);
- }
- ps_setline (pen.width);
- if (pen.texture) ps_setdash (pen.texture, pen.offset);
- ps_setpaint (pen.r, pen.g, pen.b);
-
- three = (get_rgb) ? 4 : 3;
- four = (get_rgb) ? 5 : 4;
- five = (get_rgb) ? 6 : 5;
-
- ix = (gmtdefs.xy_toggle); iy = 1 - ix;
- done = FALSE;
- for (fno = 1; !done && fno < n_args; fno++) { /* Loop over all input files */
- if (!nofile && argv[fno][0] == '-') continue;
- if (nofile) {
- fp = stdin;
- done = TRUE;
- }
- else if ((fp = fopen (argv[fno], "r")) == NULL) {
- fprintf (stderr, "psxy: Cannot open file %s\n", argv[fno]);
- continue;
- }
-
- if (!nofile && gmtdefs.verbose) {
- fprintf (stderr, "psxyz: Working on file %s\n", argv[fno]);
- sprintf (line, "File: %s\0", argv[fno]);
- ps_comment (line);
- }
- if (gmtdefs.io_header) for (i = 0; i < gmtdefs.n_header_recs; i++) fgets (line, 512, fp);
-
- if (multi_segments) {
- fgets (line, 512, fp);
- if (gmtdefs.verbose) ps_comment (line);
- }
-
- if (symbol > 0) { /* symbol part */
-
- gmt_world_map = TRUE;
-
- data1 = (struct DATA1 *) memory (CNULL, n_alloc, sizeof (struct DATA1), "psxyz");
- n = 0;
- while (fgets (line, 512, fp)) {
- n_col = sscanf (line, "%s %s %s %s %s %s", col[0], col[1], col[2], col[3], col[4], col[5]);
-
- if (multi_segments && col[0][0] == EOL_flag) continue;
-
- if (n_col < n_expected) {
- fprintf (stderr, "psxyz: Mismatch between expected (%d) and actual (%d) columns!\n", n_expected, n_col);
- fprintf (stderr, "--> %s\n", line);
- exit (-1);
- }
- x = atof (col[ix]);
- y = atof (col[iy]);
- z = atof (col[2]);
-
- if (skip_if_outside) {
- map_outside (x, y);
- if ( abs (gmt_x_status_new) > 1 || abs (gmt_y_status_new) > 1) continue;
- }
-
- project3D (x, y, z, &data1[n].x, &data1[n].y, &data1[n].z);
- if (get_rgb) data1[n].value = atof (col[3]);
- if (read_size) {
- data1[n].x_size = atof (col[three]);
- data1[n].y_size = (n_col == five) ? atof (col[four]) : data1[n].x_size;
- }
- else if (read_vector) {
- data1[n].x_size = atof (col[three]); /* direction */
- data1[n].y_size = atof (col[four]); /* length */
- }
- else {
- data1[n].x_size = symbol_size_x;
- data1[n].y_size = symbol_size_y;
- }
- n++;
- if (n == n_alloc) {
- n_alloc += GMT_CHUNK;
- data1 = (struct DATA1 *) memory ((char *)data1, n_alloc, sizeof (struct DATA1), "psxyz");
- }
- }
- data1 = (struct DATA1 *) memory ((char *)data1, n, sizeof (struct DATA1), "psxyz");
-
- /* Sort according to distance from viewer */
-
- sort_on_distance (data1, n);
-
- for (i = 0; i < n; i++) {
- if (get_rgb) {
- get_rgb24 (data1[i].value, &fill.r, &fill.g, &fill.b);
- if (symbol == COLUMN || symbol == CUBE) {
- for (j = 0; j < 3; j++) {
- red[j] = fill.r;
- green[j] = fill.g;
- blue[j] = fill.b;
- illuminate (lux[j], &red[j], &green[j], &blue[j]);
- }
- }
- }
-
- switch (symbol) {
- case BAR:
- bar3D (data1[i].x, data1[i].y, data1[i].z, base, (double)data1[i].x_size, fill.r, fill.g, fill.b, outline);
- break;
- case COLUMN:
- column3D (data1[i].x, data1[i].y, data1[i].z, base, (double)data1[i].x_size, (double)data1[i].y_size, red, green, blue, outline);
- break;
- case CROSS:
- cross3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size);
- break;
- case POINT:
- cross3D (data1[i].x, data1[i].y, data1[i].z, POINTSIZE);
- break;
- case CIRCLE:
- circle3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size, fill.r, fill.g, fill.b, outline);
- break;
- case SQUARE:
- square3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size, fill.r, fill.g, fill.b, outline);
- break;
- case TRIANGLE:
- triangle3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size, fill.r, fill.g, fill.b, outline);
- break;
- case DIAMOND:
- diamond3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size, fill.r, fill.g, fill.b, outline);
- break;
- case CUBE:
- cube3D (data1[i].x, data1[i].y, data1[i].z, (double)data1[i].x_size, (double)data1[i].y_size, red, green, blue, outline);
- break;
- case VECTOR:
- if (data1[i].y_size <= 0.0) continue;
- if (convert_angles) {
- azim_2_angle (data1[i].x, data1[i].y, 0.1, data1[i].x_size, &tmp);
- data1[i].x_size = tmp;
- }
- x2 = data1[i].x + data1[i].y_size * cosd (data1[i].x_size);
- y2 = data1[i].y + data1[i].y_size * sind (data1[i].x_size);
- gmt_vector3d (data1[i].x, data1[i].y, x2, y2, data1[i].z, v_width, h_length, h_width, gmtdefs.vector_shape, fill.r, fill.g, fill.b, outline);
- break;
- case VECTOR2:
- if (data1[i].y_size <= 0.0) continue;
- if (convert_angles) {
- azim_2_angle (data1[i].x, data1[i].y, 0.1, data1[i].x_size, &tmp);
- data1[i].x_size = tmp;
- }
- x2 = data1[i].x + data1[i].y_size * cosd (data1[i].x_size);
- y2 = data1[i].y + data1[i].y_size * sind (data1[i].x_size);
- if (data1[i].y_size < v_norm) { /* Scale arrow attributes down with length */
- v_w = v_width * data1[i].y_size * v_shrink;
- h_l = h_length * data1[i].y_size * v_shrink;
- h_w = h_width * data1[i].y_size * v_shrink;
- gmt_vector3d (data1[i].x, data1[i].y, x2, y2, data1[i].z, v_w, h_l, h_w, gmtdefs.vector_shape, fill.r, fill.g, fill.b, outline);
- }
- else /* Leave as specified */
- gmt_vector3d (data1[i].x, data1[i].y, x2, y2, data1[i].z, v_width, h_length, h_width, gmtdefs.vector_shape, fill.r, fill.g, fill.b, outline);
- break;
- }
- }
- free ((char *)data1);
- }
- else { /* Line/polygon part */
- data2 = (struct DATA2 *) memory (CNULL, n_alloc, sizeof (struct DATA2), "psxyz");
- more = fgets (line, 512, fp);
- n = 0;
- while (more) {
- while ((more && !multi_segments) || (more && multi_segments && line[0] != EOL_flag)) {
- n_read = sscanf (line, "%lf %lf %lf", &xy[ix], &xy[iy], &z);
- data2[n].x = xy[0]; data2[n].y = xy[1];
- data2[n].z = (n_read == 2) ? 0.0 : z;
- n++;
- if (n == n_alloc) {
- n_alloc += GMT_CHUNK;
- data2 = (struct DATA2 *) memory ((char *)data2, n_alloc, sizeof (struct DATA2), "psxyz");
- }
- more = fgets (line, 512, fp);
- }
-
- if (polygon) { /* Explicitly close polygon */
- data2[n].x = data2[0].x;
- data2[n].y = data2[0].y;
- data2[n].z = data2[0].z;
- n++;
- }
- data2 = (struct DATA2 *) memory ((char *)data2, n, sizeof (struct DATA2), "psxyz");
- n_alloc = n;
-
- xp = (double *) memory (CNULL, n, sizeof (double), "psxyz");
- yp = (double *) memory (CNULL, n, sizeof (double), "psxyz");
- for (i = 0; i < n; i++) geoz_to_xy (data2[i].x, data2[i].y, data2[i].z, &xp[i], &yp[i]);
-
- if (polygon) {
- if (fill.use_pattern)
- ps_imagefill (xp, yp, n, fill.pattern_no, fill.pattern, fill.inverse, fill.icon_size, FALSE);
- else
- ps_polygon (xp, yp, n, fill.r, fill.g, fill.b, outline);
- }
- else
- ps_line (xp, yp, n, 3, FALSE, TRUE);
-
- free ((char *)xp);
- free ((char *)yp);
- n = 0;
-
- if (more) more = fgets (line, 512, fp);
- }
- free ((char *)data2);
- }
- if (fp != stdin) fclose (fp);
-
- }
-
- if (pen.texture) ps_setdash (CNULL, 0);
-
- if (project_info.three_D) { /* Redraw front axes */
- ps_setpaint (gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]);
- vertical_axis (2);
- ps_setpaint (gmtdefs.background_rgb[0], gmtdefs.background_rgb[1], gmtdefs.background_rgb[2]);
- }
-
- ps_rotatetrans (z_project.xmin, z_project.ymin, 0.0);
- ps_plotend (gmtdefs.last_page);
-
- gmt_end (argc, argv);
- }
-
- int column3D (x, y, z, base, x_size, y_size, r, g, b, outline)
- double x, y, z, base, x_size, y_size;
- int r[3], g[3], b[3], outline; {
- int i, j, k;
- double zz, xp[4], yp[4], zp[4], plot_x[4], plot_y[4], top, sign;
-
- top = z;
- if (top < base) d_swap (top, base);
-
- for (i = 0; i < 3; i++) {
- sign = -1.0;
- zz = base;
- switch (z_project.face[i]) {
- case 0: /* yz plane positive side */
- sign = 1.0;
- case 1: /* negative side */
- xp[0] = xp[1] = xp[2] = xp[3] = x + sign * x_size;
- yp[0] = yp[3] = y - y_size; yp[1] = yp[2] = y + y_size;
- zp[0] = zp[1] = base; zp[2] = zp[3] = top;
- break;
- case 2: /* xz plane positive side */
- sign = 1.0;
- case 3: /* negative side */
- xp[0] = xp[3] = x - x_size; xp[1] = xp[2] = x + x_size;
- yp[0] = yp[1] = yp[2] = yp[3] = y + sign * y_size;
- zp[0] = zp[1] = base; zp[2] = zp[3] = top;
- break;
- case 4: /* xy plane positive side */
- zz = top;
- case 5: /* negative side */
- xp[0] = xp[3] = x - x_size; yp[0] = yp[1] = y - y_size;
- xp[1] = xp[2] = x + x_size; yp[2] = yp[3] = y + y_size;
- zp[0] = zp[1] = zp[2] = zp[3] = zz;
- break;
- }
- k = z_project.face[i] / 2;
- for (j = 0; j < 4; j++) xyz_to_xy (xp[j], yp[j], zp[j], &plot_x[j], &plot_y[j]);
- ps_patch (plot_x, plot_y, 4, r[k], g[k], b[k], outline);
- }
- }
-
- int cube3D (x, y, z, x_size, y_size, r, g, b, outline)
- double x, y, z, x_size, y_size;
- int r[3], g[3], b[3], outline; {
- int i, j, k;
- double xp[4], yp[4], zp[4], plot_x[4], plot_y[4], sign;
-
- for (i = 0; i < 3; i++) {
- sign = -1.0;
- switch (z_project.face[i]) {
- case 4: /* xy plane positive side */
- sign = 1.0;
- case 5: /* negative side */
- xp[0] = xp[3] = x - x_size; yp[0] = yp[1] = y - y_size;
- xp[1] = xp[2] = x + x_size; yp[2] = yp[3] = y + y_size;
- zp[0] = zp[1] = zp[2] = zp[3] = z + sign * x_size;
- break;
- case 2: /* xz plane positive side */
- sign = 1.0;
- case 3: /* negative side */
- xp[0] = xp[3] = x - x_size; xp[1] = xp[2] = x + x_size;
- yp[0] = yp[1] = yp[2] = yp[3] = y + sign * y_size;
- zp[0] = zp[1] = z - x_size; zp[2] = zp[3] = z + x_size;
- break;
- case 0: /* yz plane positive side */
- sign = 1.0;
- case 1: /* negative side */
- xp[0] = xp[1] = xp[2] = xp[3] = x + sign * x_size;
- yp[0] = yp[3] = y - y_size; yp[1] = yp[2] = y + y_size;
- zp[0] = zp[1] = z - x_size; zp[2] = zp[3] = z + x_size;
- break;
- }
- k = z_project.face[i] / 2;
- for (j = 0; j < 4; j++) xyz_to_xy (xp[j], yp[j], zp[j], &plot_x[j], &plot_y[j]);
- ps_patch (plot_x, plot_y, 4, r[k], g[k], b[k], outline);
- }
- }
-
- int cross3D (x, y, z, size)
- double x, y, z, size; {
- double xp[2], yp[2], plot_x, plot_y;
-
- xp[0] = x - size; xp[1] = x + size;
- yp[0] = y - size; yp[1] = y + size;
- xyz_to_xy (xp[0], yp[0], z, &plot_x, &plot_y);
- ps_plot (plot_x, plot_y, 3);
- xyz_to_xy (xp[1], yp[1], z, &plot_x, &plot_y);
- ps_plot (plot_x, plot_y, 2);
- xyz_to_xy (xp[1], yp[0], z, &plot_x, &plot_y);
- ps_plot (plot_x, plot_y, 3);
- xyz_to_xy (xp[0], yp[1], z, &plot_x, &plot_y);
- ps_plot (plot_x, plot_y, 2);
- }
-
- int bar3D (x, y, z, base, size, r, g, b, outline)
- double x, y, z, base, size;
- int r, g, b, outline; {
- int i;
- double xp[4], yp[4], plot_x[4], plot_y[4];
-
- xp[0] = xp[3] = x - size; xp[1] = xp[2] = x + size;
- yp[0] = yp[1] = base; yp[2] = yp[3] = y;
- for (i = 0; i < 4; i++) xyz_to_xy (xp[i], yp[i], z, &plot_x[i], &plot_y[i]);
- ps_patch (plot_x, plot_y, 4, r, g, b, outline);
- }
-
- int square3D (x, y, z, size, r, g, b, outline)
- double x, y, z, size;
- int r, g, b, outline; {
- int i;
- double xp[4], yp[4], plot_x[4], plot_y[4];
-
- xp[0] = xp[3] = x - size; xp[1] = xp[2] = x + size;
- yp[0] = yp[1] = y - size; yp[2] = yp[3] = y + size;
- for (i = 0; i < 4; i++) xyz_to_xy (xp[i], yp[i], z, &plot_x[i], &plot_y[i]);
- ps_patch (plot_x, plot_y, 4, r, g, b, outline);
- }
-
- int circle3D (x, y, z, size, r, g, b, outline)
- double x, y, z, size;
- int r, g, b, outline; {
- /* Must plot a squashed circle */
- int i;
- double xx, yy, a, da, plot_x[51], plot_y[51];
-
- da = 2.0 * M_PI / 50.0;
- for (i = 0; i <= 50; i++) {
- a = i * da;
- xx = x + size * cos (a);
- yy = y + size * sin (a);
- xyz_to_xy (xx, yy, z, &plot_x[i], &plot_y[i]);
- }
- ps_polygon (plot_x, plot_y, 51, r, g, b, outline);
- }
-
- int triangle3D (x, y, z, size, r, g, b, outline)
- double x, y, z, size;
- int r, g, b, outline; {
- int i;
- double xp[3], yp[3], plot_x[3], plot_y[3];
-
- xp[0] = x - size; yp[0] = yp[1] = y - 0.5773502 * size;
- xp[1] = x + size; xp[2] = x; yp[2] = y + 1.1547004 * size;
- for (i = 0; i < 3; i++) xyz_to_xy (xp[i], yp[i], z, &plot_x[i], &plot_y[i]);
- ps_patch (plot_x, plot_y, 3, r, g, b, outline);
- }
-
- int diamond3D (x, y, z, size, r, g, b, outline)
- double x, y, z, size;
- int r, g, b, outline; {
- int i;
- double xp[4], yp[4], plot_x[4], plot_y[4];
-
- xp[0] = xp[2] = x; xp[1] = x - size; xp[3] = x + size;
- yp[0] = y - size; yp[1] = yp[3] = y; yp[2] = y + size;
- for (i = 0; i < 4; i++) xyz_to_xy (xp[i], yp[i], z, &plot_x[i], &plot_y[i]);
- ps_patch (plot_x, plot_y, 4, r, g, b, outline);
- }
-
- int sort_on_distance (data, n)
- struct DATA1 *data;
- int n; {
- /* This function sorts the data array such that points farthest away are plotted first */
- int i;
- double dx, dy, x0, y0, x, y, dr, a, b, c;
-
- x0 = 0.5 * (project_info.xmin + project_info.xmax);
- y0 = 0.5 * (project_info.ymin + project_info.ymax);
-
- dx = 0.5 * (project_info.xmax - project_info.xmin);
- dy = 0.5 * (project_info.ymax - project_info.ymin);
- dr = hypot (dx, dy);
-
- x = x0 - dr * z_project.sin_az;
- y = y0 - dr * z_project.cos_az;
-
- if (z_project.cos_az == 0.0) {
- a = 1.0;
- b = 0.0;
- c = x;
- }
- else {
- a = -tan (z_project.view_azimuth);
- b = -1.0;
- c = y - x * a;
- }
-
- for (i = 0; i < n; i++) data[i].dist = fabs (a * data[i].x + b * data[i].y + c);
-
- qsort ((char *)data, n, sizeof (struct DATA1), compare);
- }
-
- int compare (point_1, point_2)
- struct DATA1 *point_1, *point_2; {
- int first;
-
- if (point_1->dist > point_2->dist)
- return (-1);
- else if (point_1->dist < point_2->dist)
- return (1);
- else {
- first = (point_1->z < point_2->z);
- if (first && z_project.view_elevation >= 0.0)
- return (-1);
- else if (first && z_project.view_elevation < 0.0)
- return (1);
- else
- return (0);
- }
- }
-