Beispiel #1
0
/**
 * \brief Create network arcs (edge) based on given point vector map (nodes)
 *
 * \param file input file defining arcs
 * \param Points input vector point map
 * \param Out output vector map
 * \param afield arcs layer 
 * \param nfield nodes layer 
 *
 * \return number of new arcs
 */
int create_arcs(FILE * file, struct Map_info *Pnts,
		struct Map_info *Out, int afield, int nfield)
{
    char buff[1024];
    int lcat, fcat, tcat;
    int node1, node2;
    int narcs;

    struct line_pnts *points, *points2;
    struct line_cats *cats;

    points = Vect_new_line_struct();
    points2 = Vect_new_line_struct();
    points = Vect_new_line_struct();
    cats = Vect_new_cats_struct();

    narcs = 0;

    while (G_getl2(buff, sizeof(buff) - 1, file)) {
	if (sscanf(buff, "%d%d%d", &lcat, &fcat, &tcat) != 3)
	    G_fatal_error(_("Error reading file: '%s'"), buff);

	node1 = find_node(Pnts, afield, fcat);
	node2 = find_node(Pnts, afield, tcat);

	if (node1 < 1 || node2 < 1) {
	    G_warning(_("Skipping arc %d"), lcat);
	    continue;
	}

	/* geometry */
	Vect_read_line(Pnts, points, cats, node1);
	field2n(cats, nfield);
	Vect_write_line(Out, GV_POINT, points, cats);
	Vect_read_line(Pnts, points2, cats, node2);
	field2n(cats, nfield);
	Vect_write_line(Out, GV_POINT, points2, cats);
	Vect_append_points(points, points2, GV_FORWARD);

	/* category */
	Vect_reset_cats(cats);
	Vect_cat_set(cats, afield, lcat);
	Vect_write_line(Out, GV_LINE, points, cats);

	narcs++;
    }

    Vect_destroy_line_struct(points);
    Vect_destroy_cats_struct(cats);

    return narcs;
}
Beispiel #2
0
int point_in_buffer(struct buf_contours *arr_bc, struct spatial_index *si,
		    struct Map_info *Buf, double x, double y)
{
    int i, j, ret, flag;
    struct bound_box bbox;
    static struct ilist *List = NULL;
    static struct line_pnts *Points = NULL;

    if (List == NULL)
	List = Vect_new_list();
    if (Points == NULL)
	Points = Vect_new_line_struct();

    /* select outer contours overlapping with centroid (x, y) */
    bbox.W = bbox.E = x;
    bbox.N = bbox.S = y;
    bbox.T = PORT_DOUBLE_MAX;
    bbox.B = -PORT_DOUBLE_MAX;

    Vect_spatial_index_select(si, &bbox, List);

    for (i = 0; i < List->n_values; i++) {
	Vect_read_line(Buf, Points, NULL, arr_bc[List->value[i]].outer);
	ret = Vect_point_in_poly(x, y, Points);
	if (ret == 0)
	    continue;

	flag = 1;
	for (j = 0; j < arr_bc[List->value[i]].inner_count; j++) {
	    if (arr_bc[List->value[i]].inner[j] < 1)
		continue;

	    Vect_read_line(Buf, Points, NULL, arr_bc[List->value[i]].inner[j]);
	    ret = Vect_point_in_poly(x, y, Points);
	    if (ret != 0) {	/* inside inner contour */
		flag = 0;
		break;
	    }
	}

	if (flag) {
	    /* (x,y) is inside outer contour and outside inner contours of arr_bc[i] */
	    return 1;
	}
    }

    return 0;
}
Beispiel #3
0
/*!
   \brief Get list of nodes from varray

   Returns the list of all nodes on features selected by varray.
   nodes_to_features conains the index of a feature adjecent to each
   node or -1 if no such feature specified by varray
   exists. Nodes_to_features might be NULL, in which case it is left
   unitialised.

   \param map pointer to Map_info structure
   \param varray pointer to varray structure
   \param[out] nodes list of node ids
   \param node_to_features ?
 */
void NetA_varray_to_nodes(struct Map_info *map, struct varray *varray,
			  struct ilist *nodes, int *nodes_to_features)
{
    int nlines, nnodes, i;

    nlines = Vect_get_num_lines(map);
    nnodes = Vect_get_num_nodes(map);
    if (nodes_to_features)
	for (i = 1; i <= nnodes; i++)
	    nodes_to_features[i] = -1;

    for (i = 1; i <= nlines; i++)
	if (varray->c[i]) {
	    int type = Vect_read_line(map, NULL, NULL, i);

	    if (type == GV_POINT) {
		int node;

		Vect_get_line_nodes(map, i, &node, NULL);
		Vect_list_append(nodes, node);
		if (nodes_to_features)
		    nodes_to_features[node] = i;
	    }
	    else {
		int node1, node2;

		Vect_get_line_nodes(map, i, &node1, &node2);
		Vect_list_append(nodes, node1);
		Vect_list_append(nodes, node2);
		if (nodes_to_features)
		    nodes_to_features[node1] = nodes_to_features[node2] = i;
	    }
	}
}
Beispiel #4
0
/**
   \brief Reverse list selection
   
   \param[in] Map vector map
   \param[in] type feature type
   \param[in,out] reversed list

   \return 1
*/
int reverse_selection(struct Map_info *Map, int type, struct ilist **List)
{

    struct ilist *list_reverse;
    int line, nlines, ltype;

    list_reverse = Vect_new_list();

    nlines = Vect_get_num_lines(Map);

    for (line = 1; line <= nlines; line++) {
	ltype = Vect_read_line(Map, NULL, NULL, line);

	if (!(ltype & type))
	    continue;

	if (!Vect_val_in_list(*List, line))
	    Vect_list_append(list_reverse, line);
    }

    Vect_destroy_list(*List);
    *List = list_reverse;

    return 1;
}
Beispiel #5
0
/*!
  \brief Get area boundary points (native format)
  
  Used by Vect_build_line_area() and Vect_get_area_points().
  
  \param Map pointer to Map_info struct
  \param lines array of boundary lines
  \param n_lines number of lines in array
  \param[out] APoints pointer to output line_pnts struct

  \return number of points
  \return -1 on error
*/
int Vect__get_area_points_nat(const struct Map_info *Map, const plus_t *lines, int n_lines,
                              struct line_pnts *BPoints)
{
    int i, line, aline, dir;
    static struct line_pnts *Points;
    
    if (!Points)
        Points = Vect_new_line_struct();
    
    Vect_reset_line(BPoints);
    for (i = 0; i < n_lines; i++) {
        line = lines[i];
        aline = abs(line);
        G_debug(5, "  append line(%d) = %d", i, line);
        
        if (0 > Vect_read_line(Map, Points, NULL, aline))
            return -1;
        
        dir = line > 0 ? GV_FORWARD : GV_BACKWARD;
        Vect_append_points(BPoints, Points, dir);
        BPoints->n_points--;    /* skip last point, avoids duplicates */
    }
    BPoints->n_points++;        /* close polygon */

    return BPoints->n_points;
}
Beispiel #6
0
int sort_areas(struct Map_info *Map, struct line_pnts *Points,
               int field, struct cat_list *cat_list)
{
    int i, centroid, nareas_selected;
    struct line_cats *Cats;
    CELL cat;

    G_begin_polygon_area_calculations();
    Cats = Vect_new_cats_struct();

    /* first count valid areas */
    nareas = Vect_get_num_areas(Map);
    if (nareas == 0)
	return 0;

    /* allocate list to hold valid area info */
    list =
	(struct list *)G_calloc(nareas * sizeof(char), sizeof(struct list));

    /* store area size,cat,index in list */
    nareas_selected = 0;
    for (i = 0; i < nareas; i++) {

	centroid = Vect_get_area_centroid(Map, i + 1);
	SETNULL(&cat);
	if (centroid <= 0) {
	    G_debug(2,_("Area without centroid (OK for island)"));
	}
	else {
	    Vect_read_line(Map, NULL, Cats, centroid);
	    if (field > 0) {
		if (Vect_cats_in_constraint(Cats, field, cat_list)) {
		    Vect_cat_get(Cats, field, &cat);
		    nareas_selected++;
		}
		else {
		    G_debug(2, _("Area centroid without category"));
		}
	    }
	    else {
		/* field < 1, process all areas with centroid */
		cat = 0;
		nareas_selected++;
	    }
	}

	list[i].index = i + 1;
	Vect_get_area_points(Map, i + 1, Points);
	list[i].size =
	    G_area_of_polygon(Points->x, Points->y, Points->n_points);

	list[i].cat = cat;
    }
    if (nareas_selected > 0) {
	/* sort the list by size */
	qsort(list, nareas * sizeof(char), sizeof(struct list), compare);
    }

    return nareas_selected;
}
Beispiel #7
0
/* Check if point is inside area with category of given field. All cats are set in 
 * Cats with original field.
 * returns number of cats.
 */
int point_area(struct Map_info *Map, int field, double x, double y,
	       struct line_cats *Cats)
{
    int i, area, centr;
    static struct line_cats *CCats = NULL;

    Vect_reset_cats(Cats);
    area = Vect_find_area(Map, x, y);
    G_debug(4, "  area = %d", area);

    if (!area)
	return 0;

    centr = Vect_get_area_centroid(Map, area);

    if (centr <= 0)
	return 0;

    if (!CCats)
	CCats = Vect_new_cats_struct();
    Vect_read_line(Map, NULL, CCats, centr);

    for (i = 0; i < CCats->n_cats; i++) {
	if (CCats->field[i] == field) {
	    Vect_cat_set(Cats, field, CCats->cat[i]);
	}
    }

    return Cats->n_cats;
}
Beispiel #8
0
/*!
   \brief Returns polygon array of points (outer ring) of given area

   \param Map pointer to Map_info structure
   \param area area id
   \param[out] BPoints points array

   \return number of points
   \return -1 on error
 */
int Vect_get_area_points(const struct Map_info *Map,
			 int area, struct line_pnts *BPoints)
{
    int i, line, aline, dir;
    const struct Plus_head *Plus;
    struct P_area *Area;
    static int first_time = 1;
    static struct line_pnts *Points;

    G_debug(3, "Vect_get_area_points(): area = %d", area);
    BPoints->n_points = 0;

    Plus = &(Map->plus);
    Area = Plus->Area[area];

    if (Area == NULL) {		/* dead area */
	G_warning(_("Attempt to read points of nonexistent area"));
	return -1;		/* error , because we should not read dead areas */
    }

    if (first_time == 1) {
	Points = Vect_new_line_struct();
	first_time = 0;
    }

    G_debug(3, "  n_lines = %d", Area->n_lines);
    for (i = 0; i < Area->n_lines; i++) {
	line = Area->lines[i];
	aline = abs(line);
	G_debug(3, "  append line(%d) = %d", i, line);

	if (0 > Vect_read_line(Map, Points, NULL, aline)) {
	    G_fatal_error(_("Unable to read read line %d"), aline);
	}

	G_debug(3, "  line n_points = %d", Points->n_points);

	if (line > 0)
	    dir = GV_FORWARD;
	else
	    dir = GV_BACKWARD;

	Vect_append_points(BPoints, Points, dir);
	if (i != (Area->n_lines - 1))	/* all but not last */
	    BPoints->n_points--;
	G_debug(3, "  area n_points = %d", BPoints->n_points);
    }

    return BPoints->n_points;
}
Beispiel #9
0
/*!
   \brief Get node cost

   For each node in the map, finds the category of the point on it (if
   there is any) and stores the value associated with this category in
   the array node_costs. If there is no point with a category,
   node_costs=0.

   node_costs are multiplied by 1000000 and truncated to integers (as
   is done in Vect_net_build_graph)

   \param In pointer to Map_info structure
   \param layer layer number
   \param column name of column
   \param[out] node_costs list of node costs

   \returns 1 on success
   \return 0 on failure
 */
int NetA_get_node_costs(struct Map_info *In, int layer, char *column,
			int *node_costs)
{
    int i, nlines, nnodes;
    dbCatValArray vals;
    struct line_cats *Cats;
    struct line_pnts *Points;

    dbDriver *driver;
    struct field_info *Fi;

    Fi = Vect_get_field(In, layer);
    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);

    nlines = Vect_get_num_lines(In);
    nnodes = Vect_get_num_nodes(In);
    Cats = Vect_new_cats_struct();
    Points = Vect_new_line_struct();
    for (i = 1; i <= nnodes; i++)
	node_costs[i] = 0;

    db_CatValArray_init(&vals);

    if (db_select_CatValArray(driver, Fi->table, Fi->key, column, NULL, &vals)
	== -1)
	return 0;
    for (i = 1; i <= nlines; i++) {
	int type = Vect_read_line(In, Points, Cats, i);

	if (type == GV_POINT) {
	    int node, cat;
	    double value;

	    if (!Vect_cat_get(Cats, layer, &cat))
		continue;
	    Vect_get_line_nodes(In, i, &node, NULL);
	    if (db_CatValArray_get_value_double(&vals, cat, &value) == DB_OK)
		node_costs[node] = value * 1000000.0;
	}
    }

    Vect_destroy_cats_struct(Cats);
    db_CatValArray_free(&vals);
    db_close_database_shutdown_driver(driver);
    return 1;
}
Beispiel #10
0
/*!
  \brief Fetches FIRST category number for given vector line and field
  
  \param Map pointer to Map_info structure
  \param line line id
  \param field layer number

  \return -1 no category
  \return category number (>=0)
 */
