[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.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>