[GRASS-SVN] r32501 - grass/trunk/vector/v.random

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Aug 3 16:19:04 EDT 2008


Author: martinl
Date: 2008-08-03 16:19:04 -0400 (Sun, 03 Aug 2008)
New Revision: 32501

Modified:
   grass/trunk/vector/v.random/description.html
   grass/trunk/vector/v.random/main.c
Log:
marisn: Added random attribute value creation;
Updated documentation with examples
(merge from trunk, r32498)


Modified: grass/trunk/vector/v.random/description.html
===================================================================
--- grass/trunk/vector/v.random/description.html	2008-08-03 18:30:39 UTC (rev 32500)
+++ grass/trunk/vector/v.random/description.html	2008-08-03 20:19:04 UTC (rev 32501)
@@ -3,6 +3,35 @@
 <EM>v.random</EM> randomly generates vector points within the
 current region using the selected random number generator.
 
+<p><em>v.random</em> can generate also 3D vector points or
+write random value to attribute table. Point height range or
+attribute value range is controlled by specifying zmin and zmax values.
+Both z values are included in range (<em>zmin >= z <= zmax</em>).
+Generated random attribute value type can be controlled by column
+data type. Use <b>INTEGER</b> column type for integers and 
+<b>DOUBLE PRECISION</b> for floating point numbers. Integer values are
+calculated by rounding random floating point number.
+
+<h2>EXAMPLES</h2>
+Generate 20 random points with binary attribute (only 0 or 1):
+<div class="code"><pre>
+v.random output=binary_random n=20 zmin=0 zmax=1 column='binary INTEGER'
+</pre></div>
+
+Get 20 random samples from raster map:
+<div class="code"><pre>
+v.random output=random_samples n=20
+v.db.addtable map=random_samples layer=1 columns='cat INTEGER, sample DOUBLE PRECISION'
+v.what.rast vector=random_samples raster=elevation.10m at PERMANENT layer=1 column=sample 
+</pre></div>
+
+Generate 20 random points and sample attribute data from geology (vector) map:
+<div class="code"><pre>
+v.random output=random_samples n=20
+v.db.addtable map=random_samples layer=1 columns='cat integer, geology varchar(100)'
+v.what.vect vector=random_samples layer=1 column=geology qvector=geology at PERMANENT qlayer=1 qcolumn=label 
+</pre></div>
+
 <H2>SEE ALSO</H2>
 
 UNIX man pages for <EM>rand(3)</EM> and <EM>drand48(3)</EM>.
@@ -11,7 +40,9 @@
 <A HREF="g.region.html">g.region</a>,
 <A HREF="r.random.html">r.random</a>,
 <A HREF="v.perturb.html">v.perturb</A>,
-<A HREF="v.sample.html">v.sample</A></EM>
+<A HREF="v.sample.html">v.sample</A>
+<a href="v.what.rast.html">v.what.rast</a>
+<a href="v.what.vect.html">v.what.vect</a>
 </EM>
 
 <H2>BUGS</H2>
@@ -19,10 +50,7 @@
 The RNG used by 
 <EM><A HREF="v.perturb.html">v.perturb</A></EM>
 should probably be added to this program.<BR>
-Currently no attribute table is generated.
 
-Please send any bug fixes and comments to the GRASS development team.
-
 <H2>AUTHOR</H2>
 
 <A HREF="http://mccauley-usa.com/">James Darrell McCauley</A>

Modified: grass/trunk/vector/v.random/main.c
===================================================================
--- grass/trunk/vector/v.random/main.c	2008-08-03 18:30:39 UTC (rev 32500)
+++ grass/trunk/vector/v.random/main.c	2008-08-03 20:19:04 UTC (rev 32501)
@@ -36,6 +36,7 @@
 #include <string.h>
 #include <grass/gis.h>
 #include <grass/Vect.h>
+#include <grass/dbmi.h>
 #include <grass/glocale.h>
 
 #ifndef RAND_MAX