int Vect_get_line_cat(const struct Map_info *Map, int line, int field)
{

    static struct line_cats *cats = NULL;
    int cat, ltype;

    if (cats == NULL)
	cats = Vect_new_cats_struct();

    ltype = Vect_read_line(Map, NULL, cats, line);
    Vect_cat_get(cats, field, &cat);
    G_debug(3, "Vect_get_line_cat: display line %d, ltype %d, cat %d", line,
	    ltype, cat);

    return cat;
}
Beispiel #11
0
/*!
   \brief Get area categories

   \param Map pointer to Map_info structure
   \param area area id
   \param[out] Cats list of categories

   \return 0 centroid found (but may be without categories)
   \return 1 no centroid found
 */
int Vect_get_area_cats(const struct Map_info *Map, int area, struct line_cats *Cats)
{
    int centroid;

    Vect_reset_cats(Cats);

    centroid = Vect_get_area_centroid(Map, area);
    if (centroid > 0) {
	Vect_read_line(Map, NULL, Cats, centroid);
    }
    else {
	return 1;		/* no centroid */
    }


    return 0;
}
Beispiel #12
0
/*!
   \brief Returns polygon array of points for given isle

   \param Map vector map
   \param isle island id
   \param[out] BPoints points array

   \return number of points
   \return -1 on error
 */
int
Vect_get_isle_points(const struct Map_info *Map,
		     int isle, struct line_pnts *BPoints)
{
    int i, line, aline, dir;
    const struct Plus_head *Plus;
    struct P_isle *Isle;
    static int first_time = 1;
    static struct line_pnts *Points;

    G_debug(3, "Vect_get_isle_points(): isle = %d", isle);
    BPoints->n_points = 0;

    Plus = &(Map->plus);
    Isle = Plus->Isle[isle];

    if (first_time == 1) {
	Points = Vect_new_line_struct();
	first_time = 0;
    }

    G_debug(3, "  n_lines = %d", Isle->n_lines);
    for (i = 0; i < Isle->n_lines; i++) {
	line = Isle->lines[i];
	aline = abs(line);
	G_debug(3, "  append line(%d) = %d", i, line);

	if (0 > Vect_read_line(Map, Points, NULL, aline)) {
	    G_fatal_error(_("Unable to read line %d"), aline);
	}

	G_debug(3, "  line n_points = %d", Points->n_points);

	if (line > 0)
	    dir = GV_FORWARD;
	else
	    dir = GV_BACKWARD;

	Vect_append_points(BPoints, Points, dir);
	if (i != (Isle->n_lines - 1))	/* all but not last */
	    BPoints->n_points--;
	G_debug(3, "  isle n_points = %d", BPoints->n_points);
    }

    return (BPoints->n_points);
}
Beispiel #13
0
int rmdac(struct Map_info *Out, struct Map_info *Err)
{
    int i, type, area, ndupl, nlines;

    struct line_pnts *Points;
    struct line_cats *Cats;

    nlines = Vect_get_num_lines(Out);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    G_debug(1, "nlines =  %d", nlines);

    ndupl = 0;

    for (i = 1; i <= nlines; i++) {
	G_percent(i, nlines, 2);
	if (!Vect_line_alive(Out, i))
	    continue;

	type = Vect_read_line(Out, Points, Cats, i);
	if (!(type & GV_CENTROID))
	    continue;

	area = Vect_get_centroid_area(Out, i);
	G_debug(3, "  area = %d", area);

	if (area < 0) {
	    Vect_delete_line(Out, i);
	    ndupl++;

	    if (Err) {
		Vect_write_line(Err, type, Points, Cats);
	    }
	}
    }

    G_verbose_message(_("Duplicate area centroids: %d"), ndupl);

    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    return ndupl;
}
Beispiel #14
0
/**
   \brief Select features by id

   \param[in] Map vector map
   \param[in] type feature type
   \param[in] ids ids list
   \param[in,out] List list of selected features
 
   \return number of selected lines
*/
int sel_by_id(struct Map_info *Map, int type, char *ids, struct ilist *List)
{
    int i;
    int num, id;
    struct cat_list *il;	/* NOTE: this is not cat list, but list of id's */
    struct ilist *List_tmp;

    if (first_selection) {
	List_tmp = List;
	first_selection = 0;
    }
    else {
	List_tmp = Vect_new_list();
    }

    il = Vect_new_cat_list();
    Vect_str_to_cat_list(ids, il);

    num = Vect_get_num_lines(Map);

    for (i = 0; i < il->n_ranges; i++) {
	for (id = 1; id <= num; id++) {
	    if (!(Vect_read_line(Map, NULL, NULL, id) & type)) {
		continue;
	    }
	    if (id >= il->min[i] && id <= il->max[i]) {
		Vect_list_append(List_tmp, id);
	    }
	}
    }

    G_debug(1, "  %d lines selected (by id)", List_tmp->n_values);

    /* merge lists (only duplicate items) */
    if (List_tmp != List) {
	merge_lists(List, List_tmp);
	Vect_destroy_list(List_tmp);
    }

    Vect_destroy_cat_list(il);

    return List->n_values;
}
Beispiel #15
0
/** counts the number of individual segments ( boundaries and lines ) and vertices
*/
void count(struct Map_info *map, int *num_points, int *num_lines)
{
    int index_line = 0;
    int index_point = 0;
    struct line_pnts *sites;
    struct line_cats *cats;
    int type, i;

    sites = Vect_new_line_struct();
    cats = Vect_new_cats_struct();

    for (i = 1; i <= map->plus.n_lines; i++) {

	type = Vect_read_line(map, sites, cats, i);

	if (type != GV_LINE && type != GV_BOUNDARY && type != GV_POINT)
	    continue;

	if (type == GV_LINE) {
	    index_point += sites->n_points;
	    index_line += sites->n_points - 1;
	}
	else if (type == GV_BOUNDARY) {
	    index_point += sites->n_points - 1;
	    index_line += sites->n_points - 1;
	}
	else if (type == GV_POINT) {
	    index_point++;
	}


    }

    *num_points = index_point;
    *num_lines = index_line;

    Vect_destroy_line_struct(sites);
    Vect_destroy_cats_struct(cats);
}
Beispiel #16
0
/* find next line for given line and node 
 *  return: next line (may be input line if it is loop)
 *          0 - num of lines <> 2
 */
int find_next_line(struct Map_info *map, int line, int node, int ltype)
{
    int n_lines, i, tmp_line, tmp_type, next_line;

    G_debug(2, "  find_next_line() line = %d node = %d", line, node);
    next_line = 0;
    n_lines = 0;
    for (i = 0; i < Vect_get_node_n_lines(map, node); i++) {
	tmp_line = abs(Vect_get_node_line(map, node, i));
	tmp_type = Vect_read_line(map, NULL, NULL, tmp_line);
	/* The line may be a loop so we want some other line if exists or the same line if loop */
	if (tmp_type & ltype) {
	    if (next_line == 0 || tmp_line != line)
		next_line = tmp_line;
	    n_lines++;
	}
    }
    if (n_lines != 2)
	next_line = 0;

    G_debug(2, "  -> next line = %d", next_line);
    return next_line;
}
Beispiel #17
0
void edit_line_phase2(struct edit_line *el, double x, double y)
{
    int node1, node2;
    double nodex, nodey, nodez, dist;

    el->phase = 2;

    el->Points = Vect_new_line_struct();
    el->Cats = Vect_new_cats_struct();
    el->line_type = Vect_read_line(&Map, el->Points, el->Cats, el->line);

    el->reversed = 0;

    /* Find out the node nearest to the line */
    Vect_get_line_nodes(&Map, el->line, &node1, &node2);

    Vect_get_node_coor(&Map, node2, &nodex, &nodey, &nodez);
    dist = (x - nodex) * (x - nodex) + (y - nodey) * (y - nodey);

    Vect_get_node_coor(&Map, node1, &nodex, &nodey, &nodez);
    if ((x - nodex) * (x - nodex) + (y - nodey) * (y - nodey) < dist) {
	/* The first node is the nearest => reverse the line and remember
	 * doing so. */
	Vect_line_reverse(el->Points);
	el->reversed = 1;
    }

    display_node(node1, SYMB_BACKGROUND, 1);
    display_node(node2, SYMB_BACKGROUND, 1);
    i_prompt_buttons(_("New Point"), _("Undo Last Point"), _("Close line"));

    set_location(D_u_to_d_col(el->Points->x[el->Points->n_points - 1]),
		 D_u_to_d_row(el->Points->y[el->Points->n_points - 1])
	);
    set_mode(MOUSE_LINE);
}
Beispiel #18
0
/*!
   \brief Extensive tests for correct topology

   - lines or boundaries of zero length
   - intersecting boundaries, ie. overlapping areas
   - areas without centroids that are not isles

   \param Map vector map
   \param[out] Err vector map where errors will be written or NULL

   \return 1 on success
   \return 0 on error
 */
