28
21
* <25 Feb 1995> - cleaned 'gcc -Wall' warnings (jdm)
29
22
* <25 Jun 1995> - new site API (jdm)
30
23
* <13 Sep 2000> - released under GPL
25
* COPYRIGHT: (C) 2003-2010 by the GRASS Development Team
27
* This program is free software under the GNU General
28
* Public License (>=v2). Read the file COPYING that
29
* comes with GRASS for details.
31
**************************************************************/
33
33
#include <stdlib.h>
35
#include <sys/types.h>
37
35
#include <string.h>
38
37
#include <grass/gis.h>
39
#include <grass/Vect.h>
38
#include <grass/vector.h>
40
39
#include <grass/dbmi.h>
41
40
#include <grass/glocale.h>
44
#define RAND_MAX (pow(2.0,31.0)-1)
48
#if defined(__CYGWIN__) || defined(__APPLE__) || defined(__MINGW32__)
50
static int sort_by_size(const void *a, const void *b)
51
return (rand() / 32767.0);
52
BOX_SIZE *as = (BOX_SIZE *)a;
53
BOX_SIZE *bs = (BOX_SIZE *)b;
55
if (as->size < bs->size)
58
return (as->size > bs->size);
54
#define srand48(sv) (srand((unsigned)(sv)))
57
61
int main(int argc, char *argv[])
59
char *output, buf[2000];
61
double max, zmin, zmax;
62
int i, n, b, type, usefloat;
63
char *output, buf[DB_SQL_MAX];
64
double (*rng)(void) = G_drand48;
67
int i, j, k, n, type, usefloat;
68
int area, nareas, field;
69
struct boxlist *List = NULL;
70
BOX_SIZE *size_list = NULL;
71
int alloc_size_list = 0;
72
struct Map_info In, Out;
64
73
struct line_pnts *Points;
65
74
struct line_cats *Cats;
75
struct cat_list *cat_list;
66
77
struct Cell_head window;
67
78
struct GModule *module;
70
struct Option *output, *nsites, *zmin, *zmax, *zcol;
81
struct Option *input, *field, *cats, *where, *output, *nsites,
82
*zmin, *zmax, *zcol, *ztype, *seed;
74
struct Flag *rand, *drand48, *z, *notopo;
86
struct Flag *z, *notopo, *a;
76
88
struct field_info *Fi;
109
140
_("Maximum z height (needs -z flag or column name)");
110
141
parm.zmax->answer = "0.0";
111
142
parm.zmax->guisection = _("3D output");
113
parm.zcol = G_define_option();
114
parm.zcol->key = "column";
115
parm.zcol->type = TYPE_STRING;
116
parm.zcol->multiple = NO;
117
parm.zcol->required = NO;
119
_("Column name and type (i.e. INTEGER, DOUBLE PRECISION) for z values");
144
parm.seed = G_define_option();
145
parm.seed->key = "seed";
146
parm.seed->type = TYPE_INTEGER;
147
parm.seed->required = NO;
148
parm.seed->description =
149
_("The seed to initialize the random generator. If not set the process ID is used");
151
parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
152
parm.zcol->label = _("Name of column for z values");
120
153
parm.zcol->description =
121
_("If type is not given then DOUBLE PRECISION is used. "
122
"Writes Z data to column instead of 3D vector.");
154
_("Writes z values to column");
123
155
parm.zcol->guisection = _("3D output");
157
parm.ztype = G_define_option();
158
parm.ztype->key = "column_type";
159
parm.ztype->type = TYPE_STRING;
160
parm.ztype->required = NO;
161
parm.ztype->multiple = NO;
162
parm.ztype->description = _("Type of column for z values");
163
parm.ztype->options = "integer,double precision";
164
parm.ztype->answer = "double precision";
165
parm.ztype->guisection = _("3D output");
125
167
flag.z = G_define_flag();
126
168
flag.z->key = 'z';
127
169
flag.z->description = _("Create 3D output");
128
170
flag.z->guisection = _("3D output");
130
flag.drand48 = G_define_flag();
131
flag.drand48->key = 'd';
132
flag.drand48->description = _("Use drand48() function instead of rand()");
172
flag.a = G_define_flag();
174
flag.a->description = _("Generate n points for each individual area");
134
flag.notopo = G_define_flag();
135
flag.notopo->key = 'b';
136
flag.notopo->description = _("Do not build topology");
176
flag.notopo = G_define_standard_flag(G_FLG_V_TOPO);
138
178
if (G_parser(argc, argv))
139
179
exit(EXIT_FAILURE);
141
if (flag.z->answer && parm.zcol->answer) {
142
G_fatal_error(_("v.random can't create 3D vector and attribute table at same time"));
145
181
output = parm.output->answer;
146
182
n = atoi(parm.nsites->answer);
147
b = (flag.drand48->answer == '\0') ? 0 : 1;
184
if(parm.seed->answer)
185
seed = atoi(parm.seed->answer);
150
188
G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
154
Vect_open_new(&Out, output, WITH_Z);
156
Vect_open_new(&Out, output, WITHOUT_Z);
194
if (parm.input->answer) {
195
Vect_set_open_level(2); /* topology required */
196
if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer))
197
G_fatal_error(_("Unable to open vector map <%s>"),
200
if (parm.field->answer)
201
field = Vect_get_field_number(&In, parm.field->answer);
203
if ((parm.cats->answer || parm.where->answer) && field == -1) {
204
G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."),
205
field, parm.cats->key, parm.where->key);
209
cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer,
211
nareas = Vect_get_num_areas(&In);
214
G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer);
219
G_fatal_error(_("The <-%c> flag requires an input vector with areas"),
223
/* create new vector map */
224
if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z))
225
G_fatal_error(_("Unable to create vector map <%s>"), output);
226
Vect_set_error_handler_io(NULL, &Out);
158
228
/* Do we need to write random values into attribute table? */
159
230
if (parm.zcol->answer) {
160
char **token = G_tokenize(parm.zcol->answer, " ");
162
231
Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
164
233
db_start_driver_open_database(Fi->driver,
165
234
Vect_subst_var(Fi->database, &Out));
166
235
if (driver == NULL) {
167
Vect_delete(parm.output->answer);
168
236
G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
169
237
Vect_subst_var(Fi->database, &Out), Fi->driver);
239
db_set_error_handler_driver(driver);
171
241
db_begin_transaction(driver);
173
243
db_init_string(&sql);
174
if (G_number_of_tokens(token) > 1) {
175
sprintf(buf, "create table %s (cat integer, %s)", Fi->table,
179
G_verbose_message(_("Using 'double precision' for column <%s>"), parm.zcol->answer);
180
sprintf(buf, "create table %s (cat integer, %s double precision)", Fi->table,
244
sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN,
245
parm.zcol->answer, parm.ztype->answer);
183
246
db_set_string(&sql, buf);
184
Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
247
Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
187
250
/* Create table */
188
251
G_debug(3, db_get_string(&sql));
189
252
if (db_execute_immediate(driver, &sql) != DB_OK) {
190
db_close_database(driver);
191
db_shutdown_driver(driver);
192
Vect_delete(parm.output->answer);
193
253
G_fatal_error(_("Unable to create table: %s"),
194
254
db_get_string(&sql));
258
if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK)
259
G_warning(_("Unable to create index"));
198
262
if (db_grant_on_table
199
263
(driver, Fi->table, DB_PRIV_SELECT,
200
264
DB_GROUP | DB_PUBLIC) != DB_OK) {
201
db_close_database(driver);
202
db_shutdown_driver(driver);
203
Vect_delete(parm.output->answer);
204
265
G_fatal_error(_("Unable to grant privileges on table <%s>"),
208
269
/* OK. Let's check what type of column user has created */
209
270
db_set_string(&sql, Fi->table);
210
271
if (db_describe_table(driver, &sql, &table) != DB_OK) {
211
db_close_database(driver);
212
db_shutdown_driver(driver);
213
Vect_delete(parm.output->answer);
214
272
G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
217
275
if (db_get_table_number_of_columns(table) != 2) {
218
db_close_database(driver);
219
db_shutdown_driver(driver);
220
Vect_delete(parm.output->answer);
221
276
G_fatal_error(_("Table should contain only two columns"));
224
279
type = db_get_column_sqltype(db_get_table_column(table, 1));
226
280
if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
228
282
if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
230
284
if (usefloat < 0) {
231
db_close_database(driver);
232
db_shutdown_driver(driver);
233
Vect_delete(parm.output->answer);
234
285
G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
235
286
" and DOUBLE PRECISION column types."));
237
G_free_tokens(token);
240
290
Vect_hist_command(&Out);
245
srand48((long)getpid());
247
else { /* default is rand() */
292
/* Init the random seed */
293
if(parm.seed->answer)
254
298
G_get_window(&window);
300
Points = Vect_new_line_struct();
301
Cats = Vect_new_cats_struct();
304
int first = 1, count;
305
struct bound_box abox, bbox;
309
box.S = window.south;
310
box.N = window.north;
311
box.B = -PORT_DOUBLE_MAX;
312
box.T = PORT_DOUBLE_MAX;
316
for (i = 1; i <= nareas; i++) {
318
if (!Vect_get_area_centroid(&In, i))
322
if (Vect_get_area_cats(&In, i, Cats))
325
if (!Vect_cats_in_constraint(Cats, field, cat_list))
329
Vect_get_area_box(&In, i, &abox);
330
if (!Vect_box_overlap(&abox, &box))
334
Vect_box_copy(&bbox, &abox);
338
Vect_box_extend(&bbox, &abox);
345
G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"),
348
Vect_box_copy(&box, &bbox);
350
/* does the vector overlap with the current region ? */
351
if (box.W >= window.east || box.E <= window.west ||
352
box.S >= window.north || box.N <= window.south) {
357
G_fatal_error(_("Input vector <%s> does not overlap with the current region"),
361
/* try to reduce the current region */
362
if (window.east > box.E)
364
if (window.west < box.W)
366
if (window.north > box.N)
367
window.north = box.N;
368
if (window.south < box.S)
369
window.south = box.S;
371
List = Vect_new_boxlist(1);
372
alloc_size_list = 10;
373
size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
256
377
if (flag.z->answer || parm.zcol->answer) {
257
378
zmax = atof(parm.zmax->answer);
258
379
zmin = atof(parm.zmin->answer);
261
Points = Vect_new_line_struct();
262
Cats = Vect_new_cats_struct();
264
382
G_message(_("Generating points..."));
265
for (i = 0; i < n; ++i) {
270
Vect_reset_line(Points);
271
Vect_reset_cats(Cats);
273
x = rng() / max * (window.west - window.east) + window.east;
274
y = rng() / max * (window.north - window.south) + window.south;
276
if (flag.z->answer) {
277
z = rng() / max * (zmax - zmin) + zmin;
278
Vect_append_point(Points, x, y, z);
383
if (flag.a->answer && nareas > 0) {
384
struct bound_box abox, bbox;
387
/* n points for each area */
388
nareas = Vect_get_num_areas(&In);
390
G_percent(0, nareas, 1);
391
for (area = 1; area <= nareas; area++) {
393
G_percent(area, nareas, 1);
395
if (!Vect_get_area_centroid(&In, area))
399
if (Vect_get_area_cats(&In, area, Cats))
402
if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
409
box.S = window.south;
410
box.N = window.north;
411
box.B = -PORT_DOUBLE_MAX;
412
box.T = PORT_DOUBLE_MAX;
414
Vect_get_area_box(&In, area, &abox);
415
if (!Vect_box_overlap(&box, &abox))
428
for (i = 0; i < n; ++i) {
433
Vect_reset_line(Points);
434
Vect_reset_cats(Cats);
437
x = rng() * (bbox.W - bbox.E) + bbox.E;
438
y = rng() * (bbox.N - bbox.S) + bbox.S;
439
z = rng() * (zmax - zmin) + zmin;
441
ret = Vect_point_in_area(x, y, &In, area, &abox);
443
G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret);
451
Vect_append_point(Points, x, y, z);
453
Vect_append_point(Points, x, y, 0.0);
455
if (parm.zcol->answer) {
456
sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
457
db_set_string(&sql, buf);
458
/* Round random value if column is integer type */
460
sprintf(buf, "%f )", z);
462
sprintf(buf, "%.0f )", z);
463
db_append_string(&sql, buf);
465
G_debug(3, db_get_string(&sql));
466
if (db_execute_immediate(driver, &sql) != DB_OK) {
467
G_fatal_error(_("Cannot insert new row: %s"),
468
db_get_string(&sql));
472
Vect_cat_set(Cats, 1, cat++);
473
Vect_write_line(&Out, GV_POINT, Points, Cats);
281
Vect_append_point(Points, x, y, 0.0);
283
if (parm.zcol->answer) {
284
z = rng() / max * (zmax - zmin) + zmin;
286
sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
287
db_set_string(&sql, buf);
288
/* Round random value if column is integer type */
290
sprintf(buf, "%f )", z);
478
/* n points in total */
479
for (i = 0; i < n; ++i) {
484
Vect_reset_line(Points);
485
Vect_reset_cats(Cats);
487
x = rng() * (window.west - window.east) + window.east;
488
y = rng() * (window.north - window.south) + window.south;
489
z = rng() * (zmax - zmin) + zmin;
495
/* select areas by box */
500
box.T = PORT_DOUBLE_MAX;
501
box.B = -PORT_DOUBLE_MAX;
502
Vect_select_areas_by_box(&In, &box, List);
503
G_debug(3, " %d areas selected by box", List->n_values);
505
/* sort areas by size, the smallest is likely to be the nearest */
506
if (alloc_size_list < List->n_values) {
507
alloc_size_list = List->n_values;
508
size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
512
for (j = 0; j < List->n_values; j++) {
515
if (!Vect_get_area_centroid(&In, area))
519
if (Vect_get_area_cats(&In, area, Cats))
522
if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
527
List->id[k] = List->id[j];
528
List->box[k] = List->box[j];
529
size_list[k].i = List->id[k];
531
size_list[k].box = List->box[k];
532
size_list[k].size = (box.N - box.S) * (box.E - box.W);
537
if (List->n_values == 2) {
539
if (size_list[1].size < size_list[0].size) {
540
size_list[0].i = List->id[1];
541
size_list[1].i = List->id[0];
542
size_list[0].box = List->box[1];
543
size_list[1].box = List->box[0];
546
else if (List->n_values > 2)
547
qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);
549
for (j = 0; j < List->n_values; j++) {
552
area = size_list[j].i;
553
ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box);
555
G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret);
563
x = rng() * (window.west - window.east) + window.east;
564
y = rng() * (window.north - window.south) + window.south;
565
z = rng() * (zmax - zmin) + zmin;
571
Vect_append_point(Points, x, y, z);
292
sprintf(buf, "%.0f )", z);
293
db_append_string(&sql, buf);
295
G_debug(3, db_get_string(&sql));
296
if (db_execute_immediate(driver, &sql) != DB_OK) {
297
db_close_database(driver);
298
db_shutdown_driver(driver);
299
Vect_delete(parm.output->answer);
300
G_fatal_error(_("Cannot insert new row: %s"),
301
db_get_string(&sql));
573
Vect_append_point(Points, x, y, 0.0);
575
if (parm.zcol->answer) {
576
sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
577
db_set_string(&sql, buf);
578
/* Round random value if column is integer type */
580
sprintf(buf, "%f )", z);
582
sprintf(buf, "%.0f )", z);
583
db_append_string(&sql, buf);
585
G_debug(3, db_get_string(&sql));
586
if (db_execute_immediate(driver, &sql) != DB_OK) {
587
G_fatal_error(_("Cannot insert new row: %s"),
588
db_get_string(&sql));
592
Vect_cat_set(Cats, 1, i + 1);
593
Vect_write_line(&Out, GV_POINT, Points, Cats);
305
Vect_cat_set(Cats, 1, i + 1);
306
Vect_write_line(&Out, GV_POINT, Points, Cats);
309
598
if (parm.zcol->answer) {
310
599
db_commit_transaction(driver);
311
600
db_close_database_shutdown_driver(driver);