예제 #1
0
파일: cindex.c 프로젝트: caomw/grass
/*!
  \brief Find all line/area id's for given category
  
  \param Map pointer to Map_info structure
  \param layer layer number
  \param type_mask feature type of objects to search for
  \param cat category number
  \param[out] lines array of ids of found lines/points
*/
void Vect_cidx_find_all(const struct Map_info *Map, int layer, int type_mask,
			int cat, struct ilist *lines)
{
    int type, line;
    struct Cat_index *ci;
    int field_index, idx;

    Vect_reset_list(lines);
    field_index = Vect_cidx_get_field_index(Map, layer);

    if (field_index == -1) {
	/* not found */
	return;
    }
    ci = &(Map->plus.cidx[field_index]);

    idx = Vect_cidx_find_next(Map, field_index, cat,
			      type_mask, 0, &type, &line);

    if (idx == -1) {
	return;
    }

    do {
	if (ci->cat[idx][0] != cat) {
	    break;
	}
	if (ci->cat[idx][1] & type_mask) {
	    Vect_list_append(lines, ci->cat[idx][2]);
	}
	idx++;
    } while (idx < ci->n_cats);
    return;
}
예제 #2
0
void copy_boxlist_and_destroy( struct boxlist *blist, struct ilist * list )
{
  Vect_reset_list( list );
  for ( int i = 0; i < blist->n_values; i++ )
  {
    Vect_list_append( list, blist->id[i] );
  }
  Vect_destroy_boxlist( blist );
}
예제 #3
0
파일: cats.c 프로젝트: rashadkm/grass_cmake
/*!
   \brief Get list of categories of given field.

   \param Cats line_cats structure
   \param field layer number
   \param[out] cats pointer to list where cats will be written

   \return number of found categories
   \return -1 on invalid field
 */
int Vect_field_cat_get(const struct line_cats *Cats, int field, struct ilist *cats)
{
    int n;
    
    /* reset list of categories */
    Vect_reset_list(cats);

    /* check input value */
    if (field < 1 || field > GV_FIELD_MAX)
	return -1;
    
    /* go through cats and find if field exist */
    for (n = 0; n < Cats->n_cats; n++) {
	if (Cats->field[n] == field)
	    Vect_list_append(cats, Cats->cat[n]);
    }

    return cats->n_values;
}
예제 #4
0
파일: area.c 프로젝트: caomw/grass
/*!
   \brief Creates list of boundaries for given isle

   Note that ids in <b>List</b> can be negative. The sign indicates in
   which direction the boundary should be read (negative for forward).

   \param Map pointer to Map_info structur
   \param isle island number
   \param[out] List pointer to list where boundaries are stored

   \return number of boundaries
 */
int Vect_get_isle_boundaries(const struct Map_info *Map, int isle, struct ilist *List)
{
    int i, line;
    const struct Plus_head *Plus;
    struct P_isle *Isle;

    G_debug(3, "Vect_get_isle_boundaries(): isle = %d", isle);

    Vect_reset_list(List);

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

    if (Isle == NULL)
	G_fatal_error(_("Attempt to read topo for dead isle (%d)"), isle);

    for (i = 0; i < Isle->n_lines; i++) {
	line = Isle->lines[i];
	Vect_list_append(List, line);
    }

    return (List->n_values);
}
예제 #5
0
파일: area.c 프로젝트: caomw/grass
/*!
   \brief Creates list of boundaries for given area

   Note that ids in <b>List</b> can be negative. The sign indicates in
   which direction the boundary should be read (negative for
   backward).
   
   \param Map pointer to Map_info structure
   \param area area id
   \param[out] List pointer to list of boundaries

   \return number of boundaries
*/
int Vect_get_area_boundaries(const struct Map_info *Map, int area, struct ilist *List)
{
    int i, line;
    const struct Plus_head *Plus;
    struct P_area *Area;

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

    Vect_reset_list(List);

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

    if (Area == NULL)
	G_fatal_error(_("Attempt to read topo for dead area (%d)"), area);

    for (i = 0; i < Area->n_lines; i++) {
	line = Area->lines[i];
	Vect_list_append(List, line);
    }

    return (List->n_values);
}
예제 #6
0
파일: cindex.c 프로젝트: caomw/grass
/*!
  \brief Get list of unique categories for given layer index

  \param Map pointer to Map_info structure
  \param field_index layer index
  \param[out] list output list of cats
  
  \return 1 on success
  \return 0 on error
*/
int Vect_cidx_get_unique_cats_by_index(struct Map_info *Map, int field_index, struct ilist *list)
{
    int c;
    struct Cat_index *ci;

    check_status(Map);
    check_index(Map, field_index);

    ci = &(Map->plus.cidx[field_index]);
    
    /* force sorting index -- really needed? */
    dig_cidx_sort(&(Map->plus));

    Vect_reset_list(list);
    if (ci->n_cats > 0)
        Vect_list_append(list, ci->cat[0][0]);
    for (c = 1; c < ci->n_cats; c++) {
        if (ci->cat[c][0] != ci->cat[c - 1][0])
            Vect_list_append(list, ci->cat[c][0]);
    }
    
    return list->n_values == ci->n_ucats ? 1 : 0;
}
예제 #7
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;
}
예제 #8
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;
}
예제 #9
0
/*!
   \brief Find shortest path.

   Costs for 'from' and 'to' nodes are not considered (SP found even if
   'from' or 'to' are 'closed' (costs = -1) and costs of these
   nodes are not added to SP costs result.

   \param graph pointer to graph structure
   \param from from node
   \param to to node
   \param List list of line ids
   \param cost costs value

   \return number of segments
   \return 0 is correct for from = to, or List == NULL ), ? sum of costs is better return value,
   \return -1 destination unreachable
 */
