Annotation of OpenXM_contrib/gnuplot/graph3d.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: graph3d.c,v 1.13.2.9 2002/01/31 21:24:11 lhecking Exp $";
1.1 maekawa 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));
1.1.1.3 ! ohara 98: /* HBB 20010118: these should be static, but can't --- HP-UX assembler bug */
! 99: void xtick_callback __PROTO((int axis, double place, char *text,
! 100: struct lp_style_type grid));
! 101: void ytick_callback __PROTO((int axis, double place, char *text,
! 102: struct lp_style_type grid));
! 103: void ztick_callback __PROTO((int axis, double place, char *text,
! 104: struct lp_style_type grid));
1.1 maekawa 105: static void setlinestyle __PROTO((struct lp_style_type style));
106:
107: static void boundary3d __PROTO((int scaling, struct surface_points * plots,
108: int count));
109: #if 0 /* not used */
110: static double dbl_raise __PROTO((double x, int y));
111: #endif
112: static void map_position __PROTO((struct position * pos, unsigned int *x,
113: unsigned int *y, char *what));
114:
115: /* put entries in the key */
116: static void key_sample_line __PROTO((int xl, int yl));
117: static void key_sample_point __PROTO((int xl, int yl, int pointtype));
118: static void key_text __PROTO((int xl, int yl, char *text));
119:
120:
121: #if defined(sun386) || defined(AMIGA_SC_6_1)
122: static double CheckLog __PROTO((TBOOLEAN is_log, double base_log, double x));
123: #endif
124:
125: /*
126: * The Amiga SAS/C 6.2 compiler moans about macro envocations causing
127: * multiple calls to functions. I converted these macros to inline
128: * functions coping with the problem without loosing speed.
129: * (MGR, 1993)
130: */
131: #ifdef AMIGA_SC_6_1
132: GP_INLINE static TBOOLEAN i_inrange(int z, int min, int max)
133: {
134: return ((min < max) ? ((z >= min) && (z <= max)) : ((z >= max) && (z <= min)));
135: }
136:
137: GP_INLINE static double f_max(double a, double b)
138: {
139: return (max(a, b));
140: }
141:
142: GP_INLINE static double f_min(double a, double b)
143: {
144: return (min(a, b));
145: }
146:
147: #else
148: # define f_max(a,b) GPMAX((a),(b))
149: # define f_min(a,b) GPMIN((a),(b))
150: # define i_inrange(z,a,b) inrange((z),(a),(b))
151: #endif
152:
153: #define apx_eq(x,y) (fabs(x-y) < 0.001)
154: #define ABS(x) ((x) >= 0 ? (x) : -(x))
155: #define SQR(x) ((x) * (x))
156:
157: /* Define the boundary of the plot
158: * These are computed at each call to do_plot, and are constant over
159: * the period of one do_plot. They actually only change when the term
160: * type changes and when the 'set size' factors change.
161: */
162:
163: /* in order to allow graphic.c to use clip_draw_line, we must
164: * share xleft, xright, ybot, ytop with graphics.c
165: */
166: extern int xleft, xright, ybot, ytop;
167:
168: int xmiddle, ymiddle, xscaler, yscaler;
169: static int ptitl_cnt;
170: static int max_ptitl_len;
171: static int titlelin;
172: static int key_sample_width, key_rows, key_cols, key_col_wth, yl_ref;
173: static int ktitle_lines = 0;
174:
175:
176: /* Boundary and scale factors, in user coordinates */
177: /* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
178: * file and are not the same as variables of the same names in other files
179: */
180: /*static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d; */
181: /* sizes are now set in min_array[], max_array[] from plot.c */
182: extern double min_array[], max_array[];
183: extern int auto_array[], log_array[];
184: extern double base_array[], log_base_array[];
185:
186: /* for convenience while converting to use these arrays */
187: #define x_min3d min_array[FIRST_X_AXIS]
188: #define x_max3d max_array[FIRST_X_AXIS]
189: #define y_min3d min_array[FIRST_Y_AXIS]
190: #define y_max3d max_array[FIRST_Y_AXIS]
191: #define z_min3d min_array[FIRST_Z_AXIS]
192: #define z_max3d max_array[FIRST_Z_AXIS]
193:
194: /* There are several z's to take into account - I hope I get these
195: * right !
196: *
197: * ceiling_z is the highest z in use
198: * floor_z is the lowest z in use
199: * base_z is the z of the base
200: * min3d_z is the lowest z of the graph area
201: * max3d_z is the highest z of the graph area
202: *
203: * ceiling_z is either max3d_z or base_z, and similarly for floor_z
204: * There should be no part of graph drawn outside
205: * min3d_z:max3d_z - apart from arrows, perhaps
206: */
207:
208: double ceiling_z, floor_z, base_z;
209:
210: /* and some bodges while making the change */
211: #define min3d_z min_array[FIRST_Z_AXIS]
212: #define max3d_z max_array[FIRST_Z_AXIS]
213:
214:
215: double xscale3d, yscale3d, zscale3d;
216:
217:
218: typedef double transform_matrix[4][4];
219: transform_matrix trans_mat;
220:
221: static double xaxis_y, yaxis_x, zaxis_x, zaxis_y;
222:
223: /* the co-ordinates of the back corner */
224: static double back_x, back_y;
225:
226: /* the penalty for convenience of using tic_gen to make callbacks
227: * to tick routines is that we cant pass parameters very easily.
228: * We communicate with the tick_callbacks using static variables
229: */
230:
231: /* unit vector (terminal coords) */
232: static double tic_unitx, tic_unity;
233:
234: /* (DFK) Watch for cancellation error near zero on axes labels */
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) {
1.1.1.2 maekawa 400: if (ptitl_cnt > 0) {
1.1 maekawa 401: /* calculate max no cols, limited by label-length */
402: key_cols = (int) (xright - xleft) / ((max_ptitl_len + 4) * (t->h_char) + key_sample_width);
1.1.1.2 maekawa 403: /* HBB 991019: fix division by zero problem */
404: if (key_cols == 0)
405: key_cols = 1;
1.1 maekawa 406: key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
407: /* now calculate actual no cols depending on no rows */
408: key_cols = (int) (ptitl_cnt / key_rows) + ((ptitl_cnt % key_rows) > 0);
409: key_col_wth = (int) (xright - xleft) / key_cols;
410: /* key_rows += ktitle_lines; - messes up key - div */
1.1.1.2 maekawa 411: } else {
412: key_rows = key_cols = key_col_wth = 0;
413: }
1.1 maekawa 414: }
415: /* this should also consider the view and number of lines in
416: * xformat || yformat || xlabel || ylabel */
417:
418: /* an absolute 1, with no terminal-dependent scaling ? */
419: ybot = (t->v_char) * 2.5 + 1;
1.1.1.3 ! ohara 420: if (key_rows && key == -1 && key_vpos == TUNDER) /* HBB 20000328 */
1.1 maekawa 421: ybot += key_rows * key_entry_height + ktitle_lines * t->v_char;
422:
423: if (strlen(title.text)) {
424: titlelin++;
425: for (i = 0; i < strlen(title.text); i++) {
426: if (title.text[i] == '\\')
427: titlelin++;
428: }
429: }
430: ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char) * (titlelin + 1.5) - 1;
431: if (key == -1 && key_vpos != TUNDER) {
432: /* calculate max no rows, limited be ytop-ybot */
433: i = (int) (ytop - ybot) / (t->v_char) - 1 - ktitle_lines;
434: if (ptitl_cnt > i) {
435: key_cols = (int) (ptitl_cnt / i) + ((ptitl_cnt % i) > 0);
436: /* now calculate actual no rows depending on no cols */
437: key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
438: }
439: key_rows += ktitle_lines;
440: }
441: if (key_hpos == TOUT) {
442: xright -= key_col_wth * (key_cols - 1) + key_col_wth - 2 * (t->h_char);
443: }
444: xleft += t->xmax * xoffset;
445: xright += t->xmax * xoffset;
446: ytop += t->ymax * yoffset;
447: ybot += t->ymax * yoffset;
448: xmiddle = (xright + xleft) / 2;
449: ymiddle = (ytop + ybot) / 2;
450: /* HBB 980308: sigh... another 16bit glitch: on term's with more than
451: * 8000 pixels in either direction, these calculations produce garbage
452: * results if done in (16bit) ints */
1.1.1.2 maekawa 453: xscaler = ((xright - xleft) * 4L) / 7L; /* HBB: Magic number alert! */
1.1 maekawa 454: yscaler = ((ytop - ybot) * 4L) / 7L;
455:
456: }
457:
458: #if 0
459: /* not used ; anyway, should be done using bitshifts and squares,
460: * rather than iteratively
461: */
462: static double dbl_raise(x, y)
463: double x;
464: int y;
465: {
466: register int i = ABS(y);
467: double val = 1.0;
468: while (--i >= 0)
469: val *= x;
470: if (y < 0)
471: return (1.0 / val);
472: return (val);
473: }
474: #endif
475:
476: /* we precalculate features of the key, to save lots of nested
477: * ifs in code - x,y = user supplied or computed position of key
478: * taken to be inner edge of a line sample
479: */
480: static int key_sample_left; /* offset from x for left of line sample */
481: static int key_sample_right; /* offset from x for right of line sample */
482: static int key_point_offset; /* offset from x for point sample */
483: static int key_text_left; /* offset from x for left-justified text */
484: static int key_text_right; /* offset from x for right-justified text */
485: static int key_size_left; /* distance from x to left edge of box */
486: static int key_size_right; /* distance from x to right edge of box */
487:
488: void do_3dplot(plots, pcount)
489: struct surface_points *plots;
490: int pcount; /* count of plots in linked list */
491: {
492: struct termentry *t = term;
493: int surface;
494: struct surface_points *this_plot = NULL;
495: unsigned int xl, yl;
496: int linetypeOffset = 0;
1.1.1.2 maekawa 497: /* double ztemp, temp; unused */
1.1 maekawa 498: struct text_label *this_label;
499: struct arrow_def *this_arrow;
500: TBOOLEAN scaling;
501: transform_matrix mat;
502: int key_count;
1.1.1.2 maekawa 503: char *s, *e;
1.1 maekawa 504:
505: /* Initiate transformation matrix using the global view variables. */
506: mat_rot_z(surface_rot_z, trans_mat);
507: mat_rot_x(surface_rot_x, mat);
508: mat_mult(trans_mat, trans_mat, mat);
509: mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat);
510: mat_mult(trans_mat, trans_mat, mat);
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 */
1.1.1.2 maekawa 576: zscale3d = 2.0 / (ceiling_z - floor_z) * surface_zscale;
1.1 maekawa 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: write_multiline((unsigned int) ((xleft + xright) / 2 + title.xoffset * t->h_char),
585: (unsigned int) (ytop + (titlelin + title.yoffset) * (t->h_char)),
1.1.1.2 maekawa 586: title.text, CENTRE, JUST_TOP, 0, title.font);
1.1 maekawa 587: }
588: /* PLACE TIMEDATE */
589: if (*timelabel.text) {
590: char str[MAX_LINE_LEN+1];
591: time_t now;
592: unsigned int x = t->v_char + timelabel.xoffset * t->h_char;
593: unsigned int y = timelabel_bottom ?
594: yoffset * ymax + (timelabel.yoffset + 1) * t->v_char :
595: ytop + (timelabel.yoffset - 1) * t->v_char;
596:
597: time(&now);
598: strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now));
599:
600: if (timelabel_rotate && (*t->text_angle) (1)) {
601: if (timelabel_bottom)
602: write_multiline(x, y, str, LEFT, JUST_TOP, 1, timelabel.font);
603: else
604: write_multiline(x, y, str, RIGHT, JUST_TOP, 1, timelabel.font);
605:
606: (*t->text_angle) (0);
607: } else {
608: if (timelabel_bottom)
609: write_multiline(x, y, str, LEFT, JUST_BOT, 0, timelabel.font);
610: else
611: write_multiline(x, y, str, LEFT, JUST_TOP, 0, timelabel.font);
612: }
613: }
614: /* PLACE LABELS */
615: for (this_label = first_label; this_label != NULL;
616: this_label = this_label->next) {
617: unsigned int x, y;
618:
619:
620: map_position(&this_label->place, &x, &y, "label");
621: if (this_label->rotate && (*t->text_angle) (1)) {
622: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 1, this_label->font);
623: (*t->text_angle) (0);
624: } else {
625: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 0, this_label->font);
626: }
627: }
628:
629: /* PLACE ARROWS */
630: for (this_arrow = first_arrow; this_arrow != NULL;
631: this_arrow = this_arrow->next) {
632: unsigned int sx, sy, ex, ey;
633:
634: map_position(&this_arrow->start, &sx, &sy, "arrow");
635: map_position(&this_arrow->end, &ex, &ey, "arrow");
636: term_apply_lp_properties(&(this_arrow->lp_properties));
637: (*t->arrow) (sx, sy, ex, ey, this_arrow->head);
638: }
639:
640: #ifndef LITE
641: if (hidden3d && draw_surface) {
642: init_hidden_line_removal();
643: reset_hidden_line_removal();
644: hidden_active = TRUE;
645: }
646: #endif /* not LITE */
647:
648: /* WORK OUT KEY SETTINGS AND DO KEY TITLE / BOX */
649:
650: if (key_reverse) {
651: key_sample_left = -key_sample_width;
652: key_sample_right = 0;
653: key_text_left = t->h_char;
654: key_text_right = (t->h_char) * (max_ptitl_len + 1);
655: key_size_right = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
656: key_size_left = (t->h_char) + key_sample_width;
657: } else {
658: key_sample_left = 0;
659: key_sample_right = key_sample_width;
660: key_text_left = -(int) ((t->h_char) * (max_ptitl_len + 1));
661: key_text_right = -(int) (t->h_char);
662: key_size_left = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
663: key_size_right = (t->h_char) + key_sample_width;
664: }
665: key_point_offset = (key_sample_left + key_sample_right) / 2;
666:
667: if (key == -1) {
668: if (key_vpos == TUNDER) {
669: #if 0
670: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
671: xl = max_ptitl_len * 1000 / (key_sample_width / (t->h_char) + max_ptitl_len + 2);
672: xl *= (xright - xleft) / key_cols;
673: xl /= 1000;
674: xl += xleft;
675: #else
1.1.1.2 maekawa 676: /* HBB 19990608: why calculate these again? boundary3d has already
677: * done it... */
678: if (ptitl_cnt > 0) {
1.1 maekawa 679: /* maximise no cols, limited by label-length */
680: key_cols = (int) (xright - xleft) / key_col_wth;
681: key_rows = (int) (ptitl_cnt + key_cols - 1) / key_cols;
682: /* now calculate actual no cols depending on no rows */
683: key_cols = (int) (ptitl_cnt + key_rows - 1) / key_rows;
684: key_col_wth = (int) (xright - xleft) / key_cols;
685: /* we divide into columns, then centre in column by considering
686: * ratio of key_left_size to key_right_size
687: * key_size_left/(key_size_left+key_size_right) * (xright-xleft)/key_cols
688: * do one integer division to maximise accuracy (hope we dont
689: * overflow !)
690: */
691: xl = xleft + ((xright - xleft) * key_size_left) / (key_cols * (key_size_left + key_size_right));
692: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
1.1.1.2 maekawa 693: }
1.1 maekawa 694: #endif
695: } else {
696: if (key_vpos == TTOP) {
697: yl = ytop - (t->v_tic) - t->v_char;
698: } else {
699: yl = ybot + (t->v_tic) + key_entry_height * key_rows + ktitle_lines * t->v_char;
700: }
701: if (key_hpos == TOUT) {
702: /* keys outside plot border (right) */
703: xl = xright + (t->h_tic) + key_size_left;
704: } else if (key_hpos == TLEFT) {
705: xl = xleft + (t->h_tic) + key_size_left;
706: } else {
707: xl = xright - key_size_right - key_col_wth * (key_cols - 1);
708: }
709: }
710: yl_ref = yl - ktitle_lines * (t->v_char);
711: }
712: if (key == 1) {
713: map_position(&key_user_pos, &xl, &yl, "key");
714: }
715: if (key && key_box.l_type > -3) {
716: int yt = yl;
717: int yb = yl - key_entry_height * (key_rows - ktitle_lines) - ktitle_lines * t->v_char;
718: int key_xr = xl + key_col_wth * (key_cols - 1) + key_size_right;
719: /* key_rows seems to contain title at this point ??? */
720: term_apply_lp_properties(&key_box);
721: (*t->move) (xl - key_size_left, yb);
722: (*t->vector) (xl - key_size_left, yt);
723: (*t->vector) (key_xr, yt);
724: (*t->vector) (key_xr, yb);
725: (*t->vector) (xl - key_size_left, yb);
726:
727: /* draw a horizontal line between key title and first entry JFi */
728: (*t->move) (xl - key_size_left, yt - (ktitle_lines) * t->v_char);
729: (*t->vector) (xl + key_size_right, yt - (ktitle_lines) * t->v_char);
730: }
731: /* DRAW SURFACES AND CONTOURS */
732:
733: #ifndef LITE
734: if (hidden3d && draw_surface)
735: plot3d_hidden(plots, pcount);
736: #endif /* not LITE */
737:
738: /* KEY TITLE */
739: if (key != 0 && strlen(key_title)) {
1.1.1.2 maekawa 740: char *ss = gp_alloc(strlen(key_title) + 2, "tmp string ss");
741: strcpy(ss, key_title);
742: strcat(ss, "\n");
1.1 maekawa 743: s = ss;
744: yl -= t->v_char / 2;
745: while ((e = (char *) strchr(s, '\n')) != NULL) {
746: *e = '\0';
747: if (key_just == JLEFT) {
748: (*t->justify_text) (LEFT);
749: (*t->put_text) (xl + key_text_left, yl, s);
750: } else {
751: if ((*t->justify_text) (RIGHT)) {
752: (*t->put_text) (xl + key_text_right,
753: yl, s);
754: } else {
755: int x = xl + key_text_right - (t->h_char) * strlen(s);
756: if (inrange(x, xleft, xright))
757: (*t->put_text) (x, yl, s);
758: }
759: }
760: s = ++e;
761: yl -= t->v_char;
762: }
763: yl += t->v_char / 2;
1.1.1.2 maekawa 764: free(ss);
1.1 maekawa 765: }
766: key_count = 0;
767: yl_ref = yl -= key_entry_height / 2; /* centralise the keys */
768:
769: #define NEXT_KEY_LINE() \
770: if ( ++key_count >= key_rows ) { \
771: yl = yl_ref; xl += key_col_wth; key_count = 0; \
772: } else \
773: yl -= key_entry_height
774:
775: this_plot = plots;
776: for (surface = 0;
777: surface < pcount;
778: this_plot = this_plot->next_sp, surface++) {
779:
780: #ifndef LITE
781: if (hidden3d)
782: hidden_no_update = FALSE;
783: #endif /* not LITE */
784:
785: if (draw_surface) {
786: int lkey = (key != 0 && this_plot->title && this_plot->title[0]);
787: term_apply_lp_properties(&(this_plot->lp_properties));
788:
789: #ifndef LITE
790: if (hidden3d) {
791: hidden_line_type_above = this_plot->lp_properties.l_type;
792: hidden_line_type_below = this_plot->lp_properties.l_type + 1;
793: }
794: #endif /* not LITE */
795:
796: if (lkey) {
797: key_text(xl, yl, this_plot->title);
798: }
799: switch (this_plot->plot_style) {
800: case BOXES: /* can't do boxes in 3d yet so use impulses */
801: case IMPULSES:{
802: if (lkey) {
803: key_sample_line(xl, yl);
804: }
805: if (!(hidden3d && draw_surface))
806: plot3d_impulses(this_plot);
807: break;
808: }
809: case STEPS: /* HBB: I think these should be here */
810: case FSTEPS:
811: case HISTEPS:
812: case LINES:{
813: if (lkey) {
814: key_sample_line(xl, yl);
815: }
816: if (!(hidden3d && draw_surface))
817: plot3d_lines(this_plot);
818: break;
819: }
820: case YERRORBARS: /* ignored; treat like points */
821: case XERRORBARS: /* ignored; treat like points */
822: case XYERRORBARS: /* ignored; treat like points */
823: case BOXXYERROR: /* HBB: ignore these as well */
824: case BOXERROR:
825: case CANDLESTICKS: /* HBB: dito */
826: case FINANCEBARS:
827: case VECTOR:
828: case POINTSTYLE:
1.1.1.3 ! ohara 829: if (lkey) {
1.1 maekawa 830: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
831: }
832: if (!(hidden3d && draw_surface))
833: plot3d_points(this_plot);
834: break;
835:
836: case LINESPOINTS:
837: /* put lines */
838: if (lkey)
839: key_sample_line(xl, yl);
840:
841: if (!(hidden3d && draw_surface))
842: plot3d_lines(this_plot);
843:
844: /* put points */
1.1.1.3 ! ohara 845: if (lkey)
1.1 maekawa 846: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
847:
848: if (!(hidden3d && draw_surface))
849: plot3d_points(this_plot);
850:
851: break;
852:
853: case DOTS:
854: if (lkey) {
855: if (key == 1) {
856: if (!clip_point(xl + key_point_offset, yl))
857: (*t->point) (xl + key_point_offset, yl, -1);
858: } else {
859: (*t->point) (xl + key_point_offset, yl, -1);
860: /* (*t->point)(xl+2*(t->h_char),yl, -1); */
861: }
862: }
863: if (!(hidden3d && draw_surface))
864: plot3d_dots(this_plot);
865:
866: break;
867:
868:
869: } /* switch(plot-style) */
870:
871: /* move key on a line */
872: if (lkey) {
873: NEXT_KEY_LINE();
874: }
875: } /* draw_surface */
876:
877: #ifndef LITE
878: if (hidden3d) {
879: hidden_no_update = TRUE;
880: hidden_line_type_above = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
881: hidden_line_type_below = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
882: }
883: #endif /* not LITE */
884:
885: if (draw_contour && this_plot->contours != NULL) {
886: struct gnuplot_contours *cntrs = this_plot->contours;
887:
888: term_apply_lp_properties(&(this_plot->lp_properties));
889: (*t->linetype) (this_plot->lp_properties.l_type + (hidden3d ? 2 : 1));
890:
891: if (key != 0 && this_plot->title && this_plot->title[0]
892: && !draw_surface && !label_contours) {
893: /* unlabelled contours but no surface : put key entry in now */
894: key_text(xl, yl, this_plot->title);
895:
896: switch (this_plot->plot_style) {
897: case IMPULSES:
898: case LINES:
899: case BOXES: /* HBB: I think these should be here... */
900: case STEPS:
901: case FSTEPS:
902: case HISTEPS:
903: key_sample_line(xl, yl);
904: break;
905: case YERRORBARS: /* ignored; treat like points */
906: case XERRORBARS: /* ignored; treat like points */
907: case XYERRORBARS: /* ignored; treat like points */
908: case BOXERROR: /* HBB: ignore these as well */
909: case BOXXYERROR:
910: case CANDLESTICKS: /* HBB: dito */
911: case FINANCEBARS:
912: case VECTOR:
913: case POINTSTYLE:
914: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
915: break;
916: case LINESPOINTS:
917: key_sample_line(xl, yl);
918: break;
919: case DOTS:
920: key_sample_point(xl, yl, -1);
921: break;
922: }
923: NEXT_KEY_LINE();
924: }
925: linetypeOffset = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
926: while (cntrs) {
927: if (label_contours && cntrs->isNewLevel) {
928: (*t->linetype) (linetypeOffset++);
929: if (key) {
930:
931: #ifndef LITE
932: if (hidden3d)
933: hidden_line_type_below = hidden_line_type_above = linetypeOffset - 1;
934: #endif /* not LITE */
935:
936: key_text(xl, yl, cntrs->label);
937:
938: switch (this_plot->plot_style) {
939: case IMPULSES:
940: case LINES:
941: case LINESPOINTS:
942: case BOXES: /* HBB: these should be treated as well... */
943: case STEPS:
944: case FSTEPS:
945: case HISTEPS:
946: key_sample_line(xl, yl);
947: break;
948: case YERRORBARS: /* ignored; treat like points */
949: case XERRORBARS: /* ignored; treat like points */
950: case XYERRORBARS: /* ignored; treat like points */
951: case BOXERROR: /* HBB: treat these likewise */
952: case BOXXYERROR:
953: case CANDLESTICKS: /* HBB: dito */
954: case FINANCEBARS:
955: case VECTOR:
956: case POINTSTYLE:
957: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
958: break;
959: case DOTS:
960: key_sample_point(xl, yl, -1);
961: break;
962: } /* switch */
963:
964: NEXT_KEY_LINE();
965:
966: } /* key */
967: } /* label_contours */
968: /* now draw the contour */
969: switch (this_plot->plot_style) {
970: case IMPULSES:
971: case BOXES: /* HBB: this should also be treated somehow */
972: cntr3d_impulses(cntrs, this_plot);
973: break;
974: case LINES:
975: case STEPS: /* HBB: these should also be handled, I think */
976: case FSTEPS:
977: case HISTEPS:
978: cntr3d_lines(cntrs);
979: break;
980: case YERRORBARS: /* ignored; treat like points */
981: case XERRORBARS: /* ignored; treat like points */
982: case XYERRORBARS: /* ignored; treat like points */
983: case BOXERROR: /* HBB: ignore these too... */
984: case BOXXYERROR:
985: case CANDLESTICKS: /* HBB: dito */
986: case FINANCEBARS:
987: case VECTOR:
988: case POINTSTYLE:
989: cntr3d_points(cntrs, this_plot);
990: break;
991: case LINESPOINTS:
992: cntr3d_lines(cntrs);
993: cntr3d_points(cntrs, this_plot);
994: break;
995: case DOTS:
996: cntr3d_dots(cntrs);
997: break;
998: } /*switch */
999:
1000: cntrs = cntrs->next;
1001: } /* loop over contours */
1002: } /* draw contours */
1003: } /* loop over surfaces */
1004:
1005: draw_bottom_grid(plots, pcount);
1006:
1007: term_end_plot();
1008:
1009: #ifndef LITE
1010: if (hidden3d && draw_surface) {
1011: term_hidden_line_removal();
1012: hidden_active = FALSE;
1013: }
1014: #endif /* not LITE */
1015:
1016: }
1017:
1018: /* plot3d_impulses:
1019: * Plot the surfaces in IMPULSES style
1020: */
1021: static void plot3d_impulses(plot)
1022: struct surface_points *plot;
1023: {
1024: int i; /* point index */
1025: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1026: struct iso_curve *icrvs = plot->iso_crvs;
1027:
1028: while (icrvs) {
1029: struct coordinate GPHUGE *points = icrvs->points;
1030:
1031: for (i = 0; i < icrvs->p_count; i++) {
1032: switch (points[i].type) {
1033: case INRANGE:
1034: {
1035: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1036:
1037: if (inrange(0.0, min3d_z, max3d_z)) {
1038: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
1039: } else if (inrange(min3d_z, 0.0, points[i].z)) {
1040: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
1041: } else {
1042: map3d_xy(points[i].x, points[i].y, max3d_z, &x0, &y0);
1043: }
1044:
1045: clip_move(x0, y0);
1046: clip_vector(x, y);
1047:
1048: break;
1049: }
1050: case OUTRANGE:
1051: {
1052: if (!inrange(points[i].x, x_min3d, x_max3d) ||
1053: !inrange(points[i].y, y_min3d, y_max3d))
1054: break;
1055:
1056: if (inrange(0.0, min3d_z, max3d_z)) {
1057: /* zero point is INRANGE */
1058: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
1059:
1060: /* must cross z = min3d_z or max3d_z limits */
1061: if (inrange(min3d_z, 0.0, points[i].z) &&
1062: min3d_z != 0.0 && min3d_z != points[i].z) {
1063: map3d_xy(points[i].x, points[i].y, min3d_z, &x, &y);
1064: } else {
1065: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
1066: }
1067: } else {
1068: /* zero point is also OUTRANGE */
1069: if (inrange(min3d_z, 0.0, points[i].z) &&
1070: inrange(max3d_z, 0.0, points[i].z)) {
1071: /* crosses z = min3d_z or max3d_z limits */
1072: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
1073: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
1074: } else {
1075: /* doesn't cross z = min3d_z or max3d_z limits */
1076: break;
1077: }
1078: }
1079:
1080: clip_move(x0, y0);
1081: clip_vector(x, y);
1082:
1083: break;
1084: }
1085: default: /* just a safety */
1086: case UNDEFINED:{
1087: break;
1088: }
1089: }
1090: }
1091:
1092: icrvs = icrvs->next;
1093: }
1094: }
1095:
1096: /* plot3d_lines:
1097: * Plot the surfaces in LINES style
1098: */
1099: /* We want to always draw the lines in the same direction, otherwise when
1100: we draw an adjacent box we might get the line drawn a little differently
1101: and we get splotches. */
1102:
1103: static void plot3d_lines(plot)
1104: struct surface_points *plot;
1105: {
1106: int i;
1107: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1108: double clip_x, clip_y, clip_z;
1109: struct iso_curve *icrvs = plot->iso_crvs;
1110: struct coordinate GPHUGE *points;
1111: enum coord_type prev = UNDEFINED;
1112: double lx[2], ly[2], lz[2]; /* two edge points */
1113:
1114: #ifndef LITE
1115: /* These are handled elsewhere. */
1116: if (plot->has_grid_topology && hidden3d)
1117: return;
1118: #endif /* not LITE */
1119:
1120: while (icrvs) {
1121: prev = UNDEFINED; /* type of previous plot */
1122:
1123: for (i = 0, points = icrvs->points; i < icrvs->p_count; i++) {
1124: switch (points[i].type) {
1125: case INRANGE:{
1126: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1127:
1128: if (prev == INRANGE) {
1129: clip_vector(x, y);
1130: } else {
1131: if (prev == OUTRANGE) {
1132: /* from outrange to inrange */
1133: if (!clip_lines1) {
1134: clip_move(x, y);
1135: } else {
1136: /*
1137: * Calculate intersection point and draw
1138: * vector from there
1139: */
1140: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
1141:
1142: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
1143:
1144: clip_move(x0, y0);
1145: clip_vector(x, y);
1146: }
1147: } else {
1148: clip_move(x, y);
1149: }
1150: }
1151:
1152: break;
1153: }
1154: case OUTRANGE:{
1155: if (prev == INRANGE) {
1156: /* from inrange to outrange */
1157: if (clip_lines1) {
1158: /*
1159: * Calculate intersection point and draw
1160: * vector to it
1161: */
1162:
1163: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
1164:
1165: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
1166:
1167: clip_vector(x0, y0);
1168: }
1169: } else if (prev == OUTRANGE) {
1170: /* from outrange to outrange */
1171: if (clip_lines2) {
1172: /*
1173: * Calculate the two 3D intersection points
1174: * if present
1175: */
1176: if (two_edge3d_intersect(points, i, lx, ly, lz)) {
1177:
1178: map3d_xy(lx[0], ly[0], lz[0], &x, &y);
1179:
1180: map3d_xy(lx[1], ly[1], lz[1], &x0, &y0);
1181:
1182: clip_move(x, y);
1183: clip_vector(x0, y0);
1184: }
1185: }
1186: }
1187: break;
1188: }
1189: case UNDEFINED:{
1190: break;
1191: default:
1192: graph_error("Unknown point type in plot3d_lines");
1193: }
1194: }
1195:
1196: prev = points[i].type;
1197: }
1198:
1199: icrvs = icrvs->next;
1200: }
1201: }
1202:
1203: /* plot3d_points:
1204: * Plot the surfaces in POINTSTYLE style
1205: */
1206: static void plot3d_points(plot)
1207: struct surface_points *plot;
1208: {
1209: int i;
1210: unsigned int x, y;
1211: struct termentry *t = term;
1212: struct iso_curve *icrvs = plot->iso_crvs;
1213:
1214: while (icrvs) {
1215: struct coordinate GPHUGE *points = icrvs->points;
1216:
1217: for (i = 0; i < icrvs->p_count; i++) {
1218: if (points[i].type == INRANGE) {
1219: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1220:
1221: if (!clip_point(x, y))
1222: (*t->point) (x, y, plot->lp_properties.p_type);
1223: }
1224: }
1225:
1226: icrvs = icrvs->next;
1227: }
1228: }
1229:
1230: /* plot3d_dots:
1231: * Plot the surfaces in DOTS style
1232: */
1233: static void plot3d_dots(plot)
1234: struct surface_points *plot;
1235: {
1236: int i;
1237: struct termentry *t = term;
1238: struct iso_curve *icrvs = plot->iso_crvs;
1239:
1240: while (icrvs) {
1241: struct coordinate GPHUGE *points = icrvs->points;
1242:
1243: for (i = 0; i < icrvs->p_count; i++) {
1244: if (points[i].type == INRANGE) {
1245: unsigned int x, y;
1246: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1247:
1248: if (!clip_point(x, y))
1249: (*t->point) (x, y, -1);
1250: }
1251: }
1252:
1253: icrvs = icrvs->next;
1254: }
1255: }
1256:
1257: /* cntr3d_impulses:
1258: * Plot a surface contour in IMPULSES style
1259: */
1260: static void cntr3d_impulses(cntr, plot)
1261: struct gnuplot_contours *cntr;
1262: struct surface_points *plot;
1263: {
1264: int i; /* point index */
1265: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1266:
1267: if (draw_contour & CONTOUR_SRF) {
1268: for (i = 0; i < cntr->num_pts; i++) {
1269: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
1270: &x, &y);
1271: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1272: &x0, &y0);
1273:
1274: clip_move(x0, y0);
1275: clip_vector(x, y);
1276: }
1277: } else {
1278: /* Must be on base grid, so do points. */
1279: cntr3d_points(cntr, plot);
1280: }
1281: }
1282:
1283: /* cntr3d_lines:
1284: * Plot a surface contour in LINES style
1285: */
1286: static void cntr3d_lines(cntr)
1287: struct gnuplot_contours *cntr;
1288: {
1289: int i; /* point index */
1290: unsigned int x, y; /* point in terminal coordinates */
1291:
1292: if (draw_contour & CONTOUR_SRF) {
1293: for (i = 0; i < cntr->num_pts; i++) {
1294: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
1295: &x, &y);
1296:
1297: if (i > 0) {
1298: clip_vector(x, y);
1299: if (i == 1)
1300: suppressMove = TRUE;
1301: } else {
1302: clip_move(x, y);
1303: }
1304: }
1305: }
1306: /* beginning a new contour level, so moveto() required */
1307: suppressMove = FALSE;
1308:
1309: if (draw_contour & CONTOUR_BASE) {
1310: for (i = 0; i < cntr->num_pts; i++) {
1311: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1312: &x, &y);
1313:
1314: if (i > 0) {
1315: clip_vector(x, y);
1316: if (i == 1)
1317: suppressMove = TRUE;
1318: } else {
1319: clip_move(x, y);
1320: }
1321: }
1322: }
1323: /* beginning a new contour level, so moveto() required */
1324: suppressMove = FALSE;
1325: }
1326:
1327: /* cntr3d_points:
1328: * Plot a surface contour in POINTSTYLE style
1329: */
1330: static void cntr3d_points(cntr, plot)
1331: struct gnuplot_contours *cntr;
1332: struct surface_points *plot;
1333: {
1334: int i;
1335: unsigned int x, y;
1336: struct termentry *t = term;
1337:
1338: if (draw_contour & CONTOUR_SRF) {
1339: for (i = 0; i < cntr->num_pts; i++) {
1340: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
1341:
1342: if (!clip_point(x, y))
1343: (*t->point) (x, y, plot->lp_properties.p_type);
1344: }
1345: }
1346: if (draw_contour & CONTOUR_BASE) {
1347: for (i = 0; i < cntr->num_pts; i++) {
1348: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1349: &x, &y);
1350:
1351: if (!clip_point(x, y))
1352: (*t->point) (x, y, plot->lp_properties.p_type);
1353: }
1354: }
1355: }
1356:
1357: /* cntr3d_dots:
1358: * Plot a surface contour in DOTS style
1359: */
1360: static void cntr3d_dots(cntr)
1361: struct gnuplot_contours *cntr;
1362: {
1363: int i;
1364: unsigned int x, y;
1365: struct termentry *t = term;
1366:
1367: if (draw_contour & CONTOUR_SRF) {
1368: for (i = 0; i < cntr->num_pts; i++) {
1369: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
1370:
1371: if (!clip_point(x, y))
1372: (*t->point) (x, y, -1);
1373: }
1374: }
1375: if (draw_contour & CONTOUR_BASE) {
1376: for (i = 0; i < cntr->num_pts; i++) {
1377: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1378: &x, &y);
1379:
1380: if (!clip_point(x, y))
1381: (*t->point) (x, y, -1);
1382: }
1383: }
1384: }
1385:
1386:
1387:
1388: /* map xmin | xmax to 0 | 1 and same for y
1389: * 0.1 avoids any rounding errors
1390: */
1391: #define MAP_HEIGHT_X(x) ( (int) (((x)-x_min3d)/(x_max3d-x_min3d)+0.1) )
1392: #define MAP_HEIGHT_Y(y) ( (int) (((y)-y_min3d)/(y_max3d-y_min3d)+0.1) )
1393:
1394: /* if point is at corner, update height[][] and depth[][]
1395: * we are still assuming that extremes of surfaces are at corners,
1396: * but we are not assuming order of corners
1397: */
1398: static void check_corner_height(p, height, depth)
1399: struct coordinate GPHUGE *p;
1400: double height[2][2];
1401: double depth[2][2];
1402: {
1403: if (p->type != INRANGE)
1404: return;
1405: if ((fabs(p->x - x_min3d) < zero || fabs(p->x - x_max3d) < zero) &&
1406: (fabs(p->y - y_min3d) < zero || fabs(p->y - y_max3d) < zero)) {
1407: unsigned int x = MAP_HEIGHT_X(p->x);
1408: unsigned int y = MAP_HEIGHT_Y(p->y);
1409: if (height[x][y] < p->z)
1410: height[x][y] = p->z;
1411: if (depth[x][y] > p->z)
1412: depth[x][y] = p->z;
1413: }
1414: }
1415:
1416:
1417: /* Draw the bottom grid that hold the tic marks for 3d surface. */
1418: static void draw_bottom_grid(plot, plot_num)
1419: struct surface_points *plot;
1420: int plot_num;
1421: {
1422: unsigned int x, y; /* point in terminal coordinates */
1423: struct termentry *t = term;
1424: char ss[MAX_LINE_LEN+1];
1425:
1426: /* work out where the axes and tics are drawn */
1427:
1428: {
1429: int quadrant = surface_rot_z / 90;
1430: if ((quadrant + 1) & 2) {
1431: zaxis_x = x_max3d;
1432: xaxis_y = y_max3d;
1433: } else {
1434: zaxis_x = x_min3d;
1435: xaxis_y = y_min3d;
1436: }
1437:
1438: if (quadrant & 2) {
1439: zaxis_y = y_max3d;
1440: yaxis_x = x_min3d;
1441: } else {
1442: zaxis_y = y_min3d;
1443: yaxis_x = x_max3d;
1444: }
1445:
1446: if (surface_rot_x > 90) {
1447: /* labels on the back axes */
1448: back_x = yaxis_x = x_min3d + x_max3d - yaxis_x;
1449: back_y = xaxis_y = y_min3d + y_max3d - xaxis_y;
1450: } else {
1451: back_x = x_min3d + x_max3d - yaxis_x;
1452: back_y = y_min3d + y_max3d - xaxis_y;
1453: }
1454: }
1455:
1456: if (draw_border) {
1457: unsigned int bl_x, bl_y; /* bottom left */
1458: unsigned int bb_x, bb_y; /* bottom back */
1459: unsigned int br_x, br_y; /* bottom right */
1460: unsigned int bf_x, bf_y; /* bottom front */
1461:
1462: #ifndef LITE
1463: int save_update = hidden_no_update;
1464: hidden_no_update = TRUE;
1465: #endif /* LITE */
1466:
1467: /* Here is the one and only call to this function. */
1468: setlinestyle(border_lp);
1469:
1470: map3d_xy(zaxis_x, zaxis_y, base_z, &bl_x, &bl_y);
1471: map3d_xy(back_x, back_y, base_z, &bb_x, &bb_y);
1472: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, base_z, &br_x, &br_y);
1473: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, base_z, &bf_x, &bf_y);
1474:
1475: /* border around base */
1476: {
1477: int save = hidden_active;
1478: hidden_active = FALSE; /* this is in front */
1479: if (draw_border & 4)
1480: draw_clip_line(br_x, br_y, bf_x, bf_y);
1481: if (draw_border & 1)
1482: draw_clip_line(bl_x, bl_y, bf_x, bf_y);
1483: hidden_active = save;
1484: }
1485: if (draw_border & 2)
1486: draw_clip_line(bl_x, bl_y, bb_x, bb_y);
1487: if (draw_border & 8)
1488: draw_clip_line(br_x, br_y, bb_x, bb_y);
1489:
1490: if (draw_surface || (draw_contour & CONTOUR_SRF)) {
1491: int save = hidden_active;
1492: /* map the 8 corners to screen */
1493: unsigned int fl_x, fl_y; /* floor left */
1494: unsigned int fb_x, fb_y; /* floor back */
1495: unsigned int fr_x, fr_y; /* floor right */
1496: unsigned int ff_x, ff_y; /* floor front */
1497:
1498: unsigned int tl_x, tl_y; /* top left */
1499: unsigned int tb_x, tb_y; /* top back */
1500: unsigned int tr_x, tr_y; /* top right */
1501: unsigned int tf_x, tf_y; /* top front */
1502:
1503: map3d_xy(zaxis_x, zaxis_y, floor_z, &fl_x, &fl_y);
1504: map3d_xy(back_x, back_y, floor_z, &fb_x, &fb_y);
1505: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, floor_z, &fr_x, &fr_y);
1506: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, floor_z, &ff_x, &ff_y);
1507:
1508: map3d_xy(zaxis_x, zaxis_y, ceiling_z, &tl_x, &tl_y);
1509: map3d_xy(back_x, back_y, ceiling_z, &tb_x, &tb_y);
1510: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, ceiling_z, &tr_x, &tr_y);
1511: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, ceiling_z, &tf_x, &tf_y);
1512:
1513: /* vertical lines, to surface or to very top */
1514: if ((draw_border & 0xf0) == 0xf0) {
1515: /* all four verticals drawn - save some time */
1516: draw_clip_line(fl_x, fl_y, tl_x, tl_y);
1517: draw_clip_line(fb_x, fb_y, tb_x, tb_y);
1518: draw_clip_line(fr_x, fr_y, tr_x, tr_y);
1519: hidden_active = FALSE; /* this is in front */
1520: draw_clip_line(ff_x, ff_y, tf_x, tf_y);
1521: hidden_active = save;
1522: } else {
1523: /* search surfaces for heights at corners */
1524: double height[2][2];
1525: double depth[2][2];
1526: unsigned int zaxis_i = MAP_HEIGHT_X(zaxis_x);
1527: unsigned int zaxis_j = MAP_HEIGHT_Y(zaxis_y);
1528: unsigned int back_i = MAP_HEIGHT_X(back_x);
1529: /* HBB: why isn't back_j unsigned ??? */
1530: int back_j = MAP_HEIGHT_Y(back_y);
1531:
1532: height[0][0] = height[0][1] = height[1][0] = height[1][1] = base_z;
1533: depth[0][0] = depth[0][1] = depth[1][0] = depth[1][1] = base_z;
1534:
1535: for (; --plot_num >= 0; plot = plot->next_sp) {
1536: struct iso_curve *curve = plot->iso_crvs;
1537: int count = curve->p_count;
1538: int iso;
1539: if (plot->plot_type == DATA3D) {
1540: if (!plot->has_grid_topology)
1541: continue;
1542: iso = plot->num_iso_read;
1543: } else
1544: iso = iso_samples_2;
1545:
1546: check_corner_height(curve->points, height, depth);
1547: check_corner_height(curve->points + count - 1, height, depth);
1548: while (--iso)
1549: curve = curve->next;
1550: check_corner_height(curve->points, height, depth);
1551: check_corner_height(curve->points + count - 1, height, depth);
1552: }
1553:
1554: #define VERTICAL(mask,x,y,i,j,bx,by,tx,ty) \
1555: if (draw_border&mask) \
1556: draw_clip_line(bx,by,tx,ty);\
1557: else if (height[i][j] != depth[i][j]) \
1558: { unsigned int a0,b0, a1, b1; \
1559: map3d_xy(x,y,depth[i][j],&a0,&b0); \
1560: map3d_xy(x,y,height[i][j],&a1,&b1); \
1561: draw_clip_line(a0,b0,a1,b1); \
1562: }
1563:
1564: VERTICAL(16,zaxis_x,zaxis_y,zaxis_i,zaxis_j,fl_x,fl_y,tl_x,tl_y);
1565: VERTICAL(32,back_x,back_y,back_i,back_j,fb_x,fb_y,tb_x,tb_y);
1566: 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);
1567: hidden_active = FALSE;
1568: 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);
1569: hidden_active = save;
1570: }
1571:
1572: /* now border lines on top */
1573: if (draw_border & 256)
1574: draw_clip_line(tl_x, tl_y, tb_x, tb_y);
1575: if (draw_border & 512)
1576: draw_clip_line(tr_x, tr_y, tb_x, tb_y);
1577: /* these lines are in front of surface (?) */
1578: hidden_active = FALSE;
1579: if (draw_border & 1024)
1580: draw_clip_line(tl_x, tl_y, tf_x, tf_y);
1581: if (draw_border & 2048)
1582: draw_clip_line(tr_x, tr_y, tf_x, tf_y);
1583: hidden_active = save;
1584: }
1585:
1586: #ifndef LITE
1587: hidden_no_update = save_update;
1588: #endif /* LITE */
1589:
1590: }
1591: if (xtics || *xlabel.text) {
1592: unsigned int x0, y0, x1, y1;
1593: double mid_x = (x_max3d + x_min3d) / 2;
1594: double len;
1595: map3d_xy(mid_x, xaxis_y, base_z, &x0, &y0);
1596: map3d_xy(mid_x, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
1597: { /* take care over unsigned quantities */
1598: int dx = x1 - x0;
1599: int dy = y1 - y0;
1600: /* HBB 980309: 16bit strikes back: */
1601: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
1602: if (len != 0) {
1603: tic_unitx = dx / len;
1604: tic_unity = dy / len;
1605: } else {
1606: tic_unitx = tic_unity = 0;
1607: }
1608: }
1609:
1610: if (xtics) {
1611: gen_tics(FIRST_X_AXIS, &xticdef,
1612: work_grid.l_type & (GRID_X | GRID_MX),
1613: mxtics, mxtfreq, xtick_callback);
1614: }
1615: if (*xlabel.text) {
1616: /* label at xaxis_y + 1/4 of (xaxis_y-other_y) */
1617: double step = (2 * xaxis_y - y_max3d - y_min3d) / 4;
1618: map3d_xy(mid_x, xaxis_y + step, base_z, &x1, &y1);
1619: x1 += xlabel.xoffset * t->h_char;
1620: y1 += xlabel.yoffset * t->v_char;
1621: if (!tic_in) {
1622: x1 -= tic_unitx * ticscale * (t->h_tic);
1623: y1 -= tic_unity * ticscale * (t->v_tic);
1624: }
1625: /* write_multiline mods it */
1.1.1.2 maekawa 1626: write_multiline(x1, y1, xlabel.text, CENTRE, JUST_TOP, 0, xlabel.font);
1.1 maekawa 1627: }
1628: }
1629: if (ytics || *ylabel.text) {
1630: unsigned int x0, y0, x1, y1;
1631: double mid_y = (y_max3d + y_min3d) / 2;
1632: double len;
1633: map3d_xy(yaxis_x, mid_y, base_z, &x0, &y0);
1634: map3d_xy(x_min3d + x_max3d - yaxis_x, mid_y, base_z, &x1, &y1);
1635: { /* take care over unsigned quantities */
1636: int dx = x1 - x0;
1637: int dy = y1 - y0;
1638: /* HBB 980309: 16 Bits strike again: */
1639: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
1640: if (len != 0) {
1641: tic_unitx = dx / len;
1642: tic_unity = dy / len;
1643: } else {
1644: tic_unitx = tic_unity = 0;
1645: }
1646: }
1647: if (ytics) {
1648: gen_tics(FIRST_Y_AXIS, &yticdef,
1649: work_grid.l_type & (GRID_Y | GRID_MY),
1650: mytics, mytfreq, ytick_callback);
1651: }
1652: if (*ylabel.text) {
1653: double step = (x_max3d + x_min3d - 2 * yaxis_x) / 4;
1654: map3d_xy(yaxis_x - step, mid_y, base_z, &x1, &y1);
1655: x1 += ylabel.xoffset * t->h_char;
1656: y1 += ylabel.yoffset * t->v_char;
1657: if (!tic_in) {
1658: x1 -= tic_unitx * ticscale * (t->h_tic);
1659: y1 -= tic_unity * ticscale * (t->v_tic);
1660: }
1661: /* write_multiline mods it */
1662: safe_strncpy(ss, ylabel.text, sizeof(ss));
1663: write_multiline(x1, y1, ss, CENTRE, JUST_TOP, 0, ylabel.font);
1664: }
1665: }
1666: /* do z tics */
1667:
1668: if (ztics && (draw_surface || (draw_contour & CONTOUR_SRF))) {
1669: gen_tics(FIRST_Z_AXIS, &zticdef, work_grid.l_type & (GRID_Z | GRID_MZ),
1670: mztics, mztfreq, ztick_callback);
1671: }
1.1.1.2 maekawa 1672: if ((yzeroaxis.l_type >= -2) && !is_log_x && inrange(0, x_min3d, x_max3d)) {
1.1 maekawa 1673: unsigned int x, y, x1, y1;
1.1.1.2 maekawa 1674: term_apply_lp_properties(&yzeroaxis);
1.1 maekawa 1675: map3d_xy(0.0, y_min3d, base_z, &x, &y); /* line through x=0 */
1676: map3d_xy(0.0, y_max3d, base_z, &x1, &y1);
1677: draw_clip_line(x, y, x1, y1);
1678: }
1.1.1.2 maekawa 1679: if ((xzeroaxis.l_type >= -2) && !is_log_y && inrange(0, y_min3d, y_max3d)) {
1.1 maekawa 1680: unsigned int x, y, x1, y1;
1.1.1.2 maekawa 1681: term_apply_lp_properties(&xzeroaxis);
1.1 maekawa 1682: map3d_xy(x_min3d, 0.0, base_z, &x, &y); /* line through y=0 */
1683: map3d_xy(x_max3d, 0.0, base_z, &x1, &y1);
1684: draw_clip_line(x, y, x1, y1);
1685: }
1686: /* PLACE ZLABEL - along the middle grid Z axis - eh ? */
1687: if (*zlabel.text && (draw_surface || (draw_contour & CONTOUR_SRF))) {
1688: map3d_xy(zaxis_x, zaxis_y, z_max3d + (z_max3d - base_z) / 4, &x, &y);
1689:
1690: x += zlabel.xoffset * t->h_char;
1691: y += zlabel.yoffset * t->v_char;
1692:
1.1.1.2 maekawa 1693: write_multiline(x, y, zlabel.text, CENTRE, CENTRE, 0, zlabel.font);
1.1 maekawa 1694:
1695: }
1696: }
1697:
1698:
1.1.1.3 ! ohara 1699: /* HBB 20010118: all the *_callback() functions made non-static. This
! 1700: * is necessary to work around a bug in HP's assembler shipped with
! 1701: * HP-UX 10 and higher, if GCC tries to use it */
! 1702: void xtick_callback(axis, place, text, grid)
1.1 maekawa 1703: int axis;
1704: double place;
1705: char *text;
1706: struct lp_style_type grid; /* linetype or -2 for none */
1707: {
1708: unsigned int x, y, x1, y1;
1709: double scale = (text ? ticscale : miniticscale);
1710: int dirn = tic_in ? 1 : -1;
1711: register struct termentry *t = term;
1712:
1713: map3d_xy(place, xaxis_y, base_z, &x, &y);
1714: if (grid.l_type > -2) {
1715: term_apply_lp_properties(&grid);
1716: /* to save mapping twice, map non-axis y */
1717: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
1718: draw_clip_line(x, y, x1, y1);
1719: term_apply_lp_properties(&border_lp);
1720: }
1721: if (xtics & TICS_ON_AXIS) {
1722: map3d_xy(place, (y_min3d + y_max3d) / 2, base_z, &x, &y);
1723: }
1724: x1 = x + tic_unitx * scale * (t->h_tic) * dirn;
1725: y1 = y + tic_unity * scale * (t->v_tic) * dirn;
1726: draw_clip_line(x, y, x1, y1);
1727: if (text) {
1728: int just;
1729: if (tic_unitx < -0.9)
1730: just = LEFT;
1731: else if (tic_unitx < 0.9)
1732: just = CENTRE;
1733: else
1734: just = RIGHT;
1735: #if 1
1736: /* HBB 970729: let's see if the 'tic labels collide with axes' problem
1737: * may be fixed this way: */
1738: x1 = x - tic_unitx * (t->h_char) * 1;
1739: y1 = y - tic_unity * (t->v_char) * 1;
1740: #else
1741: x1 = x - tic_unitx * (t->h_tic) * 2;
1742: y1 = y - tic_unity * (t->v_tic) * 2;
1743: #endif
1744: if (!tic_in) {
1745: x1 -= tic_unitx * (t->h_tic) * ticscale;
1746: y1 -= tic_unity * (t->v_tic) * ticscale;
1747: }
1748: clip_put_text_just(x1, y1, text, just);
1749: }
1750: if (xtics & TICS_MIRROR) {
1751: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x, &y);
1752: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
1753: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
1754: draw_clip_line(x, y, x1, y1);
1755: }
1756: }
1757:
1.1.1.3 ! ohara 1758: void ytick_callback(axis, place, text, grid)
1.1 maekawa 1759: int axis;
1760: double place;
1761: char *text;
1762: struct lp_style_type grid;
1763: {
1764: unsigned int x, y, x1, y1;
1765: double scale = (text ? ticscale : miniticscale);
1766: int dirn = tic_in ? 1 : -1;
1767: register struct termentry *t = term;
1768:
1769: map3d_xy(yaxis_x, place, base_z, &x, &y);
1770: if (grid.l_type > -2) {
1771: term_apply_lp_properties(&grid);
1772: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x1, &y1);
1773: draw_clip_line(x, y, x1, y1);
1774: term_apply_lp_properties(&border_lp);
1775: }
1776: if (ytics & TICS_ON_AXIS) {
1777: map3d_xy((x_min3d + x_max3d) / 2, place, base_z, &x, &y);
1778: }
1779: x1 = x + tic_unitx * scale * dirn * (t->h_tic);
1780: y1 = y + tic_unity * scale * dirn * (t->v_tic);
1781: draw_clip_line(x, y, x1, y1);
1782: if (text) {
1783: int just;
1784: if (tic_unitx < -0.9)
1785: just = LEFT;
1786: else if (tic_unitx < 0.9)
1787: just = CENTRE;
1788: else
1789: just = RIGHT;
1790: #if 1
1791: /* HBB 970729: same as above in xtics_callback */
1792: x1 = x - tic_unitx * (t->h_char) * 1;
1793: y1 = y - tic_unity * (t->v_char) * 1;
1794: #else
1795: x1 = x - tic_unitx * (t->h_tic) * 2;
1796: y1 = y - tic_unity * (t->v_tic) * 2;
1797: #endif
1798: if (!tic_in) {
1799: x1 -= tic_unitx * (t->h_tic) * ticscale;
1800: y1 -= tic_unity * (t->v_tic) * ticscale;
1801: }
1802: clip_put_text_just(x1, y1, text, just);
1803: }
1804: if (ytics & TICS_MIRROR) {
1805: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x, &y);
1806: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
1807: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
1808: draw_clip_line(x, y, x1, y1);
1809: }
1810: }
1811:
1.1.1.3 ! ohara 1812: void ztick_callback(axis, place, text, grid)
1.1 maekawa 1813: int axis;
1814: double place;
1815: char *text;
1816: struct lp_style_type grid;
1817: {
1818: /* HBB: inserted some ()'s to shut up gcc -Wall, here and below */
1819: int len = (text ? ticscale : miniticscale) * (tic_in ? 1 : -1) * (term->h_tic);
1820: unsigned int x, y;
1821:
1822: if (grid.l_type > -2) {
1823: unsigned int x1, y1, x2, y2, x3, y3;
1824: double other_x = x_min3d + x_max3d - zaxis_x;
1825: double other_y = y_min3d + y_max3d - zaxis_y;
1826: term_apply_lp_properties(&grid);
1827: map3d_xy(zaxis_x, zaxis_y, place, &x1, &y1);
1828: map3d_xy(back_x, back_y, place, &x2, &y2);
1829: map3d_xy(other_x, other_y, place, &x3, &y3);
1830: draw_clip_line(x1, y1, x2, y2);
1831: draw_clip_line(x2, y2, x3, y3);
1832: term_apply_lp_properties(&border_lp);
1833: }
1834: map3d_xy(zaxis_x, zaxis_y, place, &x, &y);
1835: draw_clip_line(x, y, x + len, y);
1836: if (text) {
1837: int x1 = x - (term->h_tic) * 2;
1838: if (!tic_in)
1839: x1 -= (term->h_tic) * ticscale;
1840: clip_put_text_just(x1, y, text, RIGHT);
1841: }
1842: if (ztics & TICS_MIRROR) {
1843: double other_x = x_min3d + x_max3d - zaxis_x;
1844: double other_y = y_min3d + y_max3d - zaxis_y;
1845: map3d_xy(other_x, other_y, place, &x, &y);
1846: draw_clip_line(x, y, x - len, y);
1847: }
1848: }
1849:
1850:
1851: static void map_position(pos, x, y, what)
1852: struct position *pos;
1853: unsigned int *x, *y;
1854: char *what;
1855: {
1856: double xpos = pos->x;
1857: double ypos = pos->y;
1858: double zpos = pos->z;
1859: int screens = 0; /* need either 0 or 3 screen co-ordinates */
1860:
1861: switch (pos->scalex) {
1862: case first_axes:
1863: case second_axes:
1864: xpos = LogScale(xpos, is_log_x, log_base_log_x, what, "x");
1865: break;
1866: case graph:
1867: xpos = min_array[FIRST_X_AXIS] +
1868: xpos * (max_array[FIRST_X_AXIS] - min_array[FIRST_X_AXIS]);
1869: break;
1870: case screen:
1871: ++screens;
1872: }
1873:
1874: switch (pos->scaley) {
1875: case first_axes:
1876: case second_axes:
1877: ypos = LogScale(ypos, is_log_y, log_base_log_y, what, "y");
1878: break;
1879: case graph:
1880: ypos = min_array[FIRST_Y_AXIS] +
1881: ypos * (max_array[FIRST_Y_AXIS] - min_array[FIRST_Y_AXIS]);
1882: break;
1883: case screen:
1884: ++screens;
1885: }
1886:
1887: switch (pos->scalez) {
1888: case first_axes:
1889: case second_axes:
1890: zpos = LogScale(zpos, is_log_z, log_base_log_z, what, "z");
1891: break;
1892: case graph:
1893: zpos = min_array[FIRST_Z_AXIS] +
1894: zpos * (max_array[FIRST_Z_AXIS] - min_array[FIRST_Z_AXIS]);
1895: break;
1896: case screen:
1897: ++screens;
1898: }
1899:
1900: if (screens == 0) {
1901: map3d_xy(xpos, ypos, zpos, x, y);
1902: return;
1903: }
1904: if (screens != 3) {
1905: graph_error("Cannot mix screen co-ordinates with other types");
1906: } {
1907: register struct termentry *t = term;
1.1.1.3 ! ohara 1908: /* HBB 20000914: off-by-one bug. Maximum allowed output is
! 1909: * t->?max - 1, not t->?max itself! */
! 1910: *x = pos->x * (t->xmax -1) + 0.5;
! 1911: *y = pos->y * (t->ymax -1) + 0.5;
1.1 maekawa 1912: }
1913:
1914: return;
1915: }
1916:
1917:
1918: /*
1919: * these code blocks were moved to functions, to make the code simpler
1920: */
1921:
1922: static void key_text(xl, yl, text)
1923: int xl, yl;
1924: char *text;
1925: {
1926: if (key_just == JLEFT && key == -1) {
1927: (*term->justify_text) (LEFT);
1928: (*term->put_text) (xl + key_text_left, yl, text);
1929: } else {
1930: if ((*term->justify_text) (RIGHT)) {
1931: if (key == 1)
1932: clip_put_text(xl + key_text_right, yl, text);
1933: else
1934: (*term->put_text) (xl + key_text_right, yl, text);
1935: } else {
1936: int x = xl + key_text_right - (term->h_char) * strlen(text);
1937: if (key == 1) {
1938: if (i_inrange(x, xleft, xright))
1939: clip_put_text(x, yl, text);
1940: } else {
1941: (*term->put_text) (x, yl, text);
1942: }
1943: }
1944: }
1945: }
1946:
1947: static void key_sample_line(xl, yl)
1948: int xl, yl;
1949: {
1950: if (key == -1) {
1951: (*term->move) (xl + key_sample_left, yl);
1952: (*term->vector) (xl + key_sample_right, yl);
1953: } else {
1954: /* HBB 981118: avoid crash if hidden3d sees a manually placed key:
1955: * simply turn off hidden-lining while we're drawing the key line: */
1956: int save_hidden_active = hidden_active;
1957: hidden_active = FALSE;
1958:
1959: clip_move(xl + key_sample_left, yl);
1960: clip_vector(xl + key_sample_right, yl);
1961: hidden_active = save_hidden_active;
1962: }
1963: }
1964:
1965: static void key_sample_point(xl, yl, pointtype)
1966: int xl, yl;
1967: int pointtype;
1968: {
1.1.1.3 ! ohara 1969: /* HBB 20000412: fixed incorrect clipping: the point sample was
! 1970: * clipped against the graph box, even if in 'below' or 'outside'
! 1971: * position. But the result of that clipping was utterly ignored,
! 1972: * because the 'else' part did exactly the same thing as the
! 1973: * 'then' one. Some callers of this routine thus did their own
! 1974: * clipping, which I removed, along with this change.
! 1975: *
! 1976: * Now, all 'automatically' placed cases will never be clipped,
! 1977: * only user-specified ones. */
! 1978: if ((key == -1) /* ==-1 means auto-placed key */
! 1979: || !clip_point(xl + key_point_offset, yl)) {
1.1 maekawa 1980: (*term->point) (xl + key_point_offset, yl, pointtype);
1981: }
1982: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>