=================================================================== RCS file: /home/cvs/OpenXM_contrib/gnuplot/Attic/hidden3d.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.3 diff -u -p -r1.1.1.2 -r1.1.1.3 --- OpenXM_contrib/gnuplot/Attic/hidden3d.c 2000/01/22 14:15:58 1.1.1.2 +++ OpenXM_contrib/gnuplot/Attic/hidden3d.c 2003/09/15 07:09:25 1.1.1.3 @@ -1,5 +1,5 @@ #ifndef lint -static char *RCSid = "$Id: hidden3d.c,v 1.1.1.2 2000/01/22 14:15:58 maekawa Exp $"; +static char *RCSid = "$Id: hidden3d.c,v 1.1.1.3 2003/09/15 07:09:25 ohara Exp $"; #endif /* GNUPLOT - hidden3d.c */ @@ -288,19 +288,29 @@ static t_hl_extent_y *ymin_hl, *ymax_hl; Each column is splitted into pairs of points (a,b). Each pair describes a cross of one line with the column. */ +/* HBB 20000608: finally, someone found a serious bug in this code :-( + * whenever the Cross_store array has to be reallocated, all the + * pointers in hl_buffer, and the next pointers in struct Cross become + * invalid. Use indices instead of pointers. */ + struct Cross { int a, b; - struct Cross GPHUGE *next; + unsigned int next; /* (unsigned int) -1 means: no next */ + /* HBB 20000608: was struct Cross GPHUGE *next;*/ }; +#if 0 /* HBB 20000608 */ static struct Cross GPHUGE *GPHUGE * hl_buffer; +#else +static unsigned int GPHUGE * hl_buffer; +#endif /* HBB 980303: added a global array of Cross structures, to save lots * of gp_alloc() calls (3 millions in a run through all.dem!) */ #define CROSS_STORE_INCREASE 500 /* number of Cross'es to alloc at a time */ static struct Cross *Cross_store = 0; -static int last_Cross_store = 0, free_Cross_store = 0; +static unsigned int last_Cross_store = 0, free_Cross_store = 0; struct Vertex { coordval x, y, z; @@ -454,7 +464,7 @@ static GP_INLINE int maybe_build_polygon __PROTO((stru int n, long *v, long line, int style, struct lp_style_type * lp, long next, long next_frag, int id, t_poly_tested tested)); static void init_polygons __PROTO((struct surface_points * plots, int pcount)); -static int compare_by_zmax __PROTO((const void *p1, const void *p2)); +int compare_by_zmax __PROTO((SORTFUNC_ARGS p1, SORTFUNC_ARGS p2)); static void sort_by_zmax __PROTO((void)); static int obscured __PROTO((struct Polygon GPHUGE * p)); static GP_INLINE int xy_overlap __PROTO((struct Polygon GPHUGE * a, struct Polygon GPHUGE * b)); @@ -473,7 +483,7 @@ static long split_polygon_by_plane __PROTO((long P, do static int in_front __PROTO((long Last, long Test)); /* HBB 980303: new, for the new back-buffer for *Cross structures: */ -static GP_INLINE struct Cross *get_Cross_from_store __PROTO((void)); +static GP_INLINE unsigned int get_Cross_from_store __PROTO((void)); static GP_INLINE void init_Cross_store __PROTO((void)); static GP_INLINE TBOOLEAN hl_buffer_set __PROTO((int xv, int yv)); @@ -644,8 +654,7 @@ void init_hidden_line_removal() yfact = 1; if (pnt == 0) { i = XREDUCE(xright) - XREDUCE(xleft) + 1; - pnt = (tp_pnt *) gp_alloc( - (unsigned long) (i * sizeof(tp_pnt)), "hidden pnt"); + pnt = (tp_pnt *) gp_alloc(i * sizeof(tp_pnt), "hidden pnt"); while (--i >= 0) pnt[i] = (tp_pnt) 0; } @@ -903,7 +912,7 @@ long *v, line, next, next_frag; (v) = 0; /* flag this as undefined */ \ (c) = (border) = 0; \ } else {\ - (v) = (long *) gp_alloc ((unsigned long) sizeof (long) * (n), "hidden PREPARE_POLYGON"); \ + (v) = (long *) gp_alloc (sizeof (long) * (n), "hidden PREPARE_POLYGON"); \ (v)[0] = vert_free + (i0);\ (v)[1] = vert_free + (i1);\ (v)[2] = vert_free + (i2);\ @@ -975,9 +984,9 @@ int pcount; } } vlist = (struct Vertex GPHUGE *) - gp_alloc((unsigned long) sizeof(struct Vertex) * nvert, "hidden vlist"); + gp_alloc(sizeof(struct Vertex) * nvert, "hidden vlist"); plist = (struct Polygon GPHUGE *) - gp_alloc((unsigned long) sizeof(struct Polygon) * npoly, "hidden plist"); + gp_alloc(sizeof(struct Polygon) * npoly, "hidden plist"); /* initialize vlist: */ for (vert_free = 0, this_plot = plots, surface = 0; @@ -1243,7 +1252,7 @@ int pcount; vert_free++; break; case DOTS: - v1 = (long *) gp_alloc((unsigned long) sizeof(long) * 1, + v1 = (long *) gp_alloc(sizeof(long) * 1, "hidden v1 for dots"); v1[0] = vert_free++; CHECK_PLIST(); @@ -1259,7 +1268,7 @@ int pcount; case FINANCEBARS: case POINTSTYLE: case VECTOR: - v1 = (long *) gp_alloc((unsigned long) sizeof(long) * 1, + v1 = (long *) gp_alloc(sizeof(long) * 1, "hidden v1 for point"); v1[0] = vert_free++; CHECK_PLIST(); @@ -1269,7 +1278,7 @@ int pcount; case BOXES: /* handle as IMPULSES */ case IMPULSES: n1 = 2; - v1 = (long *) gp_alloc((unsigned long) sizeof(long) * n1, + v1 = (long *) gp_alloc(sizeof(long) * n1, "hidden v1 for impulse"); v1[0] = vert_free++; v1[1] = vert_free++; @@ -1283,10 +1292,12 @@ int pcount; } } -static int compare_by_zmax(p1, p2) -const void *p1, *p2; +int compare_by_zmax(p1, p2) + SORTFUNC_ARGS p1; + SORTFUNC_ARGS p2; { - return (SIGNOF(plist[*(const long *) p2].zmax - plist[*(const long *) p1].zmax)); + return (SIGNOF(plist[*(const long *) p2].zmax + - plist[*(const long *) p1].zmax)); } static void sort_by_zmax() @@ -1294,7 +1305,7 @@ static void sort_by_zmax() { long *sortarray, i; struct Polygon GPHUGE *this; - sortarray = (long *) gp_alloc((unsigned long) sizeof(long) * pfree, "hidden sortarray"); + sortarray = (long *) gp_alloc(sizeof(long) * pfree, "hidden sortarray"); for (i = 0; i < pfree; i++) sortarray[i] = i; qsort(sortarray, (size_t) pfree, sizeof(long), compare_by_zmax); @@ -1935,10 +1946,8 @@ TBOOLEAN f; /* return value = Front(1) or Back(0) */ /* We need two new polygons instead of the old one: */ n1 = p->n - cross2 + cross1 + 2; n2 = cross2 - cross1 + 2; - v1 = (long *) gp_alloc((unsigned long) sizeof(long) * n1, - "hidden v1 for two new poly"); - v2 = (long *) gp_alloc((unsigned long) sizeof(long) * n2, - "hidden v2 for two new poly"); + v1 = (long *) gp_alloc(sizeof(long) * n1, "hidden v1 for two new poly"); + v2 = (long *) gp_alloc(sizeof(long) * n2, "hidden v2 for two new poly"); #if SHOW_SPLITTING_EDGES line1 = 1L << (n1 - 1); line2 = 1L << (n2 - 1); @@ -2140,14 +2149,20 @@ long Last, Test; test->tested = is_moved_or_split; SPLIT_TEST_BY_P; } else { - if (loop && (p->tested == is_tested)) { - /* Ouch, seems like we're in trouble, really */ + if (loop && (p->tested == is_in_loop)) { + /* Ouch, seems like we're in trouble, really: no way to + * split one of them, and we're in a loop, so we can't + * move p to the front of the list, without risking an + * endless loop. Well, let's just output the darn thing, + * then, no matter what. :-( */ +#if DEBUG /* normally off */ fprintf(stderr, "\ #Failed: In loop, without intersections.\n\ #Relations are %d, %d\n", p_rel_tplane, t_rel_pplane); print_polygon(test, "test"); print_polygon(p, "p"); +#endif continue; /* Keep quiet, maybe no-one will notice (;-) */ } else { PUT_P_IN_FRONT_TEST(is_in_loop); @@ -2210,11 +2225,11 @@ static GP_INLINE void init_Cross_store() last_Cross_store = CROSS_STORE_INCREASE; free_Cross_store = 0; Cross_store = (struct Cross *) - gp_alloc((unsigned long) last_Cross_store * sizeof(struct Cross), - "hidden cross store"); + gp_alloc(last_Cross_store * sizeof(struct Cross), "hidden cross store"); } -static GP_INLINE struct Cross *get_Cross_from_store() +static GP_INLINE unsigned int +get_Cross_from_store() { while (last_Cross_store <= free_Cross_store) { last_Cross_store += CROSS_STORE_INCREASE; @@ -2223,18 +2238,21 @@ static GP_INLINE struct Cross *get_Cross_from_store() (unsigned long) last_Cross_store * sizeof(struct Cross), "hidden cross store"); } - return Cross_store + (free_Cross_store++); + return free_Cross_store++; } static GP_INLINE TBOOLEAN hl_buffer_set(xv, yv) int xv, yv; { - struct Cross GPHUGE *c; + unsigned int c; + /*HBB 961110: lclint wanted this: */ assert(hl_buffer != 0); - for (c = hl_buffer[xv]; c != NULL; c = c->next) - if (c->a <= yv && c->b >= yv) { + for (c = hl_buffer[xv]; + c < last_Cross_store; + c = Cross_store[c].next) + if (Cross_store[c].a <= yv && Cross_store[c].b >= yv) { return TRUE; } return FALSE; @@ -2248,9 +2266,10 @@ static int hl_buff_xmin, hl_buff_xmax; /* Store a line crossing the x interval around xv between y = ya and * y = yb in the hl_buffer */ static GP_INLINE void update_hl_buffer_column(xv, ya, yb) -int xv, ya, yb; + int xv, ya, yb; { - struct Cross GPHUGE *GPHUGE * cross, GPHUGE * cross2; + unsigned int cross, cross2; + TBOOLEAN still_in_hl_buffer = TRUE; /* First, ensure that ya <= yb */ if (ya > yb) { @@ -2259,15 +2278,20 @@ int xv, ya, yb; ya = y_temp; } /* loop over all previous crossings at this x-value */ - for (cross = hl_buffer + xv; 1; cross = &(*cross)->next) { - if (*cross == NULL) { + for (cross = hl_buffer[xv], still_in_hl_buffer = TRUE; + 1; + cross = Cross_store[cross].next, still_in_hl_buffer = FALSE + ) { + if (cross > last_Cross_store) { /* first or new highest crossing at this x-value */ /* HBB 980303: new method to allocate Cross structures */ - *cross = get_Cross_from_store(); - (*cross)->a = ya; - (*cross)->b = yb; - (*cross)->next = NULL; + cross = get_Cross_from_store(); + if (still_in_hl_buffer) + hl_buffer[xv] = cross; + Cross_store[cross].a = ya; + Cross_store[cross].b = yb; + Cross_store[cross].next = (unsigned int) -1; /* HBB 961201: keep track of x-range of hl_buffer, to * speedup free()ing it */ if (xv < hl_buff_xmin) @@ -2276,28 +2300,32 @@ int xv, ya, yb; hl_buff_xmax = xv; break; } - if (yb < (*cross)->a - 1) { + if (yb < Cross_store[cross].a - 1) { /* crossing below 'cross', create new entry before 'cross' */ - cross2 = *cross; + cross2 = cross; /* HBB 980303: new method to allocate Cross structures */ - *cross = get_Cross_from_store(); - (*cross)->a = ya; - (*cross)->b = yb; - (*cross)->next = cross2; + cross = get_Cross_from_store(); + if (still_in_hl_buffer) + hl_buffer[xv] = cross; + Cross_store[cross].a = ya; + Cross_store[cross].b = yb; + Cross_store[cross].next = cross2; break; - } else if (ya <= (*cross)->b + 1) { + } else if (ya <= Cross_store[cross].b + 1) { /* crossing overlaps or covers 'cross' */ - if (ya < (*cross)->a) - (*cross)->a = ya; - if (yb > (*cross)->b) { - if ((*cross)->next && (*cross)->next->a <= yb) { + if (ya < Cross_store[cross].a) + Cross_store[cross].a = ya; + if (yb > Cross_store[cross].b) { + if (Cross_store[cross].next < last_Cross_store + && Cross_store[Cross_store[cross].next].a <= yb + ) { /* crossing spans all the way up to 'cross->next' so * unite them */ - cross2 = (*cross)->next; - (*cross)->b = cross2->b; - (*cross)->next = cross2->next; + cross2 = Cross_store[cross].next; + Cross_store[cross].b = Cross_store[cross2].b; + Cross_store[cross].next = Cross_store[cross2].next; } else - (*cross)->b = yb; + Cross_store[cross].b = yb; } break; } @@ -2625,7 +2653,7 @@ struct Polygon GPHUGE *p; for (i = hl_buff_xmin; i <= hl_buff_xmax; i++) { /* HBB 980303: one part was removed here. It isn't needed any more, * with the global store for Cross structs. */ - hl_buffer[i] = NULL; + hl_buffer[i] = (unsigned int) -1; } /* HBB 980303: instead, set back the free pointer of the Cross store: */ free_Cross_store = 0; @@ -2644,7 +2672,7 @@ struct Polygon GPHUGE *p; if (ymin_hl[i] == HL_EXTENT_Y_MAX) graph_error("Logic error #2 in hidden line"); if (pnt[i] == 0) { - pnt[i] = (t_pnt *) gp_alloc((unsigned long) y_malloc, "hidden ymalloc"); + pnt[i] = (t_pnt *) gp_alloc(y_malloc, "hidden ymalloc"); memset(pnt[i], 0, (size_t) y_malloc); } if (ymin_hl[i] < 0 || ymax_hl[i] > YREDUCE(ytop) - YREDUCE(ybot)) @@ -2691,8 +2719,8 @@ int pcount; y_malloc = (2 + (YREDUCE(ytop) >> 4) - (YREDUCE(ybot) >> 4)) * sizeof(t_pnt); /* ymin_hl, ymax_hl: */ i = sizeof(t_hl_extent_y) * (XREDUCE(xright) - XREDUCE(xleft) + 1); - ymin_hl = (t_hl_extent_y *) gp_alloc((unsigned long) i, "hidden ymin_hl"); - ymax_hl = (t_hl_extent_y *) gp_alloc((unsigned long) i, "hidden ymax_hl"); + ymin_hl = (t_hl_extent_y *) gp_alloc(i, "hidden ymin_hl"); + ymax_hl = (t_hl_extent_y *) gp_alloc(i, "hidden ymax_hl"); for (i = (XREDUCE(xright) - XREDUCE(xleft)); i >= 0; i--) { ymin_hl[i] = HL_EXTENT_Y_MAX; ymax_hl[i] = 0; @@ -2701,11 +2729,10 @@ int pcount; /* HBB 980303 new: initialize the global store for Cross structs: */ init_Cross_store(); i = XREDUCE(xright) - XREDUCE(xleft) + 1; - hl_buffer = - (struct Cross GPHUGE * GPHUGE *) gp_alloc((unsigned long) (i * sizeof(struct Cross GPHUGE *)), - "hidden hl_buffer"); + hl_buffer = (unsigned int GPHUGE *) + gp_alloc(i * sizeof(unsigned int), "hidden hl_buffer"); while (--i >= 0) - hl_buffer[i] = (struct Cross *) 0; + hl_buffer[i] = (unsigned int) -1; init_polygons(plots, pcount);