int
Vect_graph_shortest_path(dglGraph_s * graph, int from, int to, struct ilist *List,
			 double *cost)
{
    int i, line, *pclip, cArc, nRet;
    dglSPReport_s *pSPReport;
    dglInt32_t nDistance;

    G_debug(3, "Vect_graph_shortest_path(): from = %d, to = %d", from, to);

    /* Note : if from == to dgl goes to nearest node and returns back (dgl feature) => 
     *         check here for from == to */

    if (List != NULL)
	Vect_reset_list(List);

    /* Check if from and to are identical, otherwise dglib returns path to neares node and back! */
    if (from == to) {
	if (cost != NULL)
	    *cost = 0;
	return 0;
    }

    From_node = from;

    pclip = NULL;
    if (List != NULL) {
	nRet =
	    dglShortestPath(graph, &pSPReport, (dglInt32_t) from,
			    (dglInt32_t) to, clipper, pclip, NULL);
    }
    else {
	nRet =
	    dglShortestDistance(graph, &nDistance, (dglInt32_t) from,
				(dglInt32_t) to, clipper, pclip, NULL);
    }

    if (nRet == 0) {
	if (cost != NULL)
	    *cost = PORT_DOUBLE_MAX;
	return -1;
    }
    else if (nRet < 0) {
	G_warning(_("dglShortestPath error: %s"), dglStrerror(graph));
	return -1;
    }

    if (List != NULL) {
	for (i = 0; i < pSPReport->cArc; i++) {
	    line = dglEdgeGet_Id(graph, pSPReport->pArc[i].pnEdge);
	    G_debug(2, "From %ld to %ld - cost %ld user %d distance %ld",
		    pSPReport->pArc[i].nFrom, pSPReport->pArc[i].nTo,
		    /* this is the cost from clip() */
		    dglEdgeGet_Cost(graph, pSPReport->pArc[i].pnEdge) / 1000,
		    line, pSPReport->pArc[i].nDistance);
	    Vect_list_append(List, line);
	}
    }

    if (cost != NULL) {
	if (List != NULL)
	    *cost = (double)pSPReport->nDistance / 1000;
	else
	    *cost = (double)nDistance / 1000;
    }

    if (List != NULL) {
	cArc = pSPReport->cArc;
	dglFreeSPReport(graph, pSPReport);
    }
    else
	cArc = 0;

    return (cArc);
}
예제 #10
0
파일: break.c 프로젝트: caomw/grass
/*!
  \brief Connect lines in given threshold
  
  \code
        \	             \
   id1   \           ->	      \
                               \
   id2 ---------           -----+---
   \endcode

   If two lines are selected and <i>thresh</i> is -1, no limit is
   applied.

   \param Map pointer to Map_info
   \param List list of selected lines
   \param thresh threshold value

   \return number of modified lines
   \return -1 on error
 */
int Vedit_connect_lines(struct Map_info *Map, struct ilist *List,
			double thresh)
{
    int nlines_modified, connected;
    int i, j, node[2], n_nodes;
    int line, found;
    double x, y, z;

    struct ilist *List_exclude, *List_found;

    nlines_modified = 0;

    List_exclude = Vect_new_list();
    List_found = Vect_new_list();

    n_nodes = 2;

    /* collect lines to be modified */
    for (i = 0; i < List->n_values; i++) {
	line = List->value[i];

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

	if (Vect_get_line_type(Map, line) & GV_POINTS)
	    continue;

	node[0] = node[1] = -1;
	Vect_get_line_nodes(Map, line, &(node[0]), &(node[1]));
	if (node[0] < 0 || node[1] < 0)
	    continue;

	connected = 0;
	Vect_reset_list(List_exclude);
	Vect_list_append(List_exclude, line);
	for (j = 0; j < n_nodes && !connected; j++) {
	    /* for each line node find lines in threshold */
	    Vect_get_node_coor(Map, node[j], &x, &y, &z);

	    do {
		/* find first nearest line */
		found = Vect_find_line_list(Map, x, y, z,
					    GV_LINES, thresh, WITHOUT_Z,
					    List_exclude, List_found);
		
		if (found > 0 && Vect_line_alive(Map, found)) {
		    /* try to connect lines (given node) */
		    G_debug(3, "Vedit_connect_lines(): lines=%d,%d", line, found);
		    if (connect_lines(Map, !j, line, found, thresh, List)) {
			G_debug(3, "Vedit_connect_lines(): lines=%d,%d -> connected",
				line, found);
			nlines_modified += 2;
			connected = 1;
		    }
		}
		
		Vect_list_append(List_exclude, found);
	    } while(List_found->n_values > 0 && !connected);
	}
    }
    
    Vect_destroy_list(List_exclude);
    Vect_destroy_list(List_found);

    return nlines_modified;
}
예제 #11
0
/* 
   Called by Vect_remove_bridges() and Vect_chtype_bridges():
   chtype = 0 -> works like Vect_remove_bridges()
   chtype = 1 -> works like Vect_chtype_bridges()

   Algorithm: Go thorough all lines, 
   if both sides of the line have left and side 0 (candidate) do this check:
   follow adjacent lines in one direction (nearest to the right at the end node),
   if we reach this line again without dangle in the way, but with this line 
   traversed from other side it is a bridge.

   List of all lines in chain is created during the cycle.
 */