int Vect_topo_check(struct Map_info *Map, struct Map_info *Err)
{
    int line, nlines;
    int nerrors, n_zero_lines, n_zero_boundaries;
    struct line_pnts *Points;
    struct line_cats *Cats;

    /* rebuild topology if needed */
    if (Vect_get_built(Map) != GV_BUILD_ALL) {
	Vect_build_partial(Map, GV_BUILD_NONE);
	Vect_build(Map);
    }

    G_message(_("Checking for topological errors..."));

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* lines or boundaries of zero length */
    n_zero_lines = n_zero_boundaries = 0;
    nlines = Vect_get_num_lines(Map);
    for (line = 1; line <= nlines; line++) {
	int type;

	if (!Vect_line_alive(Map, line))
	    continue;
	    
	type = Vect_get_line_type(Map, line);

	if (type & GV_LINES) {
	    double len;
	    
	    Vect_read_line(Map, Points, Cats, line);
	    len = Vect_line_length(Points);
	    
	    if (len == 0) {
		if (type & GV_LINE)
		    n_zero_lines++;
		else if (type & GV_BOUNDARY)
		    n_zero_boundaries++;
		    
		if (Err)
		    Vect_write_line(Err, type, Points, Cats);
	    }
	}
    }
    
    if (n_zero_lines)
	G_warning(_("Number of lines of length zero: %d"), n_zero_lines);
    if (n_zero_boundaries)
	G_warning(_("Number of boundaries of length zero: %d"), n_zero_boundaries);

    /* remaining checks are for areas only */
    if (Vect_get_num_primitives(Map, GV_BOUNDARY) == 0)
	return 1;

    /* intersecting boundaries -> overlapping areas */
    nerrors = Vect_check_line_breaks(Map, GV_BOUNDARY, Err);
    if (nerrors)
	G_warning(_("Number of boundary intersections: %d"), nerrors);

    /* areas without centroids that are not isles
     * only makes sense if all boundaries are correct */
    nerrors = 0;
    for (line = 1; line <= nlines; line++) {
	int type;
	
	if (!Vect_line_alive(Map, line))
	    continue;
	    
	type = Vect_get_line_type(Map, line);

	if (type == GV_BOUNDARY) {
	    struct P_topo_b *topo = (struct P_topo_b *)Map->plus.Line[line]->topo;

	    if (topo->left == 0 || topo->right == 0) {
		G_debug(3, "line = %d left = %d right = %d", line, 
			topo->left, topo->right);
		nerrors++;
	    }
	}
    }
    if (nerrors)
	G_warning(_("Skipping further checks because of incorrect boundaries"));
    else {
	int i, area, left, right, neighbour;
	int nareas = Vect_get_num_areas(Map);
	struct ilist *List = Vect_new_list();

	nerrors = 0;
	for (area = 1; area <= nareas; area++) {
	    if (!Vect_area_alive(Map, area))
		continue;
	    line = Vect_get_area_centroid(Map, area);
	    if (line != 0)
		continue;   /* has centroid */

	    Vect_get_area_boundaries(Map, area, List);
	    for (i = 0; i < List->n_values; i++) {
		line = List->value[i];
		Vect_get_line_areas(Map, abs(line), &left, &right);
		if (line > 0)
		    neighbour = left;
		else
		    neighbour = right;
		    
		if (neighbour < 0) {
		    neighbour = Vect_get_isle_area(Map, abs(neighbour));
		    if (!neighbour) {
			/* borders outer void */
			nerrors++;
			if (Err) {
			    Vect_read_line(Map, Points, Cats, abs(line));
			    Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
			}
		    }
		    /* else neighbour is > 0, check below */
		}
		if (neighbour > 0) {
		    if (Vect_get_area_centroid(Map, neighbour) == 0) {
			/* neighbouring area does not have a centroid either */
			nerrors++;
			if (Err) {
			    Vect_read_line(Map, Points, Cats, abs(line));
			    Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
			}
		    }
		}
	    }
	}
	Vect_destroy_list(List);

	if (nerrors)
	    G_warning(_("Number of redundant holes: %d"), 
	              nerrors);
    }

    /* what else ? */

    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    return 1;
}
Beispiel #19
0
int main(int argc, char *argv[])
{
    int i, j, nlines, type, field, cat;
    int fd;

    /* struct Categories RCats; *//* TODO */
    struct Cell_head window;
    RASTER_MAP_TYPE out_type;
    CELL *cell;
    DCELL *dcell;
    double drow, dcol;
    char buf[2000];
    struct Option *vect_opt, *rast_opt, *field_opt, *col_opt, *where_opt;
    int Cache_size;
    struct order *cache;
    int cur_row;
    struct GModule *module;

    struct Map_info Map;
    struct line_pnts *Points;
    struct line_cats *Cats;
    int point;
    int point_cnt;		/* number of points in cache */
    int outside_cnt;		/* points outside region */
    int nocat_cnt;		/* points inside region but without category */
    int dupl_cnt;		/* duplicate categories */
    struct bound_box box;

    int *catexst, *cex;
    struct field_info *Fi;
    dbString stmt;
    dbDriver *driver;
    int select, norec_cnt, update_cnt, upderr_cnt, col_type;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("raster"));
    G_add_keyword(_("position"));
    G_add_keyword(_("querying"));
    G_add_keyword(_("attribute table"));
    module->description =
	_("Uploads raster values at positions of vector points to the table.");

    vect_opt = G_define_standard_option(G_OPT_V_INPUT);
    vect_opt->key = "vector";
    vect_opt->description =
	_("Name of input vector points map for which to edit attribute table");

    rast_opt = G_define_standard_option(G_OPT_R_INPUT);
    rast_opt->key = "raster";
    rast_opt->description = _("Name of existing raster map to be queried");

    field_opt = G_define_standard_option(G_OPT_V_FIELD);

    col_opt = G_define_option();
    col_opt->key = "column";
    col_opt->type = TYPE_STRING;
    col_opt->required = YES;
    col_opt->description =
	_("Column name (will be updated by raster values)");

    where_opt = G_define_standard_option(G_OPT_DB_WHERE);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


    field = atoi(field_opt->answer);

    db_init_string(&stmt);
    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    G_get_window(&window);
    Vect_region_box(&window, &box);	/* T and B set to +/- PORT_DOUBLE_MAX */

    /* Open vector */
    Vect_set_open_level(2);
    Vect_open_old(&Map, vect_opt->answer, "");

    Fi = Vect_get_field(&Map, field);
    if (Fi == NULL)
	G_fatal_error(_("Database connection not defined for layer %d"),
		      field);

    /* Open driver */
    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);
    }

    /* Open raster */
    fd = Rast_open_old(rast_opt->answer, "");

    out_type = Rast_get_map_type(fd);

    /* TODO: Later possibly category labels */
    /* 
       if ( Rast_read_cats (name, "", &RCats) < 0 )
       G_fatal_error ( "Cannot read category file");
     */

    /* Check column type */
    col_type = db_column_Ctype(driver, Fi->table, col_opt->answer);

    if (col_type == -1)
	G_fatal_error(_("Column <%s> not found"), col_opt->answer);

    if (col_type != DB_C_TYPE_INT && col_type != DB_C_TYPE_DOUBLE)
	G_fatal_error(_("Column type not supported"));

    if (out_type == CELL_TYPE && col_type == DB_C_TYPE_DOUBLE)
	G_warning(_("Raster type is integer and column type is float"));

    if (out_type != CELL_TYPE && col_type == DB_C_TYPE_INT)
	G_warning(_("Raster type is float and column type is integer, some data lost!!"));

    /* Read vector points to cache */
    Cache_size = Vect_get_num_primitives(&Map, GV_POINT);
    /* Note: Some space may be wasted (outside region or no category) */

    cache = (struct order *)G_calloc(Cache_size, sizeof(struct order));

    point_cnt = outside_cnt = nocat_cnt = 0;

    nlines = Vect_get_num_lines(&Map);

    G_debug(1, "Reading %d vector features fom map", nlines);

    for (i = 1; i <= nlines; i++) {
	type = Vect_read_line(&Map, Points, Cats, i);
	G_debug(4, "line = %d type = %d", i, type);

	/* check type */
	if (!(type & GV_POINT))
	    continue;		/* Points only */

	/* check region */
	if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &box)) {
	    outside_cnt++;
	    continue;
	}

	Vect_cat_get(Cats, field, &cat);
	if (cat < 0) {		/* no category of given field */
	    nocat_cnt++;
	    continue;
	}

	G_debug(4, "    cat = %d", cat);

	/* Add point to cache */
	drow = Rast_northing_to_row(Points->y[0], &window);
	dcol = Rast_easting_to_col(Points->x[0], &window);

	/* a special case.
	 *   if north falls at southern edge, or east falls on eastern edge,
	 *   the point will appear outside the window.
	 *   So, for these edges, bring the point inside the window
	 */
	if (drow == window.rows)
	    drow--;
	if (dcol == window.cols)
	    dcol--;

	cache[point_cnt].row = (int)drow;
	cache[point_cnt].col = (int)dcol;
	cache[point_cnt].cat = cat;
	cache[point_cnt].count = 1;
	point_cnt++;
    }

    Vect_set_db_updated(&Map);
    Vect_hist_command(&Map);
    Vect_close(&Map);

    G_debug(1, "Read %d vector points", point_cnt);
    /* Cache may contain duplicate categories, sort by cat, find and remove duplicates 
     * and recalc count and decrease point_cnt  */
    qsort(cache, point_cnt, sizeof(struct order), by_cat);

    G_debug(1, "Points are sorted, starting duplicate removal loop");

    for (i = 0, j = 1; j < point_cnt; j++)
	if (cache[i].cat != cache[j].cat)
	    cache[++i] = cache[j];
	else
	    cache[i].count++;
    point_cnt = i + 1;

    G_debug(1, "%d vector points left after removal of duplicates",
	    point_cnt);

    /* Report number of points not used */
    if (outside_cnt)
	G_warning(_("%d points outside current region were skipped"),
		  outside_cnt);

    if (nocat_cnt)
	G_warning(_("%d points without category were skipped"), nocat_cnt);

    /* Sort cache by current region row */
    qsort(cache, point_cnt, sizeof(struct order), by_row);

    /* Allocate space for raster row */
    if (out_type == CELL_TYPE)
	cell = Rast_allocate_c_buf();
    else
	dcell = Rast_allocate_d_buf();

    /* Extract raster values from file and store in cache */
    G_debug(1, "Extracting raster values");

    cur_row = -1;

    for (point = 0; point < point_cnt; point++) {
	if (cache[point].count > 1)
	    continue;		/* duplicate cats */

	if (cur_row != cache[point].row) {
	    if (out_type == CELL_TYPE)
		Rast_get_c_row(fd, cell, cache[point].row);
	    else
		Rast_get_d_row(fd, dcell, cache[point].row);
	}
	cur_row = cache[point].row;

	if (out_type == CELL_TYPE) {
	    cache[point].value = cell[cache[point].col];
	}
	else {
	    cache[point].dvalue = dcell[cache[point].col];
	}
    }				/* point loop */

    /* Update table from cache */
    G_debug(1, "Updating db table");

    /* select existing categories to array (array is sorted) */
    select = db_select_int(driver, Fi->table, Fi->key, NULL, &catexst);

    db_begin_transaction(driver);

    norec_cnt = update_cnt = upderr_cnt = dupl_cnt = 0;

    for (point = 0; point < point_cnt; point++) {
	if (cache[point].count > 1) {
	    G_warning(_("More points (%d) of category %d, value set to 'NULL'"),
		      cache[point].count, cache[point].cat);
	    dupl_cnt++;
	}

	/* category exist in DB ? */
	cex =
	    (int *)bsearch((void *)&(cache[point].cat), catexst, select,
			   sizeof(int), srch_cat);
	if (cex == NULL) {	/* cat does not exist in DB */
	    norec_cnt++;
	    G_warning(_("No record for category %d in table <%s>"),
		      cache[point].cat, Fi->table);
	    continue;
	}

	sprintf(buf, "update %s set %s = ", Fi->table, col_opt->answer);

	db_set_string(&stmt, buf);

	if (out_type == CELL_TYPE) {
	    if (cache[point].count > 1 ||
		Rast_is_c_null_value(&cache[point].value)) {
		sprintf(buf, "NULL");
	    }
	    else {
		sprintf(buf, "%d ", cache[point].value);
	    }
	}
	else {			/* FCELL or DCELL */
	    if (cache[point].count > 1 ||
		Rast_is_d_null_value(&cache[point].dvalue)) {
		sprintf(buf, "NULL");
	    }
	    else {
		sprintf(buf, "%.10f", cache[point].dvalue);
	    }
	}
	db_append_string(&stmt, buf);

	sprintf(buf, " where %s = %d", Fi->key, cache[point].cat);
	db_append_string(&stmt, buf);
	/* user provides where condition: */
	if (where_opt->answer) {
	    sprintf(buf, " AND %s", where_opt->answer);
	    db_append_string(&stmt, buf);
	}
	G_debug(3, db_get_string(&stmt));

	/* Update table */
	if (db_execute_immediate(driver, &stmt) == DB_OK) {
	    update_cnt++;
	}
	else {
	    upderr_cnt++;
	}
    }

    G_debug(1, "Committing DB transaction");
    db_commit_transaction(driver);
    G_free(catexst);
    db_close_database_shutdown_driver(driver);
    db_free_string(&stmt);

    /* Report */
    G_message(_("%d categories loaded from table"), select);
    G_message(_("%d categories loaded from vector"), point_cnt);
    G_message(_("%d categories from vector missing in table"), norec_cnt);
    G_message(_("%d duplicate categories in vector"), dupl_cnt);
    if (!where_opt->answer)
	G_message(_("%d records updated"), update_cnt);
    G_message(_("%d update errors"), upderr_cnt);

    exit(EXIT_SUCCESS);
}
Beispiel #20
0
int main(int argc, char *argv[])
{
    struct Map_info In, Out;
    static struct line_pnts *Points;
    struct line_cats *Cats;
    struct GModule *module;	/* GRASS module for parsing arguments */
    struct Option *map_in, *map_out;
    struct Option *cat_opt, *field_opt, *where_opt, *abcol, *afcol;
    struct Option *iter_opt, *error_opt;
    struct Flag *geo_f, *add_f;
    int chcat, with_z;
    int layer, mask_type;
    struct varray *varray;
    dglGraph_s *graph;
    int i, geo, nnodes, nlines, j, max_cat;
    char buf[2000], *covered;

    /* initialize GIS environment */
    G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */

    /* initialize module */
    module = G_define_module();
    module->keywords = _("vector, network, centrality measures");
    module->description =
	_("Computes degree, centrality, betweeness, closeness and eigenvector "
	 "centrality measures in the network.");

    /* Define the different options as defined in gis.h */
    map_in = G_define_standard_option(G_OPT_V_INPUT);
    field_opt = G_define_standard_option(G_OPT_V_FIELD);

    map_out = G_define_standard_option(G_OPT_V_OUTPUT);

    cat_opt = G_define_standard_option(G_OPT_V_CATS);
    cat_opt->guisection = _("Selection");
    where_opt = G_define_standard_option(G_OPT_WHERE);
    where_opt->guisection = _("Selection");

    afcol = G_define_standard_option(G_OPT_COLUMN);
    afcol->key = "afcolumn";
    afcol->required = NO;
    afcol->description =
	_("Name of arc forward/both direction(s) cost column");
    afcol->guisection = _("Cost");

    abcol = G_define_standard_option(G_OPT_COLUMN);
    abcol->key = "abcolumn";
    abcol->required = NO;
    abcol->description = _("Name of arc backward direction cost column");
    abcol->guisection = _("Cost");

    deg_opt = G_define_standard_option(G_OPT_COLUMN);
    deg_opt->key = "degree";
    deg_opt->required = NO;
    deg_opt->description = _("Name of degree centrality column");
    deg_opt->guisection = _("Columns");

    close_opt = G_define_standard_option(G_OPT_COLUMN);
    close_opt->key = "closeness";
    close_opt->required = NO;
    close_opt->description = _("Name of closeness centrality column");
    close_opt->guisection = _("Columns");

    betw_opt = G_define_standard_option(G_OPT_COLUMN);
    betw_opt->key = "betweenness";
    betw_opt->required = NO;
    betw_opt->description = _("Name of betweenness centrality column");
    betw_opt->guisection = _("Columns");

    eigen_opt = G_define_standard_option(G_OPT_COLUMN);
    eigen_opt->key = "eigenvector";
    eigen_opt->required = NO;
    eigen_opt->description = _("Name of eigenvector centrality column");
    eigen_opt->guisection = _("Columns");

    iter_opt = G_define_option();
    iter_opt->key = "iterations";
    iter_opt->answer = "1000";
    iter_opt->type = TYPE_INTEGER;
    iter_opt->required = NO;
    iter_opt->description =
	_("Maximum number of iterations to compute eigenvector centrality");

    error_opt = G_define_option();
    error_opt->key = "error";
    error_opt->answer = "0.1";
    error_opt->type = TYPE_DOUBLE;
    error_opt->required = NO;
    error_opt->description =
	_("Cummulative error tolerance for eigenvector centrality");

    geo_f = G_define_flag();
    geo_f->key = 'g';
    geo_f->description =
	_("Use geodesic calculation for longitude-latitude locations");

    add_f = G_define_flag();
    add_f->key = 'a';
    add_f->description = _("Add points on nodes");

    /* options and flags parser */
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    /* TODO: make an option for this */
    mask_type = GV_LINE | GV_BOUNDARY;

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    Vect_check_input_output_name(map_in->answer, map_out->answer,
				 GV_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;

    /* parse filter option and select appropriate lines */
    layer = atoi(field_opt->answer);
    chcat =
	(NetA_initialise_varray
	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
	  &varray) == 1);

    /* Create table */
    Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
    Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", 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_init_string(&tmp);
    if (deg_opt->answer)
	append_string(&tmp, deg_opt->answer);
    if (close_opt->answer)
	append_string(&tmp, close_opt->answer);
    if (betw_opt->answer)
	append_string(&tmp, betw_opt->answer);
    if (eigen_opt->answer)
	append_string(&tmp, eigen_opt->answer);
    sprintf(buf,
	    "create table %s(cat integer%s)", Fi->table, db_get_string(&tmp));

    db_set_string(&sql, buf);
    G_debug(2, db_get_string(&sql));

    if (db_execute_immediate(driver, &sql) != DB_OK) {
	db_close_database_shutdown_driver(driver);
	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
    }

    if (db_create_index2(driver, Fi->table, "cat") != 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);

    Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0,
			 afcol->answer, abcol->answer, NULL, geo, 0);
    graph = &(In.graph);
    nnodes = dglGet_NodeCount(graph);

    deg = closeness = betw = eigen = NULL;

    covered = (char *)G_calloc(nnodes + 1, sizeof(char));
    if (!covered)
	G_fatal_error(_("Out of memory"));

    if (deg_opt->answer) {
	deg = (double *)G_calloc(nnodes + 1, sizeof(double));
	if (!deg)
	    G_fatal_error(_("Out of memory"));
    }

    if (close_opt->answer) {
	closeness = (double *)G_calloc(nnodes + 1, sizeof(double));
	if (!closeness)
	    G_fatal_error(_("Out of memory"));
    }

    if (betw_opt->answer) {
	betw = (double *)G_calloc(nnodes + 1, sizeof(double));
	if (!betw)
	    G_fatal_error(_("Out of memory"));
    }

    if (eigen_opt->answer) {
	eigen = (double *)G_calloc(nnodes + 1, sizeof(double));
	if (!eigen)
	    G_fatal_error(_("Out of memory"));
    }


    if (deg_opt->answer) {
	G_message(_("Computing degree centrality measure"));
	NetA_degree_centrality(graph, deg);
    }
    if (betw_opt->answer || close_opt->answer) {
	G_message(_("Computing betweenness and/or closeness centrality measure"));
	NetA_betweenness_closeness(graph, betw, closeness);
	if (closeness)
	    for (i = 1; i <= nnodes; i++)
		closeness[i] /= (double)In.cost_multip;
    }
    if (eigen_opt->answer) {
	G_message(_("Computing eigenvector centrality measure"));
	NetA_eigenvector_centrality(graph, atoi(iter_opt->answer),
				    atof(error_opt->answer), eigen);
    }


    nlines = Vect_get_num_lines(&In);
    G_message(_("Writing data into the table..."));
    G_percent_reset();
    for (i = 1; i <= nlines; i++) {
	G_percent(i, nlines, 1);
	int type = Vect_read_line(&In, Points, Cats, i);

	if (type == GV_POINT && (!chcat || varray->c[i])) {
	    int cat, node;

	    if (!Vect_cat_get(Cats, layer, &cat))
		continue;
	    Vect_reset_cats(Cats);
	    Vect_cat_set(Cats, 1, cat);
	    Vect_write_line(&Out, type, Points, Cats);
	    Vect_get_line_nodes(&In, i, &node, NULL);
	    process_node(node, cat);
	    covered[node] = 1;
	}
    }

    if (add_f->answer && !chcat) {
	max_cat = 0;
	for (i = 1; i <= nlines; i++) {
	    Vect_read_line(&In, NULL, Cats, i);
	    for (j = 0; j < Cats->n_cats; j++)
		if (Cats->cat[j] > max_cat)
		    max_cat = Cats->cat[j];
	}
	max_cat++;
	for (i = 1; i <= nnodes; i++)
	    if (!covered[i]) {
		Vect_reset_cats(Cats);
		Vect_cat_set(Cats, 1, max_cat);
		NetA_add_point_on_node(&In, &Out, i, Cats);
		process_node(i, max_cat);
		max_cat++;
	    }

    }

    db_commit_transaction(driver);
    db_close_database_shutdown_driver(driver);

    G_free(covered);
    if (deg)
	G_free(deg);
    if (closeness)
	G_free(closeness);
    if (betw)
	G_free(betw);
    if (eigen)
	G_free(eigen);
    Vect_build(&Out);

    Vect_close(&In);
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
Beispiel #21
0
/* Returns 0 - ok , 1 - error */
int
plot(int ctype, struct Map_info *Map, int type, int field,
     char *columns, int ncols, char *sizecol, int size, double scale,
     COLOR * ocolor, COLOR * colors, int y_center, double *max_reference,
     int do3d)
{
    int ltype, nlines, line, col, more, coltype, nselcols;
    double x, y, csize, len;
    struct line_pnts *Points;
    struct line_cats *Cats;
    int cat;
    double *val;
    char buf[2000];
    struct field_info *Fi;
    dbDriver *driver;
    dbValue *value;
    dbString sql;
    dbCursor cursor;
    dbTable *table;
    dbColumn *column;

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    db_init_string(&sql);

    Fi = Vect_get_field(Map, field);
    if (Fi == NULL)
	G_fatal_error(_("Database connection not defined for layer %d"),
		      field);

    /* Open driver */
    driver = db_start_driver_open_database(Fi->driver, Fi->database);
    if (driver == NULL) {
	G_warning(_("Unable to open database <%s> by driver <%s>"),
		  Fi->database,
		  Fi->driver);
	return 1;
    }
    db_set_error_handler_driver(driver);

    val = (double *)G_malloc((ncols + 1) * sizeof(double));	/* + 1 for sizecol */

    Vect_rewind(Map);

    nlines = Vect_get_num_lines(Map);

    /* loop through each vector feature */
    for (line = 1; line <= nlines; line++) {
	G_debug(3, "line = %d", line);
	ltype = Vect_read_line(Map, Points, Cats, line);

	if (!(ltype & type))
	    continue;

	Vect_cat_get(Cats, field, &cat);
	if (cat < 0)
	    continue;

	/* Select values from DB */
	if (ctype == CTYPE_PIE && sizecol != NULL) {
	    sprintf(buf, "select %s, %s from %s where %s = %d", columns,
		    sizecol, Fi->table, Fi->key, cat);
	    nselcols = ncols + 1;
	}
	else {
	    sprintf(buf, "select %s from %s where %s = %d", columns,
		    Fi->table, Fi->key, cat);
	    nselcols = ncols;
	}

	db_set_string(&sql, buf);
	G_debug(3, "SQL: %s", buf);

	if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
	    DB_OK) {
	    G_warning(_("Unable to open select cursor: '%s'"),
		      buf);
	    return 1;
	}

	table = db_get_cursor_table(&cursor);
	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK || !more)
	    continue;

	for (col = 0; col < nselcols; col++) {
	    column = db_get_table_column(table, col);
	    value = db_get_column_value(column);
	    coltype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
	    switch (coltype) {
	    case DB_C_TYPE_INT:
		val[col] = (double)db_get_value_int(value);
		break;
	    case DB_C_TYPE_DOUBLE:
		val[col] = db_get_value_double(value);
		break;
	    default:
		G_warning("Column type not supported (must be INT or FLOAT)");
		return 1;
	    }
	    G_debug(4, "  val[%d]: %f", col, val[col]);
	}

	db_close_cursor(&cursor);

	/* Center of chart */
	if (ltype & GV_LINES) {	/* find center */
	    len = Vect_line_length(Points) / 2;
	    Vect_point_on_line(Points, len, &x, &y, NULL, NULL, NULL);
	}
	else {
	    x = Points->x[0];
	    y = Points->y[0];
	}

	if (ctype == CTYPE_PIE) {
	    if (sizecol != NULL) {
		csize = val[ncols];
		size = scale * csize;
	    }
	    pie(x, y, size, val, ncols, ocolor, colors, do3d);
	}
	else {
	    bar(x, y, size, scale, val, ncols, ocolor, colors, y_center,
		max_reference, do3d);
	}
    }

    db_close_database_shutdown_driver(driver);
    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    return 0;
}
Beispiel #22
0
/**
  \brief Extrude 2D vector feature to 3D

  - point -> 3d line (vertical)
  - line  -> set of faces (each segment defines one face)
  - area  -> set of faces + kernel

  \param In input vector map
  \param[in,out] Out output vector map
  \param Cats categories
  \param Points points
  \param fdrast background raster map
  \param trace trace raster map values
  \param interpolation method
  \param objheight object height
  \param voffset vertical offset
  \param window raster region
  \param type feature type
  \param centroid number of centroid for area

  \return number of written objects
*/
int extrude(struct Map_info *In, struct Map_info *Out,
            const struct line_cats *Cats, const struct line_pnts *Points,
            int fdrast, int trace, int interp_method, double scale, int null_defined,
            double null_val, double objheight, double voffset,
            const struct Cell_head *window, int type, int centroid)
{
    int k;			/* Points->n_points */
    int nlines;
    
    double voffset_dem;         /* minimal offset */
    double voffset_curr;	/* offset of current point */
    double voffset_next;	/* offset of next point */

    nlines = 0;

    if (type != GV_POINT && Points->n_points < 2)
	return nlines; /* not enough points to face */

    if (!Points_wall) {
        Points_wall  = Vect_new_line_struct();
        Points_roof  = Vect_new_line_struct();
        Points_floor = Vect_new_line_struct();
        Cats_floor    = Vect_new_cats_struct();
    }
    else {
        Vect_reset_line(Points_wall);
        Vect_reset_line(Points_roof);
        Vect_reset_line(Points_floor);
        Vect_reset_cats(Cats_floor);
    }

    voffset_dem = 0.0;
    /* do not trace -> calculate minimum dem offset */
    if (fdrast >= 0 && !trace) {
	for (k = 0; k < Points->n_points; k++) {
            voffset_curr = scale * Rast_get_sample(fdrast, window, NULL,
                                                   Points->y[k], Points->x[k], /* north, east */
                                                   0, interp_method);
	    if (Rast_is_d_null_value(&voffset_curr)) {
                if (null_defined)
                    voffset_curr = null_val;
                else
                    voffset_curr = 0.;
            }

	    if (k == 0) {
		voffset_dem = voffset_curr;
	    }
	    else {
		if (voffset_curr < voffset_dem)
		    voffset_dem = voffset_curr;
	    }
	}
    }

    /* build walls, roof and floor */
    for (k = 0; ; k++) {
	voffset_curr = voffset_next = 0.0;

	if (fdrast >= 0 && trace) {
	    voffset_curr = scale * Rast_get_sample(fdrast, window, NULL,
                                                   Points->y[k], Points->x[k], /* north, east */
                                                   0, interp_method);

	    if (type != GV_POINT) {
		voffset_next = scale * Rast_get_sample(fdrast, window, NULL,
                                                       Points->y[k + 1],         /* north, east */
                                                       Points->x[k + 1], 0,
                                                       interp_method);
	    }
	}

	if (Rast_is_d_null_value(&voffset_curr)) {
            if (null_defined)
                voffset_curr = null_val;
            else
                voffset_curr = 0.;
	}
        if (Rast_is_d_null_value(&voffset_next)) {
            if (null_defined)
                voffset_next = null_val;
            else
                voffset_next = 0.;
        }

        if (trace) {
            voffset_curr += voffset;
            voffset_next += voffset;
        }
        else {
            voffset_curr = voffset_dem + voffset;
            voffset_next = voffset_dem + voffset;
        }

	if (type == GV_POINT) {
	    /* point -> 3d line (vertical) */
	    Vect_append_point(Points_wall, Points->x[k], Points->y[k],
			      Points->z[k] + voffset_curr);
	    Vect_append_point(Points_wall, Points->x[k], Points->y[k],
			      Points->z[k] + objheight + (trace ? voffset_curr : 0.));
	}
	
        if (type & (GV_LINE | GV_AREA)) {
	    /* reset */
	    Vect_reset_line(Points_wall);

	    /* line/boundary segment -> face */
	    Vect_append_point(Points_wall, Points->x[k], Points->y[k],
			      Points->z[k] + voffset_curr);
	    Vect_append_point(Points_wall, Points->x[k + 1], Points->y[k + 1],
			      Points->z[k + 1] + voffset_next);
	    Vect_append_point(Points_wall, Points->x[k + 1], Points->y[k + 1],
			      Points->z[k + 1] + objheight + (trace ? voffset_next : 0.));
	    Vect_append_point(Points_wall, Points->x[k], Points->y[k],
			      Points->z[k] + objheight + (trace ? voffset_curr : 0.));
	    Vect_append_point(Points_wall, Points->x[k], Points->y[k],
			      Points->z[k] + voffset_curr);

	    Vect_write_line(Out, GV_FACE, Points_wall, Cats);
	    nlines++;

	    if (type == GV_AREA) {
		/* roof */
		Vect_append_point(Points_roof, Points->x[k], Points->y[k],
				  Points->z[k] + objheight + (trace ? voffset_curr : 0.));
                /* floor */
		Vect_append_point(Points_floor, Points->x[k], Points->y[k],
				  Points->z[k] + voffset_curr);
	    }
	}
        
        if (k >= Points->n_points - 2)
            break;
    }

    if (type == GV_POINT) {
	Vect_write_line(Out, GV_LINE, Points_wall, Cats);
    }
    else if (type == GV_AREA && Points_roof->n_points > 2) {
        /* close roof and floor */
	Vect_append_point(Points_roof,
			  Points_roof->x[0], Points_roof->y[0],
			  Points_roof->z[0]);
	Vect_append_point(Points_floor,
			  Points_floor->x[0], Points_floor->y[0],
			  Points_floor->z[0]);
        /* write roof and floor */
        Vect_write_line(Out, GV_FACE, Points_roof, Cats);
        Vect_write_line(Out, GV_FACE, Points_floor, Cats);
	nlines += 2;

	if (centroid > 0) {
	    /* centroid -> kernel */
            Vect_read_line(In, Points_floor, Cats_floor, centroid);
	    Points_floor->z[0] = Points_roof->z[0] / 2.0; /* TODO: do it better */
	    Vect_write_line(Out, GV_KERNEL, Points_floor, Cats_floor);
	    nlines++;
	}
    }
    
    return nlines;
}
Beispiel #23
0
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;
    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(_("attribute table"));
    G_add_keyword(_("database"));
    G_add_keyword(_("univariate statistics"));
    G_add_keyword(_("zonal statistics"));
    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);

    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);

    if (print_flag->answer)
	/* get field separator */
	    fs = G_option_to_separator(fs_opt);
    else
	    fs = NULL;

    /* 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);
    if (Vect_open_old(&PIn, point_opt->answer, mapset) < 0)
	G_fatal_error(_("Unable to open vector map <%s>"), point_opt->answer);

    /* 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);
    if (Vect_open_old(&AIn, area_opt->answer, mapset) < 0)
	G_fatal_error(_("Unable to open vector map <%s>"), area_opt->answer);

    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);
}
Beispiel #24
0
/* *************************************************************** */
int plot1(struct Map_info *Map, int type, int area, struct cat_list *Clist,
	  const struct color_rgb *color, const struct color_rgb *fcolor,
	  int chcat, SYMBOL * Symb, int size, int id_flag,
	  int table_colors_flag, int cats_color_flag, char *rgb_column,
	  int default_width, char *width_column, double width_scale)
{
    int i, ltype, nlines = 0, line, cat = -1;
    double *x, *y;
    struct line_pnts *Points, *PPoints;
    struct line_cats *Cats;
    double msize;
    int x0, y0;

    struct field_info *fi = NULL;
    dbDriver *driver = NULL;
    dbCatValArray cvarr_rgb, cvarr_width;
    dbCatVal *cv_rgb = NULL, *cv_width = NULL;
    int nrec_rgb = 0, nrec_width = 0;

    int open_db;
    int custom_rgb = FALSE;
    char colorstring[12];	/* RRR:GGG:BBB */
    int red, grn, blu;
    RGBA_Color *line_color, *fill_color, *primary_color;
    unsigned char which;
    int width;

    line_color = G_malloc(sizeof(RGBA_Color));
    fill_color = G_malloc(sizeof(RGBA_Color));
    primary_color = G_malloc(sizeof(RGBA_Color));

    primary_color->a = RGBA_COLOR_OPAQUE;

    /* change function prototype to pass RGBA_Color instead of color_rgb? */
    if (color) {
	line_color->r = color->r;
	line_color->g = color->g;
	line_color->b = color->b;
	line_color->a = RGBA_COLOR_OPAQUE;
    }
    else
	line_color->a = RGBA_COLOR_NONE;

    if (fcolor) {
	fill_color->r = fcolor->r;
	fill_color->g = fcolor->g;
	fill_color->b = fcolor->b;
	fill_color->a = RGBA_COLOR_OPAQUE;
    }
    else
	fill_color->a = RGBA_COLOR_NONE;


    msize = size * (D_d_to_u_col(2.0) - D_d_to_u_col(1.0));	/* do it better */

    Points = Vect_new_line_struct();
    PPoints = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    open_db = table_colors_flag || width_column;

    if (open_db) {
	fi = Vect_get_field(Map, (Clist->field > 0 ? Clist->field : 1));
	if (fi == NULL) {
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  (Clist->field > 0 ? Clist->field : 1));
	}

	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);
    }

    if (table_colors_flag) {
	/* for reading RRR:GGG:BBB color strings from table */

	if (rgb_column == NULL || *rgb_column == '\0')
	    G_fatal_error(_("Color definition column not specified"));

	db_CatValArray_init(&cvarr_rgb);

	nrec_rgb = db_select_CatValArray(driver, fi->table, fi->key,
					 rgb_column, NULL, &cvarr_rgb);

	G_debug(3, "nrec_rgb (%s) = %d", rgb_column, nrec_rgb);

	if (cvarr_rgb.ctype != DB_C_TYPE_STRING)
	    G_fatal_error(_("Color definition column (%s) not a string. "
			    "Column must be of form RRR:GGG:BBB where RGB values range 0-255."),
			  rgb_column);

	if (nrec_rgb < 0)
	    G_fatal_error(_("Cannot select data (%s) from table"),
			  rgb_column);

	G_debug(2, "\n%d records selected from table", nrec_rgb);

	for (i = 0; i < cvarr_rgb.n_values; i++) {
	    G_debug(4, "cat = %d  %s = %s", cvarr_rgb.value[i].cat,
		    rgb_column, db_get_string(cvarr_rgb.value[i].val.s));
	}
    }

    if (width_column) {
	if (*width_column == '\0')
	    G_fatal_error(_("Line width column not specified."));

	db_CatValArray_init(&cvarr_width);

	nrec_width = db_select_CatValArray(driver, fi->table, fi->key,
					   width_column, NULL, &cvarr_width);

	G_debug(3, "nrec_width (%s) = %d", width_column, nrec_width);

	if (cvarr_width.ctype != DB_C_TYPE_INT &&
	    cvarr_width.ctype != DB_C_TYPE_DOUBLE)
	    G_fatal_error(_("Line width column (%s) not a number."),
			  width_column);

	if (nrec_width < 0)
	    G_fatal_error(_("Cannot select data (%s) from table"),
			  width_column);

	G_debug(2, "\n%d records selected from table", nrec_width);

	for (i = 0; i < cvarr_width.n_values; i++) {
	    G_debug(4, "cat = %d  %s = %d", cvarr_width.value[i].cat,
		    width_column,
		    (cvarr_width.ctype ==
		     DB_C_TYPE_INT ? cvarr_width.value[i].val.
		     i : (int)cvarr_width.value[i].val.d));
	}
    }

    if (open_db)
	db_close_database_shutdown_driver(driver);

    Vect_rewind(Map);

    /* Is it necessary to reset line/label color in each loop ? */

    if (color && !table_colors_flag && !cats_color_flag)
	D_RGB_color(color->r, color->g, color->b);

    if (Vect_level(Map) >= 2)
	nlines = Vect_get_num_lines(Map);

    line = 0;
    while (1) {
	if (Vect_level(Map) >= 2) {
	    line++;
	    if (line > nlines)
		return 0;
	    if (!Vect_line_alive(Map, line))
		continue;
	    ltype = Vect_read_line(Map, Points, Cats, line);
	}
	else {
	    ltype = Vect_read_next_line(Map, Points, Cats);
	    switch (ltype) {
	    case -1:
		fprintf(stderr, _("\nERROR: vector map - can't read\n"));
		return -1;
	    case -2:		/* EOF */
		return 0;
	    }
	}

	if (!(type & ltype))
	    continue;

	if (chcat) {
	    int found = 0;

	    if (id_flag) {	/* use line id */
		if (!(Vect_cat_in_cat_list(line, Clist)))
		    continue;
	    }
	    else {
		for (i = 0; i < Cats->n_cats; i++) {
		    if (Cats->field[i] == Clist->field &&
			Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
			found = 1;
			break;
		    }
		}
		if (!found)
		    continue;
	    }
	}
	else if (Clist->field > 0) {
	    int found = 0;

	    for (i = 0; i < Cats->n_cats; i++) {
		if (Cats->field[i] == Clist->field) {
		    found = 1;
		    break;
		}
	    }
	    /* lines with no category will be displayed */
	    if (Cats->n_cats > 0 && !found)
		continue;
	}


	if (table_colors_flag) {

	    /* only first category */
	    cat = Vect_get_line_cat(Map, line,
				    (Clist->field > 0 ? Clist->field :
				     (Cats->n_cats >
				      0 ? Cats->field[0] : 1)));

	    if (cat >= 0) {
		G_debug(3, "display element %d, cat %d", line, cat);

		/* Read RGB colors from db for current area # */
		if (db_CatValArray_get_value(&cvarr_rgb, cat, &cv_rgb) !=
		    DB_OK) {
		    custom_rgb = FALSE;
		}
		else {
		    sprintf(colorstring, "%s", db_get_string(cv_rgb->val.s));

		    if (*colorstring != '\0') {
			G_debug(3, "element %d: colorstring: %s", line,
				colorstring);

			if (G_str_to_color(colorstring, &red, &grn, &blu) ==
			    1) {
			    custom_rgb = TRUE;
			    G_debug(3, "element:%d  cat %d r:%d g:%d b:%d",
				    line, cat, red, grn, blu);
			}
			else {
			    custom_rgb = FALSE;
			    G_warning(_("Error in color definition column (%s), element %d "
				       "with cat %d: colorstring [%s]"),
				      rgb_column, line, cat, colorstring);
			}
		    }
		    else {
			custom_rgb = FALSE;
			G_warning(_("Error in color definition column (%s), element %d with cat %d"),
				  rgb_column, line, cat);
		    }
		}
	    }			/* end if cat */
	    else {
		custom_rgb = FALSE;
	    }
	}			/* end if table_colors_flag */


	/* random colors */
	if (cats_color_flag) {
	    custom_rgb = FALSE;
	    if (Clist->field > 0) {
		cat = Vect_get_line_cat(Map, line, Clist->field);
		if (cat >= 0) {
		    G_debug(3, "display element %d, cat %d", line, cat);
		    /* fetch color number from category */
		    which = (cat % palette_ncolors);
		    G_debug(3, "cat:%d which color:%d r:%d g:%d b:%d", cat,
			    which, palette[which].R, palette[which].G,
			    palette[which].B);

		    custom_rgb = TRUE;
		    red = palette[which].R;
		    grn = palette[which].G;
		    blu = palette[which].B;
		}
	    }
	    else if (Cats->n_cats > 0) {
		/* fetch color number from layer */
		which = (Cats->field[0] % palette_ncolors);
		G_debug(3, "layer:%d which color:%d r:%d g:%d b:%d",
			Cats->field[0], which, palette[which].R,
			palette[which].G, palette[which].B);

		custom_rgb = TRUE;
		red = palette[which].R;
		grn = palette[which].G;
		blu = palette[which].B;
	    }
	}


	if (nrec_width) {

	    /* only first category */
	    cat = Vect_get_line_cat(Map, line,
				    (Clist->field > 0 ? Clist->field :
				     (Cats->n_cats >
				      0 ? Cats->field[0] : 1)));

	    if (cat >= 0) {
		G_debug(3, "display element %d, cat %d", line, cat);

		/* Read line width from db for current area # */

		if (db_CatValArray_get_value(&cvarr_width, cat, &cv_width) !=
		    DB_OK) {
		    width = default_width;
		}
		else {
		    width =
			width_scale * (cvarr_width.ctype ==
				       DB_C_TYPE_INT ? cv_width->val.
				       i : (int)cv_width->val.d);
		    if (width < 0) {
			G_warning(_("Error in line width column (%s), element %d "
				   "with cat %d: line width [%d]"),
				  width_column, line, cat, width);
			width = default_width;
		    }
		}
	    }			/* end if cat */
	    else {
		width = default_width;
	    }

	    D_line_width(width);
	}			/* end if nrec_width */


	/* enough of the prep work, lets start plotting stuff */
	x = Points->x;
	y = Points->y;

	if ((ltype & GV_POINTS) && Symb != NULL) {
	    if (!(color || fcolor || custom_rgb))
		continue;

	    x0 = D_u_to_d_col(x[0]);
	    y0 = D_u_to_d_row(y[0]);

	    /* skip if the point is outside of the display window */
	    /*      xy<0 tests make it go ever-so-slightly faster */
	    if (x0 < 0 || y0 < 0 ||
		x0 > D_get_d_east() || x0 < D_get_d_west() ||
		y0 > D_get_d_south() || y0 < D_get_d_north())
		continue;

	    /* use random or RGB column color if given, otherwise reset */
	    /* centroids always use default color to stand out from underlying area */
	    if (custom_rgb && (ltype != GV_CENTROID)) {
		primary_color->r = (unsigned char)red;
		primary_color->g = (unsigned char)grn;
		primary_color->b = (unsigned char)blu;
		D_symbol2(Symb, x0, y0, primary_color, line_color);
	    }
	    else
		D_symbol(Symb, x0, y0, line_color, fill_color);


	}
	else if (color || custom_rgb) {
	    if (!table_colors_flag && !cats_color_flag)
		D_RGB_color(color->r, color->g, color->b);
	    else {
		if (custom_rgb)
		    D_RGB_color((unsigned char)red, (unsigned char)grn,
				(unsigned char)blu);
		else
		    D_RGB_color(color->r, color->g, color->b);
	    }

	    /* Plot the lines */
	    if (Points->n_points == 1)	/* line with one coor */
		D_polydots_abs(x, y, Points->n_points);
	    else		/*use different user defined render methods */
		D_polyline_abs(x, y, Points->n_points);
	}
    }

    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    return 0;			/* not reached */
}
Beispiel #25
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *units_opt, *vertices_opt;
    
    struct Map_info In, Out;
    struct line_pnts *Points, *Points2;
    struct line_cats *Cats;

    int line, nlines, layer;
    double length = -1;
    int vertices = 0;
    double (*line_length) ();
    int latlon = 0;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("geometry"));
    module->description = _("Splits vector lines to shorter segments.");
    
    in_opt = G_define_standard_option(G_OPT_V_INPUT);

    layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);

    out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
    
    length_opt = G_define_option();
    length_opt->key = "length";
    length_opt->type = TYPE_DOUBLE;
    length_opt->required = NO;
    length_opt->multiple = NO;
    length_opt->description = _("Maximum segment length");

    units_opt = G_define_option();
    units_opt->key = "units";
    units_opt->type = TYPE_STRING;
    units_opt->required = NO;
    units_opt->multiple = NO;
    units_opt->options = "meters,kilometers,feet,miles,nautmiles";
    units_opt->answer = "meters";
    units_opt->description = _("Length units");
    
    vertices_opt = G_define_option();
    vertices_opt->key = "vertices";
    vertices_opt->type = TYPE_INTEGER;
    vertices_opt->required = NO;
    vertices_opt->multiple = NO;
    vertices_opt->description = _("Maximum number of vertices in segment");
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    if ((length_opt->answer && vertices_opt->answer) ||
	!(length_opt->answer || vertices_opt->answer))
	G_fatal_error(_("Use either length or vertices"));

    line_length = NULL;

    if (length_opt->answer) {
	length = atof(length_opt->answer);
	if (length <= 0)
	    G_fatal_error(_("Length must be positive but is %g"), length);

	/* convert length to meters */
	if (strcmp(units_opt->answer, "meters") == 0)
	    /* do nothing */ ;
	else if (strcmp(units_opt->answer, "kilometers") == 0)
	    length *= FROM_KILOMETERS;
	else if (strcmp(units_opt->answer, "feet") == 0)
	    length *= FROM_FEET;
	else if (strcmp(units_opt->answer, "miles") == 0)
	    length *= FROM_MILES;
	else if (strcmp(units_opt->answer, "nautmiles") == 0)
	    length *= FROM_NAUTMILES;
	else
	    G_fatal_error(_("Unknown unit %s"), units_opt->answer); 

	/* set line length function */
	if ((latlon = (G_projection() == PROJECTION_LL)) == 1)
	    line_length = Vect_line_geodesic_length;
	else {
	    double factor;
	    
	    line_length = Vect_line_length;
	    
	    /* convert length to map units */
	    if ((factor = G_database_units_to_meters_factor()) == 0)
		G_fatal_error(_("Can not get projection units"));
	    else {
		/* meters to units */
		length = length / factor;
	    }
	}
	G_verbose_message(_("length in %s: %g"), (latlon ? "meters" : "map units"), length);
    }

    if (vertices_opt->answer) {
	vertices = atoi(vertices_opt->answer);
	if (vertices < 2)
	    G_fatal_error(_("Number of vertices must be at least 2"));
    }
    
    Vect_set_open_level(2);
    Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer);
    layer = Vect_get_field_number(&In, layer_opt->answer);
    
    Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In));
    
    Vect_copy_head_data(&In, &Out);
    Vect_hist_copy(&In, &Out);
    Vect_hist_command(&Out);
    Vect_copy_tables(&In, &Out, layer);
    
    Points = Vect_new_line_struct();
    Points2 = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    nlines = Vect_get_num_lines(&In);

    for (line = 1; line <= nlines; line++) {
	int ltype;

	G_percent(line, nlines, 1);

	if (!Vect_line_alive(&In, line))
	    continue;

	ltype = Vect_read_line(&In, Points, Cats, line);

	if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
	  continue;

	if (ltype & GV_LINES) {
	    if (length > 0) {
		double l, from, to, step;

		l = line_length(Points);

		if (l <= length) {
		    Vect_write_line(&Out, ltype, Points, Cats);
		}
		else {
		    int n, i;

		    n = ceil(l / length);
		    if (latlon)
			l = Vect_line_length(Points);

		    step = l / n;
		    from = 0.;

		    for (i = 0; i < n; i++) {
			int ret;
			double x, y, z;

			if (i == n - 1) {
			    to = l;	/* to be sure that it goes to end */
			}
			else {
			    to = from + step;
			}

			ret = Vect_line_segment(Points, from, to, Points2);
			if (ret == 0) {
			    G_warning(_("Unable to make line segment: %f - %f (line length = %f)"),
				      from, to, l);
			    continue;
			}

			/* To be sure that the coordinates are identical */
			if (i > 0) {
			    Points2->x[0] = x;
			    Points2->y[0] = y;
			    Points2->z[0] = z;
			}
			if (i == n - 1) {
			    Points2->x[Points2->n_points - 1] =
				Points->x[Points->n_points - 1];
			    Points2->y[Points2->n_points - 1] =
				Points->y[Points->n_points - 1];
			    Points2->z[Points2->n_points - 1] =
				Points->z[Points->n_points - 1];
			}

			Vect_write_line(&Out, ltype, Points2, Cats);

			/* last point */
			x = Points2->x[Points2->n_points - 1];
			y = Points2->y[Points2->n_points - 1];
			z = Points2->z[Points2->n_points - 1];

			from += step;
		    }
		}
	    }
	    else {
		int start = 0;	/* number of coordinates written */

		while (start < Points->n_points - 1) {
		    int i, v;

		    Vect_reset_line(Points2);
		    for (i = 0; i < vertices; i++) {
			v = start + i;
			if (v == Points->n_points)
			    break;

			Vect_append_point(Points2, Points->x[v], Points->y[v],
					  Points->z[v]);
		    }

		    Vect_write_line(&Out, ltype, Points2, Cats);

		    start = v;
		}
	    }
	}
	else {
	    Vect_write_line(&Out, ltype, Points, Cats);
	}
    }

    Vect_close(&In);
    Vect_build(&Out);
    Vect_close(&Out);
    
    exit(EXIT_SUCCESS);
}
Beispiel #26
0
int area_area(struct Map_info *In, int *field, struct Map_info *Tmp,
	      struct Map_info *Out, struct field_info *Fi,
	      dbDriver * driver, int operator, int *ofield,
	      ATTRIBUTES * attr, struct ilist *BList, double snap)
{
    int ret, input, line, nlines, area, nareas;
    int in_area, in_centr, out_cat;
    struct line_pnts *Points;
    struct line_cats *Cats;
    CENTR *Centr;
    char buf[1000];
    dbString stmt;
    int nmodif;
    int verbose;

    verbose = G_verbose();

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* optional snap */
    if (snap > 0) {
	int i, j, snapped_lines = 0;
	struct bound_box box;
	struct boxlist *boxlist = Vect_new_boxlist(0);
	struct ilist *reflist = Vect_new_list();
	
	G_message(_("Snapping boundaries with %g ..."), snap);

	/* snap boundaries in B to boundaries in A,
	 * not modifying boundaries in A */

	if (BList->n_values > 1)
	    qsort(BList->value, BList->n_values, sizeof(int), cmp_int);

	snapped_lines = 0;
	nlines = BList->n_values;
	for (i = 0; i < nlines; i++) {
	    line = BList->value[i];
	    Vect_read_line(Tmp, Points, Cats, line);
	    /* select lines by box */
	    Vect_get_line_box(Tmp, line, &box);
	    box.E += snap;
	    box.W -= snap;
	    box.N += snap;
	    box.S -= snap;
	    box.T = 0.0;
	    box.B = 0.0;
	    Vect_select_lines_by_box(Tmp, &box, GV_BOUNDARY, boxlist);
	    
	    if (boxlist->n_values > 0) {
		Vect_reset_list(reflist);
		for (j = 0; j < boxlist->n_values; j++) {
		    int aline = boxlist->id[j];

		    if (!bsearch(&aline, BList->value, BList->n_values,
			sizeof(int), cmp_int)) {
			G_ilist_add(reflist, aline);
		    }
		}
		
		/* snap bline to alines */
		if (Vect_snap_line(Tmp, reflist, Points, snap, 0, NULL, NULL)) {
		    /* rewrite bline*/
		    Vect_delete_line(Tmp, line);
		    ret = Vect_write_line(Tmp, GV_BOUNDARY, Points, Cats);
		    G_ilist_add(BList, ret);
		    snapped_lines++;
		    G_debug(3, "line %d snapped", line);
		}
	    }
	}
	Vect_destroy_boxlist(boxlist);
	Vect_destroy_list(reflist);

	G_verbose_message(n_("%d boundary snapped",
                             "%d boundaries snapped",
                             snapped_lines), snapped_lines);
    }

    /* same procedure like for v.in.ogr:
     * Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections
     * are created. We must call Vect_break_lines(), Vect_remove_duplicates()
     * and Vect_clean_small_angles_at_nodes() until no more small dangles are found */
    do {
	G_message(_("Breaking lines..."));
	Vect_break_lines_list(Tmp, NULL, BList, GV_BOUNDARY, NULL);

	/* Probably not necessary for LINE x AREA */
	G_message(_("Removing duplicates..."));
	Vect_remove_duplicates(Tmp, GV_BOUNDARY, NULL);

	G_message(_("Cleaning boundaries at nodes..."));
	nmodif =
	    Vect_clean_small_angles_at_nodes(Tmp, GV_BOUNDARY, NULL);
    } while (nmodif > 0);

    /* ?: May be result of Vect_break_lines() + Vect_remove_duplicates() any dangle or bridge?
     * In that case, calls to Vect_remove_dangles() and Vect_remove_bridges() would be also necessary */

    G_set_verbose(0);
    /* should be fast, be silent */
    Vect_build_partial(Tmp, GV_BUILD_AREAS);
    G_set_verbose(verbose);
    nlines = Vect_get_num_lines(Tmp);
    ret = 0;
    for (line = 1; line <= nlines; line++) {
	if (!Vect_line_alive(Tmp, line))
	    continue;
	if (Vect_get_line_type(Tmp, line) == GV_BOUNDARY) {
	    int left, rite;
	    
	    Vect_get_line_areas(Tmp, line, &left, &rite);
	    
	    if (left == 0 || rite == 0) {
		/* invalid boundary */
		ret = 1;
		break;
	    }
	}
    }
    if (ret) {
	Vect_remove_dangles(Tmp, GV_BOUNDARY, -1, NULL);
	Vect_remove_bridges(Tmp, NULL, NULL, NULL);
    }

    G_set_verbose(0);
    Vect_build_partial(Tmp, GV_BUILD_NONE);
    Vect_build_partial(Tmp, GV_BUILD_BASE);
    G_set_verbose(verbose);
    G_message(_("Merging lines..."));
    Vect_merge_lines(Tmp, GV_BOUNDARY, NULL, NULL);

    /* Attach islands */
    G_message(_("Attaching islands..."));
    /* can take some time, show messages */
    Vect_build_partial(Tmp, GV_BUILD_ATTACH_ISLES);

    /* Calculate new centroids for all areas */
    nareas = Vect_get_num_areas(Tmp);

    Centr = (CENTR *) G_malloc((nareas + 1) * sizeof(CENTR));	/* index from 1 ! */
    for (area = 1; area <= nareas; area++) {
	ret =
	    Vect_get_point_in_area(Tmp, area, &(Centr[area].x),
				   &(Centr[area].y));
	if (ret < 0) {
	    G_warning(_("Cannot calculate area centroid"));
	    Centr[area].valid = 0;
	}
	else {
	    Centr[area].valid = 1;
	}
    }

    /* Query input maps */
    for (input = 0; input < 2; input++) {
	G_message(_("Querying vector map <%s>..."),
		  Vect_get_full_name(&(In[input])));

	for (area = 1; area <= nareas; area++) {
	    Centr[area].cat[input] = Vect_new_cats_struct();

	    G_percent(area, nareas, 1);

	    in_area =
		Vect_find_area(&(In[input]), Centr[area].x, Centr[area].y);
	    if (in_area > 0) {
		in_centr = Vect_get_area_centroid(&(In[input]), in_area);
		if (in_centr > 0) {
		    int i;

		    Vect_read_line(&(In[input]), NULL, Cats, in_centr);
		    /* Add all cats with original field number */
		    for (i = 0; i < Cats->n_cats; i++) {
			if (Cats->field[i] == field[input]) {
			    ATTR *at;

			    Vect_cat_set(Centr[area].cat[input], ofield[input + 1],
					 Cats->cat[i]);

			    /* Mark as used */
			    at = find_attr(&(attr[input]), Cats->cat[i]);
			    if (!at)
				G_fatal_error(_("Attribute not found"));

			    at->used = 1;
			}
		    }
		}
	    }
	}
    }

    G_message(_("Writing centroids..."));

    db_init_string(&stmt);
    out_cat = 1;
    for (area = 1; area <= nareas; area++) {
	int i;

	G_percent(area, nareas, 1);

	/* check the condition */
	switch (operator) {
	case OP_AND:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 &&
		 Centr[area].cat[1]->n_cats > 0))
		continue;
	    break;
	case OP_OR:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 ||
		 Centr[area].cat[1]->n_cats > 0))
		continue;
	    break;
	case OP_NOT:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 &&
		 !(Centr[area].cat[1]->n_cats > 0)))
		continue;
	    break;
	case OP_XOR:
	    if ((Centr[area].cat[0]->n_cats > 0 &&
		 Centr[area].cat[1]->n_cats > 0) ||
		(!(Centr[area].cat[0]->n_cats > 0) &&
		 !(Centr[area].cat[1]->n_cats > 0)))
		continue;
	    break;
	}

	Vect_reset_line(Points);
	Vect_reset_cats(Cats);

	Vect_append_point(Points, Centr[area].x, Centr[area].y, 0.0);

	if (ofield[0] > 0) {
	    /* Add new cats for all combinations of input cats (-1 in cycle for null) */
	    for (i = -1; i < Centr[area].cat[0]->n_cats; i++) {
		int j;

		if (i == -1 && Centr[area].cat[0]->n_cats > 0)
		    continue;	/* no need to make null */

		for (j = -1; j < Centr[area].cat[1]->n_cats; j++) {
		    if (j == -1 && Centr[area].cat[1]->n_cats > 0)
			continue;	/* no need to make null */

		    if (ofield[0] > 0)
			Vect_cat_set(Cats, ofield[0], out_cat);

		    /* attributes */
		    if (driver) {
			ATTR *at;

			sprintf(buf, "insert into %s values ( %d", Fi->table,
				out_cat);
			db_set_string(&stmt, buf);

			/* cata */
			if (i >= 0) {
			    if (attr[0].columns) {
				at = find_attr(&(attr[0]),
					       Centr[area].cat[0]->cat[i]);
				if (!at)
				    G_fatal_error(_("Attribute not found"));

				if (at->values)
				    db_append_string(&stmt, at->values);
				else
				    db_append_string(&stmt, attr[0].null_values);
			    }
			    else {
				sprintf(buf, ", %d", Centr[area].cat[0]->cat[i]);
				db_append_string(&stmt, buf);
			    }
			}
			else {
			    if (attr[0].columns) {
				db_append_string(&stmt, attr[0].null_values);
			    }
			    else {
				sprintf(buf, ", null");
				db_append_string(&stmt, buf);
			    }
			}

			/* catb */
			if (j >= 0) {
			    if (attr[1].columns) {
				at = find_attr(&(attr[1]),
					       Centr[area].cat[1]->cat[j]);
				if (!at)
				    G_fatal_error(_("Attribute not found"));

				if (at->values)
				    db_append_string(&stmt, at->values);
				else
				    db_append_string(&stmt, attr[1].null_values);
			    }
			    else {
				sprintf(buf, ", %d", Centr[area].cat[1]->cat[j]);
				db_append_string(&stmt, buf);
			    }
			}
			else {
			    if (attr[1].columns) {
				db_append_string(&stmt, attr[1].null_values);
			    }
			    else {
				sprintf(buf, ", null");
				db_append_string(&stmt, buf);
			    }
			}

			db_append_string(&stmt, " )");

			G_debug(3, "%s", db_get_string(&stmt));

			if (db_execute_immediate(driver, &stmt) != DB_OK)
			    G_warning(_("Unable to insert new record: '%s'"),
				      db_get_string(&stmt));
		    }
		    out_cat++;
		}
	    }
	}

	/* Add all cats from input vectors */
	if (ofield[1] > 0 && field[0] > 0) {
	    for (i = 0; i < Centr[area].cat[0]->n_cats; i++) {
		if (Centr[area].cat[0]->field[i] == field[0])
		    Vect_cat_set(Cats, ofield[1], Centr[area].cat[0]->cat[i]);
	    }
	}

	if (ofield[2] > 0 && field[1] > 0 && ofield[1] != ofield[2]) {
	    for (i = 0; i < Centr[area].cat[1]->n_cats; i++) {
		if (Centr[area].cat[1]->field[i] == field[1])
		    Vect_cat_set(Cats, ofield[2], Centr[area].cat[1]->cat[i]);
	    }
	}

	Vect_write_line(Tmp, GV_CENTROID, Points, Cats);
	Vect_write_line(Out, GV_CENTROID, Points, Cats);
    }

    G_set_verbose(0);
    /* should be fast, be silent */
    Vect_build_partial(Tmp, GV_BUILD_CENTROIDS);
    G_set_verbose(verbose);
    /* Copy valid boundaries to final output */
    nlines = Vect_get_num_lines(Tmp);

    for (line = 1; line <= nlines; line++) {
	int i, ltype, side[2], centr[2];

	G_percent(line, nlines, 1);	/* must be before any continue */

	if (!Vect_line_alive(Tmp, line))
	    continue;

	ltype = Vect_read_line(Tmp, Points, Cats, line);
	if (!(ltype & GV_BOUNDARY))
	    continue;

	Vect_get_line_areas(Tmp, line, &side[0], &side[1]);

	for (i = 0; i < 2; i++) {
	    if (side[i] == 0) {	/* This should not happen ! */
		centr[i] = 0;
		continue;
	    }

	    if (side[i] > 0) {
		area = side[i];
	    }
	    else {		/* island */
		area = Vect_get_isle_area(Tmp, abs(side[i]));
	    }

	    if (area > 0)
		centr[i] = Vect_get_area_centroid(Tmp, area);
	    else
		centr[i] = 0;
	}

	if (centr[0] || centr[1])
	    Vect_write_line(Out, GV_BOUNDARY, Points, Cats);
    }

    return 0;
}
Beispiel #27
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct Option *map_opt, *type_opt, *field_opt, *col_opt, *where_opt,
	*percentile;
    struct Flag *shell_flag, *extended;
    struct Map_info Map;
    struct field_info *Fi;
    dbDriver *Driver;
    dbCatValArray Cvarr;
    struct line_pnts *Points;
    struct line_cats *Cats;
    int otype, ofield;
    int compatible = 1;		/* types are compatible: point+centroid or line+boundary or area */
    int nrec, ctype, nlines, line, nareas, area;
    int nmissing = 0;		/* number of missing atttributes */
    int nnull = 0;		/* number of null values */
    int first = 1;

    /* Statistics */
    int count = 0;		/* number of features with non-null attribute */
    double sum = 0.0;
    double sumsq = 0.0;
    double sumcb = 0.0;
    double sumqt = 0.0;
    double sum_abs = 0.0;
    double min = 0.0 / 0.0;	/* init as nan */
    double max = 0.0 / 0.0;
    double mean, mean_abs, pop_variance, sample_variance, pop_stdev,
	sample_stdev, pop_coeff_variation, kurtosis, skewness;
    double total_size = 0.0;	/* total size: length/area */

    /* Extended statistics */
    int perc;

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("statistics"));
    module->label =
	_("Calculates univariate statistics for attribute.");
    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";

    col_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    col_opt->required = YES;

    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");

    extended = G_define_flag();
    extended->key = 'e';
    extended->description = _("Calculate extended statistics");

    G_gisinit(argv[0]);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    otype = Vect_option_to_types(type_opt);
    perc = atoi(percentile->answer);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* open input vector */
    Vect_set_open_level(2);
    Vect_open_old2(&Map, map_opt->answer, "", field_opt->answer);
    ofield = Vect_get_field_number(&Map, field_opt->answer);

    /* 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) {
	G_warning(_("Incompatible vector type(s) specified, only number of features, minimum, maximum and range "
		   "can be calculated"));
    }

    if (extended->answer && !(otype & GV_POINTS)) {
	G_warning(_("Extended statistics is currently supported only for points/centroids"));
    }

    /* Read attributes */
    db_CatValArray_init(&Cvarr);
    Fi = Vect_get_field(&Map, ofield);
    if (Fi == NULL) {
	G_fatal_error(_(" Database connection not defined for layer <%s>"), field_opt->answer);
    }

    Driver = db_start_driver_open_database(Fi->driver, Fi->database);
    if (Driver == NULL)
	G_fatal_error("Unable to open database <%s> by driver <%s>",
		      Fi->database, Fi->driver);

    /* Note do not check if the column exists in the table because it may be an expression */

    nrec =
	db_select_CatValArray(Driver, Fi->table, Fi->key, col_opt->answer,
			      where_opt->answer, &Cvarr);
    G_debug(2, "nrec = %d", nrec);

    ctype = Cvarr.ctype;
    if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
	G_fatal_error(_("Column type not supported"));

    if (nrec < 0)
	G_fatal_error(_("Unable to select data from table"));

    db_close_database_shutdown_driver(Driver);

    /* Lines */
    nlines = Vect_get_num_lines(&Map);

    for (line = 1; line <= nlines; line++) {
	int i, type;

	G_debug(3, "line = %d", line);

	type = Vect_read_line(&Map, Points, Cats, line);
	if (!(type & otype))
	    continue;

	for (i = 0; i < Cats->n_cats; i++) {
	    if (Cats->field[i] == ofield) {
		double val;
		dbCatVal *catval;

		G_debug(3, "cat = %d", Cats->cat[i]);

		if (db_CatValArray_get_value(&Cvarr, Cats->cat[i], &catval) !=
		    DB_OK) {
		    G_debug(3, "No record for cat = %d", Cats->cat[i]);
		    nmissing++;
		    continue;
		}

		if (catval->isNull) {
		    G_debug(3, "NULL value for cat = %d", Cats->cat[i]);
		    nnull++;
		    continue;
		}

		if (ctype == DB_C_TYPE_INT) {
		    val = catval->val.i;
		}
		else if (ctype == DB_C_TYPE_DOUBLE) {
		    val = catval->val.d;
		}

		count++;

		if (first) {
		    max = val;
		    min = val;
		    first = 0;
		}
		else {
		    if (val > max)
			max = val;
		    if (val < min)
			min = val;
		}

		if (compatible) {
		    if (type & GV_POINTS) {
			sum += val;
			sumsq += val * val;
			sumcb += val * val * val;
			sumqt += val * val * val * val;
			sum_abs += fabs(val);
		    }
		    else {	/* GV_LINES */
			double l;

			l = Vect_line_length(Points);
			sum += l * val;
			sumsq += l * val * val;
			sumcb += l * val * val * val;
			sumqt += l * val * val * val * val;
			sum_abs += l * fabs(val);
			total_size += l;
		    }
		}
		G_debug(3, "sum = %f total_size = %f", sum, total_size);
	    }
	}
    }

    if (otype & GV_AREA) {
	nareas = Vect_get_num_areas(&Map);
	for (area = 1; area <= nareas; area++) {
	    int i, centr;

	    G_debug(3, "area = %d", area);

	    centr = Vect_get_area_centroid(&Map, area);
	    if (centr < 1)
		continue;

	    G_debug(3, "centr = %d", centr);
	    Vect_read_line(&Map, NULL, Cats, centr);

	    for (i = 0; i < Cats->n_cats; i++) {
		if (Cats->field[i] == ofield) {
		    double val;
		    dbCatVal *catval;

		    G_debug(3, "cat = %d", Cats->cat[i]);

		    if (db_CatValArray_get_value
			(&Cvarr, Cats->cat[i], &catval) != DB_OK) {
			G_debug(3, "No record for cat = %d", Cats->cat[i]);
			nmissing++;
			continue;
		    }

		    if (catval->isNull) {
			G_debug(3, "NULL value for cat = %d", Cats->cat[i]);
			nnull++;
			continue;
		    }

		    if (ctype == DB_C_TYPE_INT) {
			val = catval->val.i;
		    }
		    else if (ctype == DB_C_TYPE_DOUBLE) {
			val = catval->val.d;
		    }

		    count++;

		    if (first) {
			max = val;
			min = val;
			first = 0;
		    }
		    else {
			if (val > max)
			    max = val;
			if (val < min)
			    min = val;
		    }

		    if (compatible) {
			double a;

			a = Vect_get_area_area(&Map, area);
			sum += a * val;
			sumsq += a * val * val;
			sumcb += a * val * val * val;
			sumqt += a * val * val * val * val;
			sum_abs += a * fabs(val);
			total_size += a;
		    }
		    G_debug(4, "sum = %f total_size = %f", sum, total_size);
		}
	    }
	}
    }

    G_debug(2, "sum = %f total_size = %f", sum, total_size);

    if (compatible) {
	if ((otype & GV_LINES) || (otype & GV_AREA)) {
	    mean = sum / total_size;
	    mean_abs = sum_abs / total_size;
	    /* Roger Bivand says it is wrong see GRASS devel list 7/2004 */
	    /*
	       pop_variance = (sumsq - sum*sum/total_size)/total_size;
	       pop_stdev = sqrt(pop_variance);
	     */
	}
	else {
	    double n = count;

	    mean = sum / count;
	    mean_abs = sum_abs / count;
	    pop_variance = (sumsq - sum * sum / count) / count;
	    pop_stdev = sqrt(pop_variance);
	    pop_coeff_variation = pop_stdev / (sqrt(sum * sum) / count);
	    sample_variance = (sumsq - sum * sum / count) / (count - 1);
	    sample_stdev = sqrt(sample_variance);
	    kurtosis =
		(sumqt / count - 4 * sum * sumcb / (n * n) +
		 6 * sum * sum * sumsq / (n * n * n) -
		 3 * sum * sum * sum * sum / (n * n * n * n))
		/ (sample_stdev * sample_stdev * sample_stdev *
		   sample_stdev) - 3;
	    skewness =
		(sumcb / n - 3 * sum * sumsq / (n * n) +
		 2 * sum * sum * sum / (n * n * n))
		/ (sample_stdev * sample_stdev * sample_stdev);
	}
    }

    G_debug(3, "otype %d:", otype);

    if (shell_flag->answer) {
	fprintf(stdout, "n=%d\n", count);
	fprintf(stdout, "nmissing=%d\n", nmissing);
	fprintf(stdout, "nnull=%d\n", nnull);
	if (count > 0) {
	    fprintf(stdout, "min=%g\n", min);
	    fprintf(stdout, "max=%g\n", max);
	    fprintf(stdout, "range=%g\n", max - min);
	    if (compatible && (otype & GV_POINTS)) {
		fprintf(stdout, "mean=%g\n", mean);
		fprintf(stdout, "mean_abs=%g\n", mean_abs);
		fprintf(stdout, "population_stddev=%g\n", pop_stdev);
		fprintf(stdout, "population_variance=%g\n", pop_variance);
		fprintf(stdout, "population_coeff_variation=%g\n",
			pop_coeff_variation);
		if (otype & GV_POINTS) {
		    fprintf(stdout, "sample_stddev=%g\n", sample_stdev);
		    fprintf(stdout, "sample_variance=%g\n", sample_variance);
		    fprintf(stdout, "kurtosis=%g\n", kurtosis);
		    fprintf(stdout, "skewness=%g\n", skewness);
		}
	    }
	}
    }
    else {
	fprintf(stdout, "number of features with non NULL attribute: %d\n",
		count);
	fprintf(stdout, "number of missing attributes: %d\n", nmissing);
	fprintf(stdout, "number of NULL attributes: %d\n", nnull);
	if (count > 0) {
	    fprintf(stdout, "minimum: %g\n", min);
	    fprintf(stdout, "maximum: %g\n", max);
	    fprintf(stdout, "range: %g\n", max - min);
	    if (compatible && (otype & GV_POINTS)) {
		fprintf(stdout, "mean: %g\n", mean);
		fprintf(stdout, "mean of absolute values: %g\n", mean_abs);
		fprintf(stdout, "population standard deviation: %g\n",
			pop_stdev);
		fprintf(stdout, "population variance: %g\n", pop_variance);
		fprintf(stdout, "population coefficient of variation: %g\n",
			pop_coeff_variation);
		if (otype & GV_POINTS) {
		    fprintf(stdout, "sample standard deviation: %g\n",
			    sample_stdev);
		    fprintf(stdout, "sample variance: %g\n", sample_variance);
		    fprintf(stdout, "kurtosis: %g\n", kurtosis);
		    fprintf(stdout, "skewness: %g\n", skewness);
		}
	    }
	}
    }

    /* TODO: mode, skewness, kurtosis */
    if (extended->answer && compatible && (otype & GV_POINTS) && count > 0) {
	double quartile_25 = 0.0, quartile_75 = 0.0, quartile_perc = 0.0;
	double median = 0.0;
	int qpos_25, qpos_75, qpos_perc;

	qpos_25 = (int)(count * 0.25 - 0.5);
	qpos_75 = (int)(count * 0.75 - 0.5);
	qpos_perc = (int)(count * perc / 100. - 0.5);

	if (db_CatValArray_sort_by_value(&Cvarr) != DB_OK)
	    G_fatal_error(_("Cannot sort the key/value array"));

	if (Cvarr.ctype == DB_C_TYPE_INT) {
	    quartile_25 = (Cvarr.value[qpos_25]).val.i;
	    if (count % 2)	/* odd */
		median = (Cvarr.value[(int)(count / 2)]).val.i;
	    else		/* even */
		median =
		    ((Cvarr.value[count / 2 - 1]).val.i +
		     (Cvarr.value[count / 2]).val.i) / 2.0;
	    quartile_75 = (Cvarr.value[qpos_75]).val.i;
	    quartile_perc = (Cvarr.value[qpos_perc]).val.i;
	}
	else {			/* must be DB_C_TYPE_DOUBLE */
	    quartile_25 = (Cvarr.value[qpos_25]).val.d;
	    if (count % 2)	/* odd */
		median = (Cvarr.value[(int)(count / 2)]).val.d;
	    else		/* even */
		median =
		    ((Cvarr.value[count / 2 - 1]).val.d +
		     (Cvarr.value[count / 2]).val.d) / 2.0;
	    quartile_75 = (Cvarr.value[qpos_75]).val.d;
	    quartile_perc = (Cvarr.value[qpos_perc]).val.d;
	}

	if (shell_flag->answer) {
	    fprintf(stdout, "first_quartile=%g\n", quartile_25);
	    fprintf(stdout, "median=%g\n", median);
	    fprintf(stdout, "third_quartile=%g\n", quartile_75);
	    fprintf(stdout, "percentile_%d=%g\n", perc, quartile_perc);
	}
	else {
	    fprintf(stdout, "1st quartile: %g\n", quartile_25);
	    if (count % 2)
		fprintf(stdout, "median (odd number of cells): %g\n", median);
	    else
		fprintf(stdout, "median (even number of cells): %g\n",
			median);
	    fprintf(stdout, "3rd quartile: %g\n", quartile_75);

	    if (perc % 10 == 1 && perc != 11)
		fprintf(stdout, "%dst percentile: %g\n", perc, quartile_perc);
	    else if (perc % 10 == 2 && perc != 12)
		fprintf(stdout, "%dnd percentile: %g\n", perc, quartile_perc);
	    else if (perc % 10 == 3 && perc != 13)
		fprintf(stdout, "%drd percentile: %g\n", perc, quartile_perc);
	    else
		fprintf(stdout, "%dth percentile: %g\n", perc, quartile_perc);
	}
    }

    Vect_close(&Map);

    exit(EXIT_SUCCESS);
}
Beispiel #28
0
int display_label(struct Map_info *Map, int type,
		  struct cat_list *Clist, LATTR *lattr, int chcat)
{
    int ltype;
    struct line_pnts *Points;
    struct line_cats *Cats;
    int ogr_centroids;

