int main(int argc, char *argv[]) { int out_fd; CELL *result, *rp; int nrows, ncols; int row, col, count_sum; int field; struct GModule *module; struct Option *in_opt, *out_opt, *field_opt; struct Option *method_opt, *size_opt; struct Map_info In; double radius; struct boxlist *List; struct Cell_head region; struct bound_box box; struct line_pnts *Points; struct line_cats *Cats; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("algebra")); G_add_keyword(_("statistics")); G_add_keyword(_("raster")); G_add_keyword(_("aggregation")); module->label = _("Neighborhood analysis tool for vector point maps."); module->description = _("Makes each cell value a " "function of the attribute values assigned to the vector points or centroids " "around it, and stores new cell values in an output raster map."); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); out_opt = G_define_standard_option(G_OPT_R_OUTPUT); method_opt = G_define_option(); method_opt->key = "method"; method_opt->type = TYPE_STRING; method_opt->required = YES; method_opt->options = "count"; method_opt->answer = "count"; method_opt->description = _("Neighborhood operation"); size_opt = G_define_option(); size_opt->key = "size"; size_opt->type = TYPE_DOUBLE; size_opt->required = YES; size_opt->description = _("Neighborhood diameter in map units"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); radius = atof(size_opt->answer) / 2; /* open input vector */ Vect_set_open_level(2); if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); field = Vect_get_field_number(&In, field_opt->answer); G_get_set_window(®ion); nrows = Rast_window_rows(); ncols = Rast_window_cols(); result = Rast_allocate_buf(CELL_TYPE); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); List = Vect_new_boxlist(0); /*open the new cellfile */ out_fd = Rast_open_new(out_opt->answer, CELL_TYPE); box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; count_sum = 0; for (row = 0; row < nrows; row++) { double x, y; G_percent(row, nrows, 2); y = Rast_row_to_northing(row + 0.5, ®ion); box.N = y + radius; box.S = y - radius; Rast_set_null_value(result, ncols, CELL_TYPE); rp = result; for (col = 0; col < ncols; col++) { int i, count; CELL value; x = Rast_col_to_easting(col + 0.5, ®ion); box.E = x + radius; box.W = x - radius; Vect_select_lines_by_box(&In, &box, GV_POINTS, List); G_debug(3, " %d lines in box", List->n_values); count = 0; for (i = 0; i < List->n_values; i++) { Vect_read_line(&In, Points, Cats, List->id[i]); if (field != -1 && Vect_cat_get(Cats, field, NULL) == 0) continue; if (Vect_points_distance(x, y, 0.0, Points->x[0], Points->y[0], 0.0, 0) <= radius) count++; } if (count > 0) { value = count; Rast_set_d_value(rp, value, CELL_TYPE); } rp = G_incr_void_ptr(rp, Rast_cell_size(CELL_TYPE)); count_sum += count; } Rast_put_row(out_fd, result, CELL_TYPE); } G_percent(1, 1, 1); Vect_close(&In); Rast_close(out_fd); if (count_sum < 1) G_warning(_("No points found")); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int lfield, pfield, n_points, n_outside, n_found, n_no_record, n_many_records; int line, type, nlines; double thresh, multip; struct Option *lines_opt, *points_opt; struct Option *lfield_opt, *pfield_opt; struct Option *driver_opt, *database_opt, *table_opt, *thresh_opt; struct GModule *module; const char *mapset; struct Map_info LMap, PMap; struct line_cats *LCats, *PCats; struct line_pnts *LPoints, *PPoints; dbDriver *rsdriver; dbHandle rshandle; dbString rsstmt; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("Linear Reference System")); G_add_keyword(_("networking")); module->description = _("Finds line id and real km+offset for given points in vector map " "using linear reference system."); lines_opt = G_define_standard_option(G_OPT_V_INPUT); lines_opt->key = "lines"; lines_opt->description = _("Input vector map containing lines"); points_opt = G_define_standard_option(G_OPT_V_INPUT); points_opt->key = "points"; points_opt->description = _("Input vector map containing points"); lfield_opt = G_define_standard_option(G_OPT_V_FIELD); lfield_opt->key = "llayer"; lfield_opt->answer = "1"; lfield_opt->description = _("Line layer"); pfield_opt = G_define_standard_option(G_OPT_V_FIELD); pfield_opt->key = "player"; pfield_opt->answer = "1"; pfield_opt->description = _("Point layer"); driver_opt = G_define_option(); driver_opt->key = "rsdriver"; driver_opt->type = TYPE_STRING; driver_opt->required = NO; driver_opt->description = _("Driver name for reference system table"); driver_opt->options = db_list_drivers(); driver_opt->answer = db_get_default_driver_name(); database_opt = G_define_option(); database_opt->key = "rsdatabase"; database_opt->type = TYPE_STRING; database_opt->required = NO; database_opt->description = _("Database name for reference system table"); database_opt->answer = db_get_default_database_name(); table_opt = G_define_option(); table_opt->key = "rstable"; table_opt->type = TYPE_STRING; table_opt->required = YES; table_opt->description = _("Name of the reference system table"); thresh_opt = G_define_option(); thresh_opt->key = "threshold"; thresh_opt->type = TYPE_DOUBLE; thresh_opt->required = NO; thresh_opt->answer = "1000"; thresh_opt->description = _("Maximum distance to nearest line"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); LCats = Vect_new_cats_struct(); PCats = Vect_new_cats_struct(); LPoints = Vect_new_line_struct(); PPoints = Vect_new_line_struct(); lfield = atoi(lfield_opt->answer); pfield = atoi(pfield_opt->answer); multip = 1000; /* Number of map units per MP unit */ thresh = atof(thresh_opt->answer); /* Open input lines */ mapset = G_find_vector2(lines_opt->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), lines_opt->answer); Vect_set_open_level(2); if (Vect_open_old(&LMap, lines_opt->answer, mapset) < 0) G_fatal_error(_("Unable to open vector map <%s>"), lines_opt->answer); /* Open input points */ mapset = G_find_vector2(points_opt->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), points_opt->answer); Vect_set_open_level(2); if (Vect_open_old(&PMap, points_opt->answer, mapset) < 0) G_fatal_error(_("Unable to open vector map <%s>"), points_opt->answer); db_init_handle(&rshandle); db_init_string(&rsstmt); rsdriver = db_start_driver(driver_opt->answer); db_set_handle(&rshandle, database_opt->answer, NULL); if (db_open_database(rsdriver, &rshandle) != DB_OK) G_fatal_error(_("Unable to open database for reference table")); n_points = n_outside = n_found = n_no_record = n_many_records = 0; nlines = Vect_get_num_lines(&PMap); G_debug(2, "nlines = %d", nlines); G_message("pcat|lid|mpost|offset"); for (line = 1; line <= nlines; line++) { int nearest, pcat, lcat, lid, ret; double along, mpost, offset; G_debug(3, "point = %d", line); type = Vect_read_line(&PMap, PPoints, PCats, line); if (type != GV_POINT) continue; Vect_cat_get(PCats, pfield, &pcat); if (pcat < 0) continue; n_points++; nearest = Vect_find_line(&LMap, PPoints->x[0], PPoints->y[0], 0.0, GV_LINE, thresh, 0, 0); fprintf(stdout, "%d", pcat); if (nearest <= 0) { fprintf(stdout, "|-|- # outside threshold\n"); n_outside++; continue; } /* Read nearest line */ Vect_read_line(&LMap, LPoints, LCats, nearest); Vect_cat_get(LCats, lfield, &lcat); Vect_line_distance(LPoints, PPoints->x[0], PPoints->y[0], 0.0, 0, NULL, NULL, NULL, NULL, NULL, &along); G_debug(3, " nearest = %d lcat = %d along = %f", nearest, lcat, along); if (lcat >= 0) { ret = LR_get_milepost(rsdriver, table_opt->answer, "lcat", "lid", "start_map", "end_map", "start_mp", "start_off", "end_mp", "end_off", lcat, along, multip, &lid, &mpost, &offset); } else { ret = 0; } if (ret == 0) { n_no_record++; fprintf(stdout, "|-|- # no record\n"); continue; } if (ret == 2) { n_many_records++; fprintf(stdout, "|-|- # too many records\n"); continue; } G_debug(3, " lid = %d mpost = %f offset = %f", lid, mpost, offset); fprintf(stdout, "|%d|%f+%f\n", lid, mpost, offset); n_found++; } db_close_database(rsdriver); /* Free, close ... */ Vect_close(&LMap); Vect_close(&PMap); G_message(_n("[%d] point read from input", "[%d] points read from input", n_points), n_points); G_message(_n("[%d] position found", "[%d] positions found", n_found), n_found); if (n_outside) G_message(_n("[%d] point outside threshold", "[%d] points outside threshold", n_outside), n_outside); if (n_no_record) G_message(_n("[%d] point - no record found", "[%d] points - no record found", n_no_record), n_no_record); if (n_many_records) G_message(_n("[%d] point - too many records found", "[%d] points - too many records found", n_many_records), n_many_records); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, j, ret, centre, line, centre1, centre2; int nlines, nnodes, type, ltype, afield, nfield, geo, cat; int node, node1, node2; double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1, l2; struct Option *map, *output; struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt, *term_opt; struct Flag *geo_f; struct GModule *module; char *mapset; struct Map_info Map, Out; struct cat_list *catlist; CENTER *Centers = NULL; int acentres = 0, ncentres = 0; NODE *Nodes; struct line_cats *Cats; struct line_pnts *Points, *SPoints; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, network, allocation"); module->label = _("Allocate subnets for nearest centres (direction from centre)."); module->description = _("Centre node must be opened (costs >= 0). " "Costs of centre node are used in calculation"); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->description = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->answer = "1"; afield_opt->description = _("Arc layer"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->description = _("Node layer"); afcol = G_define_option(); afcol->key = "afcolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); abcol = G_define_option(); abcol->key = "abcolumn"; abcol->type = TYPE_STRING; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); ncol = G_define_option(); ncol->key = "ncolumn"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of centres (points on nodes) to which net " "will be allocated, " "layer for this categories is given by nlayer option"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); SPoints = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); nfield = atoi(nfield_opt->answer); catlist = Vect_new_cat_list(); Vect_str_to_cat_list(term_opt->answer, catlist); if (geo_f->answer) geo = 1; else geo = 0; mapset = G_find_vector2(map->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), map->answer); Vect_set_open_level(2); Vect_open_old(&Map, map->answer, mapset); /* Build graph */ Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); nnodes = Vect_get_num_nodes(&Map); /* Create list of centres based on list of categories */ for (node = 1; node <= nnodes; node++) { nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, node, j)); ltype = Vect_read_line(&Map, NULL, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, nfield, &cat))) continue; if (Vect_cat_in_cat_list(cat, catlist)) { Vect_net_get_node_cost(&Map, node, &n1cost); if (n1cost == -1) { /* closed */ G_warning("Centre at closed node (costs = -1) ignored"); } else { if (acentres == ncentres) { acentres += 1; Centers = (CENTER *) G_realloc(Centers, acentres * sizeof(CENTER)); } Centers[ncentres].cat = cat; Centers[ncentres].node = node; G_debug(2, "centre = %d node = %d cat = %d", ncentres, node, cat); ncentres++; } } } } G_message(_("Number of centres: [%d] (nlayer: [%d])"), ncentres, nfield); if (ncentres == 0) G_warning(_("Not enough centres for selected nlayer. " "Nothing will be allocated.")); /* alloc and reset space for all nodes */ Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE)); for (i = 1; i <= nnodes; i++) { Nodes[i].centre = -1; } /* Fill Nodes by neares centre and costs from that centre */ G_message(_("Calculating costs from centres ...")); for (centre = 0; centre < ncentres; centre++) { G_percent(centre, ncentres, 1); node1 = Centers[centre].node; Vect_net_get_node_cost(&Map, node1, &n1cost); G_debug(2, "centre = %d node = %d cat = %d", centre, node1, Centers[centre].cat); for (node2 = 1; node2 <= nnodes; node2++) { G_debug(5, " node1 = %d node2 = %d", node1, node2); Vect_net_get_node_cost(&Map, node2, &n2cost); if (n2cost == -1) { continue; } /* closed, left it as not attached */ ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost); if (ret == -1) { continue; } /* node unreachable */ /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but * only if centre and node are not identical, because at the end node cost is add later */ if (node1 != node2) cost += n1cost; G_debug(5, "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f", node1, node2, cost, Nodes[node2].centre, Nodes[node2].cost); if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) { Nodes[node2].cost = cost; Nodes[node2].centre = centre; } } } G_percent(1, 1, 1); /* Write arcs to new map */ Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)); Vect_hist_command(&Out); nlines = Vect_get_num_lines(&Map); for (line = 1; line <= nlines; line++) { ltype = Vect_read_line(&Map, Points, NULL, line); if (!(ltype & type)) { continue; } Vect_get_line_nodes(&Map, line, &node1, &node2); centre1 = Nodes[node1].centre; centre2 = Nodes[node2].centre; s1cost = Nodes[node1].cost; s2cost = Nodes[node2].cost; G_debug(3, "Line %d:", line); G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2, node1, node2); Vect_net_get_node_cost(&Map, node1, &n1cost); Vect_net_get_node_cost(&Map, node2, &n2cost); Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost); Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost); G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost, e1cost); G_debug(3, " s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost, e2cost); Vect_reset_cats(Cats); /* First check if arc is reachable from at least one side */ if ((centre1 != -1 && n1cost != -1 && e1cost != -1) || (centre2 != -1 && n2cost != -1 && e2cost != -1)) { /* Line is reachable at least from one side */ G_debug(3, " -> arc is reachable"); if (centre1 == centre2) { /* both nodes in one area -> whole arc in one area */ if (centre1 != -1) cat = Centers[centre1].cat; /* line reachable */ else cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else { /* each node in different area */ /* Check if direction is reachable */ if (centre1 == -1 || n1cost == -1 || e1cost == -1) { /* closed from first node */ G_debug(3, " -> arc is not reachable from 1. node -> alloc to 2. node"); cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); continue; } else if (centre2 == -1 || n2cost == -1 || e2cost == -1) { /* closed from second node */ G_debug(3, " -> arc is not reachable from 2. node -> alloc to 1. node"); cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); continue; } /* Now we know that arc is reachable from both sides */ /* Add costs of node to starting costs */ s1cost += n1cost; s2cost += n2cost; /* Check if s1cost + e1cost <= s2cost or s2cost + e2cost <= s1cost ! * Note this check also possibility of (e1cost + e2cost) = 0 */ if (s1cost + e1cost <= s2cost) { /* whole arc reachable from node1 */ cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else if (s2cost + e2cost <= s1cost) { /* whole arc reachable from node2 */ cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else { /* split */ /* Calculate relative costs - we expect that costs along the line do not change */ l = Vect_line_length(Points); e1cost /= l; e2cost /= l; G_debug(3, " -> s1cost = %f e1cost = %f", s1cost, e1cost); G_debug(3, " -> s2cost = %f e2cost = %f", s2cost, e2cost); /* Costs from both centres to the splitting point must be equal: * s1cost + l1 * e1cost = s2cost + l2 * e2cost */ l1 = (l * e2cost - s1cost + s2cost) / (e1cost + e2cost); l2 = l - l1; G_debug(3, "l = %f l1 = %f l2 = %f", l, l1, l2); /* First segment */ ret = Vect_line_segment(Points, 0, l1, SPoints); if (ret == 0) { G_warning(_("Cannot get line segment, segment out of line")); } else { cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, SPoints, Cats); } /* Second segment */ ret = Vect_line_segment(Points, l1, l, SPoints); if (ret == 0) { G_warning(_("Cannot get line segment, segment out of line")); } else { Vect_reset_cats(Cats); cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, SPoints, Cats); } } } } else { /* arc is not reachable */ G_debug(3, " -> arc is not reachable"); Vect_write_line(&Out, ltype, Points, Cats); } } Vect_build(&Out); /* Free, ... */ G_free(Nodes); G_free(Centers); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { char *p; int i, j, k; int method, half, use_catno; const char *mapset; struct GModule *module; struct Option *point_opt, /* point vector */ *area_opt, /* area vector */ *point_type_opt, /* point type */ *point_field_opt, /* point layer */ *area_field_opt, /* area layer */ *method_opt, /* stats method */ *point_column_opt, /* point column for stats */ *count_column_opt, /* area column for point count */ *stats_column_opt, /* area column for stats result */ *fs_opt; /* field separator for printed output */ struct Flag *print_flag; char fs[2]; struct Map_info PIn, AIn; int point_type, point_field, area_field; struct line_pnts *Points; struct line_cats *ACats, *PCats; AREA_CAT *Area_cat; int pline, ptype, count; int area, nareas, nacats, nacatsalloc; int ctype, nrec; struct field_info *PFi, *AFi; dbString stmt; dbDriver *Pdriver, *Adriver; char buf[2000]; int update_ok, update_err; struct boxlist *List; struct bound_box box; dbCatValArray cvarr; dbColumn *column; struct pvalcat { double dval; int catno; } *pvalcats; int npvalcats, npvalcatsalloc; stat_func *statsvalue = NULL; double result; column = NULL; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("database")); G_add_keyword(_("attribute table")); module->description = _("Count points in areas, calculate statistics from point attributes."); point_opt = G_define_standard_option(G_OPT_V_INPUT); point_opt->key = "points"; point_opt->description = _("Name of existing vector map with points"); /* point_opt->guisection = _("Required"); */ area_opt = G_define_standard_option(G_OPT_V_INPUT); area_opt->key = "areas"; area_opt->description = _("Name of existing vector map with areas"); /* area_opt->guisection = _("Required"); */ point_type_opt = G_define_standard_option(G_OPT_V_TYPE); point_type_opt->key = "type"; point_type_opt->options = "point,centroid"; point_type_opt->answer = "point"; point_type_opt->label = _("Feature type"); point_type_opt->required = NO; point_field_opt = G_define_standard_option(G_OPT_V_FIELD); point_field_opt->key = "player"; point_field_opt->label = _("Layer number for points map"); area_field_opt = G_define_standard_option(G_OPT_V_FIELD); area_field_opt->key = "alayer"; area_field_opt->label = _("Layer number for area map"); method_opt = G_define_option(); method_opt->key = "method"; method_opt->type = TYPE_STRING; method_opt->required = NO; method_opt->multiple = NO; p = G_malloc(1024); for (i = 0; menu[i].name; i++) { if (i) strcat(p, ","); else *p = 0; strcat(p, menu[i].name); } method_opt->options = p; method_opt->description = _("Method for aggregate statistics"); point_column_opt = G_define_standard_option(G_OPT_DB_COLUMN); point_column_opt->key = "pcolumn"; point_column_opt->required = NO; point_column_opt->multiple = NO; point_column_opt->label = _("Column name of points map to use for statistics"); point_column_opt->description = _("Column of points map must be numeric"); count_column_opt = G_define_option(); count_column_opt->key = "ccolumn"; count_column_opt->type = TYPE_STRING; count_column_opt->required = NO; count_column_opt->multiple = NO; count_column_opt->label = _("Column name to upload points count"); count_column_opt->description = _("Column to hold points count, must be of type integer, will be created if not existing"); stats_column_opt = G_define_option(); stats_column_opt->key = "scolumn"; stats_column_opt->type = TYPE_STRING; stats_column_opt->required = NO; stats_column_opt->multiple = NO; stats_column_opt->label = _("Column name to upload statistics"); stats_column_opt->description = _("Column to hold statistics, must be of type double, will be created if not existing"); fs_opt = G_define_standard_option(G_OPT_F_SEP); fs_opt->answer = "|"; fs_opt->key_desc = "character|space|tab"; fs_opt->description = _("Output field separator"); print_flag = G_define_flag(); print_flag->key = 'p'; print_flag->label = _("Print output to stdout, do not update attribute table"); print_flag->description = _("First column is always area category"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); point_type = Vect_option_to_types(point_type_opt); point_field = atoi(point_field_opt->answer); area_field = atoi(area_field_opt->answer); strcpy(fs, " "); if (print_flag->answer) { /* get field separator */ if (fs_opt->answer) { if (strcmp(fs_opt->answer, "space") == 0) *fs = ' '; else if (strcmp(fs_opt->answer, "tab") == 0) *fs = '\t'; else if (strcmp(fs_opt->answer, "\\t") == 0) *fs = '\t'; else *fs = *fs_opt->answer; } else *fs = '|'; } /* check for stats */ if (method_opt->answer) { if (!point_column_opt->answer) { G_fatal_error("Method but no point column selected"); } if (!print_flag->answer && !stats_column_opt->answer) G_fatal_error("Name for stats column is missing"); } if (point_column_opt->answer) { if (!method_opt->answer) G_fatal_error("No method for statistics selected"); if (!print_flag->answer && !stats_column_opt->answer) G_fatal_error("Name for stats column is missing"); } /* Open points vector */ if ((mapset = G_find_vector2(point_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), point_opt->answer); Vect_set_open_level(2); Vect_open_old(&PIn, point_opt->answer, mapset); /* Open areas vector */ if ((mapset = G_find_vector2(area_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), area_opt->answer); if (!print_flag->answer && strcmp(mapset, G_mapset()) != 0) G_fatal_error(_("Vector map <%s> is not in user mapset and cannot be updated"), area_opt->answer); Vect_set_open_level(2); Vect_open_old(&AIn, area_opt->answer, mapset); method = -1; use_catno = 0; half = 0; if (method_opt->answer) { /* get the method */ for (method = 0; (p = menu[method].name); method++) if ((strcmp(p, method_opt->answer) == 0)) break; if (!p) { G_warning(_("<%s=%s> unknown %s"), method_opt->key, method_opt->answer, method_opt->answer); G_usage(); exit(EXIT_FAILURE); } /* establish the statsvalue routine */ statsvalue = menu[method].method; /* category number of lowest/highest value */ if ((strcmp(menu[method].name, menu[5].name) == 0) || (strcmp(menu[method].name, menu[7].name) == 0)) use_catno = 1; G_debug(1, "method: %s, use cat value: %s", menu[method].name, (use_catno == 1 ? "yes" : "no")); } /* Open database driver */ db_init_string(&stmt); Adriver = NULL; if (!print_flag->answer) { AFi = Vect_get_field(&AIn, area_field); if (AFi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), area_field); Adriver = db_start_driver_open_database(AFi->driver, AFi->database); if (Adriver == NULL) G_fatal_error(_("Unable to open database <%s> with driver <%s>"), AFi->database, AFi->driver); if (!count_column_opt->answer) G_fatal_error(_("ccolumn is required to upload point counts")); /* check if count column exists */ G_debug(1, "check if count column exists"); db_get_column(Adriver, AFi->table, count_column_opt->answer, &column); if (column) { /* check count column type */ if (db_column_Ctype(Adriver, AFi->table, count_column_opt->answer) != DB_C_TYPE_INT) G_fatal_error(_("ccolumn must be of type integer")); db_free_column(column); column = NULL; } else { /* create count column */ /* db_add_column() exists but is not implemented, * see lib/db/stubs/add_col.c */ sprintf(buf, "alter table %s add column %s integer", AFi->table, count_column_opt->answer); db_set_string(&stmt, buf); if (db_execute_immediate(Adriver, &stmt) != DB_OK) G_fatal_error(_("Unable to add column <%s>"), count_column_opt->answer); } if (method_opt->answer) { if (!stats_column_opt->answer) G_fatal_error(_("scolumn is required to upload point stats")); /* check if stats column exists */ G_debug(1, "check if stats column exists"); db_get_column(Adriver, AFi->table, stats_column_opt->answer, &column); if (column) { /* check stats column type */ if (db_column_Ctype (Adriver, AFi->table, stats_column_opt->answer) != DB_C_TYPE_DOUBLE) G_fatal_error(_("scolumn must be of type double")); db_free_column(column); column = NULL; } else { /* create stats column */ /* db_add_column() exists but is not implemented, * see lib/db/stubs/add_col.c */ sprintf(buf, "alter table %s add column %s double", AFi->table, stats_column_opt->answer); db_set_string(&stmt, buf); if (db_execute_immediate(Adriver, &stmt) != DB_OK) G_fatal_error(_("Unable to add column <%s>"), stats_column_opt->answer); } } } else AFi = NULL; Pdriver = NULL; if (method_opt->answer) { G_verbose_message(_("collecting attributes from points vector...")); PFi = Vect_get_field(&PIn, point_field); if (PFi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), point_field); Pdriver = db_start_driver_open_database(PFi->driver, PFi->database); if (Pdriver == NULL) G_fatal_error(_("Unable to open database <%s> with driver <%s>"), PFi->database, PFi->driver); /* check if point column exists */ db_get_column(Pdriver, PFi->table, point_column_opt->answer, &column); if (column) { db_free_column(column); column = NULL; } else { G_fatal_error(_("Column <%s> not found in table <%s>"), point_column_opt->answer, PFi->table); } /* Check column type */ ctype = db_column_Ctype(Pdriver, PFi->table, point_column_opt->answer); if (ctype == DB_C_TYPE_INT) half = menu[method].half; else if (ctype == DB_C_TYPE_DOUBLE) half = 0; else G_fatal_error(_("column for points vector must be numeric")); db_CatValArray_init(&cvarr); nrec = db_select_CatValArray(Pdriver, PFi->table, PFi->key, point_column_opt->answer, NULL, &cvarr); G_debug(1, "selected values = %d", nrec); db_close_database_shutdown_driver(Pdriver); } Points = Vect_new_line_struct(); ACats = Vect_new_cats_struct(); PCats = Vect_new_cats_struct(); List = Vect_new_boxlist(0); /* Allocate space ( may be more than needed (duplicate cats and elements without cats) ) */ if ((nareas = Vect_get_num_areas(&AIn)) <= 0) G_fatal_error("No areas in area input vector"); nacatsalloc = nareas; Area_cat = (AREA_CAT *) G_calloc(nacatsalloc, sizeof(AREA_CAT)); /* Read all cats from 'area' */ nacats = 0; for (area = 1; area <= nareas; area++) { Vect_get_area_cats(&AIn, area, ACats); if (ACats->n_cats <= 0) continue; for (i = 0; i < ACats->n_cats; i++) { if (ACats->field[i] == area_field) { Area_cat[nacats].area_cat = ACats->cat[i]; Area_cat[nacats].count = 0; Area_cat[nacats].nvalues = 0; Area_cat[nacats].nalloc = 0; nacats++; if (nacats >= nacatsalloc) { nacatsalloc += 100; Area_cat = (AREA_CAT *) G_realloc(Area_cat, nacatsalloc * sizeof(AREA_CAT)); } } } } G_debug(1, "%d cats loaded from vector (including duplicates)", nacats); /* Sort by category */ qsort((void *)Area_cat, nacats, sizeof(AREA_CAT), cmp_area); /* remove duplicate categories */ for (i = 1; i < nacats; i++) { if (Area_cat[i].area_cat == Area_cat[i - 1].area_cat) { for (j = i; j < nacats - 1; j++) { Area_cat[j].area_cat = Area_cat[j + 1].area_cat; } nacats--; } } G_debug(1, "%d cats loaded from vector (unique)", nacats); /* Go through all areas in area vector and find points in points vector * falling into the area */ npvalcatsalloc = 10; npvalcats = 0; pvalcats = (struct pvalcat *)G_calloc(npvalcatsalloc, sizeof(struct pvalcat)); G_message(_("Selecting points for each area...")); count = 0; for (area = 1; area <= nareas; area++) { dbCatVal *catval; G_debug(3, "area = %d", area); G_percent(area, nareas, 2); Vect_get_area_cats(&AIn, area, ACats); if (ACats->n_cats <= 0) continue; /* select points by box */ Vect_get_area_box(&AIn, area, &box); box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_lines_by_box(&PIn, &box, point_type, List); G_debug(4, "%d points selected by box", List->n_values); /* For each point in box check if it is in the area */ for (i = 0; i < List->n_values; i++) { pline = List->id[i]; G_debug(4, "%d: point %d", i, pline); ptype = Vect_read_line(&PIn, Points, PCats, pline); if (!(ptype & point_type)) continue; /* point in area */ if (Vect_point_in_area(Points->x[0], Points->y[0], &AIn, area, box)) { AREA_CAT *area_info, search_ai; int tmp_cat; /* stats on point column */ if (method_opt->answer) { npvalcats = 0; tmp_cat = -1; for (j = 0; j < PCats->n_cats; j++) { if (PCats->field[j] == point_field) { if (tmp_cat >= 0) G_debug(3, "More cats found in point layer (point=%d)", pline); tmp_cat = PCats->cat[j]; /* find cat in array */ db_CatValArray_get_value(&cvarr, tmp_cat, &catval); if (catval) { pvalcats[npvalcats].catno = tmp_cat; switch (cvarr.ctype) { case DB_C_TYPE_INT: pvalcats[npvalcats].dval = catval->val.i; npvalcats++; break; case DB_C_TYPE_DOUBLE: pvalcats[npvalcats].dval = catval->val.d; npvalcats++; break; } if (npvalcats >= npvalcatsalloc) { npvalcatsalloc += 10; pvalcats = (struct pvalcat *)G_realloc(pvalcats, npvalcatsalloc * sizeof (struct pvalcat)); } } } } } /* update count for all area cats of given field */ search_ai.area_cat = -1; for (j = 0; j < ACats->n_cats; j++) { if (ACats->field[j] == area_field) { if (search_ai.area_cat >= 0) G_debug(3, "More cats found in area layer (area=%d)", area); search_ai.area_cat = ACats->cat[j]; /* find cat in array */ area_info = (AREA_CAT *) bsearch((void *)&search_ai, Area_cat, nacats, sizeof(AREA_CAT), cmp_area); if (area_info->area_cat != search_ai.area_cat) G_fatal_error(_("could not find area category %d"), search_ai.area_cat); /* each point is counted once, also if it has * more than one category or no category * OK? */ area_info->count++; if (method_opt->answer) { /* ensure enough space */ if (area_info->nvalues + npvalcats >= area_info->nalloc) { if (area_info->nalloc == 0) { area_info->nalloc = npvalcats + 10; area_info->values = (double *)G_calloc(area_info->nalloc, sizeof(double)); area_info->cats = (int *)G_calloc(area_info->nalloc, sizeof(int)); } else area_info->nalloc += area_info->nvalues + npvalcats + 10; area_info->values = (double *)G_realloc(area_info->values, area_info->nalloc * sizeof(double)); area_info->cats = (int *)G_realloc(area_info->cats, area_info->nalloc * sizeof(int)); } for (k = 0; k < npvalcats; k++) { area_info->cats[area_info->nvalues] = pvalcats[k].catno; area_info->values[area_info->nvalues] = pvalcats[k].dval; area_info->nvalues++; } } } } count++; } } /* next point in box */ } /* next area */ G_debug(1, "count = %d", count); /* release catval array */ if (method_opt->answer) db_CatValArray_free(&cvarr); Vect_close(&PIn); /* Update table or print to stdout */ if (print_flag->answer) { /* print header */ fprintf(stdout, "area_cat%scount", fs); if (method_opt->answer) fprintf(stdout, "%s%s", fs, menu[method].name); fprintf(stdout, "\n"); } else { G_message("Updating attributes for area vector..."); update_err = update_ok = 0; } if (Adriver) db_begin_transaction(Adriver); for (i = 0; i < nacats; i++) { if (!print_flag->answer) G_percent(i, nacats, 2); result = 0; if (Area_cat[i].count > 0 && method_opt->answer) { /* get stats */ statsvalue(&result, Area_cat[i].values, Area_cat[i].nvalues, NULL); if (half) result += 0.5; else if (use_catno) result = Area_cat[i].cats[(int)result]; } if (print_flag->answer) { fprintf(stdout, "%d%s%d", Area_cat[i].area_cat, fs, Area_cat[i].count); if (method_opt->answer) { if (Area_cat[i].count > 0) fprintf(stdout, "%s%.15g", fs, result); else fprintf(stdout, "%snull", fs); } fprintf(stdout, "\n"); } else { sprintf(buf, "update %s set %s = %d", AFi->table, count_column_opt->answer, Area_cat[i].count); db_set_string(&stmt, buf); if (method_opt->answer) { if (Area_cat[i].count > 0) sprintf(buf, " , %s = %.15g", stats_column_opt->answer, result); else sprintf(buf, " , %s = null", stats_column_opt->answer); db_append_string(&stmt, buf); } sprintf(buf, " where %s = %d", AFi->key, Area_cat[i].area_cat); db_append_string(&stmt, buf); G_debug(2, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(Adriver, &stmt) == DB_OK) { update_ok++; } else { update_err++; } } } if (Adriver) db_commit_transaction(Adriver); if (!print_flag->answer) { G_percent(nacats, nacats, 2); db_close_database_shutdown_driver(Adriver); db_free_string(&stmt); G_message(_("%d records updated"), update_ok); if (update_err > 0) G_message(_("%d update errors"), update_err); Vect_set_db_updated(&AIn); } Vect_close(&AIn); G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, j, k, ret, city, city1; int nlines, type, ltype, afield, tfield, geo, cat; int node, node1, node2, line; struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt, *term_opt; struct Flag *geo_f; struct GModule *module; char *mapset; struct Map_info Map, Out; struct ilist *TList; /* list of terminal nodes */ struct ilist *List; struct ilist *StArcs; /* list of arcs on Steiner tree */ struct ilist *StNodes; /* list of nodes on Steiner tree */ double cost, tmpcost, tcost; struct cat_list *Clist; struct line_cats *Cats; struct line_pnts *Points; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, network, salesman"); module->label = _("Creates a cycle connecting given nodes (Traveling salesman problem)."); module->description = _("Note that TSP is NP-hard, heuristic algorithm is used by " "this module and created cycle may be sub optimal"); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->description = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->description = _("Arc layer"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "nlayer"; tfield_opt->answer = "2"; tfield_opt->description = _("Node layer (used for cities)"); afcol = G_define_option(); afcol->key = "acolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arcs' cost column (for both directions)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of points ('cities') on nodes " "(layer is specified by nlayer)"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); TList = Vect_new_list(); List = Vect_new_list(); StArcs = Vect_new_list(); StNodes = Vect_new_list(); Clist = Vect_new_cat_list(); tfield = atoi(tfield_opt->answer); Vect_str_to_cat_list(term_opt->answer, Clist); G_debug(1, "Imput categories:\n"); for (i = 0; i < Clist->n_ranges; i++) { G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]); } if (geo_f->answer) geo = 1; else geo = 0; Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT); mapset = G_find_vector2(map->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), map->answer); Vect_set_open_level(2); Vect_open_old(&Map, map->answer, mapset); nnodes = Vect_get_num_nodes(&Map); /* Create list of terminals based on list of categories */ for (i = 1; i <= nnodes; i++) { nlines = Vect_get_node_n_lines(&Map, i); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, i, j)); ltype = Vect_read_line(&Map, NULL, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; if (Vect_cat_in_cat_list(cat, Clist)) { Vect_list_append(TList, i); } } } ncities = TList->n_values; G_message(_("Number of cities: [%d]"), ncities); if (ncities < 2) G_fatal_error(_("Not enough cities (< 2)")); /* Alloc memory */ cities = (int *)G_malloc(ncities * sizeof(int)); cused = (int *)G_malloc(ncities * sizeof(int)); for (i = 0; i < ncities; i++) { G_debug(1, "%d\n", TList->value[i]); cities[i] = TList->value[i]; cused[i] = 0; /* not in cycle */ } costs = (COST **) G_malloc(ncities * sizeof(COST *)); for (i = 0; i < ncities; i++) { costs[i] = (COST *) G_malloc(ncities * sizeof(COST)); } cycle = (int *)G_malloc((ncities + 1) * sizeof(int)); /* + 1 is for output cycle */ /* Build graph */ Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL, geo, 0); /* Create sorted lists of costs */ for (i = 0; i < ncities; i++) { k = 0; for (j = 0; j < ncities; j++) { if (i == j) continue; ret = Vect_net_shortest_path(&Map, cities[i], cities[j], NULL, &cost); if (ret == -1) G_fatal_error(_("Destination node [%d] is unreachable " "from node [%d]"), cities[i], cities[j]); costs[i][k].city = j; costs[i][k].cost = cost; k++; } qsort((void *)costs[i], k, sizeof(COST), cmp); } /* debug: print sorted */ for (i = 0; i < ncities; i++) { for (j = 0; j < ncities - 1; j++) { city = costs[i][j].city; G_debug(2, "%d -> %d = %f\n", cities[i], cities[city], costs[i][j].cost); } } /* find 2 cities with largest distance */ cost = -1; for (i = 0; i < ncities; i++) { tmpcost = costs[i][ncities - 2].cost; if (tmpcost > cost) { cost = tmpcost; city = i; } } G_debug(2, "biggest costs %d - %d\n", city, costs[city][ncities - 2].city); /* add this 2 cities to array */ add_city(city, -1); add_city(costs[city][ncities - 2].city, 0); /* In each step, find not used city, with biggest cost to any used city, and insert * into cycle between 2 nearest nodes */ for (i = 0; i < ncities - 2; i++) { cost = -1; G_debug(2, "---- %d ----\n", i); for (j = 0; j < ncities; j++) { if (cused[j] == 1) continue; tmpcost = 0; for (k = 0; k < ncities - 1; k++) { G_debug(2, "? %d (%d) - %d (%d) \n", j, cnode(j), costs[j][k].city, cnode(costs[j][k].city)); if (!cused[costs[j][k].city]) continue; /* only used */ tmpcost += costs[j][k].cost; break; /* first nearest */ } G_debug(2, " cost = %f x %f\n", tmpcost, cost); if (tmpcost > cost) { cost = tmpcost; city = j; } } G_debug(2, "add %d\n", city); /* add to cycle on lovest costs */ cycle[ncyc] = cycle[0]; /* tmp for cycle */ cost = PORT_DOUBLE_MAX; for (j = 0; j < ncyc; j++) { node1 = cities[cycle[j]]; node2 = cities[cycle[j + 1]]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost = -tcost; node1 = cities[cycle[j]]; node2 = cities[city]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost += tcost; node1 = cities[cycle[j + 1]]; node2 = cities[city]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost += tcost; G_debug(2, "? %d - %d cost = %f x %f\n", node1, node2, tmpcost, cost); if (tmpcost < cost) { city1 = j; cost = tmpcost; } } add_city(city, city1); } /* Print */ G_debug(2, "Cycle:\n"); for (i = 0; i < ncities; i++) { G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]); } /* Create list of arcs */ cycle[ncities] = cycle[0]; for (i = 0; i < ncities; i++) { node1 = cities[cycle[i]]; node2 = cities[cycle[i + 1]]; G_debug(2, " %d -> %d\n", node1, node2); ret = Vect_net_shortest_path(&Map, node1, node2, List, NULL); for (j = 0; j < List->n_values; j++) { line = abs(List->value[j]); Vect_list_append(StArcs, line); Vect_get_line_nodes(&Map, line, &node1, &node2); Vect_list_append(StNodes, node1); Vect_list_append(StNodes, node2); } } /* Write arcs to new map */ Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)); Vect_hist_command(&Out); fprintf(stdout, "\nCycle:\n"); fprintf(stdout, "Arcs' categories (layer %d, %d arcs):\n", afield, StArcs->n_values); for (i = 0; i < StArcs->n_values; i++) { line = StArcs->value[i]; ltype = Vect_read_line(&Map, Points, Cats, line); Vect_write_line(&Out, ltype, Points, Cats); Vect_cat_get(Cats, afield, &cat); if (i > 0) printf(","); fprintf(stdout, "%d", cat); } fprintf(stdout, "\n\n"); fprintf(stdout, "Nodes' categories (layer %d, %d nodes):\n", tfield, StNodes->n_values); k = 0; for (i = 0; i < StNodes->n_values; i++) { node = StNodes->value[i]; nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, node, j)); ltype = Vect_read_line(&Map, Points, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; Vect_write_line(&Out, ltype, Points, Cats); if (k > 0) fprintf(stdout, ","); fprintf(stdout, "%d", cat); k++; } } fprintf(stdout, "\n\n"); Vect_build(&Out); /* Free, ... */ Vect_destroy_list(StArcs); Vect_destroy_list(StNodes); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *map_opt, *type_opt, *percentile; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("statistics")); G_add_keyword(_("univariate statistics")); G_add_keyword(_("attribute table")); G_add_keyword(_("geometry")); module->label = _("Calculates univariate statistics of vector map features."); module->description = _("Variance and standard " "deviation is calculated only for points if specified."); map_opt = G_define_standard_option(G_OPT_V_MAP); field_opt = G_define_standard_option(G_OPT_V_FIELD); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "point,line,boundary,centroid,area"; type_opt->answer = "point,line,area"; col_opt = G_define_standard_option(G_OPT_DB_COLUMN); col_opt->required = NO; where_opt = G_define_standard_option(G_OPT_DB_WHERE); percentile = G_define_option(); percentile->key = "percentile"; percentile->type = TYPE_INTEGER; percentile->required = NO; percentile->options = "0-100"; percentile->answer = "90"; percentile->description = _("Percentile to calculate (requires extended statistics flag)"); shell_flag = G_define_flag(); shell_flag->key = 'g'; shell_flag->description = _("Print the stats in shell script style"); ext_flag = G_define_flag(); ext_flag->key = 'e'; ext_flag->description = _("Calculate extended statistics"); weight_flag = G_define_flag(); weight_flag->key = 'w'; weight_flag->description = _("Weigh by line length or area size"); geometry = G_define_flag(); geometry->key = 'd'; geometry->description = _("Calculate geometric distances instead of attribute statistics"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* Only require col_opt answer if -g flag is not set */ if (!col_opt->answer && !geometry->answer) { G_fatal_error(_("Required parameter <%s> not set:\n\t(%s)"), col_opt->key, col_opt->description); } otype = Vect_option_to_types(type_opt); perc = atoi(percentile->answer); Cats = Vect_new_cats_struct(); /* open input vector */ Vect_set_open_level(2); if (Vect_open_old2(&Map, map_opt->answer, "", field_opt->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), map_opt->answer); ofield = Vect_get_field_number(&Map, field_opt->answer); if ((otype & GV_POINT) && Vect_get_num_primitives(&Map, GV_POINT) == 0) { otype &= ~(GV_POINT); if (otype & GV_POINT) G_fatal_error("Bye"); } if ((otype & GV_CENTROID) && Vect_get_num_primitives(&Map, GV_CENTROID) == 0) { otype &= ~(GV_CENTROID); } if ((otype & GV_LINE) && Vect_get_num_primitives(&Map, GV_LINE) == 0) { otype &= ~(GV_LINE); } if ((otype & GV_BOUNDARY) && Vect_get_num_primitives(&Map, GV_BOUNDARY) == 0) { otype &= ~(GV_BOUNDARY); } if ((otype & GV_AREA) && Vect_get_num_areas(&Map) == 0) { otype &= ~(GV_AREA); } /* Check if types are compatible */ if ((otype & GV_POINTS) && ((otype & GV_LINES) || (otype & GV_AREA))) compatible = 0; if ((otype & GV_LINES) && (otype & GV_AREA)) compatible = 0; if (!compatible && geometry->answer) compatible = 1; /* distances is compatible with GV_POINTS and GV_LINES */ if (!compatible && !weight_flag->answer) compatible = 1; /* attributes are always compatible without weight */ if (geometry->answer && (otype & GV_AREA)) G_fatal_error(_("Geometry distances are not supported for areas. Use '%s' instead."), "v.distance"); if (!compatible) { G_warning(_("Incompatible vector type(s) specified, only number of features, minimum, maximum and range " "can be calculated")); } if (ext_flag->answer && (!(otype & GV_POINTS) || geometry->answer)) { G_warning(_("Extended statistics is currently supported only for points/centroids")); } if (geometry->answer) select_from_geometry(); else select_from_database(); summary(); Vect_close(&Map); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int i, iopt; int operator; int aline, nalines, nskipped; int ltype, itype[2], ifield[2]; int **cats, *ncats, nfields, *fields; char *mapset[2], *pre[2]; struct GModule *module; struct GParm parm; struct GFlag flag; struct Map_info In[2], Out; struct field_info *IFi, *OFi; struct line_pnts *APoints, *BPoints; struct line_cats *ACats, *BCats; int *ALines; /* List of lines: 0 do not output, 1 - write to output */ struct ilist *List, *TmpList, *BoundList; G_gisinit(argv[0]); pre[0] = "a"; pre[1] = "b"; module = G_define_module(); module->keywords = _("vector, spatial query"); module->description = _("Selects features from vector map (A) by features from other vector map (B)."); parse_options(&parm, &flag); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (parm.operator->answer[0] == 'e') operator = OP_EQUALS; else if (parm.operator->answer[0] == 'd') { /* operator = OP_DISJOINT; */ operator = OP_INTERSECTS; flag.reverse->answer = YES; } else if (parm.operator->answer[0] == 'i') operator = OP_INTERSECTS; else if (parm.operator->answer[0] == 't') operator = OP_TOUCHES; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r') operator = OP_CROSSES; else if (parm.operator->answer[0] == 'w') operator = OP_WITHIN; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o') operator = OP_CONTAINS; else if (parm.operator->answer[0] == 'o') { if (strcmp(parm.operator->answer, "overlaps") == 0) operator = OP_OVERLAPS; else operator = OP_OVERLAP; } else if (parm.operator->answer[0] == 'r') operator = OP_RELATE; else G_fatal_error(_("Unknown operator")); if (operator == OP_RELATE && !parm.relate->answer) { G_fatal_error(_("Required parameter <%s> not set"), parm.relate->key); } for (iopt = 0; iopt < 2; iopt++) { itype[iopt] = Vect_option_to_types(parm.type[iopt]); ifield[iopt] = atoi(parm.field[iopt]->answer); Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer, GV_FATAL_EXIT); if ((mapset[iopt] = G_find_vector2(parm.input[iopt]->answer, NULL)) == NULL) { G_fatal_error(_("Vector map <%s> not found"), parm.input[iopt]->answer); } Vect_set_open_level(2); Vect_open_old(&(In[iopt]), parm.input[iopt]->answer, mapset[iopt]); } /* Read field info */ IFi = Vect_get_field(&(In[0]), ifield[0]); APoints = Vect_new_line_struct(); BPoints = Vect_new_line_struct(); ACats = Vect_new_cats_struct(); BCats = Vect_new_cats_struct(); List = Vect_new_list(); TmpList = Vect_new_list(); BoundList = Vect_new_list(); /* Open output */ Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0]))); Vect_set_map_name(&Out, _("Output from v.select")); Vect_set_person(&Out, G_whoami()); Vect_copy_head_data(&(In[0]), &Out); Vect_hist_copy(&(In[0]), &Out); Vect_hist_command(&Out); nskipped = 0; nalines = Vect_get_num_lines(&(In[0])); #ifdef HAVE_GEOS initGEOS(G_message, G_fatal_error); GEOSGeometry *AGeom = NULL; #else void *AGeom = NULL; #endif /* Alloc space for input lines array */ ALines = (int *)G_calloc(nalines + 1, sizeof(int)); G_message(_("Building spatial index...")); Vect_build_spatial_index(&In[0]); Vect_build_spatial_index(&In[1]); /* Lines in A. Go through all lines and mark those that meets condition */ if (itype[0] & (GV_POINTS | GV_LINES)) { G_message(_("Processing features...")); for (aline = 1; aline <= nalines; aline++) { BOUND_BOX abox; G_debug(3, "aline = %d", aline); G_percent(aline, nalines, 2); /* must be before any continue */ /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[0]), aline, ifield[0]) < 0) { nskipped++; continue; } /* Read line and check type */ if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_line_geos(&(In[0]), aline, <ype); #endif if (!(ltype & (GV_POINT | GV_LINE))) continue; if (!AGeom) G_fatal_error(_("Unable to read line id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } else { ltype = Vect_read_line(&(In[0]), APoints, NULL, aline); } if (!(ltype & itype[0])) continue; Vect_get_line_box(&(In[0]), aline, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; /* Check if this line overlaps any feature in B */ /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { int i; int found = 0; /* Lines */ Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; G_debug(3, " bline = %d", bline); /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { found = 1; break; } #endif } else { Vect_read_line(&(In[1]), BPoints, NULL, bline); if (Vect_line_check_intersection(APoints, BPoints, 0)) { found = 1; break; } } } if (found) { ALines[aline] = 1; continue; /* Go to next A line */ } } /* x Areas in B. */ if (itype[1] & GV_AREA) { int i; Vect_select_areas_by_box(&(In[1]), &abox, List); for (i = 0; i < List->n_values; i++) { int barea; barea = List->value[i]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { ALines[aline] = 1; break; } #endif } else { if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { ALines[aline] = 1; break; } } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } /* Areas in A. */ if (itype[0] & GV_AREA) { int aarea, naareas; G_message(_("Processing areas...")); naareas = Vect_get_num_areas(&(In[0])); for (aarea = 1; aarea <= naareas; aarea++) { BOUND_BOX abox; G_percent(aarea, naareas, 2); /* must be before any continue */ if (Vect_get_area_cat(&(In[0]), aarea, ifield[0]) < 0) { nskipped++; continue; } Vect_get_area_box(&(In[0]), aarea, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_area_geos(&(In[0]), aarea); #endif if (!AGeom) G_fatal_error(_("Unable to read area id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { add_aarea(&(In[0]), aarea, ALines); break; } #endif } else { if (line_overlap_area(&(In[1]), bline, &(In[0]), aarea)) { add_aarea(&(In[0]), aarea, ALines); continue; } } } } /* x Areas in B */ if (itype[1] & GV_AREA) { int naisles; int found = 0; /* List of areas B */ /* Make a list of features forming area A */ Vect_reset_list(List); Vect_get_area_boundaries(&(In[0]), aarea, BoundList); for (i = 0; i < BoundList->n_values; i++) { Vect_list_append(List, abs(BoundList->value[i])); } naisles = Vect_get_area_num_isles(&(In[0]), aarea); for (i = 0; i < naisles; i++) { int j, aisle; aisle = Vect_get_area_isle(&(In[0]), aarea, i); Vect_get_isle_boundaries(&(In[0]), aisle, BoundList); for (j = 0; j < BoundList->n_values; j++) { Vect_list_append(List, BoundList->value[j]); } } Vect_select_areas_by_box(&(In[1]), &abox, TmpList); for (i = 0; i < List->n_values; i++) { int j, aline; aline = abs(List->value[i]); for (j = 0; j < TmpList->n_values; j++) { int barea, bcentroid; barea = TmpList->value[j]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } /* Check if any centroid of area B is in area A. * This test is important in if area B is completely within area A */ bcentroid = Vect_get_area_centroid(&(In[1]), barea); Vect_read_line(&(In[1]), BPoints, NULL, bcentroid); if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { found = 1; break; } #endif } else { if (Vect_point_in_area(&(In[0]), aarea, BPoints->x[0], BPoints->y[0])) { found = 1; break; } /* Check intersectin of lines from List with area B */ if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { found = 1; break; } } } if (found) { add_aarea(&(In[0]), aarea, ALines); break; } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } Vect_close(&(In[1])); #ifdef HAVE_GEOS finishGEOS(); #endif /* Write lines */ nfields = Vect_cidx_get_num_fields(&(In[0])); cats = (int **)G_malloc(nfields * sizeof(int *)); ncats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { ncats[i] = 0; cats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&(In[0]), i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(&(In[0]), i); } G_message(_("Writing selected features...")); for (aline = 1; aline <= nalines; aline++) { int atype; G_debug(4, "aline = %d ALines[aline] = %d", aline, ALines[aline]); G_percent(aline, nalines, 2); if ((!flag.reverse->answer && !(ALines[aline])) || (flag.reverse->answer && ALines[aline])) continue; atype = Vect_read_line(&(In[0]), APoints, ACats, aline); Vect_write_line(&Out, atype, APoints, ACats); if (!(flag.table->answer) && (IFi != NULL)) { for (i = 0; i < ACats->n_cats; i++) { int f, j; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == ACats->field[i]) { f = j; break; } } cats[f][ncats[f]] = ACats->cat[i]; ncats[f]++; } } } /* Copy tables */ if (!(flag.table->answer)) { int ttype, ntabs = 0; G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(&(In[0])); i++) { int f, j; IFi = Vect_get_dblink(&(In[0]), i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (ncats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; /* Make a list of categories */ IFi = Vect_get_field(&(In[0]), fields[i]); if (!IFi) { /* no table */ G_warning(_("Layer %d - no table"), fields[i]); continue; } OFi = Vect_default_field_info(&Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, &Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Layer %d - unable to copy table"), fields[i]); } else { Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } } Vect_close(&(In[0])); Vect_build(&Out); Vect_close(&Out); if (nskipped > 0) { G_warning(_("%d features without category skipped"), nskipped); } G_done_msg(_("%d features written to output."), Vect_get_num_lines(&Out)); exit(EXIT_SUCCESS); }
int vect_to_rast(const char *vector_map, const char *raster_map, const char *field_name, const char *column, int cache_mb, int use, double value, int value_type, const char *rgbcolumn, const char *labelcolumn, int ftype, char *where, char *cats, int dense) { struct Map_info Map; struct line_pnts *Points; int i, field; struct cat_list *cat_list = NULL; int fd; /* for raster map */ int nareas, nlines; /* number of converted features */ int nareas_all, nplines_all; /* number of all areas, points/lines */ int stat; int format; int pass, npasses; /* Attributes */ int nrec; int ctype = 0; struct field_info *Fi; dbDriver *Driver; dbCatValArray cvarr; int is_fp = 0; nareas = 0; G_verbose_message(_("Loading data...")); Vect_set_open_level(2); if (Vect_open_old2(&Map, vector_map, "", field_name) < 0) G_fatal_error(_("Unable to open vector map <%s>"), vector_map); field = Vect_get_field_number(&Map, field_name); if (field > 0) cat_list = Vect_cats_set_constraint(&Map, field, where, cats); if ((use == USE_Z) && !(Vect_is_3d(&Map))) G_fatal_error(_("Vector map <%s> is not 3D"), Vect_get_full_name(&Map)); switch (use) { case USE_ATTR: db_CatValArray_init(&cvarr); if (!(Fi = Vect_get_field(&Map, field))) G_fatal_error(_("Database connection not defined for layer <%s>"), field_name); if ((Driver = db_start_driver_open_database(Fi->driver, Fi->database)) == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(Driver); /* Note do not check if the column exists in the table because it may be expression */ if ((nrec = db_select_CatValArray(Driver, Fi->table, Fi->key, column, NULL, &cvarr)) == -1) G_fatal_error(_("Column <%s> not found"), column); G_debug(3, "nrec = %d", nrec); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type (%s) not supported (did you mean 'labelcolumn'?)"), db_sqltype_name(ctype)); if (nrec < 0) G_fatal_error(_("No records selected from table <%s>"), Fi->table); G_debug(1, "%d records selected from table", nrec); db_close_database_shutdown_driver(Driver); for (i = 0; i < cvarr.n_values; i++) { if (ctype == DB_C_TYPE_INT) { G_debug(3, "cat = %d val = %d", cvarr.value[i].cat, cvarr.value[i].val.i); } else if (ctype == DB_C_TYPE_DOUBLE) { G_debug(3, "cat = %d val = %f", cvarr.value[i].cat, cvarr.value[i].val.d); } } switch (ctype) { case DB_C_TYPE_INT: format = CELL_TYPE; break; case DB_C_TYPE_DOUBLE: format = DCELL_TYPE; break; default: G_fatal_error(_("Unable to use column <%s>"), column); break; } break; case USE_CAT: format = CELL_TYPE; break; case USE_VAL: format = value_type; break; case USE_Z: format = DCELL_TYPE; is_fp = 1; break; case USE_D: format = DCELL_TYPE; break; default: G_fatal_error(_("Unknown use type: %d"), use); } fd = Rast_open_new(raster_map, format); Points = Vect_new_line_struct(); if (use != USE_Z && use != USE_D && (ftype & GV_AREA)) { if ((nareas = sort_areas(&Map, Points, field, cat_list)) == 0) G_warning(_("No areas selected from vector map <%s>"), vector_map); G_debug(1, "%d areas sorted", nareas); } if (nareas > 0 && dense) { G_warning(_("Area conversion and line densification are mutually exclusive, disabling line densification.")); dense = 0; } nlines = Vect_get_num_primitives(&Map, ftype); nplines_all = nlines; npasses = begin_rasterization(cache_mb, format, dense); pass = 0; nareas_all = Vect_get_num_areas(&Map); do { pass++; if (npasses > 1) G_message(_("Pass %d of %d:"), pass, npasses); stat = 0; if ((use != USE_Z && use != USE_D) && nareas) { if (do_areas (&Map, Points, &cvarr, ctype, use, value, value_type) < 0) { G_warning(_("Problem processing areas from vector map <%s>, continuing..."), vector_map); stat = -1; break; } } if (nlines) { if ((nlines = do_lines(&Map, Points, &cvarr, ctype, field, cat_list, use, value, value_type, ftype, &nplines_all, dense)) < 0) { G_warning(_("Problem processing lines from vector map <%s>, continuing..."), vector_map); stat = -1; break; } } G_important_message(_("Writing raster map...")); stat = output_raster(fd); } while (stat == 0); G_suppress_warnings(0); /* stat: 0 == repeat; 1 == done; -1 == error; */ Vect_destroy_line_struct(Points); if (stat < 0) { Rast_unopen(fd); return 1; } Vect_close(&Map); G_verbose_message(_("Creating support files for raster map...")); Rast_close(fd); update_hist(raster_map, vector_map, Map.head.orig_scale); /* colors */ if (rgbcolumn) { if (use != USE_ATTR && use != USE_CAT) { G_warning(_("Color can be updated from database only if use=attr")); update_colors(raster_map); } else { update_dbcolors(raster_map, vector_map, field, rgbcolumn, is_fp, column); } } else if (use == USE_D) update_fcolors(raster_map); else update_colors(raster_map); update_cats(raster_map); /* labels */ update_labels(raster_map, vector_map, field, labelcolumn, use, value, column); #if 0 /* maximum possible numer of areas: number of centroids * actual number of areas, currently unknown: * number of areas with centroid that are within cat constraint * and overlap with current region */ if (nareas_all > 0) G_message(_("Converted areas: %d of %d"), nareas, Vect_get_num_primitives(&Map, GV_CENTROID)); /* maximum possible numer of lines: number of GV_LINE + GV_POINT * actual number of lines, currently unknown: * number of lines are within cat constraint * and overlap with current region */ if (nlines > 0 && nplines_all > 0) G_message(_("Converted points/lines: %d of %d"), nlines, nplines_all); #endif return 0; }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats, *TCats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *catf_opt, *fieldf_opt, *wheref_opt; struct Option *catt_opt, *fieldt_opt, *wheret_opt, *typet_opt; struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol, *atype_opt; struct Flag *geo_f; int with_z, geo; int atype, ttype; struct varray *varrayf, *varrayt; int flayer, tlayer; int afield, nfield; dglGraph_s *graph; struct ilist *nodest; int i, nnodes, nlines; int *dst, *nodes_to_features; int from_nr; /* 'from' features not reachable */ dglInt32_t **prev; struct line_cats **on_path; char buf[2000]; /* Attribute table */ dbString sql; dbDriver *driver; struct field_info *Fi; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("shortest path")); module->label = _("Computes shortest distance via the network between " "the given sets of features."); module->description = _("Finds the shortest paths from each 'from' point to the nearest 'to' feature " "and various information about this relation are uploaded to the attribute table."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); map_out = G_define_standard_option(G_OPT_V_OUTPUT); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); afield_opt->guisection = _("Cost"); atype_opt = G_define_standard_option(G_OPT_V_TYPE); atype_opt->options = "line,boundary"; atype_opt->answer = "line,boundary"; atype_opt->label = _("Arc type"); atype_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); fieldf_opt = G_define_standard_option(G_OPT_V_FIELD); fieldf_opt->key = "from_layer"; fieldf_opt->label = _("From layer number or name"); fieldf_opt->guisection = _("From"); catf_opt = G_define_standard_option(G_OPT_V_CATS); catf_opt->key = "from_cats"; catf_opt->label = _("From category values"); catf_opt->guisection = _("From"); wheref_opt = G_define_standard_option(G_OPT_DB_WHERE); wheref_opt->key = "from_where"; wheref_opt->label = _("From WHERE conditions of SQL statement without 'where' keyword"); wheref_opt->guisection = _("From"); fieldt_opt = G_define_standard_option(G_OPT_V_FIELD); fieldt_opt->key = "to_layer"; fieldt_opt->description = _("To layer number or name"); fieldt_opt->guisection = _("To"); typet_opt = G_define_standard_option(G_OPT_V_TYPE); typet_opt->key = "to_type"; typet_opt->options = "point,line,boundary"; typet_opt->answer = "point"; typet_opt->description = _("To feature type"); typet_opt->guisection = _("To"); catt_opt = G_define_standard_option(G_OPT_V_CATS); catt_opt->key = "to_cats"; catt_opt->label = _("To category values"); catt_opt->guisection = _("To"); wheret_opt = G_define_standard_option(G_OPT_DB_WHERE); wheret_opt->key = "to_where"; wheret_opt->label = _("To WHERE conditions of SQL statement without 'where' keyword"); wheret_opt->guisection = _("To"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "afcolumn"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "abcolumn"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "ncolumn"; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); atype = Vect_option_to_types(atype_opt); ttype = Vect_option_to_types(typet_opt); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); TCats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } if (geo_f->answer) { geo = 1; if (G_projection() != PROJECTION_LL) G_warning(_("The current projection is not longitude-latitude")); } else geo = 0; nnodes = Vect_get_num_nodes(&In); nlines = Vect_get_num_lines(&In); dst = (int *)G_calloc(nnodes + 1, sizeof(int)); prev = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); nodes_to_features = (int *)G_calloc(nnodes + 1, sizeof(int)); on_path = (struct line_cats **)G_calloc(nlines + 1, sizeof(struct line_cats *)); if (!dst || !prev || !nodes_to_features || !on_path) G_fatal_error(_("Out of memory")); for (i = 1; i <= nlines; i++) on_path[i] = Vect_new_cats_struct(); /*initialise varrays and nodes list appropriatelly */ afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); flayer = atoi(fieldf_opt->answer); tlayer = atoi(fieldt_opt->answer); if (NetA_initialise_varray(&In, flayer, GV_POINT, wheref_opt->answer, catf_opt->answer, &varrayf) <= 0) { G_fatal_error(_("No 'from' features selected. " "Please check options '%s', '%s', '%s'."), fieldf_opt->key, wheref_opt->key, catf_opt->key); } if (NetA_initialise_varray(&In, tlayer, ttype, wheret_opt->answer, catt_opt->answer, &varrayt) <= 0) { G_fatal_error(_("No 'to' features selected. " "Please check options '%s', '%s', '%s'."), fieldt_opt->key, wheret_opt->key, catt_opt->key); } nodest = Vect_new_list(); NetA_varray_to_nodes(&In, varrayt, nodest, nodes_to_features); if (nodest->n_values == 0) G_fatal_error(_("No 'to' features")); if (0 != Vect_net_build_graph(&In, atype, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 0)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); NetA_distance_from_points(graph, nodest, dst, prev); /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver); sprintf(buf, "create table %s ( cat integer, tcat integer, dist double precision)", Fi->table); db_set_string(&sql, buf); G_debug(2, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); from_nr = 0; for (i = 1; i <= nlines; i++) { if (varrayf->c[i]) { int type = Vect_read_line(&In, Points, Cats, i); int node, tcat, cat; double cost; dglInt32_t *vertex, vertex_id; if (!Vect_cat_get(Cats, flayer, &cat)) continue; if (type & GV_POINTS) { node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0); } else { Vect_get_line_nodes(&In, i, &node, NULL); } if (node < 1) continue; if (dst[node] < 0) { /* unreachable */ from_nr++; continue; } cost = dst[node] / (double)In.dgraph.cost_multip; vertex = dglGetNode(graph, node); vertex_id = node; while (prev[vertex_id] != NULL) { Vect_cat_set(on_path [abs(dglEdgeGet_Id(graph, prev[vertex_id]))], 1, cat); vertex = dglEdgeGet_Head(graph, prev[vertex_id]); vertex_id = dglNodeGet_Id(graph, vertex); } G_debug(3, "read line %d, vertex id %d", nodes_to_features[vertex_id], (int)vertex_id); Vect_read_line(&In, NULL, TCats, nodes_to_features[vertex_id]); if (!Vect_cat_get(TCats, tlayer, &tcat)) continue; Vect_write_line(&Out, type, Points, Cats); sprintf(buf, "insert into %s values (%d, %d, %f)", Fi->table, cat, tcat, cost); db_set_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql)); }; } } for (i = 1; i <= nlines; i++) if (on_path[i]->n_cats > 0) { int type = Vect_read_line(&In, Points, NULL, i); Vect_write_line(&Out, type, Points, on_path[i]); } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); for (i = 1; i <= nlines; i++) Vect_destroy_cats_struct(on_path[i]); G_free(on_path); G_free(nodes_to_features); G_free(dst); G_free(prev); if (from_nr) G_warning(_n("%d 'from' feature was not reachable", "%d 'from' features were not reachable", from_nr), from_nr); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int i, j, k; int print_as_matrix; /* only for all */ int all; /* calculate from each to each within the threshold */ struct GModule *module; struct Option *from_opt, *to_opt, *from_type_opt, *to_type_opt, *from_field_opt, *to_field_opt; struct Option *out_opt, *max_opt, *min_opt, *table_opt; struct Option *upload_opt, *column_opt, *to_column_opt; struct Flag *print_flag, *all_flag; struct Map_info From, To, Out, *Outp; int from_type, to_type, from_field, to_field; double max, min; double *max_step; int n_max_steps, curr_step; struct line_pnts *FPoints, *TPoints; struct line_cats *FCats, *TCats; NEAR *Near, *near; int anear; /* allocated space, used only for all */ UPLOAD *Upload; /* zero terminated */ int ftype, fcat, tcat, count; int nfrom, nto, nfcats, fline, tline, tseg, tarea, area, isle, nisles; double tx, ty, tz, dist, talong, tmp_tx, tmp_ty, tmp_tz, tmp_dist, tmp_talong; struct field_info *Fi, *toFi; dbString stmt, dbstr; dbDriver *driver, *to_driver; int *catexist, ncatexist, *cex; char buf1[2000], buf2[2000]; int update_ok, update_err, update_exist, update_notexist, update_dupl, update_notfound; struct boxlist *List; struct bound_box box; dbCatValArray cvarr; dbColumn *column; all = 0; print_as_matrix = 0; column = NULL; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("database")); G_add_keyword(_("attribute table")); module->description = _("Finds the nearest element in vector map 'to' for elements in vector map 'from'."); from_opt = G_define_standard_option(G_OPT_V_INPUT); from_opt->key = "from"; from_opt->description = _("Name of existing vector map (from)"); from_opt->guisection = _("From"); from_field_opt = G_define_standard_option(G_OPT_V_FIELD); from_field_opt->key = "from_layer"; from_field_opt->label = _("Layer number or name (from)"); from_field_opt->guisection = _("From"); from_type_opt = G_define_standard_option(G_OPT_V_TYPE); from_type_opt->key = "from_type"; from_type_opt->options = "point,centroid"; from_type_opt->answer = "point"; from_type_opt->label = _("Feature type (from)"); from_type_opt->guisection = _("From"); to_opt = G_define_standard_option(G_OPT_V_INPUT); to_opt->key = "to"; to_opt->description = _("Name of existing vector map (to)"); to_opt->guisection = _("To"); to_field_opt = G_define_standard_option(G_OPT_V_FIELD); to_field_opt->key = "to_layer"; to_field_opt->label = _("Layer number or name (to)"); to_field_opt->guisection = _("To"); to_type_opt = G_define_standard_option(G_OPT_V_TYPE); to_type_opt->key = "to_type"; to_type_opt->options = "point,line,boundary,centroid,area"; to_type_opt->answer = "point,line,area"; to_type_opt->label = _("Feature type (to)"); to_type_opt->guisection = _("To"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->key = "output"; out_opt->required = NO; out_opt->description = _("Name for output vector map containing lines " "connecting nearest elements"); max_opt = G_define_option(); max_opt->key = "dmax"; max_opt->type = TYPE_DOUBLE; max_opt->required = NO; max_opt->answer = "-1"; max_opt->description = _("Maximum distance or -1 for no limit"); min_opt = G_define_option(); min_opt->key = "dmin"; min_opt->type = TYPE_DOUBLE; min_opt->required = NO; min_opt->answer = "-1"; min_opt->description = _("Minimum distance or -1 for no limit"); upload_opt = G_define_option(); upload_opt->key = "upload"; upload_opt->type = TYPE_STRING; upload_opt->required = YES; upload_opt->multiple = YES; upload_opt->options = "cat,dist,to_x,to_y,to_along,to_angle,to_attr"; upload_opt->description = _("Values describing the relation between two nearest features"); upload_opt->descriptions = _("cat;category of the nearest feature;" "dist;minimum distance to nearest feature;" "to_x;x coordinate of the nearest point on 'to' feature;" "to_y;y coordinate of the nearest point on 'to' feature;" "to_along;distance between points/centroids in 'from' map and the linear feature's " "start point in 'to' map, along this linear feature;" "to_angle;angle between the linear feature in 'to' map and the positive x axis, at " "the location of point/centroid in 'from' map, counterclockwise, in radians, which " "is between -PI and PI inclusive;" "to_attr;attribute of nearest feature given by to_column option"); /* "from_x - x coordinate of the nearest point on 'from' feature;" */ /* "from_y - y coordinate of the nearest point on 'from' feature;" */ /* "from_along - distance to the nearest point on 'from' feature along linear feature;" */ column_opt = G_define_standard_option(G_OPT_DB_COLUMN); column_opt->required = YES; column_opt->multiple = YES; column_opt->description = _("Column name(s) where values specified by 'upload' option will be uploaded"); column_opt->guisection = _("From_map"); to_column_opt = G_define_standard_option(G_OPT_DB_COLUMN); to_column_opt->key = "to_column"; to_column_opt->description = _("Column name of nearest feature (used with upload=to_attr)"); to_column_opt->guisection = _("To"); table_opt = G_define_standard_option(G_OPT_DB_TABLE); table_opt->gisprompt = "new_dbtable,dbtable,dbtable"; table_opt->description = _("Name of table created for output when the distance to all flag is used"); print_flag = G_define_flag(); print_flag->key = 'p'; print_flag->label = _("Print output to stdout, don't update attribute table"); print_flag->description = _("First column is always category of 'from' feature called from_cat"); all_flag = G_define_flag(); all_flag->key = 'a'; all_flag->label = _("Calculate distances to all features within the threshold"); all_flag->description = _("The output is written to stdout but may be uploaded " "to a new table created by this module. " "From categories are may be multiple."); /* huh? */ /* GUI dependency */ from_opt->guidependency = G_store(from_field_opt->key); sprintf(buf1, "%s,%s", to_field_opt->key, to_column_opt->key); to_opt->guidependency = G_store(buf1); to_field_opt->guidependency = G_store(to_column_opt->key); if (G_parser(argc, argv)) exit(EXIT_FAILURE); from_type = Vect_option_to_types(from_type_opt); to_type = Vect_option_to_types(to_type_opt); from_field = atoi(from_field_opt->answer); max = atof(max_opt->answer); min = atof(min_opt->answer); if (all_flag->answer) all = 1; /* Read upload and column options */ /* count */ i = 0; while (upload_opt->answers[i]) i++; if (strcmp(from_opt->answer, to_opt->answer) == 0 && all && !table_opt->answer && i == 1) print_as_matrix = 1; /* alloc */ Upload = (UPLOAD *) G_calloc(i + 1, sizeof(UPLOAD)); /* read upload */ i = 0; while (upload_opt->answers[i]) { if (strcmp(upload_opt->answers[i], "cat") == 0) Upload[i].upload = CAT; else if (strcmp(upload_opt->answers[i], "from_x") == 0) Upload[i].upload = FROM_X; else if (strcmp(upload_opt->answers[i], "from_y") == 0) Upload[i].upload = FROM_Y; else if (strcmp(upload_opt->answers[i], "to_x") == 0) Upload[i].upload = TO_X; else if (strcmp(upload_opt->answers[i], "to_y") == 0) Upload[i].upload = TO_Y; else if (strcmp(upload_opt->answers[i], "from_along") == 0) Upload[i].upload = FROM_ALONG; else if (strcmp(upload_opt->answers[i], "to_along") == 0) Upload[i].upload = TO_ALONG; else if (strcmp(upload_opt->answers[i], "dist") == 0) Upload[i].upload = DIST; else if (strcmp(upload_opt->answers[i], "to_angle") == 0) Upload[i].upload = TO_ANGLE; else if (strcmp(upload_opt->answers[i], "to_attr") == 0) { if (!(to_column_opt->answer)) { G_fatal_error(_("to_column option missing")); } Upload[i].upload = TO_ATTR; } i++; } Upload[i].upload = END; /* read columns */ i = 0; while (column_opt->answers[i]) { if (Upload[i].upload == END) { G_warning(_("Too many column names")); break; } Upload[i].column = G_store(column_opt->answers[i]); i++; } if (Upload[i].upload != END) G_fatal_error(_("Not enough column names")); /* Open 'from' vector */ Vect_set_open_level(2); Vect_open_old(&From, from_opt->answer, G_mapset()); /* Open 'to' vector */ Vect_set_open_level(2); Vect_open_old2(&To, to_opt->answer, "", to_field_opt->answer); to_field = Vect_get_field_number(&To, to_field_opt->answer); /* Open output vector */ if (out_opt->answer) { Vect_open_new(&Out, out_opt->answer, WITHOUT_Z); Vect_hist_command(&Out); Outp = &Out; } else { Outp = NULL; } /* TODO: add maxdist = -1 to Vect_select_ !!! */ /* Calc maxdist */ n_max_steps = 1; if (max != 0) { struct bound_box fbox, tbox; double dx, dy, dz, tmp_max; int n_features = 0; Vect_get_map_box(&From, &fbox); Vect_get_map_box(&To, &tbox); Vect_box_extend(&fbox, &tbox); dx = fbox.E - fbox.W; dy = fbox.N - fbox.S; if (Vect_is_3d(&From)) dz = fbox.T - fbox.B; else dz = 0.0; tmp_max = sqrt(dx * dx + dy * dy + dz * dz); if (max < 0) max = tmp_max; /* how to determine a reasonable number of steps to increase the search box? */ /* with max > 0 but max <<< tmp_max, 2 steps are sufficient, first 0 then max * a reasonable number of steps also depends on the number of features in To * e.g. only one area in To, no need to step */ nto = Vect_get_num_lines(&To); for (tline = 1; tline <= nto; tline++) { /* TODO: Vect_get_line_type() */ n_features += ((to_type & To.plus.Line[tline]->type) != 0); } if (to_type & GV_AREA) { if (Vect_get_num_areas(&To) > n_features) n_features = Vect_get_num_areas(&To); } if (n_features == 0) G_fatal_error(_("No features of selected type in To vector <%s>"), to_opt->answer); n_max_steps = sqrt(n_features) * max / tmp_max; /* max 9 steps from testing */ if (n_max_steps > 9) n_max_steps = 9; if (n_max_steps < 2) n_max_steps = 2; if (n_max_steps > n_features) n_max_steps = n_features; G_debug(2, "max = %f", max); G_debug(2, "maximum reasonable search distance = %f", tmp_max); G_debug(2, "n_features = %d", n_features); G_debug(2, "n_max_steps = %d", n_max_steps); } if (min > max) G_fatal_error("dmin can not be larger than dmax"); if (n_max_steps > 1) { /* set up steps to increase search box */ max_step = G_malloc(n_max_steps * sizeof(double)); /* first step always 0 */ max_step[0] = 0; for (curr_step = 1; curr_step < n_max_steps - 1; curr_step++) { /* for 9 steps, this would be max / [128, 64, 32, 16, 8, 4, 2] */ max_step[curr_step] = max / (2 << (n_max_steps - 1 - curr_step)); } /* last step always max */ max_step[n_max_steps - 1] = max; } else { max_step = G_malloc(sizeof(double)); max_step[0] = max; } /* Open database driver */ db_init_string(&stmt); db_init_string(&dbstr); driver = NULL; if (!print_flag->answer) { if (!all) { Fi = Vect_get_field(&From, from_field); if (Fi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), from_field); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); /* check if column exists */ i = 0; while (column_opt->answers[i]) { db_get_column(driver, Fi->table, column_opt->answers[i], &column); if (column) { db_free_column(column); column = NULL; } else { G_fatal_error(_("Column <%s> not found in table <%s>"), column_opt->answers[i], Fi->table); } i++; } } else { driver = db_start_driver_open_database(NULL, NULL); if (driver == NULL) G_fatal_error(_("Unable to open default database")); } } to_driver = NULL; if (to_column_opt->answer) { toFi = Vect_get_field(&To, to_field); if (toFi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), to_field); to_driver = db_start_driver_open_database(toFi->driver, toFi->database); if (to_driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), toFi->database, toFi->driver); /* check if to_column exists */ db_get_column(to_driver, toFi->table, to_column_opt->answer, &column); if (column) { db_free_column(column); column = NULL; } else { G_fatal_error(_("Column <%s> not found in table <%s>"), to_column_opt->answer, toFi->table); } /* Check column types */ if (!print_flag->answer && !all) { char *fcname = NULL; int fctype, tctype; i = 0; while (column_opt->answers[i]) { if (Upload[i].upload == TO_ATTR) { fcname = column_opt->answers[i]; break; } i++; } if (fcname) { fctype = db_column_Ctype(driver, Fi->table, fcname); tctype = db_column_Ctype(to_driver, toFi->table, to_column_opt->answer); if (((tctype == DB_C_TYPE_STRING || tctype == DB_C_TYPE_DATETIME) && (fctype == DB_C_TYPE_INT || fctype == DB_C_TYPE_DOUBLE)) || ((tctype == DB_C_TYPE_INT || tctype == DB_C_TYPE_DOUBLE) && (fctype == DB_C_TYPE_STRING || fctype == DB_C_TYPE_DATETIME)) ) { G_fatal_error(_("Incompatible column types")); } } } } FPoints = Vect_new_line_struct(); TPoints = Vect_new_line_struct(); FCats = Vect_new_cats_struct(); TCats = Vect_new_cats_struct(); List = Vect_new_boxlist(1); /* Allocate space ( may be more than needed (duplicate cats and elements without cats) ) */ nfrom = Vect_get_num_lines(&From); nto = Vect_get_num_lines(&To); if (all) { /* Attention with space for all, it can easily run out of memory */ anear = 2 * nfrom; Near = (NEAR *) G_calloc(anear, sizeof(NEAR)); } else { Near = (NEAR *) G_calloc(nfrom, sizeof(NEAR)); } /* Read all cats from 'from' */ if (!all) { nfcats = 0; for (i = 1; i <= nfrom; i++) { ftype = Vect_read_line(&From, NULL, FCats, i); /* This keeps also categories of areas for future (if area s in from_type) */ if (!(ftype & from_type) && (ftype != GV_CENTROID || !(from_type & GV_AREA))) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0) continue; Near[nfcats].from_cat = fcat; nfcats++; } G_debug(1, "%d cats loaded from vector (including duplicates)", nfcats); /* Sort by cats and remove duplicates */ qsort((void *)Near, nfcats, sizeof(NEAR), cmp_near); /* remove duplicates */ for (i = 1; i < nfcats; i++) { if (Near[i].from_cat == Near[i - 1].from_cat) { for (j = i; j < nfcats - 1; j++) { Near[j].from_cat = Near[j + 1].from_cat; } nfcats--; } } G_debug(1, "%d cats loaded from vector (unique)", nfcats); } /* Go through all lines in 'from' and find nearest in 'to' for each */ /* Note: as from_type is restricted to GV_POINTS (for now) everything is simple */ count = 0; /* count of distances in 'all' mode */ /* Find nearest lines */ if (to_type & (GV_POINTS | GV_LINES)) { struct line_pnts *LLPoints; if (G_projection() == PROJECTION_LL) { LLPoints = Vect_new_line_struct(); } else { LLPoints = NULL; } G_message(_("Finding nearest feature...")); for (fline = 1; fline <= nfrom; fline++) { int tmp_tcat; double tmp_tangle, tangle; double tmp_min = (min < 0 ? 0 : min); double box_edge = 0; int done = 0; curr_step = 0; G_debug(3, "fline = %d", fline); G_percent(fline, nfrom, 2); ftype = Vect_read_line(&From, FPoints, FCats, fline); if (!(ftype & from_type)) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0 && !all) continue; while (!done) { done = 1; if (!all) { /* enlarge search box until we get a hit */ /* the objective is to enlarge the search box * in the first iterations just a little bit * to keep the number of hits low */ Vect_reset_boxlist(List); while (curr_step < n_max_steps) { box_edge = max_step[curr_step]; if (box_edge < tmp_min) continue; box.E = FPoints->x[0] + box_edge; box.W = FPoints->x[0] - box_edge; box.N = FPoints->y[0] + box_edge; box.S = FPoints->y[0] - box_edge; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_lines_by_box(&To, &box, to_type, List); curr_step++; if (List->n_values > 0) break; } } else { box.E = FPoints->x[0] + max; box.W = FPoints->x[0] - max; box.N = FPoints->y[0] + max; box.S = FPoints->y[0] - max; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_lines_by_box(&To, &box, to_type, List); } G_debug(3, " %d lines in box", List->n_values); tline = 0; dist = PORT_DOUBLE_MAX; for (i = 0; i < List->n_values; i++) { tmp_tcat = -1; Vect_read_line(&To, TPoints, TCats, List->id[i]); tseg = Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], (Vect_is_3d(&From) && Vect_is_3d(&To)) ? WITH_Z : WITHOUT_Z, &tmp_tx, &tmp_ty, &tmp_tz, &tmp_dist, NULL, &tmp_talong); Vect_point_on_line(TPoints, tmp_talong, NULL, NULL, NULL, &tmp_tangle, NULL); if (tmp_dist > max || tmp_dist < min) continue; /* not in threshold */ /* TODO: more cats of the same field */ Vect_cat_get(TCats, to_field, &tmp_tcat); if (G_projection() == PROJECTION_LL) { /* calculate distances in meters not degrees (only 2D) */ Vect_reset_line(LLPoints); Vect_append_point(LLPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0]); Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz); tmp_dist = Vect_line_geodesic_length(LLPoints); Vect_reset_line(LLPoints); for (k = 0; k < tseg; k++) Vect_append_point(LLPoints, TPoints->x[k], TPoints->y[k], TPoints->z[k]); Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz); tmp_talong = Vect_line_geodesic_length(LLPoints); } G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist, tmp_tcat); if (all) { if (anear <= count) { anear += 10 + nfrom / 10; Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR)); } near = &(Near[count]); /* store info about relation */ near->from_cat = fcat; near->to_cat = tmp_tcat; /* -1 is OK */ near->dist = tmp_dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->from_z = FPoints->z[0]; near->to_x = tmp_tx; near->to_y = tmp_ty; near->to_z = tmp_tz; near->to_along = tmp_talong; /* 0 for points */ near->to_angle = tmp_tangle; near->count++; count++; } else { if (tline == 0 || (tmp_dist < dist)) { tline = List->id[i]; tcat = tmp_tcat; dist = tmp_dist; tx = tmp_tx; ty = tmp_ty; tz = tmp_tz; talong = tmp_talong; tangle = tmp_tangle; } } } G_debug(4, " dist = %f", dist); if (curr_step < n_max_steps) { /* enlarging the search box is possible */ if (tline > 0 && dist > box_edge) { /* line found but distance > search edge: * line bbox overlaps with search box, line itself is outside search box */ done = 0; } else if (tline == 0) { /* no line within max dist, but search box can still be enlarged */ done = 0; } } if (done && !all && tline > 0) { /* find near by cat */ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats, sizeof(NEAR), cmp_near); G_debug(4, " near.from_cat = %d near.count = %d", near->from_cat, near->count); /* store info about relation */ if (near->count == 0 || near->dist > dist) { near->to_cat = tcat; /* -1 is OK */ near->dist = dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->from_z = FPoints->z[0]; near->to_x = tx; near->to_y = ty; near->to_z = tz; near->to_along = talong; /* 0 for points */ near->to_angle = tangle; } near->count++; } } /* done */ } /* next feature */ if (LLPoints) { Vect_destroy_line_struct(LLPoints); } } /* Find nearest areas */ if (to_type & GV_AREA) { G_message(_("Finding nearest areas...")); for (fline = 1; fline <= nfrom; fline++) { double tmp_min = (min < 0 ? 0 : min); double box_edge = 0; int done = 0; curr_step = 0; G_debug(3, "fline = %d", fline); G_percent(fline, nfrom, 2); ftype = Vect_read_line(&From, FPoints, FCats, fline); if (!(ftype & from_type)) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0 && !all) continue; while (!done) { done = 1; if (!all) { /* enlarge search box until we get a hit */ /* the objective is to enlarge the search box * in the first iterations just a little bit * to keep the number of hits low */ Vect_reset_boxlist(List); while (curr_step < n_max_steps) { box_edge = max_step[curr_step]; if (box_edge < tmp_min) continue; box.E = FPoints->x[0] + box_edge; box.W = FPoints->x[0] - box_edge; box.N = FPoints->y[0] + box_edge; box.S = FPoints->y[0] - box_edge; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&To, &box, List); curr_step++; if (List->n_values > 0) break; } } else { box.E = FPoints->x[0] + max; box.W = FPoints->x[0] - max; box.N = FPoints->y[0] + max; box.S = FPoints->y[0] - max; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&To, &box, List); } G_debug(4, "%d areas selected by box", List->n_values); /* For each area in box check the distance */ tarea = 0; dist = PORT_DOUBLE_MAX; for (i = 0; i < List->n_values; i++) { int tmp_tcat; area = List->id[i]; G_debug(4, "%d: area %d", i, area); Vect_get_area_points(&To, area, TPoints); /* Find the distance to this area */ if (Vect_point_in_area(FPoints->x[0], FPoints->y[0], &To, area, List->box[i])) { /* in area */ tmp_dist = 0; tmp_tx = FPoints->x[0]; tmp_ty = FPoints->y[0]; } else if (Vect_point_in_poly(FPoints->x[0], FPoints->y[0], TPoints) > 0) { /* in isle */ nisles = Vect_get_area_num_isles(&To, area); for (j = 0; j < nisles; j++) { double tmp2_dist, tmp2_tx, tmp2_ty; isle = Vect_get_area_isle(&To, area, j); Vect_get_isle_points(&To, isle, TPoints); Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], WITHOUT_Z, &tmp2_tx, &tmp2_ty, NULL, &tmp2_dist, NULL, NULL); if (j == 0 || tmp2_dist < tmp_dist) { tmp_dist = tmp2_dist; tmp_tx = tmp2_tx; tmp_ty = tmp2_ty; } } } else { /* outside area */ Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], WITHOUT_Z, &tmp_tx, &tmp_ty, NULL, &tmp_dist, NULL, NULL); } if (tmp_dist > max || tmp_dist < min) continue; /* not in threshold */ Vect_get_area_cats(&To, area, TCats); tmp_tcat = -1; /* TODO: all cats of given field ? */ for (j = 0; j < TCats->n_cats; j++) { if (TCats->field[j] == to_field) { if (tmp_tcat >= 0) G_warning(_("More cats found in to_layer (area=%d)"), area); tmp_tcat = TCats->cat[j]; } } G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist, tmp_tcat); if (all) { if (anear <= count) { anear += 10 + nfrom / 10; Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR)); } near = &(Near[count]); /* store info about relation */ near->from_cat = fcat; near->to_cat = tmp_tcat; /* -1 is OK */ near->dist = tmp_dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->to_x = tmp_tx; near->to_y = tmp_ty; near->to_along = 0; /* nonsense for areas */ near->to_angle = 0; /* not supported for areas */ near->count++; count++; } else if (tarea == 0 || tmp_dist < dist) { tarea = area; tcat = tmp_tcat; dist = tmp_dist; tx = tmp_tx; ty = tmp_ty; } } if (curr_step < n_max_steps) { /* enlarging the search box is possible */ if (tarea > 0 && dist > box_edge) { /* area found but distance > search edge: * area bbox overlaps with search box, area itself is outside search box */ done = 0; } else if (tarea == 0) { /* no area within max dist, but search box can still be enlarged */ done = 0; } } if (done && !all && tarea > 0) { /* find near by cat */ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats, sizeof(NEAR), cmp_near); G_debug(4, "near.from_cat = %d near.count = %d dist = %f", near->from_cat, near->count, near->dist); /* store info about relation */ if (near->count == 0 || near->dist > dist) { near->to_cat = tcat; /* -1 is OK */ near->dist = dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->to_x = tx; near->to_y = ty; near->to_along = 0; /* nonsense for areas */ near->to_angle = 0; /* not supported for areas */ } near->count++; } } /* done */ } /* next feature */ } G_debug(3, "count = %d", count); /* Update database / print to stdout / create output map */ if (print_flag->answer) { /* print header */ fprintf(stdout, "from_cat"); i = 0; while (Upload[i].upload != END) { fprintf(stdout, "|%s", Upload[i].column); i++; } fprintf(stdout, "\n"); } else if (all && table_opt->answer) { /* create new table */ db_set_string(&stmt, "create table "); db_append_string(&stmt, table_opt->answer); db_append_string(&stmt, " (from_cat integer"); j = 0; while (Upload[j].upload != END) { db_append_string(&stmt, ", "); switch (Upload[j].upload) { case CAT: sprintf(buf2, "%s integer", Upload[j].column); break; case DIST: case FROM_X: case FROM_Y: case TO_X: case TO_Y: case FROM_ALONG: case TO_ALONG: case TO_ANGLE: sprintf(buf2, "%s double precision", Upload[j].column); } db_append_string(&stmt, buf2); j++; } db_append_string(&stmt, " )"); G_debug(3, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) != DB_OK) G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&stmt)); if (db_grant_on_table(driver, table_opt->answer, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), table_opt->answer); } else if (!all) { /* read existing cats from table */ ncatexist = db_select_int(driver, Fi->table, Fi->key, NULL, &catexist); G_debug(1, "%d cats selected from the table", ncatexist); } update_ok = update_err = update_exist = update_notexist = update_dupl = update_notfound = 0; if (!all) { count = nfcats; } else if (print_as_matrix) { qsort((void *)Near, count, sizeof(NEAR), cmp_near_to); } if (driver) db_begin_transaction(driver); /* select 'to' attributes */ if (to_column_opt->answer) { int nrec; db_CatValArray_init(&cvarr); nrec = db_select_CatValArray(to_driver, toFi->table, toFi->key, to_column_opt->answer, NULL, &cvarr); G_debug(3, "selected values = %d", nrec); if (cvarr.ctype == DB_C_TYPE_DATETIME) { G_warning(_("DATETIME type not yet supported, no attributes will be uploaded")); } db_close_database_shutdown_driver(to_driver); } if (!(print_flag->answer || (all && !table_opt->answer))) /* no printing */ G_message("Update database..."); for (i = 0; i < count; i++) { dbCatVal *catval = 0; if (!(print_flag->answer || (all && !table_opt->answer))) /* no printing */ G_percent(i, count, 1); /* Write line connecting nearest points */ if (Outp != NULL) { Vect_reset_line(FPoints); Vect_reset_cats(FCats); Vect_append_point(FPoints, Near[i].from_x, Near[i].from_y, 0); if (Near[i].dist == 0) { Vect_write_line(Outp, GV_POINT, FPoints, FCats); } else { Vect_append_point(FPoints, Near[i].to_x, Near[i].to_y, 0); Vect_write_line(Outp, GV_LINE, FPoints, FCats); } } if (Near[i].count > 1) update_dupl++; if (Near[i].count == 0) update_notfound++; if (to_column_opt->answer && Near[i].count > 0) { db_CatValArray_get_value(&cvarr, Near[i].to_cat, &catval); } if (print_flag->answer || (all && !table_opt->answer)) { /* print only */ /* input and output is the same && calculate distances && only one upload option given -> print as a matrix */ if (print_as_matrix) { if (i == 0) { for (j = 0; j < nfrom; j++) { if (j == 0) fprintf(stdout, " "); fprintf(stdout, "|%d", Near[j].to_cat); } fprintf(stdout, "\n"); } if (i % nfrom == 0) { fprintf(stdout, "%d", Near[i].from_cat); for (j = 0; j < nfrom; j++) { print_upload(Near, Upload, i + j, &cvarr, catval); } fprintf(stdout, "\n"); } } else { fprintf(stdout, "%d", Near[i].from_cat); print_upload(Near, Upload, i, &cvarr, catval); fprintf(stdout, "\n"); } } else if (all) { /* insert new record */ sprintf(buf1, "insert into %s values ( %d ", table_opt->answer, Near[i].from_cat); db_set_string(&stmt, buf1); j = 0; while (Upload[j].upload != END) { db_append_string(&stmt, ","); switch (Upload[j].upload) { case CAT: sprintf(buf2, " %d", Near[i].to_cat); break; case DIST: sprintf(buf2, " %f", Near[i].dist); break; case FROM_X: sprintf(buf2, " %f", Near[i].from_x); break; case FROM_Y: sprintf(buf2, " %f", Near[i].from_y); break; case TO_X: sprintf(buf2, " %f", Near[i].to_x); break; case TO_Y: sprintf(buf2, " %f", Near[i].to_y); break; case FROM_ALONG: sprintf(buf2, " %f", Near[i].from_along); break; case TO_ALONG: sprintf(buf2, " %f", Near[i].to_along); break; case TO_ANGLE: sprintf(buf2, " %f", Near[i].to_angle); break; case TO_ATTR: if (catval) { switch (cvarr.ctype) { case DB_C_TYPE_INT: sprintf(buf2, " %d", catval->val.i); break; case DB_C_TYPE_DOUBLE: sprintf(buf2, " %.15e", catval->val.d); break; case DB_C_TYPE_STRING: db_set_string(&dbstr, db_get_string(catval->val.s)); db_double_quote_string(&dbstr); sprintf(buf2, " '%s'", db_get_string(&dbstr)); break; case DB_C_TYPE_DATETIME: /* TODO: formating datetime */ sprintf(buf2, " null"); break; } } else { sprintf(buf2, " null"); } break; } db_append_string(&stmt, buf2); j++; } db_append_string(&stmt, " )"); G_debug(3, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) == DB_OK) { update_ok++; } else { update_err++; } } else { /* update table */ /* check if exists in table */ cex = (int *)bsearch((void *)&(Near[i].from_cat), catexist, ncatexist, sizeof(int), cmp_exist); if (cex == NULL) { /* cat does not exist in DB */ update_notexist++; continue; } update_exist++; sprintf(buf1, "update %s set", Fi->table); db_set_string(&stmt, buf1); j = 0; while (Upload[j].upload != END) { if (j > 0) db_append_string(&stmt, ","); sprintf(buf2, " %s =", Upload[j].column); db_append_string(&stmt, buf2); if (Near[i].count == 0) { /* no nearest found */ db_append_string(&stmt, " null"); } else { switch (Upload[j].upload) { case CAT: if (Near[i].to_cat > 0) sprintf(buf2, " %d", Near[i].to_cat); else sprintf(buf2, " null"); break; case DIST: sprintf(buf2, " %f", Near[i].dist); break; case FROM_X: sprintf(buf2, " %f", Near[i].from_x); break; case FROM_Y: sprintf(buf2, " %f", Near[i].from_y); break; case TO_X: sprintf(buf2, " %f", Near[i].to_x); break; case TO_Y: sprintf(buf2, " %f", Near[i].to_y); break; case FROM_ALONG: sprintf(buf2, " %f", Near[i].from_along); break; case TO_ALONG: sprintf(buf2, " %f", Near[i].to_along); break; case TO_ANGLE: sprintf(buf2, " %f", Near[i].to_angle); break; case TO_ATTR: if (catval) { switch (cvarr.ctype) { case DB_C_TYPE_INT: sprintf(buf2, " %d", catval->val.i); break; case DB_C_TYPE_DOUBLE: sprintf(buf2, " %.15e", catval->val.d); break; case DB_C_TYPE_STRING: db_set_string(&dbstr, db_get_string(catval->val.s)); db_double_quote_string(&dbstr); sprintf(buf2, " '%s'", db_get_string(&dbstr)); break; case DB_C_TYPE_DATETIME: /* TODO: formating datetime */ sprintf(buf2, " null"); break; } } else { sprintf(buf2, " null"); } break; } db_append_string(&stmt, buf2); } j++; } sprintf(buf2, " where %s = %d", Fi->key, Near[i].from_cat); db_append_string(&stmt, buf2); G_debug(2, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) == DB_OK) { update_ok++; } else { update_err++; } } } G_percent(count, count, 1); if (driver) db_commit_transaction(driver); /* print stats */ if (update_dupl > 0) G_message(_("%d categories with more than 1 feature in vector map <%s>"), update_dupl, from_opt->answer); if (update_notfound > 0) G_message(_("%d categories - no nearest feature found"), update_notfound); if (!print_flag->answer) { db_close_database_shutdown_driver(driver); db_free_string(&stmt); /* print stats */ if (all && table_opt->answer) { G_message(_("%d distances calculated"), count); G_message(_("%d records inserted"), update_ok); if (update_err > 0) G_message(_("%d insert errors"), update_err); } else if (!all) { if (nfcats > 0) G_message(_("%d categories read from the map"), nfcats); if (ncatexist > 0) G_message(_("%d categories exist in the table"), ncatexist); if (update_exist > 0) G_message(_("%d categories read from the map exist in the table"), update_exist); if (update_notexist > 0) G_message(_("%d categories read from the map don't exist in the table"), update_notexist); G_message(_("%d records updated"), update_ok); if (update_err > 0) G_message(_("%d update errors"), update_err); G_free(catexist); } Vect_set_db_updated(&From); } Vect_close(&From); if (Outp != NULL) { Vect_build(Outp); Vect_close(Outp); } G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { /* Variables' declarations */ int nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row, subregion = 0, nsubregions = 0; double N_extension, E_extension, edgeE, edgeN; int dim_vect, nparameters, BW, npoints; double lambda_B, lambda_F, grad_H, grad_L, alpha, mean; const char *dvr, *db, *mapset; char table_interpolation[GNAME_MAX], table_name[GNAME_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int last_row, last_column, flag_auxiliar = FALSE; int *lineVect; double *TN, *Q, *parVect_bilin, *parVect_bicub; /* Interpolating and least-square vectors */ double **N, **obsVect; /* Interpolation and least-square matrix */ /* Structs' declarations */ struct Map_info In, Out; struct Option *in_opt, *out_opt, *stepE_opt, *stepN_opt, *lambdaF_opt, *lambdaB_opt, *gradH_opt, *gradL_opt, *alfa_opt; struct Flag *spline_step_flag; struct GModule *module; struct Cell_head elaboration_reg, original_reg; struct Reg_dimens dims; struct bound_box general_box, overlap_box; struct Point *observ; dbDriver *driver; /*------------------------------------------------------------------------------------------*/ /* Options' declaration */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("LIDAR")); G_add_keyword(_("edges")); module->description = _("Detects the object's edges from a LIDAR data set."); spline_step_flag = G_define_flag(); spline_step_flag->key = 'e'; spline_step_flag->label = _("Estimate point density and distance"); spline_step_flag->description = _("Estimate point density and distance for the input vector points within the current region extends and quit"); in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); stepE_opt = G_define_option(); stepE_opt->key = "see"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "4"; stepE_opt->description = _("Interpolation spline step value in east direction"); stepE_opt->guisection = _("Settings"); stepN_opt = G_define_option(); stepN_opt->key = "sen"; stepN_opt->type = TYPE_DOUBLE; stepN_opt->required = NO; stepN_opt->answer = "4"; stepN_opt->description = _("Interpolation spline step value in north direction"); stepN_opt->guisection = _("Settings"); lambdaB_opt = G_define_option(); lambdaB_opt->key = "lambda_g"; lambdaB_opt->type = TYPE_DOUBLE; lambdaB_opt->required = NO; lambdaB_opt->description = _("Regularization weight in gradient evaluation"); lambdaB_opt->answer = "0.01"; lambdaB_opt->guisection = _("Settings"); gradH_opt = G_define_option(); gradH_opt->key = "tgh"; gradH_opt->type = TYPE_DOUBLE; gradH_opt->required = NO; gradH_opt->description = _("High gradient threshold for edge classification"); gradH_opt->answer = "6"; gradH_opt->guisection = _("Settings"); gradL_opt = G_define_option(); gradL_opt->key = "tgl"; gradL_opt->type = TYPE_DOUBLE; gradL_opt->required = NO; gradL_opt->description = _("Low gradient threshold for edge classification"); gradL_opt->answer = "3"; gradL_opt->guisection = _("Settings"); alfa_opt = G_define_option(); alfa_opt->key = "theta_g"; alfa_opt->type = TYPE_DOUBLE; alfa_opt->required = NO; alfa_opt->description = _("Angle range for same direction detection"); alfa_opt->answer = "0.26"; alfa_opt->guisection = _("Settings"); lambdaF_opt = G_define_option(); lambdaF_opt->key = "lambda_r"; lambdaF_opt->type = TYPE_DOUBLE; lambdaF_opt->required = NO; lambdaF_opt->description = _("Regularization weight in residual evaluation"); lambdaF_opt->answer = "2"; lambdaF_opt->guisection = _("Settings"); /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); line_out_counter = 1; stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda_F = atof(lambdaF_opt->answer); lambda_B = atof(lambdaB_opt->answer); grad_H = atof(gradH_opt->answer); grad_L = atof(gradL_opt->answer); alpha = atof(alfa_opt->answer); grad_L = grad_L * grad_L; grad_H = grad_H * grad_H; if (!(db = G__getenv2("DB_DATABASE", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of database")); if (!(dvr = G__getenv2("DB_DRIVER", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of driver")); /* Setting auxiliar table's name */ if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) { sprintf(table_name, "%s_aux", xname); sprintf(table_interpolation, "%s_edge_Interpolation", xname); } else { sprintf(table_name, "%s_aux", out_opt->answer); sprintf(table_interpolation, "%s_edge_Interpolation", out_opt->answer); } /* Something went wrong in a previous v.lidar.edgedetection execution */ if (db_table_exists(dvr, db, table_name)) { /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Old auxiliar table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Something went wrong in a previous v.lidar.edgedetection execution */ if (db_table_exists(dvr, db, table_interpolation)) { /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); if (P_Drop_Aux_Table(driver, table_interpolation) != DB_OK) G_fatal_error(_("Old auxiliar table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Checking vector names */ Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) { G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); } Vect_set_open_level(1); /* Open input vector */ if (1 > Vect_open_old(&In, in_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); /* Input vector must be 3D */ if (!Vect_is_3d(&In)) G_fatal_error(_("Input vector map <%s> is not 3D!"), in_opt->answer); /* Estimate point density and mean distance for current region */ if (spline_step_flag->answer) { double dens, dist; if (P_estimate_splinestep(&In, &dens, &dist) == 0) { G_message("Estimated point density: %.4g", dens); G_message("Estimated mean distance between points: %.4g", dist); } else G_warning(_("No points in current region!")); Vect_close(&In); exit(EXIT_SUCCESS); } /* Open output vector */ if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); /* Copy vector Head File */ Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); db_set_error_handler_driver(driver); /* Create auxiliar and interpolation table */ if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE) G_fatal_error(_("It was impossible to create <%s>."), table_name); if (P_Create_Aux2_Table(driver, table_interpolation) == FALSE) G_fatal_error(_("It was impossible to create <%s> interpolation table in database."), out_opt->answer); db_create_index2(driver, table_name, "ID"); db_create_index2(driver, table_interpolation, "ID"); /* sqlite likes that ??? */ db_close_database_shutdown_driver(driver); driver = db_start_driver_open_database(dvr, db); /* Setting regions and boxes */ G_get_set_window(&original_reg); G_get_set_window(&elaboration_reg); Vect_region_box(&elaboration_reg, &overlap_box); Vect_region_box(&elaboration_reg, &general_box); /*------------------------------------------------------------------ | Subdividing and working with tiles: | Each original region will be divided into several subregions. | Each one will be overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); nsplx_adj = NSPLX_MAX; nsply_adj = NSPLY_MAX; if (stepN > stepE) dims.overlap = OVERLAP_SIZE * stepN; else dims.overlap = OVERLAP_SIZE * stepE; P_get_edge(P_BICUBIC, &dims, stepE, stepN); P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj); G_verbose_message(_("adjusted EW splines %d"), nsplx_adj); G_verbose_message(_("adjusted NS splines %d"), nsply_adj); /* calculate number of subregions */ edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v; edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h; N_extension = original_reg.north - original_reg.south; E_extension = original_reg.east - original_reg.west; nsubregion_col = ceil(E_extension / edgeE) + 0.5; nsubregion_row = ceil(N_extension / edgeN) + 0.5; if (nsubregion_col < 0) nsubregion_col = 0; if (nsubregion_row < 0) nsubregion_row = 0; nsubregions = nsubregion_row * nsubregion_col; elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_ROW); if (elaboration_reg.north > original_reg.north) { /* First row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_ROW); } if (elaboration_reg.south <= original_reg.south) { /* Last row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_ROW); last_row = TRUE; } nsply = ceil((elaboration_reg.north - elaboration_reg.south) / stepN) + 0.5; /* if (nsply > NSPLY_MAX) { nsply = NSPLY_MAX; } */ G_debug(1, "nsply = %d", nsply); elaboration_reg.east = original_reg.west; last_column = FALSE; while (last_column == FALSE) { /* For each column */ subregion++; if (nsubregions > 1) G_message(_("subregion %d of %d"), subregion, nsubregions); P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_COLUMN); if (elaboration_reg.west < original_reg.west) { /* First column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_COLUMN); } if (elaboration_reg.east >= original_reg.east) { /* Last column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_COLUMN); last_column = TRUE; } nsplx = ceil((elaboration_reg.east - elaboration_reg.west) / stepE) + 0.5; /* if (nsplx > NSPLX_MAX) { nsplx = NSPLX_MAX; } */ G_debug(1, "nsplx = %d", nsplx); /*Setting the active region */ dim_vect = nsplx * nsply; G_debug(1, "read vector region map"); observ = P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints, dim_vect, 1); if (npoints > 0) { /* If there is any point falling into elaboration_reg... */ int i, tn; nparameters = nsplx * nsply; /* Mean's calculation */ mean = P_Mean_Calc(&elaboration_reg, observ, npoints); /* Least Squares system */ G_debug(1, _("Allocating memory for bilinear interpolation")); BW = P_get_BandWidth(P_BILINEAR, nsply); /* Bilinear interpolation */ N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ TN = G_alloc_vector(nparameters); /* vector */ parVect_bilin = G_alloc_vector(nparameters); /* Bilinear parameters vector */ obsVect = G_alloc_matrix(npoints + 1, 3); /* Observation vector */ Q = G_alloc_vector(npoints + 1); /* "a priori" var-cov matrix */ lineVect = G_alloc_ivector(npoints + 1); /* Setting obsVect vector & Q matrix */ for (i = 0; i < npoints; i++) { obsVect[i][0] = observ[i].coordX; obsVect[i][1] = observ[i].coordY; obsVect[i][2] = observ[i].coordZ - mean; lineVect[i] = observ[i].lineID; Q[i] = 1; /* Q=I */ } G_free(observ); G_verbose_message(_("Bilinear interpolation")); normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectGrad(N, lambda_B, nsplx, nsply, stepE, stepN); G_math_solver_cholesky_sband(N, parVect_bilin, TN, nparameters, BW); G_free_matrix(N); for (tn = 0; tn < nparameters; tn++) TN[tn] = 0; G_debug(1, _("Allocating memory for bicubic interpolation")); BW = P_get_BandWidth(P_BICUBIC, nsply); N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ parVect_bicub = G_alloc_vector(nparameters); /* Bicubic parameters vector */ G_verbose_message(_("Bicubic interpolation")); normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectLapl(N, lambda_F, nsplx, nsply, stepE, stepN); G_math_solver_cholesky_sband(N, parVect_bicub, TN, nparameters, BW); G_free_matrix(N); G_free_vector(TN); G_free_vector(Q); G_verbose_message(_("Point classification")); classification(&Out, elaboration_reg, general_box, overlap_box, obsVect, parVect_bilin, parVect_bicub, mean, alpha, grad_H, grad_L, dims.overlap, lineVect, npoints, driver, table_interpolation, table_name); G_free_vector(parVect_bilin); G_free_vector(parVect_bicub); G_free_matrix(obsVect); G_free_ivector(lineVect); } /* IF */ else { G_free(observ); G_warning(_("No data within this subregion. " "Consider changing the spline step.")); } } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ /* Dropping auxiliar table */ if (npoints > 0) { G_debug(1, _("Dropping <%s>"), table_name); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_warning(_("Auxiliar table could not be dropped")); } db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_map_add_dblink(&Out, F_INTERPOLATION, NULL, table_interpolation, "id", db, dvr); Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); } /*!END MAIN */
int main(int argc, char *argv[]) { int i, j, precision, field; int do_attr = 0, attr_cols[8], attr_size = 0, db_open = 0, cnt = 0; double width, radius; struct Option *in_opt, *out_opt, *prec_opt, *type_opt, *attr_opt, *field_opt; struct GModule *module; struct Map_info In; struct bound_box box; /* vector */ struct line_pnts *Points; struct line_cats *Cats; /* attribs */ dbDriver *Driver = NULL; dbHandle handle; dbTable *Table; dbString dbstring; struct field_info *Fi; /* init */ G_gisinit(argv[0]); /* parse command-line */ module = G_define_module(); module->description = _("Exports a vector map to SVG file."); G_add_keyword(_("vector")); G_add_keyword(_("export")); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); out_opt = G_define_standard_option(G_OPT_F_OUTPUT); out_opt->description = _("Name for SVG output file"); type_opt = G_define_option(); type_opt->key = "type"; type_opt->type = TYPE_STRING; type_opt->required = YES; type_opt->multiple = NO; type_opt->answer = "poly"; type_opt->options = "poly,line,point"; type_opt->label = _("Output type"); type_opt->description = _("Defines which feature-type will be extracted"); prec_opt = G_define_option(); prec_opt->key = "precision"; prec_opt->type = TYPE_INTEGER; prec_opt->required = NO; prec_opt->answer = "6"; prec_opt->multiple = NO; prec_opt->description = _("Coordinate precision"); attr_opt = G_define_standard_option(G_OPT_DB_COLUMNS); attr_opt->key = "attribute"; attr_opt->required = NO; attr_opt->multiple = YES; attr_opt->description = _("Attribute(s) to include in output SVG"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* override coordinate precision if any */ precision = atof(prec_opt->answer); if (precision < 0) { G_fatal_error(_("Precision must not be negative")); } if (precision > 15) { G_fatal_error(_("Precision must not be higher than 15")); } /* open input vector */ Vect_set_open_level(2); Vect_open_old2(&In, in_opt->answer, "", field_opt->answer); /* parse field number */ field = Vect_get_field_number(&In, field_opt->answer); /* open db-driver to attribs */ db_init_string(&dbstring); /* check for requested field */ Fi = Vect_get_field(&In, field); if (Fi != NULL) { Driver = db_start_driver(Fi->driver); if (Driver == NULL) { G_fatal_error(_("Unable to start driver <%s>"), Fi->driver); } /* open db */ db_init_handle(&handle); db_set_handle(&handle, Fi->database, NULL); if (db_open_database(Driver, &handle) != DB_OK) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); } db_set_string(&dbstring, Fi->table); if (db_describe_table(Driver, &dbstring, &Table) != DB_OK) { G_fatal_error(_("Unable to describe table <%s>"), Fi->table); } /* define column-indices for columns to extract */ dbColumn *Column; for (i = 0; i < db_get_table_number_of_columns(Table); i++) { Column = db_get_table_column(Table, i); if (attr_opt->answer != NULL) { for (j = 0; attr_opt->answers[j] != NULL; j++) { if (G_strcasecmp(attr_opt->answers[j], db_get_column_name(Column)) == 0) { attr_cols[attr_size] = i; attr_size += 1; break; } } } } do_attr = 1; db_open = 1; } /* parse bounding box and define default stroke-width, radius */ Vect_get_map_box(&In, &box); if ((box.E - box.W) >= (box.N - box.S)) { radius = (box.E - box.W) * RADIUS_SCALE; width = (box.E - box.W) * WIDTH_SCALE; } else { radius = (box.N - box.S) * RADIUS_SCALE; width = (box.N - box.S) * WIDTH_SCALE; } /* open output SVG-file and print SVG-header with viewBox and Namenspaces */ if ((fpsvg = fopen(out_opt->answer, "w")) == NULL) { G_fatal_error(_("Unable to create SVG file <%s>"), out_opt->answer); } fprintf(fpsvg, "<svg xmlns=\"%s\" xmlns:xlink=\"%s\" xmlns:gg=\"%s\" ", SVG_NS, XLINK_NS, GRASS_NS); fprintf(fpsvg, "viewBox=\"%.*f %.*f %.*f %.*f\">\n", precision, box.W, precision, box.N * -1, precision, box.E - box.W, precision, box.N - box.S); fprintf(fpsvg, "<title>v.out.svg %s %s</title>\n", in_opt->answer, out_opt->answer); /* extract areas if any or requested */ if (G_strcasecmp(type_opt->answer, "poly") == 0) { if (Vect_get_num_areas(&In) == 0) { G_warning(_("No areas found, skipping type=poly")); } else { /* extract area as paths */ fprintf(fpsvg, " <g id=\"%s\" fill=\"#CCC\" stroke=\"#000\" stroke-width=\"%.*f\" >\n", G_Areas, precision, width); for (i = 1; i <= Vect_get_num_areas(&In); i++) { /* skip areas without centroid */ if (Vect_get_area_centroid(&In, i) == 0) { G_warning(_("Skipping area %d without centroid"), i); continue; } G_percent(i, Vect_get_num_areas(&In), 10); /* extract attribs, parse area */ Vect_get_area_cats(&In, i, Cats); fprintf(fpsvg, " <path "); if (Cats->n_cats > 0) { mk_attribs(Cats->cat[0], Fi, Driver, Table, attr_cols, attr_size, do_attr); } fprintf(fpsvg, "d=\""); Vect_get_area_points(&In, i, Points); mk_path(Points, precision); /* append islands if any within current path */ for (j = 0; j < Vect_get_area_num_isles(&In, i); j++) { Vect_get_isle_points(&In, Vect_get_area_isle(&In, i, j), Points); mk_path(Points, precision); } fprintf(fpsvg, "\" />\n"); cnt += 1; } fprintf(fpsvg, " </g>\n"); G_message(_("Extracted %d areas"), cnt); } } /* extract points if requested */ if (G_strcasecmp(type_opt->answer, "point") == 0) { if (Vect_get_num_primitives(&In, GV_POINTS) == 0) { G_warning(_("No points found, skipping type=point")); } else { /* extract points as circles */ fprintf(fpsvg, " <g id=\"%s\" fill=\"#FC0\" stroke=\"#000\" " "stroke-width=\"%.*f\" >\n", G_Points, precision, width); for (i = 1; i <= Vect_get_num_primitives(&In, GV_POINTS); i++) { G_percent(i, Vect_get_num_primitives(&In, GV_POINTS), 10); Vect_read_line(&In, Points, Cats, i); if (field != -1 && !Vect_cat_get(Cats, field, NULL)) continue; for (j = 0; j < Points->n_points; j++) { fprintf(fpsvg, " <circle "); if (Cats->n_cats > 0) { mk_attribs(Cats->cat[j], Fi, Driver, Table, attr_cols, attr_size, do_attr); } fprintf(fpsvg, "cx=\"%.*f\" cy=\"%.*f\" r=\"%.*f\" />\n", precision, Points->x[j], precision, Points->y[j] * -1, precision, radius); cnt += 1; } } fprintf(fpsvg, " </g>\n"); G_message(_("Extracted %d points"), cnt); } } /* extract lines if requested */ if (G_strcasecmp(type_opt->answer, "line") == 0) { if (Vect_get_num_primitives(&In, GV_LINES) == 0) { G_warning(_("No lines found, skipping type=line")); } else { /* extract lines as paths */ fprintf(fpsvg, " <g id=\"%s\" fill=\"none\" stroke=\"#000\" " "stroke-width=\"%.*f\" >\n", G_Lines, precision, width); for (i = 1; i <= Vect_get_num_primitives(&In, GV_LINES); i++) { G_percent(i, Vect_get_num_primitives(&In, GV_LINES), 10); Vect_read_line(&In, Points, Cats, i); fprintf(fpsvg, " <path "); if (Cats->n_cats > 0) { mk_attribs(Cats->cat[0], Fi, Driver, Table, attr_cols, attr_size, do_attr); } fprintf(fpsvg, "d=\""); mk_path(Points, precision); fprintf(fpsvg, "\" />\n"); cnt += 1; } fprintf(fpsvg, " </g>\n"); G_message(_("Extracted %d lines"), cnt); } } /* finish code */ fprintf(fpsvg, "</svg>\n"); if (db_open == 1) { /* close database handle */ db_close_database(Driver); db_shutdown_driver(Driver); } /* close SVG-file */ fclose(fpsvg); G_done_msg(" "); exit(EXIT_SUCCESS); }
/*--------------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* Variables' declarations */ int row, nrows, col, ncols, MaxPoints; int nsubregion_col, nsubregion_row; int subregion = 0, nsubregions = 0; int last_row, last_column; int nlines, nlines_first, line_num; int more; int clas, region = TRUE; double Z_interp; double Thres_j, Thres_d, ew_resol, ns_resol; double minNS, minEW, maxNS, maxEW; const char *mapset; char buf[1024], table_name[GNAME_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int colorBordo, ripieno, conta, lungPunti, lungHull, xi, c1, c2; double altPiano; extern double **P, **cvxHull, **punti_bordo; /* Struct declarations */ struct Cell_head elaboration_reg, original_reg; struct element_grow **raster_matrix; struct Map_info In, Out, First; struct Option *in_opt, *out_opt, *first_opt, *Thres_j_opt, *Thres_d_opt; struct GModule *module; struct line_pnts *points, *points_first; struct line_cats *Cats, *Cats_first; struct field_info *field; dbDriver *driver; dbString sql; dbTable *table; dbCursor cursor; /*------------------------------------------------------------------------------------------*/ /* Options' declaration */ ; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("LIDAR")); module->description = _("Building contour determination and Region Growing " "algorithm for determining the building inside"); in_opt = G_define_standard_option(G_OPT_V_INPUT); in_opt->description = _("Input vector (v.lidar.edgedetection output"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); first_opt = G_define_option(); first_opt->key = "first"; first_opt->type = TYPE_STRING; first_opt->key_desc = "name"; first_opt->required = YES; first_opt->gisprompt = "old,vector,vector"; first_opt->description = _("Name of the first pulse vector map"); Thres_j_opt = G_define_option(); Thres_j_opt->key = "tj"; Thres_j_opt->type = TYPE_DOUBLE; Thres_j_opt->required = NO; Thres_j_opt->description = _("Threshold for cell object frequency in region growing"); Thres_j_opt->answer = "0.2"; Thres_d_opt = G_define_option(); Thres_d_opt->key = "td"; Thres_d_opt->type = TYPE_DOUBLE; Thres_d_opt->required = NO; Thres_d_opt->description = _("Threshold for double pulse in region growing"); Thres_d_opt->answer = "0.6"; /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Thres_j = atof(Thres_j_opt->answer); Thres_d = atof(Thres_d_opt->answer); Thres_j += 1; /* Open input vector */ Vect_check_input_output_name(in_opt->answer, out_opt->answer, GV_FATAL_EXIT); if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) { G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); } /* Setting auxiliar table's name */ if (G_name_is_fully_qualified(in_opt->answer, xname, xmapset)) { sprintf(table_name, "%s_edge_Interpolation", xname); } else sprintf(table_name, "%s_edge_Interpolation", in_opt->answer); Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (Vect_open_old(&In, in_opt->answer, mapset) < 1) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (Vect_open_old(&First, first_opt->answer, mapset) < 1) G_fatal_error(_("Unable to open vector map <%s>"), first_opt->answer); /* Open output vector */ if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) { Vect_close(&In); Vect_close(&First); exit(EXIT_FAILURE); } /* Copy vector Head File */ Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Starting driver and open db for edgedetection interpolation table */ field = Vect_get_field(&In, F_INTERPOLATION); /*if (field == NULL) G_fatal_error (_("Cannot read field info")); */ driver = db_start_driver_open_database(field->driver, field->database); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), field->driver); /* is this the right place to open the cursor ??? */ db_init_string(&sql); db_zero_string(&sql); sprintf(buf, "SELECT Interp,ID FROM %s", table_name); G_debug(1, "buf: %s", buf); db_append_string(&sql, buf); if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) G_fatal_error(_("Unable to open table <%s>"), table_name); count_obj = 1; /* no topology, get number of lines in input vector */ nlines = 0; points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_rewind(&In); while (Vect_read_next_line(&In, points, Cats) > 0) { nlines++; } Vect_rewind(&In); /* no topology, get number of lines in first pulse input vector */ nlines_first = 0; points_first = Vect_new_line_struct(); Cats_first = Vect_new_cats_struct(); Vect_rewind(&First); while (Vect_read_next_line(&First, points_first, Cats_first) > 0) { nlines_first++; } Vect_rewind(&First); /* Setting regions and boxes */ G_debug(1, _("Setting regions and boxes")); G_get_set_window(&original_reg); G_get_set_window(&elaboration_reg); /* Fixing parameters of the elaboration region */ /*! The original_region will be divided into subregions */ ew_resol = original_reg.ew_res; ns_resol = original_reg.ns_res; /* calculate number of subregions */ nsubregion_col = ceil((original_reg.east - original_reg.west) / (LATO * ew_resol)) + 0.5; nsubregion_row = ceil((original_reg.north - original_reg.south) / (LATO * ns_resol)) + 0.5; if (nsubregion_col < 0) nsubregion_col = 0; if (nsubregion_row < 0) nsubregion_row = 0; nsubregions = nsubregion_row * nsubregion_col; /* Subdividing and working with tiles */ elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each strip of LATO rows */ elaboration_reg.north = elaboration_reg.south; if (elaboration_reg.north > original_reg.north) /* First row */ elaboration_reg.north = original_reg.north; elaboration_reg.south = elaboration_reg.north - LATO * ns_resol; if (elaboration_reg.south <= original_reg.south) { /* Last row */ elaboration_reg.south = original_reg.south; last_row = TRUE; } elaboration_reg.east = original_reg.west; last_column = FALSE; while (last_column == FALSE) { /* For each strip of LATO columns */ struct bound_box elaboration_box; subregion++; if (nsubregions > 1) G_message(_("subregion %d of %d"), subregion, nsubregions); elaboration_reg.west = elaboration_reg.east; if (elaboration_reg.west < original_reg.west) /* First column */ elaboration_reg.west = original_reg.west; elaboration_reg.east = elaboration_reg.west + LATO * ew_resol; if (elaboration_reg.east >= original_reg.east) { /* Last column */ elaboration_reg.east = original_reg.east; last_column = TRUE; } /* Setting the active region */ elaboration_reg.ns_res = ns_resol; elaboration_reg.ew_res = ew_resol; nrows = (elaboration_reg.north - elaboration_reg.south) / ns_resol + 0.1; ncols = (elaboration_reg.east - elaboration_reg.west) / ew_resol + 0.1; elaboration_reg.rows = nrows; elaboration_reg.cols = ncols; G_debug(1, _("Rows = %d"), nrows); G_debug(1, _("Columns = %d"), ncols); raster_matrix = structMatrix(0, nrows, 0, ncols); MaxPoints = nrows * ncols; /* Initializing matrix */ for (row = 0; row <= nrows; row++) { for (col = 0; col <= ncols; col++) { raster_matrix[row][col].interp = 0; raster_matrix[row][col].fi = 0; raster_matrix[row][col].bordo = 0; raster_matrix[row][col].dueImp = SINGLE_PULSE; raster_matrix[row][col].orig = 0; raster_matrix[row][col].fo = 0; raster_matrix[row][col].clas = PRE_TERRAIN; raster_matrix[row][col].fc = 0; raster_matrix[row][col].obj = 0; } } G_verbose_message(_("read points in input vector")); Vect_region_box(&elaboration_reg, &elaboration_box); line_num = 0; Vect_rewind(&In); while (Vect_read_next_line(&In, points, Cats) > 0) { line_num++; if ((Vect_point_in_box (points->x[0], points->y[0], points->z[0], &elaboration_box)) && ((points->x[0] != elaboration_reg.west) || (points->x[0] == original_reg.west)) && ((points->y[0] != elaboration_reg.north) || (points->y[0] == original_reg.north))) { row = (int)(Rast_northing_to_row (points->y[0], &elaboration_reg)); col = (int)(Rast_easting_to_col (points->x[0], &elaboration_reg)); Z_interp = 0; /* TODO: make sure the current db_fetch() usage works */ /* why not: */ /* db_init_string(&sql); sprintf(buf, "SELECT Interp,ID FROM %s WHERE ID=%d", table_name, line_num); db_append_string(&sql, buf); if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) G_fatal_error(_("Unable to open table <%s>"), table_name); while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) { dbColumn *Z_Interp_col; dbValue *Z_Interp_value; table = db_get_cursor_table(&cursor); Z_Interp_col = db_get_table_column(table, 1); if (db_sqltype_to_Ctype(db_get_column_sqltype(Z_Interp_col)) == DB_C_TYPE_DOUBLE) Z_Interp_value = db_get_column_value(Z_Interp_col); else continue; Z_interp = db_get_value_double(Z_Interp_value); break; } db_close_cursor(&cursor); db_free_string(&sql); */ /* instead of */ while (1) { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK || !more) break; dbColumn *Z_Interp_col, *ID_col; dbValue *Z_Interp_value, *ID_value; table = db_get_cursor_table(&cursor); ID_col = db_get_table_column(table, 1); if (db_sqltype_to_Ctype(db_get_column_sqltype(ID_col)) == DB_C_TYPE_INT) ID_value = db_get_column_value(ID_col); else continue; if (db_get_value_int(ID_value) == line_num) { Z_Interp_col = db_get_table_column(table, 0); if (db_sqltype_to_Ctype (db_get_column_sqltype(Z_Interp_col)) == DB_C_TYPE_DOUBLE) Z_Interp_value = db_get_column_value(Z_Interp_col); else continue; Z_interp = db_get_value_double(Z_Interp_value); break; } } raster_matrix[row][col].interp += Z_interp; raster_matrix[row][col].fi++; /*if (( clas = Vect_get_line_cat (&In, line_num, F_EDGE_DETECTION_CLASS) ) != UNKNOWN_EDGE) { */ if (Vect_cat_get(Cats, F_EDGE_DETECTION_CLASS, &clas)) { raster_matrix[row][col].clas += clas; raster_matrix[row][col].fc++; } raster_matrix[row][col].orig += points->z[0]; raster_matrix[row][col].fo++; } Vect_reset_cats(Cats); Vect_reset_line(points); } for (row = 0; row <= nrows; row++) { for (col = 0; col <= ncols; col++) { if (raster_matrix[row][col].fc != 0) { raster_matrix[row][col].clas--; raster_matrix[row][col]. clas /= raster_matrix[row][col].fc; } if (raster_matrix[row][col].fi != 0) raster_matrix[row][col]. interp /= raster_matrix[row][col].fi; if (raster_matrix[row][col].fo != 0) raster_matrix[row][col]. orig /= raster_matrix[row][col].fo; } } /* DOUBLE IMPULSE */ Vect_rewind(&First); while (Vect_read_next_line(&First, points_first, Cats_first) > 0) { if ((Vect_point_in_box (points_first->x[0], points_first->y[0], points_first->z[0], &elaboration_box)) && ((points->x[0] != elaboration_reg.west) || (points->x[0] == original_reg.west)) && ((points->y[0] != elaboration_reg.north) || (points->y[0] == original_reg.north))) { row = (int)(Rast_northing_to_row (points_first->y[0], &elaboration_reg)); col = (int)(Rast_easting_to_col (points_first->x[0], &elaboration_reg)); if (fabs (points_first->z[0] - raster_matrix[row][col].orig) >= Thres_d) raster_matrix[row][col].dueImp = DOUBLE_PULSE; } Vect_reset_cats(Cats_first); Vect_reset_line(points_first); } /* REGION GROWING */ if (region == TRUE) { G_verbose_message(_("Region Growing")); punti_bordo = G_alloc_matrix(MaxPoints, 3); P = Pvector(0, MaxPoints); colorBordo = 5; ripieno = 6; for (row = 0; row <= nrows; row++) { G_percent(row, nrows, 2); for (col = 0; col <= ncols; col++) { if ((raster_matrix[row][col].clas >= Thres_j) && (raster_matrix[row][col].clas < colorBordo) && (raster_matrix[row][col].fi != 0) && (raster_matrix[row][col].dueImp == SINGLE_PULSE)) { /* Selecting a connected Object zone */ ripieno++; if (ripieno > 10) ripieno = 6; /* Selecting points on a connected edge */ for (conta = 0; conta < MaxPoints; conta++) { punti_bordo[conta][0] = 0; punti_bordo[conta][1] = 0; punti_bordo[conta][2] = 0; P[conta] = punti_bordo[conta]; /* It only makes indexes to be equal, not coord values!! */ } lungPunti = 0; lungHull = 0; regGrow8(elaboration_reg, raster_matrix, punti_bordo, &lungPunti, row, col, colorBordo, Thres_j, MaxPoints); /* CONVEX-HULL COMPUTATION */ lungHull = ch2d(P, lungPunti); cvxHull = G_alloc_matrix(lungHull, 3); for (xi = 0; xi < lungHull; xi++) { cvxHull[xi][0] = P[xi][0]; cvxHull[xi][1] = P[xi][1]; cvxHull[xi][2] = P[xi][2]; } /* Computes the interpoling plane based only on Object points */ altPiano = pianOriz(punti_bordo, lungPunti, &minNS, &minEW, &maxNS, &maxEW, raster_matrix, colorBordo); for (c1 = minNS; c1 <= maxNS; c1++) { for (c2 = minEW; c2 <= maxEW; c2++) { if (checkHull(c1, c2, cvxHull, lungHull) == 1) { raster_matrix[c1][c2].obj = count_obj; if ((raster_matrix[c1][c2].clas == PRE_TERRAIN) && (raster_matrix[c1][c2].orig >= altPiano) && (lungHull > 3)) raster_matrix[c1][c2].clas = ripieno; } } } G_free_matrix(cvxHull); count_obj++; } } } G_free_matrix(punti_bordo); free_Pvector(P, 0, MaxPoints); } /* WRITING THE OUTPUT VECTOR CATEGORIES */ Vect_rewind(&In); while (Vect_read_next_line(&In, points, Cats) > 0) { /* Read every line for buffering points */ if ((Vect_point_in_box (points->x[0], points->y[0], points->z[0], &elaboration_box)) && ((points->x[0] != elaboration_reg.west) || (points->x[0] == original_reg.west)) && ((points->y[0] != elaboration_reg.north) || (points->y[0] == original_reg.north))) { row = (int)(Rast_northing_to_row (points->y[0], &elaboration_reg)); col = (int)(Rast_easting_to_col (points->x[0], &elaboration_reg)); if (raster_matrix[row][col].clas == PRE_TERRAIN) { if (raster_matrix[row][col].dueImp == SINGLE_PULSE) Vect_cat_set(Cats, F_CLASSIFICATION, TERRAIN_SINGLE); else Vect_cat_set(Cats, F_CLASSIFICATION, TERRAIN_DOUBLE); } else { if (raster_matrix[row][col].dueImp == SINGLE_PULSE) Vect_cat_set(Cats, F_CLASSIFICATION, OBJECT_SINGLE); else Vect_cat_set(Cats, F_CLASSIFICATION, OBJECT_DOUBLE); } Vect_cat_set(Cats, F_COUNTER_OBJ, raster_matrix[row][col].obj); Vect_write_line(&Out, GV_POINT, points, Cats); } Vect_reset_cats(Cats); Vect_reset_line(points); } free_structmatrix(raster_matrix, 0, nrows - 1, 0, ncols - 1); } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ Vect_close(&In); Vect_close(&First); Vect_close(&Out); db_close_database_shutdown_driver(driver); G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, nsites, warn_once = 0; int all; long x, y; struct Cell_head window; struct GModule *module; struct { struct Option *input, *tests, *dfield, *layer; } parm; struct { struct Flag *q, *l, *region; } flag; double *w, *z; struct Map_info Map; int line, nlines, npoints; int field; struct line_pnts *Points; struct line_cats *Cats; struct bound_box box; /* Attributes */ int nrecords; int ctype; struct field_info *Fi; dbDriver *Driver; dbCatValArray cvarr; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("statistics")); G_add_keyword(_("points")); G_add_keyword(_("point pattern")); module->description = _("Tests for normality for vector points."); parm.input = G_define_standard_option(G_OPT_V_MAP); parm.layer = G_define_standard_option(G_OPT_V_FIELD); parm.tests = G_define_option(); parm.tests->key = "tests"; parm.tests->key_desc = "range"; parm.tests->type = TYPE_STRING; parm.tests->multiple = YES; parm.tests->required = YES; parm.tests->label = _("Lists of tests (1-15)"); parm.tests->description = _("E.g. 1,3-8,13"); parm.dfield = G_define_standard_option(G_OPT_DB_COLUMN); parm.dfield->required = YES; flag.region = G_define_flag(); flag.region->key = 'r'; flag.region->description = _("Use only points in current region"); flag.l = G_define_flag(); flag.l->key = 'l'; flag.l->description = _("Lognormality instead of normality"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); all = flag.region->answer ? 0 : 1; /* Open input */ Vect_set_open_level(2); if (Vect_open_old2(&Map, parm.input->answer, "", parm.layer->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), parm.input->answer); field = Vect_get_field_number(&Map, parm.layer->answer); /* Read attributes */ Fi = Vect_get_field(&Map, field); if (Fi == NULL) { G_fatal_error("Database connection not defined for layer %d", field); } Driver = db_start_driver_open_database(Fi->driver, Fi->database); if (Driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); nrecords = db_select_CatValArray(Driver, Fi->table, Fi->key, parm.dfield->answer, NULL, &cvarr); G_debug(1, "nrecords = %d", nrecords); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Only numeric column type supported")); if (nrecords < 0) G_fatal_error(_("Unable to select data from table")); G_verbose_message(_("%d records selected from table"), nrecords); db_close_database_shutdown_driver(Driver); /* Read points */ npoints = Vect_get_num_primitives(&Map, GV_POINT); z = (double *)G_malloc(npoints * sizeof(double)); G_get_window(&window); Vect_region_box(&window, &box); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); nlines = Vect_get_num_lines(&Map); nsites = 0; for (line = 1; line <= nlines; line++) { int type, cat, ret, cval; double dval; G_debug(3, "line = %d", line); type = Vect_read_line(&Map, Points, Cats, line); if (!(type & GV_POINT)) continue; if (!all) { if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &box)) continue; } Vect_cat_get(Cats, 1, &cat); G_debug(3, "cat = %d", cat); /* find actual value */ if (ctype == DB_C_TYPE_INT) { ret = db_CatValArray_get_value_int(&cvarr, cat, &cval); if (ret != DB_OK) { G_warning(_("No record for cat %d"), cat); continue; } dval = cval; } else if (ctype == DB_C_TYPE_DOUBLE) { ret = db_CatValArray_get_value_double(&cvarr, cat, &dval); if (ret != DB_OK) { G_warning(_("No record for cat %d"), cat); continue; } } G_debug(3, "dval = %e", dval); z[nsites] = dval; nsites++; } G_verbose_message(_("Number of points: %d"), nsites); if (nsites <= 0) G_fatal_error(_("No points found")); if (nsites < 4) G_warning(_("Too small sample")); if (flag.l->answer) { warn_once = 0; for (i = 0; i < nsites; ++i) { if (z[i] > 1.0e-10) z[i] = log10(z[i]); else if (!warn_once) { G_warning(_("Negative or very small point values set to -10.0")); z[i] = -10.0; warn_once = 1; } } } for (i = 0; parm.tests->answers[i]; i++) if (!scan_cats(parm.tests->answers[i], &x, &y)) { G_usage(); exit(EXIT_FAILURE); } for (i = 0; parm.tests->answers[i]; i++) { scan_cats(parm.tests->answers[i], &x, &y); while (x <= y) switch (x++) { case 1: /* moments */ fprintf(stdout, _("Moments \\sqrt{b_1} and b_2: ")); w = Cdhc_omnibus_moments(z, nsites); fprintf(stdout, "%g %g\n", w[0], w[1]); break; case 2: /* geary */ fprintf(stdout, _("Geary's a-statistic & an approx. normal: ")); w = Cdhc_geary_test(z, nsites); fprintf(stdout, "%g %g\n", w[0], w[1]); break; case 3: /* extreme deviates */ fprintf(stdout, _("Extreme normal deviates: ")); w = Cdhc_extreme(z, nsites); fprintf(stdout, "%g %g\n", w[0], w[1]); break; case 4: /* D'Agostino */ fprintf(stdout, _("D'Agostino's D & an approx. normal: ")); w = Cdhc_dagostino_d(z, nsites); fprintf(stdout, "%g %g\n", w[0], w[1]); break; case 5: /* Kuiper */ fprintf(stdout, _("Kuiper's V (regular & modified for normality): ")); w = Cdhc_kuipers_v(z, nsites); fprintf(stdout, "%g %g\n", w[1], w[0]); break; case 6: /* Watson */ fprintf(stdout, _("Watson's U^2 (regular & modified for normality): ")); w = Cdhc_watson_u2(z, nsites); fprintf(stdout, "%g %g\n", w[1], w[0]); break; case 7: /* Durbin */ fprintf(stdout, _("Durbin's Exact Test (modified Kolmogorov): ")); w = Cdhc_durbins_exact(z, nsites); fprintf(stdout, "%g\n", w[0]); break; case 8: /* Anderson-Darling */ fprintf(stdout, _("Anderson-Darling's A^2 (regular & modified for normality): ")); w = Cdhc_anderson_darling(z, nsites); fprintf(stdout, "%g %g\n", w[1], w[0]); break; case 9: /* Cramer-Von Mises */ fprintf(stdout, _("Cramer-Von Mises W^2(regular & modified for normality): ")); w = Cdhc_cramer_von_mises(z, nsites); fprintf(stdout, "%g %g\n", w[1], w[0]); break; case 10: /* Kolmogorov-Smirnov */ fprintf(stdout, _("Kolmogorov-Smirnov's D (regular & modified for normality): ")); w = Cdhc_kolmogorov_smirnov(z, nsites); fprintf(stdout, "%g %g\n", w[1], w[0]); break; case 11: /* chi-square */ fprintf(stdout, _("Chi-Square stat (equal probability classes) and d.f.: ")); w = Cdhc_chi_square(z, nsites); fprintf(stdout, "%g %d\n", w[0], (int)w[1]); break; case 12: /* Shapiro-Wilk */ if (nsites > 50) { G_warning(_("Shapiro-Wilk's W cannot be used for n > 50")); if (nsites < 99) G_message(_("Use Weisberg-Binghams's W''")); } else { fprintf(stdout, _("Shapiro-Wilk W: ")); w = Cdhc_shapiro_wilk(z, nsites); fprintf(stdout, "%g\n", w[0]); } break; case 13: /* Weisberg-Bingham */ if (nsites > 99 || nsites < 50) G_warning(_("Weisberg-Bingham's W'' cannot be used for n < 50 or n > 99")); else { fprintf(stdout, _("Weisberg-Bingham's W'': ")); w = Cdhc_weisberg_bingham(z, nsites); fprintf(stdout, "%g\n", w[0]); } break; case 14: /* Royston */ if (nsites > 2000) G_warning(_("Royston only extended Shapiro-Wilk's W up to n = 2000")); else { fprintf(stdout, _("Shapiro-Wilk W'': ")); w = Cdhc_royston(z, nsites); fprintf(stdout, "%g\n", w[0]); } break; case 15: /* Kotz */ fprintf(stdout, _("Kotz' T'_f (Lognormality vs. Normality): ")); w = Cdhc_kotz_families(z, nsites); fprintf(stdout, "%g\n", w[0]); break; default: break; } } exit(EXIT_SUCCESS); }
struct Map_info *G_sites_open_old(const char *name, const char *mapset) { struct Map_info *Map; struct field_info *fi; int more, nrows, row, ncols, col, ndbl, nstr, adbl, astr, ctype; struct site_att *sa; dbDriver *driver; dbString stmt; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; G_message( _("Dev note: Adapted sites library used for vector points. " "(module should be updated to GRASS 6 vector library)")); Map = (struct Map_info *)G_malloc(sizeof(struct Map_info)); Vect_set_open_level(1); Vect_open_old(Map, name, mapset); G_debug(1, "Vector map opened"); /* Load attributes */ Map->site_att = NULL; Map->n_site_att = 0; Map->n_site_dbl = 0; Map->n_site_str = 0; fi = Vect_get_field(Map, 1); if (fi == NULL) { /* not attribute table */ G_debug(1, "No attribute table"); return Map; } driver = db_start_driver_open_database(fi->driver, fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); db_init_string(&stmt); db_set_string(&stmt, "select * from "); db_append_string(&stmt, fi->table); if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK) G_fatal_error(_("Unable to open select cursor: '%s'"), db_get_string(&stmt)); nrows = db_get_num_rows(&cursor); G_debug(1, "%d rows selected from vector attribute table", nrows); Map->site_att = (struct site_att *) malloc(nrows * sizeof(struct site_att)); Map->n_site_att = nrows; table = db_get_cursor_table(&cursor); ncols = db_get_table_number_of_columns(table); row = 0; adbl = astr = 0; while (1) { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) G_fatal_error(_("Cannot fetch row")); if (!more) break; /* Get number of each type */ if (row == 0) { for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (strcmp(db_get_column_name(column), fi->key) == 0) continue; switch (ctype) { case DB_C_TYPE_INT: case DB_C_TYPE_DOUBLE: adbl++; break; case DB_C_TYPE_STRING: case DB_C_TYPE_DATETIME: astr++; break; } } Map->n_site_dbl = adbl; Map->n_site_str = astr; G_debug(1, "adbl = %d astr = %d", adbl, astr); } sa = &(Map->site_att[row]); sa->dbl = (double *)malloc(adbl * sizeof(double)); sa->str = (char **)malloc(astr * sizeof(char *)); ndbl = nstr = 0; for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); value = db_get_column_value(column); if (strcmp(db_get_column_name(column), fi->key) == 0) { sa->cat = db_get_value_int(value); } else { switch (ctype) { case DB_C_TYPE_INT: sa->dbl[ndbl] = db_get_value_int(value); ndbl++; break; case DB_C_TYPE_DOUBLE: sa->dbl[ndbl] = db_get_value_double(value); ndbl++; break; case DB_C_TYPE_STRING: sa->str[nstr] = G_store(db_get_value_string(value)); nstr++; break; case DB_C_TYPE_DATETIME: sa->str[nstr] = ""; /* TODO */ nstr++; break; } } } row++; } db_close_database_shutdown_driver(driver); /* sort attributes */ qsort((void *)Map->site_att, Map->n_site_att, sizeof(struct site_att), site_att_cmp); return Map; }
int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate, int bTestOpen, int bSingleNewFileIn ) { VSIStatBuf stat; CPLAssert( nLayers == 0 ); pszName = CPLStrdup( pszNewName ); // Released by destructor /* -------------------------------------------------------------------- */ /* Do the given path contains 'vector' and 'head'? */ /* -------------------------------------------------------------------- */ if ( strstr(pszName,"vector") == NULL || strstr(pszName,"head") == NULL ) { if( !bTestOpen ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not GRASS vector, access failed.\n", pszName ); } return FALSE; } /* -------------------------------------------------------------------- */ /* Is the given a regular file? */ /* -------------------------------------------------------------------- */ if( CPLStat( pszName, &stat ) != 0 || !VSI_ISREG(stat.st_mode) ) { if( !bTestOpen ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not GRASS vector, access failed.\n", pszName ); } return FALSE; } /* -------------------------------------------------------------------- */ /* Parse datasource name */ /* -------------------------------------------------------------------- */ if ( !SplitPath(pszName, &pszGisdbase, &pszLocation, &pszMapset, &pszMap) ) { if( !bTestOpen ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not GRASS datasource name, access failed.\n", pszName ); } return FALSE; } CPLDebug ( "GRASS", "Gisdbase: %s", pszGisdbase ); CPLDebug ( "GRASS", "Location: %s", pszLocation ); CPLDebug ( "GRASS", "Mapset: %s", pszMapset ); CPLDebug ( "GRASS", "Map: %s", pszMap ); /* -------------------------------------------------------------------- */ /* Init GRASS library */ /* -------------------------------------------------------------------- */ // GISBASE is path to the directory where GRASS is installed, // it is necessary because there are database drivers. if ( !getenv( "GISBASE" ) ) { static char* gisbaseEnv = NULL; const char *gisbase = GRASS_GISBASE; CPLError( CE_Warning, CPLE_AppDefined, "GRASS warning: GISBASE " "enviroment variable was not set, using:\n%s", gisbase ); char buf[2000]; snprintf ( buf, sizeof(buf), "GISBASE=%s", gisbase ); buf[sizeof(buf)-1] = '\0'; CPLFree(gisbaseEnv); gisbaseEnv = CPLStrdup ( buf ); putenv( gisbaseEnv ); } // Don't use GISRC file and read/write GRASS variables // (from location G_VAR_GISRC) to memory only. G_set_gisrc_mode ( G_GISRC_MODE_MEMORY ); // Init GRASS libraries (required). G_no_gisinit() doesn't check // write permissions for mapset compare to G_gisinit() G_no_gisinit(); // Set error function G_set_error_routine ( (GrassErrorHandler) Grass2OGRErrorHook ); /* -------------------------------------------------------------------- */ /* Set GRASS variables */ /* -------------------------------------------------------------------- */ G__setenv( "GISDBASE", pszGisdbase ); G__setenv( "LOCATION_NAME", pszLocation ); G__setenv( "MAPSET", pszMapset); G_reset_mapsets(); G_add_mapset_to_search_path ( pszMapset ); /* -------------------------------------------------------------------- */ /* Open GRASS vector map */ /* -------------------------------------------------------------------- */ Vect_set_fatal_error ( GV_FATAL_PRINT ); // Print error and continue Vect_set_open_level (2); int level = Vect_open_old ( &map, pszMap, pszMapset); if ( level < 2 ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot open GRASS vector %s on level 2.\n", pszName ); return FALSE; } CPLDebug ( "GRASS", "Num lines = %d", Vect_get_num_lines(&map) ); /* -------------------------------------------------------------------- */ /* Build a list of layers. */ /* -------------------------------------------------------------------- */ int ncidx = Vect_cidx_get_num_fields ( &map ); CPLDebug ( "GRASS", "Num layers = %d", ncidx ); for ( int i = 0; i < ncidx; i++ ) { // Create the layer object OGRGRASSLayer *poLayer; poLayer = new OGRGRASSLayer( i, &map ); // Add layer to data source layer list papoLayers = (OGRGRASSLayer **) CPLRealloc( papoLayers, sizeof(OGRGRASSLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; } bOpened = TRUE; return TRUE; }