main.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. const char *names[NFILES];
  28. struct Categories labels[NFILES];
  29. RECLASS *reclass;
  30. CELL *table;
  31. static int cmp(const void *, const void *);
  32. int main(int argc, char *argv[])
  33. {
  34. int fd[NFILES];
  35. int outfd;
  36. int i;
  37. const char *name;
  38. const char *output;
  39. const char *mapset;
  40. int non_zero;
  41. struct Range range;
  42. CELL ncats, max_cats;
  43. int primary;
  44. struct Categories pcats;
  45. struct Colors pcolr;
  46. char buf[1024];
  47. CELL result;
  48. struct GModule *module;
  49. struct
  50. {
  51. struct Option *input, *output;
  52. } parm;
  53. struct
  54. {
  55. struct Flag *z;
  56. } flag;
  57. G_gisinit(argv[0]);
  58. /* Define the different options */
  59. module = G_define_module();
  60. G_add_keyword(_("raster"));
  61. G_add_keyword(_("statistics"));
  62. module->description =
  63. _("Creates a cross product of the category values from "
  64. "multiple raster map layers.");
  65. parm.input = G_define_option();
  66. parm.input->key = "input";
  67. parm.input->type = TYPE_STRING;
  68. parm.input->required = YES;
  69. parm.input->multiple = YES;
  70. parm.input->gisprompt = "old,cell,raster";
  71. sprintf(buf, _("Names of 2-%d input raster maps"), NFILES);
  72. parm.input->description = G_store(buf);
  73. parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
  74. /* Define the different flags */
  75. flag.z = G_define_flag();
  76. flag.z->key = 'z';
  77. flag.z->description = _("Non-zero data only");
  78. if (G_parser(argc, argv))
  79. exit(EXIT_FAILURE);
  80. nrows = Rast_window_rows();
  81. ncols = Rast_window_cols();
  82. nfiles = 0;
  83. non_zero = flag.z->answer;
  84. for (nfiles = 0; (name = parm.input->answers[nfiles]); nfiles++) {
  85. if (nfiles >= NFILES)
  86. G_fatal_error(_("More than %d files not allowed"), NFILES);
  87. mapset = G_find_raster2(name, "");
  88. if (!mapset)
  89. G_fatal_error(_("Raster map <%s> not found"), name);
  90. names[nfiles] = name;
  91. fd[nfiles] = Rast_open_old(name, mapset);
  92. Rast_read_range(name, mapset, &range);
  93. ncats = range.max - range.min;
  94. if (nfiles == 0 || ncats > max_cats) {
  95. primary = nfiles;
  96. max_cats = ncats;
  97. }
  98. }
  99. if (nfiles <= 1)
  100. G_fatal_error(_("Must specify 2 or more input maps"));
  101. output = parm.output->answer;
  102. outfd = Rast_open_c_new(output);
  103. sprintf(buf, "Cross of %s", names[0]);
  104. for (i = 1; i < nfiles - 1; i++) {
  105. strcat(buf, ", ");
  106. strcat(buf, names[i]);
  107. }
  108. strcat(buf, " and ");
  109. strcat(buf, names[i]);
  110. Rast_init_cats(buf, &pcats);
  111. /* first step is cross product, but un-ordered */
  112. result = cross(fd, non_zero, primary, outfd);
  113. /* print message STEP mesage */
  114. G_message(_("%s: STEP 2 ..."), G_program_name());
  115. /* now close all files */
  116. for (i = 0; i < nfiles; i++)
  117. Rast_close(fd[i]);
  118. Rast_close(outfd);
  119. if (result <= 0)
  120. exit(0);
  121. /* build the renumbering/reclass and the new cats file */
  122. qsort(reclass, result + 1, sizeof(RECLASS), cmp);
  123. table = (CELL *) G_calloc(result + 1, sizeof(CELL));
  124. for (i = 0; i < nfiles; i++) {
  125. mapset = G_find_raster2(names[i], "");
  126. Rast_read_cats(names[i], mapset, &labels[i]);
  127. }
  128. for (ncats = 0; ncats <= result; ncats++) {
  129. table[reclass[ncats].result] = ncats;
  130. set_cat(ncats, reclass[ncats].cat, &pcats);
  131. }
  132. for (i = 0; i < nfiles; i++)
  133. Rast_free_cats(&labels[i]);
  134. /* reopen the output cell for reading and for writing */
  135. fd[0] = Rast_open_old(output, G_mapset());
  136. outfd = Rast_open_c_new(output);
  137. renumber(fd[0], outfd);
  138. G_message(_("Creating support files for <%s>..."), output);
  139. Rast_close(fd[0]);
  140. Rast_close(outfd);
  141. Rast_write_cats(output, &pcats);
  142. Rast_free_cats(&pcats);
  143. if (result > 0) {
  144. Rast_make_random_colors(&pcolr, (CELL) 1, result);
  145. Rast_write_colors(output, G_mapset(), &pcolr);
  146. }
  147. G_message(_("%ld categories"), (long)result);
  148. exit(EXIT_SUCCESS);
  149. }
  150. static int cmp(const void *aa, const void *bb)
  151. {
  152. const RECLASS *a = aa, *b = bb;
  153. int i;
  154. for (i = 0; i < (nfiles + 2); i++) {
  155. if (a->cat[i] < b->cat[i])
  156. return -1;
  157. if (a->cat[i] > b->cat[i])
  158. return 1;
  159. }
  160. return 0;
  161. }