[GRASS-SVN] r72596 - grass/trunk/vector/v.random
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Apr 6 11:13:00 PDT 2018
Author: martinl
Date: 2018-04-06 11:13:00 -0700 (Fri, 06 Apr 2018)
New Revision: 72596
Modified:
grass/trunk/vector/v.random/main.c
grass/trunk/vector/v.random/v.random.html
Log:
v.random restrict join attributes, see #3528
Modified: grass/trunk/vector/v.random/main.c
===================================================================
--- grass/trunk/vector/v.random/main.c 2018-04-06 17:51:18 UTC (rev 72595)
+++ grass/trunk/vector/v.random/main.c 2018-04-06 18:13:00 UTC (rev 72596)
@@ -22,7 +22,7 @@
* <25 Jun 1995> - new site API (jdm)
* <13 Sep 2000> - released under GPL
*
- * COPYRIGHT: (C) 2003-2010 by the GRASS Development Team
+ * COPYRIGHT: (C) 2003-2018 by the GRASS Development Team
*
* This program is free software under the GNU General
* Public License (>=v2). Read the file COPYING that
@@ -64,9 +64,10 @@
double (*rng)(void) = G_drand48;
double zmin, zmax;
int seed;
- unsigned long i, n;
+ unsigned long i, n, total_n;
int j, k, type, usefloat;
- int area, nareas, field;
+ int area, nareas, field, cat_area;
+ int cat, icol, ncols;
struct boxlist *List = NULL;
BOX_SIZE *size_list = NULL;
int alloc_size_list = 0;
@@ -86,11 +87,13 @@
{
struct Flag *z, *notopo, *a;
} flag;
- struct field_info *Fi;
- dbDriver *driver;
+ int notable;
+ struct field_info *Fi, *Fi_input;
+ dbDriver *driver, *driver_input;
+ dbString sql;
dbTable *table;
- dbString sql;
-
+ dbCatValI *cats_array = NULL;
+
G_gisinit(argv[0]);
module = G_define_module();
@@ -230,7 +233,8 @@
/* Do we need to write random values into attribute table? */
usefloat = -1;
- if (parm.zcol->answer) {
+ notable = !(parm.zcol->answer || (parm.input -> answer && field > 0));
+ if (!notable) {
Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
driver =
db_start_driver_open_database(Fi->driver,
@@ -246,9 +250,46 @@
db_init_string(&sql);
/* Create table */
- sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN,
- parm.zcol->answer, parm.ztype->answer);
- db_set_string(&sql, buf);
+ sprintf(buf, "create table %s (%s integer", Fi->table, GV_KEY_COLUMN);
+ db_set_string(&sql, buf);
+ if (parm.zcol->answer) {
+ sprintf(buf, ", %s %s", parm.zcol->answer, parm.ztype->answer);
+ db_append_string(&sql, buf);
+ }
+ if (parm.input->answer && field > 0) {
+ dbString table_name;
+ dbColumn *col;
+
+ Fi_input = Vect_get_field2(&In, parm.field->answer);
+ if (Fi_input == NULL)
+ G_fatal_error(_("Database connection not defined for layer <%s>"),
+ parm.field->answer);
+ driver_input = db_start_driver_open_database(
+ Fi_input->driver,
+ Vect_subst_var(Fi_input->database, &In));
+ if (driver_input == NULL) {
+ G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+ Vect_subst_var(Fi_input->database, &In), Fi_input->driver);
+ }
+ db_set_error_handler_driver(driver_input);
+
+ db_init_string(&table_name);
+ db_set_string(&table_name, Fi_input->table);
+ if (db_describe_table(driver_input, &table_name, &table) != DB_OK)
+ G_fatal_error(_("Unable to describe table <%s>"),
+ Fi_input->table);
+
+ ncols = db_get_table_number_of_columns(table);
+ for (icol = 0; icol < ncols; icol++) {
+ col = db_get_table_column(table, icol);
+ sprintf(buf, ",%s_%s %s", parm.input->answer,
+ db_get_column_name(col),
+ db_sqltype_name(db_get_column_sqltype(col)));
+ db_append_string(&sql, buf);
+ }
+ }
+ db_append_string(&sql, ")");
+
if (db_execute_immediate(driver, &sql) != DB_OK) {
G_fatal_error(_("Unable to create table: %s"),
db_get_string(&sql));
@@ -272,20 +313,18 @@
G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
}
- if (db_get_table_number_of_columns(table) != 2) {
- G_fatal_error(_("Table should contain only two columns"));
- }
+ if (parm.zcol->answer) {
+ type = db_get_column_sqltype(db_get_table_column(table, 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) {
+ G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
+ " and DOUBLE PRECISION column types."));
+ }
+ }
- type = db_get_column_sqltype(db_get_table_column(table, 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) {
- G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
- " and DOUBLE PRECISION column types."));
- }
-
Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
Fi->driver);
}
@@ -385,11 +424,15 @@
G_message(_("Generating points..."));
if (flag.a->answer && nareas > 0) {
struct bound_box abox, bbox;
- int cat = 1;
+ cat = 1;
/* n points for each area */
nareas = Vect_get_num_areas(&In);
-
+
+ /* init cat/cat_area array */
+ total_n = n * nareas;
+ cats_array = G_malloc(total_n * sizeof(dbCatValI));
+
G_percent(0, nareas, 1);
for (area = 1; area <= nareas; area++) {
@@ -428,11 +471,19 @@
if (bbox.N > box.N)
bbox.N = box.N;
+ if (field > 0)
+ Vect_cat_get(Cats, field, &cat_area);
+
for (i = 0; i < n; ++i) {
double x, y, z;
int outside = 1;
int ret;
+ if (field > 0) {
+ cats_array[cat-1].cat = cat;
+ cats_array[cat-1].val = cat_area;
+ }
+
Vect_reset_line(Points);
Vect_reset_cats(Cats);
@@ -455,21 +506,30 @@
else
Vect_append_point(Points, x, y, 0.0);
- if (parm.zcol->answer) {
- sprintf(buf, "insert into %s values ( %ld, ", 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, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Cannot insert new row: %s"),
- db_get_string(&sql));
- }
+ if (!notable) {
+ sprintf(buf, "insert into %s (%s", Fi->table, Fi->key);
+ db_set_string(&sql, buf);
+ if (parm.zcol->answer) {
+ sprintf(buf, ", %s", parm.zcol->answer);
+ db_append_string(&sql, buf);
+ }
+ sprintf(buf, ") values ( %d", cat);
+ db_append_string(&sql, buf);
+ if (parm.zcol->answer) {
+ /* Round random value if column is integer type */
+ if (usefloat)
+ sprintf(buf, ", %f", z);
+ else
+ sprintf(buf, ", %.0f", z);
+ db_append_string(&sql, buf);
+ }
+ db_append_string(&sql, ")");
+
+ G_debug(3, "%s", db_get_string(&sql));
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
+ G_fatal_error(_("Unable to insert new row: %s"),
+ db_get_string(&sql));
+ }
}
Vect_cat_set(Cats, 1, cat++);
@@ -478,6 +538,10 @@
}
}
else {
+ total_n = n;
+ if (parm.input->answer && field > 0)
+ cats_array = G_malloc(n * sizeof(dbCatValI));
+
/* n points in total */
for (i = 0; i < n; ++i) {
double x, y, z;
@@ -526,7 +590,7 @@
continue;
}
}
-
+
List->id[k] = List->id[j];
List->box[k] = List->box[j];
size_list[k].i = List->id[k];
@@ -579,34 +643,116 @@
else
Vect_append_point(Points, x, y, 0.0);
- if (parm.zcol->answer) {
- sprintf(buf, "insert into %s values ( %ld, ", 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);
+ cat = i + 1;
+
+ if (!notable) {
+ if (parm.input->answer) {
+ Vect_cat_get(Cats, field, &cat_area);
- G_debug(3, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Cannot insert new row: %s"),
- db_get_string(&sql));
- }
- }
+ cats_array[i].cat = cat;
+ cats_array[i].val = cat_area;
+
+ }
+
+ sprintf(buf, "insert into %s (%s", Fi->table, Fi->key);
+ db_set_string(&sql, buf);
+ if (parm.zcol->answer) {
+ sprintf(buf, ", %s", parm.zcol->answer);
+ db_append_string(&sql, buf);
+ }
+ sprintf(buf, ") values ( %ld", i + 1);
+ db_append_string(&sql, buf);
+ if (parm.zcol->answer) {
+ /* Round random value if column is integer type */
+ if (usefloat)
+ sprintf(buf, ", %f", z);
+ else
+ sprintf(buf, ", %.0f", z);
+ db_append_string(&sql, buf);
+ }
+ db_append_string(&sql, ")");
+
+ G_debug(3, "%s", db_get_string(&sql));
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
+ G_fatal_error(_("Unable to insert new row: %s"),
+ db_get_string(&sql));
+ }
+ }
- Vect_cat_set(Cats, 1, i + 1);
+ Vect_cat_set(Cats, 1, cat);
Vect_write_line(&Out, GV_POINT, Points, Cats);
}
G_percent(1, 1, 1);
}
- if (parm.zcol->answer) {
- db_commit_transaction(driver);
- db_close_database_shutdown_driver(driver);
+ if (parm.input->answer && field > 0) {
+ int more, ctype;
+ const char *column_name;
+ dbColumn *column;
+ dbValue *value;
+ dbString value_str, update_str;
+ dbCursor cursor;
+
+ db_init_string(&value_str);
+ db_init_string(&update_str);
+ sprintf(buf, "select * from %s", Fi_input->table);
+ db_set_string(&sql, buf);
+ if (db_open_select_cursor(driver_input, &sql,
+ &cursor, DB_SEQUENTIAL) != DB_OK)
+ G_fatal_error(_("Unable to open select cursor"));
+ table = db_get_cursor_table(&cursor);
+
+ while (TRUE) {
+ if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
+ G_fatal_error(_("Unable to fetch data from table <%s>"),
+ Fi_input->table);
+
+ if (!more) {
+ break;
+ }
+
+ sprintf(buf, "update %s set ", Fi->table);
+ db_set_string(&update_str, buf);
+ for (icol = 0; icol < ncols; icol++) {
+ column = db_get_table_column(table, icol);
+ column_name = db_get_column_name(column);
+ value = db_get_column_value(column);
+ if (strcmp(column_name, Fi_input->key) == 0)
+ cat_area = db_get_value_int(value);
+
+ if (icol > 0)
+ db_append_string(&update_str, ", ");
+ sprintf(buf, "%s_%s = ", parm.input->answer, column_name);
+ db_append_string(&update_str, buf);
+ ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
+ db_convert_value_to_string(value, ctype, &value_str);
+ if (ctype == DB_C_TYPE_INT || ctype == DB_C_TYPE_DOUBLE)
+ sprintf(buf, "%s", db_get_string(&value_str));
+ else
+ sprintf(buf, "'%s'", db_get_string(&value_str));
+ db_append_string(&update_str, buf);
+ }
+ for (i = 0; i < total_n; i++) {
+ if (cat_area == cats_array[i].val) {
+ db_copy_string(&sql, &update_str);
+ sprintf(buf, " where %s = %d", Fi->key, cats_array[i].cat);
+ db_append_string(&sql, buf);
+ G_debug(3, "%s", db_get_string(&sql));
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
+ G_fatal_error(_("Unable to update row: %s"),
+ db_get_string(&sql));
+ }
+ }
+ }
+ }
+ G_free(cats_array);
}
+ if (!notable) {
+ db_commit_transaction(driver);
+ db_close_database_shutdown_driver(driver);
+ }
+
if (!flag.notopo->answer) {
Vect_build(&Out);
}
Modified: grass/trunk/vector/v.random/v.random.html
===================================================================
--- grass/trunk/vector/v.random/v.random.html 2018-04-06 17:51:18 UTC (rev 72595)
+++ grass/trunk/vector/v.random/v.random.html 2018-04-06 18:13:00 UTC (rev 72596)
@@ -27,6 +27,12 @@
generated and the input map has 100 individual areas, 2000 points will
be generated in total.
+<p>
+Attributes attached to <b>restrict</b> vector map are also transfered
+if <b>layer</b> is specified,
+see <em><a href="#stratified-random-sampling:-random-sampling-from-vector-map-by-attribute">example</a></em>
+below.
+
<h2>EXAMPLES</h2>
All examples are based on the North Carolina sample dataset.
@@ -102,9 +108,9 @@
Random points with different X, Y, and Z coordinates
</center>
-<h3>Generating random points in selected polygons</h3>
+<h3>Generating random points in selected areas</h3>
-Generate 3 random points only in selected polygons ("RALEIGH" related ZIP
+Generate 3 random points only in selected areas ("RALEIGH" related ZIP
code areas):
<div class="code"><pre>
v.random restrict=zipcodes_wake output=zipcodes_local_random_n3 npoints=3 where="ZIPNAME = 'RALEIGH'" -a
@@ -120,12 +126,12 @@
<a href="v_random_points_in_polygon.png">
<img src="v_random_points_in_polygon.png" width="400" height="368" alt="v.random example" border="0">
</a><br>
-<i>Fixed number of random points generated in selected polygons</i>
+<i>Fixed number of random points generated in selected areas</i>
</div>
-<h3>Generating random adjacent polygons</h3>
+<h3>Generating random adjacent areas</h3>
-To generate random adjacent polygons, first the centroids are generated as
+To generate random adjacent areas, first the centroids are generated as
points, then a triangulation is run (North Carolina sample dataset:
<div class="code"><pre>
@@ -135,7 +141,7 @@
v.info -t randareas6k
v.category randareas6k option=print
-# plot vector polygons
+# plot vector areas
d.mon wx0
d.vect randareas6k -c
</pre></div>
@@ -142,17 +148,17 @@
<p>
<center>
<img src="vrandom_polygons.png" border=1><br>
-Random adjacent polygons from random points (here: used as centroids)
+Random adjacent areas from random points (here: used as centroids)
</center>
<p>
-To eventually obtain isolated polygons, selected polygons can be extracted with
+To eventually obtain isolated areas, selected areas can be extracted with
<em><a href="v.extract.html">v.extract</a></em>.
<p>
-These vector polygons can also be rasterized:
+These vector areas can also be rasterized:
<div class="code"><pre>
-# rasterize polygons
+# rasterize areas
# note: rastermaps must result in at least 6k pixel in this example
g.region vector=nc_state res=500 -p -a
v.to.rast randareas6k out=randareas6k use=cat
@@ -200,6 +206,12 @@
g.region -p raster=landclass96
r.to.vect -v input=landclass96 output=landclass96 type=area
v.random restrict=landclass96 output=random_samples npoints=20 where="label = 'forest'" layer=1
+v.db.select map=random_samples
+cat|landclass96_cat|landclass96_label
+1|5|forest
+2|5|forest
+3|5|forest
+...
</pre></div>
<!--
More information about the grass-commit
mailing list