    const struct Format_info *finfo;
    
    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    Vect_rewind(Map);

    ogr_centroids = FALSE;
    finfo = Vect_get_finfo(Map);
    if (Vect_maptype(Map) == GV_FORMAT_OGR ||
	(Vect_maptype(Map) == GV_FORMAT_POSTGIS &&
         finfo->pg.toposchema_name == NULL)) {
	if (Vect_level(Map) < 2)
	    G_warning(_("Topology level required for drawing centroids "
			"for OGR layers"));
	else if (Vect_get_num_primitives(Map, GV_CENTROID) > 0 &&
		 type & GV_CENTROID)
	    /* label centroids from topo, don't label boundaries */
	    ogr_centroids = TRUE;
    }
    
    while (TRUE) {
	ltype = Vect_read_next_line(Map, Points, Cats);
	if (ltype == -1)
	    G_fatal_error(_("Unable to read vector map"));
	else if (ltype == -2) /* EOF */
	    break;
	
        if (!(type & ltype) && !((type & GV_AREA) && (ltype & GV_CENTROID)))
	    continue;		/* used for both lines and labels */
	
	if (ogr_centroids && ltype == GV_BOUNDARY)
	    /* do not label boundaries */
	    continue;

	process_line(ltype, Points, Cats, lattr, chcat, Clist);
    }

