main.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /****************************************************************************
  2. *
  3. * MODULE: v.perturb
  4. * AUTHOR(S): James Darrell McCauley darrell@mccauley-usa.com
  5. * http://mccauley-usa.com/
  6. * PURPOSE: Random location perturbations of vector points
  7. *
  8. * COPYRIGHT: (C) 1994-2009 by James Darrell McCauley and the GRASS Development Team
  9. *
  10. * Modification History:
  11. * 3/2006 added min and seed MN/SM ITC-irst
  12. * 2005 updated to GRASS 6 RB ITC-irst
  13. * 0.1B <18 Feb 1994> first version (jdm)
  14. * 0.2B <02 Jan 1995> clean man page, added html page (jdm)
  15. * 0.3B <25 Feb 1995> cleaned up 'gcc -Wall' warnings (jdm)
  16. * <13 Sept 2000> released under GPL
  17. *
  18. * This program is free software under the GNU General
  19. * Public License (>=v2). Read the file COPYING that
  20. * comes with GRASS for details.
  21. *
  22. *****************************************************************************/
  23. #include <stdlib.h>
  24. #include <math.h>
  25. #include <grass/gis.h>
  26. #include <grass/dbmi.h>
  27. #include <grass/vector.h>
  28. #include <grass/glocale.h>
  29. #include "perturb.h"
  30. #include "zufall.h"
  31. int main(int argc, char **argv)
  32. {
  33. double p1, p2, numbers[1000], numbers2[1000];
  34. int (*rng) ();
  35. int i;
  36. int line, nlines, ttype, n, ret, seed, field;
  37. struct field_info *Fi, *Fin;
  38. double min = 0.;
  39. int debuglevel = 3;
  40. struct Map_info In, Out;
  41. struct line_pnts *Points;
  42. struct line_cats *Cats;
  43. struct Cell_head window;
  44. struct GModule *module;
  45. struct
  46. {
  47. struct Option *in, *out, *dist, *pars, *min, *seed, *field;
  48. struct Flag *no_topo;
  49. } parm;
  50. G_gisinit(argv[0]);
  51. module = G_define_module();
  52. G_add_keyword(_("vector"));
  53. G_add_keyword(_("geometry"));
  54. G_add_keyword(_("statistics"));
  55. G_add_keyword(_("random"));
  56. G_add_keyword(_("point pattern"));
  57. G_add_keyword(_("level1"));
  58. module->description =
  59. _("Random location perturbations of vector points.");
  60. parm.in = G_define_standard_option(G_OPT_V_INPUT);
  61. parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
  62. parm.out = G_define_standard_option(G_OPT_V_OUTPUT);
  63. parm.dist = G_define_option();
  64. parm.dist->key = "distribution";
  65. parm.dist->type = TYPE_STRING;
  66. parm.dist->required = NO;
  67. parm.dist->options = "uniform,normal";
  68. parm.dist->answer = "uniform";
  69. parm.dist->description = _("Distribution of perturbation");
  70. parm.pars = G_define_option();
  71. parm.pars->key = "parameters";
  72. parm.pars->type = TYPE_DOUBLE;
  73. parm.pars->required = YES;
  74. parm.pars->multiple = YES;
  75. parm.pars->label = _("Parameter(s) of distribution");
  76. parm.pars->description = _("If the distribution "
  77. "is uniform, only one parameter, the maximum, is needed. "
  78. "For a normal distribution, two parameters, the mean and "
  79. "standard deviation, are required.");
  80. parm.min = G_define_option();
  81. parm.min->key = "minimum";
  82. parm.min->type = TYPE_DOUBLE;
  83. parm.min->required = NO;
  84. parm.min->answer = "0.0";
  85. parm.min->description = _("Minimum deviation in map units");
  86. parm.seed = G_define_option();
  87. parm.seed->key = "seed";
  88. parm.seed->type = TYPE_INTEGER;
  89. parm.seed->required = NO;
  90. parm.seed->answer = "0";
  91. parm.seed->description = _("Seed for random number generation");
  92. parm.no_topo = G_define_standard_flag(G_FLG_V_TOPO);
  93. if (G_parser(argc, argv))
  94. exit(EXIT_FAILURE);
  95. min = atof(parm.min->answer);
  96. seed = atoi(parm.seed->answer);
  97. switch (parm.dist->answer[0]) {
  98. case 'u':
  99. rng = zufall;
  100. break;
  101. case 'n':
  102. rng = normalen;
  103. break;
  104. }
  105. if (rng == zufall) {
  106. i = sscanf(parm.pars->answer, "%lf", &p1);
  107. if (i != 1) {
  108. G_fatal_error(_("Error scanning arguments"));
  109. }
  110. else if (p1 <= 0)
  111. G_fatal_error(_("Maximum of uniform distribution must be >= zero"));
  112. }
  113. else {
  114. if ((i = sscanf(parm.pars->answer, "%lf,%lf", &p1, &p2)) != 2) {
  115. G_fatal_error(_("Error scanning arguments"));
  116. }
  117. if (p2 <= 0)
  118. G_fatal_error(_("Standard deviation of normal distribution must be >= zero"));
  119. }
  120. G_get_window(&window);
  121. /* Open input */
  122. Vect_set_open_level(2);
  123. if (Vect_open_old_head2(&In, parm.in->answer, "", parm.field->answer) < 0)
  124. G_fatal_error(_("Unable to open vector map <%s>"), parm.in->answer);
  125. field = Vect_get_field_number(&In, parm.field->answer);
  126. /* Open output */
  127. if (Vect_open_new(&Out, parm.out->answer, WITHOUT_Z) < 0) /* TODO add z support ? */
  128. G_fatal_error(_("Unable to create vector map <%s>"), parm.out->answer);
  129. Vect_hist_copy(&In, &Out);
  130. Vect_hist_command(&Out);
  131. /* Generate a bunch of random numbers */
  132. zufalli(&seed);
  133. myrng(numbers, 1000, rng, p1 - min, p2);
  134. myrng(numbers2, 1000, rng, p1, p2);
  135. Points = Vect_new_line_struct();
  136. Cats = Vect_new_cats_struct();
  137. nlines = Vect_get_num_lines(&In);
  138. /* Close input, re-open on level 1 */
  139. Vect_close(&In);
  140. Vect_set_open_level(1);
  141. if (Vect_open_old2(&In, parm.in->answer, "", parm.field->answer) < 0)
  142. G_fatal_error(_("Unable to open vector map <%s>"), parm.in->answer);
  143. i = 0;
  144. line = 0;
  145. while (1) {
  146. int type = Vect_read_next_line(&In, Points, Cats);
  147. /* Note: check for dead lines is not needed, because they are skipped by V1_read_next_line_nat() */
  148. if (type == -1) {
  149. G_fatal_error(_("Unable to read vector map"));
  150. }
  151. else if (type == -2) {
  152. break;
  153. }
  154. G_percent(line++, nlines, 4);
  155. if (type & GV_POINT) {
  156. if (field != -1 && !Vect_cat_get(Cats, field, NULL))
  157. continue;
  158. if (i >= 800) {
  159. /* Generate some more random numbers */
  160. myrng(numbers, 1000, rng, p1 - min, p2);
  161. myrng(numbers2, 1000, rng, p1, p2);
  162. i = 0;
  163. }
  164. G_debug(debuglevel, "x: %f y: %f", Points->x[0],
  165. Points->y[0]);
  166. /* perturb */
  167. /* TODO: tends to concentrate in box corners when min is used */
  168. if (numbers2[i] >= 0) {
  169. if (numbers[i] >= 0) {
  170. G_debug(debuglevel, "deltax: %f", numbers[i] + min);
  171. Points->x[0] += numbers[i++] + min;
  172. }
  173. else {
  174. G_debug(debuglevel, "deltax: %f", numbers[i] - min);
  175. Points->x[0] += numbers[i++] - min;
  176. }
  177. Points->y[0] += numbers2[i++];
  178. }
  179. else {
  180. if (numbers[i] >= 0) {
  181. G_debug(debuglevel, "deltay: %f", numbers[i] + min);
  182. Points->y[0] += numbers[i++] + min;
  183. }
  184. else {
  185. G_debug(debuglevel, "deltay: %f", numbers[i] - min);
  186. Points->y[0] += numbers[i++] - min;
  187. }
  188. Points->x[0] += numbers2[i++];
  189. }
  190. G_debug(debuglevel, "x_pert: %f y_pert: %f", Points->x[0],
  191. Points->y[0]);
  192. }
  193. Vect_write_line(&Out, type, Points, Cats);
  194. }
  195. G_percent(1, 1, 1);
  196. /* Copy tables */
  197. n = Vect_get_num_dblinks(&In);
  198. ttype = GV_1TABLE;
  199. if (n > 1)
  200. ttype = GV_MTABLE;
  201. for (i = 0; i < n; i++) {
  202. Fi = Vect_get_dblink(&In, i);
  203. if (Fi == NULL) {
  204. G_fatal_error(_("Cannot get db link info"));
  205. }
  206. Fin = Vect_default_field_info(&Out, Fi->number, Fi->name, ttype);
  207. Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fin->table, Fi->key,
  208. Fin->database, Fin->driver);
  209. ret = db_copy_table(Fi->driver, Fi->database, Fi->table,
  210. Fin->driver, Vect_subst_var(Fin->database, &Out),
  211. Fin->table);
  212. if (ret == DB_FAILED) {
  213. G_warning("Cannot copy table");
  214. }
  215. }
  216. Vect_close(&In);
  217. if (!parm.no_topo->answer)
  218. Vect_build(&Out);
  219. Vect_close(&Out);
  220. return (EXIT_SUCCESS);
  221. }