cats.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665
  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 dependant
  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 int get_cond(char **, char *, DCELL);
  326. static int get_fmt(char **, char *, int *);
  327. static int cmp(const void *, const void *);
  328. /*!
  329. * \brief read raster category file
  330. *
  331. * The category file for raster map
  332. * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
  333. * there is an error reading the category file, a diagnostic message is printed
  334. * and -1 is returned. Otherwise, 0 is returned.
  335. *
  336. * \param name
  337. * \param mapset
  338. * \param cats
  339. * \return int
  340. */
  341. int G_read_cats(const char *name,
  342. const char *mapset, struct Categories *pcats)
  343. {
  344. return G_read_raster_cats(name, mapset, pcats);
  345. }
  346. /*!
  347. * \brief
  348. *
  349. * Is the same as existing G_read_cats()
  350. *
  351. * \param name
  352. * \param mapset
  353. * \param pcats
  354. * \return int
  355. */
  356. int G_read_raster_cats(const char *name,
  357. const char *mapset, struct Categories *pcats)
  358. {
  359. char *type;
  360. switch (G__read_cats("cats", name, mapset, pcats, 1)) {
  361. case -2:
  362. type = "missing";
  363. break;
  364. case -1:
  365. type = "invalid";
  366. break;
  367. default:
  368. return 0;
  369. }
  370. G_warning(_("category support for [%s] in mapset [%s] %s"),
  371. name, mapset, type);
  372. return -1;
  373. }
  374. /*!
  375. * \brief read vector category file
  376. *
  377. * The category file for vector map
  378. * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
  379. * there is an error reading the category file, a diagnostic message is printed
  380. * and -1 is returned. Otherwise, 0 is returned.
  381. *
  382. * \param name
  383. * \param mapset
  384. * \param cats
  385. * \return int
  386. */
  387. int G_read_vector_cats(const char *name,
  388. const char *mapset, struct Categories *pcats)
  389. {
  390. char *type;
  391. switch (G__read_cats("dig_cats", name, mapset, pcats, 1)) {
  392. case -2:
  393. type = "missing";
  394. break;
  395. case -1:
  396. type = "invalid";
  397. break;
  398. default:
  399. return 0;
  400. }
  401. G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
  402. name, mapset, type);
  403. return -1;
  404. }
  405. CELL G_number_of_cats(const char *name, const char *mapset)
  406. {
  407. struct Range range;
  408. CELL min, max;
  409. /* return the max category number */
  410. if (G_read_range(name, mapset, &range) < 0)
  411. return -1;
  412. G_get_range_min_max(&range, &min, &max);
  413. if (G_is_c_null_value(&max))
  414. max = 0;
  415. return max;
  416. }
  417. CELL G__read_cats(const char *element,
  418. const char *name,
  419. const char *mapset, struct Categories * pcats, int full)
  420. {
  421. FILE *fd;
  422. char buff[1024];
  423. CELL cat;
  424. DCELL val1, val2;
  425. int old = 0, fp_map;
  426. long num = -1;
  427. if (strncmp(element, "dig", 3) == 0)
  428. fp_map = 0;
  429. else
  430. fp_map = G_raster_map_is_fp(name, mapset);
  431. if (!(fd = G_fopen_old(element, name, mapset)))
  432. return -2;
  433. /* Read the number of categories */
  434. if (G_getl(buff, sizeof buff, fd) == 0)
  435. goto error;
  436. if (sscanf(buff, "# %ld", &num) == 1)
  437. old = 0;
  438. else if (sscanf(buff, "%ld", &num) == 1)
  439. old = 1;
  440. if (!full) {
  441. fclose(fd);
  442. if (num < 0)
  443. return 0; /* coorect */
  444. return (CELL) num;
  445. }
  446. /* Read the title for the file */
  447. if (G_getl(buff, sizeof buff, fd) == 0)
  448. goto error;
  449. G_strip(buff);
  450. /* G_ascii_check(buff) ; */
  451. G_init_raster_cats(buff, pcats);
  452. if (num >= 0)
  453. pcats->num = num;
  454. if (!old) {
  455. char fmt[256];
  456. float m1, a1, m2, a2;
  457. if (G_getl(fmt, sizeof fmt, fd) == 0)
  458. goto error;
  459. /* next line contains equation coefficients */
  460. if (G_getl(buff, sizeof buff, fd) == 0)
  461. goto error;
  462. if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
  463. goto error;
  464. G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
  465. }
  466. /* Read all category names */
  467. for (cat = 0;; cat++) {
  468. char label[1024];
  469. if (G_getl(buff, sizeof buff, fd) == 0)
  470. break;
  471. if (old)
  472. G_set_cat(cat, buff, pcats);
  473. else {
  474. *label = 0;
  475. if (sscanf(buff, "%1s", label) != 1)
  476. continue;
  477. if (*label == '#')
  478. continue;
  479. *label = 0;
  480. /* for fp maps try to read a range of data */
  481. if (fp_map
  482. && sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
  483. G_set_raster_cat(&val1, &val2, label, pcats, DCELL_TYPE);
  484. else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
  485. G_set_raster_cat(&cat, &cat, label, pcats, CELL_TYPE);
  486. else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
  487. G_set_raster_cat(&val1, &val1, label, pcats, DCELL_TYPE);
  488. else
  489. goto error;
  490. }
  491. }
  492. fclose(fd);
  493. return 0;
  494. error:
  495. fclose(fd);
  496. return -1;
  497. }
  498. /*!
  499. * \brief get title from category structure struct
  500. *
  501. * Map layers store a one-line title in the category structure
  502. * as well. This routine returns a pointer to the title contained in the
  503. * <b>cats</b> structure. A legal pointer is always returned. If the map
  504. * layer does not have a title, then a pointer to the empty string "" is
  505. * returned.
  506. *
  507. * \param cats
  508. * \return char *
  509. */
  510. char *G_get_cats_title(const struct Categories *pcats)
  511. {
  512. return G_get_raster_cats_title(pcats);
  513. }
  514. /*!
  515. * \brief get raster cats title
  516. *
  517. * Returns pointer to a string with title.
  518. *
  519. * \param pcats
  520. * \return char *
  521. */
  522. char *G_get_raster_cats_title(const struct Categories *pcats)
  523. {
  524. static char *none = "";
  525. return pcats->title ? pcats->title : none;
  526. }
  527. /*!
  528. * \brief get a category label
  529. *
  530. * This routine looks up category <b>n</b> in the <b>cats</b>
  531. * structure and returns a pointer to a string which is the label for the
  532. * category. A legal pointer is always returned. If the category does not exist
  533. * in <b>cats,</b> then a pointer to the empty string "" is returned.
  534. * <b>Warning.</b> The pointer that is returned points to a hidden static
  535. * buffer. Successive calls to G_get_cat( ) overwrite this buffer.
  536. *
  537. * \param n
  538. * \param cats
  539. * \return char *
  540. */
  541. char *G_get_cat(CELL num, struct Categories *pcats)
  542. {
  543. return G_get_c_raster_cat(&num, pcats);
  544. }
  545. /*!
  546. * \brief
  547. *
  548. * given a CELL value <em>val</em> Returns pointer to a string describing
  549. * category.
  550. *
  551. * \param val
  552. * \param pcats
  553. * \return char *
  554. */
  555. char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
  556. {
  557. return G_get_raster_cat(rast, pcats, CELL_TYPE);
  558. }
  559. /*!
  560. * \brief
  561. *
  562. * given a FCELL value <em>val</em> Returns pointer to a string
  563. * describing category.
  564. *
  565. * \param val
  566. * \param pcats
  567. * \return char *
  568. */
  569. char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
  570. {
  571. return G_get_raster_cat(rast, pcats, FCELL_TYPE);
  572. }
  573. /*!
  574. * \brief
  575. *
  576. * given a DCELL value <em>val</em> Returns pointer to a string
  577. * describing category.
  578. *
  579. * \param val
  580. * \param pcats
  581. * \return char *
  582. */
  583. char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
  584. {
  585. return G_get_raster_cat(rast, pcats, DCELL_TYPE);
  586. }
  587. /*!
  588. * \brief
  589. *
  590. * given a raster value <em>val</em> of type <em>data_type</em> Returns pointer to a string
  591. * describing category.
  592. *
  593. * \param val
  594. * \param pcats
  595. * \param data_type
  596. * \return char *
  597. */
  598. char *G_get_raster_cat(void *rast,
  599. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  600. {
  601. static char label[1024];
  602. char *f, *l, *v;
  603. CELL i;
  604. DCELL val;
  605. float a[2];
  606. char fmt[30], value_str[30];
  607. if (G_is_null_value(rast, data_type)) {
  608. sprintf(label, "no data");
  609. return label;
  610. }
  611. /* first search the list of labels */
  612. *label = 0;
  613. val = G_get_raster_value_d(rast, data_type);
  614. i = G_quant_get_cell_value(&pcats->q, val);
  615. /* DEBUG fprintf (stderr, "val %lf found i %d\n", val, i); */
  616. if (!G_is_c_null_value(&i) && i < pcats->ncats) {
  617. if (pcats->labels[i] != NULL)
  618. return pcats->labels[i];
  619. return label;
  620. }
  621. /* generate the label */
  622. if ((f = pcats->fmt) == NULL)
  623. return label;
  624. a[0] = (float)val *pcats->m1 + pcats->a1;
  625. a[1] = (float)val *pcats->m2 + pcats->a2;
  626. l = label;
  627. while (*f) {
  628. if (*f == '$') {
  629. f++;
  630. if (*f == '$')
  631. *l++ = *f++;
  632. else if (*f == '?') {
  633. f++;
  634. get_cond(&f, v = value_str, val);
  635. while (*v)
  636. *l++ = *v++;
  637. }
  638. else if (get_fmt(&f, fmt, &i)) {
  639. sprintf(v = value_str, fmt, a[i]);
  640. while (*v)
  641. *l++ = *v++;
  642. }
  643. else
  644. *l++ = '$';
  645. }
  646. else {
  647. *l++ = *f++;
  648. }
  649. }
  650. *l = 0;
  651. return label;
  652. }
  653. /*!
  654. * \brief
  655. *
  656. * Sets marks
  657. * for all categories to 0. This initializes Categories structure for subsequest
  658. * calls to G_mark_raster_cats (rast_row,...) for each row of data, where
  659. * non-zero mark for i-th label means that some of the cells in rast_row are
  660. * labeled with i-th label and fall into i-th data range.
  661. * These marks help determine from the Categories structure which labels were
  662. * used and which weren't.
  663. *
  664. * \param pcats
  665. * \return int
  666. */
  667. int G_unmark_raster_cats(struct Categories *pcats)
  668. { /* structure to hold category info */
  669. register int i;
  670. for (i = 0; i < pcats->ncats; i++)
  671. pcats->marks[i] = 0;
  672. return 0;
  673. }
  674. /*!
  675. * \brief
  676. *
  677. * Looks up the category label for each raster value in
  678. * the <em>rast_row</em> and updates the marks for labels found.
  679. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  680. * so far which are labeled with i-th label and fall into i-th data range.
  681. *
  682. * \param rast_row
  683. * \param ncols
  684. * \param pcats
  685. * \return int
  686. */
  687. int G_mark_c_raster_cats(const CELL * rast_row, /* raster row to update stats */
  688. int ncols, struct Categories *pcats)
  689. { /* structure to hold category info */
  690. G_mark_raster_cats(rast_row, ncols, pcats, CELL_TYPE);
  691. return 0;
  692. }
  693. /*!
  694. * \brief
  695. *
  696. * Looks up the category label for each raster value in
  697. * the <em>rast_row</em> and updates the marks for labels found.
  698. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  699. * so far which are labeled with i-th label and fall into i-th data range.
  700. *
  701. * \param rast_row
  702. * \param ncols
  703. * \param pcats
  704. * \return int
  705. */
  706. int G_mark_f_raster_cats(const FCELL * rast_row, /* raster row to update stats */
  707. int ncols, struct Categories *pcats)
  708. { /* structure to hold category info */
  709. G_mark_raster_cats(rast_row, ncols, pcats, FCELL_TYPE);
  710. return 0;
  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 int
  724. */
  725. int 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. return 0;
  730. }
  731. /*!
  732. * \brief
  733. *
  734. * Looks up the category
  735. * label for each raster value in the <em>rast_row</em> (row of raster cell value)
  736. * and updates the marks for labels found.
  737. * NOTE: non-zero mark for i-th label stores the number of of raster cells read
  738. * so far which are labeled with i-th label and fall into i-th data range.
  739. *
  740. * \param rast_row
  741. * \param ncols
  742. * \param pcats
  743. * \param data_type
  744. * \return int
  745. */
  746. int G_mark_raster_cats(const void *rast_row, /* raster row to update stats */
  747. int ncols, struct Categories *pcats, /* structure to hold category info */
  748. RASTER_MAP_TYPE data_type)
  749. {
  750. CELL i;
  751. while (ncols-- > 0) {
  752. i = G_quant_get_cell_value(&pcats->q,
  753. G_get_raster_value_d(rast_row, data_type));
  754. if (G_is_c_null_value(&i))
  755. continue;
  756. if (i > pcats->ncats)
  757. return -1;
  758. pcats->marks[i]++;
  759. rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
  760. }
  761. return 1;
  762. }
  763. /*!
  764. * \brief
  765. *
  766. * after call to
  767. * this function G_get_next_marked_raster_cat() returns the first marked
  768. * cat label.
  769. *
  770. * \param pcats
  771. * \return int
  772. */
  773. int G_rewind_raster_cats(struct Categories *pcats)
  774. {
  775. pcats->last_marked_rule = -1;
  776. return 0;
  777. }
  778. char *G_get_next_marked_d_raster_cat(struct Categories *pcats, /* structure to hold category info */
  779. DCELL * rast1, DCELL * rast2, /* pointers to raster range */
  780. long *count)
  781. {
  782. char *descr = NULL;
  783. int found, i;
  784. found = 0;
  785. /* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
  786. /* DEBUG
  787. fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
  788. */
  789. for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
  790. i++) {
  791. descr = G_get_ith_d_raster_cat(pcats, i, rast1, rast2);
  792. /* DEBUG fprintf (stderr, "%d %d\n", i, pcats->marks[i]); */
  793. if (pcats->marks[i]) {
  794. found = 1;
  795. break;
  796. }
  797. }
  798. if (!found)
  799. return NULL;
  800. *count = pcats->marks[i];
  801. pcats->last_marked_rule = i;
  802. return descr;
  803. }
  804. char *G_get_next_marked_c_raster_cat(struct Categories *pcats, /* structure to hold category info */
  805. CELL * rast1, CELL * rast2, /* pointers to raster range */
  806. long *count)
  807. {
  808. return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
  809. CELL_TYPE);
  810. }
  811. char *G_get_next_marked_f_raster_cat(struct Categories *pcats, /* structure to hold category info */
  812. FCELL * rast1, FCELL * rast2, /* pointers to raster range */
  813. long *count)
  814. {
  815. return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
  816. FCELL_TYPE);
  817. }
  818. char *G_get_next_marked_raster_cat(struct Categories *pcats, /* structure to hold category info */
  819. void *rast1, void *rast2, /* pointers to raster range */
  820. long *count, RASTER_MAP_TYPE data_type)
  821. {
  822. DCELL val1, val2;
  823. char *lab;
  824. lab = G_get_next_marked_d_raster_cat(pcats, &val1, &val2, count);
  825. G_set_raster_value_d(rast1, val1, data_type);
  826. G_set_raster_value_d(rast2, val2, data_type);
  827. return lab;
  828. }
  829. static int get_fmt(char **f, char *fmt, int *i)
  830. {
  831. char *ff;
  832. ff = *f;
  833. if (*ff == 0)
  834. return 0;
  835. if (*ff == '$') {
  836. *f = ff + 1;
  837. return 0;
  838. }
  839. switch (*ff++) {
  840. case '1':
  841. *i = 0;
  842. break;
  843. case '2':
  844. *i = 1;
  845. break;
  846. default:
  847. return 0;
  848. }
  849. *fmt++ = '%';
  850. *fmt++ = '.';
  851. if (*ff++ != '.') {
  852. *f = ff - 1;
  853. *fmt++ = '0';
  854. *fmt++ = 'f';
  855. *fmt = 0;
  856. return 1;
  857. }
  858. *fmt = '0';
  859. while (*ff >= '0' && *ff <= '9')
  860. *fmt++ = *ff++;
  861. *fmt++ = 'f';
  862. *fmt = 0;
  863. *f = ff;
  864. return 1;
  865. }
  866. static int get_cond(char **f, char *value, DCELL val)
  867. {
  868. char *ff;
  869. ff = *f;
  870. if (val == 1.) {
  871. while (*ff)
  872. if (*ff++ == '$')
  873. break;
  874. }
  875. while (*ff)
  876. if (*ff == '$') {
  877. ff++;
  878. break;
  879. }
  880. else
  881. *value++ = *ff++;
  882. if (val != 1.) {
  883. while (*ff)
  884. if (*ff++ == '$')
  885. break;
  886. }
  887. *value = 0;
  888. *f = ff;
  889. return 0;
  890. }
  891. /*!
  892. * \brief set a category label
  893. *
  894. * The <b>label</b> is copied into the <b>cats</b> structure
  895. * for category <b>n.</b>
  896. *
  897. * \param n
  898. * \param label
  899. * \param cats
  900. * \return int
  901. */
  902. int G_set_cat(CELL num, const char *label, struct Categories *pcats)
  903. {
  904. return G_set_c_raster_cat(&num, &num, label, pcats);
  905. }
  906. /*!
  907. * \brief
  908. *
  909. * Adds the label for range <em>rast1</em> through <em>rast2</em> in
  910. * category structure <em>pcats</em>.
  911. *
  912. * \param rast1
  913. * \param rast2
  914. * \param pcats
  915. * \return int
  916. */
  917. int G_set_c_raster_cat(const CELL * rast1, const CELL * rast2,
  918. const char *label, struct Categories *pcats)
  919. {
  920. return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
  921. }
  922. /*!
  923. * \brief
  924. *
  925. * Adds the label for range <em>rast1</em> through <em>rast2</em>
  926. * in category structure <em>pcats</em>.
  927. *
  928. * \param rast1
  929. * \param rast2
  930. * \param pcats
  931. * \return int
  932. */
  933. int G_set_f_raster_cat(const FCELL * rast1, const FCELL * rast2,
  934. const char *label, struct Categories *pcats)
  935. {
  936. return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
  937. }
  938. /*!
  939. * \brief
  940. *
  941. * Adds the label for range <em>rast1</em> through <em>rast2</em>
  942. * in category structure <em>pcats</em>.
  943. *
  944. * \param rast1
  945. * \param rast2
  946. * \param pcats
  947. * \return int
  948. */
  949. int G_set_d_raster_cat(const DCELL * rast1, const DCELL * rast2,
  950. const char *label, struct Categories *pcats)
  951. {
  952. long len;
  953. DCELL dtmp1, dtmp2;
  954. int i;
  955. char *descr;
  956. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
  957. rast1,rast2,label,pcats); */
  958. if (G_is_d_null_value(rast1))
  959. return 0;
  960. if (G_is_d_null_value(rast2))
  961. return 0;
  962. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
  963. /* the set_cat() functions are used in many places to reset the labels
  964. for the range (or cat) with existing label. In this case we don't
  965. want to store both rules with identical range even though the result
  966. of get_cat() will be correct, since it will use rule added later.
  967. we don't want to overuse memory and we don't want rules which are
  968. not used to be writen out in cats file. So we first look if
  969. the label for this range has been sen, and if it has, overwrite it */
  970. for (i = 0; i < pcats->ncats; i++) {
  971. descr = G_get_ith_d_raster_cat(pcats, i, &dtmp1, &dtmp2);
  972. if ((dtmp1 == *rast1 && dtmp2 == *rast2)
  973. || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
  974. if (pcats->labels[i] != NULL)
  975. G_free(pcats->labels[i]);
  976. pcats->labels[i] = G_store(label);
  977. G_newlines_to_spaces(pcats->labels[i]);
  978. G_strip(pcats->labels[i]);
  979. return 1;
  980. }
  981. }
  982. /* when rule for this range does not exist */
  983. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): New rule: adding %d %p\n", i, pcats->labels); */
  984. G_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats, pcats->ncats);
  985. pcats->ncats++;
  986. if (pcats->nalloc < pcats->ncats) {
  987. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
  988. len = (pcats->nalloc + 256) * sizeof(char *);
  989. /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
  990. if (len != (int)len) { /* make sure len doesn't overflow int */
  991. pcats->ncats--;
  992. return -1;
  993. }
  994. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
  995. if (pcats->nalloc) {
  996. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
  997. pcats->labels =
  998. (char **)G_realloc((char *)pcats->labels, (int)len);
  999. }
  1000. else {
  1001. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
  1002. pcats->labels = (char **)G_malloc((int)len);
  1003. }
  1004. /* fflush(stderr); */
  1005. /* DEBUG fprintf (stderr, "G_set_d_raster_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
  1006. len = (pcats->nalloc + 256) * sizeof(int);
  1007. if (len != (int)len) { /* make sure len doesn't overflow int */
  1008. pcats->ncats--;
  1009. return -1;
  1010. }
  1011. if (pcats->nalloc)
  1012. pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
  1013. else
  1014. pcats->marks = (int *)G_malloc((int)len);
  1015. pcats->nalloc += 256;
  1016. }
  1017. /* DEBUG fprintf(stderr,"G_set_d_raster_cats(): store new label\n"); */
  1018. pcats->labels[pcats->ncats - 1] = G_store(label);
  1019. G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
  1020. G_strip(pcats->labels[pcats->ncats - 1]);
  1021. /* DEBUG
  1022. fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
  1023. */
  1024. /* updates cats.num = max cat values. This is really just used in old
  1025. raster programs, and I am doing it for backwards cmpatibility (Olga) */
  1026. if ((CELL) * rast1 > pcats->num)
  1027. pcats->num = (CELL) * rast1;
  1028. if ((CELL) * rast2 > pcats->num)
  1029. pcats->num = (CELL) * rast2;
  1030. /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): done\n"); */
  1031. /* DEBUG fflush(stderr); */
  1032. return 1;
  1033. }
  1034. /*!
  1035. * \brief
  1036. *
  1037. * Adds the label for range <em>rast1</em> through <em>rast2</em> in category structure <em>pcats</em>.
  1038. *
  1039. * \param rast1
  1040. * \param rast2
  1041. * \param pcats
  1042. * \param data_type
  1043. * \return int
  1044. */
  1045. int G_set_raster_cat(const void *rast1, const void *rast2,
  1046. const char *label,
  1047. struct Categories *pcats, RASTER_MAP_TYPE data_type)
  1048. {
  1049. DCELL val1, val2;
  1050. val1 = G_get_raster_value_d(rast1, data_type);
  1051. val2 = G_get_raster_value_d(rast2, data_type);
  1052. return G_set_d_raster_cat(&val1, &val2, label, pcats);
  1053. }
  1054. /*!
  1055. * \brief write raster category file
  1056. *
  1057. * Writes the category file for the raster map <b>name</b> in
  1058. * the current mapset from the <b>cats</b> structure.
  1059. * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
  1060. * printed).
  1061. *
  1062. * \param name
  1063. * \param cats
  1064. * \return int
  1065. */
  1066. int G_write_cats(const char *name, struct Categories *cats)
  1067. {
  1068. return G__write_cats("cats", name, cats);
  1069. }
  1070. /*!
  1071. * \brief
  1072. *
  1073. * Same as existing G_write_cats()
  1074. *
  1075. * \param name
  1076. * \param pcats
  1077. * \return int
  1078. */
  1079. int G_write_raster_cats(const char *name, struct Categories *cats)
  1080. {
  1081. return G__write_cats("cats", name, cats);
  1082. }
  1083. /*!
  1084. * \brief write
  1085. * vector category file
  1086. *
  1087. * Writes the category file for the vector map
  1088. * <b>name</b> in the current mapset from the <b>cats</b> structure.
  1089. * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
  1090. * printed).
  1091. *
  1092. * \param name
  1093. * \param cats
  1094. * \return int
  1095. */
  1096. int G_write_vector_cats(const char *name, struct Categories *cats)
  1097. {
  1098. return G__write_cats("dig_cats", name, cats);
  1099. }
  1100. int G__write_cats(const char *element, const char *name, struct Categories *cats)
  1101. {
  1102. FILE *fd;
  1103. int i, fp_map;
  1104. char *descr;
  1105. DCELL val1, val2;
  1106. char str1[100], str2[100];
  1107. /* DEBUG fprintf(stderr,"G__write_cats(*element = '%s', name = '%s', cats = %p\n",element,name,cats); */
  1108. if (!(fd = G_fopen_new(element, name)))
  1109. return -1;
  1110. /* write # cats - note # indicate 3.0 or later */
  1111. fprintf(fd, "# %ld categories\n", (long)cats->num);
  1112. /* title */
  1113. fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
  1114. /* write format and coefficients */
  1115. fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
  1116. fprintf(fd, "%.2f %.2f %.2f %.2f\n",
  1117. cats->m1, cats->a1, cats->m2, cats->a2);
  1118. /* if the map is integer or if this is a vector map, sort labels */
  1119. if (strncmp(element, "dig", 3) == 0)
  1120. fp_map = 0;
  1121. else
  1122. fp_map = G_raster_map_is_fp(name, G_mapset());
  1123. /* DEBUG fprintf(stderr,"G__write_cats(): fp_map = %d\n",fp_map); */
  1124. if (!fp_map)
  1125. G_sort_cats(cats);
  1126. /* write the cat numbers:label */
  1127. for (i = 0; i < G_quant_nof_rules(&cats->q); i++) {
  1128. descr = G_get_ith_d_raster_cat(cats, i, &val1, &val2);
  1129. if ((cats->fmt && cats->fmt[0])
  1130. || (descr && descr[0])) {
  1131. if (val1 == val2) {
  1132. sprintf(str1, "%.10f", val1);
  1133. G_trim_decimal(str1);
  1134. fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
  1135. }
  1136. else {
  1137. sprintf(str1, "%.10f", val1);
  1138. G_trim_decimal(str1);
  1139. sprintf(str2, "%.10f", val2);
  1140. G_trim_decimal(str2);
  1141. fprintf(fd, "%s:%s:%s\n", str1, str2,
  1142. descr != NULL ? descr : "");
  1143. }
  1144. }
  1145. }
  1146. fclose(fd);
  1147. /* DEBUG fprintf(stderr,"G__write_cats(): done\n"); */
  1148. return (1);
  1149. }
  1150. /*!
  1151. * \brief
  1152. *
  1153. * Returns i-th description and i-th data range
  1154. * from the list of category descriptions with corresponding data ranges. end
  1155. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1156. *
  1157. * \param pcats
  1158. * \param i
  1159. * \param rast1
  1160. * \param rast2
  1161. * \return char *
  1162. */
  1163. char *G_get_ith_d_raster_cat(const struct Categories *pcats,
  1164. int i, DCELL * rast1, DCELL * rast2)
  1165. {
  1166. int index;
  1167. if (i > pcats->ncats) {
  1168. G_set_d_null_value(rast1, 1);
  1169. G_set_d_null_value(rast2, 1);
  1170. return "";
  1171. }
  1172. G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
  1173. return pcats->labels[index];
  1174. }
  1175. /*!
  1176. * \brief
  1177. *
  1178. * Returns i-th description and i-th data range
  1179. * from the list of category descriptions with corresponding data ranges. end
  1180. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1181. *
  1182. * \param pcats
  1183. * \param i
  1184. * \param rast1
  1185. * \param rast2
  1186. * \return char *
  1187. */
  1188. char *G_get_ith_f_raster_cat(const struct Categories *pcats,
  1189. int i, void *rast1, void *rast2)
  1190. {
  1191. RASTER_MAP_TYPE data_type = FCELL_TYPE;
  1192. char *tmp;
  1193. DCELL val1, val2;
  1194. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1195. G_set_raster_value_d(rast1, val1, data_type);
  1196. G_set_raster_value_d(rast2, val2, data_type);
  1197. return tmp;
  1198. }
  1199. /*!
  1200. * \brief
  1201. *
  1202. * Returns i-th description and i-th data range
  1203. * from the list of category descriptions with corresponding data ranges. end
  1204. * points of data interval in <em>rast1</em> and <em>rast2</em>.
  1205. *
  1206. * \param pcats
  1207. * \param i
  1208. * \param rast1
  1209. * \param rast2
  1210. * \return char *
  1211. */
  1212. char *G_get_ith_c_raster_cat(const struct Categories *pcats,
  1213. int i, void *rast1, void *rast2)
  1214. {
  1215. RASTER_MAP_TYPE data_type = CELL_TYPE;
  1216. char *tmp;
  1217. DCELL val1, val2;
  1218. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1219. G_set_raster_value_d(rast1, val1, data_type);
  1220. G_set_raster_value_d(rast2, val2, data_type);
  1221. return tmp;
  1222. }
  1223. /*!
  1224. * \brief
  1225. *
  1226. * Returns i-th
  1227. * description and i-th data range from the list of category descriptions with
  1228. * corresponding data ranges. Stores end points of data interval in <em>rast1</em>
  1229. * and <em>rast2</em> (after converting them to <em>data_type</em>.
  1230. *
  1231. * \param pcats
  1232. * \param i
  1233. * \param rast1
  1234. * \param rast2
  1235. * \param data_type
  1236. * \return char *
  1237. */
  1238. char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
  1239. void *rast2, RASTER_MAP_TYPE data_type)
  1240. {
  1241. char *tmp;
  1242. DCELL val1, val2;
  1243. tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
  1244. G_set_raster_value_d(rast1, val1, data_type);
  1245. G_set_raster_value_d(rast2, val2, data_type);
  1246. return tmp;
  1247. }
  1248. /*!
  1249. * \brief initialize category structure
  1250. *
  1251. * To construct a new category file, the
  1252. * structure must first be initialized. This routine initializes the
  1253. * <b>cats</b> structure, and copies the <b>title</b> into the structure.
  1254. * The number of categories is set initially to <b>n.</b>
  1255. * For example:
  1256. \code
  1257. struct Categories cats;
  1258. G_init_cats ( (CELL)0, "", &cats);
  1259. \endcode
  1260. *
  1261. * \param n
  1262. * \param title
  1263. * \param cats
  1264. * \return int
  1265. */
  1266. int G_init_cats(CELL num, const char *title, struct Categories *pcats)
  1267. {
  1268. G_init_raster_cats(title, pcats);
  1269. pcats->num = num;
  1270. return 0;
  1271. }
  1272. /*!
  1273. * \brief
  1274. *
  1275. * Same as existing G_init_raster_cats() only ncats argument is
  1276. * missign. ncats has no meaning in new Categories structure and only stores
  1277. * (int) largets data value for backwards compatibility.
  1278. *
  1279. * \param title
  1280. * \param pcats
  1281. * \return int
  1282. */
  1283. int G_init_raster_cats(const char *title, struct Categories *pcats)
  1284. {
  1285. G_set_raster_cats_title(title, pcats);
  1286. pcats->labels = NULL;
  1287. pcats->nalloc = 0;
  1288. pcats->ncats = 0;
  1289. pcats->num = 0;
  1290. pcats->fmt = NULL;
  1291. pcats->m1 = 0.0;
  1292. pcats->a1 = 0.0;
  1293. pcats->m2 = 0.0;
  1294. pcats->a2 = 0.0;
  1295. pcats->last_marked_rule = -1;
  1296. G_quant_init(&pcats->q);
  1297. return 0;
  1298. }
  1299. /*!
  1300. * \brief set title in category structure
  1301. *
  1302. * The <b>title</b> is copied into the
  1303. * <b>cats</b> structure.
  1304. *
  1305. * \param title
  1306. * \param cats
  1307. * \return int
  1308. */
  1309. int G_set_cats_title(const char *title, struct Categories *pcats)
  1310. {
  1311. G_set_raster_cats_title(title, pcats);
  1312. return 0;
  1313. }
  1314. /*!
  1315. * \brief
  1316. *
  1317. * Same as existing G_set_cats_title()
  1318. *
  1319. * \param title
  1320. * \param pcats
  1321. * \return int
  1322. */
  1323. int G_set_raster_cats_title(const char *title, struct Categories *pcats)
  1324. {
  1325. if (title == NULL)
  1326. title = "";
  1327. pcats->title = G_store(title);
  1328. G_newlines_to_spaces(pcats->title);
  1329. G_strip(pcats->title);
  1330. return 0;
  1331. }
  1332. int G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
  1333. double a2, struct Categories *pcats)
  1334. {
  1335. G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
  1336. return 0;
  1337. }
  1338. /*!
  1339. * \brief
  1340. *
  1341. * Same as existing G_set_cats_fmt()
  1342. *
  1343. * \param fmt
  1344. * \param m1
  1345. * \param a1
  1346. * \param m2
  1347. * \param a2
  1348. * \param pcats
  1349. * \return int
  1350. */
  1351. int G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
  1352. double a2, struct Categories *pcats)
  1353. {
  1354. pcats->m1 = m1;
  1355. pcats->a1 = a1;
  1356. pcats->m2 = m2;
  1357. pcats->a2 = a2;
  1358. pcats->fmt = G_store(fmt);
  1359. G_newlines_to_spaces(pcats->fmt);
  1360. G_strip(pcats->fmt);
  1361. return 0;
  1362. }
  1363. /*!
  1364. * \brief free category structure memory
  1365. *
  1366. * Frees memory allocated by<i>G_read_cats, G_init_cats</i>
  1367. * and<i>G_set_cat.</i>
  1368. *
  1369. * \param cats
  1370. * \return int
  1371. */
  1372. int G_free_cats(struct Categories *pcats)
  1373. {
  1374. G_free_raster_cats(pcats);
  1375. return 0;
  1376. }
  1377. /*!
  1378. * \brief
  1379. *
  1380. * Same as existing G_free_cats()
  1381. *
  1382. * \param pcats
  1383. * \return int
  1384. */
  1385. int G_free_raster_cats(struct Categories *pcats)
  1386. {
  1387. int i;
  1388. if (pcats->title != NULL) {
  1389. G_free(pcats->title);
  1390. pcats->title = NULL;
  1391. }
  1392. if (pcats->fmt != NULL) {
  1393. G_free(pcats->fmt);
  1394. pcats->fmt = NULL;
  1395. }
  1396. if (pcats->ncats > 0) {
  1397. for (i = 0; i < pcats->ncats; i++)
  1398. if (pcats->labels[i] != NULL)
  1399. G_free(pcats->labels[i]);
  1400. G_free(pcats->labels);
  1401. G_free(pcats->marks);
  1402. pcats->labels = NULL;
  1403. }
  1404. G_quant_free(&pcats->q);
  1405. pcats->ncats = 0;
  1406. pcats->nalloc = 0;
  1407. return 0;
  1408. }
  1409. /*!
  1410. * \brief
  1411. *
  1412. * Allocates NEW space for quant rules and labels n
  1413. * <em>pcats_to</em> and copies all info from <em>pcats_from</em> cats to <em>pcats_to</em> cats.
  1414. * returns:
  1415. * 0 if successful
  1416. * -1 on fail
  1417. *
  1418. * \param pcats_to
  1419. * \param pcats_from
  1420. * \return int
  1421. */
  1422. int
  1423. G_copy_raster_cats(struct Categories *pcats_to,
  1424. const struct Categories *pcats_from)
  1425. {
  1426. int i;
  1427. char *descr;
  1428. DCELL d1, d2;
  1429. G_init_raster_cats(pcats_from->title, pcats_to);
  1430. for (i = 0; i < pcats_from->ncats; i++) {
  1431. descr = G_get_ith_d_raster_cat(pcats_from, i, &d1, &d2);
  1432. G_set_d_raster_cat(&d1, &d2, descr, pcats_to);
  1433. }
  1434. return 0;
  1435. }
  1436. int G_number_of_raster_cats(struct Categories *pcats)
  1437. {
  1438. return pcats->ncats;
  1439. }
  1440. static struct Categories save_cats;
  1441. int G_sort_cats(struct Categories *pcats)
  1442. {
  1443. int *indexes, i, ncats;
  1444. char *descr;
  1445. DCELL d1, d2;
  1446. if (pcats->ncats <= 1)
  1447. return -1;
  1448. ncats = pcats->ncats;
  1449. /* DEBUG fprintf(stderr,"G_sort_cats(): Copying to save cats buffer\n"); */
  1450. G_copy_raster_cats(&save_cats, pcats);
  1451. G_free_raster_cats(pcats);
  1452. indexes = (int *)G_malloc(sizeof(int) * ncats);
  1453. for (i = 0; i < ncats; i++)
  1454. indexes[i] = i;
  1455. qsort(indexes, ncats, sizeof(int), cmp);
  1456. G_init_raster_cats(save_cats.title, pcats);
  1457. for (i = 0; i < ncats; i++) {
  1458. descr = G_get_ith_d_raster_cat(&save_cats, indexes[i], &d1, &d2);
  1459. /* DEBUG fprintf(stderr,"G_sort_cats(): Write sorted cats, pcats = %p pcats->labels = %p\n",pcats,pcats->labels); */
  1460. G_set_d_raster_cat(&d1, &d2, descr, pcats);
  1461. /* DEBUG fflush(stderr); */
  1462. }
  1463. G_free_raster_cats(&save_cats);
  1464. /* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
  1465. /* fflush(stderr); */
  1466. return 0;
  1467. }
  1468. static int cmp(const void *aa, const void *bb)
  1469. {
  1470. const int *a = aa, *b = bb;
  1471. DCELL min_rast1, min_rast2, max_rast1, max_rast2;
  1472. CELL index;
  1473. G_quant_get_ith_rule(&(save_cats.q), *a,
  1474. &min_rast1, &max_rast1, &index, &index);
  1475. G_quant_get_ith_rule(&(save_cats.q), *b,
  1476. &min_rast2, &max_rast2, &index, &index);
  1477. if (min_rast1 < min_rast2)
  1478. return -1;
  1479. if (min_rast1 > min_rast2)
  1480. return 1;
  1481. return 0;
  1482. }