GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
null_val.c
Go to the documentation of this file.
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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
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
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
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 }
#define CELL_TYPE
Definition: raster.h:11
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags, int n)
?
Definition: null_val.c:461
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:414
double DCELL
Definition: gis.h:614
int count
int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags, int col, int n, int ncols)
Given array of 0/1 of length n starting from column.
Definition: null_val.c:374
void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags, int n)
?
Definition: null_val.c:423
void Rast__set_null_value(void *rast, int numVals, int null_is_zero, RASTER_MAP_TYPE data_type)
To set one or more raster values to null.
Definition: null_val.c:80
#define Rast_is_f_null_value(fcellVal)
Definition: defs/raster.h:412
void Rast_set_null_value(void *buf, int numVals, RASTER_MAP_TYPE data_type)
To set one or more raster values to null.
Definition: null_val.c:98
#define DCELL_TYPE
Definition: raster.h:13
void Rast_set_c_null_value(CELL *cellVals, int numVals)
To set a number of CELL raster values to NULL.
Definition: null_val.c:124
int Rast__null_bitstream_size(int)
Determines null bitstream size.
Definition: alloc_cell.c:148
#define FALSE
Definition: gis.h:63
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition: alloc_cell.c:39
int Rast_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
To check if a raster value is set to NULL.
Definition: null_val.c:179
void Rast_insert_null_values(void *rast, char *null_row, int ncols, RASTER_MAP_TYPE data_type)
To check if a CELL raster value is set to NULL.
Definition: null_val.c:279
void Rast_set_f_null_value(FCELL *fcellVals, int numVals)
To set a number of FCELL raster values to NULL.
Definition: null_val.c:138
void Rast_insert_d_null_values(DCELL *dcellVal, char *null_row, int ncols)
To insert null values into an floating-point raster map (FCELL)
Definition: null_val.c:322
void Rast_set_d_null_value(DCELL *dcellVals, int numVals)
To set a number of DCELL raster values to NULL.
Definition: null_val.c:155
float FCELL
Definition: gis.h:615
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
Check NULL.
Definition: null_val.c:338
void G_warning(const char *,...) __attribute__((format(printf
int CELL
Definition: gis.h:613
#define _(str)
Definition: glocale.h:10
void Rast_insert_f_null_values(FCELL *fcellVal, char *null_row, int ncols)
To insert null values into an floating-point raster map (FCELL)
Definition: null_val.c:307
int RASTER_MAP_TYPE
Definition: raster.h:25
#define FCELL_TYPE
Definition: raster.h:12
void Rast_insert_c_null_values(CELL *cellVal, char *null_row, int ncols)
To insert null values into an integer raster map (CELL)
Definition: null_val.c:295
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:410
void Rast__init_null_bits(unsigned char *flags, int cols)
?
Definition: null_val.c:495