main.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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 i, n, b, type, usefloat;
  56. struct Map_info Out;
  57. struct line_pnts *Points;
  58. struct line_cats *Cats;
  59. struct Cell_head window;
  60. struct GModule *module;
  61. struct
  62. {
  63. struct Option *output, *nsites, *zmin, *zmax, *zcol, *ztype;
  64. } parm;
  65. struct
  66. {
  67. struct Flag *rand, *drand48, *z, *notopo;
  68. } flag;
  69. struct field_info *Fi;
  70. dbDriver *driver;
  71. dbTable *table;
  72. dbString sql;
  73. G_gisinit(argv[0]);
  74. module = G_define_module();
  75. G_add_keyword(_("vector"));
  76. G_add_keyword(_("statistics"));
  77. G_add_keyword(_("random"));
  78. module->description = _("Generates randomly 2D/3D vector points map.");
  79. parm.output = G_define_standard_option(G_OPT_V_OUTPUT);
  80. parm.nsites = G_define_option();
  81. parm.nsites->key = "n";
  82. parm.nsites->type = TYPE_INTEGER;
  83. parm.nsites->required = YES;
  84. parm.nsites->description = _("Number of points to be created");
  85. parm.zmin = G_define_option();
  86. parm.zmin->key = "zmin";
  87. parm.zmin->type = TYPE_DOUBLE;
  88. parm.zmin->required = NO;
  89. parm.zmin->description =
  90. _("Minimum z height (needs -z flag or column name)");
  91. parm.zmin->answer = "0.0";
  92. parm.zmin->guisection = _("3D output");
  93. parm.zmax = G_define_option();
  94. parm.zmax->key = "zmax";
  95. parm.zmax->type = TYPE_DOUBLE;
  96. parm.zmax->required = NO;
  97. parm.zmax->description =
  98. _("Maximum z height (needs -z flag or column name)");
  99. parm.zmax->answer = "0.0";
  100. parm.zmax->guisection = _("3D output");
  101. parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
  102. parm.zcol->label = _("Name of column for z values");
  103. parm.zcol->description =
  104. _("Writes z values to column instead of 3D vector");
  105. parm.zcol->guisection = _("3D output");
  106. parm.ztype = G_define_option();
  107. parm.ztype->key = "column_type";
  108. parm.ztype->type = TYPE_STRING;
  109. parm.ztype->required = NO;
  110. parm.ztype->multiple = NO;
  111. parm.ztype->description = _("Type of column for z values");
  112. parm.ztype->options = "integer,double precision";
  113. parm.ztype->answer = "double precision";
  114. parm.ztype->guisection = _("3D output");
  115. flag.z = G_define_flag();
  116. flag.z->key = 'z';
  117. flag.z->description = _("Create 3D output");
  118. flag.z->guisection = _("3D output");
  119. flag.drand48 = G_define_flag();
  120. flag.drand48->key = 'd';
  121. flag.drand48->description = _("Use drand48() function instead of rand()");
  122. flag.notopo = G_define_flag();
  123. flag.notopo->key = 'b';
  124. flag.notopo->description = _("Do not build topology");
  125. if (G_parser(argc, argv))
  126. exit(EXIT_FAILURE);
  127. if (flag.z->answer && parm.zcol->answer) {
  128. G_fatal_error(_("Unable to create 3D vector and attribute table at same time"));
  129. }
  130. output = parm.output->answer;
  131. n = atoi(parm.nsites->answer);
  132. b = (flag.drand48->answer == '\0') ? 0 : 1;
  133. if (n <= 0) {
  134. G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
  135. }
  136. /* create new vector map */
  137. Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z);
  138. /* Do we need to write random values into attribute table? */
  139. if (parm.zcol->answer) {
  140. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  141. driver =
  142. db_start_driver_open_database(Fi->driver,
  143. Vect_subst_var(Fi->database, &Out));
  144. if (driver == NULL) {
  145. Vect_delete(parm.output->answer);
  146. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  147. Vect_subst_var(Fi->database, &Out), Fi->driver);
  148. }
  149. db_begin_transaction(driver);
  150. db_init_string(&sql);
  151. sprintf(buf, "create table %s (cat integer, %s %s)", Fi->table,
  152. parm.zcol->answer, parm.ztype->answer);
  153. db_set_string(&sql, buf);
  154. Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
  155. Fi->driver);
  156. /* Create table */
  157. G_debug(3, db_get_string(&sql));
  158. if (db_execute_immediate(driver, &sql) != DB_OK) {
  159. db_close_database(driver);
  160. db_shutdown_driver(driver);
  161. Vect_delete(parm.output->answer);
  162. G_fatal_error(_("Unable to create table: %s"),
  163. db_get_string(&sql));
  164. }
  165. /* Grant */
  166. if (db_grant_on_table
  167. (driver, Fi->table, DB_PRIV_SELECT,
  168. DB_GROUP | DB_PUBLIC) != DB_OK) {
  169. db_close_database(driver);
  170. db_shutdown_driver(driver);
  171. Vect_delete(parm.output->answer);
  172. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  173. Fi->table);
  174. }
  175. /* OK. Let's check what type of column user has created */
  176. db_set_string(&sql, Fi->table);
  177. if (db_describe_table(driver, &sql, &table) != DB_OK) {
  178. db_close_database(driver);
  179. db_shutdown_driver(driver);
  180. Vect_delete(parm.output->answer);
  181. G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
  182. }
  183. if (db_get_table_number_of_columns(table) != 2) {
  184. db_close_database(driver);
  185. db_shutdown_driver(driver);
  186. Vect_delete(parm.output->answer);
  187. G_fatal_error(_("Table should contain only two columns"));
  188. }
  189. type = db_get_column_sqltype(db_get_table_column(table, 1));
  190. usefloat = -1;
  191. if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
  192. usefloat = 0;
  193. if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
  194. usefloat = 1;
  195. if (usefloat < 0) {
  196. db_close_database(driver);
  197. db_shutdown_driver(driver);
  198. Vect_delete(parm.output->answer);
  199. G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
  200. " and DOUBLE PRECISION column types."));
  201. }
  202. }
  203. Vect_hist_command(&Out);
  204. if (b) {
  205. rng = drand48;
  206. max = 1.0;
  207. srand48((long)getpid());
  208. }
  209. else { /* default is rand() */
  210. rng = myrand;
  211. max = RAND_MAX;
  212. srand(getpid());
  213. }
  214. G_get_window(&window);
  215. if (flag.z->answer || parm.zcol->answer) {
  216. zmax = atof(parm.zmax->answer);
  217. zmin = atof(parm.zmin->answer);
  218. }
  219. Points = Vect_new_line_struct();
  220. Cats = Vect_new_cats_struct();
  221. G_message(_("Generating points..."));
  222. for (i = 0; i < n; ++i) {
  223. double x, y, z;
  224. G_percent(i, n, 5);
  225. Vect_reset_line(Points);
  226. Vect_reset_cats(Cats);
  227. x = rng() / max * (window.west - window.east) + window.east;
  228. y = rng() / max * (window.north - window.south) + window.south;
  229. if (flag.z->answer) {
  230. z = rng() / max * (zmax - zmin) + zmin;
  231. Vect_append_point(Points, x, y, z);
  232. }
  233. else
  234. Vect_append_point(Points, x, y, 0.0);
  235. if (parm.zcol->answer) {
  236. z = rng() / max * (zmax - zmin) + zmin;
  237. sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
  238. db_set_string(&sql, buf);
  239. /* Round random value if column is integer type */
  240. if (usefloat)
  241. sprintf(buf, "%f )", z);
  242. else
  243. sprintf(buf, "%.0f )", z);
  244. db_append_string(&sql, buf);
  245. G_debug(3, db_get_string(&sql));
  246. if (db_execute_immediate(driver, &sql) != DB_OK) {
  247. db_close_database(driver);
  248. db_shutdown_driver(driver);
  249. Vect_delete(parm.output->answer);
  250. G_fatal_error(_("Cannot insert new row: %s"),
  251. db_get_string(&sql));
  252. }
  253. }
  254. Vect_cat_set(Cats, 1, i + 1);
  255. Vect_write_line(&Out, GV_POINT, Points, Cats);
  256. }
  257. G_percent(1, 1, 1);
  258. if (parm.zcol->answer) {
  259. db_commit_transaction(driver);
  260. db_close_database_shutdown_driver(driver);
  261. }
  262. if (!flag.notopo->answer) {
  263. Vect_build(&Out);
  264. }
  265. Vect_close(&Out);
  266. exit(EXIT_SUCCESS);
  267. }
  268. double myrand()
  269. {
  270. return (double)rand();
  271. }