#include "vizual.h" /* LOCALLY Global structures */ static file_info *Headp; static struct dspec *B_spec; static struct Cap *Cap; static struct poly_info Polys[3 * (MAXTHRESH + 1)]; static int x, y; static double Xlinterp(); #define ANTICLOCKWISE 0 #define CLOCKWISE 1 /************************************** get_min_max *************************/ /* get min and max values from the original data */ static get_min_max(minmax, size, array) double *minmax; int size; double array[4]; { register int i; double min, max; min = max = *array; for (i = 0; i < size; i++) { if (array[i] > max) max = array[i]; else if (array[i] < min) min = array[i]; } minmax[0] = min; minmax[1] = max; } /*************************************** side_to_xy **************************/ static side_to_xy(xyray, pre, zz, side) double *xyray; struct poly_info *pre; double zz; int side; { double x1, x2; double y1, y2; int side2; double interp; side2 = next_higher(side, pre->vnum); x1 = pre->verts[side << 1]; y1 = pre->verts[(side << 1) + 1]; x2 = pre->verts[side2 << 1]; y2 = pre->verts[(side2 << 1) + 1]; /* debugf("%lf x1 %lf y1\n",x1,y1); debugf("%lf x2 %lf y2\n",x2,y2); */ interp = Xlinterp(pre->data[side], zz, pre->data[side2]); if (x1 != x2) xyray[0] = x1 + (interp * (x2 - x1)); else xyray[0] = x1; if (y1 != y2) xyray[1] = y1 + (interp * (y2 - y1)); else xyray[1] = y2; } /********************************** split_poly *****************************/ /* recursively subdivides polygons until no more threshold divide ** them then draws the polygon and falls thru to left over polygon ** code */ void split_poly(ta, pnum, t) int pnum; /* index to current polygon */ int ta; /* current threshold array */ int t; /* current threshold index */ { double minmax[2]; double zz; /* current threshold */ int num; int hits; int xing[4]; /* a list of the sides with hits */ int tnum; int i; int new_pnum; int side; static int first; int n_verts; cmndln_info *tp; int drawn; num = 0; hits = 0; drawn = 0; tp = &(B_spec->threshes[ta]); if (t >= tp->nthres) return; zz = (double)tp->tvalue[t]; if (t) { /* don't draw below 1st threshold */ if (B_spec->in_out == INSIDE) tnum = t + B_spec->low; else if (ta == 0) /* tnum == t; *//* fix ? MN 2001 */ tnum = t; else tnum = t + B_spec->hi; } /* calc min/max for each new poly */ get_min_max(minmax, Polys[pnum].vnum, Polys[pnum].data); if (zz > (double)minmax[1]) { /* if entirely contained */ if (t) { draw_cappolys(Headp, B_spec, Cap, &Polys[pnum], x, y, 1, tnum); } /*and we are done */ return; } /* thresh in square */ else if (WITHIN((double)minmax[0], zz, (double)minmax[1])) { /* this code from contour program: determine number of crossings (hits) ** if non-zero and even, then have 1 or 2 valid contours in cell */ for (i = 0; i < Polys[pnum].vnum; i++) { if ((Polys[pnum].data[i] <= zz && zz < Polys[pnum].data[(i + 1) % Polys[pnum].vnum]) || (Polys[pnum].data[i] > zz && zz >= Polys[pnum].data[(i + 1) % Polys[pnum].vnum])) { hits |= (1 << i); /* record which lines were crossed */ xing[num] = i; num++; } } if (!num || num & 0x01) { /* zero or odd no contour in cell */ /* just go on to next thresh */ split_poly(ta, pnum, t + 1); } /* else split into two polygons */ else { /* NUMBER OF XINGS = 2 */ /* split the polygon and the reiterate */ side = xing[0]; /* first is set to true if the first split polygon is to be drawn */ first = (zz > Polys[pnum].data[side]) ? 0 : 1; new_pnum = pnum + 1; n_verts = 0; /* 1st vert will be the location where the first xing occurs */ /* not only are the vertices stored in the poly_info variable ** but also the data values at these vertices must be stored */ Polys[new_pnum].data[n_verts] = zz; side_to_xy(&(Polys[new_pnum].verts[n_verts << 1]), &(Polys[pnum]), zz, side); n_verts++; side = next_higher(side, Polys[pnum].vnum); while (side != xing[1]) { Polys[new_pnum].data[n_verts] = Polys[pnum].data[side]; Polys[new_pnum].verts[n_verts << 1] = Polys[pnum].verts[side << 1]; Polys[new_pnum].verts[(n_verts << 1) + 1] = Polys[pnum].verts[(side << 1) + 1]; n_verts++; side = next_higher(side, Polys[pnum].vnum); } Polys[new_pnum].data[n_verts] = Polys[pnum].data[side]; Polys[new_pnum].verts[n_verts << 1] = Polys[pnum].verts[side << 1]; Polys[new_pnum].verts[(n_verts << 1) + 1] = Polys[pnum].verts[(side << 1) + 1]; n_verts++; Polys[new_pnum].data[n_verts] = zz; side_to_xy(&(Polys[new_pnum].verts[n_verts << 1]), &(Polys[pnum]), zz, side); n_verts++; Polys[new_pnum].vnum = n_verts; Polys[new_pnum].data[n_verts] = Polys[new_pnum].data[0]; if (first) { if (t) draw_cappolys(Headp, B_spec, Cap, &Polys[new_pnum], x, y, 1, tnum); drawn = 1; } else { split_poly(ta, new_pnum, t + 1); } /*============================================================================*/ /* NOW DO THE SECOND HALF OF THE SPLIT */ side = xing[1]; n_verts = 0; /* 1st vert will be the location that xing occurs */ Polys[new_pnum].data[n_verts] = zz; side_to_xy(&Polys[new_pnum].verts[n_verts << 1], &(Polys[pnum]), zz, side); n_verts++; side = next_higher(side, Polys[pnum].vnum); while (side != xing[0]) { Polys[new_pnum].data[n_verts] = Polys[pnum].data[side]; Polys[new_pnum].verts[n_verts << 1] = Polys[pnum].verts[side << 1]; Polys[new_pnum].verts[(n_verts << 1) + 1] = Polys[pnum].verts[(side << 1) + 1]; n_verts++; side = next_higher(side, Polys[pnum].vnum); } Polys[new_pnum].data[n_verts] = Polys[pnum].data[side]; Polys[new_pnum].verts[n_verts << 1] = Polys[pnum].verts[side << 1]; Polys[new_pnum].verts[(n_verts << 1) + 1] = Polys[pnum].verts[(side << 1) + 1]; n_verts++; Polys[new_pnum].data[n_verts] = zz; side_to_xy(&Polys[new_pnum].verts[n_verts << 1], &(Polys[pnum]), zz, side); n_verts++; Polys[new_pnum].vnum = n_verts; Polys[new_pnum].data[n_verts] = Polys[new_pnum].data[0]; if (!first) { if (t) { draw_cappolys(Headp, B_spec, Cap, &Polys[new_pnum], x, y, 1, tnum); } /* mark a flag */ drawn = 1; } else { split_poly(ta, new_pnum, t + 1); } } } /*end WITHIN code */ /* if no hits then ready to fall thru to left over node code which will be the tail end of the split_poly routine */ if ((t < tp->nthres) && !drawn) { split_poly(ta, pnum, t + 1); } return; } /************************************** Xlinterp ****************************/ /* rescale zz to a number between 0. and 1. */ static double Xlinterp(zmin, zz, zmax) double zmin, zz, zmax; { if (zmin == zmax) /* div by zero. should never get here */ return zmin; return (zz - zmin) / (zmax - zmin); } /******************************* next_higher *******************************/ /* given sides 0,1,2,3, return number of next side in clockwise order */ int next_higher(side, verts) int side, verts; { return ((side + 1) % verts); } int draw_cap(XHeadp, XB_spec, XCap) file_info *XHeadp; struct dspec *XB_spec; struct Cap *XCap; { int row, xdim; int ta; cmndln_info *tp; int org_tnum; /* if flat shading */ Headp = XHeadp; if (Headp->linefax.litmodel == 1) glDisable(GL_COLOR_MATERIAL); else { glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); } B_spec = XB_spec; Cap = XCap; xdim = Cap->Cols; for (y = Cap->miny; y < Cap->maxy; y++) { /* for each cell */ row = y * Cap->Cols; /*shouldn't this be Rows? JCM NO. DPG */ for (x = Cap->minx; x < Cap->maxx; x++) { Polys[0].data[0] = Polys[0].data[4] = (double)Cap->D_buff[row + xdim + x]; /*BL*/ Polys[0].data[1] = (double)Cap->D_buff[row + xdim + x + 1]; /* BR */ Polys[0].data[2] = (double)Cap->D_buff[row + x + 1]; /* TR */ Polys[0].data[3] = (double)Cap->D_buff[row + x]; /* TL */ /* for each threshold array */ for (ta = 0; ta < 2 && (tp = &(B_spec->threshes[ta]))->nthres; ta++) { { /* build initial poly */ Polys[0].verts[0] = 0.0; Polys[0].verts[1] = 1.0; Polys[0].verts[2] = 1.0; Polys[0].verts[3] = 1.0; Polys[0].verts[4] = 1.0; Polys[0].verts[5] = 0.0; Polys[0].verts[6] = 0.0; Polys[0].verts[7] = 0.0; Polys[0].verts[8] = 0.0; Polys[0].verts[9] = 1.0; Polys[0].vnum = 4; } /* First time */ if (B_spec->in_out == INSIDE) org_tnum = B_spec->low; else org_tnum = ta == 0 ? 0 : B_spec->hi; split_poly(ta, 0, 0); } } } glDisable(GL_COLOR_MATERIAL); }