range.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /*!
  2. * \file lib/raster/range.c
  3. *
  4. * \brief Raster Library - Raster range file management
  5. *
  6. * (C) 2001-2009 GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author Original author CERL
  12. */
  13. #include <unistd.h>
  14. #include <rpc/types.h> /* need this for sgi */
  15. #include <grass/raster.h>
  16. #include <grass/glocale.h>
  17. #include "R.h"
  18. #define DEFAULT_CELL_MIN 1
  19. #define DEFAULT_CELL_MAX 255
  20. static void init_rstats(struct R_stats *);
  21. /*!
  22. \brief Remove floating-point range
  23. Note: For internal use only.
  24. \param name map name
  25. */
  26. void Rast__remove_fp_range(const char *name)
  27. {
  28. G_remove_misc("cell_misc", "f_range", name);
  29. }
  30. /*!
  31. * \brief Construct default range
  32. *
  33. * Sets the integer range to [1,255]
  34. *
  35. * \param[out] r pointer to Range structure which holds range info
  36. */
  37. void Rast_construct_default_range(struct Range *range)
  38. {
  39. Rast_update_range(DEFAULT_CELL_MIN, range);
  40. Rast_update_range(DEFAULT_CELL_MAX, range);
  41. }
  42. /*!
  43. * \brief Read floating-point range
  44. *
  45. * Read the floating point range file <i>drange</i>. This file is
  46. * written in binary using XDR format.
  47. *
  48. * An empty range file indicates that the min, max are undefined. This
  49. * is a valid case, and the result should be an initialized range
  50. * struct with no defined min/max. If the range file is missing and
  51. * the map is a floating-point map, this function will create a
  52. * default range by calling G_construct_default_range().
  53. *
  54. * \param name map name
  55. * \param mapset mapset name
  56. * \param drange pointer to FPRange structure which holds fp range
  57. *
  58. * \return 1 on success
  59. * \return 2 range is empty
  60. * \return -1 on error
  61. */
  62. int Rast_read_fp_range(const char *name, const char *mapset,
  63. struct FPRange *drange)
  64. {
  65. struct Range range;
  66. int fd;
  67. char xdr_buf[2][XDR_DOUBLE_NBYTES];
  68. DCELL dcell1, dcell2;
  69. Rast_init();
  70. Rast_init_fp_range(drange);
  71. if (Rast_map_type(name, mapset) == CELL_TYPE) {
  72. /* if map is integer
  73. read integer range and convert it to double */
  74. if (Rast_read_range(name, mapset, &range) >= 0) {
  75. /* if the integer range is empty */
  76. if (range.first_time)
  77. return 2;
  78. Rast_update_fp_range((DCELL) range.min, drange);
  79. Rast_update_fp_range((DCELL) range.max, drange);
  80. return 1;
  81. }
  82. return -1;
  83. }
  84. fd = -1;
  85. if (G_find_file2_misc("cell_misc", "f_range", name, mapset)) {
  86. fd = G_open_old_misc("cell_misc", "f_range", name, mapset);
  87. if (fd < 0) {
  88. G_warning(_("Unable to read fp range file for <%s>"),
  89. G_fully_qualified_name(name, mapset));
  90. return -1;
  91. }
  92. if (read(fd, xdr_buf, sizeof(xdr_buf)) != sizeof(xdr_buf)) {
  93. /* if the f_range file exists, but empty file, meaning Nulls */
  94. close(fd);
  95. G_debug(1, "Empty fp range file meaning Nulls for <%s>",
  96. G_fully_qualified_name(name, mapset));
  97. return 2;
  98. }
  99. G_xdr_get_double(&dcell1, xdr_buf[0]);
  100. G_xdr_get_double(&dcell2, xdr_buf[1]);
  101. Rast_update_fp_range(dcell1, drange);
  102. Rast_update_fp_range(dcell2, drange);
  103. close(fd);
  104. }
  105. return 1;
  106. }
  107. /*!
  108. * \brief Read raster range (CELL)
  109. *
  110. * This routine reads the range information for the raster map
  111. * <i>name</i> in <i>mapset</i> into the <i>range</i> structure.
  112. *
  113. * A diagnostic message is printed and -1 is returned if there is an error
  114. * reading the range file. Otherwise, 0 is returned.
  115. *
  116. * Old range file (those with 4 numbers) should treat zeros in this
  117. * file as NULL-values. New range files (those with just 2 numbers)
  118. * should treat these numbers as real data (zeros are real data in
  119. * this case). An empty range file indicates that the min, max are
  120. * undefined. This is a valid case, and the result should be an
  121. * initialized range struct with no defined min/max. If the range file
  122. * is missing and the map is a floating-point map, this function will
  123. * create a default range by calling G_construct_default_range().
  124. *
  125. * \param name map name
  126. * \param mapset mapset name
  127. * \param[out] range pointer to Range structure which holds range info
  128. *
  129. * \return -1 on error
  130. * \return 1 on success
  131. * \return 2 if range is empty
  132. * \return 3 if raster map is floating-point, get range from quant rules
  133. */
  134. int Rast_read_range(const char *name, const char *mapset, struct Range *range)
  135. {
  136. FILE *fd;
  137. CELL x[4];
  138. char buf[200];
  139. int n, count;
  140. struct Quant quant;
  141. struct FPRange drange;
  142. Rast_init_range(range);
  143. fd = NULL;
  144. /* if map is not integer, read quant rules, and get limits */
  145. if (Rast_map_type(name, mapset) != CELL_TYPE) {
  146. DCELL dmin, dmax;
  147. if (Rast_read_quant(name, mapset, &quant) < 0) {
  148. G_warning(_("Unable to read quant rules for raster map <%s>"),
  149. G_fully_qualified_name(name, mapset));
  150. return -1;
  151. }
  152. if (Rast_quant_is_truncate(&quant) || Rast_quant_is_round(&quant)) {
  153. if (Rast_read_fp_range(name, mapset, &drange) >= 0) {
  154. Rast_get_fp_range_min_max(&drange, &dmin, &dmax);
  155. if (Rast_quant_is_truncate(&quant)) {
  156. x[0] = (CELL) dmin;
  157. x[1] = (CELL) dmax;
  158. }
  159. else { /* round */
  160. if (dmin > 0)
  161. x[0] = (CELL) (dmin + .5);
  162. else
  163. x[0] = (CELL) (dmin - .5);
  164. if (dmax > 0)
  165. x[1] = (CELL) (dmax + .5);
  166. else
  167. x[1] = (CELL) (dmax - .5);
  168. }
  169. }
  170. else
  171. return -1;
  172. }
  173. else
  174. Rast_quant_get_limits(&quant, &dmin, &dmax, &x[0], &x[1]);
  175. Rast_update_range(x[0], range);
  176. Rast_update_range(x[1], range);
  177. return 3;
  178. }
  179. if (G_find_file2_misc("cell_misc", "range", name, mapset)) {
  180. fd = G_fopen_old_misc("cell_misc", "range", name, mapset);
  181. if (!fd) {
  182. G_warning(_("Unable to read range file for <%s>"),
  183. G_fully_qualified_name(name, mapset));
  184. return -1;
  185. }
  186. /* if range file exists but empty */
  187. if (!fgets(buf, sizeof buf, fd)) {
  188. if (fd)
  189. fclose(fd);
  190. return 2;
  191. }
  192. x[0] = x[1] = x[2] = x[3] = 0;
  193. count = sscanf(buf, "%d%d%d%d", &x[0], &x[1], &x[2], &x[3]);
  194. /* if wrong format */
  195. if (count <= 0) {
  196. if (fd)
  197. fclose(fd);
  198. G_warning(_("Unable to read range file for <%s>"),
  199. G_fully_qualified_name(name, mapset));
  200. return -1;
  201. }
  202. for (n = 0; n < count; n++) {
  203. /* if count==4, the range file is old (4.1) and 0's in it
  204. have to be ignored */
  205. if (count < 4 || x[n])
  206. Rast_update_range((CELL) x[n], range);
  207. }
  208. fclose(fd);
  209. }
  210. return 1;
  211. }
  212. /*!
  213. * \brief Read raster stats
  214. *
  215. * Read the stats file <i>stats</i>. This file is
  216. * written in binary using XDR format.
  217. *
  218. * An empty stats file indicates that all cells are NULL. This
  219. * is a valid case, and the result should be an initialized rstats
  220. * struct with no defined stats. If the stats file is missing
  221. * this function will create a default stats with count = 0.
  222. *
  223. * \param name map name
  224. * \param mapset mapset name
  225. * \param rstats pointer to R_stats structure which holds raster stats
  226. *
  227. * \return 1 on success
  228. * \return 2 stats is empty
  229. * \return -1 on error or stats file does not exist
  230. */
  231. int Rast_read_rstats(const char *name, const char *mapset,
  232. struct R_stats *rstats)
  233. {
  234. int fd;
  235. char xdr_buf[2][XDR_DOUBLE_NBYTES];
  236. DCELL dcell1, dcell2;
  237. unsigned char cc[8];
  238. char nbytes;
  239. int i;
  240. off_t count;
  241. Rast_init();
  242. init_rstats(rstats);
  243. fd = -1;
  244. if (!G_find_file2_misc("cell_misc", "stats", name, mapset)) {
  245. G_debug(1, "Stats file does not exist");
  246. return -1;
  247. }
  248. fd = G_open_old_misc("cell_misc", "stats", name, mapset);
  249. if (fd < 0) {
  250. G_warning(_("Unable to read stats file for <%s>"),
  251. G_fully_qualified_name(name, mapset));
  252. return -1;
  253. }
  254. if (read(fd, xdr_buf, sizeof(xdr_buf)) != sizeof(xdr_buf)) {
  255. /* if the stats file exists, but empty file, meaning Nulls */
  256. close(fd);
  257. G_debug(1, "Empty stats file meaning Nulls for <%s>",
  258. G_fully_qualified_name(name, mapset));
  259. return 2;
  260. }
  261. G_xdr_get_double(&dcell1, xdr_buf[0]);
  262. G_xdr_get_double(&dcell2, xdr_buf[1]);
  263. rstats->sum = dcell1;
  264. rstats->sumsq = dcell2;
  265. /* count; see cell_values_int() in get_row.c */
  266. nbytes = 1;
  267. if (read(fd, &nbytes, 1) != 1) {
  268. /* if the stats file exists, but empty file, meaning Nulls */
  269. close(fd);
  270. G_debug(1, "Unable to read byte count in stats file for <%s>",
  271. G_fully_qualified_name(name, mapset));
  272. return -1;
  273. }
  274. if (nbytes < 1 || nbytes > sizeof(off_t)) {
  275. close(fd);
  276. G_debug(1, "Invalid byte count in stats file for <%s>",
  277. G_fully_qualified_name(name, mapset));
  278. return -1;
  279. }
  280. if (read(fd, cc, nbytes) != nbytes) {
  281. /* incorrect number of bytes for count */
  282. close(fd);
  283. G_debug(1, "Unable to read count in stats file for <%s>",
  284. G_fully_qualified_name(name, mapset));
  285. return -1;
  286. }
  287. count = 0;
  288. /* copy byte by byte */
  289. for (i = nbytes - 1; i >= 0; i--) {
  290. count = (count << 8);
  291. count = count + cc[i];
  292. }
  293. rstats->count = count;
  294. close(fd);
  295. return 1;
  296. }
  297. /*!
  298. * \brief Write raster range file
  299. *
  300. * This routine writes the range information for the raster map
  301. * <i>name</i> in the current mapset from the <i>range</i> structure.
  302. * A diagnostic message is printed and -1 is returned if there is an
  303. * error writing the range file. Otherwise, 0 is returned.
  304. *
  305. * This routine only writes 2 numbers (min,max) to the range
  306. * file, instead of the 4 (pmin,pmax,nmin,nmax) previously written.
  307. * If there is no defined min,max, an empty file is written.
  308. *
  309. * \param name map name
  310. * \param range pointer to Range structure which holds range info
  311. */
  312. void Rast_write_range(const char *name, const struct Range *range)
  313. {
  314. FILE *fp;
  315. Rast_write_rstats(name, &(range->rstats));
  316. if (Rast_map_type(name, G_mapset()) != CELL_TYPE) {
  317. G_remove_misc("cell_misc", "range", name); /* remove the old file with this name */
  318. G_fatal_error(_("Unable to write range file for <%s>"), name);
  319. }
  320. fp = G_fopen_new_misc("cell_misc", "range", name);
  321. if (!fp) {
  322. G_remove_misc("cell_misc", "range", name); /* remove the old file with this name */
  323. G_fatal_error(_("Unable to write range file for <%s>"), name);
  324. }
  325. /* if range has been updated */
  326. if (!range->first_time)
  327. fprintf(fp, "%ld %ld\n", (long)range->min, (long)range->max);
  328. fclose(fp);
  329. }
  330. /*!
  331. * \brief Write raster range file (floating-point)
  332. *
  333. * Write the floating point range file <tt>f_range</tt>. This file is
  334. * written in binary using XDR format. If there is no defined min/max
  335. * in <em>range</em>, an empty <tt>f_range</tt> file is created.
  336. *
  337. * \param name map name
  338. * \param range pointer to FPRange which holds fp range info
  339. */
  340. void Rast_write_fp_range(const char *name, const struct FPRange *range)
  341. {
  342. int fd;
  343. char xdr_buf[2][XDR_DOUBLE_NBYTES];
  344. Rast_init();
  345. Rast_write_rstats(name, &(range->rstats));
  346. fd = G_open_new_misc("cell_misc", "f_range", name);
  347. if (fd < 0) {
  348. G_remove_misc("cell_misc", "f_range", name);
  349. G_fatal_error(_("Unable to write range file for <%s>"), name);
  350. }
  351. /* if range hasn't been updated, write empty file meaning Nulls */
  352. if (range->first_time) {
  353. close(fd);
  354. return;
  355. }
  356. G_xdr_put_double(xdr_buf[0], &range->min);
  357. G_xdr_put_double(xdr_buf[1], &range->max);
  358. if (write(fd, xdr_buf, sizeof(xdr_buf)) != sizeof(xdr_buf)) {
  359. G_remove_misc("cell_misc", "f_range", name);
  360. G_fatal_error(_("Unable to write range file for <%s>"), name);
  361. }
  362. close(fd);
  363. }
  364. /*!
  365. * \brief Write raster stats file
  366. *
  367. * Write the stats file <tt>stats</tt>. This file is
  368. * written in binary using XDR format. If the count is < 1
  369. * in <em>rstats</em>, an empty <tt>stats</tt> file is created.
  370. *
  371. * \param name map name
  372. * \param rstats pointer to R_stats which holds stats info
  373. */
  374. void Rast_write_rstats(const char *name, const struct R_stats *rstats)
  375. {
  376. int fd;
  377. char xdr_buf[2][XDR_DOUBLE_NBYTES];
  378. unsigned char cc[8];
  379. char nbytes;
  380. int i;
  381. off_t count;
  382. Rast_init();
  383. fd = G_open_new_misc("cell_misc", "stats", name);
  384. if (fd < 0) {
  385. G_remove_misc("cell_misc", "stats", name);
  386. G_fatal_error(_("Unable to write stats file for <%s>"), name);
  387. }
  388. /* if count is zero, write empty file meaning Nulls */
  389. if (rstats->count < 1) {
  390. close(fd);
  391. return;
  392. }
  393. G_xdr_put_double(xdr_buf[0], &rstats->sum);
  394. G_xdr_put_double(xdr_buf[1], &rstats->sumsq);
  395. if (write(fd, xdr_buf, sizeof(xdr_buf)) != sizeof(xdr_buf)) {
  396. G_remove_misc("cell_misc", "stats", name);
  397. G_fatal_error(_("Unable to write stats file for <%s>"), name);
  398. }
  399. /* count; see convert_int() in put_row.c */
  400. count = rstats->count;
  401. nbytes = 0;
  402. /* copy byte by byte */
  403. for (i = 0; i < sizeof(off_t); i++) {
  404. cc[i] = count & 0xff;
  405. count >>= 8;
  406. if (cc[i])
  407. nbytes = i;
  408. }
  409. nbytes++;
  410. /* number of bytes needed for count */
  411. if (write(fd, &nbytes, 1) != 1) {
  412. G_remove_misc("cell_misc", "stats", name);
  413. G_fatal_error(_("Unable to write stats file for <%s>"), name);
  414. }
  415. if (write(fd, cc, nbytes) != nbytes) {
  416. G_remove_misc("cell_misc", "stats", name);
  417. G_fatal_error(_("Unable to write stats file for <%s>"), name);
  418. }
  419. close(fd);
  420. }
  421. /*!
  422. * \brief Update range structure (CELL)
  423. *
  424. * Compares the <i>cat</i> value with the minimum and maximum values
  425. * in the <i>range</i> structure, modifying the range if <i>cat</i>
  426. * extends the range.
  427. *
  428. * NULL-values must be detected and ignored.
  429. *
  430. * \param cat raster value
  431. * \param range pointer to Range structure which holds range info
  432. */
  433. void Rast_update_range(CELL cat, struct Range *range)
  434. {
  435. if (!Rast_is_c_null_value(&cat)) {
  436. if (range->first_time) {
  437. range->first_time = 0;
  438. range->min = cat;
  439. range->max = cat;
  440. return;
  441. }
  442. if (cat < range->min)
  443. range->min = cat;
  444. if (cat > range->max)
  445. range->max = cat;
  446. }
  447. }
  448. /*!
  449. * \brief Update range structure (floating-point)
  450. *
  451. * Compares the <i>cat</i> value with the minimum and maximum values
  452. * in the <i>range</i> structure, modifying the range if <i>cat</i>
  453. * extends the range.
  454. *
  455. * NULL-values must be detected and ignored.
  456. *
  457. * \param val raster value
  458. * \param range pointer to Range structure which holds range info
  459. */
  460. void Rast_update_fp_range(DCELL val, struct FPRange *range)
  461. {
  462. if (!Rast_is_d_null_value(&val)) {
  463. if (range->first_time) {
  464. range->first_time = 0;
  465. range->min = val;
  466. range->max = val;
  467. return;
  468. }
  469. if (val < range->min)
  470. range->min = val;
  471. if (val > range->max)
  472. range->max = val;
  473. }
  474. }
  475. /*!
  476. * \brief Update range structure based on raster row (CELL)
  477. *
  478. * This routine updates the <i>range</i> data just like
  479. * Rast_update_range(), but for <i>n</i> values from the <i>cell</i>
  480. * array.
  481. *
  482. * \param cell raster values
  483. * \param n number of values
  484. * \param range pointer to Range structure which holds range info
  485. */
  486. void Rast_row_update_range(const CELL * cell, int n, struct Range *range)
  487. {
  488. Rast__row_update_range(cell, n, range, 0);
  489. }
  490. /*!
  491. * \brief Update range structure based on raster row
  492. *
  493. * Note: for internal use only.
  494. *
  495. * \param cell raster values
  496. * \param n number of values
  497. * \param range pointer to Range structure which holds range info
  498. * \param ignore_zeros ignore zeros
  499. */
  500. void Rast__row_update_range(const CELL * cell, int n,
  501. struct Range *range, int ignore_zeros)
  502. {
  503. CELL cat;
  504. while (n-- > 0) {
  505. cat = *cell++;
  506. if (Rast_is_c_null_value(&cat) || (ignore_zeros && !cat))
  507. continue;
  508. if (range->first_time) {
  509. range->first_time = 0;
  510. range->min = cat;
  511. range->max = cat;
  512. range->rstats.sum = cat;
  513. range->rstats.sumsq = (DCELL) cat * cat;
  514. range->rstats.count = 1;
  515. continue;
  516. }
  517. if (cat < range->min)
  518. range->min = cat;
  519. if (cat > range->max)
  520. range->max = cat;
  521. range->rstats.sum += cat;
  522. range->rstats.sumsq += (DCELL) cat * cat;
  523. range->rstats.count += 1;
  524. }
  525. }
  526. /*!
  527. * \brief Update range structure based on raster row (floating-point)
  528. *
  529. * This routine updates the <i>range</i> data just like
  530. * Rast_update_range(), but for <i>n</i> values from the <i>cell</i>
  531. * array.
  532. *
  533. * \param cell raster values
  534. * \param n number of values
  535. * \param range pointer to Range structure which holds range info
  536. * \param data_type raster type (CELL, FCELL, DCELL)
  537. */
  538. void Rast_row_update_fp_range(const void *rast, int n,
  539. struct FPRange *range,
  540. RASTER_MAP_TYPE data_type)
  541. {
  542. size_t size = Rast_cell_size(data_type);
  543. DCELL val = 0.0;
  544. while (n-- > 0) {
  545. switch (data_type) {
  546. case CELL_TYPE:
  547. val = (DCELL) * ((CELL *) rast);
  548. break;
  549. case FCELL_TYPE:
  550. val = (DCELL) * ((FCELL *) rast);
  551. break;
  552. case DCELL_TYPE:
  553. val = *((DCELL *) rast);
  554. break;
  555. }
  556. if (Rast_is_null_value(rast, data_type)) {
  557. rast = G_incr_void_ptr(rast, size);
  558. continue;
  559. }
  560. if (range->first_time) {
  561. range->first_time = 0;
  562. range->min = val;
  563. range->max = val;
  564. range->rstats.sum = val;
  565. range->rstats.sumsq = val * val;
  566. range->rstats.count = 1;
  567. }
  568. else {
  569. if (val < range->min)
  570. range->min = val;
  571. if (val > range->max)
  572. range->max = val;
  573. range->rstats.sum += val;
  574. range->rstats.sumsq += val * val;
  575. range->rstats.count += 1;
  576. }
  577. rast = G_incr_void_ptr(rast, size);
  578. }
  579. }
  580. /*!
  581. * \brief Initialize range structure
  582. *
  583. * Initializes the <i>range</i> structure for updates by
  584. * Rast_update_range() and Rast_row_update_range().
  585. *
  586. * Must set a flag in the range structure that indicates that no
  587. * min/max have been defined - probably a <tt>"first"</tt> boolean
  588. * flag.
  589. *
  590. * \param range pointer to Range structure which holds range info
  591. */
  592. void Rast_init_range(struct Range *range)
  593. {
  594. Rast_set_c_null_value(&(range->min), 1);
  595. Rast_set_c_null_value(&(range->max), 1);
  596. init_rstats(&range->rstats);
  597. range->first_time = 1;
  598. }
  599. /*!
  600. * \brief Get range min and max
  601. *
  602. * The minimum and maximum CELL values are extracted from the
  603. * <i>range</i> structure.
  604. *
  605. * If the range structure has no defined min/max (first!=0) there will
  606. * not be a valid range. In this case the min and max returned must be
  607. * the NULL-value.
  608. *
  609. * \param range pointer to Range structure which holds range info
  610. * \param[out] min minimum value
  611. * \param[out] max maximum value
  612. */
  613. void Rast_get_range_min_max(const struct Range *range, CELL * min, CELL * max)
  614. {
  615. if (range->first_time) {
  616. Rast_set_c_null_value(min, 1);
  617. Rast_set_c_null_value(max, 1);
  618. }
  619. else {
  620. if (Rast_is_c_null_value(&(range->min)))
  621. Rast_set_c_null_value(min, 1);
  622. else
  623. *min = range->min;
  624. if (Rast_is_c_null_value(&(range->max)))
  625. Rast_set_c_null_value(max, 1);
  626. else
  627. *max = range->max;
  628. }
  629. }
  630. /*!
  631. * \brief Initialize fp range
  632. *
  633. * Must set a flag in the range structure that indicates that no
  634. * min/max have been defined - probably a <tt>"first"</tt> boolean
  635. * flag.
  636. *
  637. * \param range pointer to FPRange which holds fp range info
  638. */
  639. void Rast_init_fp_range(struct FPRange *range)
  640. {
  641. Rast_set_d_null_value(&(range->min), 1);
  642. Rast_set_d_null_value(&(range->max), 1);
  643. init_rstats(&range->rstats);
  644. range->first_time = 1;
  645. }
  646. /*!
  647. * \brief Get minimum and maximum value from fp range
  648. *
  649. * Extract the min/max from the range structure <i>range</i>. If the
  650. * range structure has no defined min/max (first!=0) there will not be
  651. * a valid range. In this case the min and max returned must be the
  652. * NULL-value.
  653. *
  654. * \param range pointer to FPRange which holds fp range info
  655. * \param[out] min minimum value
  656. * \param[out] max maximum value
  657. */
  658. void Rast_get_fp_range_min_max(const struct FPRange *range,
  659. DCELL * min, DCELL * max)
  660. {
  661. if (range->first_time) {
  662. Rast_set_d_null_value(min, 1);
  663. Rast_set_d_null_value(max, 1);
  664. }
  665. else {
  666. if (Rast_is_d_null_value(&(range->min)))
  667. Rast_set_d_null_value(min, 1);
  668. else
  669. *min = range->min;
  670. if (Rast_is_d_null_value(&(range->max)))
  671. Rast_set_d_null_value(max, 1);
  672. else
  673. *max = range->max;
  674. }
  675. }
  676. static void init_rstats(struct R_stats *rstats)
  677. {
  678. Rast_set_d_null_value(&(rstats->sum), 1);
  679. Rast_set_d_null_value(&(rstats->sumsq), 1);
  680. rstats->count = 0;
  681. }