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 { 00077 if(nulls[i]) 00078 { 00079 switch (map_type) 00080 { 00081 case CELL_TYPE: 00082 G_set_c_null_value((CELL *) (c + i), 1); 00083 break; 00084 00085 case FCELL_TYPE: 00086 G_set_f_null_value((FCELL *) (f + i), 1); 00087 break; 00088 00089 case DCELL_TYPE: 00090 G_set_d_null_value((DCELL *) (d + i), 1); 00091 break; 00092 00093 default: 00094 G_warning(_("EmbedGivenNulls: wrong data type!")); 00095 } 00096 } 00097 } 00098 00099 return 1; 00100 } 00101 00102 /**************************************************************************** 00103 * void InitError (void) 00104 * 00105 * PURPOSE: To print an error message and exit the program. This function 00106 * is called if something tries to access a null pattern before 00107 * it is initialized. 00108 * INPUT VARS: none 00109 * RETURN VAL: none 00110 *****************************************************************************/ 00111 static void InitError (void) 00112 { 00113 char errMsg[512]; /* array to hold error message */ 00114 00115 strcpy(errMsg, _("Null values have not been initialized. ")); 00116 strcat(errMsg, _("G_gisinit() must be called first. ")); 00117 strcat(errMsg, _("Please advise GRASS developers of this error.\n")); 00118 G_fatal_error(errMsg); 00119 00120 return; 00121 } 00122 00123 /*========================== Library Functions =============================*/ 00124 00125 /**************************************************************************** 00126 * void G__init_null_patterns (void) 00127 * 00128 * PURPOSE: To initialize the three null patterns for CELL, FCELL, and 00129 * DCELL data types. It also sets the initialized flag to TRUE. 00130 * This function is called by G_gisinit() 00131 * INPUT VARS: none 00132 * RETURN VAL: none 00133 *****************************************************************************/ 00134 void G__init_null_patterns (void) 00135 { 00136 unsigned char *bytePtr; /* pointer to traverse FCELL and DCELL */ 00137 int numBits; /* number of bits for CELL type */ 00138 int i; /* counter */ 00139 00140 if (!initialized) 00141 { 00142 /* Create the null pattern for the CELL data type - set the left */ 00143 /* most bit to 1 and the rest to 0, basically INT_MIN. Since CELL is */ 00144 /* some type of integer the bytes are not split into exponent and */ 00145 /* mantissa. Thus a simple left shift can be used */ 00146 numBits = sizeof(CELL) * 8; 00147 00148 cellNullPattern = 1 << (numBits - 1); 00149 00150 /* Create the null pattern for the FCELL data type - set all bits */ 00151 /* to 1, basically NaN. Need to use a byte pointer since bytes */ 00152 /* represent the exponent and mantissa */ 00153 bytePtr = (unsigned char *) &fcellNullPattern; 00154 00155 for (i = 0; i < sizeof(FCELL); i++) 00156 { 00157 *bytePtr = (unsigned char) 255; 00158 bytePtr++; 00159 } 00160 00161 /* Create the null pattern for the DCELL data type - set all bits */ 00162 /* to 1, basically NaN. Need to use a byte pointer since bytes */ 00163 /* represent the exponent and mantissa */ 00164 bytePtr = (unsigned char *) &dcellNullPattern; 00165 00166 for (i = 0; i < sizeof(DCELL); i++) 00167 { 00168 *bytePtr = (unsigned char) 255; 00169 bytePtr++; 00170 } 00171 00172 /* Set the initialized flag to TRUE */ 00173 initialized = TRUE; 00174 } 00175 00176 return; 00177 } 00178 00179 /**************************************************************************** 00180 * void G__set_null_value (void *rast, int numVals, int null_is_zero, 00181 * RASTER_MAP_TYPE data_type) 00182 * 00183 * PURPOSE: To set one or more raster values to null. It also sets null 00184 * to zero if null_is_zero is TRUE. 00185 * INPUT VARS: rast => pointer to values to set to null 00186 * numVals => number of values to set to null 00187 * null_is_zero => flag to indicate if NULL = 0 00188 * data_type => type of raster - CELL, FCELL, DCELL 00189 * RETURN VAL: none 00190 *****************************************************************************/ 00191 void G__set_null_value (void *rast, int numVals, int null_is_zero, 00192 RASTER_MAP_TYPE data_type) 00193 { 00194 if (null_is_zero) 00195 { 00196 G_zero((char *) rast, numVals * G_raster_size(data_type)); 00197 return; 00198 } 00199 00200 G_set_null_value(rast, numVals, data_type); 00201 00202 return; 00203 } 00204 00205 /**************************************************************************** 00206 * void G_set_null_value (void *buf, int numVals, RASTER_MAP_TYPE data_type) 00207 * 00208 * PURPOSE: To set one or more raster values to null. 00209 * INPUT VARS: rast => pointer to values to set to null 00210 * numVals => number of values to set to null 00211 * data_type => type of raster - CELL, FCELL, DCELL 00212 * RETURN VAL: none 00213 *****************************************************************************/ 00214 void G_set_null_value (void *buf, int numVals, RASTER_MAP_TYPE data_type) 00215 { 00216 switch (data_type) 00217 { 00218 case CELL_TYPE: 00219 G_set_c_null_value((CELL *) buf, numVals); 00220 break; 00221 00222 case FCELL_TYPE: 00223 G_set_f_null_value((FCELL *) buf, numVals); 00224 break; 00225 00226 case DCELL_TYPE: 00227 G_set_d_null_value((DCELL *) buf, numVals); 00228 break; 00229 00230 default: 00231 G_warning(_("G_set_null_value: wrong data type!")); 00232 } 00233 00234 return; 00235 } 00236 00237 /**************************************************************************** 00238 * void G_set_c_null_value (CELL *cellVals, int numVals) 00239 * 00240 * PURPOSE: To set a number of CELL raster values to NULL. 00241 * INPUT VARS: cellVals => pointer to CELL values to set to null 00242 * numVals => number of values to set to null 00243 * RETURN VAL: none 00244 *****************************************************************************/ 00245 void G_set_c_null_value (CELL *cellVals, int numVals) 00246 { 00247 CELL *cellPtr; /* pointer to CELL array to set to null */ 00248 int i; /* counter */ 00249 00250 /* Check if the null patterns have been initialized */ 00251 if (!initialized) 00252 { 00253 InitError(); 00254 } 00255 00256 /* Set numVals consecutive CELL values to null */ 00257 cellPtr = cellVals; 00258 00259 for (i = 0; i < numVals; i++) 00260 { 00261 *cellPtr = cellNullPattern; 00262 cellPtr++; 00263 } 00264 00265 return; 00266 } 00267 00268 /**************************************************************************** 00269 * void G_set_f_null_value (FCELL *fcellVals, int numVals) 00270 * 00271 * PURPOSE: To set a number of FCELL raster values to NULL. 00272 * INPUT VARS: fcellVals => pointer to FCELL values to set to null 00273 * numVals => number of values to set to null 00274 * RETURN VAL: none 00275 *****************************************************************************/ 00276 void G_set_f_null_value (FCELL *fcellVals, int numVals) 00277 { 00278 FCELL *fcellPtr; /* pointer to FCELL array to set to null */ 00279 int i; /* counter */ 00280 00281 /* Check if the null patterns have been initialized */ 00282 if (!initialized) 00283 { 00284 InitError(); 00285 } 00286 00287 /* Set numVals consecutive FCELL values to null */ 00288 fcellPtr = fcellVals; 00289 00290 for (i = 0; i < numVals; i++) 00291 { 00292 *fcellPtr = fcellNullPattern; 00293 fcellPtr++; 00294 } 00295 00296 return; 00297 } 00298 00299 /**************************************************************************** 00300 * void G_set_d_null_value (DCELL *dcellVals, int numVals) 00301 * 00302 * PURPOSE: To set a number of DCELL raster values to NULL. 00303 * INPUT VARS: dcellVals => pointer to DCELL values to set to null 00304 * numVals => number of values to set to null 00305 * RETURN VAL: none 00306 *****************************************************************************/ 00307 void G_set_d_null_value (DCELL *dcellVals, int numVals) 00308 { 00309 DCELL *dcellPtr; /* pointer to DCELL array to set to null */ 00310 int i; /* counter */ 00311 00312 /* Check if the null patterns have been initialized */ 00313 if (!initialized) 00314 { 00315 InitError(); 00316 } 00317 00318 /* Set numVals consecutive DCELL values to null */ 00319 dcellPtr = dcellVals; 00320 00321 for (i = 0; i < numVals; i++) 00322 { 00323 *dcellPtr = dcellNullPattern; 00324 dcellPtr++; 00325 } 00326 00327 return; 00328 } 00329 00330 /**************************************************************************** 00331 * int G_is_null_value (void *rast, RASTER_MAP_TYPE data_type) 00332 * 00333 * PURPOSE: To check if a raster value is set to NULL 00334 * INPUT VARS: rast => raster value to check 00335 * data_type => type of raster - CELL, FCELL, DCELL 00336 * RETURN VAL: TRUE if raster value is NULL FALSE otherwise 00337 *****************************************************************************/ 00338 00354 int G_is_null_value (const void *rast, RASTER_MAP_TYPE data_type) 00355 { 00356 switch(data_type) 00357 { 00358 case CELL_TYPE: 00359 return (G_is_c_null_value((CELL *) rast)); 00360 00361 case FCELL_TYPE: 00362 return (G_is_f_null_value((FCELL *) rast)); 00363 00364 case DCELL_TYPE: 00365 return (G_is_d_null_value((DCELL *) rast)); 00366 00367 default: 00368 G_warning("G_is_null_value: wrong data type!"); 00369 return FALSE; 00370 } 00371 } 00372 00373 /**************************************************************************** 00374 * 00375 * int G_is_c_null_value (CELL *cellVal) 00376 * 00377 * PURPOSE: To check if a CELL raster value is set to NULL 00378 * INPUT VARS: cellVal => CELL raster value to check 00379 * RETURN VAL: TRUE if CELL raster value is NULL FALSE otherwise 00380 *****************************************************************************/ 00381 00392 int G_is_c_null_value (const CELL *cellVal) 00393 { 00394 int i; /* counter */ 00395 00396 /* Check if the null patterns have been initialized */ 00397 if (!initialized) 00398 { 00399 InitError(); 00400 } 00401 00402 /* Check if the CELL value matches the null pattern */ 00403 for(i = 0; i < sizeof (CELL); i++) 00404 { 00405 if(((unsigned char *) cellVal)[i] != 00406 ((unsigned char *) &cellNullPattern)[i]) 00407 { 00408 return FALSE; 00409 } 00410 } 00411 00412 return TRUE; 00413 } 00414 00415 /**************************************************************************** 00416 * 00417 * int G_is_f_null_value (FCELL *fcellVal) 00418 * 00419 * PURPOSE: To check if a FCELL raster value is set to NULL 00420 * INPUT VARS: fcellVal => FCELL raster value to check 00421 * RETURN VAL: TRUE if FCELL raster value is NULL FALSE otherwise 00422 *****************************************************************************/ 00423 00446 int G_is_f_null_value (const FCELL *fcellVal) 00447 { 00448 int i; /* counter */ 00449 00450 /* Check if the null patterns have been initialized */ 00451 if (!initialized) 00452 { 00453 InitError(); 00454 } 00455 00456 /* Check if the FCELL value matches the null pattern */ 00457 for(i = 0; i < sizeof (FCELL); i++) 00458 { 00459 if(((unsigned char *) fcellVal)[i] != 00460 ((unsigned char *) &fcellNullPattern)[i]) 00461 { 00462 return FALSE; 00463 } 00464 } 00465 00466 return TRUE; 00467 } 00468 00469 /**************************************************************************** 00470 * 00471 * int G_is_d_null_value (DCELL *dcellVal) 00472 * 00473 * PURPOSE: To check if a DCELL raster value is set to NULL 00474 * INPUT VARS: dcellVal => DCELL raster value to check 00475 * RETURN VAL: TRUE if DCELL raster value is NULL FALSE otherwise 00476 *****************************************************************************/ 00477 00489 int G_is_d_null_value (const DCELL *dcellVal) 00490 { 00491 int i; /* counter */ 00492 00493 /* Check if the null patterns have been initialized */ 00494 if (!initialized) 00495 { 00496 InitError(); 00497 } 00498 00499 /* Check if the DCELL value matches the null pattern */ 00500 for(i = 0; i < sizeof (DCELL); i++) 00501 { 00502 if(((unsigned char *) dcellVal)[i] != 00503 ((unsigned char *) &dcellNullPattern)[i]) 00504 { 00505 return FALSE; 00506 } 00507 } 00508 00509 return TRUE; 00510 } 00511 00512 /**************************************************************************** 00513 * 00514 * int G_insert_null_values (void *rast, char *null_row, int ncols, 00515 * RASTER_MAP_TYPE data_type) 00516 * 00517 * PURPOSE: To insert null values into a map. Needs more..... 00518 * INPUT VARS: rast => ?? 00519 * null_row => ?? 00520 * ncols => ?? 00521 * data_type => type of raster - CELL, FCELL, DCELL 00522 * RETURN VAL: ?? 00523 *****************************************************************************/ 00524 00542 int G_insert_null_values (void *rast, char *null_row, int ncols, 00543 RASTER_MAP_TYPE data_type) 00544 { 00545 return (EmbedGivenNulls(rast, null_row, data_type, ncols)); 00546 } 00547 00548 /**************************************************************************** 00549 * 00550 * int G_insert_c_null_values (CELL *cellVal, char *null_row, int ncols) 00551 * 00552 * PURPOSE: To insert null values into a CELL map. Needs more..... 00553 * INPUT VARS: cellVal => ?? 00554 * null_row => ?? 00555 * ncols => ?? 00556 * RETURN VAL: ?? 00557 *****************************************************************************/ 00558 00571 int G_insert_c_null_values (CELL *cellVal, char *null_row, int ncols) 00572 { 00573 return (EmbedGivenNulls((void *) cellVal, null_row, CELL_TYPE, ncols)); 00574 } 00575 00576 /**************************************************************************** 00577 * 00578 * int G_insert_f_null_values (FCELL *fcellVal, char *null_row, int ncols) 00579 * 00580 * PURPOSE: To insert null values into a FCELL map. Needs more..... 00581 * INPUT VARS: fcellVal => ?? 00582 * null_row => ?? 00583 * ncols => ?? 00584 * RETURN VAL: ?? 00585 *****************************************************************************/ 00586 00599 int G_insert_f_null_values (FCELL *fcellVal, char *null_row, int ncols) 00600 { 00601 return (EmbedGivenNulls((void *) fcellVal, null_row, FCELL_TYPE, ncols)); 00602 } 00603 00604 /**************************************************************************** 00605 * 00606 * int G_insert_d_null_values (DCELL *dcellVal, char *null_row, int ncols) 00607 * 00608 * PURPOSE: To insert null values into a DCELL map. Needs more..... 00609 * INPUT VARS: dcellVal => ?? 00610 * null_row => ?? 00611 * ncols => ?? 00612 * RETURN VAL: ?? 00613 *****************************************************************************/ 00614 00627 int G_insert_d_null_values (DCELL *dcellVal, char *null_row, int ncols) 00628 { 00629 return (EmbedGivenNulls((void *) dcellVal, null_row, DCELL_TYPE, ncols)); 00630 } 00631 00632 /**************************************************************************** 00633 * int G__check_null_bit (unsigned char *flags, int bit_num, int n) 00634 * 00635 * PURPOSE: To... 00636 * INPUT VARS: flags => ?? 00637 * bit_num => ?? 00638 * n => ?? 00639 * RETURN VAL: ?? 00640 *****************************************************************************/ 00641 int G__check_null_bit (unsigned char *flags, int bit_num, int n) 00642 { 00643 int ind; 00644 int offset; 00645 00646 /* find the index of the unsigned char in which this bit appears */ 00647 ind = G__null_bitstream_size(bit_num + 1) - 1; 00648 00649 /* find how many unsigned chars the buffer with bit_num+1 (counting from 0 00650 has and subtract 1 to get unsigned char index */ 00651 if (ind > G__null_bitstream_size(n) - 1 ) 00652 { 00653 G_warning("G__check_null_bit: can't access index %d. Size of flags is %d (bit # is %d", ind, G__null_bitstream_size(n) - 1, bit_num); 00654 return -1; 00655 } 00656 00657 offset = (ind+1)*8 - bit_num - 1; 00658 00659 return ((flags[ind] & ( (unsigned char) 1 << offset)) != 0); 00660 } 00661 00662 /**************************************************************************** 00663 * int G__set_flags_from_01_random (char *zero_ones, unsigned char *flags, 00664 * int col, int n, int ncols) 00665 * 00666 * PURPOSE: given array of 0/1 of length n starting from column col 00667 * set the corresponding bits of flags; total number of bits 00668 * in flags is ncols 00669 * INPUT VARS: zero_ones => ?? 00670 * flags => ?? 00671 * col => ?? 00672 * n => ?? 00673 * ncols => ?? 00674 * RETURN VAL: ?? 00675 *****************************************************************************/ 00676 int G__set_flags_from_01_random (char *zero_ones, unsigned char *flags, 00677 int col, int n, int ncols) 00678 { 00679 unsigned char v; 00680 int count; 00681 int size; 00682 int i, k; 00683 00684 if (col==0 && n == ncols) 00685 { 00686 G__convert_01_flags(zero_ones, flags, n); 00687 return 0; 00688 } 00689 00690 count = 0; 00691 size = G__null_bitstream_size(ncols); 00692 00693 for (i = 0; i < size; i++) 00694 { 00695 v = 0; 00696 k = 8; 00697 00698 while (k-- > 0) 00699 { 00700 if (count >= col && count < (col+ n)) 00701 { 00702 v = v | ((unsigned char) zero_ones[count - col] << k); 00703 } 00704 else if(count < ncols) 00705 { 00706 v = v | 00707 ((unsigned char) G__check_null_bit(flags, count, ncols) << k); 00708 } 00709 00710 /* otherwise keep this bit the same as it was */ 00711 count++; 00712 } 00713 00714 flags[i] = v; 00715 } 00716 00717 return 1; 00718 } 00719 00720 /**************************************************************************** 00721 * int G__convert_01_flags (char *zero_ones, unsigned char *flags, int n) 00722 * 00723 * PURPOSE: To... 00724 * INPUT VARS: zero_ones => ?? 00725 * flags => ?? 00726 * n => ?? 00727 * RETURN VAL: ?? 00728 *****************************************************************************/ 00729 int G__convert_01_flags (char *zero_ones, unsigned char *flags, int n) 00730 { 00731 unsigned char *v; 00732 int count; 00733 int size; 00734 int i, k; 00735 00736 /* pad the flags with 0's to make size multiple of 8 */ 00737 v = flags; 00738 size = G__null_bitstream_size(n); 00739 count = 0; 00740 00741 for (i = 0; i < size; i++) 00742 { 00743 *v = 0; 00744 k = 8; 00745 00746 while (k-- > 0) 00747 { 00748 if (count < n) 00749 { 00750 *v = *v | ((unsigned char) zero_ones[count] << k); 00751 } 00752 00753 count++; 00754 } 00755 00756 v++; 00757 } 00758 00759 return 0; 00760 } 00761 00762 /**************************************************************************** 00763 * int G__convert_flags_01 (char *zero_ones, unsigned char *flags, int n) 00764 * 00765 * PURPOSE: To... 00766 * INPUT VARS: zero_ones => ?? 00767 * flags => ?? 00768 * n => ?? 00769 * RETURN VAL: ?? 00770 *****************************************************************************/ 00771 int G__convert_flags_01 (char *zero_ones, unsigned char *flags, int n) 00772 { 00773 unsigned char *v; 00774 int count; 00775 int size; 00776 int i, k; 00777 00778 count = 0; 00779 v = flags; 00780 size = G__null_bitstream_size(n); 00781 00782 for (i = 0; i < size; i++) 00783 { 00784 k = 8; 00785 00786 while (k-- > 0) 00787 { 00788 if (count < n) 00789 { 00790 zero_ones[count] = ((*v & ( (unsigned char) 1 << k)) != 0); 00791 count++; 00792 } 00793 } 00794 00795 v++; 00796 } 00797 00798 return 0; 00799 } 00800 00801 /**************************************************************************** 00802 * int G__init_null_bits (unsigned char *flags, int cols) 00803 * 00804 * PURPOSE: To... 00805 * INPUT VARS: flags => ?? 00806 * cols => ?? 00807 * RETURN VAL: ?? 00808 *****************************************************************************/ 00809 int G__init_null_bits (unsigned char *flags, int cols) 00810 { 00811 unsigned char *v; 00812 int size; 00813 int i; 00814 00815 /* pad the flags with 0's to make size multiple of 8 */ 00816 v = flags; 00817 size = G__null_bitstream_size(cols); 00818 00819 for (i = 0; i < size; i++) 00820 { 00821 if((i+1) * 8 <= cols) 00822 { 00823 *v = (unsigned char) 255; 00824 } 00825 else 00826 { 00827 *v = (unsigned char) 255 << ((i+1) * 8 - cols); 00828 } 00829 00830 v++; 00831 } 00832 00833 return 0; 00834 } 00835