void
remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
{
    int i, type, nlines, line;
    int left, right, node1, node2, current_line, next_line;
    int bridges_removed = 0;	/* number of removed bridges */
    int lines_removed = 0;	/* number of lines removed */
    char *lmsg;
    struct Plus_head *Plus;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct ilist *CycleList;
    struct ilist *BridgeList;

    int dangle, other_side;

    if (chtype)
	lmsg = "changed lines";
    else
	lmsg = "removed lines";

    Plus = &(Map->plus);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    CycleList = Vect_new_list();
    BridgeList = Vect_new_list();

    nlines = Vect_get_num_lines(Map);

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

    for (line = 1; line <= nlines; line++) {
	G_percent(line, nlines, 1);
	if (!Vect_line_alive(Map, line))
	    continue;

	type = Vect_read_line(Map, NULL, NULL, line);
	if (!(type & GV_BOUNDARY))
	    continue;

	Vect_get_line_areas(Map, line, &left, &right);

	if (left != 0 || right != 0)
	    continue;		/* Cannot be bridge */

	G_debug(2, "line %d - bridge candidate", line);

	Vect_get_line_nodes(Map, line, &node1, &node2);

	if (abs(node1) == abs(node2))
	    continue;		/* either zero length or loop -> cannot be a bridge */

	current_line = -line;	/* we start with negative (go forward, node2 ) */

	dangle = 0;
	other_side = 0;
	Vect_reset_list(CycleList);
	Vect_reset_list(BridgeList);
	while (1) {
	    next_line =
		dig_angle_next_line(Plus, current_line, GV_RIGHT,
				    GV_BOUNDARY);

	    /* Add this line to the list */
	    /* TODO: Vect_val_in_list() and Vect_list_append() behave O(n)
	     * change to O(log n) */
	    if (Vect_val_in_list(CycleList, abs(next_line)))	/* other side -> bridge chain */
		Vect_list_append(BridgeList, abs(next_line));
	    else
		dig_list_add(CycleList, abs(next_line)); /* not in list, can add new line fast */

	    if (abs(next_line) == abs(current_line)) {
		G_debug(4, "  dangle -> no bridge");
		dangle = 1;
		break;
	    }
	    if (abs(next_line) == line) {	/* start line reached */
		/* which side */
		if (next_line < 0) {	/* other side (connected by node 2) */
		    G_debug(5, "  other side reached");
		    other_side = 1;
		}
		else {		/* start side */
		    break;
		}
	    }

	    current_line = -next_line;	/* change the sign to look at the next node in following cycle */
	}

	if (!dangle && other_side) {
	    G_debug(3, " line %d is part of bridge chain", line);

	    for (i = 0; i < BridgeList->n_values; i++) {
		Vect_read_line(Map, Points, Cats, BridgeList->value[i]);

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

		if (!chtype)
		    Vect_delete_line(Map, BridgeList->value[i]);
		else
		    Vect_rewrite_line(Map, BridgeList->value[i], GV_LINE,
				      Points, Cats);

		lines_removed++;
	    }
	    bridges_removed++;
	}
    }
    G_verbose_message("Removed lines: %d", lines_removed);
    G_verbose_message("Removed bridges: %d", bridges_removed);
}
예제 #12
0
파일: main.c 프로젝트: rkrug/grass-ci
/* Calculate costs for MST on given set of terminals.
 *  If AList / NList is not NULL, list of arcs / nodes in MST is created
 *  Note: qsort() from more (say >30) terminals, takes long time (most of mst()).
 *        To improve the speed, there are used two sorted queues of costs:
 *          1. for all combinations of in trms
 *          2. from 'sp' to all other terminals
 *        Because 1. is sorted only if new sp as added to list of terminals,
 *        and 2. is much shorter than 1., a lot of time is saved.
 */
