cats.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. /*!
  2. * \file raster/cats.c
  3. *
  4. * \brief Raster Library - Raster categories management
  5. *
  6. * Code in this file works with category files. There are two formats:
  7. * Pre 3.0 direct category encoding form:
  8. *
  9. * 2 categories
  10. * Map Title
  11. * Elevation: 1000.00 to 1005.00 feet
  12. * Elevation: 1005.00 to 1010.00 feet
  13. * Elevation: 1010.00 to 1015.00 feet
  14. *
  15. * 3.0 format
  16. *
  17. * # 2 categories
  18. * Map Title
  19. * Elevation: $1.2 to $2.2 feet ## Format Statement
  20. * 5.0 1000 5.0 1005 ## Coefficients
  21. *
  22. * The coefficient line can be followed by explicit category labels
  23. * which override the format label generation.
  24. * 0:no data
  25. * 2: .
  26. * 5: . ## explicit category labels
  27. * 7: .
  28. * explicit labels can be also of the form:
  29. * 5.5:5:9 label description
  30. * or
  31. * 15:30 label description
  32. *
  33. * In the format line
  34. * $1 refers to the value num*5.0+1000 (ie, using the first 2 coefficients)
  35. * $2 refers to the value num*5.0+1005 (ie, using the last 2 coefficients)
  36. *
  37. * $1.2 will print $1 with 2 decimal places.
  38. *
  39. * Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx
  40. * otherwise. The $yyy$ is optional. Thus
  41. *
  42. * $1 meter$?s
  43. *
  44. * will become: 1 meter (for category 1)
  45. * 2 meters (for category 2), etc.
  46. *
  47. * The format and coefficients above would be used to generate the
  48. * following statement in creation of the format appropriate category
  49. * string for category "num":
  50. *
  51. * sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
  52. *
  53. * Note: while both the format and coefficent lins must be present
  54. * a blank line for the fmt will effectively suppress automatic
  55. * label generation
  56. *
  57. * Note: quant rules of Categories structures are heavily dependent
  58. * on the fact that rules are stored in the same order they are entered.
  59. * since i-th rule and i-th label are entered at the same time, we
  60. * know that i-th rule maps fp range to i, thus we know for sure
  61. * that cats.labels[i] corresponds to i-th quant rule
  62. *
  63. * (C) 2001-2009 by the GRASS Development Team
  64. *
  65. * This program is free software under the GNU General Public License
  66. * (>=v2). Read the file COPYING that comes with GRASS for details.
  67. *
  68. * \author Original author CERL
  69. */
  70. #include <stdlib.h>
  71. #include <string.h>
  72. #include <grass/gis.h>
  73. #include <grass/raster.h>
  74. #include <grass/glocale.h>
  75. static void get_cond(char **, char *, DCELL);
  76. static int get_fmt(char **, char *, int *);
  77. static int cmp(const void *, const void *);
  78. static void write_cats(const char *element, const char *name,
  79. struct Categories *cats);
  80. static CELL read_cats(const char *element, const char *name,
  81. const char *mapset, struct Categories *pcats, int full);
  82. static struct Categories save_cats;
  83. /*!
  84. * \brief Read raster category file
  85. *
  86. * The category file for raster map <i>name</i> in <i>mapset</i> is
  87. * read into the <i>cats</i> structure. If there is an error reading
  88. * the category file, a diagnostic message is printed and -1 is
  89. * returned. Otherwise, 0 is returned.
  90. *
  91. * \param name raster map name
  92. * \param mapset mapset name
  93. * \param[out] cats pointer to Cats structure
  94. *
  95. * \return -1 on error
  96. * \return 0 on success
  97. */
  98. int Rast_read_cats(const char *name,
  99. const char *mapset, struct Categories *pcats)
  100. {
  101. switch (read_cats("cats", name, mapset, pcats, 1)) {
  102. case -2:
  103. G_warning(_("Category support for <%s@%s> missing"), name, mapset);
  104. break;
  105. case -1:
  106. G_warning(_("Category support for <%s@%s> invalid"), name, mapset);
  107. break;
  108. default:
  109. return 0;
  110. }
  111. return -1;
  112. }
  113. /*!
  114. * \brief Read vector category file
  115. *
  116. * <b>Note:</b> This function works with <b>old</b> vector format.
  117. *
  118. * \todo: To be moved to the vector library
  119. *
  120. * The category file for vector map <i>name</i> in <i>mapset</i> is
  121. * read into the <i>cats</i> structure. If there is an error reading
  122. * the category file, a diagnostic message is printed and -1 is
  123. * returned. Otherwise, 0 is returned.
  124. *
  125. * \param name vector map name
  126. * \param mapset mapset name
  127. * \param[out] cats pointer to Cats structure
  128. *
  129. * \return -1 on error
  130. * \return 0 on success
  131. */
  132. int Rast_read_vector_cats(const char *name,
  133. const char *mapset, struct Categories *pcats)
  134. {
  135. switch (read_cats("dig_cats", name, mapset, pcats, 1)) {
  136. case -2:
  137. G_warning(_("Category support for vector map <%s@%s> missing"),
  138. name, mapset);
  139. break;
  140. case -1:
  141. G_warning(_("Category support for vector map <%s@%s> invalid"),
  142. name, mapset);
  143. break;
  144. default:
  145. return 0;
  146. }
  147. return -1;
  148. }
  149. /*!
  150. \brief Get number of categories
  151. \param name raster map name
  152. \param mapset mapset name
  153. \return -1 on error
  154. \return number of cats
  155. */
  156. CELL Rast_get_max_c_cat(const char *name, const char *mapset)
  157. {
  158. struct Range range;
  159. CELL min, max;
  160. /* return the max category number */
  161. if (Rast_read_range(name, mapset, &range) < 0)
  162. return -1;
  163. Rast_get_range_min_max(&range, &min, &max);
  164. if (Rast_is_c_null_value(&max))
  165. max = 0;
  166. return max;
  167. }
  168. static CELL read_cats(const char *element,
  169. const char *name,
  170. const char *mapset, struct Categories *pcats, int full)
  171. {
  172. FILE *fd;
  173. char buff[1024];
  174. CELL cat;
  175. DCELL val1, val2;
  176. int old = 0, fp_map;
  177. long num = -1;
  178. if (strncmp(element, "dig", 3) == 0)
  179. fp_map = 0;
  180. else
  181. fp_map = Rast_map_is_fp(name, mapset);
  182. if (!(fd = G_fopen_old(element, name, mapset)))
  183. return -2;
  184. /* Read the number of categories */
  185. if (G_getl(buff, sizeof buff, fd) == 0)
  186. goto error;
  187. if (sscanf(buff, "# %ld", &num) == 1)
  188. old = 0;
  189. else if (sscanf(buff, "%ld", &num) == 1)
  190. old = 1;
  191. if (!full) {
  192. fclose(fd);
  193. if (num < 0)
  194. return 0; /* coorect */
  195. return (CELL) num;
  196. }
  197. /* Read the title for the file */
  198. if (G_getl(buff, sizeof buff, fd) == 0)
  199. goto error;
  200. G_strip(buff);
  201. /* G_ascii_check(buff) ; */
  202. Rast_init_cats(buff, pcats);
  203. if (num >= 0)
  204. pcats->num = num;
  205. if (!old) {
  206. char fmt[256];
  207. float m1, a1, m2, a2;
  208. if (G_getl(fmt, sizeof fmt, fd) == 0)
  209. goto error;
  210. /* next line contains equation coefficients */
  211. if (G_getl(buff, sizeof buff, fd) == 0)
  212. goto error;
  213. if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
  214. goto error;
  215. Rast_set_cats_fmt(fmt, m1, a1, m2, a2, pcats);
  216. }
  217. /* Read all category names */
  218. for (cat = 0;; cat++) {
  219. char label[1024];
  220. if (G_getl(buff, sizeof buff, fd) == 0)
  221. break;
  222. if (old)
  223. Rast_set_c_cat(&cat, &cat, buff, pcats);
  224. else {
  225. *label = 0;
  226. if (sscanf(buff, "%1s", label) != 1)
  227. continue;
  228. if (*label == '#')
  229. continue;
  230. *label = 0;
  231. /* for fp maps try to read a range of data */
  232. if (fp_map
  233. && sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
  234. Rast_set_cat(&val1, &val2, label, pcats, DCELL_TYPE);
  235. else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
  236. Rast_set_cat(&cat, &cat, label, pcats, CELL_TYPE);
  237. else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
  238. Rast_set_cat(&val1, &val1, label, pcats, DCELL_TYPE);
  239. else
  240. goto error;
  241. }
  242. }
  243. fclose(fd);
  244. return 0;
  245. error:
  246. fclose(fd);
  247. return -1;
  248. }
  249. /*!
  250. * \brief Get title from category structure struct
  251. *
  252. * \todo Remove from GIS Library, replace by Rast_get_c_cats_title().
  253. *
  254. * Map layers store a one-line title in the category structure as
  255. * well. This routine returns a pointer to the title contained in the
  256. * <i>cats</i> structure. A legal pointer is always returned. If the
  257. * map layer does not have a title, then a pointer to the empty string
  258. * "" is returned.
  259. *
  260. * \param cats pointer to Categories structure
  261. *
  262. * \return title
  263. * \return "" if missing
  264. */
  265. char *Rast_get_cats_title(const struct Categories *pcats)
  266. {
  267. return pcats->title ? pcats->title : "";
  268. }
  269. /*!
  270. * \brief Get a raster category label (CELL)
  271. *
  272. * This routine looks up category <i>rast</i> in the <i>pcats</i>
  273. * structure and returns a pointer to a string which is the label for
  274. * the category. A legal pointer is always returned. If the category
  275. * does not exist in <i>pcats</i>, then a pointer to the empty string
  276. * "" is returned.
  277. *
  278. * <b>Warning:</b> The pointer that is returned points to a hidden
  279. * static buffer. Successive calls to Rast_get_c_cat() overwrite this
  280. * buffer.
  281. *
  282. * \param rast cell value
  283. * \param pcats pointer to Categories structure
  284. *
  285. * \return pointer to category label
  286. * \return "" if category is not found
  287. */
  288. char *Rast_get_c_cat(CELL * rast, struct Categories *pcats)
  289. {
  290. return Rast_get_cat(rast, pcats, CELL_TYPE);
  291. }
  292. /*!
  293. * \brief Get a raster category label (FCELL)
  294. *
  295. * This routine looks up category <i>rast</i> in the <i>pcats</i>
  296. * structure and returns a pointer to a string which is the label for
  297. * the category. A legal pointer is always returned. If the category
  298. * does not exist in <i>pcats</i>, then a pointer to the empty string
  299. * "" is returned.
  300. *
  301. * <b>Warning:</b> The pointer that is returned points to a hidden
  302. * static buffer. Successive calls to Rast_get_c_cat() overwrite this
  303. * buffer.
  304. *
  305. * \param rast cell value
  306. * \param pcats pointer to Categories structure
  307. *
  308. * \return pointer to category label
  309. * \return "" if category is not found
  310. */
  311. char *Rast_get_f_cat(FCELL * rast, struct Categories *pcats)
  312. {
  313. return Rast_get_cat(rast, pcats, FCELL_TYPE);
  314. }
  315. /*!
  316. * \brief Get a raster category label (DCELL)
  317. *
  318. * This routine looks up category <i>rast</i> in the <i>pcats</i>
  319. * structure and returns a pointer to a string which is the label for
  320. * the category. A legal pointer is always returned. If the category
  321. * does not exist in <i>pcats</i>, then a pointer to the empty string
  322. * "" is returned.
  323. *
  324. * <b>Warning:</b> The pointer that is returned points to a hidden
  325. * static buffer. Successive calls to Rast_get_c_cat() overwrite this
  326. * buffer.
  327. *
  328. * \param rast cell value
  329. * \param pcats pointer to Categories structure
  330. *
  331. * \return pointer to category label
  332. * \return "" if category is not found
  333. */
  334. char *Rast_get_d_cat(DCELL * rast, struct Categories *pcats)
  335. {
  336. return Rast_get_cat(rast, pcats, DCELL_TYPE);
  337. }
  338. /*!
  339. * \brief Get a raster category label
  340. *
  341. * This routine looks up category <i>rast</i> in the <i>pcats</i>
  342. * structure and returns a pointer to a string which is the label for
  343. * the category. A legal pointer is always returned. If the category
  344. * does not exist in <i>pcats</i>, then a pointer to the empty string
  345. * "" is returned.
  346. *
  347. * <b>Warning:</b> The pointer that is returned points to a hidden
  348. * static buffer. Successive calls to Rast_get_c_cat() overwrite this
  349. * buffer.
  350. *
  351. * \param rast cell value
  352. * \param pcats pointer to Categories structure
  353. * \param data_type map type (CELL, FCELL, DCELL)
  354. *
  355. * \return pointer to category label
  356. * \return "" if category is not found
  357. */
  358. char *Rast_get_cat(void *rast,
  359. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  360. {
  361. static char label[1024];
  362. char *f, *l, *v;
  363. CELL i;
  364. DCELL val;
  365. float a[2];
  366. char fmt[30], value_str[30];
  367. if (Rast_is_null_value(rast, data_type)) {
  368. sprintf(label, "no data");
  369. return label;
  370. }
  371. /* first search the list of labels */
  372. *label = 0;
  373. val = Rast_get_d_value(rast, data_type);
  374. i = Rast_quant_get_cell_value(&pcats->q, val);
  375. G_debug(5, "Rast_get_cat(): val %lf found i %d", val, i);
  376. if (!Rast_is_c_null_value(&i) && i < pcats->ncats) {
  377. if (pcats->labels[i] != NULL)
  378. return pcats->labels[i];
  379. return label;
  380. }
  381. /* generate the label */
  382. if ((f = pcats->fmt) == NULL)
  383. return label;
  384. a[0] = (float)val *pcats->m1 + pcats->a1;
  385. a[1] = (float)val *pcats->m2 + pcats->a2;
  386. l = label;
  387. while (*f) {
  388. if (*f == '$') {
  389. f++;
  390. if (*f == '$')
  391. *l++ = *f++;
  392. else if (*f == '?') {
  393. f++;
  394. get_cond(&f, v = value_str, val);
  395. while (*v)
  396. *l++ = *v++;
  397. }
  398. else if (get_fmt(&f, fmt, &i)) {
  399. sprintf(v = value_str, fmt, a[i]);
  400. while (*v)
  401. *l++ = *v++;
  402. }
  403. else
  404. *l++ = '$';
  405. }
  406. else {
  407. *l++ = *f++;
  408. }
  409. }
  410. *l = 0;
  411. return label;
  412. }
  413. /*!
  414. * \brief Sets marks for all categories to 0.
  415. *
  416. * This initializes Categories structure for subsequest calls to
  417. * Rast_mark_cats() for each row of data, where non-zero mark for
  418. * i-th label means that some of the cells in rast_row are labeled
  419. * with i-th label and fall into i-th data range. These marks help
  420. * determine from the Categories structure which labels were used and
  421. * which weren't.
  422. *
  423. * \param pcats pointer to Categories structure
  424. */
  425. void Rast_unmark_cats(struct Categories *pcats)
  426. {
  427. int i;
  428. for (i = 0; i < pcats->ncats; i++)
  429. pcats->marks[i] = 0;
  430. }
  431. /*!
  432. * \brief Looks up the category label for each raster value (CELL).
  433. *
  434. * Looks up the category label for each raster value in the
  435. * <i>rast_row</i> and updates the marks for labels found.
  436. *
  437. * <b>Note:</b> Non-zero mark for i-th label stores the number of of
  438. * raster cells read so far which are labeled with i-th label and fall
  439. * into i-th data range.
  440. *
  441. * \param rast_row raster row to update stats
  442. * \param ncols number of columns
  443. * \param pcats pointer to Categories structure
  444. *
  445. */
  446. void Rast_mark_c_cats(const CELL * rast_row,
  447. int ncols, struct Categories *pcats)
  448. {
  449. Rast_mark_cats(rast_row, ncols, pcats, CELL_TYPE);
  450. }
  451. /*!
  452. * \brief Looks up the category label for each raster value (FCELL).
  453. *
  454. * Looks up the category label for each raster value in the
  455. * <i>rast_row</i> and updates the marks for labels found.
  456. *
  457. * <b>Note:</b> Non-zero mark for i-th label stores the number of of
  458. * raster cells read so far which are labeled with i-th label and fall
  459. * into i-th data range.
  460. *
  461. * \param rast_row raster row to update stats
  462. * \param ncols number of columns
  463. * \param pcats pointer to Categories structure
  464. *
  465. */
  466. void Rast_mark_f_cats(const FCELL * rast_row,
  467. int ncols, struct Categories *pcats)
  468. {
  469. Rast_mark_cats(rast_row, ncols, pcats, FCELL_TYPE);
  470. }
  471. /*!
  472. * \brief Looks up the category label for each raster value (DCELL).
  473. *
  474. * Looks up the category label for each raster value in the
  475. * <i>rast_row</i> and updates the marks for labels found.
  476. *
  477. * <b>Note:</b> Non-zero mark for i-th label stores the number of of
  478. * raster cells read so far which are labeled with i-th label and fall
  479. * into i-th data range.
  480. *
  481. * \param rast_row raster row to update stats
  482. * \param ncols number of columns
  483. * \param pcats pointer to Categories structure
  484. *
  485. */
  486. void Rast_mark_d_cats(const DCELL * rast_row,
  487. int ncols, struct Categories *pcats)
  488. {
  489. Rast_mark_cats(rast_row, ncols, pcats, DCELL_TYPE);
  490. }
  491. /*!
  492. * \brief Looks up the category label for each raster value (DCELL).
  493. *
  494. * Looks up the category label for each raster value in the
  495. * <i>rast_row</i> and updates the marks for labels found.
  496. *
  497. * <b>Note:</b> Non-zero mark for i-th label stores the number of of
  498. * raster cells read so far which are labeled with i-th label and fall
  499. * into i-th data range.
  500. *
  501. * \param rast_row raster row to update stats
  502. * \param ncols number of columns
  503. * \param pcats pointer to Categories structure
  504. *
  505. * \return -1 on error
  506. * \return 1 on success
  507. */
  508. int Rast_mark_cats(const void *rast_row,
  509. int ncols, struct Categories *pcats,
  510. RASTER_MAP_TYPE data_type)
  511. {
  512. size_t size = Rast_cell_size(data_type);
  513. CELL i;
  514. while (ncols-- > 0) {
  515. i = Rast_quant_get_cell_value(&pcats->q,
  516. Rast_get_d_value(rast_row, data_type));
  517. if (Rast_is_c_null_value(&i))
  518. continue;
  519. if (i > pcats->ncats)
  520. return -1;
  521. pcats->marks[i]++;
  522. rast_row = G_incr_void_ptr(rast_row, size);
  523. }
  524. return 1;
  525. }
  526. /*!
  527. * \brief Rewind raster categories
  528. *
  529. * After call to this function Rast_get_next_marked_cat() returns
  530. * the first marked cat label.
  531. *
  532. * \param pcats pointer to Categories structure
  533. */
  534. void Rast_rewind_cats(struct Categories *pcats)
  535. {
  536. pcats->last_marked_rule = -1;
  537. }
  538. /*!
  539. \brief Get next marked raster categories (DCELL)
  540. \param pcats pointer to Categories structure
  541. \param rast1, rast2 cell values (raster range)
  542. \param[out] count count
  543. \return NULL if not found
  544. \return description if found
  545. */
  546. char *Rast_get_next_marked_d_cat(struct Categories *pcats,
  547. DCELL * rast1, DCELL * rast2, long *count)
  548. {
  549. char *descr = NULL;
  550. int found, i;
  551. found = 0;
  552. /* pcats->ncats should be == Rast_quant_nof_rules(&pcats->q) */
  553. G_debug(3, "last marked %d nrules %d\n", pcats->last_marked_rule,
  554. Rast_quant_nof_rules(&pcats->q));
  555. for (i = pcats->last_marked_rule + 1; i < Rast_quant_nof_rules(&pcats->q);
  556. i++) {
  557. descr = Rast_get_ith_d_cat(pcats, i, rast1, rast2);
  558. G_debug(5, "%d %d", i, pcats->marks[i]);
  559. if (pcats->marks[i]) {
  560. found = 1;
  561. break;
  562. }
  563. }
  564. if (!found)
  565. return NULL;
  566. *count = pcats->marks[i];
  567. pcats->last_marked_rule = i;
  568. return descr;
  569. }
  570. /*!
  571. \brief Get next marked raster categories (CELL)
  572. \param pcats pointer to Categories structure
  573. \param rast1, rast2 cell values (raster range)
  574. \param[out] count count
  575. \return NULL if not found
  576. \return description if found
  577. */
  578. char *Rast_get_next_marked_c_cat(struct Categories *pcats,
  579. CELL * rast1, CELL * rast2, long *count)
  580. {
  581. return Rast_get_next_marked_cat(pcats, rast1, rast2, count, CELL_TYPE);
  582. }
  583. /*!
  584. \brief Get next marked raster categories (FCELL)
  585. \param pcats pointer to Categories structure
  586. \param rast1, rast2 cell values (raster range)
  587. \param[out] count count
  588. \return NULL if not found
  589. \return description if found
  590. */
  591. char *Rast_get_next_marked_f_cat(struct Categories *pcats,
  592. FCELL * rast1, FCELL * rast2, long *count)
  593. {
  594. return Rast_get_next_marked_cat(pcats, rast1, rast2, count, FCELL_TYPE);
  595. }
  596. /*!
  597. \brief Get next marked raster categories
  598. \param pcats pointer to Categories structure
  599. \param rast1, rast2 cell values (raster range)
  600. \param[out] count count
  601. \param data_type map type
  602. \return NULL if not found
  603. \return description if found
  604. */
  605. char *Rast_get_next_marked_cat(struct Categories *pcats,
  606. void *rast1, void *rast2,
  607. long *count, RASTER_MAP_TYPE data_type)
  608. {
  609. DCELL val1, val2;
  610. char *lab;
  611. lab = Rast_get_next_marked_d_cat(pcats, &val1, &val2, count);
  612. Rast_set_d_value(rast1, val1, data_type);
  613. Rast_set_d_value(rast2, val2, data_type);
  614. return lab;
  615. }
  616. static int get_fmt(char **f, char *fmt, int *i)
  617. {
  618. char *ff;
  619. ff = *f;
  620. if (*ff == 0)
  621. return 0;
  622. if (*ff == '$') {
  623. *f = ff + 1;
  624. return 0;
  625. }
  626. switch (*ff++) {
  627. case '1':
  628. *i = 0;
  629. break;
  630. case '2':
  631. *i = 1;
  632. break;
  633. default:
  634. return 0;
  635. }
  636. *fmt++ = '%';
  637. *fmt++ = '.';
  638. if (*ff++ != '.') {
  639. *f = ff - 1;
  640. *fmt++ = '0';
  641. *fmt++ = 'f';
  642. *fmt = 0;
  643. return 1;
  644. }
  645. *fmt = '0';
  646. while (*ff >= '0' && *ff <= '9')
  647. *fmt++ = *ff++;
  648. *fmt++ = 'f';
  649. *fmt = 0;
  650. *f = ff;
  651. return 1;
  652. }
  653. static void get_cond(char **f, char *value, DCELL val)
  654. {
  655. char *ff;
  656. ff = *f;
  657. if (val == 1.) {
  658. while (*ff)
  659. if (*ff++ == '$')
  660. break;
  661. }
  662. while (*ff)
  663. if (*ff == '$') {
  664. ff++;
  665. break;
  666. }
  667. else
  668. *value++ = *ff++;
  669. if (val != 1.) {
  670. while (*ff)
  671. if (*ff++ == '$')
  672. break;
  673. }
  674. *value = 0;
  675. *f = ff;
  676. }
  677. /*!
  678. * \brief Set a raster category label (CELL)
  679. *
  680. * Adds the label for range <i>rast1</i> through <i>rast2</i> in
  681. * category structure <i>pcats</i>.
  682. *
  683. * \param rast1, rast2 raster values (range)
  684. * \param label category label
  685. * \param pcats pointer to Categories structure
  686. *
  687. * \return -1 on error
  688. * \return 0 if null value detected
  689. * \return 1 on success
  690. */
  691. int Rast_set_c_cat(const CELL * rast1, const CELL * rast2,
  692. const char *label, struct Categories *pcats)
  693. {
  694. return Rast_set_cat(rast1, rast2, label, pcats, CELL_TYPE);
  695. }
  696. /*!
  697. * \brief Set a raster category label (FCELL)
  698. *
  699. * Adds the label for range <i>rast1</i> through <i>rast2</i> in
  700. * category structure <i>pcats</i>.
  701. *
  702. * \param rast1, rast2 raster values (range)
  703. * \param label category label
  704. * \param pcats pointer to Categories structure
  705. *
  706. * \return
  707. */
  708. int Rast_set_f_cat(const FCELL * rast1, const FCELL * rast2,
  709. const char *label, struct Categories *pcats)
  710. {
  711. return Rast_set_cat(rast1, rast2, label, pcats, FCELL_TYPE);
  712. }
  713. /*!
  714. * \brief Set a raster category label (DCELL)
  715. *
  716. * Adds the label for range <i>rast1</i> through <i>rast2</i> in
  717. * category structure <i>pcats</i>.
  718. *
  719. * \param rast1, rast2 raster values (range)
  720. * \param label category label
  721. * \param pcats pointer to Categories structure
  722. *
  723. * \return -1 on error
  724. * \return 0 if null value detected
  725. * \return 1 on success
  726. */
  727. int Rast_set_d_cat(const DCELL * rast1, const DCELL * rast2,
  728. const char *label, struct Categories *pcats)
  729. {
  730. long len;
  731. DCELL dtmp1, dtmp2;
  732. int i;
  733. char *descr;
  734. /* DEBUG fprintf(stderr,"Rast_set_d_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
  735. rast1,rast2,label,pcats); */
  736. if (Rast_is_d_null_value(rast1))
  737. return 0;
  738. if (Rast_is_d_null_value(rast2))
  739. return 0;
  740. /* DEBUG fprintf (stderr, "Rast_set_d_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
  741. /* the set_cat() functions are used in many places to reset the labels
  742. for the range (or cat) with existing label. In this case we don't
  743. want to store both rules with identical range even though the result
  744. of get_cat() will be correct, since it will use rule added later.
  745. we don't want to overuse memory and we don't want rules which are
  746. not used to be writen out in cats file. So we first look if
  747. the label for this range has been sen, and if it has, overwrite it */
  748. for (i = 0; i < pcats->ncats; i++) {
  749. descr = Rast_get_ith_d_cat(pcats, i, &dtmp1, &dtmp2);
  750. if ((dtmp1 == *rast1 && dtmp2 == *rast2)
  751. || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
  752. if (pcats->labels[i] != NULL)
  753. G_free(pcats->labels[i]);
  754. pcats->labels[i] = G_store(label);
  755. G_newlines_to_spaces(pcats->labels[i]);
  756. G_strip(pcats->labels[i]);
  757. return 1;
  758. }
  759. }
  760. /* when rule for this range does not exist */
  761. /* DEBUG fprintf (stderr, "Rast_set_d_cat(): New rule: adding %d %p\n", i, pcats->labels); */
  762. Rast_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats,
  763. pcats->ncats);
  764. pcats->ncats++;
  765. if (pcats->nalloc < pcats->ncats) {
  766. /* DEBUG fprintf (stderr, "Rast_set_d_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
  767. len = (pcats->nalloc + 256) * sizeof(char *);
  768. /* DEBUG fprintf (stderr, "Rast_set_d_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
  769. if (len != (int)len) { /* make sure len doesn't overflow int */
  770. pcats->ncats--;
  771. return -1;
  772. }
  773. /* DEBUG fprintf(stderr,"Rast_set_d_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
  774. if (pcats->nalloc) {
  775. /* DEBUG fprintf(stderr,"Rast_set_d_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
  776. pcats->labels =
  777. (char **)G_realloc((char *)pcats->labels, (int)len);
  778. }
  779. else {
  780. /* DEBUG fprintf(stderr,"Rast_set_d_cat(): alloc-ing new labels pointer array\n"); */
  781. pcats->labels = (char **)G_malloc((int)len);
  782. }
  783. /* fflush(stderr); */
  784. /* DEBUG fprintf (stderr, "Rast_set_d_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
  785. len = (pcats->nalloc + 256) * sizeof(int);
  786. if (len != (int)len) { /* make sure len doesn't overflow int */
  787. pcats->ncats--;
  788. return -1;
  789. }
  790. if (pcats->nalloc)
  791. pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
  792. else
  793. pcats->marks = (int *)G_malloc((int)len);
  794. pcats->nalloc += 256;
  795. }
  796. /* DEBUG fprintf(stderr,"Rast_set_d_cats(): store new label\n"); */
  797. pcats->labels[pcats->ncats - 1] = G_store(label);
  798. G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
  799. G_strip(pcats->labels[pcats->ncats - 1]);
  800. /* DEBUG
  801. fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
  802. */
  803. /* updates cats.num = max cat values. This is really just used in old
  804. raster programs, and I am doing it for backwards cmpatibility (Olga) */
  805. if ((CELL) * rast1 > pcats->num)
  806. pcats->num = (CELL) * rast1;
  807. if ((CELL) * rast2 > pcats->num)
  808. pcats->num = (CELL) * rast2;
  809. /* DEBUG fprintf(stderr,"Rast_set_d_cat(): done\n"); */
  810. /* DEBUG fflush(stderr); */
  811. return 1;
  812. }
  813. /*!
  814. * \brief Set a raster category label
  815. *
  816. * Adds the label for range <i>rast1</i> through <i>rast2</i> in
  817. * category structure <i>pcats</i>.
  818. *
  819. * \param rast1, rast2 raster values (range)
  820. * \param label category label
  821. * \param pcats pointer to Categories structure
  822. * \param data_type map type
  823. *
  824. * \return -1 on error
  825. * \return 0 if null value detected
  826. * \return 1 on success
  827. */
  828. int Rast_set_cat(const void *rast1, const void *rast2,
  829. const char *label,
  830. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  831. {
  832. DCELL val1, val2;
  833. val1 = Rast_get_d_value(rast1, data_type);
  834. val2 = Rast_get_d_value(rast2, data_type);
  835. return Rast_set_d_cat(&val1, &val2, label, pcats);
  836. }
  837. /*!
  838. * \brief Write raster category file
  839. *
  840. * \todo To be removed, replaced by Rast_write_cats().
  841. *
  842. * Writes the category file for the raster map <i>name</i> in the
  843. * current mapset from the <i>cats</i> structure.
  844. *
  845. * \param name map name
  846. * \param cats pointer to Categories structure
  847. *
  848. * \return void
  849. */
  850. void Rast_write_cats(const char *name, struct Categories *cats)
  851. {
  852. write_cats("cats", name, cats);
  853. }
  854. /*!
  855. * \brief Write vector category file
  856. *
  857. * <b>Note:</b> Used for only old vector format!
  858. *
  859. * \todo Move to the vector library.
  860. *
  861. * \param name map name
  862. * \param cats pointer to Categories structure
  863. *
  864. * \return void
  865. */
  866. void Rast_write_vector_cats(const char *name, struct Categories *cats)
  867. {
  868. write_cats("dig_cats", name, cats);
  869. }
  870. static void write_cats(const char *element, const char *name,
  871. struct Categories *cats)
  872. {
  873. FILE *fd;
  874. int i, fp_map;
  875. char *descr;
  876. DCELL val1, val2;
  877. char str1[100], str2[100];
  878. fd = G_fopen_new(element, name);
  879. if (!fd)
  880. G_fatal_error(_("Unable to open %s file for map <%s>"), element, name);
  881. /* write # cats - note # indicate 3.0 or later */
  882. fprintf(fd, "# %ld categories\n", (long)cats->num);
  883. /* title */
  884. fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
  885. /* write format and coefficients */
  886. fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
  887. fprintf(fd, "%.2f %.2f %.2f %.2f\n",
  888. cats->m1, cats->a1, cats->m2, cats->a2);
  889. /* if the map is integer or if this is a vector map, sort labels */
  890. if (strncmp(element, "dig", 3) == 0)
  891. fp_map = 0;
  892. else
  893. fp_map = Rast_map_is_fp(name, G_mapset());
  894. if (!fp_map)
  895. Rast_sort_cats(cats);
  896. /* write the cat numbers:label */
  897. for (i = 0; i < Rast_quant_nof_rules(&cats->q); i++) {
  898. descr = Rast_get_ith_d_cat(cats, i, &val1, &val2);
  899. if ((cats->fmt && cats->fmt[0])
  900. || (descr && descr[0])) {
  901. if (val1 == val2) {
  902. sprintf(str1, "%.10f", val1);
  903. G_trim_decimal(str1);
  904. fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
  905. }
  906. else {
  907. sprintf(str1, "%.10f", val1);
  908. G_trim_decimal(str1);
  909. sprintf(str2, "%.10f", val2);
  910. G_trim_decimal(str2);
  911. fprintf(fd, "%s:%s:%s\n", str1, str2,
  912. descr != NULL ? descr : "");
  913. }
  914. }
  915. }
  916. fclose(fd);
  917. }
  918. /*!
  919. * \brief Get category description (DCELL)
  920. *
  921. * Returns i-th description and i-th data range from the list of
  922. * category descriptions with corresponding data ranges. end points of
  923. * data interval in <i>rast1</i> and <i>rast2</i>.
  924. *
  925. * \param pcats pointer to Categories structure
  926. * \param i index
  927. * \param rast1, rast2 raster values (range)
  928. *
  929. * \return "" on error
  930. * \return pointer to category description
  931. */
  932. char *Rast_get_ith_d_cat(const struct Categories *pcats,
  933. int i, DCELL * rast1, DCELL * rast2)
  934. {
  935. int index;
  936. if (i > pcats->ncats) {
  937. Rast_set_d_null_value(rast1, 1);
  938. Rast_set_d_null_value(rast2, 1);
  939. return "";
  940. }
  941. Rast_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
  942. return pcats->labels[index];
  943. }
  944. /*!
  945. * \brief Get category description (FCELL)
  946. *
  947. * Returns i-th description and i-th data range from the list of
  948. * category descriptions with corresponding data ranges. end points of
  949. * data interval in <i>rast1</i> and <i>rast2</i>.
  950. *
  951. * \param pcats pointer to Categories structure
  952. * \param i index
  953. * \param rast1, rast2 raster values (range)
  954. *
  955. * \return "" on error
  956. * \return pointer to category description
  957. */
  958. char *Rast_get_ith_f_cat(const struct Categories *pcats,
  959. int i, void *rast1, void *rast2)
  960. {
  961. RASTER_MAP_TYPE data_type = FCELL_TYPE;
  962. char *tmp;
  963. DCELL val1, val2;
  964. tmp = Rast_get_ith_d_cat(pcats, i, &val1, &val2);
  965. Rast_set_d_value(rast1, val1, data_type);
  966. Rast_set_d_value(rast2, val2, data_type);
  967. return tmp;
  968. }
  969. /*!
  970. * \brief Get category description (CELL)
  971. *
  972. * Returns i-th description and i-th data range from the list of
  973. * category descriptions with corresponding data ranges. end points of
  974. * data interval in <i>rast1</i> and <i>rast2</i>.
  975. *
  976. * \param pcats pointer to Categories structure
  977. * \param i index
  978. * \param rast1, rast2 raster values (range)
  979. *
  980. * \return "" on error
  981. * \return pointer to category description
  982. */
  983. char *Rast_get_ith_c_cat(const struct Categories *pcats,
  984. int i, void *rast1, void *rast2)
  985. {
  986. RASTER_MAP_TYPE data_type = CELL_TYPE;
  987. char *tmp;
  988. DCELL val1, val2;
  989. tmp = Rast_get_ith_d_cat(pcats, i, &val1, &val2);
  990. Rast_set_d_value(rast1, val1, data_type);
  991. Rast_set_d_value(rast2, val2, data_type);
  992. return tmp;
  993. }
  994. /*!
  995. * \brief Get category description
  996. *
  997. * Returns i-th description and i-th data range from the list of
  998. * category descriptions with corresponding data ranges. end points of
  999. * data interval in <i>rast1</i> and <i>rast2</i>.
  1000. *
  1001. * \param pcats pointer to Categories structure
  1002. * \param i index
  1003. * \param rast1, rast2 raster values (range)
  1004. * \param data_type map type
  1005. *
  1006. * \return "" on error
  1007. * \return pointer to category description
  1008. */
  1009. char *Rast_get_ith_cat(const struct Categories *pcats, int i, void *rast1,
  1010. void *rast2, RASTER_MAP_TYPE data_type)
  1011. {
  1012. char *tmp;
  1013. DCELL val1, val2;
  1014. tmp = Rast_get_ith_d_cat(pcats, i, &val1, &val2);
  1015. Rast_set_d_value(rast1, val1, data_type);
  1016. Rast_set_d_value(rast2, val2, data_type);
  1017. return tmp;
  1018. }
  1019. /*!
  1020. * \brief Initialize category structure
  1021. *
  1022. * To construct a new category file, the structure must first be
  1023. * initialized. This routine initializes the <i>cats</i> structure,
  1024. * and copies the <i>title</i> into the structure. The number of
  1025. * categories is set initially to <i>n</i>.
  1026. *
  1027. * For example:
  1028. \code
  1029. struct Categories cats;
  1030. Rast_init_cats ("", &cats);
  1031. \endcode
  1032. *
  1033. * \todo Eliminate pcats->num. Num has no meaning in new Categories
  1034. * structure and only stores (int) largets data value for backwards
  1035. * compatibility.
  1036. *
  1037. * \param title title
  1038. * \param pcats pointer to Categories structure
  1039. */
  1040. void Rast_init_cats(const char *title, struct Categories *pcats)
  1041. {
  1042. Rast_set_cats_title(title, pcats);
  1043. pcats->labels = NULL;
  1044. pcats->nalloc = 0;
  1045. pcats->ncats = 0;
  1046. pcats->num = 0;
  1047. pcats->fmt = NULL;
  1048. pcats->m1 = 0.0;
  1049. pcats->a1 = 0.0;
  1050. pcats->m2 = 0.0;
  1051. pcats->a2 = 0.0;
  1052. pcats->last_marked_rule = -1;
  1053. Rast_quant_init(&pcats->q);
  1054. }
  1055. /*!
  1056. * \brief Set title in category structure
  1057. *
  1058. * \todo To be removed, replaced by Rast_set_cats_title().
  1059. *
  1060. * The <i>title</i> is copied into the <i>pcats</i> structure.
  1061. *
  1062. * \param title title
  1063. * \param pcats pointer to Categories structure
  1064. */
  1065. void Rast_set_cats_title(const char *title, struct Categories *pcats)
  1066. {
  1067. if (title == NULL)
  1068. title = "";
  1069. pcats->title = G_store(title);
  1070. G_newlines_to_spaces(pcats->title);
  1071. G_strip(pcats->title);
  1072. }
  1073. /*!
  1074. \brief Set category fmt (?)
  1075. \param fmt
  1076. \param m1,
  1077. \param a1,m2,a2
  1078. \param pcats pointer to Categories structure
  1079. */
  1080. void Rast_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
  1081. double a2, struct Categories *pcats)
  1082. {
  1083. pcats->m1 = m1;
  1084. pcats->a1 = a1;
  1085. pcats->m2 = m2;
  1086. pcats->a2 = a2;
  1087. pcats->fmt = G_store(fmt);
  1088. G_newlines_to_spaces(pcats->fmt);
  1089. G_strip(pcats->fmt);
  1090. }
  1091. /*!
  1092. * \brief Free category structure memory
  1093. *
  1094. * \todo To be removed, replaced by Rast_free_cats().
  1095. *
  1096. * Frees memory allocated by Rast_read_cats(), Rast_init_cats() and
  1097. * Rast_set_c_cat().
  1098. *
  1099. * \param pcats pointer to Categories structure
  1100. */
  1101. void Rast_free_cats(struct Categories *pcats)
  1102. {
  1103. int i;
  1104. if (pcats->title != NULL) {
  1105. G_free(pcats->title);
  1106. pcats->title = NULL;
  1107. }
  1108. if (pcats->fmt != NULL) {
  1109. G_free(pcats->fmt);
  1110. pcats->fmt = NULL;
  1111. }
  1112. if (pcats->ncats > 0) {
  1113. for (i = 0; i < pcats->ncats; i++)
  1114. if (pcats->labels[i] != NULL)
  1115. G_free(pcats->labels[i]);
  1116. G_free(pcats->labels);
  1117. G_free(pcats->marks);
  1118. pcats->labels = NULL;
  1119. }
  1120. Rast_quant_free(&pcats->q);
  1121. pcats->ncats = 0;
  1122. pcats->nalloc = 0;
  1123. }
  1124. /*!
  1125. * \brief Copy raster categories
  1126. *
  1127. * Allocates NEW space for quant rules and labels n <i>pcats_to</i>
  1128. * and copies all info from <i>pcats_from</i> cats to
  1129. * <i>pcats_to</i> cats.
  1130. *
  1131. * \param pcats_to pointer to destination Categories structure
  1132. * \param pcats_from pointer to source Categories structure
  1133. */
  1134. void Rast_copy_cats(struct Categories *pcats_to,
  1135. const struct Categories *pcats_from)
  1136. {
  1137. int i;
  1138. char *descr;
  1139. DCELL d1, d2;
  1140. Rast_init_cats(pcats_from->title, pcats_to);
  1141. for (i = 0; i < pcats_from->ncats; i++) {
  1142. descr = Rast_get_ith_d_cat(pcats_from, i, &d1, &d2);
  1143. Rast_set_d_cat(&d1, &d2, descr, pcats_to);
  1144. }
  1145. }
  1146. /*!
  1147. \brief Get number of raster categories
  1148. \param pcats pointer to Categories structure
  1149. \return number of categories
  1150. */
  1151. int Rast_number_of_cats(struct Categories *pcats)
  1152. {
  1153. return pcats->ncats;
  1154. }
  1155. /*!
  1156. \brief Sort categories
  1157. \param pcats pointer to Categories structure
  1158. \return -1 on error (nothing to sort)
  1159. \return 0 on success
  1160. */
  1161. int Rast_sort_cats(struct Categories *pcats)
  1162. {
  1163. int *indexes, i, ncats;
  1164. char *descr;
  1165. DCELL d1, d2;
  1166. if (pcats->ncats <= 1)
  1167. return -1;
  1168. ncats = pcats->ncats;
  1169. G_debug(3, "Rast_sort_cats(): Copying to save cats buffer");
  1170. Rast_copy_cats(&save_cats, pcats);
  1171. Rast_free_cats(pcats);
  1172. indexes = (int *)G_malloc(sizeof(int) * ncats);
  1173. for (i = 0; i < ncats; i++)
  1174. indexes[i] = i;
  1175. qsort(indexes, ncats, sizeof(int), cmp);
  1176. Rast_init_cats(save_cats.title, pcats);
  1177. for (i = 0; i < ncats; i++) {
  1178. descr = Rast_get_ith_d_cat(&save_cats, indexes[i], &d1, &d2);
  1179. G_debug(4, " Write sorted cats, pcats = %p pcats->labels = %p",
  1180. pcats, pcats->labels);
  1181. Rast_set_d_cat(&d1, &d2, descr, pcats);
  1182. }
  1183. Rast_free_cats(&save_cats);
  1184. return 0;
  1185. }
  1186. static int cmp(const void *aa, const void *bb)
  1187. {
  1188. const int *a = aa, *b = bb;
  1189. DCELL min_rast1, min_rast2, max_rast1, max_rast2;
  1190. CELL index;
  1191. Rast_quant_get_ith_rule(&(save_cats.q), *a,
  1192. &min_rast1, &max_rast1, &index, &index);
  1193. Rast_quant_get_ith_rule(&(save_cats.q), *b,
  1194. &min_rast2, &max_rast2, &index, &index);
  1195. if (min_rast1 < min_rast2)
  1196. return -1;
  1197. if (min_rast1 > min_rast2)
  1198. return 1;
  1199. return 0;
  1200. }