main.c 8.5 KB

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