Annotation of OpenXM_contrib/gnuplot/graph3d.c, Revision 1.1.1.2
1.1 maekawa 1: #ifndef lint
1.1.1.2 ! maekawa 2: static char *RCSid = "$Id: graph3d.c,v 1.13.2.4 1999/10/19 13:31:49 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));
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) {
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;
420: if (key_rows && key_vpos == TUNDER)
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:
1.1.1.2 ! maekawa 512: #if 0
! 513: /* HBB 19990609: this is *not* the way to implement 'set view' <z_scale> */
1.1 maekawa 514: /* modify min_z/max_z so it will zscale properly. */
515: ztemp = (z_max3d - z_min3d) / (2.0 * surface_zscale);
516: temp = (z_max3d + z_min3d) / 2.0;
517: z_min3d = temp - ztemp;
518: z_max3d = temp + ztemp;
1.1.1.2 ! maekawa 519: #endif /* 0 */
1.1 maekawa 520:
521: /* The extrema need to be set even when a surface is not being
522: * drawn. Without this, gnuplot used to assume that the X and
523: * Y axis started at zero. -RKC
524: */
525:
526: if (polar)
527: graph_error("Cannot splot in polar coordinate system.");
528:
529: /* done in plot3d.c
530: * if (z_min3d == VERYLARGE || z_max3d == -VERYLARGE ||
531: * x_min3d == VERYLARGE || x_max3d == -VERYLARGE ||
532: * y_min3d == VERYLARGE || y_max3d == -VERYLARGE)
533: * graph_error("all points undefined!");
534: */
535:
536: /* If we are to draw the bottom grid make sure zmin is updated properly. */
537: if (xtics || ytics || work_grid.l_type) {
538: base_z = z_min3d - (z_max3d - z_min3d) * ticslevel;
539: if (ticslevel >= 0)
540: floor_z = base_z;
541: else
542: floor_z = z_min3d;
543:
544: if (ticslevel < -1)
545: ceiling_z = base_z;
546: else
547: ceiling_z = z_max3d;
548: } else {
549: floor_z = base_z = z_min3d;
550: ceiling_z = z_max3d;
551: }
552:
553: /* see comment accompanying similar tests of x_min/x_max and y_min/y_max
554: * in graphics.c:do_plot(), for history/rationale of these tests */
555: if (x_min3d == x_max3d)
556: graph_error("x_min3d should not equal x_max3d!");
557: if (y_min3d == y_max3d)
558: graph_error("y_min3d should not equal y_max3d!");
559: if (z_min3d == z_max3d)
560: graph_error("z_min3d should not equal z_max3d!");
561:
562: #ifndef LITE
563: if (hidden3d) {
564: struct surface_points *plot;
565: int p = 0;
566: /* Verify data is hidden line removable - grid based. */
567: for (plot = plots; ++p <= pcount; plot = plot->next_sp) {
568: if (plot->plot_type == DATA3D && !plot->has_grid_topology) {
569: fprintf(stderr, "Notice: Cannot remove hidden lines from non grid data\n");
570: return;
571: }
572: }
573: }
574: #endif /* not LITE */
575:
576: term_start_plot();
577:
578: screen_ok = FALSE;
579: scaling = (*t->scale) (xsize, ysize);
580:
581: /* now compute boundary for plot (xleft, xright, ytop, ybot) */
582: boundary3d(scaling, plots, pcount);
583:
584: /* SCALE FACTORS */
1.1.1.2 ! maekawa 585: zscale3d = 2.0 / (ceiling_z - floor_z) * surface_zscale;
1.1 maekawa 586: yscale3d = 2.0 / (y_max3d - y_min3d);
587: xscale3d = 2.0 / (x_max3d - x_min3d);
588:
589: term_apply_lp_properties(&border_lp); /* border linetype */
590:
591: /* PLACE TITLE */
592: if (*title.text != 0) {
593: write_multiline((unsigned int) ((xleft + xright) / 2 + title.xoffset * t->h_char),
594: (unsigned int) (ytop + (titlelin + title.yoffset) * (t->h_char)),
1.1.1.2 ! maekawa 595: title.text, CENTRE, JUST_TOP, 0, title.font);
1.1 maekawa 596: }
597: /* PLACE TIMEDATE */
598: if (*timelabel.text) {
599: char str[MAX_LINE_LEN+1];
600: time_t now;
601: unsigned int x = t->v_char + timelabel.xoffset * t->h_char;
602: unsigned int y = timelabel_bottom ?
603: yoffset * ymax + (timelabel.yoffset + 1) * t->v_char :
604: ytop + (timelabel.yoffset - 1) * t->v_char;
605:
606: time(&now);
607: strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now));
608:
609: if (timelabel_rotate && (*t->text_angle) (1)) {
610: if (timelabel_bottom)
611: write_multiline(x, y, str, LEFT, JUST_TOP, 1, timelabel.font);
612: else
613: write_multiline(x, y, str, RIGHT, JUST_TOP, 1, timelabel.font);
614:
615: (*t->text_angle) (0);
616: } else {
617: if (timelabel_bottom)
618: write_multiline(x, y, str, LEFT, JUST_BOT, 0, timelabel.font);
619: else
620: write_multiline(x, y, str, LEFT, JUST_TOP, 0, timelabel.font);
621: }
622: }
623: /* PLACE LABELS */
624: for (this_label = first_label; this_label != NULL;
625: this_label = this_label->next) {
626: unsigned int x, y;
627:
628:
629: map_position(&this_label->place, &x, &y, "label");
630: if (this_label->rotate && (*t->text_angle) (1)) {
631: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 1, this_label->font);
632: (*t->text_angle) (0);
633: } else {
634: write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 0, this_label->font);
635: }
636: }
637:
638: /* PLACE ARROWS */
639: for (this_arrow = first_arrow; this_arrow != NULL;
640: this_arrow = this_arrow->next) {
641: unsigned int sx, sy, ex, ey;
642:
643: map_position(&this_arrow->start, &sx, &sy, "arrow");
644: map_position(&this_arrow->end, &ex, &ey, "arrow");
645: term_apply_lp_properties(&(this_arrow->lp_properties));
646: (*t->arrow) (sx, sy, ex, ey, this_arrow->head);
647: }
648:
649: #ifndef LITE
650: if (hidden3d && draw_surface) {
651: init_hidden_line_removal();
652: reset_hidden_line_removal();
653: hidden_active = TRUE;
654: }
655: #endif /* not LITE */
656:
657: /* WORK OUT KEY SETTINGS AND DO KEY TITLE / BOX */
658:
659: if (key_reverse) {
660: key_sample_left = -key_sample_width;
661: key_sample_right = 0;
662: key_text_left = t->h_char;
663: key_text_right = (t->h_char) * (max_ptitl_len + 1);
664: key_size_right = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
665: key_size_left = (t->h_char) + key_sample_width;
666: } else {
667: key_sample_left = 0;
668: key_sample_right = key_sample_width;
669: key_text_left = -(int) ((t->h_char) * (max_ptitl_len + 1));
670: key_text_right = -(int) (t->h_char);
671: key_size_left = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
672: key_size_right = (t->h_char) + key_sample_width;
673: }
674: key_point_offset = (key_sample_left + key_sample_right) / 2;
675:
676: if (key == -1) {
677: if (key_vpos == TUNDER) {
678: #if 0
679: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
680: xl = max_ptitl_len * 1000 / (key_sample_width / (t->h_char) + max_ptitl_len + 2);
681: xl *= (xright - xleft) / key_cols;
682: xl /= 1000;
683: xl += xleft;
684: #else
1.1.1.2 ! maekawa 685: /* HBB 19990608: why calculate these again? boundary3d has already
! 686: * done it... */
! 687: if (ptitl_cnt > 0) {
1.1 maekawa 688: /* maximise no cols, limited by label-length */
689: key_cols = (int) (xright - xleft) / key_col_wth;
690: key_rows = (int) (ptitl_cnt + key_cols - 1) / key_cols;
691: /* now calculate actual no cols depending on no rows */
692: key_cols = (int) (ptitl_cnt + key_rows - 1) / key_rows;
693: key_col_wth = (int) (xright - xleft) / key_cols;
694: /* we divide into columns, then centre in column by considering
695: * ratio of key_left_size to key_right_size
696: * key_size_left/(key_size_left+key_size_right) * (xright-xleft)/key_cols
697: * do one integer division to maximise accuracy (hope we dont
698: * overflow !)
699: */
700: xl = xleft + ((xright - xleft) * key_size_left) / (key_cols * (key_size_left + key_size_right));
701: yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
1.1.1.2 ! maekawa 702: }
1.1 maekawa 703: #endif
704: } else {
705: if (key_vpos == TTOP) {
706: yl = ytop - (t->v_tic) - t->v_char;
707: } else {
708: yl = ybot + (t->v_tic) + key_entry_height * key_rows + ktitle_lines * t->v_char;
709: }
710: if (key_hpos == TOUT) {
711: /* keys outside plot border (right) */
712: xl = xright + (t->h_tic) + key_size_left;
713: } else if (key_hpos == TLEFT) {
714: xl = xleft + (t->h_tic) + key_size_left;
715: } else {
716: xl = xright - key_size_right - key_col_wth * (key_cols - 1);
717: }
718: }
719: yl_ref = yl - ktitle_lines * (t->v_char);
720: }
721: if (key == 1) {
722: map_position(&key_user_pos, &xl, &yl, "key");
723: }
724: if (key && key_box.l_type > -3) {
725: int yt = yl;
726: int yb = yl - key_entry_height * (key_rows - ktitle_lines) - ktitle_lines * t->v_char;
727: int key_xr = xl + key_col_wth * (key_cols - 1) + key_size_right;
728: /* key_rows seems to contain title at this point ??? */
729: term_apply_lp_properties(&key_box);
730: (*t->move) (xl - key_size_left, yb);
731: (*t->vector) (xl - key_size_left, yt);
732: (*t->vector) (key_xr, yt);
733: (*t->vector) (key_xr, yb);
734: (*t->vector) (xl - key_size_left, yb);
735:
736: /* draw a horizontal line between key title and first entry JFi */
737: (*t->move) (xl - key_size_left, yt - (ktitle_lines) * t->v_char);
738: (*t->vector) (xl + key_size_right, yt - (ktitle_lines) * t->v_char);
739: }
740: /* DRAW SURFACES AND CONTOURS */
741:
742: #ifndef LITE
743: if (hidden3d && draw_surface)
744: plot3d_hidden(plots, pcount);
745: #endif /* not LITE */
746:
747: /* KEY TITLE */
748: if (key != 0 && strlen(key_title)) {
1.1.1.2 ! maekawa 749: char *ss = gp_alloc(strlen(key_title) + 2, "tmp string ss");
! 750: strcpy(ss, key_title);
! 751: strcat(ss, "\n");
1.1 maekawa 752: s = ss;
753: yl -= t->v_char / 2;
754: while ((e = (char *) strchr(s, '\n')) != NULL) {
755: *e = '\0';
756: if (key_just == JLEFT) {
757: (*t->justify_text) (LEFT);
758: (*t->put_text) (xl + key_text_left, yl, s);
759: } else {
760: if ((*t->justify_text) (RIGHT)) {
761: (*t->put_text) (xl + key_text_right,
762: yl, s);
763: } else {
764: int x = xl + key_text_right - (t->h_char) * strlen(s);
765: if (inrange(x, xleft, xright))
766: (*t->put_text) (x, yl, s);
767: }
768: }
769: s = ++e;
770: yl -= t->v_char;
771: }
772: yl += t->v_char / 2;
1.1.1.2 ! maekawa 773: free(ss);
1.1 maekawa 774: }
775: key_count = 0;
776: yl_ref = yl -= key_entry_height / 2; /* centralise the keys */
777:
778: #define NEXT_KEY_LINE() \
779: if ( ++key_count >= key_rows ) { \
780: yl = yl_ref; xl += key_col_wth; key_count = 0; \
781: } else \
782: yl -= key_entry_height
783:
784: this_plot = plots;
785: for (surface = 0;
786: surface < pcount;
787: this_plot = this_plot->next_sp, surface++) {
788:
789: #ifndef LITE
790: if (hidden3d)
791: hidden_no_update = FALSE;
792: #endif /* not LITE */
793:
794: if (draw_surface) {
795: int lkey = (key != 0 && this_plot->title && this_plot->title[0]);
796: term_apply_lp_properties(&(this_plot->lp_properties));
797:
798: #ifndef LITE
799: if (hidden3d) {
800: hidden_line_type_above = this_plot->lp_properties.l_type;
801: hidden_line_type_below = this_plot->lp_properties.l_type + 1;
802: }
803: #endif /* not LITE */
804:
805: if (lkey) {
806: key_text(xl, yl, this_plot->title);
807: }
808: switch (this_plot->plot_style) {
809: case BOXES: /* can't do boxes in 3d yet so use impulses */
810: case IMPULSES:{
811: if (lkey) {
812: key_sample_line(xl, yl);
813: }
814: if (!(hidden3d && draw_surface))
815: plot3d_impulses(this_plot);
816: break;
817: }
818: case STEPS: /* HBB: I think these should be here */
819: case FSTEPS:
820: case HISTEPS:
821: case LINES:{
822: if (lkey) {
823: key_sample_line(xl, yl);
824: }
825: if (!(hidden3d && draw_surface))
826: plot3d_lines(this_plot);
827: break;
828: }
829: case YERRORBARS: /* ignored; treat like points */
830: case XERRORBARS: /* ignored; treat like points */
831: case XYERRORBARS: /* ignored; treat like points */
832: case BOXXYERROR: /* HBB: ignore these as well */
833: case BOXERROR:
834: case CANDLESTICKS: /* HBB: dito */
835: case FINANCEBARS:
836: case VECTOR:
837: case POINTSTYLE:
838: if (lkey && !clip_point(xl + key_point_offset, yl)) {
839: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
840: }
841: if (!(hidden3d && draw_surface))
842: plot3d_points(this_plot);
843: break;
844:
845: case LINESPOINTS:
846: /* put lines */
847: if (lkey)
848: key_sample_line(xl, yl);
849:
850: if (!(hidden3d && draw_surface))
851: plot3d_lines(this_plot);
852:
853: /* put points */
854: if (lkey && !clip_point(xl + key_point_offset, yl))
855: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
856:
857: if (!(hidden3d && draw_surface))
858: plot3d_points(this_plot);
859:
860: break;
861:
862: case DOTS:
863: if (lkey) {
864: if (key == 1) {
865: if (!clip_point(xl + key_point_offset, yl))
866: (*t->point) (xl + key_point_offset, yl, -1);
867: } else {
868: (*t->point) (xl + key_point_offset, yl, -1);
869: /* (*t->point)(xl+2*(t->h_char),yl, -1); */
870: }
871: }
872: if (!(hidden3d && draw_surface))
873: plot3d_dots(this_plot);
874:
875: break;
876:
877:
878: } /* switch(plot-style) */
879:
880: /* move key on a line */
881: if (lkey) {
882: NEXT_KEY_LINE();
883: }
884: } /* draw_surface */
885:
886: #ifndef LITE
887: if (hidden3d) {
888: hidden_no_update = TRUE;
889: hidden_line_type_above = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
890: hidden_line_type_below = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
891: }
892: #endif /* not LITE */
893:
894: if (draw_contour && this_plot->contours != NULL) {
895: struct gnuplot_contours *cntrs = this_plot->contours;
896:
897: term_apply_lp_properties(&(this_plot->lp_properties));
898: (*t->linetype) (this_plot->lp_properties.l_type + (hidden3d ? 2 : 1));
899:
900: if (key != 0 && this_plot->title && this_plot->title[0]
901: && !draw_surface && !label_contours) {
902: /* unlabelled contours but no surface : put key entry in now */
903: key_text(xl, yl, this_plot->title);
904:
905: switch (this_plot->plot_style) {
906: case IMPULSES:
907: case LINES:
908: case BOXES: /* HBB: I think these should be here... */
909: case STEPS:
910: case FSTEPS:
911: case HISTEPS:
912: key_sample_line(xl, yl);
913: break;
914: case YERRORBARS: /* ignored; treat like points */
915: case XERRORBARS: /* ignored; treat like points */
916: case XYERRORBARS: /* ignored; treat like points */
917: case BOXERROR: /* HBB: ignore these as well */
918: case BOXXYERROR:
919: case CANDLESTICKS: /* HBB: dito */
920: case FINANCEBARS:
921: case VECTOR:
922: case POINTSTYLE:
923: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
924: break;
925: case LINESPOINTS:
926: key_sample_line(xl, yl);
927: break;
928: case DOTS:
929: key_sample_point(xl, yl, -1);
930: break;
931: }
932: NEXT_KEY_LINE();
933: }
934: linetypeOffset = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
935: while (cntrs) {
936: if (label_contours && cntrs->isNewLevel) {
937: (*t->linetype) (linetypeOffset++);
938: if (key) {
939:
940: #ifndef LITE
941: if (hidden3d)
942: hidden_line_type_below = hidden_line_type_above = linetypeOffset - 1;
943: #endif /* not LITE */
944:
945: key_text(xl, yl, cntrs->label);
946:
947: switch (this_plot->plot_style) {
948: case IMPULSES:
949: case LINES:
950: case LINESPOINTS:
951: case BOXES: /* HBB: these should be treated as well... */
952: case STEPS:
953: case FSTEPS:
954: case HISTEPS:
955: key_sample_line(xl, yl);
956: break;
957: case YERRORBARS: /* ignored; treat like points */
958: case XERRORBARS: /* ignored; treat like points */
959: case XYERRORBARS: /* ignored; treat like points */
960: case BOXERROR: /* HBB: treat these likewise */
961: case BOXXYERROR:
962: case CANDLESTICKS: /* HBB: dito */
963: case FINANCEBARS:
964: case VECTOR:
965: case POINTSTYLE:
966: key_sample_point(xl, yl, this_plot->lp_properties.p_type);
967: break;
968: case DOTS:
969: key_sample_point(xl, yl, -1);
970: break;
971: } /* switch */
972:
973: NEXT_KEY_LINE();
974:
975: } /* key */
976: } /* label_contours */
977: /* now draw the contour */
978: switch (this_plot->plot_style) {
979: case IMPULSES:
980: case BOXES: /* HBB: this should also be treated somehow */
981: cntr3d_impulses(cntrs, this_plot);
982: break;
983: case LINES:
984: case STEPS: /* HBB: these should also be handled, I think */
985: case FSTEPS:
986: case HISTEPS:
987: cntr3d_lines(cntrs);
988: break;
989: case YERRORBARS: /* ignored; treat like points */
990: case XERRORBARS: /* ignored; treat like points */
991: case XYERRORBARS: /* ignored; treat like points */
992: case BOXERROR: /* HBB: ignore these too... */
993: case BOXXYERROR:
994: case CANDLESTICKS: /* HBB: dito */
995: case FINANCEBARS:
996: case VECTOR:
997: case POINTSTYLE:
998: cntr3d_points(cntrs, this_plot);
999: break;
1000: case LINESPOINTS:
1001: cntr3d_lines(cntrs);
1002: cntr3d_points(cntrs, this_plot);
1003: break;
1004: case DOTS:
1005: cntr3d_dots(cntrs);
1006: break;
1007: } /*switch */
1008:
1009: cntrs = cntrs->next;
1010: } /* loop over contours */
1011: } /* draw contours */
1012: } /* loop over surfaces */
1013:
1014: draw_bottom_grid(plots, pcount);
1015:
1016: term_end_plot();
1017:
1018: #ifndef LITE
1019: if (hidden3d && draw_surface) {
1020: term_hidden_line_removal();
1021: hidden_active = FALSE;
1022: }
1023: #endif /* not LITE */
1024:
1025: }
1026:
1027: /* plot3d_impulses:
1028: * Plot the surfaces in IMPULSES style
1029: */
1030: static void plot3d_impulses(plot)
1031: struct surface_points *plot;
1032: {
1033: int i; /* point index */
1034: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1035: struct iso_curve *icrvs = plot->iso_crvs;
1036:
1037: while (icrvs) {
1038: struct coordinate GPHUGE *points = icrvs->points;
1039:
1040: for (i = 0; i < icrvs->p_count; i++) {
1041: switch (points[i].type) {
1042: case INRANGE:
1043: {
1044: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1045:
1046: if (inrange(0.0, min3d_z, max3d_z)) {
1047: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
1048: } else if (inrange(min3d_z, 0.0, points[i].z)) {
1049: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
1050: } else {
1051: map3d_xy(points[i].x, points[i].y, max3d_z, &x0, &y0);
1052: }
1053:
1054: clip_move(x0, y0);
1055: clip_vector(x, y);
1056:
1057: break;
1058: }
1059: case OUTRANGE:
1060: {
1061: if (!inrange(points[i].x, x_min3d, x_max3d) ||
1062: !inrange(points[i].y, y_min3d, y_max3d))
1063: break;
1064:
1065: if (inrange(0.0, min3d_z, max3d_z)) {
1066: /* zero point is INRANGE */
1067: map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
1068:
1069: /* must cross z = min3d_z or max3d_z limits */
1070: if (inrange(min3d_z, 0.0, points[i].z) &&
1071: min3d_z != 0.0 && min3d_z != points[i].z) {
1072: map3d_xy(points[i].x, points[i].y, min3d_z, &x, &y);
1073: } else {
1074: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
1075: }
1076: } else {
1077: /* zero point is also OUTRANGE */
1078: if (inrange(min3d_z, 0.0, points[i].z) &&
1079: inrange(max3d_z, 0.0, points[i].z)) {
1080: /* crosses z = min3d_z or max3d_z limits */
1081: map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
1082: map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
1083: } else {
1084: /* doesn't cross z = min3d_z or max3d_z limits */
1085: break;
1086: }
1087: }
1088:
1089: clip_move(x0, y0);
1090: clip_vector(x, y);
1091:
1092: break;
1093: }
1094: default: /* just a safety */
1095: case UNDEFINED:{
1096: break;
1097: }
1098: }
1099: }
1100:
1101: icrvs = icrvs->next;
1102: }
1103: }
1104:
1105: /* plot3d_lines:
1106: * Plot the surfaces in LINES style
1107: */
1108: /* We want to always draw the lines in the same direction, otherwise when
1109: we draw an adjacent box we might get the line drawn a little differently
1110: and we get splotches. */
1111:
1112: static void plot3d_lines(plot)
1113: struct surface_points *plot;
1114: {
1115: int i;
1116: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1117: double clip_x, clip_y, clip_z;
1118: struct iso_curve *icrvs = plot->iso_crvs;
1119: struct coordinate GPHUGE *points;
1120: enum coord_type prev = UNDEFINED;
1121: double lx[2], ly[2], lz[2]; /* two edge points */
1122:
1123: #ifndef LITE
1124: /* These are handled elsewhere. */
1125: if (plot->has_grid_topology && hidden3d)
1126: return;
1127: #endif /* not LITE */
1128:
1129: while (icrvs) {
1130: prev = UNDEFINED; /* type of previous plot */
1131:
1132: for (i = 0, points = icrvs->points; i < icrvs->p_count; i++) {
1133: switch (points[i].type) {
1134: case INRANGE:{
1135: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1136:
1137: if (prev == INRANGE) {
1138: clip_vector(x, y);
1139: } else {
1140: if (prev == OUTRANGE) {
1141: /* from outrange to inrange */
1142: if (!clip_lines1) {
1143: clip_move(x, y);
1144: } else {
1145: /*
1146: * Calculate intersection point and draw
1147: * vector from there
1148: */
1149: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
1150:
1151: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
1152:
1153: clip_move(x0, y0);
1154: clip_vector(x, y);
1155: }
1156: } else {
1157: clip_move(x, y);
1158: }
1159: }
1160:
1161: break;
1162: }
1163: case OUTRANGE:{
1164: if (prev == INRANGE) {
1165: /* from inrange to outrange */
1166: if (clip_lines1) {
1167: /*
1168: * Calculate intersection point and draw
1169: * vector to it
1170: */
1171:
1172: edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
1173:
1174: map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
1175:
1176: clip_vector(x0, y0);
1177: }
1178: } else if (prev == OUTRANGE) {
1179: /* from outrange to outrange */
1180: if (clip_lines2) {
1181: /*
1182: * Calculate the two 3D intersection points
1183: * if present
1184: */
1185: if (two_edge3d_intersect(points, i, lx, ly, lz)) {
1186:
1187: map3d_xy(lx[0], ly[0], lz[0], &x, &y);
1188:
1189: map3d_xy(lx[1], ly[1], lz[1], &x0, &y0);
1190:
1191: clip_move(x, y);
1192: clip_vector(x0, y0);
1193: }
1194: }
1195: }
1196: break;
1197: }
1198: case UNDEFINED:{
1199: break;
1200: default:
1201: graph_error("Unknown point type in plot3d_lines");
1202: }
1203: }
1204:
1205: prev = points[i].type;
1206: }
1207:
1208: icrvs = icrvs->next;
1209: }
1210: }
1211:
1212: /* plot3d_points:
1213: * Plot the surfaces in POINTSTYLE style
1214: */
1215: static void plot3d_points(plot)
1216: struct surface_points *plot;
1217: {
1218: int i;
1219: unsigned int x, y;
1220: struct termentry *t = term;
1221: struct iso_curve *icrvs = plot->iso_crvs;
1222:
1223: while (icrvs) {
1224: struct coordinate GPHUGE *points = icrvs->points;
1225:
1226: for (i = 0; i < icrvs->p_count; i++) {
1227: if (points[i].type == INRANGE) {
1228: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1229:
1230: if (!clip_point(x, y))
1231: (*t->point) (x, y, plot->lp_properties.p_type);
1232: }
1233: }
1234:
1235: icrvs = icrvs->next;
1236: }
1237: }
1238:
1239: /* plot3d_dots:
1240: * Plot the surfaces in DOTS style
1241: */
1242: static void plot3d_dots(plot)
1243: struct surface_points *plot;
1244: {
1245: int i;
1246: struct termentry *t = term;
1247: struct iso_curve *icrvs = plot->iso_crvs;
1248:
1249: while (icrvs) {
1250: struct coordinate GPHUGE *points = icrvs->points;
1251:
1252: for (i = 0; i < icrvs->p_count; i++) {
1253: if (points[i].type == INRANGE) {
1254: unsigned int x, y;
1255: map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
1256:
1257: if (!clip_point(x, y))
1258: (*t->point) (x, y, -1);
1259: }
1260: }
1261:
1262: icrvs = icrvs->next;
1263: }
1264: }
1265:
1266: /* cntr3d_impulses:
1267: * Plot a surface contour in IMPULSES style
1268: */
1269: static void cntr3d_impulses(cntr, plot)
1270: struct gnuplot_contours *cntr;
1271: struct surface_points *plot;
1272: {
1273: int i; /* point index */
1274: unsigned int x, y, x0, y0; /* point in terminal coordinates */
1275:
1276: if (draw_contour & CONTOUR_SRF) {
1277: for (i = 0; i < cntr->num_pts; i++) {
1278: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
1279: &x, &y);
1280: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1281: &x0, &y0);
1282:
1283: clip_move(x0, y0);
1284: clip_vector(x, y);
1285: }
1286: } else {
1287: /* Must be on base grid, so do points. */
1288: cntr3d_points(cntr, plot);
1289: }
1290: }
1291:
1292: /* cntr3d_lines:
1293: * Plot a surface contour in LINES style
1294: */
1295: static void cntr3d_lines(cntr)
1296: struct gnuplot_contours *cntr;
1297: {
1298: int i; /* point index */
1299: unsigned int x, y; /* point in terminal coordinates */
1300:
1301: if (draw_contour & CONTOUR_SRF) {
1302: for (i = 0; i < cntr->num_pts; i++) {
1303: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
1304: &x, &y);
1305:
1306: if (i > 0) {
1307: clip_vector(x, y);
1308: if (i == 1)
1309: suppressMove = TRUE;
1310: } else {
1311: clip_move(x, y);
1312: }
1313: }
1314: }
1315: /* beginning a new contour level, so moveto() required */
1316: suppressMove = FALSE;
1317:
1318: if (draw_contour & CONTOUR_BASE) {
1319: for (i = 0; i < cntr->num_pts; i++) {
1320: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1321: &x, &y);
1322:
1323: if (i > 0) {
1324: clip_vector(x, y);
1325: if (i == 1)
1326: suppressMove = TRUE;
1327: } else {
1328: clip_move(x, y);
1329: }
1330: }
1331: }
1332: /* beginning a new contour level, so moveto() required */
1333: suppressMove = FALSE;
1334: }
1335:
1336: /* cntr3d_points:
1337: * Plot a surface contour in POINTSTYLE style
1338: */
1339: static void cntr3d_points(cntr, plot)
1340: struct gnuplot_contours *cntr;
1341: struct surface_points *plot;
1342: {
1343: int i;
1344: unsigned int x, y;
1345: struct termentry *t = term;
1346:
1347: if (draw_contour & CONTOUR_SRF) {
1348: for (i = 0; i < cntr->num_pts; i++) {
1349: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
1350:
1351: if (!clip_point(x, y))
1352: (*t->point) (x, y, plot->lp_properties.p_type);
1353: }
1354: }
1355: if (draw_contour & CONTOUR_BASE) {
1356: for (i = 0; i < cntr->num_pts; i++) {
1357: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1358: &x, &y);
1359:
1360: if (!clip_point(x, y))
1361: (*t->point) (x, y, plot->lp_properties.p_type);
1362: }
1363: }
1364: }
1365:
1366: /* cntr3d_dots:
1367: * Plot a surface contour in DOTS style
1368: */
1369: static void cntr3d_dots(cntr)
1370: struct gnuplot_contours *cntr;
1371: {
1372: int i;
1373: unsigned int x, y;
1374: struct termentry *t = term;
1375:
1376: if (draw_contour & CONTOUR_SRF) {
1377: for (i = 0; i < cntr->num_pts; i++) {
1378: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z, &x, &y);
1379:
1380: if (!clip_point(x, y))
1381: (*t->point) (x, y, -1);
1382: }
1383: }
1384: if (draw_contour & CONTOUR_BASE) {
1385: for (i = 0; i < cntr->num_pts; i++) {
1386: map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
1387: &x, &y);
1388:
1389: if (!clip_point(x, y))
1390: (*t->point) (x, y, -1);
1391: }
1392: }
1393: }
1394:
1395:
1396:
1397: /* map xmin | xmax to 0 | 1 and same for y
1398: * 0.1 avoids any rounding errors
1399: */
1400: #define MAP_HEIGHT_X(x) ( (int) (((x)-x_min3d)/(x_max3d-x_min3d)+0.1) )
1401: #define MAP_HEIGHT_Y(y) ( (int) (((y)-y_min3d)/(y_max3d-y_min3d)+0.1) )
1402:
1403: /* if point is at corner, update height[][] and depth[][]
1404: * we are still assuming that extremes of surfaces are at corners,
1405: * but we are not assuming order of corners
1406: */
1407: static void check_corner_height(p, height, depth)
1408: struct coordinate GPHUGE *p;
1409: double height[2][2];
1410: double depth[2][2];
1411: {
1412: if (p->type != INRANGE)
1413: return;
1414: if ((fabs(p->x - x_min3d) < zero || fabs(p->x - x_max3d) < zero) &&
1415: (fabs(p->y - y_min3d) < zero || fabs(p->y - y_max3d) < zero)) {
1416: unsigned int x = MAP_HEIGHT_X(p->x);
1417: unsigned int y = MAP_HEIGHT_Y(p->y);
1418: if (height[x][y] < p->z)
1419: height[x][y] = p->z;
1420: if (depth[x][y] > p->z)
1421: depth[x][y] = p->z;
1422: }
1423: }
1424:
1425:
1426: /* Draw the bottom grid that hold the tic marks for 3d surface. */
1427: static void draw_bottom_grid(plot, plot_num)
1428: struct surface_points *plot;
1429: int plot_num;
1430: {
1431: unsigned int x, y; /* point in terminal coordinates */
1432: struct termentry *t = term;
1433: char ss[MAX_LINE_LEN+1];
1434:
1435: /* work out where the axes and tics are drawn */
1436:
1437: {
1438: int quadrant = surface_rot_z / 90;
1439: if ((quadrant + 1) & 2) {
1440: zaxis_x = x_max3d;
1441: xaxis_y = y_max3d;
1442: } else {
1443: zaxis_x = x_min3d;
1444: xaxis_y = y_min3d;
1445: }
1446:
1447: if (quadrant & 2) {
1448: zaxis_y = y_max3d;
1449: yaxis_x = x_min3d;
1450: } else {
1451: zaxis_y = y_min3d;
1452: yaxis_x = x_max3d;
1453: }
1454:
1455: if (surface_rot_x > 90) {
1456: /* labels on the back axes */
1457: back_x = yaxis_x = x_min3d + x_max3d - yaxis_x;
1458: back_y = xaxis_y = y_min3d + y_max3d - xaxis_y;
1459: } else {
1460: back_x = x_min3d + x_max3d - yaxis_x;
1461: back_y = y_min3d + y_max3d - xaxis_y;
1462: }
1463: }
1464:
1465: if (draw_border) {
1466: unsigned int bl_x, bl_y; /* bottom left */
1467: unsigned int bb_x, bb_y; /* bottom back */
1468: unsigned int br_x, br_y; /* bottom right */
1469: unsigned int bf_x, bf_y; /* bottom front */
1470:
1471: #ifndef LITE
1472: int save_update = hidden_no_update;
1473: hidden_no_update = TRUE;
1474: #endif /* LITE */
1475:
1476: /* Here is the one and only call to this function. */
1477: setlinestyle(border_lp);
1478:
1479: map3d_xy(zaxis_x, zaxis_y, base_z, &bl_x, &bl_y);
1480: map3d_xy(back_x, back_y, base_z, &bb_x, &bb_y);
1481: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, base_z, &br_x, &br_y);
1482: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, base_z, &bf_x, &bf_y);
1483:
1484: /* border around base */
1485: {
1486: int save = hidden_active;
1487: hidden_active = FALSE; /* this is in front */
1488: if (draw_border & 4)
1489: draw_clip_line(br_x, br_y, bf_x, bf_y);
1490: if (draw_border & 1)
1491: draw_clip_line(bl_x, bl_y, bf_x, bf_y);
1492: hidden_active = save;
1493: }
1494: if (draw_border & 2)
1495: draw_clip_line(bl_x, bl_y, bb_x, bb_y);
1496: if (draw_border & 8)
1497: draw_clip_line(br_x, br_y, bb_x, bb_y);
1498:
1499: if (draw_surface || (draw_contour & CONTOUR_SRF)) {
1500: int save = hidden_active;
1501: /* map the 8 corners to screen */
1502: unsigned int fl_x, fl_y; /* floor left */
1503: unsigned int fb_x, fb_y; /* floor back */
1504: unsigned int fr_x, fr_y; /* floor right */
1505: unsigned int ff_x, ff_y; /* floor front */
1506:
1507: unsigned int tl_x, tl_y; /* top left */
1508: unsigned int tb_x, tb_y; /* top back */
1509: unsigned int tr_x, tr_y; /* top right */
1510: unsigned int tf_x, tf_y; /* top front */
1511:
1512: map3d_xy(zaxis_x, zaxis_y, floor_z, &fl_x, &fl_y);
1513: map3d_xy(back_x, back_y, floor_z, &fb_x, &fb_y);
1514: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, floor_z, &fr_x, &fr_y);
1515: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, floor_z, &ff_x, &ff_y);
1516:
1517: map3d_xy(zaxis_x, zaxis_y, ceiling_z, &tl_x, &tl_y);
1518: map3d_xy(back_x, back_y, ceiling_z, &tb_x, &tb_y);
1519: map3d_xy(x_min3d + x_max3d - zaxis_x, y_min3d + y_max3d - zaxis_y, ceiling_z, &tr_x, &tr_y);
1520: map3d_xy(x_min3d + x_max3d - back_x, y_min3d + y_max3d - back_y, ceiling_z, &tf_x, &tf_y);
1521:
1522: /* vertical lines, to surface or to very top */
1523: if ((draw_border & 0xf0) == 0xf0) {
1524: /* all four verticals drawn - save some time */
1525: draw_clip_line(fl_x, fl_y, tl_x, tl_y);
1526: draw_clip_line(fb_x, fb_y, tb_x, tb_y);
1527: draw_clip_line(fr_x, fr_y, tr_x, tr_y);
1528: hidden_active = FALSE; /* this is in front */
1529: draw_clip_line(ff_x, ff_y, tf_x, tf_y);
1530: hidden_active = save;
1531: } else {
1532: /* search surfaces for heights at corners */
1533: double height[2][2];
1534: double depth[2][2];
1535: unsigned int zaxis_i = MAP_HEIGHT_X(zaxis_x);
1536: unsigned int zaxis_j = MAP_HEIGHT_Y(zaxis_y);
1537: unsigned int back_i = MAP_HEIGHT_X(back_x);
1538: /* HBB: why isn't back_j unsigned ??? */
1539: int back_j = MAP_HEIGHT_Y(back_y);
1540:
1541: height[0][0] = height[0][1] = height[1][0] = height[1][1] = base_z;
1542: depth[0][0] = depth[0][1] = depth[1][0] = depth[1][1] = base_z;
1543:
1544: for (; --plot_num >= 0; plot = plot->next_sp) {
1545: struct iso_curve *curve = plot->iso_crvs;
1546: int count = curve->p_count;
1547: int iso;
1548: if (plot->plot_type == DATA3D) {
1549: if (!plot->has_grid_topology)
1550: continue;
1551: iso = plot->num_iso_read;
1552: } else
1553: iso = iso_samples_2;
1554:
1555: check_corner_height(curve->points, height, depth);
1556: check_corner_height(curve->points + count - 1, height, depth);
1557: while (--iso)
1558: curve = curve->next;
1559: check_corner_height(curve->points, height, depth);
1560: check_corner_height(curve->points + count - 1, height, depth);
1561: }
1562:
1563: #define VERTICAL(mask,x,y,i,j,bx,by,tx,ty) \
1564: if (draw_border&mask) \
1565: draw_clip_line(bx,by,tx,ty);\
1566: else if (height[i][j] != depth[i][j]) \
1567: { unsigned int a0,b0, a1, b1; \
1568: map3d_xy(x,y,depth[i][j],&a0,&b0); \
1569: map3d_xy(x,y,height[i][j],&a1,&b1); \
1570: draw_clip_line(a0,b0,a1,b1); \
1571: }
1572:
1573: VERTICAL(16,zaxis_x,zaxis_y,zaxis_i,zaxis_j,fl_x,fl_y,tl_x,tl_y);
1574: VERTICAL(32,back_x,back_y,back_i,back_j,fb_x,fb_y,tb_x,tb_y);
1575: 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);
1576: hidden_active = FALSE;
1577: 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);
1578: hidden_active = save;
1579: }
1580:
1581: /* now border lines on top */
1582: if (draw_border & 256)
1583: draw_clip_line(tl_x, tl_y, tb_x, tb_y);
1584: if (draw_border & 512)
1585: draw_clip_line(tr_x, tr_y, tb_x, tb_y);
1586: /* these lines are in front of surface (?) */
1587: hidden_active = FALSE;
1588: if (draw_border & 1024)
1589: draw_clip_line(tl_x, tl_y, tf_x, tf_y);
1590: if (draw_border & 2048)
1591: draw_clip_line(tr_x, tr_y, tf_x, tf_y);
1592: hidden_active = save;
1593: }
1594:
1595: #ifndef LITE
1596: hidden_no_update = save_update;
1597: #endif /* LITE */
1598:
1599: }
1600: if (xtics || *xlabel.text) {
1601: unsigned int x0, y0, x1, y1;
1602: double mid_x = (x_max3d + x_min3d) / 2;
1603: double len;
1604: map3d_xy(mid_x, xaxis_y, base_z, &x0, &y0);
1605: map3d_xy(mid_x, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
1606: { /* take care over unsigned quantities */
1607: int dx = x1 - x0;
1608: int dy = y1 - y0;
1609: /* HBB 980309: 16bit strikes back: */
1610: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
1611: if (len != 0) {
1612: tic_unitx = dx / len;
1613: tic_unity = dy / len;
1614: } else {
1615: tic_unitx = tic_unity = 0;
1616: }
1617: }
1618:
1619: if (xtics) {
1620: gen_tics(FIRST_X_AXIS, &xticdef,
1621: work_grid.l_type & (GRID_X | GRID_MX),
1622: mxtics, mxtfreq, xtick_callback);
1623: }
1624: if (*xlabel.text) {
1625: /* label at xaxis_y + 1/4 of (xaxis_y-other_y) */
1626: double step = (2 * xaxis_y - y_max3d - y_min3d) / 4;
1627: map3d_xy(mid_x, xaxis_y + step, base_z, &x1, &y1);
1628: x1 += xlabel.xoffset * t->h_char;
1629: y1 += xlabel.yoffset * t->v_char;
1630: if (!tic_in) {
1631: x1 -= tic_unitx * ticscale * (t->h_tic);
1632: y1 -= tic_unity * ticscale * (t->v_tic);
1633: }
1634: /* write_multiline mods it */
1.1.1.2 ! maekawa 1635: write_multiline(x1, y1, xlabel.text, CENTRE, JUST_TOP, 0, xlabel.font);
1.1 maekawa 1636: }
1637: }
1638: if (ytics || *ylabel.text) {
1639: unsigned int x0, y0, x1, y1;
1640: double mid_y = (y_max3d + y_min3d) / 2;
1641: double len;
1642: map3d_xy(yaxis_x, mid_y, base_z, &x0, &y0);
1643: map3d_xy(x_min3d + x_max3d - yaxis_x, mid_y, base_z, &x1, &y1);
1644: { /* take care over unsigned quantities */
1645: int dx = x1 - x0;
1646: int dy = y1 - y0;
1647: /* HBB 980309: 16 Bits strike again: */
1648: len = sqrt(((double) dx) * dx + ((double) dy) * dy);
1649: if (len != 0) {
1650: tic_unitx = dx / len;
1651: tic_unity = dy / len;
1652: } else {
1653: tic_unitx = tic_unity = 0;
1654: }
1655: }
1656: if (ytics) {
1657: gen_tics(FIRST_Y_AXIS, &yticdef,
1658: work_grid.l_type & (GRID_Y | GRID_MY),
1659: mytics, mytfreq, ytick_callback);
1660: }
1661: if (*ylabel.text) {
1662: double step = (x_max3d + x_min3d - 2 * yaxis_x) / 4;
1663: map3d_xy(yaxis_x - step, mid_y, base_z, &x1, &y1);
1664: x1 += ylabel.xoffset * t->h_char;
1665: y1 += ylabel.yoffset * t->v_char;
1666: if (!tic_in) {
1667: x1 -= tic_unitx * ticscale * (t->h_tic);
1668: y1 -= tic_unity * ticscale * (t->v_tic);
1669: }
1670: /* write_multiline mods it */
1671: safe_strncpy(ss, ylabel.text, sizeof(ss));
1672: write_multiline(x1, y1, ss, CENTRE, JUST_TOP, 0, ylabel.font);
1673: }
1674: }
1675: /* do z tics */
1676:
1677: if (ztics && (draw_surface || (draw_contour & CONTOUR_SRF))) {
1678: gen_tics(FIRST_Z_AXIS, &zticdef, work_grid.l_type & (GRID_Z | GRID_MZ),
1679: mztics, mztfreq, ztick_callback);
1680: }
1.1.1.2 ! maekawa 1681: if ((yzeroaxis.l_type >= -2) && !is_log_x && inrange(0, x_min3d, x_max3d)) {
1.1 maekawa 1682: unsigned int x, y, x1, y1;
1.1.1.2 ! maekawa 1683: term_apply_lp_properties(&yzeroaxis);
1.1 maekawa 1684: map3d_xy(0.0, y_min3d, base_z, &x, &y); /* line through x=0 */
1685: map3d_xy(0.0, y_max3d, base_z, &x1, &y1);
1686: draw_clip_line(x, y, x1, y1);
1687: }
1.1.1.2 ! maekawa 1688: if ((xzeroaxis.l_type >= -2) && !is_log_y && inrange(0, y_min3d, y_max3d)) {
1.1 maekawa 1689: unsigned int x, y, x1, y1;
1.1.1.2 ! maekawa 1690: term_apply_lp_properties(&xzeroaxis);
1.1 maekawa 1691: map3d_xy(x_min3d, 0.0, base_z, &x, &y); /* line through y=0 */
1692: map3d_xy(x_max3d, 0.0, base_z, &x1, &y1);
1693: draw_clip_line(x, y, x1, y1);
1694: }
1695: /* PLACE ZLABEL - along the middle grid Z axis - eh ? */
1696: if (*zlabel.text && (draw_surface || (draw_contour & CONTOUR_SRF))) {
1697: map3d_xy(zaxis_x, zaxis_y, z_max3d + (z_max3d - base_z) / 4, &x, &y);
1698:
1699: x += zlabel.xoffset * t->h_char;
1700: y += zlabel.yoffset * t->v_char;
1701:
1.1.1.2 ! maekawa 1702: write_multiline(x, y, zlabel.text, CENTRE, CENTRE, 0, zlabel.font);
1.1 maekawa 1703:
1704: }
1705: }
1706:
1707:
1708: static void xtick_callback(axis, place, text, grid)
1709: int axis;
1710: double place;
1711: char *text;
1712: struct lp_style_type grid; /* linetype or -2 for none */
1713: {
1714: unsigned int x, y, x1, y1;
1715: double scale = (text ? ticscale : miniticscale);
1716: int dirn = tic_in ? 1 : -1;
1717: register struct termentry *t = term;
1718:
1719: map3d_xy(place, xaxis_y, base_z, &x, &y);
1720: if (grid.l_type > -2) {
1721: term_apply_lp_properties(&grid);
1722: /* to save mapping twice, map non-axis y */
1723: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
1724: draw_clip_line(x, y, x1, y1);
1725: term_apply_lp_properties(&border_lp);
1726: }
1727: if (xtics & TICS_ON_AXIS) {
1728: map3d_xy(place, (y_min3d + y_max3d) / 2, base_z, &x, &y);
1729: }
1730: x1 = x + tic_unitx * scale * (t->h_tic) * dirn;
1731: y1 = y + tic_unity * scale * (t->v_tic) * dirn;
1732: draw_clip_line(x, y, x1, y1);
1733: if (text) {
1734: int just;
1735: if (tic_unitx < -0.9)
1736: just = LEFT;
1737: else if (tic_unitx < 0.9)
1738: just = CENTRE;
1739: else
1740: just = RIGHT;
1741: #if 1
1742: /* HBB 970729: let's see if the 'tic labels collide with axes' problem
1743: * may be fixed this way: */
1744: x1 = x - tic_unitx * (t->h_char) * 1;
1745: y1 = y - tic_unity * (t->v_char) * 1;
1746: #else
1747: x1 = x - tic_unitx * (t->h_tic) * 2;
1748: y1 = y - tic_unity * (t->v_tic) * 2;
1749: #endif
1750: if (!tic_in) {
1751: x1 -= tic_unitx * (t->h_tic) * ticscale;
1752: y1 -= tic_unity * (t->v_tic) * ticscale;
1753: }
1754: clip_put_text_just(x1, y1, text, just);
1755: }
1756: if (xtics & TICS_MIRROR) {
1757: map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x, &y);
1758: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
1759: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
1760: draw_clip_line(x, y, x1, y1);
1761: }
1762: }
1763:
1764: static void ytick_callback(axis, place, text, grid)
1765: int axis;
1766: double place;
1767: char *text;
1768: struct lp_style_type grid;
1769: {
1770: unsigned int x, y, x1, y1;
1771: double scale = (text ? ticscale : miniticscale);
1772: int dirn = tic_in ? 1 : -1;
1773: register struct termentry *t = term;
1774:
1775: map3d_xy(yaxis_x, place, base_z, &x, &y);
1776: if (grid.l_type > -2) {
1777: term_apply_lp_properties(&grid);
1778: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x1, &y1);
1779: draw_clip_line(x, y, x1, y1);
1780: term_apply_lp_properties(&border_lp);
1781: }
1782: if (ytics & TICS_ON_AXIS) {
1783: map3d_xy((x_min3d + x_max3d) / 2, place, base_z, &x, &y);
1784: }
1785: x1 = x + tic_unitx * scale * dirn * (t->h_tic);
1786: y1 = y + tic_unity * scale * dirn * (t->v_tic);
1787: draw_clip_line(x, y, x1, y1);
1788: if (text) {
1789: int just;
1790: if (tic_unitx < -0.9)
1791: just = LEFT;
1792: else if (tic_unitx < 0.9)
1793: just = CENTRE;
1794: else
1795: just = RIGHT;
1796: #if 1
1797: /* HBB 970729: same as above in xtics_callback */
1798: x1 = x - tic_unitx * (t->h_char) * 1;
1799: y1 = y - tic_unity * (t->v_char) * 1;
1800: #else
1801: x1 = x - tic_unitx * (t->h_tic) * 2;
1802: y1 = y - tic_unity * (t->v_tic) * 2;
1803: #endif
1804: if (!tic_in) {
1805: x1 -= tic_unitx * (t->h_tic) * ticscale;
1806: y1 -= tic_unity * (t->v_tic) * ticscale;
1807: }
1808: clip_put_text_just(x1, y1, text, just);
1809: }
1810: if (ytics & TICS_MIRROR) {
1811: map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x, &y);
1812: x1 = x - tic_unitx * scale * (t->h_tic) * dirn;
1813: y1 = y - tic_unity * scale * (t->v_tic) * dirn;
1814: draw_clip_line(x, y, x1, y1);
1815: }
1816: }
1817:
1818: static void ztick_callback(axis, place, text, grid)
1819: int axis;
1820: double place;
1821: char *text;
1822: struct lp_style_type grid;
1823: {
1824: /* HBB: inserted some ()'s to shut up gcc -Wall, here and below */
1825: int len = (text ? ticscale : miniticscale) * (tic_in ? 1 : -1) * (term->h_tic);
1826: unsigned int x, y;
1827:
1828: if (grid.l_type > -2) {
1829: unsigned int x1, y1, x2, y2, x3, y3;
1830: double other_x = x_min3d + x_max3d - zaxis_x;
1831: double other_y = y_min3d + y_max3d - zaxis_y;
1832: term_apply_lp_properties(&grid);
1833: map3d_xy(zaxis_x, zaxis_y, place, &x1, &y1);
1834: map3d_xy(back_x, back_y, place, &x2, &y2);
1835: map3d_xy(other_x, other_y, place, &x3, &y3);
1836: draw_clip_line(x1, y1, x2, y2);
1837: draw_clip_line(x2, y2, x3, y3);
1838: term_apply_lp_properties(&border_lp);
1839: }
1840: map3d_xy(zaxis_x, zaxis_y, place, &x, &y);
1841: draw_clip_line(x, y, x + len, y);
1842: if (text) {
1843: int x1 = x - (term->h_tic) * 2;
1844: if (!tic_in)
1845: x1 -= (term->h_tic) * ticscale;
1846: clip_put_text_just(x1, y, text, RIGHT);
1847: }
1848: if (ztics & TICS_MIRROR) {
1849: double other_x = x_min3d + x_max3d - zaxis_x;
1850: double other_y = y_min3d + y_max3d - zaxis_y;
1851: map3d_xy(other_x, other_y, place, &x, &y);
1852: draw_clip_line(x, y, x - len, y);
1853: }
1854: }
1855:
1856:
1857: static void map_position(pos, x, y, what)
1858: struct position *pos;
1859: unsigned int *x, *y;
1860: char *what;
1861: {
1862: double xpos = pos->x;
1863: double ypos = pos->y;
1864: double zpos = pos->z;
1865: int screens = 0; /* need either 0 or 3 screen co-ordinates */
1866:
1867: switch (pos->scalex) {
1868: case first_axes:
1869: case second_axes:
1870: xpos = LogScale(xpos, is_log_x, log_base_log_x, what, "x");
1871: break;
1872: case graph:
1873: xpos = min_array[FIRST_X_AXIS] +
1874: xpos * (max_array[FIRST_X_AXIS] - min_array[FIRST_X_AXIS]);
1875: break;
1876: case screen:
1877: ++screens;
1878: }
1879:
1880: switch (pos->scaley) {
1881: case first_axes:
1882: case second_axes:
1883: ypos = LogScale(ypos, is_log_y, log_base_log_y, what, "y");
1884: break;
1885: case graph:
1886: ypos = min_array[FIRST_Y_AXIS] +
1887: ypos * (max_array[FIRST_Y_AXIS] - min_array[FIRST_Y_AXIS]);
1888: break;
1889: case screen:
1890: ++screens;
1891: }
1892:
1893: switch (pos->scalez) {
1894: case first_axes:
1895: case second_axes:
1896: zpos = LogScale(zpos, is_log_z, log_base_log_z, what, "z");
1897: break;
1898: case graph:
1899: zpos = min_array[FIRST_Z_AXIS] +
1900: zpos * (max_array[FIRST_Z_AXIS] - min_array[FIRST_Z_AXIS]);
1901: break;
1902: case screen:
1903: ++screens;
1904: }
1905:
1906: if (screens == 0) {
1907: map3d_xy(xpos, ypos, zpos, x, y);
1908: return;
1909: }
1910: if (screens != 3) {
1911: graph_error("Cannot mix screen co-ordinates with other types");
1912: } {
1913: register struct termentry *t = term;
1914: *x = pos->x * (t->xmax) + 0.5;
1915: *y = pos->y * (t->ymax) + 0.5;
1916: }
1917:
1918: return;
1919: }
1920:
1921:
1922: /*
1923: * these code blocks were moved to functions, to make the code simpler
1924: */
1925:
1926: static void key_text(xl, yl, text)
1927: int xl, yl;
1928: char *text;
1929: {
1930: if (key_just == JLEFT && key == -1) {
1931: (*term->justify_text) (LEFT);
1932: (*term->put_text) (xl + key_text_left, yl, text);
1933: } else {
1934: if ((*term->justify_text) (RIGHT)) {
1935: if (key == 1)
1936: clip_put_text(xl + key_text_right, yl, text);
1937: else
1938: (*term->put_text) (xl + key_text_right, yl, text);
1939: } else {
1940: int x = xl + key_text_right - (term->h_char) * strlen(text);
1941: if (key == 1) {
1942: if (i_inrange(x, xleft, xright))
1943: clip_put_text(x, yl, text);
1944: } else {
1945: (*term->put_text) (x, yl, text);
1946: }
1947: }
1948: }
1949: }
1950:
1951: static void key_sample_line(xl, yl)
1952: int xl, yl;
1953: {
1954: if (key == -1) {
1955: (*term->move) (xl + key_sample_left, yl);
1956: (*term->vector) (xl + key_sample_right, yl);
1957: } else {
1958: /* HBB 981118: avoid crash if hidden3d sees a manually placed key:
1959: * simply turn off hidden-lining while we're drawing the key line: */
1960: int save_hidden_active = hidden_active;
1961: hidden_active = FALSE;
1962:
1963: clip_move(xl + key_sample_left, yl);
1964: clip_vector(xl + key_sample_right, yl);
1965: hidden_active = save_hidden_active;
1966: }
1967: }
1968:
1969: static void key_sample_point(xl, yl, pointtype)
1970: int xl, yl;
1971: int pointtype;
1972: {
1973: if (!clip_point(xl + key_point_offset, yl)) {
1974: (*term->point) (xl + key_point_offset, yl, pointtype);
1975: } else {
1976: (*term->point) (xl + key_point_offset, yl, pointtype);
1977: }
1978: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>