int mst(struct Map_info *Map, int *trms, int ntrms,	/* array of terminal, number of terminals */
	double *cst, double max_cst,	/* cost, maximum cost */
	struct ilist *AList, struct ilist *NList,	/* list of arcs/nodes in ST */
	int sp,			/* Steiner point (node) to be tested with terminals, (0 = ignore) */
	int rebuild)
{				/* rebuild the sorted list of costs for terminals */
    int i, j, node1, node2, com1, com2, t1, t2, line;
    static int k;
    int tcpos, scpos;		/* current position in the term_costs / sp_costs */
    double tcst;
    struct ilist *List;
    int nsteps, quse;
    int nall;			/* number of terminals + sp ( if used ) */

    if (AList != NULL) {
	Vect_reset_list(AList);
    }
    List = Vect_new_list();

    /* Create sorted array for all combinations of terms */
    if (rebuild) {
	k = 0;
	for (i = 0; i < ntrms; i++) {
	    for (j = i + 1; j < ntrms; j++) {
		term_costs[k].term1 = i;
		term_costs[k].term2 = j;
		get_node_costs(trms[i], trms[j], &tcst);
		term_costs[k].cost = tcst;
		k++;
	    }
	}

	qsort((void *)term_costs, k, sizeof(COST), cmp);	/* this takes most of a time in mst() */
	for (i = 0; i < k; i++) {
	    G_debug(3, "  %d - %d cost = %f\n", term_costs[i].term1,
		    term_costs[i].term2, term_costs[i].cost);
	}
    }

    /* Create sorted array for all combinations of sp -> terms */
    if (sp > 0) {
	for (i = 0; i < ntrms; i++) {
	    sp_costs[i].term1 = -1;	/* not needed */
	    sp_costs[i].term2 = i;
	    get_node_costs(sp, trms[i], &tcst);
	    sp_costs[i].cost = tcst;
	}
	qsort((void *)sp_costs, ntrms, sizeof(COST), cmp);
	for (i = 0; i < ntrms; i++) {
	    G_debug(3, "  %d - %d cost = %f\n", sp_costs[i].term1,
		    sp_costs[i].term2, sp_costs[i].cost);
	}
    }

    tcst = 0;

    /* MST has number_of_terminals-1 arcs */
    if (sp > 0) {
	nall = ntrms + 1;
	nsteps = ntrms;		/* i.e. + one StP */
    }
    else {
	nall = ntrms;
	nsteps = ntrms - 1;
    }
    G_debug(1, "nall = %d\n", nall);
    for (i = 0; i < nall; i++)
	comps[i] = 0;

    tcpos = 0;
    scpos = 0;
    G_debug(2, "nsteps = %d\n", nsteps);
    for (i = 0; i < nsteps; i++) {
	G_debug(2, "step = %d\n", i);
	/* Take the best (lowest costs, no cycle) from both queues */
	/* For both queues go to next lowest costs without cycle */
	/* treminal costs */
	for (j = tcpos; j < k; j++) {
	    t1 = term_costs[j].term1;
	    t2 = term_costs[j].term2;
	    com1 = comps[t1];
	    com2 = comps[t2];
	    if (com1 != com2 || com1 == 0) {	/* will not create cycle -> candidate */
		tcpos = j;
		break;
	    }
	}
	if (j == k) {		/* arc without cycle not found */
	    tcpos = -1;
	}

	/* StP costs */
	if (sp > 0) {
	    for (j = scpos; j < ntrms; j++) {
		t1 = ntrms;	/* StP is on first fre position */
		t2 = sp_costs[j].term2;
		com1 = comps[t1];
		com2 = comps[t2];
		G_debug(3, "scpos: j = %d comps(%d) = %d coms(%d) = %d\n", j,
			t1, com1, t2, com2);
		if (com1 != com2 || com1 == 0) {	/* will not create cycle -> candidate */
		    scpos = j;
		    G_debug(3, " ok -> scpos = %d\n", scpos);
		    break;
		}
	    }
	    if (j == ntrms) {	/* arc without cycle not found */
		scpos = -1;
	    }
	}
	else {
	    scpos = -1;
	}
	/* Do not access invalid items even for debugging */
    if (tcpos != -1 && scpos != -1)
        G_debug(3, "tcost = %f, scost = %f\n", term_costs[tcpos].cost,
            sp_costs[scpos].cost);

	/* Now we have positions set on lowest costs in each queue or -1 if no more/not used */
	if (tcpos >= 0 && scpos >= 0) {
	    if (term_costs[tcpos].cost < sp_costs[scpos].cost)
		quse = 1;	/* use terms queue */
	    else
		quse = 2;	/* use sp queue */
	}
	else if (tcpos >= 0) {
	    quse = 1;		/* use terms queue */
	}
	else {
	    quse = 2;		/* use sp queue */
	}


	/* Now we know from which queue take next arc -> add arc to components */
	if (quse == 1) {
	    t1 = term_costs[tcpos].term1;
	    t2 = term_costs[tcpos].term2;
	    tcst += term_costs[tcpos].cost;
	    tcpos++;
	}
	else {
	    t1 = ntrms;
	    t2 = sp_costs[scpos].term2;
	    tcst += sp_costs[scpos].cost;
	    scpos++;
	}
	G_debug(3, "quse = %d t1 = %d t2 = %d\n", quse, t1, t2);
	G_debug(3, "tcst = %f (max = %f)\n", tcst, max_cst);

	com1 = comps[t1];
	com2 = comps[t2];
	comps[t1] = i + 1;
	comps[t2] = i + 1;
	G_debug(3, "comps(%d) = %d coms(%d) = %d\n", t1, i + 1, t2, i + 1);

	/* reset connected branches */
	for (j = 0; j < nall; j++) {
	    if (comps[j] == com1 && com1 != 0)
		comps[j] = i + 1;

	    if (comps[j] == com2 && com2 != 0)
		comps[j] = i + 1;
	}
	if (tcst > max_cst) {
	    G_debug(3, "cost > max -> return\n");
	    *cst = PORT_DOUBLE_MAX;
	    return 1;
	}

	/* add to list of arcs */
	if (AList != NULL) {
	    node1 = trms[t1];
	    node2 = trms[t2];
	    Vect_net_shortest_path(Map, node1, node2, List, NULL);
	    for (j = 0; j < List->n_values; j++) {
		Vect_list_append(AList, abs(List->value[j]));
	    }
	}
    }

    /* create list of nodes */
    if (NList != NULL) {
	Vect_reset_list(NList);
	for (i = 0; i < AList->n_values; i++) {
	    line = AList->value[i];
	    Vect_get_line_nodes(Map, line, &node1, &node2);
	    Vect_list_append(NList, node1);
	    Vect_list_append(NList, node2);
	}
    }

    *cst = tcst;

    Vect_destroy_list(List);

    return 1;
}
예제 #13
0
파일: main.c 프로젝트: imincik/pkg-grass
int main(int argc, char *argv[])
{
    int i, iopt;
    int operator;
    int aline, nalines, nskipped;
    int ltype, itype[2], ifield[2];
    int **cats, *ncats, nfields, *fields;
    char *mapset[2], *pre[2];
    struct GModule *module;
    struct GParm parm;
    struct GFlag flag;
    struct Map_info In[2], Out;
    struct field_info *IFi, *OFi;
    struct line_pnts *APoints, *BPoints;
    struct line_cats *ACats, *BCats;
    int *ALines;		/* List of lines: 0 do not output, 1 - write to output */
    struct ilist *List, *TmpList, *BoundList;

    G_gisinit(argv[0]);

    pre[0] = "a";
    pre[1] = "b";

    module = G_define_module();
    module->keywords = _("vector, spatial query");
    module->description =
	_("Selects features from vector map (A) by features from other vector map (B).");

    parse_options(&parm, &flag);
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    if (parm.operator->answer[0] == 'e')
	operator = OP_EQUALS;
    else if (parm.operator->answer[0] == 'd') {
	/* operator = OP_DISJOINT; */
	operator = OP_INTERSECTS;
	flag.reverse->answer = YES;
    }
    else if (parm.operator->answer[0] == 'i')
	operator = OP_INTERSECTS;
    else if (parm.operator->answer[0] == 't')
	operator = OP_TOUCHES;
    else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r')
	operator = OP_CROSSES;
    else if (parm.operator->answer[0] == 'w')
	operator = OP_WITHIN;
    else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o')
	operator = OP_CONTAINS;
    else if (parm.operator->answer[0] == 'o') {
	if (strcmp(parm.operator->answer, "overlaps") == 0)
	    operator = OP_OVERLAPS;
	else
	    operator = OP_OVERLAP;
    }
    else if (parm.operator->answer[0] == 'r')
	operator = OP_RELATE;
    else
	G_fatal_error(_("Unknown operator"));
    
    if (operator == OP_RELATE && !parm.relate->answer) {
	G_fatal_error(_("Required parameter <%s> not set"),
		      parm.relate->key);
    }
    
    for (iopt = 0; iopt < 2; iopt++) {
	itype[iopt] = Vect_option_to_types(parm.type[iopt]);
	ifield[iopt] = atoi(parm.field[iopt]->answer);

	Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer,
				     GV_FATAL_EXIT);

	if ((mapset[iopt] =
	     G_find_vector2(parm.input[iopt]->answer, NULL)) == NULL) {
	    G_fatal_error(_("Vector map <%s> not found"),
			  parm.input[iopt]->answer);
	}
	
	Vect_set_open_level(2);
	Vect_open_old(&(In[iopt]), parm.input[iopt]->answer, mapset[iopt]);
    }
    
    /* Read field info */
    IFi = Vect_get_field(&(In[0]), ifield[0]);

    APoints = Vect_new_line_struct();
    BPoints = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    BCats = Vect_new_cats_struct();
    List = Vect_new_list();
    TmpList = Vect_new_list();
    BoundList = Vect_new_list();

    /* Open output */
    Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0])));
    Vect_set_map_name(&Out, _("Output from v.select"));
    Vect_set_person(&Out, G_whoami());
    Vect_copy_head_data(&(In[0]), &Out);
    Vect_hist_copy(&(In[0]), &Out);
    Vect_hist_command(&Out);

    nskipped = 0;
    nalines = Vect_get_num_lines(&(In[0]));

