range.c 17 KB

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