    if (ogr_centroids) {
	/* show label for centroids stored in topo (for OGR layers
	   only) */
	int line, nlines;
	struct bound_box box;
	struct boxlist *list;
	
	list = Vect_new_boxlist(FALSE); /* bboxes not needed */
	Vect_get_constraint_box(Map, &box);
	nlines = Vect_select_lines_by_box(Map, &box, GV_CENTROID, list);
	G_debug(3, "ncentroids (ogr) = %d", nlines);
	
	for (line = 0; line < nlines; line++) {
	    ltype = Vect_read_line(Map, Points, Cats, list->id[line]);
	    process_line(ltype, Points, Cats, lattr, chcat, Clist);
	}
	Vect_destroy_boxlist(list);
    }

    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);

    return 0;
}
Beispiel #29
0
/* merge a given line with all other lines of the same type and 
 * with the same categories */
static int merge_line(struct Map_info *Map, int line,
		      struct line_pnts *MPoints, struct line_cats *MCats)
{
    int nlines, i, first, last, next_line, curr_line;
    int merged = 0, newl = 0;
    int next_node, direction, node_n_lines, type, ltype, lines_type;
    static struct ilist *List = NULL;
    static struct line_pnts *Points = NULL;
    static struct line_cats *Cats = NULL;
    type = GV_LINE;