#ifdef HAVE_GEOS
    initGEOS(G_message, G_fatal_error);
    GEOSGeometry *AGeom = NULL;
#else
    void *AGeom = NULL;
#endif

    /* Alloc space for input lines array */
    ALines = (int *)G_calloc(nalines + 1, sizeof(int));

    G_message(_("Building spatial index..."));
    Vect_build_spatial_index(&In[0]);
    Vect_build_spatial_index(&In[1]);
    
    /* Lines in A. Go through all lines and mark those that meets condition */
    if (itype[0] & (GV_POINTS | GV_LINES)) {
	G_message(_("Processing features..."));
	
	for (aline = 1; aline <= nalines; aline++) {
	    BOUND_BOX abox;

	    G_debug(3, "aline = %d", aline);
	    G_percent(aline, nalines, 2);	/* must be before any continue */

	    /* Check category */
	    if (!flag.cat->answer && Vect_get_line_cat(&(In[0]), aline, ifield[0]) < 0) {
		nskipped++;
		continue;
	    }

	    /* Read line and check type */
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		AGeom = Vect_read_line_geos(&(In[0]), aline, &ltype);
#endif
		if (!(ltype & (GV_POINT | GV_LINE)))
		    continue;

		if (!AGeom)
		    G_fatal_error(_("Unable to read line id %d from vector map <%s>"),
				  aline, Vect_get_full_name(&(In[0])));
	    }
	    else {
		ltype = Vect_read_line(&(In[0]), APoints, NULL, aline);
	    }
	    
	    if (!(ltype & itype[0]))
		continue;
	    
	    Vect_get_line_box(&(In[0]), aline, &abox);
	    abox.T = PORT_DOUBLE_MAX;
	    abox.B = -PORT_DOUBLE_MAX;

	    /* Check if this line overlaps any feature in B */
	    /* x Lines in B */
	    if (itype[1] & (GV_POINTS | GV_LINES)) {
		int i;
		int found = 0;
		
		/* Lines */
		Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List);
		for (i = 0; i < List->n_values; i++) {
		    int bline;
		    
		    bline = List->value[i];
		    G_debug(3, "  bline = %d", bline);
		    
		    /* Check category */
		    if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }
		    
		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(line_relate_geos(&(In[1]), AGeom,
					    bline, operator, parm.relate->answer)) {

			    found = 1;
			    break;
			}
#endif
		    }
		    else {
			Vect_read_line(&(In[1]), BPoints, NULL, bline);

			if (Vect_line_check_intersection(APoints, BPoints, 0)) {
			    found = 1;
			    break;
			}
		    }
		}
		
		if (found) {
		    ALines[aline] = 1;
		    continue;	/* Go to next A line */
		}
	    }
	    
	    /* x Areas in B. */
	    if (itype[1] & GV_AREA) {
		int i;
		
		Vect_select_areas_by_box(&(In[1]), &abox, List);
		for (i = 0; i < List->n_values; i++) {
		    int barea;
		    
		    barea = List->value[i];
		    G_debug(3, "  barea = %d", barea);
		    
		    if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }

		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(area_relate_geos(&(In[1]), AGeom,
					    barea, operator, parm.relate->answer)) {
			    ALines[aline] = 1;
			    break;
			}
#endif
		    }
		    else {
			if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) {
			    ALines[aline] = 1;
			    break;
			}
		    }
		}
	    }
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		GEOSGeom_destroy(AGeom);
#endif
		AGeom = NULL;
	    }
	}
    }
    
    /* Areas in A. */
    if (itype[0] & GV_AREA) {
	int aarea, naareas;

	G_message(_("Processing areas..."));
	
	naareas = Vect_get_num_areas(&(In[0]));

	for (aarea = 1; aarea <= naareas; aarea++) {
	    BOUND_BOX abox;

	    G_percent(aarea, naareas, 2);	/* must be before any continue */

	    if (Vect_get_area_cat(&(In[0]), aarea, ifield[0]) < 0) {
		nskipped++;
		continue;
	    }
	
	    Vect_get_area_box(&(In[0]), aarea, &abox);
	    abox.T = PORT_DOUBLE_MAX;
	    abox.B = -PORT_DOUBLE_MAX;

	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		AGeom = Vect_read_area_geos(&(In[0]), aarea);
#endif
		if (!AGeom)
		    G_fatal_error(_("Unable to read area id %d from vector map <%s>"),
				  aline, Vect_get_full_name(&(In[0])));
	    }

	    /* x Lines in B */
	    if (itype[1] & (GV_POINTS | GV_LINES)) {
		Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List);

		for (i = 0; i < List->n_values; i++) {
		    int bline;

		    bline = List->value[i];

		    if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }
		    
		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(line_relate_geos(&(In[1]), AGeom,
					    bline, operator, parm.relate->answer)) {
			    add_aarea(&(In[0]), aarea, ALines);
			    break;
			}
#endif
		    }
		    else {
			if (line_overlap_area(&(In[1]), bline, &(In[0]), aarea)) {
			    add_aarea(&(In[0]), aarea, ALines);
			    continue;
			}
		    }
		}
	    }

	    /* x Areas in B */
	    if (itype[1] & GV_AREA) {
		int naisles;
		int found = 0;

		/* List of areas B */

		/* Make a list of features forming area A */
		Vect_reset_list(List);

		Vect_get_area_boundaries(&(In[0]), aarea, BoundList);
		for (i = 0; i < BoundList->n_values; i++) {
		    Vect_list_append(List, abs(BoundList->value[i]));
		}

		naisles = Vect_get_area_num_isles(&(In[0]), aarea);

		for (i = 0; i < naisles; i++) {
		    int j, aisle;

		    aisle = Vect_get_area_isle(&(In[0]), aarea, i);

		    Vect_get_isle_boundaries(&(In[0]), aisle, BoundList);
		    for (j = 0; j < BoundList->n_values; j++) {
			Vect_list_append(List, BoundList->value[j]);
		    }
		}

		Vect_select_areas_by_box(&(In[1]), &abox, TmpList);

		for (i = 0; i < List->n_values; i++) {
		    int j, aline;

		    aline = abs(List->value[i]);

		    for (j = 0; j < TmpList->n_values; j++) {
			int barea, bcentroid;

			barea = TmpList->value[j];
			G_debug(3, "  barea = %d", barea);

			if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) {
			    nskipped++;
			    continue;
			}

			/* Check if any centroid of area B is in area A.
			 * This test is important in if area B is completely within area A */
			bcentroid = Vect_get_area_centroid(&(In[1]), barea);
			Vect_read_line(&(In[1]), BPoints, NULL, bcentroid);

			if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			    if(area_relate_geos(&(In[1]), AGeom,
						barea, operator, parm.relate->answer)) {
				found = 1;
				break;
			    }
#endif
			}
			else {
			    if (Vect_point_in_area(&(In[0]), aarea,
						   BPoints->x[0], BPoints->y[0])) {
				found = 1;
				break;
			    }
			    
			    /* Check intersectin of lines from List with area B */
			    if (line_overlap_area(&(In[0]), aline,
						  &(In[1]), barea)) {
				found = 1;
				break;
			    }
			}
		    }
		    if (found) {
			add_aarea(&(In[0]), aarea, ALines);
			break;
		    }
		}
	    }
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		GEOSGeom_destroy(AGeom);
#endif
		AGeom = NULL;
	    }
	}
    }
    
    Vect_close(&(In[1]));