@@ -54,9 +55,10 @@
 
 int main(int argc, char *argv[])
 {
-    char *output;
-    double (*rng) (), max;
-    int i, n, b;
+    char *output, buf[2000];
+    double (*rng) ();
+    double max, zmin, zmax;
+    int i, n, b, type, usefloat;
     struct Map_info Out;
     struct line_pnts *Points;
     struct line_cats *Cats;
@@ -64,12 +66,16 @@
     struct GModule *module;
     struct
     {
-	struct Option *output, *nsites, *zmin, *zmax;
+	struct Option *output, *nsites, *zmin, *zmax, *zcol;
     } parm;
     struct
     {
 	struct Flag *rand, *drand48, *z, *notopo;
     } flag;
+    struct field_info *Fi;
+    dbDriver *driver;
+    dbTable *table;
+    dbString sql;
 
     G_gisinit(argv[0]);
 
@@ -90,15 +96,23 @@
     parm.zmin->key = "zmin";
     parm.zmin->type = TYPE_DOUBLE;
     parm.zmin->required = NO;
-    parm.zmin->description = _("Minimum z height (needs -z flag)");
+    parm.zmin->description = _("Minimum z height (needs -z flag or column name)");
     parm.zmin->answer = "0.0";
 
     parm.zmax = G_define_option();
     parm.zmax->key = "zmax";
     parm.zmax->type = TYPE_DOUBLE;
     parm.zmax->required = NO;
-    parm.zmax->description = _("Maximum z height (needs -z flag)");
+    parm.zmax->description = _("Maximum z height (needs -z flag or column name)");
     parm.zmax->answer = "0.0";
+    
+    parm.zcol = G_define_standard_option(G_OPT_COLUMN);
+    parm.zcol->key = "column";
+    parm.zcol->required = NO;
+    parm.zcol->multiple = NO;
+    parm.zcol->label = _("Column name and type (i.e. INTEGER, DOUBLE PRECISION) for z values");
+    parm.zcol->description =
+            _("Writes Z data to column instead of 3D vector");
 
     flag.z = G_define_flag();
     flag.z->key = 'z';
@@ -115,6 +129,10 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+    if (flag.z->answer && parm.zcol->answer) {
+        G_fatal_error(_("v.random can't create 3D vector and attribute table at same time"));
+    }
+    
     output = parm.output->answer;
     n = atoi(parm.nsites->answer);
     b = (flag.drand48->answer == '\0') ? 0 : 1;
@@ -129,6 +147,74 @@
     else
 	Vect_open_new(&Out, output, WITHOUT_Z);
 
+    /* Do we need to write random values into attribute table? */
+    if (parm.zcol->answer) { 
+        Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
+        driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Out));
+        if (driver == NULL) {
+            Vect_delete(parm.output->answer);
+            G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+                          Vect_subst_var(Fi->database, &Out), Fi->driver);
+        }
+        db_begin_transaction(driver);
+
+        db_init_string(&sql);
+        sprintf(buf, "create table %s (cat integer, %s)", Fi->table, parm.zcol->answer);
+        db_set_string(&sql, buf);
+        Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database, Fi->driver);
+        
+        /* Create table */
+        G_debug(3, db_get_string(&sql));
+        if (db_execute_immediate(driver, &sql) != DB_OK) {
+            db_close_database(driver);
+            db_shutdown_driver(driver);
+            Vect_delete(parm.output->answer);
+            G_fatal_error(_("Unable to create table: %s"),
+                          db_get_string(&sql));
+        }
+
+        /* Grant */
+        if (db_grant_on_table
+            (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) {
+                 db_close_database(driver);
+                 db_shutdown_driver(driver);
+                 Vect_delete(parm.output->answer);
+                 G_fatal_error(_("Unable to grant privileges on table <%s>"),
+                               Fi->table);
+        }
+        
+        /* OK. Let's check what type of column user has created */
+        db_set_string(&sql, Fi->table);
+        if (db_describe_table(driver, &sql, &table) != DB_OK) {
+            db_close_database(driver);
+            db_shutdown_driver(driver);
+            Vect_delete(parm.output->answer);
+            G_fatal_error(_("Unable to describe table <%s>"),
+                          Fi->table);
+        }
+        
+        if (db_get_table_number_of_columns(table) != 2) {
+            db_close_database(driver);
+            db_shutdown_driver(driver);
+            Vect_delete(parm.output->answer);
+            G_fatal_error(_("Table should contain only two columns"));
+        }
+        
+        type = db_get_column_sqltype(db_get_table_column(table, 1));
+        usefloat = -1;
+        if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
+            usefloat = 0;
+        if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
+            usefloat = 1;
+        if (usefloat < 0) {
+            db_close_database(driver);
+            db_shutdown_driver(driver);
+            Vect_delete(parm.output->answer);
+            G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER" 
+                    " and DOUBLE PRECISION column types."));
+        }
+    }
+    
     Vect_hist_command(&Out);
 
     if (b) {
@@ -145,10 +231,15 @@
 
     G_get_window(&window);
 
+    if (flag.z->answer || parm.zcol->answer) {
+        zmax = atof(parm.zmax->answer);
+        zmin = atof(parm.zmin->answer);
+    }
+
     Points = Vect_new_line_struct();
     Cats = Vect_new_cats_struct();
 
-    G_important_message(_("Generating points..."));
+    G_message(_("Generating points..."));
     for (i = 0; i < n; ++i) {
 	double x, y, z;
 
@@ -157,22 +248,45 @@
 	Vect_reset_line(Points);
 	Vect_reset_cats(Cats);
 
-	x = rng() / max * (window.west - window.east) + window.east;
-	y = rng() / max * (window.north - window.south) + window.south;
+        x = rng() / max * (window.west - window.east) + window.east;
+        y = rng() / max * (window.north - window.south) + window.south;
 
-
 	if (flag.z->answer) {
-	    z = rng() / max * (atof(parm.zmax->answer) -
-			       atof(parm.zmin->answer)) +
-		atof(parm.zmin->answer);
+            z = rng() / max * (zmax - zmin) + zmin;
 	    Vect_append_point(Points, x, y, z);
 	}
 	else
 	    Vect_append_point(Points, x, y, 0.0);
 
+        if (parm.zcol->answer) {
+            z = rng() / max * (zmax - zmin) + zmin; 
+
+            sprintf(buf, "insert into %s values ( %d, ", Fi->table, i+1 );
+            db_set_string(&sql, buf);
+            /* Round random value if column is integer type */
+            if (usefloat)
+                sprintf(buf, "%f )", z);
+            else
+                sprintf(buf, "%.0f )", z);
+            db_append_string(&sql, buf);
+
+            G_debug(3, db_get_string ( &sql ));
+            if (db_execute_immediate (driver, &sql) != DB_OK) {
+                db_close_database(driver);
+                db_shutdown_driver(driver);
+                Vect_delete(parm.output->answer);
+                G_fatal_error(_("Cannot insert new row: %s"), db_get_string ( &sql ));
+            }
+        }
+
 	Vect_cat_set(Cats, 1, i + 1);
 	Vect_write_line(&Out, GV_POINT, Points, Cats);
     }
+    
+    if (parm.zcol->answer) {
+        db_commit_transaction ( driver );
+        db_close_database_shutdown_driver ( driver );
+    }
 
     if (!flag.notopo->answer) {
 	if (G_verbose() > G_verbose_min())



More information about the grass-commit mailing list