#include #include #include #include #include #include #define LUCKY 33 #define MODE_DIRECT 0 #define MODE_SLICE 1 #define MODE_FULL 2 #define MODE_PRELOAD 3 #define MODE_DEFAULT 0 #define STATUS_READY 0 #define STATUS_BUSY 1 /* structure for slice mode reading from volume file*/ typedef struct { int num, skip; int crnt, base; void *slice[MAX_VOL_SLICES]; } slice_data; static geovol_file *Data[MAX_VOL_FILES]; static geovol_file Df[MAX_VOL_FILES]; /* trying to avoid allocation */ static int Numfiles = 0; static int Cur_id = LUCKY; static int Cur_max; static int Rows, Cols, Depths; /* local functions prototypes */ void *open_g3d_file(char *, IFLAG *, double *, double *); int close_g3d_file(void *); /******************************************************************/ /* initialize */ static int init_volfiles(void) { int i; G3D_Region *w3; for (i = 0; i < MAX_VOL_FILES; i++) { /* avoiding dynamic allocation */ Data[i] = &(Df[i]); } Cur_max = MAX_VOL_FILES; /* get window */ w3 = GVL_get_window(); /* set cols, rows, depths from window */ Cols = w3->cols; Rows = w3->rows; Depths = w3->depths; return (1); } /******************************************************************/ /* check number of files */ static int check_num_volfiles(void) { if (Numfiles < Cur_max) { return (0); } fprintf(stderr, "maximum number of datafiles exceeded\n"); exit(0); /* This return statement keeps compilers happy, it is never executed */ return (0); } /******************************************************************/ /* get geovol_file structure for given handle */ geovol_file *gvl_file_get_volfile(int id) { int i; for (i = 0; i < Numfiles; i++) { if (Data[i]->data_id == id) { return (Data[i]); } } return (NULL); } /******************************************************************/ /* find file with name and type in geovol_file array an return handle*/ int find_datah(char *name, IFLAG type, int begin) { static int i; int start; start = begin ? 0 : i + 1; for (i = start; i < Numfiles; i++) { if (!strcmp(Data[i]->file_name, name)) { if (Data[i]->file_type == type) { return (Data[i]->data_id); } } } return (-1); } /******************************************************************/ /* return file name for given handle */ char *gvl_file_get_name(int id) { int i; geovol_file *fvf; static char retstr[NAME_SIZ]; for (i = 0; i < Numfiles; i++) { if (Data[i]->data_id == id) { fvf = Data[i]; strcpy(retstr, fvf->file_name); return (retstr); } } return (NULL); } /******************************************************************/ /* return file type for given handle */ int gvl_file_get_file_type(geovol_file *vf) { return (vf->file_type); } /******************************************************************/ /* return data type for given handle */ int gvl_file_get_data_type(geovol_file *vf) { return (vf->data_type); } /******************************************************************/ /* return minimum and maximum value in volume file */ void gvl_file_get_min_max(geovol_file *vf, double *min, double *max) { *min = vf->min; *max = vf->max; } /******************************************************************/ /* open volume file */ void *open_volfile(char *name, IFLAG file_type, IFLAG *data_type, double *min, double *max) { if (file_type == VOL_FTYPE_G3D) { return open_g3d_file(name, data_type, min, max); } return (NULL); } /******************************************************************/ /* close volume file */ int close_volfile(void *map, IFLAG type) { if (type == VOL_FTYPE_G3D) { return close_g3d_file(map); } return (-1); } /******************************************************************/ /* get handle for given file name and type */ int gvl_file_newh(char *name, IFLAG file_type) { geovol_file *new; static int first = 1; int i, id; void *m; IFLAG data_type; double min, max; if (first) { if (0 > init_volfiles()) { return (-1); } first = 0; } if ( 0 <= (id = find_datah(name, file_type, 1))) { for (i = 0; i < Numfiles; i++) { if (Data[i]->data_id == id) { new = Data[i]; new->count++; return (id); } } } if (0 > check_num_volfiles()) { return (-1); } if (!name) { return (-1); } if ((m = open_volfile(name, file_type, &data_type, &min, &max)) == NULL) { return (-1); } new = Data[Numfiles]; if (new) { Numfiles++; new->data_id = Cur_id++; strcpy(new->file_name, name); new->file_type = file_type; new->count = 1; new->map = m; new->min = min; new->max = max; new->data_type = data_type; new->status = STATUS_READY; new->buff = NULL; new->mode = 255; gvl_file_set_mode(new, MODE_DEFAULT); return (new->data_id); } return (-1); } /******************************************************************/ /* free allocated buffers */ int free_volfile_buffs(geovol_file * vf) { if (vf->mode == MODE_SLICE) { free(vf->buff); vf->buff = NULL; } if (vf->mode == MODE_PRELOAD) { free(vf->buff); vf->buff = NULL; } return (1); } /******************************************************************/ /* free geovol_file structure for given handle */ int gvl_file_free_datah(int id) { int i, j, found = -1; geovol_file *fvf; #ifdef TRACE_FUNCS { fprintf(stderr, "gvl_file_free_datah\n"); } #endif for (i = 0; i < Numfiles; i++) { if (Data[i]->data_id == id) { found = 1; fvf = Data[i]; if (fvf->count > 1) { fvf->count--; } else { close_volfile(fvf->map, fvf->file_type); free_volfile_buffs(fvf); strcpy(fvf->file_name, ""); fvf->data_id = 0; for (j = i; j < (Numfiles - 1); j++) { Data[j] = Data[j + 1]; } Data[j] = fvf; --Numfiles; } } } return (found); } /******************************************************************/ /* reading from G3D raster volume files */ /******************************************************************/ /******************************************************************/ /* open g3d file */ void *open_g3d_file(char *filename, IFLAG *type, double *min, double *max) { char *mapset; int itype; void *map; /* search for g3d file a return his mapset */ if (NULL == (mapset = G_find_grid3(filename,""))) { #ifdef DEBUG_MSG fprintf(stderr, "can't find grid3 file : %s\n", filename); #endif return (NULL); } /* open g3d file */ if (NULL == (map = G3d_openCellOld(filename, mapset, G3D_DEFAULT_WINDOW, G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT))) { #ifdef DEBUG_MSG fprintf(stderr, "error opening grid3 file : %s\n", filename); #endif return (NULL); } /* load range into range structure of map */ if (!G3d_range_load(map)) { #ifdef DEBUG_MSG fprintf(stderr, "error reading range for file : %s\n", filename); #endif return (NULL); } G3d_range_min_max(map, min, max); /* get file data type */ itype = G3d_fileTypeMap(map); if (itype == G3D_FLOAT) *type = VOL_DTYPE_FLOAT; if (itype == G3D_DOUBLE) *type = VOL_DTYPE_DOUBLE; return (map); } /******************************************************************/ /* close g3d file */ int close_g3d_file(void *map) { /* close opened g3d file */ if (G3d_closeCell(map) != 1) { #ifdef DEBUG_MSG fprintf(stderr, "error closing grid3 file"); #endif return (-1); } return (1); } /******************************************************************/ /* read value from g3d file */ int read_g3d_value(IFLAG type, void *map, int x, int y, int z, void *value) { switch (type) { /* float data type */ case (VOL_DTYPE_FLOAT) : *((float *)value) = G3d_getFloat(map, x, y, z); break; /* double data type */ case (VOL_DTYPE_DOUBLE) : *((double *)value) = G3d_getDouble(map, x, y, z); break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ /* read slice of values at level from g3d file */ int read_g3d_slice(IFLAG type, void *map, int level, void *data) { int x, y; switch (type) { /* float data type */ case (VOL_DTYPE_FLOAT) : for (x = 0; x < Cols; x++) { for (y = 0; y < Rows; y++) { ((float *) data)[x + y * Cols] = G3d_getFloat(map, x, y, level); } } break; /* double data type */ case (VOL_DTYPE_DOUBLE) : for (x = 0; x < Cols; x++) { for (y = 0; y < Rows; y++) { ((double *) data)[x + y * Cols] = G3d_getDouble(map, x, y, level); } } break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ /* read all values from g3d file */ int read_g3d_vol(IFLAG type, void *map, void *data) { int x, y, z; switch (type) { /* float data type */ case (VOL_DTYPE_FLOAT) : for (x = 0; x < Cols; x++) { for (y = 0; y < Rows; y++) { for (z = 0; z < Depths; z++) { ((float *) data)[x + y * Cols + z * Rows * Cols] = G3d_getFloat(map, x, y, z); } } } break; /* double data type */ case (VOL_DTYPE_DOUBLE) : for (x = 0; x < Cols; x++) { for (y = 0; y < Rows; y++) { for (z = 0; z < Depths; z++) { ((double *) data)[x + y * Cols + z * Rows * Cols] = G3d_getDouble(map, x, y, z); } } } break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ int is_null_g3d_value(IFLAG type, void *value) { switch (type) { /* float data type */ case (VOL_DTYPE_FLOAT) : return G3d_isNullValueNum(value, G3D_FLOAT); break; /* double data type */ case (VOL_DTYPE_DOUBLE) : return G3d_isNullValueNum(value, G3D_DOUBLE); break; /* unsupported data type */ default : return (-1); } } /******************************************************************/ /* reading from buffer */ /******************************************************************/ /******************************************************************/ /* get value from buffer */ int get_buff_value(IFLAG type, void *data, int offset, void *value) { switch (type) { /* float data type */ case (VOL_DTYPE_FLOAT) : *((float*) value) = ((float *) data)[offset]; break; /* double data type */ case (VOL_DTYPE_DOUBLE) : *((double*) value) = ((double *) data)[offset]; break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ /* direct mode reading from volume file */ /******************************************************************/ /******************************************************************/ /* read value direct from volume file */ int get_direct_value(geovol_file *vf, int x, int y, int z, void *value) { switch (vf->file_type) { /* G3D file type */ case (VOL_FTYPE_G3D) : if (0 > read_g3d_value(vf->data_type, vf->map, x, y, z, value)) return (-1); break; default : return (-1); } return (1); } /******************************************************************/ /* full mode reading from volume file */ /******************************************************************/ /******************************************************************/ /* allocate buffer memory for full mode reading */ int alloc_vol_buff(geovol_file *vf) { switch (vf->data_type) { /* float data type */ case (VOL_DTYPE_FLOAT) : if ((vf->buff = (float*) malloc(sizeof(float) * Cols * Rows * Depths)) == NULL) return (-1); break; /* double data type */ case (VOL_DTYPE_DOUBLE) : if ((vf->buff = (double*) malloc(sizeof(double) * Cols * Rows * Depths)) == NULL) return (-1); break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ /* free memory buffer memory */ int free_vol_buff(geovol_file *vf) { free(vf->buff); return (1); } /******************************************************************/ /* read all values from volume file */ int read_vol(geovol_file *vf) { switch (vf->file_type) { /* G3D file format */ case (VOL_FTYPE_G3D) : if (0 > read_g3d_vol(vf->data_type, vf->map, vf->buff)) return (-1); break; /* unsupported file format */ default : return (-1); } return (1); } /******************************************************************/ /* get value from volume buffer */ int get_vol_value(geovol_file *vf, int x, int y, int z, void *value) { get_buff_value(vf->data_type, vf->buff, z * Rows * Cols + y * Cols + x, value); return (1); } /******************************************************************/ /* slice mode reading from volume file */ /******************************************************************/ /******************************************************************/ /* allocate buffer for slice mode reading */ int alloc_slice_buff(geovol_file *vf) { int i; slice_data *sd = (slice_data *) vf->buff; switch (vf->data_type) { /* float data type */ case (VOL_DTYPE_FLOAT) : for (i = 0; i < sd->num; i++) { if ((sd->slice[i] = (float*) malloc(sizeof(float) * Cols * Rows)) == NULL) return (-1); } break; /* double data type */ case (VOL_DTYPE_DOUBLE) : for (i = 0; i < sd->num; i++) { if ((sd->slice[i] = (double*) malloc(sizeof(double) * Cols * Rows)) == NULL) return (-1); } break; /* unsupported data type */ default : return (-1); } return (1); } /******************************************************************/ /* free buffer for slice mode reading */ int free_slice_buff(geovol_file *vf) { int i; slice_data *sd = (slice_data *) vf->buff; for (i = 0; i < sd->num; i++) { free(sd->slice[i]); } return (1); } /******************************************************************/ /* read slice of values at level from volume file */ int read_slice(geovol_file *vf, int s, int l) { /* get slice structure */ slice_data *sd = (slice_data *) vf->buff; switch (vf->file_type) { /* G3D file format */ case (VOL_FTYPE_G3D) : if (0 > read_g3d_slice(vf->data_type, vf->map, l, sd->slice[s])) return (-1); break; /* unsupported file format */ default : return (-1); } return (1); } /******************************************************************/ /* read new slice into buffer */ void shift_slices(geovol_file *vf) { void *tmp; int i; slice_data *sd = (slice_data *) vf->buff; /* change pointers to slices */ tmp = sd->slice[0]; for (i = 0; i < sd->num - 1; i++) { sd->slice[i] = sd->slice[i+1]; } sd->slice[sd->num - 1] = tmp; /* read new slice data */ read_slice(vf, sd->num, sd->crnt + 1 + (sd->num - sd->base)); /* increase current slice value */ sd->crnt++; } /******************************************************************/ /* get value from slice buffer */ int get_slice_value(geovol_file *vf, int x, int y, int z, void *value) { slice_data *sd = (slice_data *) vf->buff; /* value is in loaded slices */ if ((z >= sd->crnt - (sd->base - 1)) && (z <= sd->crnt + sd->num - sd->base)) { get_buff_value(vf->data_type, sd->slice[(z - sd->crnt)], y * Cols + x, value); } /* if value isn't in loaded slices, need read new data slice */ else if (z == sd->crnt - (sd->base - 1) + 1) { shift_slices(vf); get_buff_value(vf->data_type, sd->slice[(z - sd->crnt)], y * Cols + x, value); } /* value out of range */ else { return (-1); } return (1); } /******************************************************************/ /* reading from volume file */ /******************************************************************/ /******************************************************************/ /* start read - allocate memory buffer a read first data into buffer */ int gvl_file_start_read(geovol_file *vf) { int i; slice_data *sd; /* check status */ if (vf->status == STATUS_BUSY) return (-1); switch (vf->mode) { /* read whole volume into memory */ case (MODE_FULL) : /* allocate memory */ if (0 > alloc_vol_buff(vf)) return (-1); /* read volume */ read_vol(vf); break; /* read first data slices into memory */ case (MODE_SLICE) : /* allocate slices buffer memory */ if (0 > alloc_slice_buff(vf)) return (-1); /* read volume */ sd = (slice_data *) vf->buff; /* set current slice to 0 */ sd->crnt = 0; /* read first slices into buffer */ for (i = 0; i < (sd->num - sd->base + 1); i++) read_slice(vf, (sd->base - 1) + i, i); break; } /* set status */ vf->status = STATUS_BUSY; return (1); } /******************************************************************/ /* end read - free buffer memory */ int gvl_file_end_read(geovol_file *vf) { /* check status */ if (vf->status == STATUS_READY) return (-1); switch (vf->mode) { case (MODE_FULL) : if (0 > free_vol_buff(vf)) return (-1); break; case (MODE_SLICE) : /* allocate slices buffer memory */ if (0 > free_slice_buff(vf)) return (-1); } /* set status */ vf->status = STATUS_READY; return (1); } /******************************************************************/ /* get value for volume file at x, y, z */ int gvl_file_get_value(geovol_file *vf, int x, int y, int z, void *value) { /* check status */ if (vf->status != STATUS_BUSY) { return (-1); } switch (vf->mode) { /* read value direct from g3d file */ case (MODE_DIRECT) : if (0 > get_direct_value(vf, x, y, z, value)) return (-1); break; case (MODE_SLICE) : if (0 > get_slice_value(vf, x, y, z, value)) return (-1); break; case (MODE_FULL) : case (MODE_PRELOAD) : if (0 > get_vol_value(vf, x, y, z, value)) return (-1); break; } return (1); } /******************************************************************/ int gvl_file_is_null_value(geovol_file *vf, void *value) { switch (vf->file_type) { /* G3D file format */ case (VOL_FTYPE_G3D) : return is_null_g3d_value(vf->file_type, value); break; /* unsupported file format */ default : return (-1); } } /******************************************************************/ /* set parameters for reading volumes */ /******************************************************************/ /******************************************************************/ /* set read mode */ int gvl_file_set_mode(geovol_file *vf, IFLAG mode) { slice_data *sd; if (vf->status == STATUS_BUSY) return (-1); if (vf->mode == mode) return (1); if (vf->mode == MODE_SLICE) free(vf->buff); if (vf->mode == MODE_PRELOAD) free(vf->buff); if (mode == MODE_SLICE) { if ((vf->buff = (slice_data *) malloc(sizeof(slice_data))) == NULL) return (-1); sd = (slice_data *) vf->buff; sd->num = 1; sd->crnt = 0; sd->base = 1; } if (mode == MODE_PRELOAD) { /* allocate memory */ if (0 > alloc_vol_buff(vf)) return (-1); /* read volume */ read_vol(vf); } vf->mode = mode; return (1); } /******************************************************************/ /* set parameters for slice reading */ int gvl_file_set_slices_param(geovol_file *vf, int n, int b) { slice_data *sd; if (vf->status == STATUS_BUSY) return (-1); if (!(vf->mode == MODE_SLICE)) return (-1); sd = (slice_data *) vf->buff; sd->num = n; sd->base = b; return (1); }