#ifdef HAVE_GEOS
    finishGEOS();
#endif

    /* Write lines */
    nfields = Vect_cidx_get_num_fields(&(In[0]));
    cats = (int **)G_malloc(nfields * sizeof(int *));
    ncats = (int *)G_malloc(nfields * sizeof(int));
    fields = (int *)G_malloc(nfields * sizeof(int));
    for (i = 0; i < nfields; i++) {
	ncats[i] = 0;
	cats[i] =
	    (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&(In[0]), i) *
			    sizeof(int));
	fields[i] = Vect_cidx_get_field_number(&(In[0]), i);
    }

    G_message(_("Writing selected features..."));
    for (aline = 1; aline <= nalines; aline++) {
	int atype;

	G_debug(4, "aline = %d ALines[aline] = %d", aline, ALines[aline]);
	G_percent(aline, nalines, 2);
	
	if ((!flag.reverse->answer && !(ALines[aline])) ||
	    (flag.reverse->answer && ALines[aline]))
	    continue;

	atype = Vect_read_line(&(In[0]), APoints, ACats, aline);
	Vect_write_line(&Out, atype, APoints, ACats);

	if (!(flag.table->answer) && (IFi != NULL)) {
	    for (i = 0; i < ACats->n_cats; i++) {
		int f, j;

		for (j = 0; j < nfields; j++) {	/* find field */
		    if (fields[j] == ACats->field[i]) {
			f = j;
			break;
		    }
		}
		cats[f][ncats[f]] = ACats->cat[i];
		ncats[f]++;
	    }
	}
    }

    /* Copy tables */
    if (!(flag.table->answer)) {
	int ttype, ntabs = 0;

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

	/* Number of output tabs */
	for (i = 0; i < Vect_get_num_dblinks(&(In[0])); i++) {
	    int f, j;

	    IFi = Vect_get_dblink(&(In[0]), i);

	    for (j = 0; j < nfields; j++) {	/* find field */
		if (fields[j] == IFi->number) {
		    f = j;
		    break;
		}
	    }
	    if (ncats[f] > 0)
		ntabs++;
	}

	if (ntabs > 1)
	    ttype = GV_MTABLE;
	else
	    ttype = GV_1TABLE;

	for (i = 0; i < nfields; i++) {
	    int ret;

	    if (fields[i] == 0)
		continue;

	    /* Make a list of categories */
	    IFi = Vect_get_field(&(In[0]), fields[i]);
	    if (!IFi) {		/* no table */
		G_warning(_("Layer %d - no table"), fields[i]);
		continue;
	    }

	    OFi =
		Vect_default_field_info(&Out, IFi->number, IFi->name, ttype);

	    ret =
		db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table,
				      OFi->driver,
				      Vect_subst_var(OFi->database, &Out),
				      OFi->table, IFi->key, cats[i],
				      ncats[i]);

	    if (ret == DB_FAILED) {
		G_warning(_("Layer %d - unable to copy table"), fields[i]);
	    }
	    else {
		Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table,
				    IFi->key, OFi->database, OFi->driver);
	    }
	}
    }

    Vect_close(&(In[0]));

    Vect_build(&Out);
    Vect_close(&Out);

    if (nskipped > 0) {
      G_warning(_("%d features without category skipped"), nskipped);
    }

    G_done_msg(_("%d features written to output."), Vect_get_num_lines(&Out));

    exit(EXIT_SUCCESS);
}
예제 #14
0
파일: path.c 프로젝트: caomw/grass
/*!
   \brief Find a path (minimum number of edges) from 'from' to 'to' using only edges in 'edges'.

   Precisely, edge with id I is used if edges[abs(i)] == 1. List
   stores the indices of lines on the path. Method return number of
   edges or -1 if no path exist.

   \param graph input graph
   \param from 'from' position
   \param to 'to' position
   \param edges list of available edges
   \param[out] list list of edges

   \return number of edges
   \return -1 on failure
 */