    nlines = Vect_get_num_lines(Map);

    if (!Points)
	Points = Vect_new_line_struct();
    if (!Cats)
	Cats = Vect_new_cats_struct();
    if (!List)
	List = Vect_new_list();

    Vect_reset_line(Points);
    Vect_reset_cats(Cats);
    Vect_reset_cats(MCats);
    Vect_reset_list(List);

    if (!Vect_line_alive(Map, line))
	return 0;

    ltype = Vect_get_line_type(Map, line);

    if (!(ltype & type))
	return 0;
	
    Vect_read_line(Map, MPoints, MCats, line);

    /* special cases:
     *  - loop back to start boundary via several other boundaries
     *  - one boundary forming closed loop
     *  - node with 3 entries but only 2 boundaries, one of them connecting twice,
     *    the other one must then be topologically incorrect in case of boundary */

    /* go backward as long as there is only one other line/boundary at the current node */
    G_debug(3, "go backward");
    Vect_get_line_nodes(Map, line, &next_node, NULL);

    first = -line;
    while (1) {
	node_n_lines = Vect_get_node_n_lines(Map, next_node);
	/* count lines/boundaries at this node */
	lines_type = 0;
	next_line = first;
	for (i = 0; i < node_n_lines; i++) {
	    curr_line = Vect_get_node_line(Map, next_node, i);
	    if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
		lines_type++;
	    if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
		if (abs(curr_line) != abs(first)) {
		    Vect_read_line(Map, NULL, Cats, abs(curr_line));
		    
		    /* catgories must be identical */
		    if (compare_cats(MCats, Cats) == 0)
			next_line = curr_line;
		}
	    }
	}
	if (lines_type == 2 && abs(next_line) != abs(first) &&
	    abs(next_line) != line) {
	    first = next_line;

	    if (first < 0) {
		Vect_get_line_nodes(Map, -first, &next_node, NULL);
	    }
	    else {
		Vect_get_line_nodes(Map, first, NULL, &next_node);
	    }
	}
	else
	    break;
    }

    /* go forward as long as there is only one other line/boundary at the current node */
    G_debug(3, "go forward");

    /* reverse direction */
    last = -first;

    if (last < 0) {
	Vect_get_line_nodes(Map, -last, &next_node, NULL);
    }
    else {
	Vect_get_line_nodes(Map, last, NULL, &next_node);
    }

    Vect_reset_list(List);
    while (1) {
	G_ilist_add(List, last);
	node_n_lines = Vect_get_node_n_lines(Map, next_node);
	lines_type = 0;
	next_line = last;
	for (i = 0; i < node_n_lines; i++) {
	    curr_line = Vect_get_node_line(Map, next_node, i);
	    if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
		lines_type++;
	    if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
		if (abs(curr_line) != abs(last)) {
		    Vect_read_line(Map, NULL, Cats, abs(curr_line));
		    
		    if (compare_cats(MCats, Cats) == 0)
			next_line = curr_line;
		}
	    }
	}

	if (lines_type == 2 && abs(next_line) != abs(last) &&
	    abs(next_line) != abs(first)) {
	    last = next_line;

	    if (last < 0) {
		Vect_get_line_nodes(Map, -last, &next_node, NULL);
	    }
	    else {
		Vect_get_line_nodes(Map, last, NULL, &next_node);
	    }
	}
	else
	    break;
    }

    /* merge lines */
    G_debug(3, "merge %d lines", List->n_values);
    Vect_reset_line(MPoints);

    for (i = 0; i < List->n_values; i++) {
	Vect_reset_line(Points);
	Vect_read_line(Map, Points, Cats, abs(List->value[i]));
	direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD);
	Vect_append_points(MPoints, Points, direction);
	MPoints->n_points--;
	Vect_delete_line(Map, abs(List->value[i]));
    }
    MPoints->n_points++;
    merged += List->n_values;
    newl++;

    return merged;
}
Beispiel #30
0
void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, int type )
{
  unsigned char *wkb;
  int wkbsize;

  // TODO int may be 64 bits (memcpy)
  if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) || mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) /* points or lines */
  {
    if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
    {
      double x, y, z;
      Vect_get_node_coor( mSource->mMap, id, &x, &y, &z );
      Vect_reset_line( mPoints );
      Vect_append_point( mPoints, x, y, z );
    }
    else
    {
      Vect_read_line( mSource->mMap, mPoints, 0, id );
    }
    int npoints = mPoints->n_points;

    if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
    {
      wkbsize = 1 + 4 + 2 * 8;
    }
    else if ( type & GV_POINTS )
    {
      wkbsize = 1 + 4 + 2 * 8;
    }
    else if ( type & GV_LINES )
    {
      wkbsize = 1 + 4 + 4 + npoints * 2 * 8;
    }
    else // GV_FACE
    {
      wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8;
    }
    wkb = new unsigned char[wkbsize];
    unsigned char *wkbp = wkb;
    wkbp[0] = ( unsigned char ) QgsApplication::endian();
    wkbp += 1;

    /* WKB type */
    memcpy( wkbp, &mSource->mQgisType, 4 );
    wkbp += 4;

    /* Number of rings */
    if ( type & GV_FACE )
    {
      int nrings = 1;
      memcpy( wkbp, &nrings, 4 );
      wkbp += 4;
    }

    /* number of points */
    if ( type & ( GV_LINES | GV_FACE ) )
    {
      QgsDebugMsg( QString( "set npoints = %1" ).arg( npoints ) );
      memcpy( wkbp, &npoints, 4 );
      wkbp += 4;
    }

    for ( int i = 0; i < npoints; i++ )
    {
      memcpy( wkbp, &( mPoints->x[i] ), 8 );
      memcpy( wkbp + 8, &( mPoints->y[i] ), 8 );
      wkbp += 16;
    }
  }
  else   // GV_AREA
  {
    Vect_get_area_points( mSource->mMap, id, mPoints );
    int npoints = mPoints->n_points;

    wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
    wkb = new unsigned char[wkbsize];
    wkb[0] = ( unsigned char ) QgsApplication::endian();
    int offset = 1;

    /* WKB type */
    memcpy( wkb + offset, &mSource->mQgisType, 4 );
    offset += 4;

    /* Number of rings */
    int nisles = Vect_get_area_num_isles( mSource->mMap, id );
    int nrings = 1 + nisles;
    memcpy( wkb + offset, &nrings, 4 );
    offset += 4;

    /* Outer ring */
    memcpy( wkb + offset, &npoints, 4 );
    offset += 4;
    for ( int i = 0; i < npoints; i++ )
    {
      memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
      memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
      offset += 16;
    }

    /* Isles */
    for ( int i = 0; i < nisles; i++ )
    {
      Vect_get_isle_points( mSource->mMap, Vect_get_area_isle( mSource->mMap, id, i ), mPoints );
      npoints = mPoints->n_points;

      // add space
      wkbsize += 4 + npoints * 2 * 8;
      wkb = ( unsigned char * ) realloc( wkb, wkbsize );

      memcpy( wkb + offset, &npoints, 4 );
      offset += 4;
      for ( int i = 0; i < npoints; i++ )
      {
        memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
        memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
        offset += 16;
      }
    }
  }

  feature.setGeometryAndOwnership( wkb, wkbsize );
}