reclass.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <grass/gis.h>
  4. #include <grass/raster.h>
  5. #include <grass/manage.h>
  6. #include <grass/glocale.h>
  7. #include "rule.h"
  8. extern CELL DEFAULT;
  9. extern int default_rule, default_to_itself;
  10. extern char *default_label;
  11. static void compose(struct Reclass *new, const struct Reclass *mid,
  12. const struct Reclass *old)
  13. {
  14. int first;
  15. CELL i, j, k;
  16. long num;
  17. first = 1;
  18. for (i = old->min; i <= old->max; i++) {
  19. j = old->table[i - old->min];
  20. if (Rast_is_c_null_value(&j) || j < mid->min || j > mid->max)
  21. continue;
  22. k = mid->table[j - mid->min];
  23. if (Rast_is_c_null_value(&k))
  24. continue;
  25. if (first) {
  26. new->min = new->max = i;
  27. first = 0;
  28. }
  29. else {
  30. if (i < new->min)
  31. new->min = i;
  32. if (i > new->max)
  33. new->max = i;
  34. }
  35. }
  36. if (first)
  37. new->min = new->max = 0;
  38. new->type = RECLASS_TABLE;
  39. num = new->max - new->min + 1;
  40. /* make sure don't overflow int */
  41. if (num != (int)num)
  42. G_fatal_error(_("Too many categories"));
  43. new->num = num;
  44. new->table = (CELL *) G_calloc(new->num, sizeof(CELL));
  45. for (i = new->min; i <= new->max; i++) {
  46. j = old->table[i - old->min];
  47. if (Rast_is_c_null_value(&j) || j < mid->min || j > mid->max) {
  48. Rast_set_c_null_value(&new->table[i - new->min], 1);
  49. continue;
  50. }
  51. k = mid->table[j - mid->min];
  52. new->table[i - new->min] = k;
  53. }
  54. }
  55. static void init_reclass(struct Reclass *rec, const RULE * rules)
  56. {
  57. int first;
  58. const RULE *r;
  59. long num;
  60. first = 1;
  61. if (default_rule && !Rast_is_c_null_value(&DEFAULT)) {
  62. struct Range range;
  63. Rast_read_range(rec->name, rec->mapset, &range);
  64. Rast_get_range_min_max(&range, &rec->min, &rec->max);
  65. if (!Rast_is_c_null_value(&rec->min) && !Rast_is_c_null_value(&rec->max))
  66. first = 0;
  67. }
  68. /* first find the min,max cats */
  69. for (r = rules; r; r = r->next) {
  70. if (first) {
  71. rec->min = r->lo;
  72. rec->max = r->hi;
  73. first = 0;
  74. }
  75. else {
  76. if (r->lo < rec->min)
  77. rec->min = r->lo;
  78. if (r->hi > rec->max)
  79. rec->max = r->hi;
  80. }
  81. }
  82. /* make sure we have at least one entry */
  83. if (first)
  84. rec->min = rec->max = 0;
  85. /* allocate reclass table */
  86. rec->type = RECLASS_TABLE;
  87. num = rec->max - rec->min + 1;
  88. /* make sure don't overflow int */
  89. if (num != (int)num)
  90. G_fatal_error(_("Too many categories"));
  91. rec->num = num;
  92. rec->table = G_calloc(rec->num, sizeof(CELL));
  93. }
  94. static void init_table(struct Reclass *rec, int *is_default)
  95. {
  96. int i;
  97. for (i = 0; i < rec->num; i++) {
  98. if (default_rule) {
  99. if (default_to_itself)
  100. rec->table[i] = i + rec->min;
  101. else
  102. rec->table[i] = DEFAULT;
  103. is_default[i] = 1;
  104. }
  105. else {
  106. Rast_set_c_null_value(&rec->table[i], 1);
  107. is_default[i] = 0;
  108. }
  109. }
  110. }
  111. static void fill_table(struct Reclass *rec, int *is_default,
  112. const RULE * rules)
  113. {
  114. const RULE *r;
  115. int i;
  116. for (r = rules; r; r = r->next)
  117. for (i = r->lo; i <= r->hi; i++) {
  118. rec->table[i - rec->min] = r->new;
  119. if (r->new >= rec->min && r->new <= rec->max)
  120. is_default[r->new - rec->min] = 0;
  121. }
  122. }
  123. static void set_cats(struct Categories *cats, /* const */ int *is_default,
  124. /* const */ struct Reclass *rec)
  125. {
  126. struct Categories old_cats;
  127. int cats_read = 0;
  128. if (default_rule && default_to_itself)
  129. cats_read = (Rast_read_cats(rec->name, rec->mapset, &old_cats) >= 0);
  130. if (cats_read) {
  131. int i;
  132. for (i = 0; i < rec->num; i++)
  133. if (is_default[i]) {
  134. int x = i + rec->min;
  135. char *label = Rast_get_c_cat(&x, &old_cats);
  136. Rast_set_c_cat(&x, &x, label, cats);
  137. }
  138. }
  139. else if (default_rule)
  140. Rast_set_c_cat(&DEFAULT, &DEFAULT, default_label, cats);
  141. }
  142. static int _reclass( /* const */ RULE * rules, struct Categories *cats,
  143. struct Reclass *new)
  144. {
  145. int *is_default;
  146. init_reclass(new, rules);
  147. is_default = G_calloc(new->num, sizeof(int));
  148. init_table(new, is_default);
  149. fill_table(new, is_default, rules);
  150. set_cats(cats, is_default, new);
  151. return 0;
  152. }
  153. static int re_reclass( /* const */ RULE * rules, struct Categories *cats,
  154. /* const */ struct Reclass *old, struct Reclass *new,
  155. const char *input_name, const char *input_mapset)
  156. {
  157. struct Reclass mid;
  158. mid.name = G_store(input_name);
  159. mid.mapset = G_store(input_mapset);
  160. _reclass(rules, cats, &mid);
  161. compose(new, &mid, old);
  162. return 0;
  163. }
  164. int reclass(const char *old_name, const char *old_mapset,
  165. const char *new_name, RULE *rules, struct Categories *cats,
  166. const char *title)
  167. {
  168. struct Reclass old, new;
  169. struct History hist;
  170. int is_reclass;
  171. FILE *fd;
  172. char buf[GNAME_MAX + GMAPSET_MAX];
  173. is_reclass = Rast_get_reclass(old_name, old_mapset, &old);
  174. if (is_reclass < 0)
  175. G_fatal_error(_("Cannot read header file of <%s@%s>"), old_name,
  176. old_mapset);
  177. if (is_reclass) {
  178. new.name = G_store(old.name);
  179. new.mapset = G_store(old.mapset);
  180. re_reclass(rules, cats, &old, &new, old_name, old_mapset);
  181. }
  182. else {
  183. new.name = G_store(old_name);
  184. new.mapset = G_store(old_mapset);
  185. _reclass(rules, cats, &new);
  186. }
  187. if (G_find_file2("cell", new_name, G_mapset()) &&
  188. Rast_map_type(new_name, G_mapset()) != CELL_TYPE) {
  189. M_read_list(FALSE, NULL);
  190. if (M_do_remove(M_get_element("raster"), new_name) == 1)
  191. G_fatal_error(_("Cannot overwrite existing raster map <%s>"),
  192. new_name);
  193. }
  194. if (Rast_put_reclass(new_name, &new) < 0)
  195. G_fatal_error(_("Cannot create reclass file of <%s>"), new_name);
  196. if (!title) {
  197. G_snprintf(buf, sizeof(buf), "Reclass of %s in %s", new.name, new.mapset);
  198. title = buf;
  199. }
  200. if ((fd = G_fopen_new("cell", new_name)) == NULL)
  201. G_fatal_error(_("Cannot create raster map <%s>"), new_name);
  202. fprintf(fd, "Don't remove me\n");
  203. fclose(fd);
  204. Rast_set_cats_title(title, cats);
  205. Rast_write_cats(new_name, cats);
  206. Rast_free_cats(cats);
  207. Rast_short_history(new_name, "reclass", &hist);
  208. Rast_set_history(&hist, HIST_DATSRC_1, "Reclassified map based on:");
  209. Rast_format_history(&hist, HIST_DATSRC_2, " Map [%s] in mapset [%s]",
  210. new.name, new.mapset);
  211. Rast_command_history(&hist);
  212. Rast_write_history(new_name, &hist);
  213. new_range(new_name, &new);
  214. return 0;
  215. }