[BACK]Return to graph3d.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

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>