int NetA_find_path(dglGraph_s * graph, int from, int to, int *edges,
		   struct ilist *list)
{
    dglInt32_t **prev, *queue;
    dglEdgesetTraverser_s et;
    char *vis;
    int begin, end, cur, nnodes;

    nnodes = dglGet_NodeCount(graph);
    prev = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
    queue = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
    vis = (char *)G_calloc(nnodes + 1, sizeof(char));
    if (!prev || !queue || !vis) {
	G_fatal_error(_("Out of memory"));
	return -1;
    }
    Vect_reset_list(list);

    begin = 0;
    end = 1;
    vis[from] = 'y';
    queue[0] = from;
    prev[from] = NULL;
    while (begin != end) {
	dglInt32_t vertex = queue[begin++];

	if (vertex == to)
	    break;
	dglInt32_t *edge, *node = dglGetNode(graph, vertex);

	dglEdgeset_T_Initialize(&et, graph,
				dglNodeGet_OutEdgeset(graph, node));
	for (edge = dglEdgeset_T_First(&et); edge;
	     edge = dglEdgeset_T_Next(&et)) {
	    dglInt32_t id = abs(dglEdgeGet_Id(graph, edge));
	    dglInt32_t to =
		dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
	    if (edges[id] && !vis[to]) {
		vis[to] = 'y';
		prev[to] = edge;
		queue[end++] = to;
	    }
	}
	dglEdgeset_T_Release(&et);
    }
    G_free(queue);
    if (!vis[to]) {
	G_free(prev);
	G_free(vis);
	return -1;
    }

