1 /*!
2 * \file lib/raster/null_val.c
3 *
4 * \brief Raster Library - NULL value management
5 *
6 * To provide functionality to handle NULL values for data types CELL,
7 * FCELL, and DCELL. May need more...
8 *
9 * (C) 2001-2009 GRASS Development Team
10 *
11 * This program is free software under the GNU General Public License
12 * (>=v2). Read the file COPYING that comes with GRASS for details.
13 *
14 * \author Original author unknown - probably CERL
15 * \author Justin Hickey - Thailand - jhickey@hpcc.nectec.or.th
16 */
17
18 /* System include files */
19 #include <string.h>
20
21 /* Grass and local include files */
22 #include <grass/gis.h>
23 #include <grass/raster.h>
24 #include <grass/glocale.h>
25
26 static void EmbedGivenNulls(void *, char *, RASTER_MAP_TYPE, int);
27
28 /*!
29 \brief To insert null values into a map. Needs more.....
30
31 \param cell raster values
32 \param nulls raster null values
33 \param map_type type of raster - CELL, FCELL, DCELL
34 \param ncols number of columns
35 */
EmbedGivenNulls(void * cell,char * nulls,RASTER_MAP_TYPE map_type,int ncols)36 void EmbedGivenNulls(void *cell, char *nulls, RASTER_MAP_TYPE map_type,
37 int ncols)
38 {
39 CELL *c;
40 FCELL *f;
41 DCELL *d;
42 int i;
43
44 c = (CELL *) cell;
45 f = (FCELL *) cell;
46 d = (DCELL *) cell;
47
48 for (i = 0; i < ncols; i++) {
49 if (nulls[i]) {
50 switch (map_type) {
51 case CELL_TYPE:
52 Rast_set_c_null_value((CELL *) (c + i), 1);
53 break;
54
55 case FCELL_TYPE:
56 Rast_set_f_null_value((FCELL *) (f + i), 1);
57 break;
58
59 case DCELL_TYPE:
60 Rast_set_d_null_value((DCELL *) (d + i), 1);
61 break;
62
63 default:
64 G_warning(_("EmbedGivenNulls: wrong data type"));
65 }
66 }
67 }
68 }
69
70 /*!
71 \brief To set one or more raster values to null.
72
73 It also sets null to zero if null_is_zero is TRUE.
74
75 \param rast pointer to values to set to null
76 \param numVals number of values to set to null
77 \param null_is_zero flag to indicate if NULL = 0
78 \param data_type type of raster - CELL, FCELL, DCELL
79 */
Rast__set_null_value(void * rast,int numVals,int null_is_zero,RASTER_MAP_TYPE data_type)80 void Rast__set_null_value(void *rast, int numVals, int null_is_zero,
81 RASTER_MAP_TYPE data_type)
82 {
83 if (null_is_zero) {
84 G_zero((char *)rast, numVals * Rast_cell_size(data_type));
85 return;
86 }
87
88 Rast_set_null_value(rast, numVals, data_type);
89 }
90
91 /*!
92 \brief To set one or more raster values to null.
93
94 \param buf pointer to values to set to null
95 \param numVals number of values to set to null
96 \param data_type type of raster - CELL, FCELL, DCELL
97 */
Rast_set_null_value(void * buf,int numVals,RASTER_MAP_TYPE data_type)98 void Rast_set_null_value(void *buf, int numVals, RASTER_MAP_TYPE data_type)
99 {
100 switch (data_type) {
101 case CELL_TYPE:
102 Rast_set_c_null_value((CELL *) buf, numVals);
103 break;
104
105 case FCELL_TYPE:
106 Rast_set_f_null_value((FCELL *) buf, numVals);
107 break;
108
109 case DCELL_TYPE:
110 Rast_set_d_null_value((DCELL *) buf, numVals);
111 break;
112
113 default:
114 G_warning(_("Rast_set_null_value: wrong data type!"));
115 }
116 }
117
118 /*!
119 \brief To set a number of CELL raster values to NULL.
120
121 \param cellVals pointer to CELL values to set to null
122 \param numVals number of values to set to null
123 */
Rast_set_c_null_value(CELL * cellVals,int numVals)124 void Rast_set_c_null_value(CELL * cellVals, int numVals)
125 {
126 int i; /* counter */
127
128 for (i = 0; i < numVals; i++)
129 cellVals[i] = (int)0x80000000;
130 }
131
132 /*!
133 \brief To set a number of FCELL raster values to NULL.
134
135 \param fcellVals pointer to FCELL values to set to null
136 \param numVals number of values to set to null
137 */
Rast_set_f_null_value(FCELL * fcellVals,int numVals)138 void Rast_set_f_null_value(FCELL * fcellVals, int numVals)
139 {
140 static const unsigned char null_bits[4] = {
141 0xFF, 0xFF, 0xFF, 0xFF
142 };
143 int i;
144
145 for (i = 0; i < numVals; i++)
146 memcpy(&fcellVals[i], null_bits, sizeof(null_bits));
147 }
148
149 /*!
150 \brief To set a number of DCELL raster values to NULL.
151
152 \param dcellVals pointer to DCELL values to set to null
153 \param numVals number of values to set to null
154 */
Rast_set_d_null_value(DCELL * dcellVals,int numVals)155 void Rast_set_d_null_value(DCELL * dcellVals, int numVals)
156 {
157 static const unsigned char null_bits[8] = {
158 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
159 };
160 int i;
161
162 for (i = 0; i < numVals; i++)
163 memcpy(&dcellVals[i], null_bits, sizeof(null_bits));
164 }
165
166 /*!
167 \brief To check if a raster value is set to NULL
168
169 - If the <em>data_type</em> is CELL_TYPE, calls Rast_is_c_null_value()
170 - If the <em>data_type</em> is FCELL_TYPE, calls Rast_is_f_null_value()
171 - If the <em>data_type</em> is DCELL_TYPE, calls Rast_is_d_null_value()
172
173 \param rast raster value to check
174 \param data_type type of raster - CELL, FCELL, DCELL
175
176 \return TRUE if raster value is NULL
177 \return FALSE otherwise
178 */
Rast_is_null_value(const void * rast,RASTER_MAP_TYPE data_type)179 int Rast_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
180 {
181 switch (data_type) {
182 case CELL_TYPE:
183 return (Rast_is_c_null_value((CELL *) rast));
184
185 case FCELL_TYPE:
186 return (Rast_is_f_null_value((FCELL *) rast));
187
188 case DCELL_TYPE:
189 return (Rast_is_d_null_value((DCELL *) rast));
190
191 default:
192 G_warning("Rast_is_null_value: wrong data type!");
193 return FALSE;
194 }
195 }
196
197 /*!
198 \brief To check if a CELL raster value is set to NULL
199
200 Returns 1 if <em>cell</em> is NULL, 0 otherwise. This will test if the
201 value <em>cell</em> is the largest <tt>int</tt>.
202
203 \param cellVal CELL raster value to check
204
205 \return TRUE if CELL raster value is NULL
206 \return FALSE otherwise
207 */
208 #ifndef Rast_is_c_null_value
Rast_is_c_null_value(const CELL * cellVal)209 int Rast_is_c_null_value(const CELL * cellVal)
210 {
211 /* Check if the CELL value matches the null pattern */
212 return *cellVal == (CELL) 0x80000000;
213 }
214 #endif
215
216 /*!
217 \brief To check if a FCELL raster value is set to NULL
218
219 Returns 1 if <em>fcell</em> is NULL, 0 otherwise. This will test if
220 the value <em>fcell</em> is a NaN. It isn't good enough to test for
221 a particular NaN bit pattern since the machine code may change this
222 bit pattern to a different NaN. The test will be
223
224 \code
225 if(fcell==0.0) return 0;
226 if(fcell>0.0) return 0;
227 if(fcell<0.0) return 0;
228 return 1;
229 \endcode
230
231 or (as suggested by Mark Line)
232 \code
233 return (fcell != fcell);
234 \endcode
235
236 \param fcellVal FCELL raster value to check
237
238 \return TRUE if FCELL raster value is NULL
239 \return FALSE otherwise
240 */
241 #ifndef Rast_is_f_null_value
Rast_is_f_null_value(const FCELL * fcellVal)242 int Rast_is_f_null_value(const FCELL * fcellVal)
243 {
244 return *fcellVal != *fcellVal;
245 }
246 #endif
247
248 /*!
249 \brief To check if a DCELL raster value is set to NULL
250
251 Returns 1 if <em>dcell</em> is NULL, 0 otherwise. This will test if
252 the value <em>dcell</em> is a NaN. Same test as in
253 Rast_is_f_null_value().
254
255 \param dcellVal DCELL raster value to check
256
257 \return TRUE if DCELL raster value is NULL
258 \return FALSE otherwise
259 */
260 #ifndef Rast_is_d_null_value
Rast_is_d_null_value(const DCELL * dcellVal)261 int Rast_is_d_null_value(const DCELL * dcellVal)
262 {
263 return *dcellVal != *dcellVal;
264 }
265 #endif
266
267 /*!
268 \brief To insert null values into a map.
269
270 - If the <em>data_type</em> is CELL_TYPE, calls Rast_insert_c_null_values()
271 - If the <em>data_type</em> is FCELL_TYPE, calls Rast_insert_f_null_values()
272 - If the <em>data_type</em> is DCELL_TYPE, calls Rast_insert_d_null_values()
273
274 \param rast pointer raster values
275 \param null_row null row
276 \param ncols number of columns
277 \param data_type type of raster - CELL, FCELL, DCELL
278 */
Rast_insert_null_values(void * rast,char * null_row,int ncols,RASTER_MAP_TYPE data_type)279 void Rast_insert_null_values(void *rast, char *null_row, int ncols,
280 RASTER_MAP_TYPE data_type)
281 {
282 EmbedGivenNulls(rast, null_row, data_type, ncols);
283 }
284
285 /*!
286 \brief To insert null values into an integer raster map (CELL)
287
288 For each of the <em>count</em> <em>flags</em> which is true(!=0),
289 set the corresponding <em>cell</em> to the NULL value.
290
291 \param rast pointer raster values
292 \param null_row null row
293 \param ncols number of columns
294 */
Rast_insert_c_null_values(CELL * cellVal,char * null_row,int ncols)295 void Rast_insert_c_null_values(CELL * cellVal, char *null_row, int ncols)
296 {
297 EmbedGivenNulls((void *)cellVal, null_row, CELL_TYPE, ncols);
298 }
299
300 /*!
301 \brief To insert null values into an floating-point raster map (FCELL)
302
303 \param fcellVal pointer raster values
304 \param null_row null row
305 \param ncols number of columns
306 */
Rast_insert_f_null_values(FCELL * fcellVal,char * null_row,int ncols)307 void Rast_insert_f_null_values(FCELL * fcellVal, char *null_row, int ncols)
308 {
309 EmbedGivenNulls((void *)fcellVal, null_row, FCELL_TYPE, ncols);
310 }
311
312 /*!
313 \brief To insert null values into an floating-point raster map (FCELL)
314
315 For each for the <em>count</em> <em>flag</em> which is true(!=0), set
316 the corresponding <em>dcell</em> to the NULL value.
317
318 \param dcellVal pointer raster values
319 \param null_row null row
320 \param ncols number of columns
321 */
Rast_insert_d_null_values(DCELL * dcellVal,char * null_row,int ncols)322 void Rast_insert_d_null_values(DCELL * dcellVal, char *null_row, int ncols)
323 {
324 EmbedGivenNulls((void *)dcellVal, null_row, DCELL_TYPE, ncols);
325 }
326
327 /*!
328 \brief Check NULL
329
330 Note: Only for internal use.
331
332 \param flags null bitmap
333 \param bit_num index of bit to check
334 \param n size of null bitmap (in bits)
335
336 \return 1 if set, 0 if unset
337 */
Rast__check_null_bit(const unsigned char * flags,int bit_num,int n)338 int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
339 {
340 int ind;
341 int offset;
342
343 /* check that bit_num is in range */
344 if (bit_num < 0 || bit_num >= n)
345 G_fatal_error("Rast__check_null_bit: index %d out of range (size = %d).",
346 bit_num, n);
347
348
349 /* find the index of the unsigned char in which this bit appears */
350 ind = bit_num / 8;
351
352 offset = bit_num & 7;
353
354 return ((flags[ind] & ((unsigned char)0x80 >> offset)) != 0);
355 }
356
357 /*!
358 \brief Given array of 0/1 of length n starting from column.
359
360 Note: Only for internal use.
361
362 Given array of 0/1 of length n starting from column set the
363 corresponding bits of flags; total number of bits in flags is ncols.
364
365 \param zero_ones
366 \param flags
367 \param col
368 \param n
369 \param ncols
370
371 \return 0
372 \return 1
373 */
G__set_flags_from_01_random(const char * zero_ones,unsigned char * flags,int col,int n,int ncols)374 int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags,
375 int col, int n, int ncols)
376 {
377 unsigned char v;
378 int count;
379 int size;
380 int i, k;
381
382 if (col == 0 && n == ncols) {
383 Rast__convert_01_flags(zero_ones, flags, n);
384 return 0;
385 }
386
387 count = 0;
388 size = Rast__null_bitstream_size(ncols);
389
390 for (i = 0; i < size; i++) {
391 v = 0;
392 k = 8;
393
394 while (k-- > 0) {
395 if (count >= col && count < (col + n)) {
396 v = v | ((unsigned char)zero_ones[count - col] << k);
397 }
398 else if (count < ncols) {
399 v = v |
400 ((unsigned char)Rast__check_null_bit(flags, count, ncols)
401 << k);
402 }
403
404 /* otherwise keep this bit the same as it was */
405 count++;
406 }
407
408 flags[i] = v;
409 }
410
411 return 1;
412 }
413
414 /*!
415 \brief ?
416
417 Note: Only for internal use.
418
419 \param zero_ones
420 \param flags
421 \param n
422 */
Rast__convert_01_flags(const char * zero_ones,unsigned char * flags,int n)423 void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags,
424 int n)
425 {
426 unsigned char *v;
427 int count;
428 int size;
429 int i, k;
430
431 /* pad the flags with 0's to make size multiple of 8 */
432 v = flags;
433 size = Rast__null_bitstream_size(n);
434 count = 0;
435
436 for (i = 0; i < size; i++) {
437 *v = 0;
438 k = 8;
439
440 while (k-- > 0) {
441 if (count < n) {
442 *v = *v | ((unsigned char)zero_ones[count] << k);
443 }
444
445 count++;
446 }
447
448 v++;
449 }
450 }
451
452 /*!
453 \brief ?
454
455 Note: Only for internal use.
456
457 \param zero_ones
458 \param flags
459 \param n
460 */
Rast__convert_flags_01(char * zero_ones,const unsigned char * flags,int n)461 void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags,
462 int n)
463 {
464 const unsigned char *v;
465 int count;
466 int size;
467 int i, k;
468
469 count = 0;
470 v = flags;
471 size = Rast__null_bitstream_size(n);
472
473 for (i = 0; i < size; i++) {
474 k = 8;
475
476 while (k-- > 0) {
477 if (count < n) {
478 zero_ones[count] = ((*v & ((unsigned char)1 << k)) != 0);
479 count++;
480 }
481 }
482
483 v++;
484 }
485 }
486
487 /*!
488 \brief ?
489
490 Note: Only for internal use.
491
492 \param flags
493 \param cols
494 */
Rast__init_null_bits(unsigned char * flags,int cols)495 void Rast__init_null_bits(unsigned char *flags, int cols)
496 {
497 unsigned char *v;
498 int size;
499 int i;
500
501 /* pad the flags with 0's to make size multiple of 8 */
502 v = flags;
503 size = Rast__null_bitstream_size(cols);
504
505 for (i = 0; i < size; i++) {
506 if ((i + 1) * 8 <= cols) {
507 *v = (unsigned char)255;
508 }
509 else {
510 *v = (unsigned char)255 << ((i + 1) * 8 - cols);
511 }
512
513 v++;
514 }
515 }
516