main.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /****************************************************************
  2. *
  3. * MODULE: v.random (based on s.rand)
  4. *
  5. * AUTHOR(S): James Darrell McCauley darrell@mccauley-usa.com
  6. * http://mccauley-usa.com/
  7. * OGR support by Martin Landa <landa.martin gmail.com>
  8. *
  9. * PURPOSE: Randomly generate a 2D/3D GRASS vector points map.
  10. *
  11. * Modification History:
  12. *
  13. * s.rand v 0.5B <25 Jun 1995> Copyright (c) 1993-1995. James Darrell McCauley
  14. * <?? ??? 1993> - began coding and released test version (jdm)
  15. * <10 Jan 1994> - changed RAND_MAX for rand(), since it is different for
  16. * SunOS 4.1.x and Solaris 2.3. stdlib.h in the latter defines
  17. * RAND_MAX, but it doesn't in the former. v0.2B (jdm)
  18. * <02 Jan 1995> - clean Gmakefile, man page. added html v0.3B (jdm)
  19. * <25 Feb 1995> - cleaned 'gcc -Wall' warnings (jdm)
  20. * <25 Jun 1995> - new site API (jdm)
  21. * <13 Sep 2000> - released under GPL
  22. *
  23. * COPYRIGHT: (C) 2003-2010 by the GRASS Development Team
  24. *
  25. * This program is free software under the GNU General
  26. * Public License (>=v2). Read the file COPYING that
  27. * comes with GRASS for details.
  28. *
  29. **************************************************************/
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #include <sys/types.h>
  33. #include <unistd.h>
  34. #include <string.h>
  35. #include <grass/gis.h>
  36. #include <grass/vector.h>
  37. #include <grass/dbmi.h>
  38. #include <grass/glocale.h>
  39. #ifndef RAND_MAX
  40. #define RAND_MAX (pow(2.0,31.0)-1)
  41. #endif
  42. double myrand(void);
  43. #if defined(__CYGWIN__) || defined(__APPLE__) || defined(__MINGW32__)
  44. double drand48()
  45. {
  46. return (rand() / 32767.0);
  47. }
  48. #define srand48(sv) (srand((unsigned)(sv)))
  49. #endif
  50. int main(int argc, char *argv[])
  51. {
  52. char *output, buf[2000];
  53. double (*rng) ();
  54. double max, zmin, zmax;
  55. int seed;
  56. int i, n, b, type, usefloat;
  57. struct Map_info Out;
  58. struct line_pnts *Points;
  59. struct line_cats *Cats;
  60. struct Cell_head window;
  61. struct GModule *module;
  62. struct
  63. {
  64. struct Option *output, *nsites, *zmin, *zmax, *zcol, *ztype, *seed;
  65. } parm;
  66. struct
  67. {
  68. struct Flag *rand, *drand48, *z, *notopo;
  69. } flag;
  70. struct field_info *Fi;
  71. dbDriver *driver;
  72. dbTable *table;
  73. dbString sql;
  74. G_gisinit(argv[0]);
  75. module = G_define_module();
  76. G_add_keyword(_("vector"));
  77. G_add_keyword(_("statistics"));
  78. G_add_keyword(_("random"));
  79. module->description = _("Generates randomly 2D/3D vector points map.");
  80. parm.output = G_define_standard_option(G_OPT_V_OUTPUT);
  81. parm.nsites = G_define_option();
  82. parm.nsites->key = "n";
  83. parm.nsites->type = TYPE_INTEGER;
  84. parm.nsites->required = YES;
  85. parm.nsites->description = _("Number of points to be created");
  86. parm.zmin = G_define_option();
  87. parm.zmin->key = "zmin";
  88. parm.zmin->type = TYPE_DOUBLE;
  89. parm.zmin->required = NO;
  90. parm.zmin->description =
  91. _("Minimum z height (needs -z flag or column name)");
  92. parm.zmin->answer = "0.0";
  93. parm.zmin->guisection = _("3D output");
  94. parm.zmax = G_define_option();
  95. parm.zmax->key = "zmax";
  96. parm.zmax->type = TYPE_DOUBLE;
  97. parm.zmax->required = NO;
  98. parm.zmax->description =
  99. _("Maximum z height (needs -z flag or column name)");
  100. parm.zmax->answer = "0.0";
  101. parm.zmax->guisection = _("3D output");
  102. parm.seed = G_define_option();
  103. parm.seed->key = "seed";
  104. parm.seed->type = TYPE_INTEGER;
  105. parm.seed->required = NO;
  106. parm.seed->description =
  107. _("The seed to initialize the random generator. If not set the process id is used.");
  108. parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
  109. parm.zcol->label = _("Name of column for z values");
  110. parm.zcol->description =
  111. _("Writes z values to column");
  112. parm.zcol->guisection = _("3D output");
  113. parm.ztype = G_define_option();
  114. parm.ztype->key = "column_type";
  115. parm.ztype->type = TYPE_STRING;
  116. parm.ztype->required = NO;
  117. parm.ztype->multiple = NO;
  118. parm.ztype->description = _("Type of column for z values");
  119. parm.ztype->options = "integer,double precision";
  120. parm.ztype->answer = "double precision";
  121. parm.ztype->guisection = _("3D output");
  122. flag.z = G_define_flag();
  123. flag.z->key = 'z';
  124. flag.z->description = _("Create 3D output");
  125. flag.z->guisection = _("3D output");
  126. flag.drand48 = G_define_flag();
  127. flag.drand48->key = 'd';
  128. flag.drand48->description = _("Use drand48() function instead of rand()");
  129. flag.notopo = G_define_flag();
  130. flag.notopo->key = 'b';
  131. flag.notopo->description = _("Do not build topology");
  132. if (G_parser(argc, argv))
  133. exit(EXIT_FAILURE);
  134. output = parm.output->answer;
  135. n = atoi(parm.nsites->answer);
  136. b = (flag.drand48->answer == '\0') ? 0 : 1;
  137. if(parm.seed->answer)
  138. seed = atoi(parm.seed->answer);
  139. if (n <= 0) {
  140. G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
  141. }
  142. /* create new vector map */
  143. Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z);
  144. /* Do we need to write random values into attribute table? */
  145. if (parm.zcol->answer) {
  146. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  147. driver =
  148. db_start_driver_open_database(Fi->driver,
  149. Vect_subst_var(Fi->database, &Out));
  150. if (driver == NULL) {
  151. Vect_delete(parm.output->answer);
  152. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  153. Vect_subst_var(Fi->database, &Out), Fi->driver);
  154. }
  155. db_begin_transaction(driver);
  156. db_init_string(&sql);
  157. sprintf(buf, "create table %s (cat integer, %s %s)", Fi->table,
  158. parm.zcol->answer, parm.ztype->answer);
  159. db_set_string(&sql, buf);
  160. Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  161. Fi->driver);
  162. /* Create table */
  163. G_debug(3, db_get_string(&sql));
  164. if (db_execute_immediate(driver, &sql) != DB_OK) {
  165. db_close_database(driver);
  166. db_shutdown_driver(driver);
  167. Vect_delete(parm.output->answer);
  168. G_fatal_error(_("Unable to create table: %s"),
  169. db_get_string(&sql));
  170. }
  171. /* Grant */
  172. if (db_grant_on_table
  173. (driver, Fi->table, DB_PRIV_SELECT,
  174. DB_GROUP | DB_PUBLIC) != DB_OK) {
  175. db_close_database(driver);
  176. db_shutdown_driver(driver);
  177. Vect_delete(parm.output->answer);
  178. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  179. Fi->table);
  180. }
  181. /* OK. Let's check what type of column user has created */
  182. db_set_string(&sql, Fi->table);
  183. if (db_describe_table(driver, &sql, &table) != DB_OK) {
  184. db_close_database(driver);
  185. db_shutdown_driver(driver);
  186. Vect_delete(parm.output->answer);
  187. G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
  188. }
  189. if (db_get_table_number_of_columns(table) != 2) {
  190. db_close_database(driver);
  191. db_shutdown_driver(driver);
  192. Vect_delete(parm.output->answer);
  193. G_fatal_error(_("Table should contain only two columns"));
  194. }
  195. type = db_get_column_sqltype(db_get_table_column(table, 1));
  196. usefloat = -1;
  197. if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
  198. usefloat = 0;
  199. if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
  200. usefloat = 1;
  201. if (usefloat < 0) {
  202. db_close_database(driver);
  203. db_shutdown_driver(driver);
  204. Vect_delete(parm.output->answer);
  205. G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
  206. " and DOUBLE PRECISION column types."));
  207. }
  208. }
  209. Vect_hist_command(&Out);
  210. if (b) {
  211. rng = drand48;
  212. max = 1.0;
  213. /* Init the random seed */
  214. if(parm.seed->answer)
  215. srand48((long)seed);
  216. else
  217. srand48((long)getpid());
  218. }
  219. else { /* default is rand() */
  220. rng = myrand;
  221. max = RAND_MAX;
  222. /* Init the random seed */
  223. if(parm.seed->answer)
  224. srand(seed);
  225. else
  226. srand(getpid());
  227. }
  228. G_get_window(&window);
  229. if (flag.z->answer || parm.zcol->answer) {
  230. zmax = atof(parm.zmax->answer);
  231. zmin = atof(parm.zmin->answer);
  232. }
  233. Points = Vect_new_line_struct();
  234. Cats = Vect_new_cats_struct();
  235. G_message(_("Generating points..."));
  236. for (i = 0; i < n; ++i) {
  237. double x, y, z;
  238. G_percent(i, n, 5);
  239. Vect_reset_line(Points);
  240. Vect_reset_cats(Cats);
  241. x = rng() / max * (window.west - window.east) + window.east;
  242. y = rng() / max * (window.north - window.south) + window.south;
  243. z = rng() / max * (zmax - zmin) + zmin;
  244. if (flag.z->answer)
  245. Vect_append_point(Points, x, y, z);
  246. else
  247. Vect_append_point(Points, x, y, 0.0);
  248. if (parm.zcol->answer) {
  249. sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
  250. db_set_string(&sql, buf);
  251. /* Round random value if column is integer type */
  252. if (usefloat)
  253. sprintf(buf, "%f )", z);
  254. else
  255. sprintf(buf, "%.0f )", z);
  256. db_append_string(&sql, buf);
  257. G_debug(3, db_get_string(&sql));
  258. if (db_execute_immediate(driver, &sql) != DB_OK) {
  259. db_close_database(driver);
  260. db_shutdown_driver(driver);
  261. Vect_delete(parm.output->answer);
  262. G_fatal_error(_("Cannot insert new row: %s"),
  263. db_get_string(&sql));
  264. }
  265. }
  266. Vect_cat_set(Cats, 1, i + 1);
  267. Vect_write_line(&Out, GV_POINT, Points, Cats);
  268. }
  269. G_percent(1, 1, 1);
  270. if (parm.zcol->answer) {
  271. db_commit_transaction(driver);
  272. db_close_database_shutdown_driver(driver);
  273. }
  274. if (!flag.notopo->answer) {
  275. Vect_build(&Out);
  276. }
  277. Vect_close(&Out);
  278. exit(EXIT_SUCCESS);
  279. }
  280. double myrand()
  281. {
  282. return (double)rand();
  283. }