/* misc.c */ /* * Vis5D system for visualizing five dimensional gridded data sets. * Copyright (C) 1990 - 2000 Bill Hibbard, Johan Kellum, Brian Paul, * Dave Santek, and Andre Battaiola. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * As a special exception to the terms of the GNU General Public * License, you are permitted to link Vis5D with (and distribute the * resulting source and executables) the LUI library (copyright by * Stellar Computer Inc. and licensed for distribution with Vis5D), * the McIDAS library, and/or the NetCDF library, where those * libraries are governed by the terms of their own licenses. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../config.h" #include #include #include #include #include #include #include #include "api.h" #include "globals.h" #include "memory.h" #include "imemory.h" #include "misc.h" #include "proj.h" #include "sync.h" #include "vis5d.h" /* * Print an error message and abort. */ void die( char *msg ) { printf("Error: %s\n",msg); abort(); } /* * C implementation of unix 'which' command: find the full path to * where the specified executable resides. * Input: file - executable file to search for * Output: fullpath - the full path/name for the file * Return: 1 = ok, 0 = file not found */ int which( char *file, char *fullpath ) { char *pathvar, *pos; char path[1000]; int len; char s[1000]; struct stat buf; /* get the value of PATH from the user's environment */ pathvar = getenv( "PATH" ); /* try each path */ len = 0; for (pos=pathvar;*pos;pos++) { if (*pos==':') { path[len] = 0; /* try it */ strcpy( s, path ); strcat( s, "/" ); strcat( s, file ); if (stat(s, &buf) == 0) { /* found */ if ((buf.st_mode & S_IEXEC)) { /* and executable */ strcpy( fullpath, s ); return 1; } } /* go on to next path */ len = 0; } else { path[len++] = *pos; } } /* if we get here, we didn't find visad-d, try the current directory */ strcpy( s, "./" ); strcat( s, file ); if (stat(s, &buf)==0 && (buf.st_mode & S_IEXEC)) { /* found it! */ strcpy( fullpath, s ); return 1; } return 0; } /* * Check if the named program is installed on the system. * Return: 1 = installed, 0 = not installed. */ int installed( char *program ) { char path[1000]; if (which(program,path)==0) { /* printf("Can't save/print window image because '%s' not found.\n", program); printf("Install it from your OS CD/tape.\n"); */ return 0; } else { return 1; } } /*** round ************************************************************ Round off x to a 'nice' value. **********************************************************************/ float round( float x ) { float base, fudge; int temp; for (base=1000000.0; fabs(x/base)<1.0 && base>0.000001; base/=10.0); fudge = (x>0.0) ? 0.5 : -0.5; temp = (int) (x/base + fudge); return temp * base; } /* Input: index - the index of the vis5d_ctx * Output: it will return the position in the Display_Context's * ctxarray of the desired vis5d_ctx index */ int return_ctx_index_pos( Display_Context dtx, int index) { int yo, spandex; for (yo = 0; yo < dtx->numofctxs; yo++){ spandex = dtx->ctxarray[yo]; if (spandex == index){ return yo; } } /*printf("error in return_ctx_index_pos\n"); */ return -1; } /* Input: index - the index of the vis5d_ctx * time - the timestep of the display_ctx * Output: return the timestep associates with the display_ctx's * timestep */ int return_ctx_time( Display_Context dtx, int index, int time) { int yo; for (yo = 0; yo < dtx->numofctxs; yo++){ if (index == dtx->TimeStep[time].owners[yo]){ return dtx->TimeStep[time].ownerstimestep[yo]; } } printf("error in return_ctx_time\n"); return -1; } /* * When a horizontal slice is moved to a new position (in grid coords), * this function should be called to update the position in Z and height. * Input: level - position of slice in grid levels * z - position of slice in Z graphics coords * hgt - position of slice in height coords. */ void new_hslice_pos( Context ctx, float level, float *z, float *hgt ) { *hgt = gridlevelPRIME_to_height( ctx->dpy_ctx, level); *z = height_to_zPRIME(ctx->dpy_ctx, *hgt); } void new_hwindslice_pos( Display_Context dtx, float level, float *z, float *hgt ) { *z = gridlevelPRIME_to_zPRIME( dtx, -1, -1, level ); *hgt =gridlevelPRIME_to_height( dtx, level ); } /* * Similar function to new_hslice_pos(). * NOTE: the graphics and geo coordinates are PRIME */ void new_vslice_pos( Context ctx, float r, float c, float *x, float *y, float *lat, float *lon ) { float zero = 0.0, z; float row, col; row = r; /* this is needed because r and c are really doubles */ col = c; gridPRIME_to_xyzPRIME( ctx->dpy_ctx, -1, -1, 1, &row, &col, &zero, x, y, &z ); rowcolPRIME_to_latlon( ctx->dpy_ctx, -1, -1, r, c, lat, lon ); } void new_vwindslice_pos( Display_Context dtx, float r, float c, float *x, float *y, float *lat, float *lon ) { float zero = 0.0, z; float row, col; row = r; /* this is needed because r and c are really doubles */ col = c; gridPRIME_to_xyzPRIME( dtx, -1, -1, 1, &row, &col, &zero, x, y, &z ); rowcolPRIME_to_latlon( dtx, -1, -1, r, c, lat, lon ); } /* * Set the initial position, etc. of the graphics for a specified variable. */ void init_graphics_pos( Context ctx, int var ) { Display_Context dtx; float l; /* TODO: This should be split into initialization functions for each graph type and variable */ dtx = ctx->dpy_ctx; ctx->IsoLevel[var] = ctx->Variable[var]->MinVal; l = ((float) dtx->LowLev + (float) (dtx->Nl-1) / 2); if(! ctx->Variable[var]->HSliceRequest){ ctx->Variable[var]->HSliceRequest = (hslice_request *) allocate(ctx,sizeof(hslice_request)); } ctx->Variable[var]->HSliceRequest->stipple=VIS5D_SOLID_LINE; ctx->Variable[var]->HSliceRequest->linewidth = 1; ctx->Variable[var]->HSliceRequest->Level = l; new_hslice_pos( ctx, ctx->Variable[var]->HSliceRequest->Level, &ctx->Variable[var]->HSliceRequest->Z, &ctx->Variable[var]->HSliceRequest->Hgt ); if (ctx->Variable[var]->MinVal > ctx->Variable[var]->MaxVal) { ctx->Variable[var]->HSliceRequest->Interval = 0.0; } else { ctx->Variable[var]->HSliceRequest->Interval = round( (ctx->Variable[var]->MaxVal - ctx->Variable[var]->MinVal) / 10.0 ); } ctx->Variable[var]->HSliceRequest->LowLimit = ctx->Variable[var]->MinVal; ctx->Variable[var]->HSliceRequest->HighLimit = ctx->Variable[var]->MaxVal; if(! ctx->Variable[var]->CHSliceRequest){ ctx->Variable[var]->CHSliceRequest = (hslice_request *) allocate(ctx,sizeof(hslice_request)); ctx->Variable[var]->CHSliceRequest->fillstyle = GL_FILL; ctx->Variable[var]->CHSliceRequest->textureflag=0; } ctx->Variable[var]->CHSliceRequest->Level = l; ctx->Variable[var]->CHSliceRequest->LowLimit = ctx->Variable[var]->MinVal; ctx->Variable[var]->CHSliceRequest->HighLimit = ctx->Variable[var]->MaxVal; new_hslice_pos( ctx, ctx->Variable[var]->CHSliceRequest->Level, &ctx->Variable[var]->CHSliceRequest->Z, &ctx->Variable[var]->CHSliceRequest->Hgt ); if(! ctx->Variable[var]->VSliceRequest){ ctx->Variable[var]->VSliceRequest = (vslice_request *) allocate(ctx,sizeof(vslice_request)); #ifdef DEBUG_MEM printf("VSliceRequest 0x%x %d\n",ctx->Variable[var]->VSliceRequest,sizeof(vslice_request)); #endif } ctx->Variable[var]->VSliceRequest->stipple=VIS5D_SOLID_LINE; ctx->Variable[var]->VSliceRequest->linewidth = 1; ctx->Variable[var]->VSliceRequest->R1 = (float) (dtx->Nr-1) / 2.0; ctx->Variable[var]->VSliceRequest->R2 = 0.0; ctx->Variable[var]->VSliceRequest->C1 = (float) (dtx->Nr-1) / 2.0; ctx->Variable[var]->VSliceRequest->C2 = (float) (dtx->Nc-1); if (ctx->Variable[var]->MinVal > ctx->Variable[var]->MaxVal) { ctx->Variable[var]->VSliceRequest->Interval = 0.0; } else { ctx->Variable[var]->VSliceRequest->Interval = round( (ctx->Variable[var]->MaxVal - ctx->Variable[var]->MinVal) / 10.0 ); } ctx->Variable[var]->VSliceRequest->LowLimit = ctx->Variable[var]->MinVal; ctx->Variable[var]->VSliceRequest->HighLimit = ctx->Variable[var]->MaxVal; new_vslice_pos( ctx, ctx->Variable[var]->VSliceRequest->R1, ctx->Variable[var]->VSliceRequest->R2, &ctx->Variable[var]->VSliceRequest->X1, &ctx->Variable[var]->VSliceRequest->Y1, &ctx->Variable[var]->VSliceRequest->Lat1, &ctx->Variable[var]->VSliceRequest->Lon1 ); new_vslice_pos( ctx, ctx->Variable[var]->VSliceRequest->C1, ctx->Variable[var]->VSliceRequest->C2, &ctx->Variable[var]->VSliceRequest->X2, &ctx->Variable[var]->VSliceRequest->Y2, &ctx->Variable[var]->VSliceRequest->Lat2, &ctx->Variable[var]->VSliceRequest->Lon2 ); if(! ctx->Variable[var]->CVSliceRequest){ ctx->Variable[var]->CVSliceRequest = (vslice_request *) allocate(ctx,sizeof(vslice_request)); ctx->Variable[var]->CVSliceRequest->fillstyle = GL_FILL; ctx->Variable[var]->CVSliceRequest->textureflag=0; } ctx->Variable[var]->CVSliceRequest->R1 = ctx->Variable[var]->VSliceRequest->R1; ctx->Variable[var]->CVSliceRequest->R2 = ctx->Variable[var]->VSliceRequest->R2; ctx->Variable[var]->CVSliceRequest->C1 = ctx->Variable[var]->VSliceRequest->C1; ctx->Variable[var]->CVSliceRequest->C2 = ctx->Variable[var]->VSliceRequest->C2; ctx->Variable[var]->CVSliceRequest->LowLimit = ctx->Variable[var]->MinVal; ctx->Variable[var]->CVSliceRequest->HighLimit = ctx->Variable[var]->MaxVal; new_vslice_pos( ctx, ctx->Variable[var]->CVSliceRequest->R1, ctx->Variable[var]->CVSliceRequest->R2, &ctx->Variable[var]->CVSliceRequest->X1, &ctx->Variable[var]->CVSliceRequest->Y1, &ctx->Variable[var]->CVSliceRequest->Lat1, &ctx->Variable[var]->CVSliceRequest->Lon1 ); new_vslice_pos( ctx, ctx->Variable[var]->CVSliceRequest->C1, ctx->Variable[var]->CVSliceRequest->C2, &ctx->Variable[var]->CVSliceRequest->X2, &ctx->Variable[var]->CVSliceRequest->Y2, &ctx->Variable[var]->CVSliceRequest->Lat2, &ctx->Variable[var]->CVSliceRequest->Lon2 ); } /* * Free a traj struct and any memory it points to. */ static void free_traj( Display_Context dtx, struct traj *t ) { int bytes; Context trajuctx; trajuctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, dtx->TrajUowner)]; /* WLH 4 Nov 98 */ if (trajuctx == NULL) return; /* vertices */ bytes = 3 * t->length * sizeof(int_2); deallocate( trajuctx, t->verts, bytes ); if (t->kind==1) { /* ribbon normals */ bytes = 3 * t->length * sizeof(int_1); deallocate( trajuctx, t->norms, bytes ); } if (t->colors) { /* colors */ bytes = t->length * sizeof(uint_1); deallocate( trajuctx, t->colors, bytes ); } bytes = trajuctx->NumTimes * sizeof(uint_2); deallocate( trajuctx, t->start, bytes ); deallocate( trajuctx, t->len, bytes ); deallocate( trajuctx, t, sizeof(struct traj) ); } /*** del_last_traj **************************************************** Delete the most recent trajectory. **********************************************************************/ void del_last_traj( Display_Context dtx ) { LOCK_ON( TrajLock ); if (dtx->NumTraj) { free_traj( dtx, dtx->TrajTable[dtx->NumTraj-1] ); dtx->TrajTable[dtx->NumTraj-1] = NULL; dtx->NumTraj--; } LOCK_OFF( TrajLock ); } /*** del_traj_group *************************************************** Delete a group of trajectories. Input: g - the trajectory group number in [0..VIS5D_TRAJ_SETS-1]. **********************************************************************/ void del_traj_group( Display_Context dtx, int g ) { int i, j; LOCK_ON( TrajLock ); i = 0; while (iNumTraj) { if (dtx->TrajTable[i]->group==g) { if (iTrajTable[i] ); /* delete this one by shifting remaining trajectories backward */ for (j=i+1;jNumTraj;j++) { dtx->TrajTable[j-1] = dtx->TrajTable[j]; } } dtx->NumTraj--; } else { i++; } } LOCK_OFF( TrajLock ); } /* * Deallocate an isosurface's memory. */ int free_isosurface( Context ctx, int time, int var ) { Display_Context dtx; int ctime, ftime, t, total; dtx = ctx->dpy_ctx; total = 0; if (!ctx->SameIsoColorVarOwner[var]){ ftime = dtx->TimeStep[time].ownerstimestep[return_ctx_index_pos(dtx, ctx->context_index)]; for(t=0; t < dtx->NumTimes; t++){ ctime = dtx->TimeStep[t].ownerstimestep[return_ctx_index_pos(dtx, ctx->context_index)]; if ( ctime==ftime){ if (ctx->Variable[var]->SurfTable[time]->valid) { int b1, b2, b3, b4; /* vertices */ b1 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(int_2) * 3; if (b1) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->verts, b1 ); } /* normals */ b2 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(int_1) * 3; if (b2) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->norms, b2 ); } /* indices */ b3 = ctx->Variable[var]->SurfTable[time]->numindex * sizeof(uint_index); if (b3) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->index, b3 ); } /* colors */ if (ctx->Variable[var]->SurfTable[time]->colors) { b4 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(uint_1); deallocate( ctx, ctx->Variable[var]->SurfTable[time]->colors, b4 ); ctx->Variable[var]->SurfTable[time]->colors = NULL; } else { b4 = 0; } ctx->Variable[var]->SurfTable[time]->valid = 0; total += b1 + b2 + b3 + b4; } } } return total; } else{ if (ctx->Variable[var] && ctx->Variable[var]->SurfTable[time] && ctx->Variable[var]->SurfTable[time]->valid) { int b1, b2, b3, b4; /* vertices */ b1 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(int_2) * 3; if (b1) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->verts, b1 ); } /* normals */ b2 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(int_1) * 3; if (b2) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->norms, b2 ); } /* indices */ b3 = ctx->Variable[var]->SurfTable[time]->numindex * sizeof(uint_index); if (b3) { deallocate( ctx, ctx->Variable[var]->SurfTable[time]->index, b3 ); } /* colors */ if (ctx->Variable[var]->SurfTable[time]->colors) { b4 = ctx->Variable[var]->SurfTable[time]->numverts * sizeof(uint_1); deallocate( ctx, ctx->Variable[var]->SurfTable[time]->colors, b4 ); ctx->Variable[var]->SurfTable[time]->colors = NULL; } else { b4 = 0; } ctx->Variable[var]->SurfTable[time]->valid = 0; return b1 + b2 + b3 + b4; } else { return 0; } } return 0; } int free_textplot( Irregular_Context itx, int time) { if (itx->TextPlotTable[time].valid){ int b1, b2; b1 = itx->TextPlotTable[time].numverts * sizeof(int_2) * 3; if (b1){ i_deallocate( itx, itx->TextPlotTable[time].verts, b1); } if (itx->TextPlotTable[time].colors){ b2 = itx->TextPlotTable[time].numverts/2 * sizeof(uint_1); if (b2){ i_deallocate( itx, itx->TextPlotTable[time].colors, b2); } } itx->TextPlotTable[time].valid = 0; return b1 + b2; } else{ return 0; } } int free_hslice( Context ctx, int time, int var ) { int i; if(! (ctx->Variable[var] && ctx->Variable[var]->HSliceTable[time])) return 0; if (ctx->Variable[var]->HSliceTable[time]->valid) { int b1, b2, b3, b4; b1 = ctx->Variable[var]->HSliceTable[time]->num1 * sizeof(int_2) * 3; if (b1) { deallocate( ctx, ctx->Variable[var]->HSliceTable[time]->verts1, b1 ); } b2 = ctx->Variable[var]->HSliceTable[time]->num2 * sizeof(int_2) * 3; if (b2) { deallocate( ctx, ctx->Variable[var]->HSliceTable[time]->verts2, b2 ); } b3 = ctx->Variable[var]->HSliceTable[time]->num3 * sizeof(int_2) * 3; if (b3) { deallocate( ctx, ctx->Variable[var]->HSliceTable[time]->verts3, b3 ); } b4 = ctx->Variable[var]->HSliceTable[time]->numboxverts * 3 * sizeof(float); if (b4) { deallocate( ctx, ctx->Variable[var]->HSliceTable[time]->boxverts, b4 ); } ctx->Variable[var]->HSliceTable[time]->valid = 0; return b1 + b2 + b3 + b4; } else { return 0; } } int free_vslice( Context ctx, int time, int var ) { int i; if(! (ctx->Variable[var] && ctx->Variable[var]->VSliceTable[time])) return 0; if ( ctx->Variable[var]->VSliceTable[time]->valid) { int b1, b2, b3, b4; if (ctx->Variable[var]->VSliceTable[time]->valid && ctx->Variable[var]->VSliceTable[time]->num1) { b1 = ctx->Variable[var]->VSliceTable[time]->num1 * sizeof(int_2) * 3; deallocate( ctx, ctx->Variable[var]->VSliceTable[time]->verts1, b1 ); } if (ctx->Variable[var]->VSliceTable[time]->valid && ctx->Variable[var]->VSliceTable[time]->num2) { b2 = ctx->Variable[var]->VSliceTable[time]->num2 * sizeof(int_2) * 3; deallocate( ctx, ctx->Variable[var]->VSliceTable[time]->verts2, b2 ); } if (ctx->Variable[var]->VSliceTable[time]->valid && ctx->Variable[var]->VSliceTable[time]->num3) { b3 = ctx->Variable[var]->VSliceTable[time]->num3 * sizeof(int_2) * 3; deallocate( ctx, ctx->Variable[var]->VSliceTable[time]->verts3, b3 ); } b4 = ctx->Variable[var]->VSliceTable[time]->numboxverts * 3 * sizeof(float); if (b4) { deallocate( ctx, ctx->Variable[var]->VSliceTable[time]->boxverts, b4 ); } ctx->Variable[var]->VSliceTable[time]->valid = 0; return b1 + b2 + b3 + b4; } else { return 0; } } int free_chslice( Context ctx, int time, int var ) { if(! (ctx->Variable[var] && ctx->Variable[var]->CHSliceTable[time])) return 0; if (ctx->Variable[var]->CHSliceTable[time]->valid) { int nrnc, b1, b2; nrnc = ctx->Variable[var]->CHSliceTable[time]->rows * ctx->Variable[var]->CHSliceTable[time]->columns; b1 = nrnc * sizeof(uint_1); deallocate( ctx, ctx->Variable[var]->CHSliceTable[time]->color_indexes, b1 ); b2 = 3 * nrnc * sizeof(int_2); deallocate( ctx, ctx->Variable[var]->CHSliceTable[time]->verts, b2 ); ctx->Variable[var]->CHSliceTable[time]->valid = 0; return b1 + b2; } else { return 0; } } int free_cvslice( Context ctx, int time, int var ) { if(! (ctx->Variable[var] && ctx->Variable[var]->CVSliceTable[time])) return 0; if (ctx->Variable[var]->CVSliceTable[time]->valid) { int nrnc, b1, b2; nrnc = ctx->Variable[var]->CVSliceTable[time]->rows * ctx->Variable[var]->CVSliceTable[time]->columns; b1 = nrnc * sizeof(uint_1); deallocate( ctx, ctx->Variable[var]->CVSliceTable[time]->color_indexes, b1 ); b2 = 3 * nrnc * sizeof(int_2); deallocate( ctx, ctx->Variable[var]->CVSliceTable[time]->verts, b2 ); ctx->Variable[var]->CVSliceTable[time]->valid = 0; return b1 + b2; } else { return 0; } } /* * Free all the graphics of a specified physical variable. */ int free_param_graphics( Context ctx, int var ) { int time; for (time=0;timeNumTimes;time++) { LOCK_ON( GfxLock ); /* isosurfaces */ free_isosurface( ctx, time, var ); /* horizontal contour slices */ free_hslice( ctx, time, var ); /* vertical contour slices */ free_vslice( ctx, time, var ); /* horizontal colored slices */ free_chslice( ctx, time, var ); /* vertical colored slices */ free_cvslice( ctx, time, var ); LOCK_OFF( GfxLock ); } return 0; } int free_hwind( Display_Context dtx, int time, int ws ) { Context uctx; uctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, dtx->Uvarowner[ws])]; if (dtx->HWindTable[ws][time].valid) { int b1, b2; /* MJK 10.14.98 dtx->DisplayHWind[ws] = 0; */ b1 = dtx->HWindTable[ws][time].nvectors * sizeof(int_2) * 3; /* WLH 4 Nov 98 if (b1) { */ /* WLH 4 Nov 98 */ if (b1 && uctx) { deallocate( uctx, dtx->HWindTable[ws][time].verts, b1 ); } b2 = dtx->HWindTable[ws][time].numboxverts * 3 * sizeof(float); /* WLH 4 Nov 98 if (b2) { */ /* WLH 4 Nov 98 */ if (b2 && uctx) { deallocate( uctx, dtx->HWindTable[ws][time].boxverts, b2 ); } dtx->HWindTable[ws][time].valid = 0; return b1 + b2; } else { return 0; } } int free_vwind( Display_Context dtx, int time, int ws ) { Context uctx; uctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, dtx->Uvarowner[ws])]; if (dtx->VWindTable[ws][time].valid) { int b1, b2; /* MJK 10.14.98 dtx->DisplayVWind[ws] = 0; */ b1 = dtx->VWindTable[ws][time].nvectors * sizeof(int_2) * 3; /* WLH 4 Nov 98 if (b1) { */ /* WLH 4 Nov 98 */ if (b1 && uctx) { deallocate( uctx, dtx->VWindTable[ws][time].verts, b1 ); } b2 = dtx->VWindTable[ws][time].numboxverts * 3 * sizeof(float); /* WLH 4 Nov 98 if (b2) { */ /* WLH 4 Nov 98 */ if (b2 && uctx) { deallocate( uctx, dtx->VWindTable[ws][time].boxverts, b2 ); } dtx->VWindTable[ws][time].valid = 0; return b1 + b2; } else { return 0; } } int free_hstream( Display_Context dtx, int time, int ws ) { Context uctx; uctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, dtx->Uvarowner[ws])]; if (dtx->HStreamTable[ws][time].valid) { int b1, b2; /* MJK 10.14.98 dtx->DisplayHStream[ws] = 0; */ b1 = dtx->HStreamTable[ws][time].nlines * sizeof(int_2) * 3; /* WLH 4 Nov 98 if (b1) { */ /* WLH 4 Nov 98 */ if (b1 && uctx) { deallocate( uctx, dtx->HStreamTable[ws][time].verts, b1 ); } b2 = dtx->HStreamTable[ws][time].numboxverts * 3 * sizeof(float); /* WLH 4 Nov 98 if (b2) { */ /* WLH 4 Nov 98 */ if (b2 && uctx) { deallocate( uctx, dtx->HStreamTable[ws][time].boxverts, b2 ); } dtx->HStreamTable[ws][time].valid = 0; return b1 + b2; } else { return 0; } } int free_vstream( Display_Context dtx, int time, int ws ) { Context uctx; uctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, dtx->Uvarowner[ws])]; if (dtx->VStreamTable[ws][time].valid) { int b1, b2; /* MJK 10.14.98 dtx->DisplayVStream[ws] = 0; */ b1 = dtx->VStreamTable[ws][time].nlines * sizeof(int_2) * 3; /* WLH 4 Nov 98 if (b1) { */ /* WLH 4 Nov 98 */ if (b1 && uctx) { deallocate( uctx, dtx->VStreamTable[ws][time].verts, b1 ); } b2 = dtx->VStreamTable[ws][time].numboxverts * 3 * sizeof(float); /* WLH 4 Nov 98 if (b2) { */ /* WLH 4 Nov 98 */ if (b2 && uctx) { deallocate( uctx, dtx->VStreamTable[ws][time].boxverts, b2 ); } dtx->VStreamTable[ws][time].valid = 0; return b1 + b2; } else { return 0; } } void free_all_graphics( Context ctx ) { int set, var, time, ws; for (var=0;varNumVars;var++) { free_param_graphics( ctx, var ); } if(ctx->dpy_ctx){ for (time=0;time< ctx->dpy_ctx->NumTimes; time++) { for (ws=0;wsdpy_ctx->Uvarowner[ws] == ctx->context_index){ free_hwind( ctx->dpy_ctx, time, ws ); free_vwind( ctx->dpy_ctx, time, ws ); free_hstream( ctx->dpy_ctx, time, ws ); free_vstream( ctx->dpy_ctx, time, ws ); } } } if (ctx->context_index == ctx->dpy_ctx->TrajUowner){ for (set = 0; set < VIS5D_TRAJ_SETS; set++){ ctx->dpy_ctx->DisplayTraj[set] = 0; vis5d_delete_traj_set(ctx->dpy_ctx->dpy_context_index, set); } } } } void turn_off_and_free_var_graphics( Context ctx, int var) { int set, i, time; free_param_graphics( ctx, var ); for (i=0;icontext_index == ctx->dpy_ctx->Uvarowner[i]) && (var == ctx->dpy_ctx->Uvar[i] || var == ctx->dpy_ctx->Vvar[i] || var == ctx->dpy_ctx->Wvar[i])){ for (time = 0; time < ctx->dpy_ctx->NumTimes; time++){ free_hwind( ctx->dpy_ctx, time, i); free_vwind( ctx->dpy_ctx, time, i); free_hstream( ctx->dpy_ctx, time, i); free_vstream( ctx->dpy_ctx, time, i); } } } if ((ctx->context_index == ctx->dpy_ctx->TrajUowner) && (var == ctx->dpy_ctx->TrajU || var == ctx->dpy_ctx->TrajV || var == ctx->dpy_ctx->TrajW) ){ for (set = 0; set < VIS5D_TRAJ_SETS; set++){ vis5d_delete_traj_set(ctx->dpy_ctx->dpy_context_index, set); } } } /* BUG FIX MJK 8.10.98 */ /* Added this function so when ever dtx map and vert parameters */ /* are changed, graphics will but turned off and deallocated */ void turn_off_and_free_all_display_graphics( Display_Context dtx ) { int yo, var, time, set, ws; Context ctx; /* param graphics */ for (yo = 0; yo < dtx->numofctxs; yo++){ ctx = dtx->ctxpointerarray[yo]; for (var=0;varNumVars;var++) { free_param_graphics( ctx, var ); vis5d_enable_graphics(ctx->context_index, VIS5D_ISOSURF, var, VIS5D_OFF); vis5d_enable_graphics(ctx->context_index, VIS5D_HSLICE, var, VIS5D_OFF); vis5d_enable_graphics(ctx->context_index, VIS5D_VSLICE, var, VIS5D_OFF); vis5d_enable_graphics(ctx->context_index, VIS5D_CHSLICE, var, VIS5D_OFF); vis5d_enable_graphics(ctx->context_index, VIS5D_CVSLICE, var, VIS5D_OFF); vis5d_enable_graphics(ctx->context_index, VIS5D_VOLUME, var, VIS5D_OFF); } } /* traj sets */ for (set = 0; set < VIS5D_TRAJ_SETS; set++){ vis5d_delete_traj_set(dtx->dpy_context_index, set); dtx->DisplayTraj[set] = 0; } /* U,V,W graphics */ for (ws=0;wsNumTimes;time++) { free_hwind( dtx, time, ws ); free_vwind( dtx, time, ws ); free_hstream( dtx, time, ws ); free_vstream( dtx, time, ws ); } dtx->DisplayHWind[ws] = 0; dtx->DisplayVWind[ws] = 0; dtx->DisplayHStream[ws] = 0; dtx->DisplayVStream[ws] = 0; } } static int AccessTime = 1; /* access time pseudo-clock */ /*** recent *********************************************************** Inform the memory manager of the most recently used graphic. Input: ig - the graphic type: ISOSURF, HSLICE, VWIND, TRAJ, etc. ip - which parameter, wind slice, traj group, etc. **********************************************************************/ void recent( Context ctx, int ig, int ip ) { switch (ig) { case ISOSURF: ctx->RecentIsosurf[ip] = AccessTime; break; case HSLICE: ctx->RecentHSlice[ip] = AccessTime; break; case VSLICE: ctx->RecentVSlice[ip] = AccessTime; break; case CHSLICE: ctx->RecentCHSlice[ip] = AccessTime; break; case CVSLICE: ctx->RecentCVSlice[ip] = AccessTime; break; case HWIND: ctx->dpy_ctx->RecentHWind[ip] = AccessTime; break; case VWIND: ctx->dpy_ctx->RecentVWind[ip] = AccessTime; break; case HSTREAM: ctx->dpy_ctx->RecentHStream[ip] = AccessTime; break; case VSTREAM: ctx->dpy_ctx->RecentVStream[ip] = AccessTime; break; case TRAJ: ctx->dpy_ctx->RecentTraj[ip] = AccessTime; break; default: printf("error in recent( %d, %d )\n", ig, ip ); } AccessTime++; } /* because (val % limit) doesn't work for negatives */ static int adjust( int val, int limit ) { while (val < 0) val += limit; while (val >= limit) val -= limit; return val; } /* * Free all graphics for a particular time step. * Return: number of bytes freed or 0 if nothing found to deallocate. * * NOTE: time is in ctx time */ static int free_time( Context ctx, int time ) { int var, ws, bytes; int ctime, t, vtime; Display_Context dtx; dtx = ctx->dpy_ctx; bytes = 0; LOCK_ON( GfxLock ); for (ws=0;wsUvarowner[ws] == ctx->context_index){ for(t=0; t < dtx->NumTimes; t++){ ctime = dtx->TimeStep[t].ownerstimestep[return_ctx_index_pos(dtx, ctx->context_index)]; if (ctime==time){ bytes += free_hwind( dtx, t, ws); bytes += free_vwind( dtx, t, ws); bytes += free_hstream( dtx, t, ws); bytes += free_vstream( dtx, t, ws); } } } } vtime = time; /* WLH 26 Jan 2000 */ for (var=0;varNumVars;var++) { /* isosurfaces */ bytes += free_isosurface( ctx, vtime, var ); /* horizontal contour slices */ bytes += free_hslice( ctx, vtime, var ); /* vertical contour slices */ bytes += free_vslice( ctx, vtime, var ); /* horizontal colored slices */ bytes += free_chslice( ctx, vtime, var ); /* vertical colored slices */ bytes += free_cvslice( ctx, vtime, var ); } LOCK_OFF( GfxLock ); return bytes; } int i_deallocate_lru( Irregular_Context itx ) { /* this has not been implemented yet, since so far there is */ /* only one graphic displayable for an irregular data context */ return 0; } /*** deallocate_lru *************************************************** Find and deallocate the least-recently-used graphic. Return: number of bytes freed or 0 if nothing found to deallocate. **********************************************************************/ int deallocate_lru( Context ctx ) { int var, time, t, oldtime, oldig, oldvar, bytes; static int first_time=1; Display_Context dtx; dtx = ctx->dpy_ctx; if (first_time) { printf("WARNING: Memory is full, graphics may be discarded\n"); first_time = 0; } oldtime = AccessTime; if (ctx->VeryLarge) { int tp, tm; tm = adjust(ctx->CurTime + ctx->NumTimes / 2, ctx->NumTimes); tp = adjust(tm + 1, ctx->NumTimes); bytes = 0; while ((tp != ctx->CurTime || tm != ctx->CurTime) && bytes == 0) { if (tp != ctx->CurTime) { bytes += free_time( ctx, tp); tp = adjust(tp + 1, ctx->NumTimes); } if (tm != ctx->CurTime) { bytes += free_time( ctx, tm); tm = adjust(tm - 1, ctx->NumTimes); } } if (bytes == 0) { /*printf("free_lru() failed\n");*/ } return bytes; } else { /* find oldest isosurface */ for (var=0;varNumVars;var++) { t = ctx->RecentIsosurf[var]; if (t>0 && tNumVars;var++) { t = ctx->RecentHSlice[var]; if (t>0 && tNumVars;var++) { t = ctx->RecentVSlice[var]; if (t>0 && tNumVars;var++) { t = ctx->RecentCHSlice[var]; if (t>0 && tNumVars;var++) { t = ctx->RecentCVSlice[var]; if (t>0 && tUvarowner[var] == ctx->context_index){ t = dtx->RecentHWind[var]; if (t>0 && tUvarowner[var] == ctx->context_index){ t = dtx->RecentVWind[var]; if (t>0 && tUvarowner[var] == ctx->context_index){ t = dtx->RecentHStream[var]; if (t>0 && tUvarowner[var] == ctx->context_index){ t = dtx->RecentVStream[var]; if (t>0 && tTrajUowner == ctx->context_index){ t = dtx->RecentTraj[var]; if (t>0 && tNumTimes;time++) { bytes += free_isosurface( ctx, time, oldvar ); /*printf("[reclaimed %d] isosurf %d %d\n", bytes,oldvar,time);*/ } ctx->RecentIsosurf[oldvar] = 0; } else if (oldig==HSLICE) { /* dealloc all 'oldvar' horizontal contour slices */ for (time=0;timeNumTimes;time++) { bytes += free_hslice( ctx, time, oldvar ); /*printf("[reclaimed %d] hslice %d %d\n", bytes,oldvar,time);*/ } ctx->RecentHSlice[oldvar] = 0; } else if (oldig==VSLICE) { /* dealloc all 'oldvar' horizontal contour slices */ for (time=0;timeNumTimes;time++) { bytes += free_vslice( ctx, time, oldvar ); /*printf("[reclaimed %d] vslice %d %d\n", bytes,oldvar,time);*/ } ctx->RecentVSlice[oldvar] = 0; } else if (oldig==CHSLICE) { for (time=0;timeNumTimes;time++) { bytes += free_chslice( ctx, time, oldvar ); /*printf("[reclaimed %d] chslice %d %d\n", bytes,oldvar,time);*/ } ctx->RecentCHSlice[oldvar] = 0; } else if (oldig==CVSLICE) { for (time=0;timeNumTimes;time++) { bytes += free_cvslice( ctx, time, oldvar ); /*printf("[reclaimed %d] cvslice %d %d\n", bytes,oldvar,time);*/ } ctx->RecentCVSlice[oldvar] = 0; } else if (oldig==HWIND) { for (time=0;timeNumTimes;time++) { bytes += free_hwind( dtx, time, oldvar ); /*printf("[reclaimed %d] hwind %d\n", bytes*3,time);*/ } dtx->RecentHWind[oldvar] = 0; } else if (oldig==VWIND) { for (time=0;timeNumTimes;time++) { bytes += free_vwind( dtx, time, oldvar ); /*printf("[reclaimed %d] vwind %d\n", bytes*3,time );*/ } dtx->RecentVWind[oldvar] = 0; } else if (oldig==HSTREAM) { for (time=0;timeNumTimes;time++) { bytes += free_hstream( dtx, time, oldvar ); /*printf("[reclaimed %d] hstream %d\n", bytes*3,time);*/ } dtx->RecentHStream[oldvar] = 0; } else if (oldig==VSTREAM) { for (time=0;timeNumTimes;time++) { bytes += free_vstream( dtx, time, oldvar ); /*printf("[reclaimed %d] vstream %d\n", bytes*3,time);*/ } dtx->RecentVStream[oldvar] = 0; } else if (oldig==TRAJ) { del_traj_group( dtx, oldvar ); bytes = 1; dtx->RecentTraj[oldvar] = 0; } else { printf("oldig=%d\n", oldig ); die("error in deallocate_lru"); } if (bytes==0) bytes = 1; return bytes; } else { /*printf("free_lru() failed\n");*/ return 0; } } }