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