    cur = to;
    while (prev[cur] != NULL) {
	Vect_list_append(list, abs(dglEdgeGet_Id(graph, prev[cur])));
	cur = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[cur]));
    }

    G_free(prev);
    G_free(vis);
    return list->n_values;
}
예제 #15
0
/*!
  \brief Merge lines/boundaries
  
  At least two lines need to be given.
  
  \param Map pointer to Map_info
  \param List list of selected lines
  
   \return number of merged lines
   \return -1 on error
*/
int Vedit_merge_lines(struct Map_info *Map, struct ilist *List)
{
    struct ilist *List_in_box;

    struct line_pnts *Points1, *Points2, *Points;
    struct line_cats *Cats1, *Cats2;

    int line_i, i, j;
    int line, line1, type1, line2;
    int do_merge;

    /* number of lines (original, selected, merged) */
    int nlines, nlines_merged;

    nlines_merged = 0;

    if (List->n_values < 2) {
	return 0;
    }

    Points1 = Vect_new_line_struct();
    Cats1 = Vect_new_cats_struct();
    Points2 = Vect_new_line_struct();
    Cats2 = Vect_new_cats_struct();
    Points = Vect_new_line_struct();

    List_in_box = Vect_new_list();

    nlines = Vect_get_num_lines(Map);
    
    /* merge lines */
    for (line_i = 0; line_i < List->n_values; line_i++) {
	line1 = List->value[line_i];

	if (!Vect_line_alive(Map, line1))
	    continue;

	type1 = Vect_read_line(Map, Points1, Cats1, line1);

	if (!(type1 & GV_LINES))
	    continue;

	Vect_reset_line(Points);

	for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) {
	    Vect_reset_list(List_in_box);

	    /* define searching region */
	    Vect_reset_line(Points2);
	    /*
	       Vect_append_point (Points2, Points1 -> x[i] - thresh,
	       Points1 -> y[i] + thresh, Points1 -> z[i]);
	       Vect_append_point (Points2, Points1 -> x[i] + thresh,
	       Points1 -> y[i] + thresh, Points1 -> z[i]);
	       Vect_append_point (Points2, Points1 -> x[i] + thresh,
	       Points1 -> y[i] - thresh, Points1 -> z[i]);
	       Vect_append_point (Points2, Points1 -> x[i] - thresh,
	       Points1 -> y[i] - thresh, Points1 -> z[i]);
	     */
	    Vect_append_point(Points2, Points1->x[i],
			      Points1->y[i], Points1->z[i]);

	    /* 
	     * merge lines only if two lines found in the region
	     * i.e. the current line and an adjacent line
	     */
	    if (1 < Vect_select_lines_by_polygon(Map, Points2, 0, NULL,
						 GV_LINES, List_in_box)) {
		do_merge = 1;
		line2 = -1;
		for (j = 0; do_merge && j < List->n_values; j++) {
		    if (List->value[j] == line1 ||
			!Vect_line_alive(Map, List->value[j]))
			continue;

		    if (Vect_val_in_list(List_in_box, List->value[j])) {
			if (line2 > 0) {
			    /* three lines found
			     * selected lines will be not merged
			     */
			    do_merge = 0;
			}
			else {
			    line2 = List->value[j];
			}
		    }
		}

		if (!do_merge || line2 < 0)
		    continue;

		Vect_read_line(Map, Points2, Cats2, line2);

		merge_lines(Points1, Cats1, Points2, Cats2, -1.0, &Points);	/* do not use threshold value */

		G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2);

		if (Points->n_points > 0) {
		    if (Vect_delete_line(Map, line2) == -1) {
			return -1;
		    }

		    if (line2 <= nlines)
			nlines_merged++;
		}
	    }
	}			/* for each node */

	if (Points->n_points > 0) {
	    line = Vect_rewrite_line(Map, line1, type1, Points, Cats1);
	    if (line < 0) {
		return -1;
	    }

	    if (line1 <= nlines)
		nlines_merged++;

	    /* update number of lines */
	    Vect_list_append(List, line);
	}
    }				/* for each line */

    /* destroy stuctures */
    Vect_destroy_line_struct(Points1);
    Vect_destroy_line_struct(Points2);
    Vect_destroy_line_struct(Points);

    Vect_destroy_cats_struct(Cats1);
    Vect_destroy_cats_struct(Cats2);

    return nlines_merged;
}