range.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /**********************************************************************
  2. *
  3. * G_read_range (name, mapset, range)
  4. * const char *name name of map
  5. * const char *mapset mapset that map belongs to
  6. * struct Range *range struct to hold range info
  7. *
  8. * Reads the data range information associated with map layer "map"
  9. * in mapset "mapset"
  10. *
  11. * returns: 1 if successful
  12. * 2 range is empty
  13. * 3 map is fp: get range from quant rules
  14. * -1 on fail
  15. *
  16. * note: a warning message is printed if the file is missing or incorrect
  17. *
  18. **********************************************************************
  19. *
  20. * G_read_fp_range (name, mapset, range)
  21. * const char *name name of map
  22. * const char *mapset mapset that map belongs to
  23. * struct FPRange *range struct to hold range info
  24. *
  25. * Reads the fp data range information associated with map layer "map"
  26. * in mapset "mapset" . If map is integer, the integer range is read
  27. * and the max and min values are casted to doubles and copied to FPRange
  28. *
  29. * returns: 1 if successful
  30. * 2 range is empty
  31. * -1 on fail
  32. *
  33. * note: a warning message is printed if the file is missing or incorrect
  34. *
  35. **********************************************************************
  36. *
  37. * G_write_[fp_]range (name, range)
  38. * const char *name name of map
  39. * struct [FP]Range *range struct holding range info
  40. *
  41. * Writes the range information associated with map layer "map"
  42. *
  43. * returns: 0 if successful
  44. * -1 on fail (or if the map is fp )
  45. *
  46. **********************************************************************
  47. *
  48. * G_init_[fp_]range (range)
  49. * struct [FP]Range *range struct for range info
  50. *
  51. * initializes range structure for call to G_update_[fp_]range()
  52. *
  53. **********************************************************************
  54. *
  55. * G_construct_default_range (range)
  56. * struct Range *range struct for range info
  57. *
  58. * returns 1 and range is set to DEFAULT_CELL_MIN
  59. * and DEFAULT_SET_MAX, otherwise returns -1
  60. *
  61. **********************************************************************
  62. *
  63. * G_update_[fp_]range (cat, range)
  64. * DCELL cat cat to be factored into range
  65. * struct [FP]Range *range struct for range info
  66. **********************************************************************
  67. *
  68. * G_row_update_[fp_]range (rast, range, data_type)
  69. * void *rast raster row to be factored into range
  70. * struct [FP]Range *range struct for range info
  71. * RASTER_MAP_TYPE data_type;
  72. **********************************************************************
  73. *
  74. * G_get_[fp_]range_min_max (range, min, max)
  75. * struct [FP]Range *range;
  76. * [D]CELL *min, *max;
  77. **********************************************************************/
  78. #include <unistd.h>
  79. #include <rpc/types.h> /* need this for sgi */
  80. #include <rpc/xdr.h>
  81. #include "G.h"
  82. #include <grass/glocale.h>
  83. #define DEFAULT_CELL_MIN 1
  84. #define DEFAULT_CELL_MAX 255
  85. /*-------------------------------------------------------------------------*/
  86. /*-------------------------------------------------------------------------*/
  87. /* range functions for type "Range" */
  88. /*-------------------------------------------------------------------------*/
  89. void G__remove_fp_range(const char *name)
  90. {
  91. G_remove_misc("cell_misc", "f_range", name);
  92. }
  93. /*!
  94. * \brief
  95. *
  96. * Sets the integer range <em>r</em> to [1,255]
  97. *
  98. * \param r
  99. * \return
  100. */
  101. void G_construct_default_range(struct Range *range)
  102. {
  103. G_update_range(DEFAULT_CELL_MIN, range);
  104. G_update_range(DEFAULT_CELL_MAX, range);
  105. }
  106. /*!
  107. * \brief
  108. *
  109. * Read the floating point range file <tt>f_range</tt>. This file is
  110. * written in binary using XDR format. If there is no defined min/max in <em>r</em>,
  111. * an empty <tt>f_range</tt>file is created.
  112. * An empty range file indicates that the min, max are undefined. This is a
  113. * valid case, and the result should be an initialized range struct with no
  114. * defined min/max.
  115. * If the range file is missing and the map is a floating-point map, this
  116. * function will create a default range by calling <tt>G_construct_default_range()</tt>.
  117. *
  118. * \param r
  119. * \param name
  120. * \param mapset
  121. * \return int
  122. */
  123. int G_read_fp_range(const char *name, const char *mapset,
  124. struct FPRange *drange)
  125. {
  126. struct Range range;
  127. int fd;
  128. char buf[200], xdr_buf[100];
  129. DCELL dcell1, dcell2;
  130. XDR xdr_str;
  131. G_init_fp_range(drange);
  132. if (G_raster_map_type(name, mapset) == CELL_TYPE) {
  133. /* if map is integer
  134. read integer range and convert it to double */
  135. if (G_read_range(name, mapset, &range) >= 0) {
  136. /* if the integer range is empty */
  137. if (range.first_time)
  138. return 2;
  139. G_update_fp_range((DCELL) range.min, drange);
  140. G_update_fp_range((DCELL) range.max, drange);
  141. return 1;
  142. }
  143. return -1;
  144. }
  145. fd = -1;
  146. if (G_find_file2_misc("cell_misc", "f_range", name, mapset)) {
  147. fd = G_open_old_misc("cell_misc", "f_range", name, mapset);
  148. if (fd < 0)
  149. goto error;
  150. if (read(fd, xdr_buf, 2 * XDR_DOUBLE_NBYTES) != 2 * XDR_DOUBLE_NBYTES)
  151. return 2;
  152. xdrmem_create(&xdr_str, xdr_buf, (u_int) XDR_DOUBLE_NBYTES * 2,
  153. XDR_DECODE);
  154. /* if the f_range file exists, but empty */
  155. if (!xdr_double(&xdr_str, &dcell1) || !xdr_double(&xdr_str, &dcell2))
  156. goto error;
  157. G_update_fp_range(dcell1, drange);
  158. G_update_fp_range(dcell2, drange);
  159. close(fd);
  160. return 1;
  161. }
  162. error:
  163. if (fd > 0)
  164. close(fd);
  165. sprintf(buf, _("can't read f_range file for [%s in %s]"), name, mapset);
  166. G_warning(buf);
  167. return -1;
  168. }
  169. /*-------------------------------------------------------------------------*/
  170. /*!
  171. * \brief read raster range
  172. *
  173. * This routine reads the range information for the
  174. * raster map <b>name</b> in <b>mapset</b> into the <b>range</b>
  175. * structure.
  176. * A diagnostic message is printed and -1 is returned if there is an error
  177. * reading the range file. Otherwise, 0 is returned.
  178. *
  179. * Old range file (those with 4 numbers) should
  180. * treat zeros in this file as NULL-values. New range files (those with just 2
  181. * numbers) should treat these numbers as real data (zeros are real data in this
  182. * case).
  183. * An empty range file indicates that the min, max are undefined. This is a
  184. * valid case, and the result should be an initialized range struct with no
  185. * defined min/max.
  186. * If the range file is missing and the map is a floating-point map, this
  187. * function will create a default range by calling <tt>G_construct_default_range()</tt>.
  188. *
  189. * \param name
  190. * \param mapset
  191. * \param range
  192. *
  193. * \return int
  194. */
  195. int G_read_range(const char *name, const char *mapset, struct Range *range)
  196. {
  197. FILE *fd;
  198. CELL x[4];
  199. char buf[200];
  200. int n, count;
  201. struct Quant quant;
  202. struct FPRange drange;
  203. G_init_range(range);
  204. fd = NULL;
  205. /* if map is not integer, read quant rules, and get limits */
  206. if (G_raster_map_type(name, mapset) != CELL_TYPE) {
  207. DCELL dmin, dmax;
  208. if (G_read_quant(name, mapset, &quant) < 0) {
  209. sprintf(buf,
  210. "G_read_range(): can't read quant rules for fp map %s@%s",
  211. name, mapset);
  212. G_warning(buf);
  213. return -1;
  214. }
  215. if (G_quant_is_truncate(&quant) || G_quant_is_round(&quant)) {
  216. if (G_read_fp_range(name, mapset, &drange) >= 0) {
  217. G_get_fp_range_min_max(&drange, &dmin, &dmax);
  218. if (G_quant_is_truncate(&quant)) {
  219. x[0] = (CELL) dmin;
  220. x[1] = (CELL) dmax;
  221. }
  222. else { /* round */
  223. if (dmin > 0)
  224. x[0] = (CELL) (dmin + .5);
  225. else
  226. x[0] = (CELL) (dmin - .5);
  227. if (dmax > 0)
  228. x[1] = (CELL) (dmax + .5);
  229. else
  230. x[1] = (CELL) (dmax - .5);
  231. }
  232. }
  233. else
  234. return -1;
  235. }
  236. else
  237. G_quant_get_limits(&quant, &dmin, &dmax, &x[0], &x[1]);
  238. G_update_range(x[0], range);
  239. G_update_range(x[1], range);
  240. return 3;
  241. }
  242. if (G_find_file2_misc("cell_misc", "range", name, mapset)) {
  243. fd = G_fopen_old_misc("cell_misc", "range", name, mapset);
  244. if (!fd)
  245. goto error;
  246. /* if range file exists but empty */
  247. if (!fgets(buf, sizeof buf, fd))
  248. return 2;
  249. x[0] = x[1] = x[2] = x[3] = 0;
  250. count = sscanf(buf, "%d%d%d%d", &x[0], &x[1], &x[2], &x[3]);
  251. /* if wrong format */
  252. if (count <= 0)
  253. goto error;
  254. for (n = 0; n < count; n++) {
  255. /* if count==4, the range file is old (4.1) and 0's in it
  256. have to be ignored */
  257. if (count < 4 || x[n])
  258. G_update_range((CELL) x[n], range);
  259. }
  260. fclose(fd);
  261. return 1;
  262. }
  263. error:
  264. if (fd)
  265. fclose(fd);
  266. sprintf(buf, _("can't read range file for [%s in %s]"), name, mapset);
  267. G_warning(buf);
  268. return -1;
  269. }
  270. /*-------------------------------------------------------------------------*/
  271. /*!
  272. * \brief write raster range file
  273. *
  274. * This routine writes the range information for the raster map
  275. * <b>name</b> in the current mapset from the <b>range</b> structure.
  276. * A diagnostic message is printed and -1 is returned if there is an error
  277. * writing the range file. Otherwise, 0 is returned.
  278. *
  279. * This routine only writes 2 numbers (min,max) to the range
  280. * file, instead of the 4 (pmin,pmax,nmin,nmax) previously written.
  281. * If there is no defined min,max, an empty file is written.
  282. *
  283. * \param name
  284. * \param range
  285. *
  286. * \return int
  287. */
  288. int G_write_range(const char *name, const struct Range *range)
  289. {
  290. FILE *fd;
  291. if (G_raster_map_type(name, G_mapset()) != CELL_TYPE)
  292. goto error;
  293. fd = G_fopen_new_misc("cell_misc", "range", name);
  294. if (!fd)
  295. goto error;
  296. if (range->first_time)
  297. /* if range hasn't been updated */
  298. {
  299. fclose(fd);
  300. return 0;
  301. }
  302. fprintf(fd, "%ld %ld\n", (long)range->min, (long)range->max);
  303. fclose(fd);
  304. return 0;
  305. error:
  306. G_remove_misc("cell_misc", "range", name); /* remove the old file with this name */
  307. G_warning(_("can't write range file for [%s in %s]"),
  308. name, G_mapset());
  309. return -1;
  310. }
  311. /*-------------------------------------------------------------------------*/
  312. /*!
  313. * \brief
  314. *
  315. * Write the floating point range
  316. * file <tt>f_range</tt>. This file is written in binary using XDR format. If
  317. * there is no defined min/max in <em>r</em>, an empty <tt>f_range</tt>file is
  318. * created.
  319. *
  320. * \param r
  321. * \return
  322. */
  323. int G_write_fp_range(const char *name, const struct FPRange *range)
  324. {
  325. int fd;
  326. char xdr_buf[100];
  327. XDR xdr_str;
  328. fd = G_open_new_misc("cell_misc", "f_range", name);
  329. if (fd < 0)
  330. goto error;
  331. if (range->first_time)
  332. /* if range hasn't been updated, write empty file meaning Nulls */
  333. {
  334. close(fd);
  335. return 0;
  336. }
  337. xdrmem_create(&xdr_str, xdr_buf, (u_int) XDR_DOUBLE_NBYTES * 2,
  338. XDR_ENCODE);
  339. if (!xdr_double(&xdr_str, (double *)&(range->min)))
  340. goto error;
  341. if (!xdr_double(&xdr_str, (double *)&(range->max)))
  342. goto error;
  343. write(fd, xdr_buf, XDR_DOUBLE_NBYTES * 2);
  344. close(fd);
  345. return 0;
  346. error:
  347. G_remove_misc("cell_misc", "f_range", name); /* remove the old file with this name */
  348. G_warning(_("can't write range file for [%s in %s]"),
  349. name, G_mapset());
  350. return -1;
  351. }
  352. /*-------------------------------------------------------------------------*/
  353. /*!
  354. * \brief update range structure
  355. *
  356. * Compares the <b>cat</b> value with the minimum and maximum
  357. * values in the <b>range</b> structure, modifying the range if <b>cat</b>
  358. * extends the range.
  359. *
  360. * NULL-values must be detected and ignored.
  361. *
  362. * \param cat
  363. * \param range
  364. *
  365. * \return
  366. */
  367. void G_update_range(CELL cat, struct Range *range)
  368. {
  369. if (!G_is_c_null_value(&cat)) {
  370. if (range->first_time) {
  371. range->first_time = 0;
  372. range->min = cat;
  373. range->max = cat;
  374. return;
  375. }
  376. if (cat < range->min)
  377. range->min = cat;
  378. if (cat > range->max)
  379. range->max = cat;
  380. }
  381. }
  382. /*-------------------------------------------------------------------------*/
  383. void G_update_fp_range(DCELL val, struct FPRange *range)
  384. {
  385. if (!G_is_d_null_value(&val)) {
  386. if (range->first_time) {
  387. range->first_time = 0;
  388. range->min = val;
  389. range->max = val;
  390. return;
  391. }
  392. if (val < range->min)
  393. range->min = val;
  394. if (val > range->max)
  395. range->max = val;
  396. }
  397. }
  398. /*-------------------------------------------------------------------------*/
  399. /*!
  400. * \brief update range structure
  401. *
  402. * This routine updates the <b>range</b> data
  403. * just like <i>G_update_range</i>, but for <b>n</b> values from the
  404. * <b>cell</b> array.
  405. *
  406. * \param cell
  407. * \param n
  408. * \param range
  409. * \return
  410. */
  411. void G_row_update_range(const CELL *cell, int n, struct Range *range)
  412. {
  413. G__row_update_range(cell, n, range, 0);
  414. }
  415. /*-------------------------------------------------------------------------*/
  416. void G__row_update_range(const CELL *cell, int n,
  417. struct Range *range, int ignore_zeros)
  418. {
  419. CELL cat;
  420. while (n-- > 0) {
  421. cat = *cell++;
  422. if (G_is_c_null_value(&cat) || (ignore_zeros && !cat))
  423. continue;
  424. if (range->first_time) {
  425. range->first_time = 0;
  426. range->min = cat;
  427. range->max = cat;
  428. continue;
  429. }
  430. if (cat < range->min)
  431. range->min = cat;
  432. if (cat > range->max)
  433. range->max = cat;
  434. }
  435. }
  436. /*-------------------------------------------------------------------------*/
  437. void G_row_update_fp_range(const void *rast, int n,
  438. struct FPRange *range, RASTER_MAP_TYPE data_type)
  439. {
  440. DCELL val = 0L;
  441. while (n-- > 0) {
  442. switch (data_type) {
  443. case CELL_TYPE:
  444. val = (DCELL) * ((CELL *) rast);
  445. break;
  446. case FCELL_TYPE:
  447. val = (DCELL) * ((FCELL *) rast);
  448. break;
  449. case DCELL_TYPE:
  450. val = *((DCELL *) rast);
  451. break;
  452. }
  453. if (G_is_null_value(rast, data_type)) {
  454. rast = G_incr_void_ptr(rast, G_raster_size(data_type));
  455. continue;
  456. }
  457. if (range->first_time) {
  458. range->first_time = 0;
  459. range->min = val;
  460. range->max = val;
  461. }
  462. else {
  463. if (val < range->min)
  464. range->min = val;
  465. if (val > range->max)
  466. range->max = val;
  467. }
  468. rast = G_incr_void_ptr(rast, G_raster_size(data_type));
  469. }
  470. }
  471. /*-------------------------------------------------------------------------*/
  472. /*!
  473. * \brief initialize range structure
  474. *
  475. * Initializes the <b>range</b> structure for updates by
  476. * <i>G_update_range</i> and <i>G_row_update_range.</i>
  477. *
  478. * Must set a flag in the range structure that indicates that
  479. * no min/max have been defined - probably a <tt>"first"</tt> boolean flag.
  480. *
  481. * \param range
  482. * \return
  483. */
  484. void G_init_range(struct Range *range)
  485. {
  486. G_set_c_null_value(&(range->min), 1);
  487. G_set_c_null_value(&(range->max), 1);
  488. range->first_time = 1;
  489. }
  490. /*-------------------------------------------------------------------------*/
  491. /*!
  492. * \brief get range min and max
  493. *
  494. * The <b>min</b>inum and <b>max</b>imum CELL
  495. * values are extracted from the <b>range</b> structure.
  496. *
  497. * If the range structure has no defined min/max
  498. * (first!=0) there will not be a valid range. In this case the min and
  499. * max returned must be the NULL-value.
  500. *
  501. * \param range
  502. * \param min
  503. * \param max
  504. * \return
  505. */
  506. void G_get_range_min_max(const struct Range *range, CELL * min, CELL * max)
  507. {
  508. if (range->first_time) {
  509. G_set_c_null_value(min, 1);
  510. G_set_c_null_value(max, 1);
  511. }
  512. else {
  513. if (G_is_c_null_value(&(range->min)))
  514. G_set_c_null_value(min, 1);
  515. else
  516. *min = range->min;
  517. if (G_is_c_null_value(&(range->max)))
  518. G_set_c_null_value(max, 1);
  519. else
  520. *max = range->max;
  521. }
  522. }
  523. /*-------------------------------------------------------------------------*/
  524. /*!
  525. * \brief
  526. *
  527. * Must set a flag in the range
  528. * structure that indicates that no min/max have been defined - probably a
  529. * <tt>"first"</tt> boolean flag.
  530. *
  531. * \param r
  532. * \return
  533. */
  534. void G_init_fp_range(struct FPRange *range)
  535. {
  536. G_set_d_null_value(&(range->min), 1);
  537. G_set_d_null_value(&(range->max), 1);
  538. range->first_time = 1;
  539. }
  540. /*-------------------------------------------------------------------------*/
  541. /*!
  542. * \brief
  543. *
  544. * Extract the min/max from the range structure <em>r</em>.
  545. * If the range structure has no defined min/max (first!=0) there will not be a
  546. * valid range. In this case the min and max returned must be the NULL-value.
  547. *
  548. * \param r
  549. * \param min
  550. * \param max
  551. * \return
  552. */
  553. void G_get_fp_range_min_max(const struct FPRange *range,
  554. DCELL *min, DCELL *max)
  555. {
  556. if (range->first_time) {
  557. G_set_d_null_value(min, 1);
  558. G_set_d_null_value(max, 1);
  559. }
  560. else {
  561. if (G_is_d_null_value(&(range->min)))
  562. G_set_d_null_value(min, 1);
  563. else
  564. *min = range->min;
  565. if (G_is_d_null_value(&(range->max)))
  566. G_set_d_null_value(max, 1);
  567. else
  568. *max = range->max;
  569. }
  570. }