GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
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] = {0xFF, 0xFF, 0xFF, 0xFF};
141  int i;
142 
143  for (i = 0; i < numVals; i++)
144  memcpy(&fcellVals[i], null_bits, sizeof(null_bits));
145 }
146 
147 /*!
148  \brief To set a number of DCELL raster values to NULL.
149 
150  \param dcellVals pointer to DCELL values to set to null
151  \param numVals number of values to set to null
152  */
153 void Rast_set_d_null_value(DCELL *dcellVals, int numVals)
154 {
155  static const unsigned char null_bits[8] = {0xFF, 0xFF, 0xFF, 0xFF,
156  0xFF, 0xFF, 0xFF, 0xFF};
157  int i;
158 
159  for (i = 0; i < numVals; i++)
160  memcpy(&dcellVals[i], null_bits, sizeof(null_bits));
161 }
162 
163 /*!
164  \brief To check if a raster value is set to NULL
165 
166  - If the <em>data_type</em> is CELL_TYPE, calls Rast_is_c_null_value()
167  - If the <em>data_type</em> is FCELL_TYPE, calls Rast_is_f_null_value()
168  - If the <em>data_type</em> is DCELL_TYPE, calls Rast_is_d_null_value()
169 
170  \param rast raster value to check
171  \param data_type type of raster - CELL, FCELL, DCELL
172 
173  \return TRUE if raster value is NULL
174  \return FALSE otherwise
175  */
176 int Rast_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
177 {
178  switch (data_type) {
179  case CELL_TYPE:
180  return (Rast_is_c_null_value((CELL *)rast));
181 
182  case FCELL_TYPE:
183  return (Rast_is_f_null_value((FCELL *)rast));
184 
185  case DCELL_TYPE:
186  return (Rast_is_d_null_value((DCELL *)rast));
187 
188  default:
189  G_warning("Rast_is_null_value: wrong data type!");
190  return FALSE;
191  }
192 }
193 
194 /*!
195  \brief To check if a CELL raster value is set to NULL
196 
197  Returns 1 if <em>cell</em> is NULL, 0 otherwise. This will test if the
198  value <em>cell</em> is the largest <tt>int</tt>.
199 
200  \param cellVal CELL raster value to check
201 
202  \return TRUE if CELL raster value is NULL
203  \return FALSE otherwise
204  */
205 #ifndef Rast_is_c_null_value
206 int Rast_is_c_null_value(const CELL *cellVal)
207 {
208  /* Check if the CELL value matches the null pattern */
209  return *cellVal == (CELL)0x80000000;
210 }
211 #endif
212 
213 /*!
214  \brief To check if a FCELL raster value is set to NULL
215 
216  Returns 1 if <em>fcell</em> is NULL, 0 otherwise. This will test if
217  the value <em>fcell</em> is a NaN. It isn't good enough to test for
218  a particular NaN bit pattern since the machine code may change this
219  bit pattern to a different NaN. The test will be
220 
221  \code
222  if(fcell==0.0) return 0;
223  if(fcell>0.0) return 0;
224  if(fcell<0.0) return 0;
225  return 1;
226  \endcode
227 
228  or (as suggested by Mark Line)
229  \code
230  return (fcell != fcell);
231  \endcode
232 
233  \param fcellVal FCELL raster value to check
234 
235  \return TRUE if FCELL raster value is NULL
236  \return FALSE otherwise
237  */
238 #ifndef Rast_is_f_null_value
239 int Rast_is_f_null_value(const FCELL *fcellVal)
240 {
241  return *fcellVal != *fcellVal;
242 }
243 #endif
244 
245 /*!
246  \brief To check if a DCELL raster value is set to NULL
247 
248  Returns 1 if <em>dcell</em> is NULL, 0 otherwise. This will test if
249  the value <em>dcell</em> is a NaN. Same test as in
250  Rast_is_f_null_value().
251 
252  \param dcellVal DCELL raster value to check
253 
254  \return TRUE if DCELL raster value is NULL
255  \return FALSE otherwise
256  */
257 #ifndef Rast_is_d_null_value
258 int Rast_is_d_null_value(const DCELL *dcellVal)
259 {
260  return *dcellVal != *dcellVal;
261 }
262 #endif
263 
264 /*!
265  \brief To insert null values into a map.
266 
267  - If the <em>data_type</em> is CELL_TYPE, calls Rast_insert_c_null_values()
268  - If the <em>data_type</em> is FCELL_TYPE, calls Rast_insert_f_null_values()
269  - If the <em>data_type</em> is DCELL_TYPE, calls Rast_insert_d_null_values()
270 
271  \param rast pointer raster values
272  \param null_row null row
273  \param ncols number of columns
274  \param data_type type of raster - CELL, FCELL, DCELL
275  */
276 void Rast_insert_null_values(void *rast, char *null_row, int ncols,
277  RASTER_MAP_TYPE data_type)
278 {
279  EmbedGivenNulls(rast, null_row, data_type, ncols);
280 }
281 
282 /*!
283  \brief To insert null values into an integer raster map (CELL)
284 
285  For each of the <em>count</em> <em>flags</em> which is true(!=0),
286  set the corresponding <em>cell</em> to the NULL value.
287 
288  \param rast pointer raster values
289  \param null_row null row
290  \param ncols number of columns
291  */
292 void Rast_insert_c_null_values(CELL *cellVal, char *null_row, int ncols)
293 {
294  EmbedGivenNulls((void *)cellVal, null_row, CELL_TYPE, ncols);
295 }
296 
297 /*!
298  \brief To insert null values into an floating-point raster map (FCELL)
299 
300  \param fcellVal pointer raster values
301  \param null_row null row
302  \param ncols number of columns
303  */
304 void Rast_insert_f_null_values(FCELL *fcellVal, char *null_row, int ncols)
305 {
306  EmbedGivenNulls((void *)fcellVal, null_row, FCELL_TYPE, ncols);
307 }
308 
309 /*!
310  \brief To insert null values into an floating-point raster map (FCELL)
311 
312  For each for the <em>count</em> <em>flag</em> which is true(!=0), set
313  the corresponding <em>dcell</em> to the NULL value.
314 
315  \param dcellVal pointer raster values
316  \param null_row null row
317  \param ncols number of columns
318  */
319 void Rast_insert_d_null_values(DCELL *dcellVal, char *null_row, int ncols)
320 {
321  EmbedGivenNulls((void *)dcellVal, null_row, DCELL_TYPE, ncols);
322 }
323 
324 /*!
325  \brief Check NULL
326 
327  Note: Only for internal use.
328 
329  \param flags null bitmap
330  \param bit_num index of bit to check
331  \param n size of null bitmap (in bits)
332 
333  \return 1 if set, 0 if unset
334  */
335 int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
336 {
337  int ind;
338  int offset;
339 
340  /* check that bit_num is in range */
341  if (bit_num < 0 || bit_num >= n)
343  "Rast__check_null_bit: index %d out of range (size = %d).", bit_num,
344  n);
345 
346  /* find the index of the unsigned char in which this bit appears */
347  ind = bit_num / 8;
348 
349  offset = bit_num & 7;
350 
351  return ((flags[ind] & ((unsigned char)0x80 >> offset)) != 0);
352 }
353 
354 /*!
355  \brief Given array of 0/1 of length n starting from column.
356 
357  Note: Only for internal use.
358 
359  Given array of 0/1 of length n starting from column set the
360  corresponding bits of flags; total number of bits in flags is ncols.
361 
362  \param zero_ones
363  \param flags
364  \param col
365  \param n
366  \param ncols
367 
368  \return 0
369  \return 1
370  */
371 int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags,
372  int col, int n, int ncols)
373 {
374  unsigned char v;
375  int count;
376  int size;
377  int i, k;
378 
379  if (col == 0 && n == ncols) {
380  Rast__convert_01_flags(zero_ones, flags, n);
381  return 0;
382  }
383 
384  count = 0;
385  size = Rast__null_bitstream_size(ncols);
386 
387  for (i = 0; i < size; i++) {
388  v = 0;
389  k = 8;
390 
391  while (k-- > 0) {
392  if (count >= col && count < (col + n)) {
393  v = v | ((unsigned char)zero_ones[count - col] << k);
394  }
395  else if (count < ncols) {
396  v = v |
397  ((unsigned char)Rast__check_null_bit(flags, count, ncols)
398  << k);
399  }
400 
401  /* otherwise keep this bit the same as it was */
402  count++;
403  }
404 
405  flags[i] = v;
406  }
407 
408  return 1;
409 }
410 
411 /*!
412  \brief ?
413 
414  Note: Only for internal use.
415 
416  \param zero_ones
417  \param flags
418  \param n
419  */
420 void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags, int n)
421 {
422  unsigned char *v;
423  int count;
424  int size;
425  int i, k;
426 
427  /* pad the flags with 0's to make size multiple of 8 */
428  v = flags;
429  size = Rast__null_bitstream_size(n);
430  count = 0;
431 
432  for (i = 0; i < size; i++) {
433  *v = 0;
434  k = 8;
435 
436  while (k-- > 0) {
437  if (count < n) {
438  *v = *v | ((unsigned char)zero_ones[count] << k);
439  }
440 
441  count++;
442  }
443 
444  v++;
445  }
446 }
447 
448 /*!
449  \brief ?
450 
451  Note: Only for internal use.
452 
453  \param zero_ones
454  \param flags
455  \param n
456  */
457 void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags, int n)
458 {
459  const unsigned char *v;
460  int count;
461  int size;
462  int i, k;
463 
464  count = 0;
465  v = flags;
466  size = Rast__null_bitstream_size(n);
467 
468  for (i = 0; i < size; i++) {
469  k = 8;
470 
471  while (k-- > 0) {
472  if (count < n) {
473  zero_ones[count] = ((*v & ((unsigned char)1 << k)) != 0);
474  count++;
475  }
476  }
477 
478  v++;
479  }
480 }
481 
482 /*!
483  \brief ?
484 
485  Note: Only for internal use.
486 
487  \param flags
488  \param cols
489  */
490 void Rast__init_null_bits(unsigned char *flags, int cols)
491 {
492  unsigned char *v;
493  int size;
494  int i;
495 
496  /* pad the flags with 0's to make size multiple of 8 */
497  v = flags;
498  size = Rast__null_bitstream_size(cols);
499 
500  for (i = 0; i < size; i++) {
501  if ((i + 1) * 8 <= cols) {
502  *v = (unsigned char)255;
503  }
504  else {
505  *v = (unsigned char)255 << ((i + 1) * 8 - cols);
506  }
507 
508  v++;
509  }
510 }
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int Rast__null_bitstream_size(int)
Determines null bitstream size.
Definition: alloc_cell.c:147
#define Rast_is_f_null_value(fcellVal)
Definition: defs/raster.h:406
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition: alloc_cell.c:38
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:408
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:404
float FCELL
Definition: gis.h:630
#define FALSE
Definition: gis.h:83
double DCELL
Definition: gis.h:629
int CELL
Definition: gis.h:628
#define _(str)
Definition: glocale.h:10
int count
void Rast_set_d_null_value(DCELL *dcellVals, int numVals)
To set a number of DCELL raster values to NULL.
Definition: null_val.c:153
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:371
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
int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
Check NULL.
Definition: null_val.c:335
void Rast__init_null_bits(unsigned char *flags, int cols)
?
Definition: null_val.c:490
void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags, int n)
?
Definition: null_val.c:457
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:276
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:176
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
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__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
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:304
void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags, int n)
?
Definition: null_val.c:420
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:319
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:292
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
#define CELL_TYPE
Definition: raster.h:11
int RASTER_MAP_TYPE
Definition: raster.h:25