Annotation of OpenXM_contrib/gnuplot/graph3d.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: graph3d.c,v 1.106 1998/06/18 14:55:07 ddenholm Exp $";
! 3: #endif
! 4:
! 5: /* GNUPLOT - graph3d.c */
! 6:
! 7: /*[
! 8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
! 9: *
! 10: * Permission to use, copy, and distribute this software and its
! 11: * documentation for any purpose with or without fee is hereby granted,
! 12: * provided that the above copyright notice appear in all copies and
! 13: * that both that copyright notice and this permission notice appear
! 14: * in supporting documentation.
! 15: *
! 16: * Permission to modify the software is granted, but not the right to
! 17: * distribute the complete modified source code. Modifications are to
! 18: * be distributed as patches to the released version. Permission to
! 19: * distribute binaries produced by compiling modified sources is granted,
! 20: * provided you
! 21: * 1. distribute the corresponding source modifications from the
! 22: * released version in the form of a patch file along with the binaries,
! 23: * 2. add special version identification to distinguish your version
! 24: * in addition to the base release version number,
! 25: * 3. provide your name and address as the primary contact for the
! 26: * support of your modified version, and
! 27: * 4. retain our contact information in regard to use of the base
! 28: * software.
! 29: * Permission to distribute the released version of the source code along
! 30: * with corresponding source modifications in the form of a patch file is
! 31: * granted with same provisions 2 through 4 for binary distributions.
! 32: *
! 33: * This software is provided "as is" without express or implied warranty
! 34: * to the extent permitted by applicable law.
! 35: ]*/
! 36:
! 37:
! 38: /*
! 39: * AUTHORS
! 40: *
! 41: * Original Software:
! 42: * Gershon Elber and many others.
! 43: *
! 44: * 19 September 1992 Lawrence Crowl (crowl@cs.orst.edu)
! 45: * Added user-specified bases for log scaling.
! 46: *
! 47: * 3.6 - split graph3d.c into graph3d.c (graph),
! 48: * util3d.c (intersections, etc)
! 49: * hidden3d.c (hidden-line removal code)
! 50: *
! 51: */
! 52:
! 53: #include "plot.h"
! 54: #include "setshow.h"
! 55:
! 56: static int p_height;
! 57: static int p_width; /* pointsize * t->h_tic */
! 58: static int key_entry_height; /* bigger of t->v_size, pointsize*t->v_tick */
! 59:
! 60: int suppressMove = 0; /* to prevent moveto while drawing contours */
! 61:
! 62: /*
! 63: * hidden_line_type_above, hidden_line_type_below - controls type of lines
! 64: * for above and below parts of the surface.
! 65: * hidden_no_update - if TRUE lines will be hidden line removed but they
! 66: * are not assumed to be part of the surface (i.e. grid) and therefore
! 67: * do not influence the hidings.
! 68: * hidden_active - TRUE if hidden lines are to be removed.
! 69: */
! 70: int hidden_active = FALSE;
! 71: int hidden_no_update; /* HBB 980324: made this visible despite LITE */
! 72:
! 73: /* LITE defines a restricted memory version for MS-DOS, which doesn't
! 74: * use the routines in hidden3d.c
! 75: */
! 76:
! 77: #ifndef LITE
! 78: int hidden_line_type_above, hidden_line_type_below;
! 79: #endif /* LITE */
! 80:
! 81:
! 82: static double LogScale __PROTO((double coord, TBOOLEAN is_log,
! 83: double log_base_log, char *what, char *axis));
! 84: static void plot3d_impulses __PROTO((struct surface_points * plot));
! 85: static void plot3d_lines __PROTO((struct surface_points * plot));
! 86: static void plot3d_points __PROTO((struct surface_points * plot));
! 87: static void plot3d_dots __PROTO((struct surface_points * plot));
! 88: static void cntr3d_impulses __PROTO((struct gnuplot_contours * cntr,
! 89: struct surface_points * plot));
! 90: static void cntr3d_lines __PROTO((struct gnuplot_contours * cntr));
! 91: static void cntr3d_points __PROTO((struct gnuplot_contours * cntr,
! 92: struct surface_points * plot));
! 93: static void cntr3d_dots __PROTO((struct gnuplot_contours * cntr));
! 94: static void check_corner_height __PROTO((struct coordinate GPHUGE * point,
! 95: double height[2][2], double depth[2][2]));
! 96: static void draw_bottom_grid __PROTO((struct surface_points * plot,
! 97: int plot_count));
! 98: static void xtick_callback __PROTO((int axis, double place, char *text,
! 99: struct lp_style_type grid));
! 100: static void ytick_callback __PROTO((int axis, double place, char *text,
! 101: struct lp_style_type grid));
! 102: static void ztick_callback __PROTO((int axis, double place, char *text,
! 103: struct lp_style_type grid));
! 104: static void setlinestyle __PROTO((struct lp_style_type style));
! 105:
! 106: static void boundary3d __PROTO((int scaling, struct surface_points * plots,
! 107: int count));
! 108: #if 0 /* not used */
! 109: static double dbl_raise __PROTO((double x, int y));
! 110: #endif
! 111: static void map_position __PROTO((struct position * pos, unsigned int *x,
! 112: unsigned int *y, char *what));
! 113:
! 114: /* put entries in the key */
! 115: static void key_sample_line __PROTO((int xl, int yl));
! 116: static void key_sample_point __PROTO((int xl, int yl, int pointtype));
! 117: static void key_text __PROTO((int xl, int yl, char *text));
! 118:
! 119:
! 120: #if defined(sun386) || defined(AMIGA_SC_6_1)
! 121: static double CheckLog __PROTO((TBOOLEAN is_log, double base_log, double x));
! 122: #endif
! 123:
! 124: /*
! 125: * The Amiga SAS/C 6.2 compiler moans about macro envocations causing
! 126: * multiple calls to functions. I converted these macros to inline
! 127: * functions coping with the problem without loosing speed.
! 128: * (MGR, 1993)
! 129: */
! 130: #ifdef AMIGA_SC_6_1
! 131: GP_INLINE static TBOOLEAN i_inrange(int z, int min, int max)
! 132: {
! 133: return ((min < max) ? ((z >= min) && (z <= max)) : ((z >= max) && (z <= min)));
! 134: }
! 135:
! 136: GP_INLINE static double f_max(double a, double b)
! 137: {
! 138: return (max(a, b));
! 139: }
! 140:
! 141: GP_INLINE static double f_min(double a, double b)
! 142: {
! 143: return (min(a, b));
! 144: }
! 145:
! 146: #else
! 147: # define f_max(a,b) GPMAX((a),(b))
! 148: # define f_min(a,b) GPMIN((a),(b))
! 149: # define i_inrange(z,a,b) inrange((z),(a),(b))
! 150: #endif
! 151:
! 152: #define apx_eq(x,y) (fabs(x-y) < 0.001)
! 153: #define ABS(x) ((x) >= 0 ? (x) : -(x))
! 154: #define SQR(x) ((x) * (x))
! 155:
! 156: /* Define the boundary of the plot
! 157: * These are computed at each call to do_plot, and are constant over
! 158: * the period of one do_plot. They actually only change when the term
! 159: * type changes and when the 'set size' factors change.
! 160: */
! 161:
! 162: /* in order to allow graphic.c to use clip_draw_line, we must
! 163: * share xleft, xright, ybot, ytop with graphics.c
! 164: */
! 165: extern int xleft, xright, ybot, ytop;
! 166:
! 167: int xmiddle, ymiddle, xscaler, yscaler;
! 168: static int ptitl_cnt;
! 169: static int max_ptitl_len;
! 170: static int titlelin;
! 171: static int key_sample_width, key_rows, key_cols, key_col_wth, yl_ref;
! 172: static int ktitle_lines = 0;
! 173:
! 174:
! 175: /* Boundary and scale factors, in user coordinates */
! 176: /* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
! 177: * file and are not the same as variables of the same names in other files
! 178: */
! 179: /*static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d; */
! 180: /* sizes are now set in min_array[], max_array[] from plot.c */
! 181: extern double min_array[], max_array[];
! 182: extern int auto_array[], log_array[];
! 183: extern double base_array[], log_base_array[];
! 184:
! 185: /* for convenience while converting to use these arrays */
! 186: #define x_min3d min_array[FIRST_X_AXIS]
! 187: #define x_max3d max_array[FIRST_X_AXIS]
! 188: #define y_min3d min_array[FIRST_Y_AXIS]
! 189: #define y_max3d max_array[FIRST_Y_AXIS]
! 190: #define z_min3d min_array[FIRST_Z_AXIS]
! 191: #define z_max3d max_array[FIRST_Z_AXIS]
! 192:
! 193: /* There are several z's to take into account - I hope I get these
! 194: * right !
! 195: *
! 196: * ceiling_z is the highest z in use
! 197: * floor_z is the lowest z in use
! 198: * base_z is the z of the base
! 199: * min3d_z is the lowest z of the graph area
! 200: * max3d_z is the highest z of the graph area
! 201: *
! 202: * ceiling_z is either max3d_z or base_z, and similarly for floor_z
! 203: * There should be no part of graph drawn outside
! 204: * min3d_z:max3d_z - apart from arrows, perhaps
! 205: */
! 206:
! 207: double ceiling_z, floor_z, base_z;
! 208:
! 209: /* and some bodges while making the change */
! 210: #define min3d_z min_array[FIRST_Z_AXIS]
! 211: #define max3d_z max_array[FIRST_Z_AXIS]
! 212:
! 213:
! 214: double xscale3d, yscale3d, zscale3d;
! 215:
! 216:
! 217: typedef double transform_matrix[4][4];
! 218: transform_matrix trans_mat;
! 219:
! 220: static double xaxis_y, yaxis_x, zaxis_x, zaxis_y;
! 221:
! 222: /* the co-ordinates of the back corner */
! 223: static double back_x, back_y;
! 224:
! 225: /* the penalty for convenience of using tic_gen to make callbacks
! 226: * to tick routines is that we cant pass parameters very easily.
! 227: * We communicate with the tick_callbacks using static variables
! 228: */
! 229:
! 230: /* unit vector (terminal coords) */
! 231: static double tic_unitx, tic_unity;
! 232:
! 233: /* (DFK) Watch for cancellation error near zero on axes labels */
! 234: #define SIGNIF (0.01) /* less than one hundredth of a tic mark */
! 235: #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
! 236: #define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
! 237:
! 238: /* And the functions to map from user to terminal coordinates */
! 239: #define map_x(x) (int)(x+0.5) /* maps floating point x to screen */
! 240: #define map_y(y) (int)(y+0.5) /* same for y */
! 241:
! 242: /* And the functions to map from user 3D space into normalized -1..1 */
! 243: #define map_x3d(x) ((x-x_min3d)*xscale3d-1.0)
! 244: #define map_y3d(y) ((y-y_min3d)*yscale3d-1.0)
! 245: #define map_z3d(z) ((z-floor_z)*zscale3d-1.0)
! 246:
! 247:
! 248:
! 249: /* Initialize the line style using the current device and set hidden styles
! 250: * to it as well if hidden line removal is enabled */
! 251: static void setlinestyle(style)
! 252: struct lp_style_type style;
! 253: {
! 254: term_apply_lp_properties(&style);
! 255:
! 256: #ifndef LITE
! 257: if (hidden3d) {
! 258: hidden_line_type_above = style.l_type;
! 259: hidden_line_type_below = style.l_type;
! 260: }
! 261: #endif /* LITE */
! 262: }
! 263:
! 264: /* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog
! 265: * macro, so I write it as a function on that machine.
! 266: *
! 267: * Amiga SAS/C 6.2 thinks it will do too much work calling functions in
! 268: * macro arguments twice, thus I inline theese functions. (MGR, 1993)
! 269: */
! 270: #if defined(sun386) || defined(AMIGA_SC_6_1)
! 271: GP_INLINE static double CheckLog(is_log, base_log, x)
! 272: TBOOLEAN is_log;
! 273: double base_log;
! 274: double x;
! 275: {
! 276: if (is_log)
! 277: return (pow(base_log, x));
! 278: else
! 279: return (x);
! 280: }
! 281: #else
! 282: /* (DFK) Use 10^x if logscale is in effect, else x */
! 283: # define CheckLog(is_log, base_log, x) ((is_log) ? pow(base_log, (x)) : (x))
! 284: #endif /* sun386 || SAS/C */
! 285:
! 286: static double LogScale(coord, is_log, log_base_log, what, axis)
! 287: double coord; /* the value */
! 288: TBOOLEAN is_log; /* is this axis in logscale? */
! 289: double log_base_log; /* if so, the log of its base */
! 290: char *what; /* what is the coord for? */
! 291: char *axis; /* which axis is this for ("x" or "y")? */
! 292: {
! 293: if (is_log) {
! 294: if (coord <= 0.0) {
! 295: char errbuf[100]; /* place to write error message */
! 296: (void) sprintf(errbuf, "%s has %s coord of %g; must be above 0 for log scale!",
! 297: what, axis, coord);
! 298: graph_error(errbuf);
! 299: } else
! 300: return (log(coord) / log_base_log);
! 301: }
! 302: return (coord);
! 303: }
! 304:
! 305: /* And the functions to map from user 3D space to terminal coordinates */
! 306: void map3d_xy(x, y, z, xt, yt)
! 307: double x, y, z;
! 308: unsigned int *xt, *yt;
! 309: {
! 310: int i, j;
! 311: double v[4], res[4], /* Homogeneous coords. vectors. */
! 312: w = trans_mat[3][3];
! 313:
! 314: v[0] = map_x3d(x); /* Normalize object space to -1..1 */
! 315: v[1] = map_y3d(y);
! 316: v[2] = map_z3d(z);
! 317: v[3] = 1.0;
! 318:
! 319: for (i = 0; i < 2; i++) { /* Dont use the third axes (z). */
! 320: res[i] = trans_mat[3][i]; /* Initiate it with the weight factor */
! 321: for (j = 0; j < 3; j++)
! 322: res[i] += v[j] * trans_mat[j][i];
! 323: }
! 324:
! 325: for (i = 0; i < 3; i++)
! 326: w += v[i] * trans_mat[i][3];
! 327: if (w == 0)
! 328: w = 1e-5;
! 329:
! 330: *xt = (unsigned int) ((res[0] * xscaler / w) + xmiddle);
! 331: *yt = (unsigned int) ((res[1] * yscaler / w) + ymiddle);
! 332: }
! 333:
! 334:
! 335:
! 336: /* And the functions to map from user 3D space to terminal z coordinate */
! 337: int map3d_z(x, y, z)
! 338: double x, y, z;
! 339: {
! 340: int i, zt;
! 341: double v[4], res, /* Homogeneous coords. vectors. */
! 342: w = trans_mat[3][3];
! 343:
! 344: v[0] = map_x3d(x); /* Normalize object space to -1..1 */
! 345: v[1] = map_y3d(y);
! 346: v[2] = map_z3d(z);
! 347: v[3] = 1.0;
! 348:
! 349: res = trans_mat[3][2]; /* Initiate it with the weight factor. */
! 350: for (i = 0; i < 3; i++)
! 351: res += v[i] * trans_mat[i][2];
! 352: if (w == 0)
! 353: w = 1e-5;
! 354: for (i = 0; i < 3; i++)
! 355: w += v[i] * trans_mat[i][3];
! 356: zt = ((int) (res * 16384 / w));
! 357: return zt;
! 358: }
! 359:
! 360: /* borders of plotting area */
! 361: /* computed once on every call to do_plot */
! 362: static void boundary3d(scaling, plots, count)
! 363: TBOOLEAN scaling; /* TRUE if terminal is doing the scaling */
! 364: struct surface_points *plots;
! 365: int count;
! 366: {
! 367: register struct termentry *t = term;
! 368: int ytlen, i;
! 369:
! 370: titlelin = 0;
! 371:
! 372: p_height = pointsize * t->v_tic;
! 373: p_width = pointsize * t->h_tic;
! 374: if (key_swidth >= 0)
! 375: key_sample_width = key_swidth * (t->h_char) + pointsize * (t->h_tic);
! 376: else
! 377: key_sample_width = 0;
! 378: key_entry_height = pointsize * (t->v_tic) * 1.25 * key_vert_factor;
! 379: if (key_entry_height < (t->v_char)) {
! 380: /* is this reasonable ? */
! 381: key_entry_height = (t->v_char) * key_vert_factor;
! 382: }
! 383:
! 384: /* count max_len key and number keys (plot-titles and contour labels) with len > 0 */
! 385: max_ptitl_len = find_maxl_keys3d(plots, count, &ptitl_cnt);
! 386: if ((ytlen = label_width(key_title, &ktitle_lines)) > max_ptitl_len)
! 387: max_ptitl_len = ytlen;
! 388: key_col_wth = (max_ptitl_len + 4) * (t->h_char) + key_sample_width;
! 389:
! 390: /* luecken@udel.edu modifications
! 391: sizes the plot to take up more of available resolution */
! 392: if (lmargin >= 0)
! 393: xleft = (t->h_char) * lmargin;
! 394: else
! 395: xleft = (t->h_char) * 2 + (t->h_tic);
! 396: xright = (scaling ? 1 : xsize) * (t->xmax) - (t->h_char) * 2 - (t->h_tic);
! 397: key_rows = ptitl_cnt;
! 398: key_cols = 1;
! 399: if (key == -1 && key_vpos == TUNDER) {
! 400: /* calculate max no cols, limited by label-length */
! 401: key_cols = (int) (xright - xleft) / ((max_ptitl_len + 4) * (t->h_char) + key_sample_width);
! 402: key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
! 403: /* now calculate actual no cols depending on no rows */
! 404: key_cols = (int) (ptitl_cnt / key_rows) + ((ptitl_cnt % key_rows) > 0);
! 405: key_col_wth = (int) (xright - xleft) / key_cols;
! 406: /* key_rows += ktitle_lines; - messes up key - div */
! 407: }
! 408: /* this should also consider the view and number of lines in
! 409: * xformat || yformat || xlabel || ylabel */
! 410:
! 411: /* an absolute 1, with no terminal-dependent scaling ? */
! 412: ybot = (t->v_char) * 2.5 + 1;
! 413: if (key_rows && key_vpos == TUNDER)
! 414: ybot += key_rows * key_entry_height + ktitle_lines * t->v_char;
! 415:
! 416: if (strlen(title.text)) {
! 417: titlelin++;
! 418: for (i = 0; i < strlen(title.text); i++) {
! 419: if (title.text[i] == '\\')
! 420: titlelin++;
! 421: }
! 422: }
! 423: ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char) * (titlelin + 1.5) - 1;
! 424: if (key == -1 && key_vpos != TUNDER) {
! 425: /* calculate max no rows, limited be ytop-ybot */
! 426: i = (int) (ytop - ybot) / (t->v_char) - 1 - ktitle_lines;
! 427: if (ptitl_cnt > i) {
! 428: key_cols = (int) (ptitl_cnt / i) + ((ptitl_cnt % i) > 0);
! 429: /* now calculate actual no rows depending on no cols */
! 430: key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
! 431: }
! 432: key_rows += ktitle_lines;
! 433: }
! 434: if (key_hpos == TOUT) {
! 435: xright -= key_col_wth * (key_cols - 1) + key_col_wth - 2 * (t->h_char);
! 436: }
! 437: xleft += t->xmax * xoffset;
! 438: xright += t->xmax * xoffset;
! 439: ytop += t->ymax * yoffset;
! 440: ybot += t->ymax * yoffset;
! 441: xmiddle = (xright + xleft) / 2;
! 442: ymiddle = (ytop + ybot) / 2;
! 443: /* HBB 980308: sigh... another 16bit glitch: on term's with more than
! 444: * 8000 pixels in either direction, these calculations produce garbage
! 445: * results if done in (16bit) ints */
! 446: xscaler = (xright - xleft) * 4 / 7; /* HBB: Magic number alert! */
! 447: yscaler = ((ytop - ybot) * 4L) / 7L;
! 448:
! 449: }
! 450:
! 451: #if 0
! 452: /* not used ; anyway, should be done using bitshifts and squares,
! 453: * rather than iteratively
! 454: */
! 455: static double dbl_raise(x, y)
! 456: double x;
! 457: int y;
! 458: {
! 459: register int i = ABS(y);
! 460: double val = 1.0;
! 461: while (--i >= 0)
! 462: val *= x;
! 463: if (y < 0)
! 464: return (1.0 / val);
! 465: return (val);
! 466: }
! 467: #endif
! 468:
! 469: /* we precalculate features of the key, to save lots of nested
! 470: * ifs in code - x,y = user supplied or computed position of key
! 471: * taken to be inner edge of a line sample
! 472: */
! 473: static int key_sample_left; /* offset from x for left of line sample */
! 474: static int key_sample_right; /* offset from x for right of line sample */
! 475: static int key_point_offset; /* offset from x for point sample */
! 476: static int key_text_left; /* offset from x for left-justified text */
! 477: static int key_text_right; /* offset from x for right-justified text */
! 478: static int key_size_left; /* distance from x to left edge of box */
! 479: static int key_size_right; /* distance from x to right edge of box */
! 480:
! 481: void do_3dplot(plots, pcount)
! 482: struct surface_points *plots;
! 483: int pcount; /* count of plots in linked list */
! 484: {
! 485: struct termentry *t = term;
! 486: int surface;
! 487: struct surface_points *this_plot = NULL;
! 488: unsigned int xl, yl;
! 489: int linetypeOffset = 0;
! 490: double ztemp, temp;
! 491: struct text_label *this_label;
! 492: struct arrow_def *this_arrow;
! 493: TBOOLEAN scaling;
! 494: transform_matrix mat;
! 495: int key_count;
! 496: char ss[MAX_LINE_LEN+1], *s, *e;
! 497:
! 498: /* Initiate transformation matrix using the global view variables. */
! 499: mat_rot_z(surface_rot_z, trans_mat);
! 500: mat_rot_x(surface_rot_x, mat);
! 501: mat_mult(trans_mat, trans_mat, mat);
! 502: mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat);
! 503: mat_mult(trans_mat, trans_mat, mat);
! 504:
! 505: /* modify min_z/max_z so it will zscale properly. */
! 506: ztemp = (z_max3d - z_min3d) / (2.0 * surface_zscale);
! 507: temp = (z_max3d + z_min3d) / 2.0;
! 508: z_min3d = temp - ztemp;
! 509: z_max3d = temp + ztemp;
! 510:
! 511:
! 512: /* The extrema need to be set even when a surface is not being
! 513: * drawn. Without this, gnuplot used to assume that the X and
! 514: * Y axis started at zero. -RKC
! 515: */
! 516:
! 517: if (polar)
! 518: graph_error("Cannot splot in polar coordinate system.");
! 519:
! 520: /* done in plot3d.c
! 521: * if (z_min3d == VERYLARGE || z_max3d == -VERYLARGE ||
! 522: * x_min3d == VERYLARGE || x_max3d == -VERYLARGE ||
! 523: * y_min3d == VERYLARGE || y_max3d == -VERYLARGE)
! 524: * graph_error("all points undefined!");
! 525: */
! 526:
! 527: /* If we are to draw the bottom grid make sure zmin is updated properly. */
! 528: if (xtics || ytics || work_grid.l_type) {
! 529: base_z = z_min3d - (z_max3d - z_min3d) * ticslevel;
! 530: if (ticslevel >= 0)
! 531: floor_z = base_z;
! 532: else
! 533: floor_z = z_min3d;
! 534:
! 535: if (ticslevel < -1)
! 536: ceiling_z = base_z;
! 537: else
! 538: ceiling_z = z_max3d;
! 539: } else {
! 540: floor_z = base_z = z_min3d;
! 541: ceiling_z = z_max3d;
! 542: }
! 543:
! 544: /* see comment accompanying similar tests of x_min/x_max and y_min/y_max
! 545: * in graphics.c:do_plot(), for history/rationale of these tests */
! 546: if (x_min3d == x_max3d)
! 547: graph_error("x_min3d should not equal x_max3d!");
! 548: if (y_min3d == y_max3d)
! 549: graph_error("y_min3d should not equal y_max3d!");
! 550: if (z_min3d == z_max3d)
! 551: graph_error("z_min3d should not equal z_max3d!");
! 552:
! 553: #ifndef LITE
! 554: if (hidden3d) {
! 555: struct surface_points *plot;
! 556: int p = 0;
! 557: /* Verify data is hidden line removable - grid based. */
! 558: for (plot = plots; ++p <= pcount; plot = plot->next_sp) {
! 559: if (plot->plot_type == DATA3D && !plot->has_grid_topology) {
! 560: fprintf(stderr, "Notice: Cannot remove hidden lines from non grid data\n");
! 561: return;
! 562: }
! 563: }
! 564: }
! 565: #endif /* not LITE */
! 566:
! 567: term_start_plot();
! 568:
! 569: screen_ok = FALSE;
! 570: scaling = (*t->scale) (xsize, ysize);
! 571:
! 572: /* now compute boundary for plot (xleft, xright, ytop, ybot) */
! 573: boundary3d(scaling, plots, pcount);
! 574:
! 575: /* SCALE FACTORS */
! 576: zscale3d = 2.0 / (ceiling_z - floor_z);
! 577: yscale3d = 2.0 / (y_max3d - y_min3d);
! 578: xscale3d = 2.0 / (x_max3d - x_min3d);
! 579:
! 580: term_apply_lp_properties(&border_lp); /* border linetype */
! 581:
! 582: /* PLACE TITLE */
! 583: if (*title.text != 0) {
! 584: safe_strncpy(ss, title.text, sizeof(ss));
! 585: write_multiline((unsigned int) ((xleft + xright) / 2 + title.xoffset * t->h_char),
! 586: (unsigned int) (ytop + (titlelin + title.yoffset) * (t->h_char)),
! 587: ss, CENTRE, JUST_TOP, 0, title.font);
! 588: }
! 589: /* PLACE TIMEDATE */
! 590: if (*timelabel.text) {
! 591: char str[MAX_LINE_LEN+1];
! 592: time_t now;
! 593: unsigned int x = t->v_char + timelabel.xoffset * t->h_char;
! 594: unsigned int y = timelabel_bottom ?
! 595: yoffset * ymax + (timelabel.yoffset + 1) * t->v_char :
! 596: ytop + (timelabel.yoffset - 1) * t->v_char;
! 597:
! 598: time(&now);
! 599: strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now));
! 600:
! 601: if (timelabel_rotate && (*t->text_angle) (1)) {
! 602: if (timelabel_bottom)
! 603: write_multiline(x, y, str, LEFT, JUST_TOP, 1, timelabel.font);
! 604: else
! 605: write_multiline(x, y, str, RIGHT, JUST_TOP, 1, timelabel.font);
! 606:
! 607: (*t->text_angle) (0);
! 608: } else {
! 609: if (timelabel_bottom)
! 610: write_multiline(x, y, str, LEFT, JUST_BOT, 0, timelabel.font);
! 611: else
! 612: write_multiline(x, y, str, LEFT, JUST_TOP, 0, timelabel.font);
! 613: }
! 614: }
! 615: /* PLACE LABELS */
! 616: for (this_label = first_label; this_label != NULL;
! 617: this_label = this_label->next) {
! 618: unsigned int x, y;
! 619:
! 620:
! 621: map_position(&this_label->place, &x, &y, "label");
! 622: safe_strncpy(ss, this_label->text, sizeof(ss));
! 623: if (this_label->rotate && (*t->text_angle) (1)) {
! 624: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 1, this_label->font);
! 625: (*t->text_angle) (0);
! 626: } else {
! 627: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 0, this_label->font);
! 628: }
! 629: }
! 630:
! 631: /* PLACE ARROWS */
! 632: for (this_arrow = first_arrow; this_arrow != NULL;
! 633: this_arrow = this_arrow->next) {
! 634: unsigned int sx, sy, ex, ey;
! 635:
! 636: map_position(&this_arrow->start, &sx, &sy, "arrow");
! 637: map_position(&this_arrow->end, &ex, &ey, "arrow");
! 638: term_apply_lp_properties(&(this_arrow->lp_properties));
! 639: (*t->arrow) (sx, sy, ex, ey, this_arrow->head);
! 640: }
! 641:
! 642: #ifndef LITE
! 643: if (hidden3d && draw_surface) {
! 644: init_hidden_line_removal();
! 645: reset_hidden_line_removal();
! 646: hidden_active = TRUE;
! 647: }
! 648: #endif /* not LITE */
! 649:
! 650: /* WORK OUT KEY SETTINGS AND DO KEY TITLE / BOX */
! 651:
! 652: if (key_reverse) {
! 653: key_sample_left = -key_sample_width;
! 654: key_sample_right = 0;
! 655: key_text_left = t->h_char;
! 656: key_text_right = (t->h_char) * (max_ptitl_len + 1);
! 657: key_size_right = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
! 658: key_size_left = (t->h_char) + key_sample_width;
! 659: } else {
! 660: key_sample_left = 0;
! 661: key_sample_right = key_sample_width;
! 662: key_text_left = -(int) ((t->h_char) * (max_ptitl_len + 1));
! 663: key_text_right = -(int) (t->h_char);
! 664: key_size_left = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
! 665: key_size_right = (t->h_char) + key_sample_width;
! 666: }
! 667: key_point_offset = (key_sample_left + key_sample_right) / 2;
! 668:
! 669: if (key == -1) {
! 670: if (key_vpos == TUNDER) {
! 671: #if 0
! 672: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
! 673: xl = max_ptitl_len * 1000 / (key_sample_width / (t->h_char) + max_ptitl_len + 2);
! 674: xl *= (xright - xleft) / key_cols;
! 675: xl /= 1000;
! 676: xl += xleft;
! 677: #else
! 678: /* maximise no cols, limited by label-length */
! 679: key_cols = (int) (xright - xleft) / key_col_wth;
! 680: key_rows = (int) (ptitl_cnt + key_cols - 1) / key_cols;
! 681: /* now calculate actual no cols depending on no rows */
! 682: key_cols = (int) (ptitl_cnt + key_rows - 1) / key_rows;
! 683: key_col_wth = (int) (xright - xleft) / key_cols;
! 684: /* we divide into columns, then centre in column by considering
! 685: * ratio of key_left_size to key_right_size
! 686: * key_size_left/(key_size_left+key_size_right) * (xright-xleft)/key_cols
! 687: * do one integer division to maximise accuracy (hope we dont
! 688: * overflow !)
! 689: */
! 690: xl = xleft + ((xright - xleft) * key_size_left) / (key_cols * (key_size_left + key_size_right));
! 691: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
! 692: #endif
! 693: } else {
! 694: if (key_vpos == TTOP) {
! 695: yl = ytop - (t->v_tic) - t->v_char;
! 696: } else {
! 697: yl = ybot + (t->v_tic) + key_entry_height * key_rows + ktitle_lines * t->v_char;
! 698: }
! 699: if (key_hpos == TOUT) {
! 700: /* keys outside plot border (right) */
! 701: xl = xright + (t->h_tic) + key_size_left;
! 702: } else if (key_hpos == TLEFT) {
! 703: xl = xleft + (t->h_tic) + key_size_left;
! 704: } else {
! 705: xl = xright - key_size_right - key_col_wth * (key_cols - 1);
! 706: }
! 707: }
! 708: yl_ref = yl - ktitle_lines * (t->v_char);
! 709: }
! 710: if (key == 1) {
! 711: map_position(&key_user_pos, &xl, &yl, "key");
! 712: }
! 713: if (key && key_box.l_type > -3) {
! 714: int yt = yl;
! 715: int yb = yl - key_entry_height * (key_rows - ktitle_lines) - ktitle_lines * t->v_char;
! 716: int key_xr = xl + key_col_wth * (key_cols - 1) + key_size_right;
! 717: /* key_rows seems to contain title at this point ??? */
! 718: term_apply_lp_properties(&key_box);
! 719: (*t->move) (xl - key_size_left, yb);
! 720: (*t->vector) (xl - key_size_left, yt);
! 721: (*t->vector) (key_xr, yt);
! 722: (*t->vector) (key_xr, yb);
! 723: (*t->vector) (xl - key_size_left, yb);
! 724:
! 725: /* draw a horizontal line between key title and first entry JFi */
! 726: (*t->move) (xl - key_size_left, yt - (ktitle_lines) * t->v_char);
! 727: (*t->vector) (xl + key_size_right, yt - (ktitle_lines) * t->v_char);
! 728: }
! 729: /* DRAW SURFACES AND CONTOURS */
! 730:
! 731: #ifndef LITE
! 732: if (hidden3d && draw_surface)
! 733: plot3d_hidden(plots, pcount);
! 734: #endif /* not LITE */
! 735:
! 736: /* KEY TITLE */
! 737: if (key != 0 && strlen(key_title)) {
! 738: sprintf(ss, "%s\n", key_title);
! 739: s = ss;
! 740: yl -= t->v_char / 2;
! 741: while ((e = (char *) strchr(s, '\n')) != NULL) {
! 742: *e = '\0';
! 743: if (key_just == JLEFT) {
! 744: (*t->justify_text) (LEFT);
! 745: (*t->put_text) (xl + key_text_left, yl, s);
! 746: } else {
! 747: if ((*t->justify_text) (RIGHT)) {
! 748: (*t->put_text) (xl + key_text_right,
! 749: yl, s);
! 750: } else {
! 751: int x = xl + key_text_right - (t->h_char) * strlen(s);
! 752: if (inrange(x, xleft, xright))
! 753: (*t->put_text) (x, yl, s);
! 754: }
! 755: }
! 756: s = ++e;
! 757: yl -= t->v_char;
! 758: }
! 759: yl += t->v_char / 2;
! 760: }
! 761: key_count = 0;
! 762: yl_ref = yl -= key_entry_height / 2; /* centralise the keys */
! 763:
! 764: #define NEXT_KEY_LINE() \
! 765: if ( ++key_count >= key_rows ) { \
! 766: yl = yl_ref; xl += key_col_wth; key_count = 0; \
! 767: } else \
! 768: yl -= key_entry_height
! 769:
! 770: this_plot = plots;
! 771: for (surface = 0;
! 772: surface < pcount;
! 773: this_plot = this_plot->next_sp, surface++) {
! 774:
! 775: #ifndef LITE
! 776: if (hidden3d)
! 777: hidden_no_update = FALSE;
! 778: #endif /* not LITE */
! 779:
! 780: if (draw_surface) {
! 781: int lkey = (key != 0 && this_plot->title && this_plot->title[0]);
! 782: term_apply_lp_properties(&(this_plot->lp_properties));
! 783:
! 784: #ifndef LITE
! 785: if (hidden3d) {
! 786: hidden_line_type_above = this_plot->lp_properties.l_type;
! 787: hidden_line_type_below = this_plot->lp_properties.l_type + 1;
! 788: }
! 789: #endif /* not LITE */
! 790:
! 791: if (lkey) {
! 792: key_text(xl, yl, this_plot->title);
! 793: }
! 794: switch (this_plot->plot_style) {
! 795: case BOXES: /* can't do boxes in 3d yet so use impulses */
! 796: case IMPULSES:{
! 797: if (lkey) {
! 798: key_sample_line(xl, yl);
! 799: }
! 800: if (!(hidden3d && draw_surface))
! 801: plot3d_impulses(this_plot);
! 802: break;
! 803: }
! 804: case STEPS: /* HBB: I think these should be here */
! 805: case FSTEPS:
! 806: case HISTEPS:
! 807: case LINES:{
! 808: if (lkey) {
! 809: key_sample_line(xl, yl);
! 810: }
! 811: if (!(hidden3d && draw_surface))
! 812: plot3d_lines(this_plot);
! 813: break;
! 814: }
! 815: case YERRORBARS: /* ignored; treat like points */
! 816: case XERRORBARS: /* ignored; treat like points */
! 817: case XYERRORBARS: /* ignored; treat like points */
! 818: case BOXXYERROR: /* HBB: ignore these as well */
! 819: case BOXERROR:
! 820: case CANDLESTICKS: /* HBB: dito */
! 821: case FINANCEBARS:
! 822: case VECTOR:
! 823: case POINTSTYLE:
! 824: if (lkey && !clip_point(xl + key_point_offset, yl)) {
! 825: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
! 826: }
! 827: if (!(hidden3d && draw_surface))
! 828: plot3d_points(this_plot);
! 829: break;
! 830:
! 831: case LINESPOINTS:
! 832: /* put lines */
! 833: if (lkey)
! 834: key_sample_line(xl, yl);
! 835:
! 836: if (!(hidden3d && draw_surface))
! 837: plot3d_lines(this_plot);
! 838:
! 839: /* put points */
! 840: if (lkey && !clip_point(xl + key_point_offset, yl))
! 841: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
! 842:
! 843: if (!(hidden3d && draw_surface))
! 844: plot3d_points(this_plot);
! 845:
! 846: break;
! 847:
! 848: case DOTS:
! 849: if (lkey) {
! 850: if (key == 1) {
! 851: if (!clip_point(xl + key_point_offset, yl))
! 852: (*t->point) (xl + key_point_offset, yl, -1);
! 853: } else {
! 854: (*t->point) (xl + key_point_offset, yl, -1);
! 855: /* (*t->point)(xl+2*(t->h_char),yl, -1); */
! 856: }
! 857: }
! 858: if (!(hidden3d && draw_surface))
! 859: plot3d_dots(this_plot);
! 860:
! 861: break;
! 862:
! 863:
! 864: } /* switch(plot-style) */
! 865:
! 866: /* move key on a line */
! 867: if (lkey) {
! 868: NEXT_KEY_LINE();
! 869: }
! 870: } /* draw_surface */
! 871:
! 872: #ifndef LITE
! 873: if (hidden3d) {
! 874: hidden_no_update = TRUE;
! 875: hidden_line_type_above = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
! 876: hidden_line_type_below = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
! 877: }
! 878: #endif /* not LITE */
! 879:
! 880: if (draw_contour && this_plot->contours != NULL) {
! 881: struct gnuplot_contours *cntrs = this_plot->contours;
! 882:
! 883: term_apply_lp_properties(&(this_plot->lp_properties));
! 884: (*t->linetype) (this_plot->lp_properties.l_type + (hidden3d ? 2 : 1));
! 885:
! 886: if (key != 0 && this_plot->title && this_plot->title[0]
! 887: && !draw_surface && !label_contours) {
! 888: /* unlabelled contours but no surface : put key entry in now */
! 889: key_text(xl, yl, this_plot->title);
! 890:
! 891: switch (this_plot->plot_style) {
! 892: case IMPULSES:
! 893: case LINES:
! 894: case BOXES: /* HBB: I think these should be here... */
! 895: case STEPS:
! 896: case FSTEPS:
! 897: case HISTEPS:
! 898: key_sample_line(xl, yl);
! 899: break;
! 900: case YERRORBARS: /* ignored; treat like points */
! 901: case XERRORBARS: /* ignored; treat like points */
! 902: case XYERRORBARS: /* ignored; treat like points */
! 903: case BOXERROR: /* HBB: ignore these as well */
! 904: case BOXXYERROR:
! 905: case CANDLESTICKS: /* HBB: dito */
! 906: case FINANCEBARS:
! 907: case VECTOR:
! 908: case POINTSTYLE:
! 909: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
! 910: break;
! 911: case LINESPOINTS:
! 912: key_sample_line(xl, yl);
! 913: break;
! 914: case DOTS:
! 915: key_sample_point(xl, yl, -1);
! 916: break;
! 917: }
! 918: NEXT_KEY_LINE();
! 919: }
! 920: linetypeOffset = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
! 921: while (cntrs) {
! 922: if (label_contours && cntrs->isNewLevel) {
! 923: (*t->linetype) (linetypeOffset++);
! 924: if (key) {
! 925:
! 926: #ifndef LITE
! 927: if (hidden3d)
! 928: hidden_line_type_below = hidden_line_type_above = linetypeOffset - 1;
! 929: #endif /* not LITE */
! 930:
! 931: key_text(xl, yl, cntrs->label);
! 932:
! 933: switch (this_plot->plot_style) {
! 934: case IMPULSES:
! 935: case LINES:
! 936: case LINESPOINTS:
! 937: case BOXES: /* HBB: these should be treated as well... */
! 938: case STEPS:
! 939: case FSTEPS:
! 940: case HISTEPS:
! 941: key_sample_line(xl, yl);
! 942: break;
! 943: case YERRORBARS: /* ignored; treat like points */
! 944: case XERRORBARS: /* ignored; treat like points */
! 945: case XYERRORBARS: /* ignored; treat like points */
! 946: case BOXERROR: /* HBB: treat these likewise */
! 947: case BOXXYERROR:
! 948: case CANDLESTICKS: /* HBB: dito */
! 949: case FINANCEBARS:
! 950: case VECTOR:
! 951: case POINTSTYLE:
! 952: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
! 953: break;
! 954: case DOTS:
! 955: key_sample_point(xl, yl, -1);
! 956: break;
! 957: } /* switch */
! 958:
! 959: NEXT_KEY_LINE();
! 960:
! 961: } /* key */
! 962: } /* label_contours */
! 963: /* now draw the contour */
! 964: switch (this_plot->plot_style) {
! 965: case IMPULSES:
! 966: case BOXES: /* HBB: this should also be treated somehow */
! 967: cntr3d_impulses(cntrs, this_plot);
! 968: break;
! 969: case LINES:
! 970: case STEPS: /* HBB: these should also be handled, I think */
! 971: case FSTEPS:
! 972: case HISTEPS:
! 973: cntr3d_lines(cntrs);
! 974: break;
! 975: case YERRORBARS: /* ignored; treat like points */
! 976: case XERRORBARS: /* ignored; treat like points */
! 977: case XYERRORBARS: /* ignored; treat like points */
! 978: case BOXERROR: /* HBB: ignore these too... */
! 979: case BOXXYERROR:
! 980: case CANDLESTICKS: /* HBB: dito */
! 981: case FINANCEBARS:
! 982: case VECTOR:
! 983: case POINTSTYLE:
! 984: cntr3d_points(cntrs, this_plot);
! 985: break;
! 986: case LINESPOINTS:
! 987: cntr3d_lines(cntrs);
! 988: cntr3d_points(cntrs, this_plot);
! 989: break;
! 990: case DOTS:
! 991: cntr3d_dots(cntrs);
! 992: break;
! 993: } /*switch */
! 994:
! 995: cntrs = cntrs->next;
! 996: } /* loop over contours */
! 997: } /* draw contours */
! 998: } /* loop over surfaces */
! 999:
! 1000: draw_bottom_grid(plots, pcount);
! 1001:
! 1002: term_end_plot();
! 1003:
! 1004: #ifndef LITE
! 1005: if (hidden3d && draw_surface) {
! 1006: term_hidden_line_removal();
! 1007: hidden_active = FALSE;
! 1008: }
! 1009: #endif /* not LITE */
! 1010:
! 1011: }
! 1012:
! 1013: /* plot3d_impulses:
! 1014: * Plot the surfaces in IMPULSES style
! 1015: */
! 1016: static void plot3d_impulses(plot)
! 1017: struct surface_points *plot;
! 1018: {
! 1019: int i; /* point index */
! 1020: unsigned int x, y, x0, y0; /* point in terminal coordinates */
! 1021: struct iso_curve *icrvs = plot->iso_crvs;
! 1022:
! 1023: while (icrvs) {
! 1024: struct coordinate GPHUGE *points = icrvs->points;
! 1025:
! 1026: for (i = 0; i < icrvs->p_count; i++) {
! 1027: switch (points[i].type) {
! 1028: case INRANGE:
! 1029: {
! 1030: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
! 1031:
! 1032: if (inrange(0.0, min3d_z, max3d_z)) {
! 1033: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
! 1034: } else if (inrange(min3d_z, 0.0, points[i].z)) {
! 1035: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
! 1036: } else {
! 1037: map3d_xy(points[i].x, points[i].y, max3d_z, &x0, &y0);
! 1038: }
! 1039:
! 1040: clip_move(x0, y0);
! 1041: clip_vector(x, y);
! 1042:
! 1043: break;
! 1044: }
! 1045: case OUTRANGE:
! 1046: {
! 1047: if (!inrange(points[i].x, x_min3d, x_max3d) ||
! 1048: !inrange(points[i].y, y_min3d, y_max3d))
! 1049: break;
! 1050:
! 1051: if (inrange(0.0, min3d_z, max3d_z)) {
! 1052: /* zero point is INRANGE */
! 1053: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
! 1054:
! 1055: /* must cross z = min3d_z or max3d_z limits */
! 1056: if (inrange(min3d_z, 0.0, points[i].z) &&
! 1057: min3d_z != 0.0 && min3d_z != points[i].z) {
! 1058: map3d_xy(points[i].x, points[i].y, min3d_z, &x, &y);
! 1059: } else {
! 1060: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
! 1061: }
! 1062: } else {
! 1063: /* zero point is also OUTRANGE */
! 1064: if (inrange(min3d_z, 0.0, points[i].z) &&
! 1065: inrange(max3d_z, 0.0, points[i].z)) {
! 1066: /* crosses z = min3d_z or max3d_z limits */
! 1067: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
! 1068: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
! 1069: } else {
! 1070: /* doesn't cross z = min3d_z or max3d_z limits */
! 1071: break;
! 1072: }
! 1073: }
! 1074:
! 1075: clip_move(x0, y0);
! 1076: clip_vector(x, y);
! 1077:
! 1078: break;
! 1079: }
! 1080: default: /* just a safety */
! 1081: case UNDEFINED:{
! 1082: break;
! 1083: }
! 1084: }
! 1085: }
! 1086:
! 1087: icrvs = icrvs->next;
! 1088: }
! 1089: }
! 1090:
! 1091: /* plot3d_lines:
! 1092: * Plot the surfaces in LINES style
! 1093: */
! 1094: /* We want to always draw the lines in the same direction, otherwise when
! 1095: we draw an adjacent box we might get the line drawn a little differently
! 1096: and we get splotches. */
! 1097:
! 1098: static void plot3d_lines(plot)
! 1099: struct surface_points *plot;
! 1100: {
! 1101: int i;
! 1102: unsigned int x, y, x0, y0; /* point in terminal coordinates */
! 1103: double clip_x, clip_y, clip_z;
! 1104: struct iso_curve *icrvs = plot->iso_crvs;
! 1105: struct coordinate GPHUGE *points;
! 1106: enum coord_type prev = UNDEFINED;
! 1107: double lx[2], ly[2], lz[2]; /* two edge points */
! 1108:
! 1109: #ifndef LITE
! 1110: /* These are handled elsewhere. */
! 1111: if (plot->has_grid_topology && hidden3d)
! 1112: return;
! 1113: #endif /* not LITE */
! 1114:
! 1115: while (icrvs) {
! 1116: prev = UNDEFINED; /* type of previous plot */
! 1117:
! 1118: for (i = 0, points = icrvs->points; i < icrvs->p_count; i++) {
! 1119: switch (points[i].type) {
! 1120: case INRANGE:{
! 1121: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
! 1122:
! 1123: if (prev == INRANGE) {
! 1124: clip_vector(x, y);
! 1125: } else {
! 1126: if (prev == OUTRANGE) {
! 1127: /* from outrange to inrange */
! 1128: if (!clip_lines1) {
! 1129: clip_move(x, y);
! 1130: } else {
! 1131: /*
! 1132: * Calculate intersection point and draw
! 1133: * vector from there
! 1134: */
! 1135: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
! 1136:
! 1137: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
! 1138:
! 1139: clip_move(x0, y0);
! 1140: clip_vector(x, y);
! 1141: }
! 1142: } else {
! 1143: clip_move(x, y);
! 1144: }
! 1145: }
! 1146:
! 1147: break;
! 1148: }
! 1149: case OUTRANGE:{
! 1150: if (prev == INRANGE) {
! 1151: /* from inrange to outrange */
! 1152: if (clip_lines1) {
! 1153: /*
! 1154: * Calculate intersection point and draw
! 1155: * vector to it
! 1156: */
! 1157:
! 1158: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
! 1159:
! 1160: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
! 1161:
! 1162: clip_vector(x0, y0);
! 1163: }
! 1164: } else if (prev == OUTRANGE) {
! 1165: /* from outrange to outrange */
! 1166: if (clip_lines2) {
! 1167: /*
! 1168: * Calculate the two 3D intersection points
! 1169: * if present
! 1170: */
! 1171: if (two_edge3d_intersect(points, i, lx, ly, lz)) {
! 1172:
! 1173: map3d_xy(lx[0], ly[0], lz[0], &x, &y);
! 1174:
! 1175: map3d_xy(lx[1], ly[1], lz[1], &x0, &y0);
! 1176:
! 1177: clip_move(x, y);
! 1178: clip_vector(x0, y0);
! 1179: }
! 1180: }
! 1181: }
! 1182: break;
! 1183: }
! 1184: case UNDEFINED:{
! 1185: break;
! 1186: default:
! 1187: graph_error("Unknown point type in plot3d_lines");
! 1188: }
! 1189: }
! 1190:
! 1191: prev = points[i].type;
! 1192: }
! 1193:
! 1194: icrvs = icrvs->next;
! 1195: }
! 1196: }
! 1197:
! 1198: /* plot3d_points:
! 1199: * Plot the surfaces in POINTSTYLE style
! 1200: */
! 1201: static void plot3d_points(plot)
! 1202: struct surface_points *plot;
! 1203: {
! 1204: int i;
! 1205: unsigned int x, y;
! 1206: struct termentry *t = term;
! 1207: struct iso_curve *icrvs = plot->iso_crvs;
! 1208:
! 1209: while (icrvs) {
! 1210: struct coordinate GPHUGE *points = icrvs->points;
! 1211:
! 1212: for (i = 0; i < icrvs->p_count; i++) {
! 1213: if (points[i].type == INRANGE) {
! 1214: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
! 1215:
! 1216: if (!clip_point(x, y))
! 1217: (*t->point) (x, y, plot->lp_properties.p_type);
! 1218: }
! 1219: }
! 1220:
! 1221: icrvs = icrvs->next;
! 1222: }
! 1223: }
! 1224:
! 1225: /* plot3d_dots:
! 1226: * Plot the surfaces in DOTS style
! 1227: */
! 1228: static void plot3d_dots(plot)
! 1229: struct surface_points *plot;
! 1230: {
! 1231: int i;
! 1232: struct termentry *t = term;
! 1233: struct iso_curve *icrvs = plot->iso_crvs;
! 1234:
! 1235: while (icrvs) {
! 1236: struct coordinate GPHUGE *points = icrvs->points;
! 1237:
! 1238: for (i = 0; i < icrvs->p_count; i++) {
! 1239: if (points[i].type == INRANGE) {
! 1240: unsigned int x, y;
! 1241: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
! 1242:
! 1243: if (!clip_point(x, y))
! 1244: (*t->point) (x, y, -1);
! 1245: }
! 1246: }
! 1247:
! 1248: icrvs = icrvs->next;
! 1249: }
! 1250: }
! 1251:
! 1252: /* cntr3d_impulses:
! 1253: * Plot a surface contour in IMPULSES style
! 1254: */
! 1255: static void cntr3d_impulses(cntr, plot)
! 1256: struct gnuplot_contours *cntr;
! 1257: struct surface_points *plot;
! 1258: {
! 1259: int i; /* point index */
! 1260: unsigned int x, y, x0, y0; /* point in terminal coordinates */
! 1261:
! 1262: if (draw_contour & CONTOUR_SRF) {
! 1263: for (i = 0; i < cntr->num_pts; i++) {
! 1264: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
! 1265: &x, &y);
! 1266: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
! 1267: &x0, &y0);
! 1268:
! 1269: clip_move(x0, y0);
! 1270: clip_vector(x, y);
! 1271: }
! 1272: } else {
! 1273: /* Must be on base grid, so do points. */
! 1274: cntr3d_points(cntr, plot);
! 1275: }
! 1276: }
! 1277:
! 1278: /* cntr3d_lines:
! 1279: * Plot a surface contour in LINES style
! 1280: */
! 1281: static void cntr3d_lines(cntr)
! 1282: struct gnuplot_contours *cntr;
! 1283: {
! 1284: int i; /* point index */
! 1285: unsigned int x, y; /* point in terminal coordinates */
! 1286:
! 1287: if (draw_contour & CONTOUR_SRF) {
! 1288: for (i = 0; i < cntr->num_pts; i++) {
! 1289: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
! 1290: &x, &y);
! 1291:
! 1292: if (i > 0) {
! 1293: clip_vector(x, y);
! 1294: if (i == 1)
! 1295: suppressMove = TRUE;
! 1296: } else {
! 1297: clip_move(x, y);
! 1298: }
! 1299: }
! 1300: }
! 1301: /* beginning a new contour level, so moveto() required */
! 1302: suppressMove = FALSE;
! 1303:
! 1304: if (draw_contour & CONTOUR_BASE) {
! 1305: for (i = 0; i < cntr->num_pts; i++) {
! 1306: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
! 1307: &x, &y);
! 1308:
! 1309: if (i > 0) {
! 1310: clip_vector(x, y);
! 1311: if (i == 1)
! 1312: suppressMove = TRUE;
! 1313: } else {
! 1314: clip_move(x, y);
! 1315: }
! 1316: }
! 1317: }
! 1318: /* beginning a new contour level, so moveto() required */
! 1319: suppressMove = FALSE;
! 1320: }
! 1321:
! 1322: /* cntr3d_points:
! 1323: * Plot a surface contour in POINTSTYLE style
! 1324: */
! 1325: static void cntr3d_points(cntr, plot)
! 1326: struct gnuplot_contours *cntr;
! 1327: struct surface_points *plot;
! 1328: {
! 1329: int i;
! 1330: unsigned int x, y;
! 1331: struct termentry *t = term;
! 1332:
! 1333: if (draw_contour & CONTOUR_SRF) {
! 1334: for (i = 0; i < cntr->num_pts; i++) {
! 1335: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
! 1336:
! 1337: if (!clip_point(x, y))
! 1338: (*t->point) (x, y, plot->lp_properties.p_type);
! 1339: }
! 1340: }
! 1341: if (draw_contour & CONTOUR_BASE) {
! 1342: for (i = 0; i < cntr->num_pts; i++) {
! 1343: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
! 1344: &x, &y);
! 1345:
! 1346: if (!clip_point(x, y))
! 1347: (*t->point) (x, y, plot->lp_properties.p_type);
! 1348: }
! 1349: }
! 1350: }
! 1351:
! 1352: /* cntr3d_dots:
! 1353: * Plot a surface contour in DOTS style
! 1354: */
! 1355: static void cntr3d_dots(cntr)
! 1356: struct gnuplot_contours *cntr;
! 1357: {
! 1358: int i;
! 1359: unsigned int x, y;
! 1360: struct termentry *t = term;
! 1361:
! 1362: if (draw_contour & CONTOUR_SRF) {
! 1363: for (i = 0; i < cntr->num_pts; i++) {
! 1364: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
! 1365:
! 1366: if (!clip_point(x, y))
! 1367: (*t->point) (x, y, -1);
! 1368: }
! 1369: }
! 1370: if (draw_contour & CONTOUR_BASE) {
! 1371: for (i = 0; i < cntr->num_pts; i++) {
! 1372: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
! 1373: &x, &y);
! 1374:
! 1375: if (!clip_point(x, y))
! 1376: (*t->point) (x, y, -1);
! 1377: }
! 1378: }
! 1379: }
! 1380:
! 1381:
! 1382:
! 1383: /* map xmin | xmax to 0 | 1 and same for y
! 1384: * 0.1 avoids any rounding errors
! 1385: */
! 1386: #define MAP_HEIGHT_X(x) ( (int) (((x)-x_min3d)/(x_max3d-x_min3d)+0.1) )
! 1387: #define MAP_HEIGHT_Y(y) ( (int) (((y)-y_min3d)/(y_max3d-y_min3d)+0.1) )
! 1388:
! 1389: /* if point is at corner, update height[][] and depth[][]
! 1390: * we are still assuming that extremes of surfaces are at corners,
! 1391: * but we are not assuming order of corners
! 1392: */
! 1393: static void check_corner_height(p, height, depth)
! 1394: struct coordinate GPHUGE *p;
! 1395: double height[2][2];
! 1396: double depth[2][2];
! 1397: {
! 1398: if (p->type != INRANGE)
! 1399: return;
! 1400: if ((fabs(p->x - x_min3d) < zero || fabs(p->x - x_max3d) < zero) &&
! 1401: (fabs(p->y - y_min3d) < zero || fabs(p->y - y_max3d) < zero)) {
! 1402: unsigned int x = MAP_HEIGHT_X(p->x);
! 1403: unsigned int y = MAP_HEIGHT_Y(p->y);
! 1404: if (height[x][y] < p->z)
! 1405: height[x][y] = p->z;
! 1406: if (depth[x][y] > p->z)
! 1407: depth[x][y] = p->z;
! 1408: }
! 1409: }
! 1410:
! 1411:
! 1412: /* Draw the bottom grid that hold the tic marks for 3d surface. */
! 1413: static void draw_bottom_grid(plot, plot_num)
! 1414: struct surface_points *plot;
! 1415: int plot_num;
! 1416: {
! 1417: unsigned int x, y; /* point in terminal coordinates */
! 1418: struct termentry *t = term;
! 1419: char ss[MAX_LINE_LEN+1];
! 1420:
! 1421: /* work out where the axes and tics are drawn */
! 1422:
! 1423: {
! 1424: int quadrant = surface_rot_z / 90;
! 1425: if ((quadrant + 1) & 2) {
! 1426: zaxis_x = x_max3d;
! 1427: xaxis_y = y_max3d;
! 1428: } else {
! 1429: zaxis_x = x_min3d;
! 1430: xaxis_y = y_min3d;
! 1431: }
! 1432:
! 1433: if (quadrant & 2) {
! 1434: zaxis_y = y_max3d;
! 1435: yaxis_x = x_min3d;
! 1436: } else {
! 1437: zaxis_y = y_min3d;
! 1438: yaxis_x = x_max3d;
! 1439: }
! 1440:
! 1441: if (surface_rot_x > 90) {
! 1442: /* labels on the back axes */
! 1443: back_x = yaxis_x = x_min3d + x_max3d - yaxis_x;
! 1444: back_y = xaxis_y = y_min3d + y_max3d - xaxis_y;
! 1445: } else {
! 1446: back_x = x_min3d + x_max3d - yaxis_x;
! 1447: back_y = y_min3d + y_max3d - xaxis_y;
! 1448: }
! 1449: }
! 1450:
! 1451: if (draw_border) {
! 1452: unsigned int bl_x, bl_y; /* bottom left */
! 1453: unsigned int bb_x, bb_y; /* bottom back */
! 1454: unsigned int br_x, br_y; /* bottom right */
! 1455: unsigned int bf_x, bf_y; /* bottom front */
! 1456:
! 1457: #ifndef LITE
! 1458: int save_update = hidden_no_update;
! 1459: hidden_no_update = TRUE;
! 1460: #endif /* LITE */
! 1461:
! 1462: /* Here is the one and only call to this function. */
! 1463: setlinestyle(border_lp);
! 1464:
! 1465: map3d_xy(zaxis_x, zaxis_y, base_z, &bl_x, &bl_y);
! 1466: map3d_xy(back_x, back_y, base_z, &bb_x, &bb_y);
! 1467: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, base_z, &br_x, &br_y);
! 1468: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, base_z, &bf_x, &bf_y);
! 1469:
! 1470: /* border around base */
! 1471: {
! 1472: int save = hidden_active;
! 1473: hidden_active = FALSE; /* this is in front */
! 1474: if (draw_border & 4)
! 1475: draw_clip_line(br_x, br_y, bf_x, bf_y);
! 1476: if (draw_border & 1)
! 1477: draw_clip_line(bl_x, bl_y, bf_x, bf_y);
! 1478: hidden_active = save;
! 1479: }
! 1480: if (draw_border & 2)
! 1481: draw_clip_line(bl_x, bl_y, bb_x, bb_y);
! 1482: if (draw_border & 8)
! 1483: draw_clip_line(br_x, br_y, bb_x, bb_y);
! 1484:
! 1485: if (draw_surface || (draw_contour & CONTOUR_SRF)) {
! 1486: int save = hidden_active;
! 1487: /* map the 8 corners to screen */
! 1488: unsigned int fl_x, fl_y; /* floor left */
! 1489: unsigned int fb_x, fb_y; /* floor back */
! 1490: unsigned int fr_x, fr_y; /* floor right */
! 1491: unsigned int ff_x, ff_y; /* floor front */
! 1492:
! 1493: unsigned int tl_x, tl_y; /* top left */
! 1494: unsigned int tb_x, tb_y; /* top back */
! 1495: unsigned int tr_x, tr_y; /* top right */
! 1496: unsigned int tf_x, tf_y; /* top front */
! 1497:
! 1498: map3d_xy(zaxis_x, zaxis_y, floor_z, &fl_x, &fl_y);
! 1499: map3d_xy(back_x, back_y, floor_z, &fb_x, &fb_y);
! 1500: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, floor_z, &fr_x, &fr_y);
! 1501: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, floor_z, &ff_x, &ff_y);
! 1502:
! 1503: map3d_xy(zaxis_x, zaxis_y, ceiling_z, &tl_x, &tl_y);
! 1504: map3d_xy(back_x, back_y, ceiling_z, &tb_x, &tb_y);
! 1505: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, ceiling_z, &tr_x, &tr_y);
! 1506: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, ceiling_z, &tf_x, &tf_y);
! 1507:
! 1508: /* vertical lines, to surface or to very top */
! 1509: if ((draw_border & 0xf0) == 0xf0) {
! 1510: /* all four verticals drawn - save some time */
! 1511: draw_clip_line(fl_x, fl_y, tl_x, tl_y);
! 1512: draw_clip_line(fb_x, fb_y, tb_x, tb_y);
! 1513: draw_clip_line(fr_x, fr_y, tr_x, tr_y);
! 1514: hidden_active = FALSE; /* this is in front */
! 1515: draw_clip_line(ff_x, ff_y, tf_x, tf_y);
! 1516: hidden_active = save;
! 1517: } else {
! 1518: /* search surfaces for heights at corners */
! 1519: double height[2][2];
! 1520: double depth[2][2];
! 1521: unsigned int zaxis_i = MAP_HEIGHT_X(zaxis_x);
! 1522: unsigned int zaxis_j = MAP_HEIGHT_Y(zaxis_y);
! 1523: unsigned int back_i = MAP_HEIGHT_X(back_x);
! 1524: /* HBB: why isn't back_j unsigned ??? */
! 1525: int back_j = MAP_HEIGHT_Y(back_y);
! 1526:
! 1527: height[0][0] = height[0][1] = height[1][0] = height[1][1] = base_z;
! 1528: depth[0][0] = depth[0][1] = depth[1][0] = depth[1][1] = base_z;
! 1529:
! 1530: for (; --plot_num >= 0; plot = plot->next_sp) {
! 1531: struct iso_curve *curve = plot->iso_crvs;
! 1532: int count = curve->p_count;
! 1533: int iso;
! 1534: if (plot->plot_type == DATA3D) {
! 1535: if (!plot->has_grid_topology)
! 1536: continue;
! 1537: iso = plot->num_iso_read;
! 1538: } else
! 1539: iso = iso_samples_2;
! 1540:
! 1541: check_corner_height(curve->points, height, depth);
! 1542: check_corner_height(curve->points + count - 1, height, depth);
! 1543: while (--iso)
! 1544: curve = curve->next;
! 1545: check_corner_height(curve->points, height, depth);
! 1546: check_corner_height(curve->points + count - 1, height, depth);
! 1547: }
! 1548:
! 1549: #define VERTICAL(mask,x,y,i,j,bx,by,tx,ty) \
! 1550: if (draw_border&mask) \
! 1551: draw_clip_line(bx,by,tx,ty);\
! 1552: else if (height[i][j] != depth[i][j]) \
! 1553: { unsigned int a0,b0, a1, b1; \
! 1554: map3d_xy(x,y,depth[i][j],&a0,&b0); \
! 1555: map3d_xy(x,y,height[i][j],&a1,&b1); \
! 1556: draw_clip_line(a0,b0,a1,b1); \
! 1557: }
! 1558:
! 1559: VERTICAL(16,zaxis_x,zaxis_y,zaxis_i,zaxis_j,fl_x,fl_y,tl_x,tl_y);
! 1560: VERTICAL(32,back_x,back_y,back_i,back_j,fb_x,fb_y,tb_x,tb_y);
! 1561: VERTICAL(64,x_min3d+x_max3d-zaxis_x,y_min3d+y_max3d-zaxis_y,1-zaxis_i,1-zaxis_j,fr_x,fr_y,tr_x,tr_y);
! 1562: hidden_active = FALSE;
! 1563: VERTICAL(128,x_min3d+x_max3d-back_x,y_min3d+y_max3d-back_y,1-back_i,1-back_j,ff_x,ff_y,tf_x,tf_y);
! 1564: hidden_active = save;
! 1565: }
! 1566:
! 1567: /* now border lines on top */
! 1568: if (draw_border & 256)
! 1569: draw_clip_line(tl_x, tl_y, tb_x, tb_y);
! 1570: if (draw_border & 512)
! 1571: draw_clip_line(tr_x, tr_y, tb_x, tb_y);
! 1572: /* these lines are in front of surface (?) */
! 1573: hidden_active = FALSE;
! 1574: if (draw_border & 1024)
! 1575: draw_clip_line(tl_x, tl_y, tf_x, tf_y);
! 1576: if (draw_border & 2048)
! 1577: draw_clip_line(tr_x, tr_y, tf_x, tf_y);
! 1578: hidden_active = save;
! 1579: }
! 1580:
! 1581: #ifndef LITE
! 1582: hidden_no_update = save_update;
! 1583: #endif /* LITE */
! 1584:
! 1585: }
! 1586: if (xtics || *xlabel.text) {
! 1587: unsigned int x0, y0, x1, y1;
! 1588: double mid_x = (x_max3d + x_min3d) / 2;
! 1589: double len;
! 1590: map3d_xy(mid_x, xaxis_y, base_z, &x0, &y0);
! 1591: map3d_xy(mid_x, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
! 1592: { /* take care over unsigned quantities */
! 1593: int dx = x1 - x0;
! 1594: int dy = y1 - y0;
! 1595: /* HBB 980309: 16bit strikes back: */
! 1596: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
! 1597: if (len != 0) {
! 1598: tic_unitx = dx / len;
! 1599: tic_unity = dy / len;
! 1600: } else {
! 1601: tic_unitx = tic_unity = 0;
! 1602: }
! 1603: }
! 1604:
! 1605: if (xtics) {
! 1606: gen_tics(FIRST_X_AXIS, &xticdef,
! 1607: work_grid.l_type & (GRID_X | GRID_MX),
! 1608: mxtics, mxtfreq, xtick_callback);
! 1609: }
! 1610: if (*xlabel.text) {
! 1611: /* label at xaxis_y + 1/4 of (xaxis_y-other_y) */
! 1612: double step = (2 * xaxis_y - y_max3d - y_min3d) / 4;
! 1613: map3d_xy(mid_x, xaxis_y + step, base_z, &x1, &y1);
! 1614: x1 += xlabel.xoffset * t->h_char;
! 1615: y1 += xlabel.yoffset * t->v_char;
! 1616: if (!tic_in) {
! 1617: x1 -= tic_unitx * ticscale * (t->h_tic);
! 1618: y1 -= tic_unity * ticscale * (t->v_tic);
! 1619: }
! 1620: /* write_multiline mods it */
! 1621: safe_strncpy(ss, xlabel.text, sizeof(ss));
! 1622: write_multiline(x1, y1, ss, CENTRE, JUST_TOP, 0, xlabel.font);
! 1623: }
! 1624: }
! 1625: if (ytics || *ylabel.text) {
! 1626: unsigned int x0, y0, x1, y1;
! 1627: double mid_y = (y_max3d + y_min3d) / 2;
! 1628: double len;
! 1629: map3d_xy(yaxis_x, mid_y, base_z, &x0, &y0);
! 1630: map3d_xy(x_min3d + x_max3d - yaxis_x, mid_y, base_z, &x1, &y1);
! 1631: { /* take care over unsigned quantities */
! 1632: int dx = x1 - x0;
! 1633: int dy = y1 - y0;
! 1634: /* HBB 980309: 16 Bits strike again: */
! 1635: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
! 1636: if (len != 0) {
! 1637: tic_unitx = dx / len;
! 1638: tic_unity = dy / len;
! 1639: } else {
! 1640: tic_unitx = tic_unity = 0;
! 1641: }
! 1642: }
! 1643: if (ytics) {
! 1644: gen_tics(FIRST_Y_AXIS, &yticdef,
! 1645: work_grid.l_type & (GRID_Y | GRID_MY),
! 1646: mytics, mytfreq, ytick_callback);
! 1647: }
! 1648: if (*ylabel.text) {
! 1649: double step = (x_max3d + x_min3d - 2 * yaxis_x) / 4;
! 1650: map3d_xy(yaxis_x - step, mid_y, base_z, &x1, &y1);
! 1651: x1 += ylabel.xoffset * t->h_char;
! 1652: y1 += ylabel.yoffset * t->v_char;
! 1653: if (!tic_in) {
! 1654: x1 -= tic_unitx * ticscale * (t->h_tic);
! 1655: y1 -= tic_unity * ticscale * (t->v_tic);
! 1656: }
! 1657: /* write_multiline mods it */
! 1658: safe_strncpy(ss, ylabel.text, sizeof(ss));
! 1659: write_multiline(x1, y1, ss, CENTRE, JUST_TOP, 0, ylabel.font);
! 1660: }
! 1661: }
! 1662: /* do z tics */
! 1663:
! 1664: if (ztics && (draw_surface || (draw_contour & CONTOUR_SRF))) {
! 1665: gen_tics(FIRST_Z_AXIS, &zticdef, work_grid.l_type & (GRID_Z | GRID_MZ),
! 1666: mztics, mztfreq, ztick_callback);
! 1667: }
! 1668: if ((xzeroaxis.l_type >= -2) && !is_log_y && inrange(0, y_min3d, y_max3d)) {
! 1669: unsigned int x, y, x1, y1;
! 1670: term_apply_lp_properties(&xzeroaxis);
! 1671: map3d_xy(0.0, y_min3d, base_z, &x, &y); /* line through x=0 */
! 1672: map3d_xy(0.0, y_max3d, base_z, &x1, &y1);
! 1673: draw_clip_line(x, y, x1, y1);
! 1674: }
! 1675: if ((yzeroaxis.l_type >= -2) && !is_log_x && inrange(0, x_min3d, x_max3d)) {
! 1676: unsigned int x, y, x1, y1;
! 1677: term_apply_lp_properties(&yzeroaxis);
! 1678: map3d_xy(x_min3d, 0.0, base_z, &x, &y); /* line through y=0 */
! 1679: map3d_xy(x_max3d, 0.0, base_z, &x1, &y1);
! 1680: draw_clip_line(x, y, x1, y1);
! 1681: }
! 1682: /* PLACE ZLABEL - along the middle grid Z axis - eh ? */
! 1683: if (*zlabel.text && (draw_surface || (draw_contour & CONTOUR_SRF))) {
! 1684: map3d_xy(zaxis_x, zaxis_y, z_max3d + (z_max3d - base_z) / 4, &x, &y);
! 1685:
! 1686: x += zlabel.xoffset * t->h_char;
! 1687: y += zlabel.yoffset * t->v_char;
! 1688:
! 1689: safe_strncpy(ss, zlabel.text, sizeof(ss));
! 1690: write_multiline(x, y, ss, CENTRE, CENTRE, 0, zlabel.font);
! 1691:
! 1692: }
! 1693: }
! 1694:
! 1695:
! 1696: static void xtick_callback(axis, place, text, grid)
! 1697: int axis;
! 1698: double place;
! 1699: char *text;
! 1700: struct lp_style_type grid; /* linetype or -2 for none */
! 1701: {
! 1702: unsigned int x, y, x1, y1;
! 1703: double scale = (text ? ticscale : miniticscale);
! 1704: int dirn = tic_in ? 1 : -1;
! 1705: register struct termentry *t = term;
! 1706:
! 1707: map3d_xy(place, xaxis_y, base_z, &x, &y);
! 1708: if (grid.l_type > -2) {
! 1709: term_apply_lp_properties(&grid);
! 1710: /* to save mapping twice, map non-axis y */
! 1711: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
! 1712: draw_clip_line(x, y, x1, y1);
! 1713: term_apply_lp_properties(&border_lp);
! 1714: }
! 1715: if (xtics & TICS_ON_AXIS) {
! 1716: map3d_xy(place, (y_min3d + y_max3d) / 2, base_z, &x, &y);
! 1717: }
! 1718: x1 = x + tic_unitx * scale * (t->h_tic) * dirn;
! 1719: y1 = y + tic_unity * scale * (t->v_tic) * dirn;
! 1720: draw_clip_line(x, y, x1, y1);
! 1721: if (text) {
! 1722: int just;
! 1723: if (tic_unitx < -0.9)
! 1724: just = LEFT;
! 1725: else if (tic_unitx < 0.9)
! 1726: just = CENTRE;
! 1727: else
! 1728: just = RIGHT;
! 1729: #if 1
! 1730: /* HBB 970729: let's see if the 'tic labels collide with axes' problem
! 1731: * may be fixed this way: */
! 1732: x1 = x - tic_unitx * (t->h_char) * 1;
! 1733: y1 = y - tic_unity * (t->v_char) * 1;
! 1734: #else
! 1735: x1 = x - tic_unitx * (t->h_tic) * 2;
! 1736: y1 = y - tic_unity * (t->v_tic) * 2;
! 1737: #endif
! 1738: if (!tic_in) {
! 1739: x1 -= tic_unitx * (t->h_tic) * ticscale;
! 1740: y1 -= tic_unity * (t->v_tic) * ticscale;
! 1741: }
! 1742: clip_put_text_just(x1, y1, text, just);
! 1743: }
! 1744: if (xtics & TICS_MIRROR) {
! 1745: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x, &y);
! 1746: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
! 1747: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
! 1748: draw_clip_line(x, y, x1, y1);
! 1749: }
! 1750: }
! 1751:
! 1752: static void ytick_callback(axis, place, text, grid)
! 1753: int axis;
! 1754: double place;
! 1755: char *text;
! 1756: struct lp_style_type grid;
! 1757: {
! 1758: unsigned int x, y, x1, y1;
! 1759: double scale = (text ? ticscale : miniticscale);
! 1760: int dirn = tic_in ? 1 : -1;
! 1761: register struct termentry *t = term;
! 1762:
! 1763: map3d_xy(yaxis_x, place, base_z, &x, &y);
! 1764: if (grid.l_type > -2) {
! 1765: term_apply_lp_properties(&grid);
! 1766: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x1, &y1);
! 1767: draw_clip_line(x, y, x1, y1);
! 1768: term_apply_lp_properties(&border_lp);
! 1769: }
! 1770: if (ytics & TICS_ON_AXIS) {
! 1771: map3d_xy((x_min3d + x_max3d) / 2, place, base_z, &x, &y);
! 1772: }
! 1773: x1 = x + tic_unitx * scale * dirn * (t->h_tic);
! 1774: y1 = y + tic_unity * scale * dirn * (t->v_tic);
! 1775: draw_clip_line(x, y, x1, y1);
! 1776: if (text) {
! 1777: int just;
! 1778: if (tic_unitx < -0.9)
! 1779: just = LEFT;
! 1780: else if (tic_unitx < 0.9)
! 1781: just = CENTRE;
! 1782: else
! 1783: just = RIGHT;
! 1784: #if 1
! 1785: /* HBB 970729: same as above in xtics_callback */
! 1786: x1 = x - tic_unitx * (t->h_char) * 1;
! 1787: y1 = y - tic_unity * (t->v_char) * 1;
! 1788: #else
! 1789: x1 = x - tic_unitx * (t->h_tic) * 2;
! 1790: y1 = y - tic_unity * (t->v_tic) * 2;
! 1791: #endif
! 1792: if (!tic_in) {
! 1793: x1 -= tic_unitx * (t->h_tic) * ticscale;
! 1794: y1 -= tic_unity * (t->v_tic) * ticscale;
! 1795: }
! 1796: clip_put_text_just(x1, y1, text, just);
! 1797: }
! 1798: if (ytics & TICS_MIRROR) {
! 1799: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x, &y);
! 1800: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
! 1801: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
! 1802: draw_clip_line(x, y, x1, y1);
! 1803: }
! 1804: }
! 1805:
! 1806: static void ztick_callback(axis, place, text, grid)
! 1807: int axis;
! 1808: double place;
! 1809: char *text;
! 1810: struct lp_style_type grid;
! 1811: {
! 1812: /* HBB: inserted some ()'s to shut up gcc -Wall, here and below */
! 1813: int len = (text ? ticscale : miniticscale) * (tic_in ? 1 : -1) * (term->h_tic);
! 1814: unsigned int x, y;
! 1815:
! 1816: if (grid.l_type > -2) {
! 1817: unsigned int x1, y1, x2, y2, x3, y3;
! 1818: double other_x = x_min3d + x_max3d - zaxis_x;
! 1819: double other_y = y_min3d + y_max3d - zaxis_y;
! 1820: term_apply_lp_properties(&grid);
! 1821: map3d_xy(zaxis_x, zaxis_y, place, &x1, &y1);
! 1822: map3d_xy(back_x, back_y, place, &x2, &y2);
! 1823: map3d_xy(other_x, other_y, place, &x3, &y3);
! 1824: draw_clip_line(x1, y1, x2, y2);
! 1825: draw_clip_line(x2, y2, x3, y3);
! 1826: term_apply_lp_properties(&border_lp);
! 1827: }
! 1828: map3d_xy(zaxis_x, zaxis_y, place, &x, &y);
! 1829: draw_clip_line(x, y, x + len, y);
! 1830: if (text) {
! 1831: int x1 = x - (term->h_tic) * 2;
! 1832: if (!tic_in)
! 1833: x1 -= (term->h_tic) * ticscale;
! 1834: clip_put_text_just(x1, y, text, RIGHT);
! 1835: }
! 1836: if (ztics & TICS_MIRROR) {
! 1837: double other_x = x_min3d + x_max3d - zaxis_x;
! 1838: double other_y = y_min3d + y_max3d - zaxis_y;
! 1839: map3d_xy(other_x, other_y, place, &x, &y);
! 1840: draw_clip_line(x, y, x - len, y);
! 1841: }
! 1842: }
! 1843:
! 1844:
! 1845: static void map_position(pos, x, y, what)
! 1846: struct position *pos;
! 1847: unsigned int *x, *y;
! 1848: char *what;
! 1849: {
! 1850: double xpos = pos->x;
! 1851: double ypos = pos->y;
! 1852: double zpos = pos->z;
! 1853: int screens = 0; /* need either 0 or 3 screen co-ordinates */
! 1854:
! 1855: switch (pos->scalex) {
! 1856: case first_axes:
! 1857: case second_axes:
! 1858: xpos = LogScale(xpos, is_log_x, log_base_log_x, what, "x");
! 1859: break;
! 1860: case graph:
! 1861: xpos = min_array[FIRST_X_AXIS] +
! 1862: xpos * (max_array[FIRST_X_AXIS] - min_array[FIRST_X_AXIS]);
! 1863: break;
! 1864: case screen:
! 1865: ++screens;
! 1866: }
! 1867:
! 1868: switch (pos->scaley) {
! 1869: case first_axes:
! 1870: case second_axes:
! 1871: ypos = LogScale(ypos, is_log_y, log_base_log_y, what, "y");
! 1872: break;
! 1873: case graph:
! 1874: ypos = min_array[FIRST_Y_AXIS] +
! 1875: ypos * (max_array[FIRST_Y_AXIS] - min_array[FIRST_Y_AXIS]);
! 1876: break;
! 1877: case screen:
! 1878: ++screens;
! 1879: }
! 1880:
! 1881: switch (pos->scalez) {
! 1882: case first_axes:
! 1883: case second_axes:
! 1884: zpos = LogScale(zpos, is_log_z, log_base_log_z, what, "z");
! 1885: break;
! 1886: case graph:
! 1887: zpos = min_array[FIRST_Z_AXIS] +
! 1888: zpos * (max_array[FIRST_Z_AXIS] - min_array[FIRST_Z_AXIS]);
! 1889: break;
! 1890: case screen:
! 1891: ++screens;
! 1892: }
! 1893:
! 1894: if (screens == 0) {
! 1895: map3d_xy(xpos, ypos, zpos, x, y);
! 1896: return;
! 1897: }
! 1898: if (screens != 3) {
! 1899: graph_error("Cannot mix screen co-ordinates with other types");
! 1900: } {
! 1901: register struct termentry *t = term;
! 1902: *x = pos->x * (t->xmax) + 0.5;
! 1903: *y = pos->y * (t->ymax) + 0.5;
! 1904: }
! 1905:
! 1906: return;
! 1907: }
! 1908:
! 1909:
! 1910: /*
! 1911: * these code blocks were moved to functions, to make the code simpler
! 1912: */
! 1913:
! 1914: static void key_text(xl, yl, text)
! 1915: int xl, yl;
! 1916: char *text;
! 1917: {
! 1918: if (key_just == JLEFT && key == -1) {
! 1919: (*term->justify_text) (LEFT);
! 1920: (*term->put_text) (xl + key_text_left, yl, text);
! 1921: } else {
! 1922: if ((*term->justify_text) (RIGHT)) {
! 1923: if (key == 1)
! 1924: clip_put_text(xl + key_text_right, yl, text);
! 1925: else
! 1926: (*term->put_text) (xl + key_text_right, yl, text);
! 1927: } else {
! 1928: int x = xl + key_text_right - (term->h_char) * strlen(text);
! 1929: if (key == 1) {
! 1930: if (i_inrange(x, xleft, xright))
! 1931: clip_put_text(x, yl, text);
! 1932: } else {
! 1933: (*term->put_text) (x, yl, text);
! 1934: }
! 1935: }
! 1936: }
! 1937: }
! 1938:
! 1939: static void key_sample_line(xl, yl)
! 1940: int xl, yl;
! 1941: {
! 1942: if (key == -1) {
! 1943: (*term->move) (xl + key_sample_left, yl);
! 1944: (*term->vector) (xl + key_sample_right, yl);
! 1945: } else {
! 1946: /* HBB 981118: avoid crash if hidden3d sees a manually placed key:
! 1947: * simply turn off hidden-lining while we're drawing the key line: */
! 1948: int save_hidden_active = hidden_active;
! 1949: hidden_active = FALSE;
! 1950:
! 1951: clip_move(xl + key_sample_left, yl);
! 1952: clip_vector(xl + key_sample_right, yl);
! 1953: hidden_active = save_hidden_active;
! 1954: }
! 1955: }
! 1956:
! 1957: static void key_sample_point(xl, yl, pointtype)
! 1958: int xl, yl;
! 1959: int pointtype;
! 1960: {
! 1961: if (!clip_point(xl + key_point_offset, yl)) {
! 1962: (*term->point) (xl + key_point_offset, yl, pointtype);
! 1963: } else {
! 1964: (*term->point) (xl + key_point_offset, yl, pointtype);
! 1965: }
! 1966: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>