null_val.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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. /* System include files */
  18. #include <string.h>
  19. /* Grass and local include files */
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include <grass/glocale.h>
  23. static void EmbedGivenNulls(void *, char *, RASTER_MAP_TYPE, int);
  24. /*!
  25. \brief To insert null values into a map. Needs more.....
  26. \param cell raster values
  27. \param nulls raster null values
  28. \param map_type type of raster - CELL, FCELL, DCELL
  29. \param ncols number of columns
  30. */
  31. void EmbedGivenNulls(void *cell, char *nulls, RASTER_MAP_TYPE map_type,
  32. int ncols)
  33. {
  34. CELL *c;
  35. FCELL *f;
  36. DCELL *d;
  37. int i;
  38. c = (CELL *) cell;
  39. f = (FCELL *) cell;
  40. d = (DCELL *) cell;
  41. for (i = 0; i < ncols; i++) {
  42. if (nulls[i]) {
  43. switch (map_type) {
  44. case CELL_TYPE:
  45. Rast_set_c_null_value((CELL *) (c + i), 1);
  46. break;
  47. case FCELL_TYPE:
  48. Rast_set_f_null_value((FCELL *) (f + i), 1);
  49. break;
  50. case DCELL_TYPE:
  51. Rast_set_d_null_value((DCELL *) (d + i), 1);
  52. break;
  53. default:
  54. G_warning(_("EmbedGivenNulls: wrong data type"));
  55. }
  56. }
  57. }
  58. }
  59. /*!
  60. \brief To set one or more raster values to null.
  61. It also sets null to zero if null_is_zero is TRUE.
  62. \param rast pointer to values to set to null
  63. \param numVals number of values to set to null
  64. \param null_is_zero flag to indicate if NULL = 0
  65. \param data_type type of raster - CELL, FCELL, DCELL
  66. */
  67. void Rast__set_null_value(void *rast, int numVals, int null_is_zero,
  68. RASTER_MAP_TYPE data_type)
  69. {
  70. if (null_is_zero) {
  71. G_zero((char *)rast, numVals * Rast_cell_size(data_type));
  72. return;
  73. }
  74. Rast_set_null_value(rast, numVals, data_type);
  75. }
  76. /*!
  77. \brief To set one or more raster values to null.
  78. \param buf pointer to values to set to null
  79. \param numVals number of values to set to null
  80. \param data_type type of raster - CELL, FCELL, DCELL
  81. */
  82. void Rast_set_null_value(void *buf, int numVals, RASTER_MAP_TYPE data_type)
  83. {
  84. switch (data_type) {
  85. case CELL_TYPE:
  86. Rast_set_c_null_value((CELL *) buf, numVals);
  87. break;
  88. case FCELL_TYPE:
  89. Rast_set_f_null_value((FCELL *) buf, numVals);
  90. break;
  91. case DCELL_TYPE:
  92. Rast_set_d_null_value((DCELL *) buf, numVals);
  93. break;
  94. default:
  95. G_warning(_("Rast_set_null_value: wrong data type!"));
  96. }
  97. }
  98. /*!
  99. \brief To set a number of CELL raster values to NULL.
  100. \param cellVals pointer to CELL values to set to null
  101. \param numVals number of values to set to null
  102. */
  103. void Rast_set_c_null_value(CELL * cellVals, int numVals)
  104. {
  105. int i; /* counter */
  106. for (i = 0; i < numVals; i++)
  107. cellVals[i] = (int)0x80000000;
  108. }
  109. /*!
  110. \brief To set a number of FCELL raster values to NULL.
  111. \param fcellVals pointer to FCELL values to set to null
  112. \param numVals number of values to set to null
  113. */
  114. void Rast_set_f_null_value(FCELL * fcellVals, int numVals)
  115. {
  116. static const unsigned char null_bits[4] = {
  117. 0xFF, 0xFF, 0xFF, 0xFF
  118. };
  119. int i;
  120. for (i = 0; i < numVals; i++)
  121. memcpy(&fcellVals[i], null_bits, sizeof(null_bits));
  122. }
  123. /*!
  124. \brief To set a number of DCELL raster values to NULL.
  125. \param dcellVals pointer to DCELL values to set to null
  126. \param numVals number of values to set to null
  127. */
  128. void Rast_set_d_null_value(DCELL * dcellVals, int numVals)
  129. {
  130. static const unsigned char null_bits[8] = {
  131. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  132. };
  133. int i;
  134. for (i = 0; i < numVals; i++)
  135. memcpy(&dcellVals[i], null_bits, sizeof(null_bits));
  136. }
  137. /*!
  138. \brief To check if a raster value is set to NULL
  139. - If the <em>data_type</em> is CELL_TYPE, calls Rast_is_c_null_value()
  140. - If the <em>data_type</em> is FCELL_TYPE, calls Rast_is_f_null_value()
  141. - If the <em>data_type</em> is DCELL_TYPE, calls Rast_is_d_null_value()
  142. \param rast raster value to check
  143. \param data_type type of raster - CELL, FCELL, DCELL
  144. \return TRUE if raster value is NULL
  145. \return FALSE otherwise
  146. */
  147. int Rast_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
  148. {
  149. switch (data_type) {
  150. case CELL_TYPE:
  151. return (Rast_is_c_null_value((CELL *) rast));
  152. case FCELL_TYPE:
  153. return (Rast_is_f_null_value((FCELL *) rast));
  154. case DCELL_TYPE:
  155. return (Rast_is_d_null_value((DCELL *) rast));
  156. default:
  157. G_warning("Rast_is_null_value: wrong data type!");
  158. return FALSE;
  159. }
  160. }
  161. /*!
  162. \brief To check if a CELL raster value is set to NULL
  163. Returns 1 if <em>cell</em> is NULL, 0 otherwise. This will test if the
  164. value <em>cell</em> is the largest <tt>int</tt>.
  165. \param cellVal CELL raster value to check
  166. \return TRUE if CELL raster value is NULL
  167. \return FALSE otherwise
  168. */
  169. #ifndef Rast_is_c_null_value
  170. int Rast_is_c_null_value(const CELL * cellVal)
  171. {
  172. /* Check if the CELL value matches the null pattern */
  173. return *cellVal == (CELL) 0x80000000;
  174. }
  175. #endif
  176. /*!
  177. \brief To check if a FCELL raster value is set to NULL
  178. Returns 1 if <em>fcell</em> is NULL, 0 otherwise. This will test if
  179. the value <em>fcell</em> is a NaN. It isn't good enough to test for
  180. a particular NaN bit pattern since the machine code may change this
  181. bit pattern to a different NaN. The test will be
  182. \code
  183. if(fcell==0.0) return 0;
  184. if(fcell>0.0) return 0;
  185. if(fcell<0.0) return 0;
  186. return 1;
  187. \endcode
  188. or (as suggested by Mark Line)
  189. \code
  190. return (fcell != fcell);
  191. \endcode
  192. \param fcellVal FCELL raster value to check
  193. \return TRUE if FCELL raster value is NULL
  194. \return FALSE otherwise
  195. */
  196. #ifndef Rast_is_f_null_value
  197. int Rast_is_f_null_value(const FCELL * fcellVal)
  198. {
  199. return *fcellVal != *fcellVal;
  200. }
  201. #endif
  202. /*!
  203. \brief To check if a DCELL raster value is set to NULL
  204. Returns 1 if <em>dcell</em> is NULL, 0 otherwise. This will test if
  205. the value <em>dcell</em> is a NaN. Same test as in
  206. Rast_is_f_null_value().
  207. \param dcellVal DCELL raster value to check
  208. \return TRUE if DCELL raster value is NULL
  209. \return FALSE otherwise
  210. */
  211. #ifndef Rast_is_d_null_value
  212. int Rast_is_d_null_value(const DCELL * dcellVal)
  213. {
  214. return *dcellVal != *dcellVal;
  215. }
  216. #endif
  217. /*!
  218. \brief To insert null values into a map.
  219. - If the <em>data_type</em> is CELL_TYPE, calls Rast_insert_c_null_values()
  220. - If the <em>data_type</em> is FCELL_TYPE, calls Rast_insert_f_null_values()
  221. - If the <em>data_type</em> is DCELL_TYPE, calls Rast_insert_d_null_values()
  222. \param rast pointer raster values
  223. \param null_row null row
  224. \param ncols number of columns
  225. \param data_type type of raster - CELL, FCELL, DCELL
  226. */
  227. void Rast_insert_null_values(void *rast, char *null_row, int ncols,
  228. RASTER_MAP_TYPE data_type)
  229. {
  230. EmbedGivenNulls(rast, null_row, data_type, ncols);
  231. }
  232. /*!
  233. \brief To insert null values into an integer raster map (CELL)
  234. For each of the <em>count</em> <em>flags</em> which is true(!=0),
  235. set the corresponding <em>cell</em> to the NULL value.
  236. \param rast pointer raster values
  237. \param null_row null row
  238. \param ncols number of columns
  239. */
  240. void Rast_insert_c_null_values(CELL * cellVal, char *null_row, int ncols)
  241. {
  242. EmbedGivenNulls((void *)cellVal, null_row, CELL_TYPE, ncols);
  243. }
  244. /*!
  245. \brief To insert null values into an floating-point raster map (FCELL)
  246. \param fcellVal pointer raster values
  247. \param null_row null row
  248. \param ncols number of columns
  249. */
  250. void Rast_insert_f_null_values(FCELL * fcellVal, char *null_row, int ncols)
  251. {
  252. EmbedGivenNulls((void *)fcellVal, null_row, FCELL_TYPE, ncols);
  253. }
  254. /*!
  255. \brief To insert null values into an floating-point raster map (FCELL)
  256. For each for the <em>count</em> <em>flag</em> which is true(!=0), set
  257. the corresponding <em>dcell</em> to the NULL value.
  258. \param dcellVal pointer raster values
  259. \param null_row null row
  260. \param ncols number of columns
  261. */
  262. void Rast_insert_d_null_values(DCELL * dcellVal, char *null_row, int ncols)
  263. {
  264. EmbedGivenNulls((void *)dcellVal, null_row, DCELL_TYPE, ncols);
  265. }
  266. /*!
  267. \brief Check NULL
  268. Note: Only for internal use.
  269. \param flags null bitmap
  270. \param bit_num index of bit to check
  271. \param n size of null bitmap (in bits)
  272. \return 1 if set, 0 if unset
  273. */
  274. int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
  275. {
  276. int ind;
  277. int offset;
  278. /* check that bit_num is in range */
  279. if (bit_num < 0 || bit_num >= n)
  280. G_fatal_error("Rast__check_null_bit: index %d out of range (size = %d).",
  281. bit_num, n);
  282. /* find the index of the unsigned char in which this bit appears */
  283. ind = bit_num / 8;
  284. offset = bit_num & 7;
  285. return ((flags[ind] & ((unsigned char)0x80 >> offset)) != 0);
  286. }
  287. /*!
  288. \brief Given array of 0/1 of length n starting from column.
  289. Note: Only for internal use.
  290. Given array of 0/1 of length n starting from column set the
  291. corresponding bits of flags; total number of bits in flags is ncols.
  292. \param zero_ones
  293. \param flags
  294. \param col
  295. \param n
  296. \param ncols
  297. \return 0
  298. \return 1
  299. */
  300. int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags,
  301. int col, int n, int ncols)
  302. {
  303. unsigned char v;
  304. int count;
  305. int size;
  306. int i, k;
  307. if (col == 0 && n == ncols) {
  308. Rast__convert_01_flags(zero_ones, flags, n);
  309. return 0;
  310. }
  311. count = 0;
  312. size = Rast__null_bitstream_size(ncols);
  313. for (i = 0; i < size; i++) {
  314. v = 0;
  315. k = 8;
  316. while (k-- > 0) {
  317. if (count >= col && count < (col + n)) {
  318. v = v | ((unsigned char)zero_ones[count - col] << k);
  319. }
  320. else if (count < ncols) {
  321. v = v |
  322. ((unsigned char)Rast__check_null_bit(flags, count, ncols)
  323. << k);
  324. }
  325. /* otherwise keep this bit the same as it was */
  326. count++;
  327. }
  328. flags[i] = v;
  329. }
  330. return 1;
  331. }
  332. /*!
  333. \brief ?
  334. Note: Only for internal use.
  335. \param zero_ones
  336. \param flags
  337. \param n
  338. */
  339. void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags,
  340. int n)
  341. {
  342. unsigned char *v;
  343. int count;
  344. int size;
  345. int i, k;
  346. /* pad the flags with 0's to make size multiple of 8 */
  347. v = flags;
  348. size = Rast__null_bitstream_size(n);
  349. count = 0;
  350. for (i = 0; i < size; i++) {
  351. *v = 0;
  352. k = 8;
  353. while (k-- > 0) {
  354. if (count < n) {
  355. *v = *v | ((unsigned char)zero_ones[count] << k);
  356. }
  357. count++;
  358. }
  359. v++;
  360. }
  361. }
  362. /*!
  363. \brief ?
  364. Note: Only for internal use.
  365. \param zero_ones
  366. \param flags
  367. \param n
  368. */
  369. void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags,
  370. int n)
  371. {
  372. const unsigned char *v;
  373. int count;
  374. int size;
  375. int i, k;
  376. count = 0;
  377. v = flags;
  378. size = Rast__null_bitstream_size(n);
  379. for (i = 0; i < size; i++) {
  380. k = 8;
  381. while (k-- > 0) {
  382. if (count < n) {
  383. zero_ones[count] = ((*v & ((unsigned char)1 << k)) != 0);
  384. count++;
  385. }
  386. }
  387. v++;
  388. }
  389. }
  390. /*!
  391. \brief ?
  392. Note: Only for internal use.
  393. \param flags
  394. \param cols
  395. */
  396. void Rast__init_null_bits(unsigned char *flags, int cols)
  397. {
  398. unsigned char *v;
  399. int size;
  400. int i;
  401. /* pad the flags with 0's to make size multiple of 8 */
  402. v = flags;
  403. size = Rast__null_bitstream_size(cols);
  404. for (i = 0; i < size; i++) {
  405. if ((i + 1) * 8 <= cols) {
  406. *v = (unsigned char)255;
  407. }
  408. else {
  409. *v = (unsigned char)255 << ((i + 1) * 8 - cols);
  410. }
  411. v++;
  412. }
  413. }