cats.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645
  1. /**********************************************************************
  2. *
  3. * Code in this file works with category files. There are two formats:
  4. * Pre 3.0 direct category encoding form:
  5. *
  6. * 2 categories
  7. * Map Title
  8. * Elevation: 1000.00 to 1005.00 feet
  9. * Elevation: 1005.00 to 1010.00 feet
  10. * Elevation: 1010.00 to 1015.00 feet
  11. *
  12. * 3.0 format
  13. *
  14. * # 2 categories
  15. * Map Title
  16. * Elevation: $1.2 to $2.2 feet ## Format Statement
  17. * 5.0 1000 5.0 1005 ## Coefficients
  18. *
  19. * The coefficient line can be followed by explicit category labels
  20. * which override the format label generation.
  21. * 0:no data
  22. * 2: .
  23. * 5: . ## explicit category labels
  24. * 7: .
  25. * explicit labels can be also of the form:
  26. * 5.5:5:9 label description
  27. * or
  28. * 15:30 label description
  29. *
  30. * In the format line
  31. * $1 refers to the value num*5.0+1000 (ie, using the first 2 coefficients)
  32. * $2 refers to the value num*5.0+1005 (ie, using the last 2 coefficients)
  33. *
  34. * $1.2 will print $1 with 2 decimal places.
  35. *
  36. * Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx
  37. * otherwise. The $yyy$ is optional. Thus
  38. *
  39. * $1 meter$?s
  40. *
  41. * will become: 1 meter (for category 1)
  42. * 2 meters (for category 2), etc.
  43. *
  44. * The format and coefficients above would be used to generate the
  45. * following statement in creation of the format appropriate category
  46. * string for category "num":
  47. *
  48. * sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
  49. *
  50. * Note: while both the format and coefficent lins must be present
  51. * a blank line for the fmt will effectively suppress automatic
  52. * label generation
  53. *
  54. * Note: quant rules of Categories structures are heavily dependent
  55. * on the fact that rules are stored in the same order they are entered.
  56. * since i-th rule and i-th label are entered at the same time, we
  57. * know that i-th rule maps fp range to i, thus we know for sure
  58. * that cats.labels[i] corresponds to i-th quant rule
  59. *
  60. **********************************************************************
  61. *
  62. * G_read_[raster]_cats (name, mapset, pcats)
  63. * const char *name name of cell file
  64. * const char *mapset mapset that cell file belongs to
  65. * struct Categories *pcats structure to hold category info
  66. *
  67. * Reads the category information associated with cell file "name"
  68. * in mapset "mapset" into the structure "pcats".
  69. *
  70. * returns: 0 if successful
  71. * -1 on fail
  72. *
  73. * note: a warning message is printed if the file is
  74. * "missing" or "invalid".
  75. **********************************************************************
  76. *
  77. * G_copy_raster_cats (pcats_to, pcats_from)
  78. * struct Categories *pcats_to
  79. * const struct Categories *pcats_from
  80. *
  81. * Allocates NEW space for quant rules and labels and copies
  82. * all info from "from" cats to "to" cats
  83. *
  84. * returns: 0 if successful
  85. * -1 on fail
  86. *
  87. **********************************************************************
  88. *
  89. * G_read_vector_cats (name, mapset, pcats)
  90. * const char *name name of vector map
  91. * const char *mapset mapset that vector map belongs to
  92. * struct Categories *pcats structure to hold category info
  93. *
  94. *
  95. * returns: 0 if successful
  96. * -1 on fail
  97. *
  98. * note: a warning message is printed if the file is
  99. * "missing" or "invalid".
  100. **********************************************************************
  101. * Returns pointer to a string describing category.
  102. **********************************************************************
  103. *
  104. * G_number_of_cats(name, mapset)
  105. * returns the largest category number in the map.
  106. * -1 on error
  107. * WARING: do not use for fp maps!
  108. **********************************************************************
  109. *
  110. * char *
  111. * G_get_c/f/d_raster_cat (num, pcats)
  112. * [F/D]CELL *val pointer to cell value
  113. * struct Categories *pcats structure to hold category info
  114. *
  115. * Returns pointer to a string describing category.
  116. *
  117. **********************************************************************
  118. *
  119. * char *
  120. * G_get_raster_cat (val, pcats, data_type)
  121. * void *val pointer to cell value
  122. * struct Categories *pcats structure to hold category info
  123. * RASTER_MAP_TYPE data_type type of raster cell
  124. *
  125. * Returns pointer to a string describing category.
  126. *
  127. **********************************************************************
  128. *
  129. * char *
  130. * G_get_ith_c/f/d_raster_cat (pcats, i, rast1, rast2)
  131. * [F/D]CELL *rast1, *rast2 cat range
  132. * struct Categories *pcats structure to hold category info
  133. *
  134. * Returns pointer to a string describing category.
  135. *
  136. **********************************************************************
  137. *
  138. * int
  139. * G_number_of_raster_cats (pcats)
  140. * struct Categories *pcats structure to hold category info
  141. *
  142. * Returns pcats->ncats number of labels
  143. *
  144. **********************************************************************
  145. *
  146. * char *
  147. * G_get_ith_raster_cat (pcats, i, rast1, rast2, data_type)
  148. * void *rast1, *rast2 cat range
  149. * struct Categories *pcats structure to hold category info
  150. * RASTER_MAP_TYPE data_type type of raster cell
  151. *
  152. * Returns pointer to a string describing category.
  153. *
  154. **********************************************************************
  155. *
  156. * char *
  157. * G_get_[raster]_cats_title (pcats)
  158. * struct Categories *pcats structure to hold category info
  159. *
  160. * Returns pointer to a string with title
  161. *
  162. **********************************************************************
  163. *
  164. * G_init_cats (ncats, title, pcats)
  165. * CELL ncats number of categories
  166. * const char *title cell title
  167. * struct Categories *pcats structure to hold category info
  168. *
  169. * Initializes the cats structure for subsequent calls to G_set_cat()
  170. **********************************************************************
  171. *
  172. * G_unmark_raster_cats (pcats)
  173. * struct Categories *pcats structure to hold category info
  174. *
  175. * initialize cats.marks: the statistics of how many values of map
  176. * have each label
  177. *
  178. **********************************************************************
  179. *
  180. * G_rewind_raster_cats (pcats)
  181. * struct Categories *pcats structure to hold category info
  182. *
  183. * after calll to this function G_get_next_marked_raster_cat() returns
  184. * rhe first marked cat label.
  185. *
  186. **********************************************************************
  187. *
  188. * char* G_get_next_marked_raster_cat(pcats, rast1, rast2, stats, data_type)
  189. * struct Categories *pcats structure to hold category info
  190. * void *rast1, *rast2; pointers to raster range
  191. * long *stats;
  192. * RASTER_MAP_TYPE data_type
  193. *
  194. * returns the next marked label.
  195. * NULL if none found
  196. *
  197. **********************************************************************
  198. *
  199. * char* G_get_next_marked_f/d/craster_cat(pcats, rast1, rast2, stats)
  200. * struct Categories *pcats structure to hold category info
  201. * [D/F]CELL *rast1, *rast2; pointers to raster range
  202. * long *stats;
  203. *
  204. * returns the next marked label.
  205. * NULL if none found
  206. *
  207. **********************************************************************
  208. *
  209. * G_mark_raster_cats (rast_row, ncols, pcats, data_type)
  210. * void *raster_row; raster row to update stats
  211. * struct Categories *pcats structure to hold category info
  212. * RASTER_MAP_TYPE data_type;
  213. * Finds the index of label for each raster cell in a row, and
  214. * increases pcats->marks[index]
  215. * Note: if there are no explicit cats: only rules for cats, no
  216. * marking is done.
  217. *
  218. **********************************************************************
  219. *
  220. * G_mark_c/d/f_raster_cats (rast_row, ncols, pcats)
  221. * int ncols;
  222. * [D?F]CELL *raster_row; raster row to update stats
  223. * struct Categories *pcats structure to hold category info
  224. *
  225. * Finds the index of label for each raster cell in a row, and
  226. * increases pcats->marks[index]
  227. *
  228. **********************************************************************
  229. *
  230. * G_init_raster_cats (title, pcats)
  231. * const char *title cell title
  232. * struct Categories *pcats structure to hold category info
  233. *
  234. * Initializes the cats structure for subsequent calls to G_set_cat()
  235. *
  236. **********************************************************************
  237. *
  238. * G_set_[raster]_cats_fmt (fmt, m1, a1, m2, a2, pcats)
  239. * const char *fmt user form of the equation format
  240. * float m1,a1,m2,a2 coefficients
  241. * struct Categories *pcats structure to hold category info
  242. *
  243. * configures the cats structure for the equation. Must be called
  244. * after G_init_cats().
  245. *
  246. **********************************************************************
  247. *
  248. * G_set_[raster]_cats_title (title, pcats)
  249. * const char *title cell file title
  250. * struct Categories *pcats structure holding category info
  251. *
  252. * Store title as cell file in cats structure
  253. * Returns nothing.
  254. *
  255. **********************************************************************
  256. *
  257. * G_set_cat (num, label, pcats)
  258. * CELL num category number
  259. * const char *label category label
  260. * struct Categories *pcats structure to hold category info
  261. *
  262. * Adds the string buff to represent category "num" in category structure
  263. * pcats.
  264. *
  265. * Returns: 0 is cat is null value -1 too many cats, 1 ok.
  266. *
  267. **********************************************************************
  268. *
  269. * G_set_[f/d/c]_raster_cat (&val1, &val2, label, pcats)
  270. * [D/F]CELL *val1, *val2; pointers to raster values
  271. * const char *label category label
  272. * struct Categories *pcats structure to hold category info
  273. *
  274. * Adds the label for range val1 through val2 in category structure
  275. * pcats.
  276. *
  277. * Returns: 0 if cat is null value -1 too many cats, 1 ok.
  278. *
  279. **********************************************************************
  280. *
  281. * G_set_raster_cat (val1, val2, label, pcats, data_type)
  282. * void *val1, *val2; pointers to raster values
  283. * const char *label category label
  284. * struct Categories *pcats structure to hold category info
  285. * RASTER_MAP_TYPE data_type type of raster cell
  286. *
  287. * Adds the label for range val1 through val2 in category structure
  288. * pcats.
  289. *
  290. * Returns: 0 if cat is null value -1 too many cats, 1 ok.
  291. *
  292. **********************************************************************
  293. *
  294. * G_write_[raster]_cats (name, pcats)
  295. * const char *name name of cell file
  296. * struct Categories *pcats structure holding category info
  297. *
  298. * Writes the category information associated with cell file "name"
  299. * into current mapset from the structure "pcats".
  300. *
  301. * returns: 1 if successful
  302. * -1 on fail
  303. **********************************************************************
  304. *
  305. * G_write_vector_cats (name, pcats)
  306. * const char *name name of vector map
  307. * struct Categories *pcats structure holding category info
  308. *
  309. * Writes the category information associated with vector map "name"
  310. * into current mapset from the structure "pcats".
  311. *
  312. * returns: 1 if successful
  313. * -1 on fail
  314. **********************************************************************
  315. *
  316. * G_free_[raster]_cats (pcats)
  317. * struct Categories *pcats structure holding category info
  318. *
  319. * Releases memory allocated for the cats structure
  320. **********************************************************************/
  321. #include <stdlib.h>
  322. #include <string.h>
  323. #include <grass/gis.h>
  324. #include <grass/glocale.h>
  325. static void get_cond(char **, char *, DCELL);
  326. static int get_fmt(char **, char *, int *);
  327. static int cmp(const void *, const void *);
  328. static int write_cats(const char *element, const char *name, struct Categories *cats);
  329. static CELL read_cats(const char *element,
  330. const char *name,
  331. const char *mapset, struct Categories * pcats, int full);
  332. /*!
  333. * \brief read raster category file
  334. *
  335. * The category file for raster map
  336. * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
  337. * there is an error reading the category file, a diagnostic message is printed
  338. * and -1 is returned. Otherwise, 0 is returned.
  339. *
  340. * \param name
  341. * \param mapset
  342. * \param cats
  343. * \return int
  344. */
  345. int G_read_cats(const char *name,
  346. const char *mapset, struct Categories *pcats)
  347. {
  348. return G_read_raster_cats(name, mapset, pcats);
  349. }
  350. /*!
  351. * \brief
  352. *
  353. * Is the same as existing G_read_cats()
  354. *
  355. * \param name
  356. * \param mapset
  357. * \param pcats
  358. * \return int
  359. */
  360. int G_read_raster_cats(const char *name,
  361. const char *mapset, struct Categories *pcats)
  362. {
  363. char *type;
  364. switch (read_cats("cats", name, mapset, pcats, 1)) {
  365. case -2:
  366. type = "missing";
  367. break;
  368. case -1:
  369. type = "invalid";
  370. break;
  371. default:
  372. return 0;
  373. }
  374. G_warning(_("category support for [%s] in mapset [%s] %s"),
  375. name, mapset, type);
  376. return -1;
  377. }
  378. /*!
  379. * \brief read vector category file
  380. *
  381. * The category file for vector map
  382. * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
  383. * there is an error reading the category file, a diagnostic message is printed
  384. * and -1 is returned. Otherwise, 0 is returned.
  385. *
  386. * \param name
  387. * \param mapset
  388. * \param cats
  389. * \return int
  390. */
  391. int G_read_vector_cats(const char *name,
  392. const char *mapset, struct Categories *pcats)
  393. {
  394. char *type;
  395. switch (read_cats("dig_cats", name, mapset, pcats, 1)) {
  396. case -2:
  397. type = "missing";
  398. break;
  399. case -1:
  400. type = "invalid";
  401. break;
  402. default:
  403. return 0;
  404. }
  405. G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
  406. name, mapset, type);
  407. return -1;
  408. }
  409. CELL G_number_of_cats(const char *name, const char *mapset)
  410. {
  411. struct Range range;
  412. CELL min, max;
  413. /* return the max category number */
  414. if (G_read_range(name, mapset, &range) < 0)
  415. return -1;
  416. G_get_range_min_max(&range, &min, &max);
  417. if (G_is_c_null_value(&max))
  418. max = 0;
  419. return max;
  420. }
  421. static CELL read_cats(const char *element,
  422. const char *name,
  423. const char *mapset, struct Categories * pcats, int full)
  424. {
  425. FILE *fd;
  426. char buff[1024];
  427. CELL cat;
  428. DCELL val1, val2;
  429. int old = 0, fp_map;
  430. long num = -1;
  431. if (strncmp(element, "dig", 3) == 0)
  432. fp_map = 0;
  433. else
  434. fp_map = G_raster_map_is_fp(name, mapset);
  435. if (!(fd = G_fopen_old(element, name, mapset)))
  436. return -2;
  437. /* Read the number of categories */
  438. if (G_getl(buff, sizeof buff, fd) == 0)
  439. goto error;
  440. if (sscanf(buff, "# %ld", &num) == 1)
  441. old = 0;
  442. else if (sscanf(buff, "%ld", &num) == 1)
  443. old = 1;
  444. if (!full) {
  445. fclose(fd);
  446. if (num < 0)
  447. return 0; /* coorect */
  448. return (CELL) num;
  449. }
  450. /* Read the title for the file */
  451. if (G_getl(buff, sizeof buff, fd) == 0)
  452. goto error;
  453. G_strip(buff);
  454. /* G_ascii_check(buff) ; */
  455. G_init_raster_cats(buff, pcats);
  456. if (num >= 0)
  457. pcats->num = num;
  458. if (!old) {
  459. char fmt[256];
  460. float m1, a1, m2, a2;
  461. if (G_getl(fmt, sizeof fmt, fd) == 0)
  462. goto error;
  463. /* next line contains equation coefficients */
  464. if (G_getl(buff, sizeof buff, fd) == 0)
  465. goto error;
  466. if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
  467. goto error;
  468. G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
  469. }
  470. /* Read all category names */
  471. for (cat = 0;; cat++) {
  472. char label[1024];
  473. if (G_getl(buff, sizeof buff, fd) == 0)
  474. break;
  475. if (old)
  476. G_set_cat(cat, buff, pcats);
  477. else {
  478. *label = 0;
  479. if (sscanf(buff, "%1s", label) != 1)
  480. continue;
  481. if (*label == '#')
  482. continue;
  483. *label = 0;
  484. /* for fp maps try to read a range of data */
  485. if (fp_map
  486. && sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
  487. G_set_raster_cat(&val1, &val2, label, pcats, DCELL_TYPE);
  488. else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
  489. G_set_raster_cat(&cat, &cat, label, pcats, CELL_TYPE);
  490. else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
  491. G_set_raster_cat(&val1, &val1, label, pcats, DCELL_TYPE);
  492. else
  493. goto error;
  494. }
  495. }
  496. fclose(fd);
  497. return 0;
  498. error:
  499. fclose(fd);
  500. return -1;
  501. }
  502. /*!
  503. * \brief get title from category structure struct
  504. *
  505. * Map layers store a one-line title in the category structure
  506. * as well. This routine returns a pointer to the title contained in the
  507. * <b>cats</b> structure. A legal pointer is always returned. If the map
  508. * layer does not have a title, then a pointer to the empty string "" is
  509. * returned.
  510. *
  511. * \param cats
  512. * \return char *
  513. */
  514. char *G_get_cats_title(const struct Categories *pcats)
  515. {
  516. return G_get_raster_cats_title(pcats);
  517. }
  518. /*!
  519. * \brief get raster cats title
  520. *
  521. * Returns pointer to a string with title.
  522. *
  523. * \param pcats
  524. * \return char *
  525. */
  526. char *G_get_raster_cats_title(const struct Categories *pcats)
  527. {
  528. return pcats->title ? pcats->title : "";
  529. }
  530. /*!
  531. * \brief get a category label
  532. *
  533. * This routine looks up category <b>n</b> in the <b>cats</b>
  534. * structure and returns a pointer to a string which is the label for the
  535. * category. A legal pointer is always returned. If the category does not exist
  536. * in <b>cats,</b> then a pointer to the empty string "" is returned.
  537. * <b>Warning.</b> The pointer that is returned points to a hidden static
  538. * buffer. Successive calls to G_get_cat( ) overwrite this buffer.
  539. *
  540. * \param n
  541. * \param cats
  542. * \return char *
  543. */
  544. char *G_get_cat(CELL num, struct Categories *pcats)
  545. {
  546. return G_get_c_raster_cat(&num, pcats);
  547. }
  548. /*!
  549. * \brief
  550. *
  551. * given a CELL value <em>val</em> Returns pointer to a string describing
  552. * category.
  553. *
  554. * \param val
  555. * \param pcats
  556. * \return char *
  557. */
  558. char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
  559. {
  560. return G_get_raster_cat(rast, pcats, CELL_TYPE);
  561. }
  562. /*!
  563. * \brief
  564. *
  565. * given a FCELL value <em>val</em> Returns pointer to a string
  566. * describing category.
  567. *
  568. * \param val
  569. * \param pcats
  570. * \return char *
  571. */
  572. char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
  573. {
  574. return G_get_raster_cat(rast, pcats, FCELL_TYPE);
  575. }
  576. /*!
  577. * \brief
  578. *
  579. * given a DCELL value <em>val</em> Returns pointer to a string
  580. * describing category.
  581. *
  582. * \param val
  583. * \param pcats
  584. * \return char *
  585. */
  586. char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
  587. {
  588. return G_get_raster_cat(rast, pcats, DCELL_TYPE);
  589. }
  590. /*!
  591. * \brief
  592. *
  593. * given a raster value <em>val</em> of type <em>data_type</em> Returns pointer to a string
  594. * describing category.
  595. *
  596. * \param val
  597. * \param pcats
  598. * \param data_type
  599. * \return char *
  600. */
  601. char *G_get_raster_cat(void *rast,
  602. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  603. {
  604. static char label[1024];
  605. char *f, *l, *v;
  606. CELL i;
  607. DCELL val;
  608. float a[2];
  609. char fmt[30], value_str[30];
  610. if (G_is_null_value(rast, data_type)) {
  611. sprintf(label, "no data");
  612. return label;
  613. }
  614. /* first search the list of labels */
  615. *label = 0;
  616. val = G_get_raster_value_d(rast, data_type);
  617. i = G_quant_get_cell_value(&pcats->q, val);
  618. /* DEBUG fprintf (stderr, "val %lf found i %d\n", val, i); */
  619. if (!G_is_c_null_value(&i) && i < pcats->ncats) {
  620. if (pcats->labels[i] != NULL)
  621. return pcats->labels[i];
  622. return label;
  623. }
  624. /* generate the label */
  625. if ((f = pcats->fmt) == NULL)
  626. return label;
  627. a[0] = (float)val *pcats->m1 + pcats->a1;
  628. a[1] = (float)val *pcats->m2 + pcats->a2;
  629. l = label;
  630. while (*f) {
  631. if (*f == '$') {
  632. f++;
  633. if (*f == '$')
  634. *l++ = *f++;
  635. else if (*f == '?') {
  636. f++;
  637. get_cond(&f, v = value_str, val);
  638. while (*v)
  639. *l++ = *v++;
  640. }
  641. else if (get_fmt(&f, fmt, &i)) {
  642. sprintf(v = value_str, fmt, a[i]);
  643. while (*v)
  644. *l++ = *v++;
  645. }
  646. else
  647. *l++ = '$';
  648. }
  649. else {
  650. *l++ = *f++;
  651. }
  652. }
  653. *l = 0;
  654. return label;
  655. }
  656. /*!
  657. * \brief
  658. *
  659. * Sets marks
  660. * for all categories to 0. This initializes Categories structure for subsequest
  661. * calls to G_mark_raster_cats (rast_row,...) for each row of data, where
  662. * non-zero mark for i-th label means that some of the cells in rast_row are
  663. * labeled with i-th label and fall into i-th data range.
  664. * These marks help determine from the Categories structure which labels were
  665. * used and which weren't.
  666. *
  667. * \param pcats
  668. * \return
  669. */
  670. void G_unmark_raster_cats(struct Categories *pcats)
  671. { /* structure to hold category info */
  672. int i;
  673. for (i = 0; i < pcats->ncats; i++)
  674. pcats->marks[i] = 0;
  675. }
  676. /*!
  677. * \brief
  678. *
  679. * Looks up the category label for each raster value in
  680. * the <em>rast_row</em> and updates the marks for labels found.
  681. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  682. * so far which are labeled with i-th label and fall into i-th data range.
  683. *
  684. * \param rast_row
  685. * \param ncols
  686. * \param pcats
  687. * \return
  688. */
  689. void G_mark_c_raster_cats(const CELL * rast_row, /* raster row to update stats */
  690. int ncols, struct Categories *pcats)
  691. { /* structure to hold category info */
  692. G_mark_raster_cats(rast_row, ncols, pcats, CELL_TYPE);
  693. }
  694. /*!
  695. * \brief
  696. *
  697. * Looks up the category label for each raster value in
  698. * the <em>rast_row</em> and updates the marks for labels found.
  699. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  700. * so far which are labeled with i-th label and fall into i-th data range.
  701. *
  702. * \param rast_row
  703. * \param ncols
  704. * \param pcats
  705. * \return
  706. */
  707. void G_mark_f_raster_cats(const FCELL * rast_row, /* raster row to update stats */
  708. int ncols, struct Categories *pcats)
  709. { /* structure to hold category info */
  710. G_mark_raster_cats(rast_row, ncols, pcats, FCELL_TYPE);
  711. }
  712. /*!
  713. * \brief
  714. *
  715. * Looks up the category label for each raster value in
  716. * the <em>rast_row</em> and updates the marks for labels found.
  717. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  718. * so far which are labeled with i-th label and fall into i-th data range.
  719. *
  720. * \param rast_row
  721. * \param ncols
  722. * \param pcats
  723. * \return
  724. */
  725. void G_mark_d_raster_cats(const DCELL * rast_row, /* raster row to update stats */
  726. int ncols, struct Categories *pcats)
  727. { /* structure to hold category info */
  728. G_mark_raster_cats(rast_row, ncols, pcats, DCELL_TYPE);
  729. }
  730. /*!
  731. * \brief
  732. *
  733. * Looks up the category
  734. * label for each raster value in the <em>rast_row</em> (row of raster cell value)
  735. * and updates the marks for labels found.
  736. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  737. * so far which are labeled with i-th label and fall into i-th data range.
  738. *
  739. * \param rast_row
  740. * \param ncols
  741. * \param pcats
  742. * \param data_type
  743. * \return int
  744. */
  745. int G_mark_raster_cats(const void *rast_row, /* raster row to update stats */
  746. int ncols, struct Categories *pcats, /* structure to hold category info */
  747. RASTER_MAP_TYPE data_type)
  748. {
  749. CELL i;
  750. while (ncols-- > 0) {
  751. i = G_quant_get_cell_value(&pcats->q,
  752. G_get_raster_value_d(rast_row, data_type));
  753. if (G_is_c_null_value(&i))
  754. continue;
  755. if (i > pcats->ncats)
  756. return -1;
  757. pcats->marks[i]++;
  758. rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
  759. }
  760. return 1;
  761. }
  762. /*!
  763. * \brief
  764. *
  765. * after call to
  766. * this function G_get_next_marked_raster_cat() returns the first marked
  767. * cat label.
  768. *
  769. * \param pcats
  770. * \return
  771. */
  772. void G_rewind_raster_cats(struct Categories *pcats)
  773. {
  774. pcats->last_marked_rule = -1;
  775. }
  776. char *G_get_next_marked_d_raster_cat(struct Categories *pcats, /* structure to hold category info */
  777. DCELL * rast1, DCELL * rast2, /* pointers to raster range */
  778. long *count)
  779. {
  780. char *descr = NULL;
  781. int found, i;
  782. found = 0;
  783. /* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
  784. /* DEBUG
  785. fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
  786. */
  787. for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
  788. i++) {
  789. descr = G_get_ith_d_raster_cat(pcats, i, rast1, rast2);
  790. /* DEBUG fprintf (stderr, "%d %d\n", i, pcats->marks[i]); */
  791. if (pcats->marks[i]) {
  792. found = 1;
  793. break;
  794. }
  795. }
  796. if (!found)
  797. return NULL;
  798. *count = pcats->marks[i];
  799. pcats->last_marked_rule = i;
  800. return descr;
  801. }
  802. char *G_get_next_marked_c_raster_cat(struct Categories *pcats, /* structure to hold category info */
  803. CELL * rast1, CELL * rast2, /* pointers to raster range */
  804. long *count)
  805. {
  806. return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
  807. CELL_TYPE);
  808. }
  809. char *G_get_next_marked_f_raster_cat(struct Categories *pcats, /* structure to hold category info */
  810. FCELL * rast1, FCELL * rast2, /* pointers to raster range */
  811. long *count)
  812. {
  813. return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
  814. FCELL_TYPE);
  815. }
  816. char *G_get_next_marked_raster_cat(struct Categories *pcats, /* structure to hold category info */
  817. void *rast1, void *rast2, /* pointers to raster range */
  818. long *count, RASTER_MAP_TYPE data_type)
  819. {
  820. DCELL val1, val2;
  821. char *lab;
  822. lab = G_get_next_marked_d_raster_cat(pcats, &val1, &val2, count);
  823. G_set_raster_value_d(rast1, val1, data_type);
  824. G_set_raster_value_d(rast2, val2, data_type);
  825. return lab;
  826. }
  827. static int get_fmt(char **f, char *fmt, int *i)
  828. {
  829. char *ff;
  830. ff = *f;
  831. if (*ff == 0)
  832. return 0;
  833. if (*ff == '$') {
  834. *f = ff + 1;
  835. return 0;
  836. }
  837. switch (*ff++) {
  838. case '1':
  839. *i = 0;
  840. break;
  841. case '2':
  842. *i = 1;
  843. break;
  844. default:
  845. return 0;
  846. }
  847. *fmt++ = '%';
  848. *fmt++ = '.';
  849. if (*ff++ != '.') {
  850. *f = ff - 1;
  851. *fmt++ = '0';
  852. *fmt++ = 'f';
  853. *fmt = 0;
  854. return 1;
  855. }
  856. *fmt = '0';
  857. while (*ff >= '0' && *ff <= '9')
  858. *fmt++ = *ff++;
  859. *fmt++ = 'f';
  860. *fmt = 0;
  861. *f = ff;
  862. return 1;
  863. }
  864. static void get_cond(char **f, char *value, DCELL val)
  865. {
  866. char *ff;
  867. ff = *f;
  868. if (val == 1.) {
  869. while (*ff)
  870. if (*ff++ == '$')
  871. break;
  872. }
  873. while (*ff)
  874. if (*ff == '$') {
  875. ff++;
  876. break;
  877. }
  878. else
  879. *value++ = *ff++;
  880. if (val != 1.) {
  881. while (*ff)
  882. if (*ff++ == '$')
  883. break;
  884. }
  885. *value = 0;
  886. *f = ff;
  887. }
  888. /*!
  889. * \brief set a category label
  890. *
  891. * The <b>label</b> is copied into the <b>cats</b> structure
  892. * for category <b>n.</b>
  893. *
  894. * \param n
  895. * \param label
  896. * \param cats
  897. * \return int
  898. */
  899. int G_set_cat(CELL num, const char *label, struct Categories *pcats)
  900. {
  901. return G_set_c_raster_cat(&num, &num, label, pcats);
  902. }
  903. /*!
  904. * \brief
  905. *
  906. * Adds the label for range <em>rast1</em> through <em>rast2</em> in
  907. * category structure <em>pcats</em>.
  908. *
  909. * \param rast1
  910. * \param rast2
  911. * \param pcats
  912. * \return int
  913. */
  914. int G_set_c_raster_cat(const CELL * rast1, const CELL * rast2,
  915. const char *label, struct Categories *pcats)
  916. {
  917. return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
  918. }
  919. /*!
  920. * \brief
  921. *
  922. * Adds the label for range <em>rast1</em> through <em>rast2</em>
  923. * in category structure <em>pcats</em>.
  924. *
  925. * \param rast1
  926. * \param rast2
  927. * \param pcats
  928. * \return int
  929. */
  930. int G_set_f_raster_cat(const FCELL * rast1, const FCELL * rast2,
  931. const char *label, struct Categories *pcats)
  932. {
  933. return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
  934. }
  935. /*!
  936. * \brief
  937. *
  938. * Adds the label for range <em>rast1</em> through <em>rast2</em>
  939. * in category structure <em>pcats</em>.
  940. *
  941. * \param rast1
  942. * \param rast2
  943. * \param pcats
  944. * \return int
  945. */
  946. int G_set_d_raster_cat(const DCELL * rast1, const DCELL * rast2,
  947. const char *label, struct Categories *pcats)
  948. {
  949. long len;
  950. DCELL dtmp1, dtmp2;
  951. int i;
  952. char *descr;
  953. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
  954. rast1,rast2,label,pcats); */
  955. if (G_is_d_null_value(rast1))
  956. return 0;
  957. if (G_is_d_null_value(rast2))
  958. return 0;
  959. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
  960. /* the set_cat() functions are used in many places to reset the labels
  961. for the range (or cat) with existing label. In this case we don't
  962. want to store both rules with identical range even though the result
  963. of get_cat() will be correct, since it will use rule added later.
  964. we don't want to overuse memory and we don't want rules which are
  965. not used to be writen out in cats file. So we first look if
  966. the label for this range has been sen, and if it has, overwrite it */
  967. for (i = 0; i < pcats->ncats; i++) {
  968. descr = G_get_ith_d_raster_cat(pcats, i, &dtmp1, &dtmp2);
  969. if ((dtmp1 == *rast1 && dtmp2 == *rast2)
  970. || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
  971. if (pcats->labels[i] != NULL)
  972. G_free(pcats->labels[i]);
  973. pcats->labels[i] = G_store(label);
  974. G_newlines_to_spaces(pcats->labels[i]);
  975. G_strip(pcats->labels[i]);
  976. return 1;
  977. }
  978. }
  979. /* when rule for this range does not exist */
  980. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): New rule: adding %d %p\n", i, pcats->labels); */
  981. G_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats, pcats->ncats);
  982. pcats->ncats++;
  983. if (pcats->nalloc < pcats->ncats) {
  984. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
  985. len = (pcats->nalloc + 256) * sizeof(char *);
  986. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
  987. if (len != (int)len) { /* make sure len doesn't overflow int */
  988. pcats->ncats--;
  989. return -1;
  990. }
  991. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
  992. if (pcats->nalloc) {
  993. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
  994. pcats->labels =
  995. (char **)G_realloc((char *)pcats->labels, (int)len);
  996. }
  997. else {
  998. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
  999. pcats->labels = (char **)G_malloc((int)len);
  1000. }
  1001. /* fflush(stderr); */
  1002. /* DEBUG fprintf (stderr, "G_set_d_raster_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
  1003. len = (pcats->nalloc + 256) * sizeof(int);
  1004. if (len != (int)len) { /* make sure len doesn't overflow int */
  1005. pcats->ncats--;
  1006. return -1;
  1007. }
  1008. if (pcats->nalloc)
  1009. pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
  1010. else
  1011. pcats->marks = (int *)G_malloc((int)len);
  1012. pcats->nalloc += 256;
  1013. }
  1014. /* DEBUG fprintf(stderr,"G_set_d_raster_cats(): store new label\n"); */
  1015. pcats->labels[pcats->ncats - 1] = G_store(label);
  1016. G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
  1017. G_strip(pcats->labels[pcats->ncats - 1]);
  1018. /* DEBUG
  1019. fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
  1020. */
  1021. /* updates cats.num = max cat values. This is really just used in old
  1022. raster programs, and I am doing it for backwards cmpatibility (Olga) */
  1023. if ((CELL) * rast1 > pcats->num)
  1024. pcats->num = (CELL) * rast1;
  1025. if ((CELL) * rast2 > pcats->num)
  1026. pcats->num = (CELL) * rast2;
  1027. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): done\n"); */
  1028. /* DEBUG fflush(stderr); */
  1029. return 1;
  1030. }
  1031. /*!
  1032. * \brief
  1033. *
  1034. * Adds the label for range <em>rast1</em> through <em>rast2</em> in category structure <em>pcats</em>.
  1035. *
  1036. * \param rast1
  1037. * \param rast2
  1038. * \param pcats
  1039. * \param data_type
  1040. * \return int
  1041. */
  1042. int G_set_raster_cat(const void *rast1, const void *rast2,
  1043. const char *label,
  1044. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  1045. {
  1046. DCELL val1, val2;
  1047. val1 = G_get_raster_value_d(rast1, data_type);
  1048. val2 = G_get_raster_value_d(rast2, data_type);
  1049. return G_set_d_raster_cat(&val1, &val2, label, pcats);
  1050. }
  1051. /*!
  1052. * \brief write raster category file
  1053. *
  1054. * Writes the category file for the raster map <b>name</b> in
  1055. * the current mapset from the <b>cats</b> structure.
  1056. * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
  1057. * printed).
  1058. *
  1059. * \param name
  1060. * \param cats
  1061. * \return int
  1062. */
  1063. int G_write_cats(const char *name, struct Categories *cats)
  1064. {
  1065. return write_cats("cats", name, cats);
  1066. }
  1067. /*!
  1068. * \brief
  1069. *
  1070. * Same as existing G_write_cats()
  1071. *
  1072. * \param name
  1073. * \param pcats
  1074. * \return int
  1075. */
  1076. int G_write_raster_cats(const char *name, struct Categories *cats)
  1077. {
  1078. return write_cats("cats", name, cats);
  1079. }
  1080. /*!
  1081. * \brief write
  1082. * vector category file
  1083. *
  1084. * Writes the category file for the vector map
  1085. * <b>name</b> in the current mapset from the <b>cats</b> structure.
  1086. * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
  1087. * printed).
  1088. *
  1089. * \param name
  1090. * \param cats
  1091. * \return int
  1092. */
  1093. int G_write_vector_cats(const char *name, struct Categories *cats)
  1094. {
  1095. return write_cats("dig_cats", name, cats);
  1096. }
  1097. static int write_cats(const char *element, const char *name, struct Categories *cats)
  1098. {
  1099. FILE *fd;
  1100. int i, fp_map;
  1101. char *descr;
  1102. DCELL val1, val2;
  1103. char str1[100], str2[100];
  1104. if (!(fd = G_fopen_new(element, name)))
  1105. return -1;
  1106. /* write # cats - note # indicate 3.0 or later */
  1107. fprintf(fd, "# %ld categories\n", (long)cats->num);
  1108. /* title */
  1109. fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
  1110. /* write format and coefficients */
  1111. fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
  1112. fprintf(fd, "%.2f %.2f %.2f %.2f\n",
  1113. cats->m1, cats->a1, cats->m2, cats->a2);
  1114. /* if the map is integer or if this is a vector map, sort labels */
  1115. if (strncmp(element, "dig", 3) == 0)
  1116. fp_map = 0;
  1117. else
  1118. fp_map = G_raster_map_is_fp(name, G_mapset());
  1119. if (!fp_map)
  1120. G_sort_cats(cats);
  1121. /* write the cat numbers:label */
  1122. for (i = 0; i < G_quant_nof_rules(&cats->q); i++) {
  1123. descr = G_get_ith_d_raster_cat(cats, i, &val1, &val2);
  1124. if ((cats->fmt && cats->fmt[0])
  1125. || (descr && descr[0])) {
  1126. if (val1 == val2) {
  1127. sprintf(str1, "%.10f", val1);
  1128. G_trim_decimal(str1);
  1129. fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
  1130. }
  1131. else {
  1132. sprintf(str1, "%.10f", val1);
  1133. G_trim_decimal(str1);
  1134. sprintf(str2, "%.10f", val2);
  1135. G_trim_decimal(str2);
  1136. fprintf(fd, "%s:%s:%s\n", str1, str2,
  1137. descr != NULL ? descr : "");
  1138. }
  1139. }
  1140. }
  1141. fclose(fd);
  1142. return (1);
  1143. }
  1144. /*!
  1145. * \brief
  1146. *
  1147. * Returns i-th description and i-th data range
  1148. * from the list of category descriptions with corresponding data ranges. end
  1149. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1150. *
  1151. * \param pcats
  1152. * \param i
  1153. * \param rast1
  1154. * \param rast2
  1155. * \return char *
  1156. */
  1157. char *G_get_ith_d_raster_cat(const struct Categories *pcats,
  1158. int i, DCELL * rast1, DCELL * rast2)
  1159. {
  1160. int index;
  1161. if (i > pcats->ncats) {
  1162. G_set_d_null_value(rast1, 1);
  1163. G_set_d_null_value(rast2, 1);
  1164. return "";
  1165. }
  1166. G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
  1167. return pcats->labels[index];
  1168. }
  1169. /*!
  1170. * \brief
  1171. *
  1172. * Returns i-th description and i-th data range
  1173. * from the list of category descriptions with corresponding data ranges. end
  1174. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1175. *
  1176. * \param pcats
  1177. * \param i
  1178. * \param rast1
  1179. * \param rast2
  1180. * \return char *
  1181. */
  1182. char *G_get_ith_f_raster_cat(const struct Categories *pcats,
  1183. int i, void *rast1, void *rast2)
  1184. {
  1185. RASTER_MAP_TYPE data_type = FCELL_TYPE;
  1186. char *tmp;
  1187. DCELL val1, val2;
  1188. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1189. G_set_raster_value_d(rast1, val1, data_type);
  1190. G_set_raster_value_d(rast2, val2, data_type);
  1191. return tmp;
  1192. }
  1193. /*!
  1194. * \brief
  1195. *
  1196. * Returns i-th description and i-th data range
  1197. * from the list of category descriptions with corresponding data ranges. end
  1198. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1199. *
  1200. * \param pcats
  1201. * \param i
  1202. * \param rast1
  1203. * \param rast2
  1204. * \return char *
  1205. */
  1206. char *G_get_ith_c_raster_cat(const struct Categories *pcats,
  1207. int i, void *rast1, void *rast2)
  1208. {
  1209. RASTER_MAP_TYPE data_type = CELL_TYPE;
  1210. char *tmp;
  1211. DCELL val1, val2;
  1212. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1213. G_set_raster_value_d(rast1, val1, data_type);
  1214. G_set_raster_value_d(rast2, val2, data_type);
  1215. return tmp;
  1216. }
  1217. /*!
  1218. * \brief
  1219. *
  1220. * Returns i-th
  1221. * description and i-th data range from the list of category descriptions with
  1222. * corresponding data ranges. Stores end points of data interval in <em>rast1</em>
  1223. * and <em>rast2</em> (after converting them to <em>data_type</em>.
  1224. *
  1225. * \param pcats
  1226. * \param i
  1227. * \param rast1
  1228. * \param rast2
  1229. * \param data_type
  1230. * \return char *
  1231. */
  1232. char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
  1233. void *rast2, RASTER_MAP_TYPE data_type)
  1234. {
  1235. char *tmp;
  1236. DCELL val1, val2;
  1237. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1238. G_set_raster_value_d(rast1, val1, data_type);
  1239. G_set_raster_value_d(rast2, val2, data_type);
  1240. return tmp;
  1241. }
  1242. /*!
  1243. * \brief initialize category structure
  1244. *
  1245. * To construct a new category file, the
  1246. * structure must first be initialized. This routine initializes the
  1247. * <b>cats</b> structure, and copies the <b>title</b> into the structure.
  1248. * The number of categories is set initially to <b>n.</b>
  1249. * For example:
  1250. \code
  1251. struct Categories cats;
  1252. G_init_cats ( (CELL)0, "", &cats);
  1253. \endcode
  1254. *
  1255. * \param n
  1256. * \param title
  1257. * \param cats
  1258. */
  1259. void G_init_cats(CELL num, const char *title, struct Categories *pcats)
  1260. {
  1261. G_init_raster_cats(title, pcats);
  1262. pcats->num = num;
  1263. }
  1264. /*!
  1265. * \brief
  1266. *
  1267. * Same as existing G_init_raster_cats() only ncats argument is
  1268. * missign. ncats has no meaning in new Categories structure and only stores
  1269. * (int) largets data value for backwards compatibility.
  1270. *
  1271. * \param title
  1272. * \param pcats
  1273. * \return
  1274. */
  1275. void G_init_raster_cats(const char *title, struct Categories *pcats)
  1276. {
  1277. G_set_raster_cats_title(title, pcats);
  1278. pcats->labels = NULL;
  1279. pcats->nalloc = 0;
  1280. pcats->ncats = 0;
  1281. pcats->num = 0;
  1282. pcats->fmt = NULL;
  1283. pcats->m1 = 0.0;
  1284. pcats->a1 = 0.0;
  1285. pcats->m2 = 0.0;
  1286. pcats->a2 = 0.0;
  1287. pcats->last_marked_rule = -1;
  1288. G_quant_init(&pcats->q);
  1289. }
  1290. /*!
  1291. * \brief set title in category structure
  1292. *
  1293. * The <b>title</b> is copied into the
  1294. * <b>cats</b> structure.
  1295. *
  1296. * \param title
  1297. * \param cats
  1298. * \return
  1299. */
  1300. void G_set_cats_title(const char *title, struct Categories *pcats)
  1301. {
  1302. G_set_raster_cats_title(title, pcats);
  1303. }
  1304. /*!
  1305. * \brief
  1306. *
  1307. * Same as existing G_set_cats_title()
  1308. *
  1309. * \param title
  1310. * \param pcats
  1311. * \return
  1312. */
  1313. void G_set_raster_cats_title(const char *title, struct Categories *pcats)
  1314. {
  1315. if (title == NULL)
  1316. title = "";
  1317. pcats->title = G_store(title);
  1318. G_newlines_to_spaces(pcats->title);
  1319. G_strip(pcats->title);
  1320. }
  1321. void G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
  1322. double a2, struct Categories *pcats)
  1323. {
  1324. G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
  1325. }
  1326. /*!
  1327. * \brief
  1328. *
  1329. * Same as existing G_set_cats_fmt()
  1330. *
  1331. * \param fmt
  1332. * \param m1
  1333. * \param a1
  1334. * \param m2
  1335. * \param a2
  1336. * \param pcats
  1337. */
  1338. void G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
  1339. double a2, struct Categories *pcats)
  1340. {
  1341. pcats->m1 = m1;
  1342. pcats->a1 = a1;
  1343. pcats->m2 = m2;
  1344. pcats->a2 = a2;
  1345. pcats->fmt = G_store(fmt);
  1346. G_newlines_to_spaces(pcats->fmt);
  1347. G_strip(pcats->fmt);
  1348. }
  1349. /*!
  1350. * \brief free category structure memory
  1351. *
  1352. * Frees memory allocated by<i>G_read_cats, G_init_cats</i>
  1353. * and<i>G_set_cat.</i>
  1354. *
  1355. * \param cats
  1356. * \return
  1357. */
  1358. void G_free_cats(struct Categories *pcats)
  1359. {
  1360. G_free_raster_cats(pcats);
  1361. }
  1362. /*!
  1363. * \brief
  1364. *
  1365. * Same as existing G_free_cats()
  1366. *
  1367. * \param pcats
  1368. * \return
  1369. */
  1370. void G_free_raster_cats(struct Categories *pcats)
  1371. {
  1372. int i;
  1373. if (pcats->title != NULL) {
  1374. G_free(pcats->title);
  1375. pcats->title = NULL;
  1376. }
  1377. if (pcats->fmt != NULL) {
  1378. G_free(pcats->fmt);
  1379. pcats->fmt = NULL;
  1380. }
  1381. if (pcats->ncats > 0) {
  1382. for (i = 0; i < pcats->ncats; i++)
  1383. if (pcats->labels[i] != NULL)
  1384. G_free(pcats->labels[i]);
  1385. G_free(pcats->labels);
  1386. G_free(pcats->marks);
  1387. pcats->labels = NULL;
  1388. }
  1389. G_quant_free(&pcats->q);
  1390. pcats->ncats = 0;
  1391. pcats->nalloc = 0;
  1392. }
  1393. /*!
  1394. * \brief
  1395. *
  1396. * Allocates NEW space for quant rules and labels n
  1397. * <em>pcats_to</em> and copies all info from <em>pcats_from</em> cats to <em>pcats_to</em> cats.
  1398. * returns:
  1399. * 0 if successful
  1400. * -1 on fail
  1401. *
  1402. * \param pcats_to
  1403. * \param pcats_from
  1404. * \return
  1405. */
  1406. void G_copy_raster_cats(struct Categories *pcats_to,
  1407. const struct Categories *pcats_from)
  1408. {
  1409. int i;
  1410. char *descr;
  1411. DCELL d1, d2;
  1412. G_init_raster_cats(pcats_from->title, pcats_to);
  1413. for (i = 0; i < pcats_from->ncats; i++) {
  1414. descr = G_get_ith_d_raster_cat(pcats_from, i, &d1, &d2);
  1415. G_set_d_raster_cat(&d1, &d2, descr, pcats_to);
  1416. }
  1417. }
  1418. int G_number_of_raster_cats(struct Categories *pcats)
  1419. {
  1420. return pcats->ncats;
  1421. }
  1422. static struct Categories save_cats;
  1423. int G_sort_cats(struct Categories *pcats)
  1424. {
  1425. int *indexes, i, ncats;
  1426. char *descr;
  1427. DCELL d1, d2;
  1428. if (pcats->ncats <= 1)
  1429. return -1;
  1430. ncats = pcats->ncats;
  1431. /* DEBUG fprintf(stderr,"G_sort_cats(): Copying to save cats buffer\n"); */
  1432. G_copy_raster_cats(&save_cats, pcats);
  1433. G_free_raster_cats(pcats);
  1434. indexes = (int *)G_malloc(sizeof(int) * ncats);
  1435. for (i = 0; i < ncats; i++)
  1436. indexes[i] = i;
  1437. qsort(indexes, ncats, sizeof(int), cmp);
  1438. G_init_raster_cats(save_cats.title, pcats);
  1439. for (i = 0; i < ncats; i++) {
  1440. descr = G_get_ith_d_raster_cat(&save_cats, indexes[i], &d1, &d2);
  1441. /* DEBUG fprintf(stderr,"G_sort_cats(): Write sorted cats, pcats = %p pcats->labels = %p\n",pcats,pcats->labels); */
  1442. G_set_d_raster_cat(&d1, &d2, descr, pcats);
  1443. /* DEBUG fflush(stderr); */
  1444. }
  1445. G_free_raster_cats(&save_cats);
  1446. /* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
  1447. /* fflush(stderr); */
  1448. return 0;
  1449. }
  1450. static int cmp(const void *aa, const void *bb)
  1451. {
  1452. const int *a = aa, *b = bb;
  1453. DCELL min_rast1, min_rast2, max_rast1, max_rast2;
  1454. CELL index;
  1455. G_quant_get_ith_rule(&(save_cats.q), *a,
  1456. &min_rast1, &max_rast1, &index, &index);
  1457. G_quant_get_ith_rule(&(save_cats.q), *b,
  1458. &min_rast2, &max_rast2, &index, &index);
  1459. if (min_rast1 < min_rast2)
  1460. return -1;
  1461. if (min_rast1 > min_rast2)
  1462. return 1;
  1463. return 0;
  1464. }