GRASS Programmer's Manual  6.4.1(2011)
null_val.c
Go to the documentation of this file.
00001 /*
00002  *
00003  *****************************************************************************
00004  *
00005  * MODULE:      GRASS gis library
00006  * AUTHOR(S):   Original author unknown - probably CERL
00007  *              Justin Hickey - Thailand - jhickey@hpcc.nectec.or.th
00008  * PURPOSE:     To provide functionality to handle NULL values for data types
00009  *              CELL, FCELL, and DCELL. May need more...
00010  * COPYRIGHT:    (C) 2000 by the GRASS Development Team
00011  *
00012  *               This program is free software under the GNU General Public
00013  *              License (>=v2). Read the file COPYING that comes with GRASS
00014  *              for details.
00015  *
00016  *****************************************************************************/
00017 
00018 /*============================= Include Files ==============================*/
00019 
00020 /* System include files */
00021 #include <string.h>
00022 
00023 /* Grass and local include files */
00024 #include <grass/gis.h>
00025 #include <grass/glocale.h>
00026 
00027 /*======================= Internal Constants/Defines =======================*/
00028 
00029 /* none */
00030 
00031 /*========================== Internal Typedefs =============================*/
00032 
00033 /* none */
00034 
00035 /*====================== Static Variable Declaration =======================*/
00036 
00037 /* Null pattern variables */
00038 static CELL cellNullPattern;
00039 static FCELL fcellNullPattern;
00040 static DCELL dcellNullPattern;
00041 
00042 /* Flag to indicate null patterns are initialized */
00043 static int initialized = FALSE;
00044 
00045 /*============================== Prototypes ================================*/
00046 
00047 static int EmbedGivenNulls(void *, char *, RASTER_MAP_TYPE, int);
00048 static void InitError(void);
00049 
00050 /*======================= Internal Static Functions ========================*/
00051 
00052 /****************************************************************************
00053 * int EmbedGivenNulls (void *cell, char *nulls, RASTER_MAP_TYPE map_type,
00054 *   int ncols)
00055 *
00056 * PURPOSE:      To insert null values into a map. Needs more.....
00057 * INPUT VARS:   cell        =>  ??
00058 *               nulls       =>  ??
00059 *               map_type    =>  type of raster - CELL, FCELL, DCELL
00060 *               ncols       =>  ??
00061 * RETURN VAL:   ??
00062 *****************************************************************************/
00063 static int EmbedGivenNulls(void *cell, char *nulls, RASTER_MAP_TYPE map_type,
00064                            int ncols)
00065 {
00066     CELL *c;
00067     FCELL *f;
00068     DCELL *d;
00069     int i;
00070 
00071     c = (CELL *) cell;
00072     f = (FCELL *) cell;
00073     d = (DCELL *) cell;
00074 
00075     for (i = 0; i < ncols; i++) {
00076         if (nulls[i]) {
00077             switch (map_type) {
00078             case CELL_TYPE:
00079                 G_set_c_null_value((CELL *) (c + i), 1);
00080                 break;
00081 
00082             case FCELL_TYPE:
00083                 G_set_f_null_value((FCELL *) (f + i), 1);
00084                 break;
00085 
00086             case DCELL_TYPE:
00087                 G_set_d_null_value((DCELL *) (d + i), 1);
00088                 break;
00089 
00090             default:
00091                 G_warning(_("EmbedGivenNulls: wrong data type!"));
00092             }
00093         }
00094     }
00095 
00096     return 1;
00097 }
00098 
00099 /****************************************************************************
00100 * void InitError (void)
00101 *
00102 * PURPOSE:      To print an error message and exit the program. This function
00103 *               is called if something tries to access a null pattern before
00104 *               it is initialized.
00105 * INPUT VARS:   none
00106 * RETURN VAL:   none
00107 *****************************************************************************/
00108 static void InitError(void)
00109 {
00110     char errMsg[512];           /* array to hold error message */
00111 
00112     strcpy(errMsg, _("Null values have not been initialized. "));
00113     strcat(errMsg, _("G_gisinit() must be called first. "));
00114     strcat(errMsg, _("Please advise GRASS developers of this error.\n"));
00115     G_fatal_error(errMsg);
00116 
00117     return;
00118 }
00119 
00120 /*========================== Library Functions =============================*/
00121 
00122 /****************************************************************************
00123 * void G__init_null_patterns (void)
00124 *
00125 * PURPOSE:      To initialize the three null patterns for CELL, FCELL, and
00126 *               DCELL data types. It also sets the initialized flag to TRUE.
00127 *               This function is called by G_gisinit()
00128 * INPUT VARS:   none
00129 * RETURN VAL:   none
00130 *****************************************************************************/
00131 void G__init_null_patterns(void)
00132 {
00133     unsigned char *bytePtr;     /* pointer to traverse FCELL and DCELL */
00134     int numBits;                /* number of bits for CELL type */
00135     int i;                      /* counter */
00136 
00137     if (!initialized) {
00138         /* Create the null pattern for the CELL data type - set the left */
00139         /* most bit to 1 and the rest to 0, basically INT_MIN. Since CELL is */
00140         /* some type of integer the bytes are not split into exponent and */
00141         /* mantissa. Thus a simple left shift can be used */
00142         numBits = sizeof(CELL) * 8;
00143 
00144         cellNullPattern = 1 << (numBits - 1);
00145 
00146         /* Create the null pattern for the FCELL data type - set all bits */
00147         /* to 1, basically NaN. Need to use a byte pointer since bytes */
00148         /* represent the exponent and mantissa */
00149         bytePtr = (unsigned char *)&fcellNullPattern;
00150 
00151         for (i = 0; i < sizeof(FCELL); i++) {
00152             *bytePtr = (unsigned char)255;
00153             bytePtr++;
00154         }
00155 
00156         /* Create the null pattern for the DCELL data type - set all bits */
00157         /* to 1, basically NaN. Need to use a byte pointer since bytes */
00158         /* represent the exponent and mantissa */
00159         bytePtr = (unsigned char *)&dcellNullPattern;
00160 
00161         for (i = 0; i < sizeof(DCELL); i++) {
00162             *bytePtr = (unsigned char)255;
00163             bytePtr++;
00164         }
00165 
00166         /* Set the initialized flag to TRUE */
00167         initialized = TRUE;
00168     }
00169 
00170     return;
00171 }
00172 
00173 /****************************************************************************
00174 * void G__set_null_value (void *rast, int numVals, int null_is_zero,
00175 *   RASTER_MAP_TYPE data_type)
00176 *
00177 * PURPOSE:      To set one or more raster values to null. It also sets null
00178 *               to zero if null_is_zero is TRUE.
00179 * INPUT VARS:   rast            =>  pointer to values to set to null
00180 *               numVals         =>  number of values to set to null
00181 *               null_is_zero    =>  flag to indicate if NULL = 0
00182 *               data_type       =>  type of raster - CELL, FCELL, DCELL
00183 * RETURN VAL:   none
00184 *****************************************************************************/
00185 void G__set_null_value(void *rast, int numVals, int null_is_zero,
00186                        RASTER_MAP_TYPE data_type)
00187 {
00188     if (null_is_zero) {
00189         G_zero((char *)rast, numVals * G_raster_size(data_type));
00190         return;
00191     }
00192 
00193     G_set_null_value(rast, numVals, data_type);
00194 
00195     return;
00196 }
00197 
00198 /****************************************************************************
00199 * void G_set_null_value (void *buf, int numVals, RASTER_MAP_TYPE data_type)
00200 *
00201 * PURPOSE:      To set one or more raster values to null.
00202 * INPUT VARS:   buf         =>  pointer to values to set to null
00203 *               numVals     =>  number of values to set to null
00204 *               data_type   =>  type of raster - CELL, FCELL, DCELL
00205 * RETURN VAL:   none
00206 *****************************************************************************/
00207 void G_set_null_value(void *buf, int numVals, RASTER_MAP_TYPE data_type)
00208 {
00209     switch (data_type) {
00210     case CELL_TYPE:
00211         G_set_c_null_value((CELL *) buf, numVals);
00212         break;
00213 
00214     case FCELL_TYPE:
00215         G_set_f_null_value((FCELL *) buf, numVals);
00216         break;
00217 
00218     case DCELL_TYPE:
00219         G_set_d_null_value((DCELL *) buf, numVals);
00220         break;
00221 
00222     default:
00223         G_warning(_("G_set_null_value: wrong data type!"));
00224     }
00225 
00226     return;
00227 }
00228 
00229 /****************************************************************************
00230 * void G_set_c_null_value (CELL *cellVals, int numVals)
00231 *
00232 * PURPOSE:      To set a number of CELL raster values to NULL.
00233 * INPUT VARS:   cellVals    =>  pointer to CELL values to set to null
00234 *               numVals     =>  number of values to set to null
00235 * RETURN VAL:   none
00236 *****************************************************************************/
00237 void G_set_c_null_value(CELL * cellVals, int numVals)
00238 {
00239     CELL *cellPtr;              /* pointer to CELL array to set to null */
00240     int i;                      /* counter */
00241 
00242     /* Check if the null patterns have been initialized */
00243     if (!initialized) {
00244         InitError();
00245     }
00246 
00247     /* Set numVals consecutive CELL values to null */
00248     cellPtr = cellVals;
00249 
00250     for (i = 0; i < numVals; i++) {
00251         *cellPtr = cellNullPattern;
00252         cellPtr++;
00253     }
00254 
00255     return;
00256 }
00257 
00258 /****************************************************************************
00259 * void G_set_f_null_value (FCELL *fcellVals, int numVals)
00260 *
00261 * PURPOSE:      To set a number of FCELL raster values to NULL.
00262 * INPUT VARS:   fcellVals   =>  pointer to FCELL values to set to null
00263 *               numVals     =>  number of values to set to null
00264 * RETURN VAL:   none
00265 *****************************************************************************/
00266 void G_set_f_null_value(FCELL * fcellVals, int numVals)
00267 {
00268     FCELL *fcellPtr;            /* pointer to FCELL array to set to null */
00269     int i;                      /* counter */
00270 
00271     /* Check if the null patterns have been initialized */
00272     if (!initialized) {
00273         InitError();
00274     }
00275 
00276     /* Set numVals consecutive FCELL values to null */
00277     fcellPtr = fcellVals;
00278 
00279     for (i = 0; i < numVals; i++) {
00280         *fcellPtr = fcellNullPattern;
00281         fcellPtr++;
00282     }
00283 
00284     return;
00285 }
00286 
00287 /****************************************************************************
00288 * void G_set_d_null_value (DCELL *dcellVals, int numVals)
00289 *
00290 * PURPOSE:      To set a number of DCELL raster values to NULL.
00291 * INPUT VARS:   dcellVals   =>  pointer to DCELL values to set to null
00292 *               numVals     =>  number of values to set to null
00293 * RETURN VAL:   none
00294 *****************************************************************************/
00295 void G_set_d_null_value(DCELL * dcellVals, int numVals)
00296 {
00297     DCELL *dcellPtr;            /* pointer to DCELL array to set to null */
00298     int i;                      /* counter */
00299 
00300     /* Check if the null patterns have been initialized */
00301     if (!initialized) {
00302         InitError();
00303     }
00304 
00305     /* Set numVals consecutive DCELL values to null */
00306     dcellPtr = dcellVals;
00307 
00308     for (i = 0; i < numVals; i++) {
00309         *dcellPtr = dcellNullPattern;
00310         dcellPtr++;
00311     }
00312 
00313     return;
00314 }
00315 
00316 /****************************************************************************
00317 * int G_is_null_value (void *rast, RASTER_MAP_TYPE data_type)
00318 *
00319 * PURPOSE:      To check if a raster value is set to NULL
00320 * INPUT VARS:   rast        =>  raster value to check 
00321 *               data_type   =>  type of raster - CELL, FCELL, DCELL
00322 * RETURN VAL:   TRUE if raster value is NULL FALSE otherwise
00323 *****************************************************************************/
00324 
00337 int G_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
00338 {
00339     switch (data_type) {
00340     case CELL_TYPE:
00341         return (G_is_c_null_value((CELL *) rast));
00342 
00343     case FCELL_TYPE:
00344         return (G_is_f_null_value((FCELL *) rast));
00345 
00346     case DCELL_TYPE:
00347         return (G_is_d_null_value((DCELL *) rast));
00348 
00349     default:
00350         G_warning("G_is_null_value: wrong data type!");
00351         return FALSE;
00352     }
00353 }
00354 
00355 /****************************************************************************
00356 * 
00357 * int G_is_c_null_value (CELL *cellVal)
00358 *
00359 * PURPOSE:      To check if a CELL raster value is set to NULL
00360 * INPUT VARS:   cellVal    =>   CELL raster value to check
00361 * RETURN VAL:   TRUE if CELL raster value is NULL FALSE otherwise
00362 *****************************************************************************/
00363 
00374 int G_is_c_null_value(const CELL * cellVal)
00375 {
00376     int i;                      /* counter */
00377 
00378     /* Check if the null patterns have been initialized */
00379     if (!initialized) {
00380         InitError();
00381     }
00382 
00383     /* Check if the CELL value matches the null pattern */
00384     for (i = 0; i < sizeof(CELL); i++) {
00385         if (((unsigned char *)cellVal)[i] !=
00386             ((unsigned char *)&cellNullPattern)[i]) {
00387             return FALSE;
00388         }
00389     }
00390 
00391     return TRUE;
00392 }
00393 
00394 /****************************************************************************
00395 * 
00396 * int G_is_f_null_value (FCELL *fcellVal)
00397 *
00398 * PURPOSE:      To check if a FCELL raster value is set to NULL
00399 * INPUT VARS:   fcellVal    =>  FCELL raster value to check
00400 * RETURN VAL:   TRUE if FCELL raster value is NULL FALSE otherwise
00401 *****************************************************************************/
00402 
00425 int G_is_f_null_value(const FCELL * fcellVal)
00426 {
00427     return *fcellVal != *fcellVal;
00428 }
00429 
00430 /****************************************************************************
00431 * 
00432 * int G_is_d_null_value (DCELL *dcellVal)
00433 *
00434 * PURPOSE:      To check if a DCELL raster value is set to NULL
00435 * INPUT VARS:   dcellVal    =>  DCELL raster value to check
00436 * RETURN VAL:   TRUE if DCELL raster value is NULL FALSE otherwise
00437 *****************************************************************************/
00438 
00450 int G_is_d_null_value(const DCELL * dcellVal)
00451 {
00452     return *dcellVal != *dcellVal;
00453 }
00454 
00455 /****************************************************************************
00456 * 
00457 * int G_insert_null_values (void *rast, char *null_row, int ncols,
00458 *   RASTER_MAP_TYPE data_type)
00459 *
00460 * PURPOSE:      To insert null values into a map. Needs more.....
00461 * INPUT VARS:   rast        =>  ??
00462 *               null_row    =>  ??
00463 *               ncols       =>  ??
00464 *               data_type   =>  type of raster - CELL, FCELL, DCELL
00465 * RETURN VAL:   ??
00466 *****************************************************************************/
00467 
00485 int G_insert_null_values(void *rast, char *null_row, int ncols,
00486                          RASTER_MAP_TYPE data_type)
00487 {
00488     return (EmbedGivenNulls(rast, null_row, data_type, ncols));
00489 }
00490 
00491 /****************************************************************************
00492 * 
00493 * int G_insert_c_null_values (CELL *cellVal, char *null_row, int ncols)
00494 *
00495 * PURPOSE:      To insert null values into a CELL map. Needs more.....
00496 * INPUT VARS:   cellVal     =>  ??
00497 *               null_row    =>  ??
00498 *               ncols       =>  ??
00499 * RETURN VAL:   ??
00500 *****************************************************************************/
00501 
00514 int G_insert_c_null_values(CELL * cellVal, char *null_row, int ncols)
00515 {
00516     return (EmbedGivenNulls((void *)cellVal, null_row, CELL_TYPE, ncols));
00517 }
00518 
00519 /****************************************************************************
00520 * 
00521 * int G_insert_f_null_values (FCELL *fcellVal, char *null_row, int ncols)
00522 *
00523 * PURPOSE:      To insert null values into a FCELL map. Needs more.....
00524 * INPUT VARS:   fcellVal    =>  ??
00525 *               null_row    =>  ??
00526 *               ncols       =>  ??
00527 * RETURN VAL:   ??
00528 *****************************************************************************/
00529 
00542 int G_insert_f_null_values(FCELL * fcellVal, char *null_row, int ncols)
00543 {
00544     return (EmbedGivenNulls((void *)fcellVal, null_row, FCELL_TYPE, ncols));
00545 }
00546 
00547 /****************************************************************************
00548 * 
00549 * int G_insert_d_null_values (DCELL *dcellVal, char *null_row, int ncols)
00550 *
00551 * PURPOSE:      To insert null values into a DCELL map. Needs more.....
00552 * INPUT VARS:   dcellVal    =>  ??
00553 *               null_row    =>  ??
00554 *               ncols       =>  ??
00555 * RETURN VAL:   ??
00556 *****************************************************************************/
00557 
00570 int G_insert_d_null_values(DCELL * dcellVal, char *null_row, int ncols)
00571 {
00572     return (EmbedGivenNulls((void *)dcellVal, null_row, DCELL_TYPE, ncols));
00573 }
00574 
00575 /****************************************************************************
00576 * int G__check_null_bit (unsigned char *flags, int bit_num, int n)
00577 *
00578 * PURPOSE:      To...
00579 * INPUT VARS:   flags   =>  ??
00580 *               bit_num =>  ??
00581 *               n       =>  ??
00582 * RETURN VAL:   ??
00583 *****************************************************************************/
00584 int G__check_null_bit(const unsigned char *flags, int bit_num, int n)
00585 {
00586     int ind;
00587     int offset;
00588 
00589     /* find the index of the unsigned char in which this bit appears */
00590     ind = G__null_bitstream_size(bit_num + 1) - 1;
00591 
00592     /* find how many unsigned chars the buffer with bit_num+1 (counting from 0
00593        has and subtract 1 to get unsigned char index */
00594     if (ind > G__null_bitstream_size(n) - 1) {
00595         G_warning("G__check_null_bit: can't access index %d. "
00596                   "Size of flags is %d (bit # is %d",
00597              ind, G__null_bitstream_size(n) - 1, bit_num);
00598         return -1;
00599     }
00600 
00601     offset = (ind + 1) * 8 - bit_num - 1;
00602 
00603     return ((flags[ind] & ((unsigned char)1 << offset)) != 0);
00604 }
00605 
00606 /****************************************************************************
00607 * int G__set_flags_from_01_random (char *zero_ones, unsigned char *flags, 
00608 *   int col, int n, int ncols)
00609 *
00610 * PURPOSE:      given array of 0/1 of length n starting from column col
00611 *               set the corresponding  bits of flags; total number of bits
00612 *               in flags is ncols
00613 * INPUT VARS:   zero_ones   =>  ??
00614 *               flags       =>  ??
00615 *               col         =>  ??
00616 *               n           =>  ??
00617 *               ncols       =>  ??
00618 * RETURN VAL:   ??
00619 *****************************************************************************/
00620 int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags,
00621                                 int col, int n, int ncols)
00622 {
00623     unsigned char v;
00624     int count;
00625     int size;
00626     int i, k;
00627 
00628     if (col == 0 && n == ncols) {
00629         G__convert_01_flags(zero_ones, flags, n);
00630         return 0;
00631     }
00632 
00633     count = 0;
00634     size = G__null_bitstream_size(ncols);
00635 
00636     for (i = 0; i < size; i++) {
00637         v = 0;
00638         k = 8;
00639 
00640         while (k-- > 0) {
00641             if (count >= col && count < (col + n)) {
00642                 v = v | ((unsigned char)zero_ones[count - col] << k);
00643             }
00644             else if (count < ncols) {
00645                 v = v |
00646                     ((unsigned char)G__check_null_bit(flags, count, ncols) << k);
00647             }
00648 
00649             /* otherwise  keep this bit the same as it was */
00650             count++;
00651         }
00652 
00653         flags[i] = v;
00654     }
00655 
00656     return 1;
00657 }
00658 
00659 /****************************************************************************
00660 * int G__convert_01_flags (char *zero_ones, unsigned char *flags, int n)
00661 *
00662 * PURPOSE:      To...
00663 * INPUT VARS:   zero_ones   =>  ??
00664 *               flags       =>  ??
00665 *               n           =>  ??
00666 * RETURN VAL:   ??
00667 *****************************************************************************/
00668 int G__convert_01_flags(const char *zero_ones, unsigned char *flags, int n)
00669 {
00670     unsigned char *v;
00671     int count;
00672     int size;
00673     int i, k;
00674 
00675     /* pad the flags with 0's to make size multiple of 8 */
00676     v = flags;
00677     size = G__null_bitstream_size(n);
00678     count = 0;
00679 
00680     for (i = 0; i < size; i++) {
00681         *v = 0;
00682         k = 8;
00683 
00684         while (k-- > 0) {
00685             if (count < n) {
00686                 *v = *v | ((unsigned char)zero_ones[count] << k);
00687             }
00688 
00689             count++;
00690         }
00691 
00692         v++;
00693     }
00694 
00695     return 0;
00696 }
00697 
00698 /****************************************************************************
00699 * int G__convert_flags_01 (char *zero_ones, unsigned char *flags, int n)
00700 *
00701 * PURPOSE:      To...
00702 * INPUT VARS:   zero_ones   =>  ??
00703 *               flags       =>  ??
00704 *               n           =>  ??
00705 * RETURN VAL:   ??
00706 *****************************************************************************/
00707 int G__convert_flags_01(char *zero_ones, const unsigned char *flags, int n)
00708 {
00709     const unsigned char *v;
00710     int count;
00711     int size;
00712     int i, k;
00713 
00714     count = 0;
00715     v = flags;
00716     size = G__null_bitstream_size(n);
00717 
00718     for (i = 0; i < size; i++) {
00719         k = 8;
00720 
00721         while (k-- > 0) {
00722             if (count < n) {
00723                 zero_ones[count] = ((*v & ((unsigned char)1 << k)) != 0);
00724                 count++;
00725             }
00726         }
00727 
00728         v++;
00729     }
00730 
00731     return 0;
00732 }
00733 
00734 /****************************************************************************
00735 * int G__init_null_bits (unsigned char *flags, int cols)
00736 *
00737 * PURPOSE:      To...
00738 * INPUT VARS:   flags   =>  ??
00739 *               cols    =>  ??
00740 * RETURN VAL:   ??
00741 *****************************************************************************/
00742 int G__init_null_bits(unsigned char *flags, int cols)
00743 {
00744     unsigned char *v;
00745     int size;
00746     int i;
00747 
00748     /* pad the flags with 0's to make size multiple of 8 */
00749     v = flags;
00750     size = G__null_bitstream_size(cols);
00751 
00752     for (i = 0; i < size; i++) {
00753         if ((i + 1) * 8 <= cols) {
00754             *v = (unsigned char)255;
00755         }
00756         else {
00757             *v = (unsigned char)255 << ((i + 1) * 8 - cols);
00758         }
00759 
00760         v++;
00761     }
00762 
00763     return 0;
00764 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines