/*! \brief Writes feature on level 2 \param Map pointer to Map_info structure \param type feature type \param points pointer to line_pnts structure (feature geometry) \param cats pointer to line_cats structure (feature categories) \return feature offset into file \return -1 on error */ off_t V2_write_line_ogr(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats) { int line; off_t offset; struct Plus_head *plus; struct bound_box box; line = 0; G_debug(3, "V2_write_line_ogr()"); offset = V1_write_line_ogr(Map, type, points, cats); if (offset < 0) return -1; /* Update topology */ plus = &(Map->plus); /* Add line */ if (plus->built >= GV_BUILD_BASE) { dig_line_box(points, &box); line = dig_add_line(plus, type, points, &box, offset); G_debug(3, " line added to topo with id = %d", line); if (line == 1) Vect_box_copy(&(plus->box), &box); else Vect_box_extend(&(plus->box), &box); V2__add_line_to_topo_ogr(Map, line, points, cats); } G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines, plus->n_upnodes); /* returns int line, but is defined as off_t for compatibility with * Write_line_array in write.c */ return line; }
/* code taken from Vect_build_nat() */ int level_one_info(struct Map_info *Map) { struct Plus_head *plus; int i, type, first = 1; off_t offset; struct line_pnts *Points; struct line_cats *Cats; struct bound_box box; int n_primitives, n_points, n_lines, n_boundaries, n_centroids; int n_faces, n_kernels; G_debug(1, "Count vector objects for level 1"); plus = &(Map->plus); n_primitives = n_points = n_lines = n_boundaries = n_centroids = 0; n_faces = n_kernels = 0; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_rewind(Map); /* G_message(_("Registering primitives...")); */ i = 1; while (1) { /* register line */ type = Vect_read_next_line(Map, Points, Cats); /* Note: check for dead lines is not needed, because they are skipped by V1_read_next_line_nat() */ if (type == -1) { G_warning(_("Unable to read vector map")); return 0; } else if (type == -2) { break; } /* count features */ n_primitives++; if (type & GV_POINT) /* probably most common */ n_points++; else if (type & GV_LINE) n_lines++; else if (type & GV_BOUNDARY) n_boundaries++; else if (type & GV_CENTROID) n_centroids++; else if (type & GV_KERNEL) n_kernels++; else if (type & GV_FACE) n_faces++; offset = Map->head.last_offset; G_debug(3, "Register line: offset = %lu", (unsigned long)offset); dig_line_box(Points, &box); if (first == 1) { Vect_box_copy(&(plus->box), &box); first = 0; } else Vect_box_extend(&(plus->box), &box); /* can't print progress, unfortunately */ /* if (G_verbose() > G_verbose_min() && i % 1000 == 0) { if (format == G_INFO_FORMAT_PLAIN) fprintf(stderr, "%d..", i); else fprintf(stderr, "%11d\b\b\b\b\b\b\b\b\b\b\b", i); } i++; */ } /* save result in plus */ plus->n_lines = n_primitives; plus->n_plines = n_points; plus->n_llines = n_lines; plus->n_blines = n_boundaries; plus->n_clines = n_centroids; plus->n_klines = n_kernels; plus->n_flines = n_faces; return 1; }
/*! \brief Dump topology to file \param Map vector map \param out file for output (stdout/stderr for example) \return 1 on success \return 0 on error */ int Vect_topo_dump(const struct Map_info *Map, FILE *out) { int i, j, line, isle; float angle_deg; struct P_node *Node; struct P_line *Line; struct P_area *Area; struct P_isle *Isle; struct bound_box box; const struct Plus_head *plus; plus = &(Map->plus); fprintf(out, "---------- TOPOLOGY DUMP ----------\n"); fprintf(out, "Map: %s\n", Vect_get_full_name(Map)); fprintf(out, "Topology format: "); if (Map->format == GV_FORMAT_NATIVE) fprintf(out, "native"); else if (Map->format == GV_FORMAT_POSTGIS && Map->fInfo.pg.toposchema_name) { fprintf(out, "PostGIS"); } else { fprintf(out, "pseudo (simple features)"); if (Map->format == GV_FORMAT_OGR) fprintf(out, " @ OGR"); else fprintf(out, " @ PostgreSQL"); } fprintf(out, "\n"); fprintf(out, SEP); /* box */ Vect_box_copy(&box, &(plus->box)); fprintf(out, "N,S,E,W,T,B: %f, %f, %f, %f, %f, %f\n", box.N, box.S, box.E, box.W, box.T, box.B); fprintf(out, SEP); /* nodes */ fprintf(out, "Nodes (%d nodes, alive + dead):\n", plus->n_nodes); for (i = 1; i <= plus->n_nodes; i++) { if (plus->Node[i] == NULL) { continue; } Node = plus->Node[i]; fprintf(out, "node = %d, n_lines = %d, xyz = %f, %f, %f\n", i, Node->n_lines, Node->x, Node->y, Node->z); for (j = 0; j < Node->n_lines; j++) { line = Node->lines[j]; Line = plus->Line[abs(line)]; angle_deg = (Node->angles[j] * 180) / M_PI; if (angle_deg < 0) angle_deg += 360; fprintf(out, " line = %3d, type = %d, angle = %f (%.4f)\n", line, Line->type, Node->angles[j], angle_deg); } } fprintf(out, SEP); /* lines */ fprintf(out, "Lines (%d lines, alive + dead):\n", plus->n_lines); for (i = 1; i <= plus->n_lines; i++) { if (plus->Line[i] == NULL) { continue; } Line = plus->Line[i]; if (Line->type == GV_POINT) { fprintf(out, "line = %d, type = %d, offset = %lu\n", i, Line->type, (unsigned long)Line->offset); } else if (Line->type == GV_CENTROID) { struct P_topo_c *topo = (struct P_topo_c *)Line->topo; fprintf(out, "line = %d, type = %d, offset = %lu, area = %d\n", i, Line->type, (unsigned long)Line->offset, topo->area); } else if (Line->type == GV_LINE) { struct P_topo_l *topo = (struct P_topo_l *)Line->topo; fprintf(out, "line = %d, type = %d, offset = %lu, n1 = %d, n2 = %d\n", i, Line->type, (unsigned long)Line->offset, topo->N1, topo->N2); } else if (Line->type == GV_BOUNDARY) { struct P_topo_b *topo = (struct P_topo_b *)Line->topo; fprintf(out, "line = %d, type = %d, offset = %lu, n1 = %d, n2 = %d, " "left = %d, right = %d\n", i, Line->type, (unsigned long)Line->offset, topo->N1, topo->N2, topo->left, topo->right); } else if (Line->type == GV_FACE) { struct P_topo_f *topo = (struct P_topo_f *)Line->topo; fprintf(out, "line = %d, type = %d, offset = %lu, e1 = %d, e2 = %d, " "e3 = %d, left = %d, right = %d\n", i, Line->type, (unsigned long)Line->offset, topo->E[0], topo->E[1], topo->E[2], topo->left, topo->right); } else if (Line->type == GV_KERNEL) { struct P_topo_k *topo = (struct P_topo_k *)Line->topo; fprintf(out, "line = %d, type = %d, offset = %lu, volume = %d", i, Line->type, (unsigned long)Line->offset, topo->volume); } } fprintf(out, SEP); /* areas */ fprintf(out, "Areas (%d areas, alive + dead):\n", plus->n_areas); for (i = 1; i <= plus->n_areas; i++) { if (plus->Area[i] == NULL) { continue; } Area = plus->Area[i]; fprintf(out, "area = %d, n_lines = %d, n_isles = %d centroid = %d\n", i, Area->n_lines, Area->n_isles, Area->centroid); for (j = 0; j < Area->n_lines; j++) { line = Area->lines[j]; Line = plus->Line[abs(line)]; fprintf(out, " line = %3d\n", line); } for (j = 0; j < Area->n_isles; j++) { isle = Area->isles[j]; fprintf(out, " isle = %3d\n", isle); } } fprintf(out, SEP); /* isles */ fprintf(out, "Islands (%d islands, alive + dead):\n", plus->n_isles); for (i = 1; i <= plus->n_isles; i++) { if (plus->Isle[i] == NULL) { continue; } Isle = plus->Isle[i]; fprintf(out, "isle = %d, n_lines = %d area = %d\n", i, Isle->n_lines, Isle->area); for (j = 0; j < Isle->n_lines; j++) { line = Isle->lines[j]; Line = plus->Line[abs(line)]; fprintf(out, " line = %3d\n", line); } } return 1; }
int main(int argc, char **argv) { struct GModule *module; struct Option *map_opt, *field_opt, *fs_opt, *vs_opt, *nv_opt, *col_opt, *where_opt, *file_opt; struct Flag *c_flag, *v_flag, *r_flag; dbDriver *driver; dbString sql, value_string; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; struct field_info *Fi; int ncols, col, more; struct Map_info Map; char query[1024]; struct ilist *list_lines; struct bound_box *min_box, *line_box; int i, line, area, init_box, cat; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("database")); G_add_keyword(_("attribute table")); module->description = _("Prints vector map attributes."); map_opt = G_define_standard_option(G_OPT_V_MAP); field_opt = G_define_standard_option(G_OPT_V_FIELD); col_opt = G_define_standard_option(G_OPT_DB_COLUMNS); where_opt = G_define_standard_option(G_OPT_DB_WHERE); fs_opt = G_define_standard_option(G_OPT_F_SEP); fs_opt->description = _("Output field separator"); fs_opt->guisection = _("Format"); vs_opt = G_define_standard_option(G_OPT_F_SEP); vs_opt->key = "vs"; vs_opt->description = _("Output vertical record separator"); vs_opt->answer = NULL; vs_opt->guisection = _("Format"); nv_opt = G_define_option(); nv_opt->key = "nv"; nv_opt->type = TYPE_STRING; nv_opt->required = NO; nv_opt->description = _("Null value indicator"); nv_opt->guisection = _("Format"); file_opt = G_define_standard_option(G_OPT_F_OUTPUT); file_opt->key = "file"; file_opt->required = NO; file_opt->description = _("Name for output file (if omitted or \"-\" output to stdout)"); r_flag = G_define_flag(); r_flag->key = 'r'; r_flag->description = _("Print minimal region extent of selected vector features instead of attributes"); c_flag = G_define_flag(); c_flag->key = 'c'; c_flag->description = _("Do not include column names in output"); c_flag->guisection = _("Format"); v_flag = G_define_flag(); v_flag->key = 'v'; v_flag->description = _("Vertical output (instead of horizontal)"); v_flag->guisection = _("Format"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* set input vector map name and mapset */ if (file_opt->answer && strcmp(file_opt->answer, "-") != 0) { if (NULL == freopen(file_opt->answer, "w", stdout)) { G_fatal_error(_("Unable to open file <%s> for writing"), file_opt->answer); } } if (r_flag->answer) { min_box = (struct bound_box *) G_malloc(sizeof(struct bound_box)); G_zero((void *)min_box, sizeof(struct bound_box)); line_box = (struct bound_box *) G_malloc(sizeof(struct bound_box)); list_lines = Vect_new_list(); } else { min_box = line_box = NULL; list_lines = NULL; } db_init_string(&sql); db_init_string(&value_string); /* open input vector */ if (!r_flag->answer) Vect_open_old_head2(&Map, map_opt->answer, "", field_opt->answer); else { if (2 > Vect_open_old2(&Map, map_opt->answer, "", field_opt->answer)) { Vect_close(&Map); G_fatal_error(_("Unable to open vector map <%s> at topology level. " "Flag '%c' requires topology level."), map_opt->answer, r_flag->key); } } if ((Fi = Vect_get_field2(&Map, field_opt->answer)) == NULL) G_fatal_error(_("Database connection not defined for layer <%s>"), field_opt->answer); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (!driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); if (col_opt->answer) sprintf(query, "SELECT %s FROM ", col_opt->answer); else sprintf(query, "SELECT * FROM "); db_set_string(&sql, query); db_append_string(&sql, Fi->table); if (where_opt->answer) { char *buf = NULL; buf = G_malloc((strlen(where_opt->answer) + 8)); sprintf(buf, " WHERE %s", where_opt->answer); db_append_string(&sql, buf); G_free(buf); } if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) G_fatal_error(_("Unable to open select cursor")); table = db_get_cursor_table(&cursor); ncols = db_get_table_number_of_columns(table); /* column names if horizontal output (ignore for -r) */ if (!v_flag->answer && !c_flag->answer && !r_flag->answer) { for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); if (col) fprintf(stdout, "%s", fs_opt->answer); fprintf(stdout, "%s", db_get_column_name(column)); } fprintf(stdout, "\n"); } init_box = 1; /* fetch the data */ while (1) { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) G_fatal_error(_("Unable to fetch data from table <%s>"), Fi->table); if (!more) break; cat = -1; for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); value = db_get_column_value(column); if (cat < 0 && strcmp(Fi->key, db_get_column_name(column)) == 0) { cat = db_get_value_int(value); if (r_flag->answer) break; } if (r_flag->answer) continue; db_convert_column_value_to_string(column, &value_string); if (!c_flag->answer && v_flag->answer) fprintf(stdout, "%s%s", db_get_column_name(column), fs_opt->answer); if (col && !v_flag->answer) fprintf(stdout, "%s", fs_opt->answer); if (nv_opt->answer && db_test_value_isnull(value)) fprintf(stdout, "%s", nv_opt->answer); else fprintf(stdout, "%s", db_get_string(&value_string)); if (v_flag->answer) fprintf(stdout, "\n"); } if (r_flag->answer) { /* get minimal region extent */ Vect_cidx_find_all(&Map, Vect_get_field_number(&Map, field_opt->answer), -1, cat, list_lines); for (i = 0; i < list_lines->n_values; i++) { line = list_lines->value[i]; area = Vect_get_centroid_area(&Map, line); if (area > 0) { if (!Vect_get_area_box(&Map, area, line_box)) G_fatal_error(_("Unable to get bounding box of area %d"), area); } else { if (!Vect_get_line_box(&Map, line, line_box)) G_fatal_error(_("Unable to get bounding box of line %d"), line); } if (init_box) { Vect_box_copy(min_box, line_box); init_box = 0; } else { Vect_box_extend(min_box, line_box); } } } else { if (!v_flag->answer) fprintf(stdout, "\n"); else if (vs_opt->answer) fprintf(stdout, "%s\n", vs_opt->answer); } } if (r_flag->answer) { fprintf(stdout, "n=%f\n", min_box->N); fprintf(stdout, "s=%f\n", min_box->S); fprintf(stdout, "w=%f\n", min_box->W); fprintf(stdout, "e=%f\n", min_box->E); if (Vect_is_3d(&Map)) { fprintf(stdout, "t=%f\n", min_box->T); fprintf(stdout, "b=%f\n", min_box->B); } fflush(stdout); G_free((void *)min_box); G_free((void *)line_box); Vect_destroy_list(list_lines); } db_close_cursor(&cursor); db_close_database_shutdown_driver(driver); Vect_close(&Map); exit(EXIT_SUCCESS); }
/*! \brief Build topology \param Map vector map \param build build level \return 1 on success \return 0 on error */ int Vect_build_nat(struct Map_info *Map, int build) { struct Plus_head *plus; int i, s, type, line; off_t offset; int side, area; struct line_cats *Cats; struct P_line *Line; struct P_area *Area; struct bound_box box; G_debug(3, "Vect_build_nat() build = %d", build); plus = &(Map->plus); if (build == plus->built) return 1; /* Do nothing */ /* Check if upgrade or downgrade */ if (build < plus->built) { /* -> downgrade */ Vect__build_downgrade(Map, build); return 1; } /* -> upgrade */ if (!Points) Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); if (plus->built < GV_BUILD_BASE) { int npoints, c; /* * We shall go through all primitives in coor file and add * new node for each end point to nodes structure if the node * with the same coordinates doesn't exist yet. */ /* register lines, create nodes */ Vect_rewind(Map); G_message(_("Registering primitives...")); i = 0; npoints = 0; while (TRUE) { /* register line */ type = Vect_read_next_line(Map, Points, Cats); /* Note: check for dead lines is not needed, because they are skipped by V1_read_next_line() */ if (type == -1) { G_warning(_("Unable to read vector map")); return 0; } else if (type == -2) { break; } G_progress(++i, 1e4); npoints += Points->n_points; offset = Map->head.last_offset; G_debug(3, "Register line: offset = %lu", (unsigned long)offset); dig_line_box(Points, &box); line = dig_add_line(plus, type, Points, &box, offset); if (line == 1) Vect_box_copy(&(plus->box), &box); else Vect_box_extend(&(plus->box), &box); /* Add all categories to category index */ if (build == GV_BUILD_ALL) { for (c = 0; c < Cats->n_cats; c++) { dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], line, type); } if (Cats->n_cats == 0) /* add field 0, cat 0 */ dig_cidx_add_cat(plus, 0, 0, line, type); } } G_progress(1, 1); G_message(_n("One primitive registered", "%d primitives registered", plus->n_lines), plus->n_lines); G_message(_n("One vertex registered", "%d vertices registered", npoints), npoints); plus->built = GV_BUILD_BASE; } if (build < GV_BUILD_AREAS) return 1; if (plus->built < GV_BUILD_AREAS) { /* Build areas */ /* Go through all bundaries and try to build area for both sides */ G_important_message(_("Building areas...")); for (line = 1; line <= plus->n_lines; line++) { G_percent(line, plus->n_lines, 1); /* build */ if (plus->Line[line] == NULL) { continue; } /* dead line */ Line = plus->Line[line]; if (Line->type != GV_BOUNDARY) { continue; } for (s = 0; s < 2; s++) { if (s == 0) side = GV_LEFT; else side = GV_RIGHT; G_debug(3, "Build area for line = %d, side = %d", line, side); Vect_build_line_area(Map, line, side); } } G_message(_n("One area built", "%d areas built", plus->n_areas), plus->n_areas); G_message(_n("One isle built", "%d isles built", plus->n_isles), plus->n_isles); plus->built = GV_BUILD_AREAS; } if (build < GV_BUILD_ATTACH_ISLES) return 1; /* Attach isles to areas */ if (plus->built < GV_BUILD_ATTACH_ISLES) { G_important_message(_("Attaching islands...")); for (i = 1; i <= plus->n_isles; i++) { G_percent(i, plus->n_isles, 1); Vect_attach_isle(Map, i); } plus->built = GV_BUILD_ATTACH_ISLES; } if (build < GV_BUILD_CENTROIDS) return 1; /* Attach centroids to areas */ if (plus->built < GV_BUILD_CENTROIDS) { int nlines; struct P_topo_c *topo; G_important_message(_("Attaching centroids...")); nlines = Vect_get_num_lines(Map); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 1); Line = plus->Line[line]; if (!Line) continue; /* Dead */ if (Line->type != GV_CENTROID) continue; Vect_read_line(Map, Points, NULL, line); area = Vect_find_area(Map, Points->x[0], Points->y[0]); if (area > 0) { G_debug(3, "Centroid (line=%d) in area %d", line, area); Area = plus->Area[area]; topo = (struct P_topo_c *)Line->topo; if (Area->centroid == 0) { /* first */ Area->centroid = line; topo->area = area; } else { /* duplicate */ topo->area = -area; } } } plus->built = GV_BUILD_CENTROIDS; } /* Add areas to category index */ for (i = 1; i <= plus->n_areas; i++) { int c; if (plus->Area[i] == NULL) continue; if (plus->Area[i]->centroid > 0) { Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid); for (c = 0; c < Cats->n_cats; c++) { dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i, GV_AREA); } } if (plus->Area[i]->centroid == 0 || Cats->n_cats == 0) /* no centroid or no cats */ dig_cidx_add_cat(plus, 0, 0, i, GV_AREA); } Vect_destroy_cats_struct(Cats); return 1; }
int main(int argc, char *argv[]) { char *output, buf[DB_SQL_MAX]; double (*rng)(void) = G_drand48; double zmin, zmax; int seed; int i, j, k, n, type, usefloat; int area, nareas, field; struct boxlist *List = NULL; BOX_SIZE *size_list = NULL; int alloc_size_list = 0; struct Map_info In, Out; struct line_pnts *Points; struct line_cats *Cats; struct cat_list *cat_list; struct bound_box box; struct Cell_head window; struct GModule *module; struct { struct Option *input, *field, *cats, *where, *output, *nsites, *zmin, *zmax, *zcol, *ztype, *seed; } parm; struct { struct Flag *z, *notopo, *a; } flag; struct field_info *Fi; dbDriver *driver; dbTable *table; dbString sql; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("sampling")); G_add_keyword(_("statistics")); G_add_keyword(_("random")); module->description = _("Generates random 2D/3D vector points."); parm.output = G_define_standard_option(G_OPT_V_OUTPUT); parm.nsites = G_define_option(); parm.nsites->key = "n"; parm.nsites->type = TYPE_INTEGER; parm.nsites->required = YES; parm.nsites->description = _("Number of points to be created"); parm.input = G_define_standard_option(G_OPT_V_INPUT); parm.input->required = NO; parm.input->description = _("Restrict points to areas in input vector"); parm.input->guisection = _("Selection"); parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL); parm.field->guisection = _("Selection"); parm.cats = G_define_standard_option(G_OPT_V_CATS); parm.cats->guisection = _("Selection"); parm.where = G_define_standard_option(G_OPT_DB_WHERE); parm.where->guisection = _("Selection"); parm.zmin = G_define_option(); parm.zmin->key = "zmin"; parm.zmin->type = TYPE_DOUBLE; parm.zmin->required = NO; parm.zmin->description = _("Minimum z height (needs -z flag or column name)"); parm.zmin->answer = "0.0"; parm.zmin->guisection = _("3D output"); 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 or column name)"); parm.zmax->answer = "0.0"; parm.zmax->guisection = _("3D output"); parm.seed = G_define_option(); parm.seed->key = "seed"; parm.seed->type = TYPE_INTEGER; parm.seed->required = NO; parm.seed->description = _("The seed to initialize the random generator. If not set the process ID is used"); parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN); parm.zcol->label = _("Name of column for z values"); parm.zcol->description = _("Writes z values to column"); parm.zcol->guisection = _("3D output"); parm.ztype = G_define_option(); parm.ztype->key = "column_type"; parm.ztype->type = TYPE_STRING; parm.ztype->required = NO; parm.ztype->multiple = NO; parm.ztype->description = _("Type of column for z values"); parm.ztype->options = "integer,double precision"; parm.ztype->answer = "double precision"; parm.ztype->guisection = _("3D output"); flag.z = G_define_flag(); flag.z->key = 'z'; flag.z->description = _("Create 3D output"); flag.z->guisection = _("3D output"); flag.a = G_define_flag(); flag.a->key = 'a'; flag.a->description = _("Generate n points for each individual area"); flag.notopo = G_define_standard_flag(G_FLG_V_TOPO); if (G_parser(argc, argv)) exit(EXIT_FAILURE); output = parm.output->answer; n = atoi(parm.nsites->answer); if(parm.seed->answer) seed = atoi(parm.seed->answer); if (n <= 0) { G_fatal_error(_("Number of points must be > 0 (%d given)"), n); } nareas = 0; cat_list = NULL; field = -1; if (parm.input->answer) { Vect_set_open_level(2); /* topology required */ if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer)) G_fatal_error(_("Unable to open vector map <%s>"), parm.input->answer); if (parm.field->answer) field = Vect_get_field_number(&In, parm.field->answer); if ((parm.cats->answer || parm.where->answer) && field == -1) { G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."), field, parm.cats->key, parm.where->key); field = 1; } if (field > 0) cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer, parm.cats->answer); nareas = Vect_get_num_areas(&In); if (nareas == 0) { Vect_close(&In); G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer); } } else { if (flag.a->answer) G_fatal_error(_("The <-%c> flag requires an input vector with areas"), flag.a->key); } /* create new vector map */ if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z)) G_fatal_error(_("Unable to create vector map <%s>"), output); Vect_set_error_handler_io(NULL, &Out); /* Do we need to write random values into attribute table? */ usefloat = -1; 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) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Out), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); db_init_string(&sql); 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); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); /* Create table */ G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql)); } /* Create index */ if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK) G_warning(_("Unable to create index")); /* Grant */ if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) { 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) { 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")); } 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_hist_command(&Out); /* Init the random seed */ if(parm.seed->answer) G_srand48(seed); else G_srand48_auto(); G_get_window(&window); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); if (nareas > 0) { int first = 1, count; struct bound_box abox, bbox; box.W = window.west; box.E = window.east; box.S = window.south; box.N = window.north; box.B = -PORT_DOUBLE_MAX; box.T = PORT_DOUBLE_MAX; count = 0; for (i = 1; i <= nareas; i++) { if (!Vect_get_area_centroid(&In, i)) continue; if (field > 0) { if (Vect_get_area_cats(&In, i, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) continue; } Vect_get_area_box(&In, i, &abox); if (!Vect_box_overlap(&abox, &box)) continue; if (first) { Vect_box_copy(&bbox, &abox); first = 0; } else Vect_box_extend(&bbox, &abox); count++; } if (count == 0) { Vect_close(&In); Vect_close(&Out); Vect_delete(output); G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"), parm.input->answer); } Vect_box_copy(&box, &bbox); /* does the vector overlap with the current region ? */ if (box.W >= window.east || box.E <= window.west || box.S >= window.north || box.N <= window.south) { Vect_close(&In); Vect_close(&Out); Vect_delete(output); G_fatal_error(_("Input vector <%s> does not overlap with the current region"), parm.input->answer); } /* try to reduce the current region */ if (window.east > box.E) window.east = box.E; if (window.west < box.W) window.west = box.W; if (window.north > box.N) window.north = box.N; if (window.south < box.S) window.south = box.S; List = Vect_new_boxlist(1); alloc_size_list = 10; size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE)); } zmin = zmax = 0; if (flag.z->answer || parm.zcol->answer) { zmax = atof(parm.zmax->answer); zmin = atof(parm.zmin->answer); } G_message(_("Generating points...")); if (flag.a->answer && nareas > 0) { struct bound_box abox, bbox; int cat = 1; /* n points for each area */ nareas = Vect_get_num_areas(&In); G_percent(0, nareas, 1); for (area = 1; area <= nareas; area++) { G_percent(area, nareas, 1); if (!Vect_get_area_centroid(&In, area)) continue; if (field > 0) { if (Vect_get_area_cats(&In, area, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) { continue; } } box.W = window.west; box.E = window.east; box.S = window.south; box.N = window.north; box.B = -PORT_DOUBLE_MAX; box.T = PORT_DOUBLE_MAX; Vect_get_area_box(&In, area, &abox); if (!Vect_box_overlap(&box, &abox)) continue; bbox = abox; if (bbox.W < box.W) bbox.W = box.W; if (bbox.E > box.E) bbox.E = box.E; if (bbox.S < box.S) bbox.S = box.S; if (bbox.N > box.N) bbox.N = box.N; for (i = 0; i < n; ++i) { double x, y, z; int outside = 1; int ret; Vect_reset_line(Points); Vect_reset_cats(Cats); while (outside) { x = rng() * (bbox.W - bbox.E) + bbox.E; y = rng() * (bbox.N - bbox.S) + bbox.S; z = rng() * (zmax - zmin) + zmin; ret = Vect_point_in_area(x, y, &In, area, &abox); G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret); if (ret >= 1) { outside = 0; } } if (flag.z->answer) Vect_append_point(Points, x, y, z); else Vect_append_point(Points, x, y, 0.0); if (parm.zcol->answer) { 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) { G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } } Vect_cat_set(Cats, 1, cat++); Vect_write_line(&Out, GV_POINT, Points, Cats); } } } else { /* n points in total */ for (i = 0; i < n; ++i) { double x, y, z; G_percent(i, n, 4); Vect_reset_line(Points); Vect_reset_cats(Cats); x = rng() * (window.west - window.east) + window.east; y = rng() * (window.north - window.south) + window.south; z = rng() * (zmax - zmin) + zmin; if (nareas) { int outside = 1; do { /* select areas by box */ box.E = x; box.W = x; box.N = y; box.S = y; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&In, &box, List); G_debug(3, " %d areas selected by box", List->n_values); /* sort areas by size, the smallest is likely to be the nearest */ if (alloc_size_list < List->n_values) { alloc_size_list = List->n_values; size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE)); } k = 0; for (j = 0; j < List->n_values; j++) { area = List->id[j]; if (!Vect_get_area_centroid(&In, area)) continue; if (field > 0) { if (Vect_get_area_cats(&In, area, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) { continue; } } List->id[k] = List->id[j]; List->box[k] = List->box[j]; size_list[k].i = List->id[k]; box = List->box[k]; size_list[k].box = List->box[k]; size_list[k].size = (box.N - box.S) * (box.E - box.W); k++; } List->n_values = k; if (List->n_values == 2) { /* simple swap */ if (size_list[1].size < size_list[0].size) { size_list[0].i = List->id[1]; size_list[1].i = List->id[0]; size_list[0].box = List->box[1]; size_list[1].box = List->box[0]; } } else if (List->n_values > 2) qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size); for (j = 0; j < List->n_values; j++) { int ret; area = size_list[j].i; ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box); G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret); if (ret >= 1) { outside = 0; break; } } if (outside) { x = rng() * (window.west - window.east) + window.east; y = rng() * (window.north - window.south) + window.south; z = rng() * (zmax - zmin) + zmin; } } while (outside); } if (flag.z->answer) Vect_append_point(Points, x, y, z); else Vect_append_point(Points, x, y, 0.0); if (parm.zcol->answer) { 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) { 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); } G_percent(1, 1, 1); } if (parm.zcol->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } if (!flag.notopo->answer) { Vect_build(&Out); } Vect_close(&Out); exit(EXIT_SUCCESS); }