null_val.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*!
  2. * \file raster/null_value.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_raster_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. int i;
  119. for (i = 0; i < numVals; i++)
  120. memcpy(&fcellVals[i], null_bits, sizeof(null_bits));
  121. }
  122. /*!
  123. \brief To set a number of DCELL raster values to NULL.
  124. \param dcellVals pointer to DCELL values to set to null
  125. \param numVals number of values to set to null
  126. */
  127. void Rast_set_d_null_value(DCELL *dcellVals, int numVals)
  128. {
  129. static const unsigned char null_bits[8] = {
  130. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  131. int i;
  132. for (i = 0; i < numVals; i++)
  133. memcpy(&dcellVals[i], null_bits, sizeof(null_bits));
  134. }
  135. /*!
  136. \brief To check if a raster value is set to NULL
  137. - If the <em>data_type</em> is CELL_TYPE, calls Rast_is_c_null_value()
  138. - If the <em>data_type</em> is FCELL_TYPE, calls Rast_is_f_null_value()
  139. - If the <em>data_type</em> is DCELL_TYPE, calls Rast_is_d_null_value()
  140. \param rast raster value to check
  141. \param data_type type of raster - CELL, FCELL, DCELL
  142. \return TRUE if raster value is NULL
  143. \return FALSE otherwise
  144. */
  145. int Rast_is_null_value(const void *rast, RASTER_MAP_TYPE data_type)
  146. {
  147. switch (data_type) {
  148. case CELL_TYPE:
  149. return (Rast_is_c_null_value((CELL *) rast));
  150. case FCELL_TYPE:
  151. return (Rast_is_f_null_value((FCELL *) rast));
  152. case DCELL_TYPE:
  153. return (Rast_is_d_null_value((DCELL *) rast));
  154. default:
  155. G_warning("Rast_is_null_value: wrong data type!");
  156. return FALSE;
  157. }
  158. }
  159. /*!
  160. \brief To check if a CELL raster value is set to NULL
  161. Returns 1 if <em>cell</em> is NULL, 0 otherwise. This will test if the
  162. value <em>cell</em> is the largest <tt>int</tt>.
  163. \param cellVal CELL raster value to check
  164. \return TRUE if CELL raster value is NULL
  165. \return FALSE otherwise
  166. */
  167. int Rast_is_c_null_value(const CELL * cellVal)
  168. {
  169. /* Check if the CELL value matches the null pattern */
  170. return *cellVal == (CELL) 0x80000000;
  171. }
  172. /*!
  173. \brief To check if a FCELL raster value is set to NULL
  174. Returns 1 if <em>fcell</em> is NULL, 0 otherwise. This will test if
  175. the value <em>fcell</em> is a NaN. It isn't good enough to test for
  176. a particular NaN bit pattern since the machine code may change this
  177. bit pattern to a different NaN. The test will be
  178. \code
  179. if(fcell==0.0) return 0;
  180. if(fcell>0.0) return 0;
  181. if(fcell<0.0) return 0;
  182. return 1;
  183. \endcode
  184. or (as suggested by Mark Line)
  185. \code
  186. return (fcell != fcell);
  187. \endcode
  188. \param fcellVal FCELL raster value to check
  189. \return TRUE if FCELL raster value is NULL
  190. \return FALSE otherwise
  191. */
  192. int Rast_is_f_null_value(const FCELL * fcellVal)
  193. {
  194. return *fcellVal != *fcellVal;
  195. }
  196. /*!
  197. \brief To check if a DCELL raster value is set to NULL
  198. Returns 1 if <em>dcell</em> is NULL, 0 otherwise. This will test if
  199. the value <em>dcell</em> is a NaN. Same test as in
  200. Rast_is_f_null_value().
  201. \param dcellVal DCELL raster value to check
  202. \return TRUE if DCELL raster value is NULL
  203. \return FALSE otherwise
  204. */
  205. int Rast_is_d_null_value(const DCELL * dcellVal)
  206. {
  207. return *dcellVal != *dcellVal;
  208. }
  209. /*!
  210. \brief To insert null values into a map.
  211. - If the <em>data_type</em> is CELL_TYPE, calls Rast_insert_c_null_values()
  212. - If the <em>data_type</em> is FCELL_TYPE, calls Rast_insert_f_null_values()
  213. - If the <em>data_type</em> is DCELL_TYPE, calls Rast_insert_d_null_values()
  214. \param rast pointer raster values
  215. \param null_row null row
  216. \param ncols number of columns
  217. \param data_type type of raster - CELL, FCELL, DCELL
  218. */
  219. void Rast_insert_null_values(void *rast, char *null_row, int ncols,
  220. RASTER_MAP_TYPE data_type)
  221. {
  222. EmbedGivenNulls(rast, null_row, data_type, ncols);
  223. }
  224. /*!
  225. \brief To insert null values into an integer raster map (CELL)
  226. For each of the <em>count</em> <em>flags</em> which is true(!=0),
  227. set the corresponding <em>cell</em> to the NULL value.
  228. \param rast pointer raster values
  229. \param null_row null row
  230. \param ncols number of columns
  231. */
  232. void Rast_insert_c_null_values(CELL * cellVal, char *null_row, int ncols)
  233. {
  234. EmbedGivenNulls((void *)cellVal, null_row, CELL_TYPE, ncols);
  235. }
  236. /*!
  237. \brief To insert null values into an floating-point raster map (FCELL)
  238. \param fcellVal pointer raster values
  239. \param null_row null row
  240. \param ncols number of columns
  241. */
  242. void Rast_insert_f_null_values(FCELL * fcellVal, char *null_row, int ncols)
  243. {
  244. EmbedGivenNulls((void *)fcellVal, null_row, FCELL_TYPE, ncols);
  245. }
  246. /*!
  247. \brief To insert null values into an floating-point raster map (FCELL)
  248. For each for the <em>count</em> <em>flag</em> which is true(!=0), set
  249. the corresponding <em>dcell</em> to the NULL value.
  250. \param dcellVal pointer raster values
  251. \param null_row null row
  252. \param ncols number of columns
  253. */
  254. void Rast_insert_d_null_values(DCELL * dcellVal, char *null_row, int ncols)
  255. {
  256. EmbedGivenNulls((void *)dcellVal, null_row, DCELL_TYPE, ncols);
  257. }
  258. /*!
  259. \brief Check NULL
  260. Note: Only for internal use.
  261. \param flags ?
  262. \param bit_num ?
  263. \param n ?
  264. \return -1 on error
  265. */
  266. int Rast__check_null_bit(const unsigned char *flags, int bit_num, int n)
  267. {
  268. int ind;
  269. int offset;
  270. /* find the index of the unsigned char in which this bit appears */
  271. ind = Rast__null_bitstream_size(bit_num + 1) - 1;
  272. /* find how many unsigned chars the buffer with bit_num+1 (counting from 0
  273. has and subtract 1 to get unsigned char index */
  274. if (ind > Rast__null_bitstream_size(n) - 1) {
  275. G_warning("Rast__check_null_bit: Unable to access index %d. "
  276. "Size of flags is %d (bit # is %d)",
  277. ind, Rast__null_bitstream_size(n) - 1, bit_num);
  278. return -1;
  279. }
  280. offset = (ind + 1) * 8 - bit_num - 1;
  281. return ((flags[ind] & ((unsigned char)1 << offset)) != 0);
  282. }
  283. /*!
  284. \brief Given array of 0/1 of length n starting from column.
  285. Note: Only for internal use.
  286. Given array of 0/1 of length n starting from column set the
  287. corresponding bits of flags; total number of bits in flags is ncols.
  288. \param zero_ones
  289. \param flags
  290. \param col
  291. \param n
  292. \param ncols
  293. \return 0
  294. \return 1
  295. */
  296. int G__set_flags_from_01_random(const char *zero_ones, unsigned char *flags,
  297. int col, int n, int ncols)
  298. {
  299. unsigned char v;
  300. int count;
  301. int size;
  302. int i, k;
  303. if (col == 0 && n == ncols) {
  304. Rast__convert_01_flags(zero_ones, flags, n);
  305. return 0;
  306. }
  307. count = 0;
  308. size = Rast__null_bitstream_size(ncols);
  309. for (i = 0; i < size; i++) {
  310. v = 0;
  311. k = 8;
  312. while (k-- > 0) {
  313. if (count >= col && count < (col + n)) {
  314. v = v | ((unsigned char)zero_ones[count - col] << k);
  315. }
  316. else if (count < ncols) {
  317. v = v |
  318. ((unsigned char)Rast__check_null_bit(flags, count, ncols) << k);
  319. }
  320. /* otherwise keep this bit the same as it was */
  321. count++;
  322. }
  323. flags[i] = v;
  324. }
  325. return 1;
  326. }
  327. /*!
  328. \brief ?
  329. Note: Only for internal use.
  330. \param zero_ones
  331. \param flags
  332. \param n
  333. */
  334. void Rast__convert_01_flags(const char *zero_ones, unsigned char *flags, int n)
  335. {
  336. unsigned char *v;
  337. int count;
  338. int size;
  339. int i, k;
  340. /* pad the flags with 0's to make size multiple of 8 */
  341. v = flags;
  342. size = Rast__null_bitstream_size(n);
  343. count = 0;
  344. for (i = 0; i < size; i++) {
  345. *v = 0;
  346. k = 8;
  347. while (k-- > 0) {
  348. if (count < n) {
  349. *v = *v | ((unsigned char)zero_ones[count] << k);
  350. }
  351. count++;
  352. }
  353. v++;
  354. }
  355. }
  356. /*!
  357. \brief ?
  358. Note: Only for internal use.
  359. \param zero_ones
  360. \param flags
  361. \param n
  362. */
  363. void Rast__convert_flags_01(char *zero_ones, const unsigned char *flags, int n)
  364. {
  365. const unsigned char *v;
  366. int count;
  367. int size;
  368. int i, k;
  369. count = 0;
  370. v = flags;
  371. size = Rast__null_bitstream_size(n);
  372. for (i = 0; i < size; i++) {
  373. k = 8;
  374. while (k-- > 0) {
  375. if (count < n) {
  376. zero_ones[count] = ((*v & ((unsigned char)1 << k)) != 0);
  377. count++;
  378. }
  379. }
  380. v++;
  381. }
  382. }
  383. /*!
  384. \brief ?
  385. Note: Only for internal use.
  386. \param flags
  387. \param cols
  388. */
  389. void Rast__init_null_bits(unsigned char *flags, int cols)
  390. {
  391. unsigned char *v;
  392. int size;
  393. int i;
  394. /* pad the flags with 0's to make size multiple of 8 */
  395. v = flags;
  396. size = Rast__null_bitstream_size(cols);
  397. for (i = 0; i < size; i++) {
  398. if ((i + 1) * 8 <= cols) {
  399. *v = (unsigned char)255;
  400. }
  401. else {
  402. *v = (unsigned char)255 << ((i + 1) * 8 - cols);
  403. }
  404. v++;
  405. }
  406. }