main.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /****************************************************************************
  2. *
  3. * MODULE: r.cross
  4. *
  5. * AUTHOR(S): Michael Shapiro - CERL
  6. *
  7. * PURPOSE: Creates a cross product of the category values from
  8. * multiple raster map layers.
  9. *
  10. * COPYRIGHT: (C) 2006 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. ***************************************************************************/
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include "glob.h"
  21. #include "local_proto.h"
  22. #include <grass/raster.h>
  23. #include <grass/glocale.h>
  24. int nfiles;
  25. int nrows;
  26. int ncols;
  27. int NCATS = 1 << SHIFT;
  28. const char *names[NFILES];
  29. struct Categories labels[NFILES];
  30. NODE *tree; /* tree of values */
  31. int tlen; /* allocate tree size */
  32. int N; /* number of actual nodes in tree */
  33. RECLASS *reclass;
  34. CELL *table;
  35. static int cmp(const void *, const void *);
  36. int main(int argc, char *argv[])
  37. {
  38. int fd[NFILES];
  39. int outfd;
  40. int i;
  41. const char *name;
  42. const char *output;
  43. const char *mapset;
  44. int non_zero;
  45. struct Range range;
  46. CELL ncats, max_cats;
  47. int primary;
  48. struct Categories pcats;
  49. struct Colors pcolr;
  50. char buf[1024];
  51. CELL result;
  52. struct GModule *module;
  53. struct
  54. {
  55. struct Option *input, *output;
  56. } parm;
  57. struct
  58. {
  59. struct Flag *z;
  60. } flag;
  61. G_gisinit(argv[0]);
  62. /* Define the different options */
  63. module = G_define_module();
  64. G_add_keyword(_("raster"));
  65. module->description =
  66. _("Creates a cross product of the category values from "
  67. "multiple raster map layers.");
  68. parm.input = G_define_option();
  69. parm.input->key = "input";
  70. parm.input->type = TYPE_STRING;
  71. parm.input->required = YES;
  72. parm.input->multiple = YES;
  73. parm.input->gisprompt = "old,cell,raster";
  74. sprintf(buf, _("Names of 2-%d input raster maps"), NFILES);
  75. parm.input->description = G_store(buf);
  76. parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
  77. /* Define the different flags */
  78. flag.z = G_define_flag();
  79. flag.z->key = 'z';
  80. flag.z->description = _("Non-zero data only");
  81. if (G_parser(argc, argv))
  82. exit(EXIT_FAILURE);
  83. nrows = G_window_rows();
  84. ncols = G_window_cols();
  85. nfiles = 0;
  86. non_zero = flag.z->answer;
  87. for (nfiles = 0; (name = parm.input->answers[nfiles]); nfiles++) {
  88. if (nfiles >= NFILES)
  89. G_fatal_error(_("More than %d files not allowed"), NFILES);
  90. mapset = G_find_raster2(name, "");
  91. if (!mapset)
  92. G_fatal_error(_("Raster map <%s> not found"), name);
  93. names[nfiles] = name;
  94. fd[nfiles] = Rast_open_old(name, mapset);
  95. if (fd[nfiles] < 0)
  96. G_fatal_error(_("Unable to open raster map <%s>"), name);
  97. Rast_read_range(name, mapset, &range);
  98. ncats = range.max - range.min;
  99. if (nfiles == 0 || ncats > max_cats) {
  100. primary = nfiles;
  101. max_cats = ncats;
  102. }
  103. }
  104. if (nfiles <= 1)
  105. G_fatal_error(_("Must specify 2 or more input maps"));
  106. output = parm.output->answer;
  107. outfd = Rast_open_c_new(output);
  108. if (outfd < 0)
  109. G_fatal_error(_("Unable to create raster map <%s>"),
  110. parm.output->answer);
  111. sprintf(buf, "Cross of %s", names[0]);
  112. for (i = 1; i < nfiles - 1; i++) {
  113. strcat(buf, ", ");
  114. strcat(buf, names[i]);
  115. }
  116. strcat(buf, " and ");
  117. strcat(buf, names[i]);
  118. Rast_init_cats(buf, &pcats);
  119. /* first step is cross product, but un-ordered */
  120. result = cross(fd, non_zero, primary, outfd);
  121. /* print message STEP mesage */
  122. G_message(_("%s: STEP 2 ..."), G_program_name());
  123. /* now close all files */
  124. for (i = 0; i < nfiles; i++)
  125. Rast_close(fd[i]);
  126. Rast_close(outfd);
  127. if (result <= 0)
  128. exit(0);
  129. /* build the renumbering/reclass and the new cats file */
  130. qsort(reclass, result + 1, sizeof(RECLASS), cmp);
  131. table = (CELL *) G_calloc(result + 1, sizeof(CELL));
  132. for (i = 0; i < nfiles; i++) {
  133. mapset = G_find_raster2(names[i], "");
  134. Rast_read_cats(names[i], mapset, &labels[i]);
  135. }
  136. for (ncats = 0; ncats <= result; ncats++) {
  137. table[reclass[ncats].result] = ncats;
  138. set_cat(ncats, reclass[ncats].cat, &pcats);
  139. }
  140. for (i = 0; i < nfiles; i++)
  141. Rast_free_cats(&labels[i]);
  142. /* reopen the output cell for reading and for writing */
  143. fd[0] = Rast_open_old(output, G_mapset());
  144. outfd = Rast_open_c_new(output);
  145. renumber(fd[0], outfd);
  146. G_message(_("Creating support files for <%s>..."), output);
  147. Rast_close(fd[0]);
  148. Rast_close(outfd);
  149. Rast_write_cats(output, &pcats);
  150. Rast_free_cats(&pcats);
  151. if (result > 0) {
  152. Rast_make_random_colors(&pcolr, (CELL) 1, result);
  153. Rast_write_colors(output, G_mapset(), &pcolr);
  154. }
  155. G_message(_("%ld categories"), (long)result);
  156. exit(EXIT_SUCCESS);
  157. }
  158. static int cmp(const void *aa, const void *bb)
  159. {
  160. const RECLASS *a = aa, *b = bb;
  161. int i;
  162. for (i = 0; i < (nfiles + 2); i++) {
  163. if (a->cat[i] < b->cat[i])
  164. return -1;
  165. if (a->cat[i] > b->cat[i])
  166. return 1;
  167. }
  168. return 0;
  169. }