Пример #1
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;
}
Пример #2
0
/**
   \brief merge two list, i.e. store only duplicate items

   \param[in] alist,blist list to be merged

   \return result number of items
*/
static int merge_lists(struct ilist *alist, struct ilist *blist)
{
    int i;

    struct ilist *list_del;

    list_del = Vect_new_list();

    for (i = 0; i < alist->n_values; i++) {
	if (!Vect_val_in_list(blist, alist->value[i]))
	    Vect_list_append(list_del, alist->value[i]);
    }

    Vect_list_delete_list(alist, list_del);

    Vect_destroy_list(list_del);

    return alist->n_values;
}
Пример #3
0
int export_areas_multi(struct Map_info *In, int field, int donocat,
                       OGRFeatureDefnH Ogr_featuredefn,OGRLayerH Ogr_layer,
                       struct field_info *Fi, dbDriver *driver, int ncol, int *colctype,
                       const char **colname, int doatt, int nocat,
                       int *n_noatt, int *n_nocat)
{
    int i, n_exported, area;
    int cat, ncats_field, line, type, findex, ipart;

    struct line_pnts *Points;
    struct line_cats *Cats;
    struct ilist *cat_list, *line_list, *lcats;

    OGRGeometryH Ogr_geometry, Ogr_geometry_part;
    OGRFeatureH Ogr_feature;
    OGRwkbGeometryType wkbtype, wkbtype_part;
    
    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    cat_list = Vect_new_list();
    line_list = Vect_new_list();
    lcats = Vect_new_list();

    n_exported = 0;

    /* check if category index is available for given field */
    findex = Vect_cidx_get_field_index(In, field);
    if (findex == -1)
        G_fatal_error(_("Unable to export multi-features. No category index for layer %d."),
                      field);
    
    /* determine type */
    wkbtype_part = wkbPolygon;
    wkbtype = get_multi_wkbtype(wkbtype_part);
    
    ncats_field = Vect_cidx_get_unique_cats_by_index(In, findex, cat_list);
    G_debug(1, "n_cats = %d for layer %d", ncats_field, field);

    if (donocat)
	G_message(_("Exporting features with category..."));

    for (i = 0; i < cat_list->n_values; i++) {
        G_percent(i, cat_list->n_values - 1, 5);

        cat = cat_list->value[i];
        /* find all centroids with given category */
        Vect_cidx_find_all(In, field, GV_CENTROID, cat, line_list);

        /* create multi-feature */
        Ogr_geometry = OGR_G_CreateGeometry(wkbtype);

        /* build simple features geometry, go through all parts */
        for (ipart = 0; ipart < line_list->n_values; ipart++) {
            line = line_list->value[ipart];
            G_debug(3, "cat=%d, line=%d -> part=%d", cat, line, ipart);

            /* get centroid's category */
            Vect_read_line(In, NULL, Cats, line);
            /* check for category consistency */
            Vect_field_cat_get(Cats, field, lcats);
	    if (!Vect_val_in_list(lcats, cat))
                G_fatal_error(_("Unable to create multi-feature. "
                                "Category %d not found in line %d, field %d"),
                              cat, line, field);
            
            /* find correspoding area */
            area = Vect_get_centroid_area(In, line);
            if (area == 0)
                continue;
                
            /* create polygon from area */
            Ogr_geometry_part = create_polygon(In, area, Points);

            /* add part */
            OGR_G_AddGeometryDirectly(Ogr_geometry, Ogr_geometry_part);
        }

        if (!OGR_G_IsEmpty(Ogr_geometry)) {
            /* write multi-feature */
            Ogr_feature = OGR_F_Create(Ogr_featuredefn);
            OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
            
            mk_att(cat, Fi, driver, ncol, colctype, colname, doatt, nocat,
                   Ogr_feature, n_noatt);
            OGR_L_CreateFeature(Ogr_layer, Ogr_feature);

            OGR_F_Destroy(Ogr_feature);

            n_exported++;
        }
        else {
            /* skip empty features */
            G_debug(3, "multi-feature is empty -> skipped");
        }
        
        OGR_G_DestroyGeometry(Ogr_geometry);
    }

    if (donocat)
	G_message(_("Exporting features without category..."));

    /* check lines without category, if -c flag is given write them as
     * one multi-feature */
    Ogr_geometry = OGR_G_CreateGeometry(wkbtype);
    
    Vect_rewind(In);
    Vect_set_constraint_type(In, GV_CENTROID);
    while(TRUE) {
        type = Vect_read_next_line(In, NULL, Cats);
        if (type < 0)
            break;

        /* get centroid's category */
        Vect_cat_get(Cats, field, &cat);
        if (cat > 0)
            continue; /* skip features with category */
        if (cat < 0 && !donocat) {
            (*n_nocat)++;
            continue; /* skip lines without category, do not export
                       * not labeled */
        }

        /* find correspoding area */
	line = Vect_get_next_line_id(In);
        area = Vect_get_centroid_area(In, line);
        if (area == 0)
            continue;
                
        /* create polygon from area */
        Ogr_geometry_part = create_polygon(In, area, Points);
        
        /* add part */
        OGR_G_AddGeometryDirectly(Ogr_geometry, Ogr_geometry_part);

        (*n_nocat)++;
    }

    if (!OGR_G_IsEmpty(Ogr_geometry)) {
        /* write multi-feature */
        Ogr_feature = OGR_F_Create(Ogr_featuredefn);
        OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
        
        mk_att(cat, Fi, driver, ncol, colctype, colname, doatt, nocat,
               Ogr_feature, n_noatt);
        OGR_L_CreateFeature(Ogr_layer, Ogr_feature);

        OGR_F_Destroy(Ogr_feature);
        
        n_exported++;
    }
    else {
        /* skip empty features */
        G_debug(3, "multi-feature is empty -> skipped");
    }
    
    OGR_G_DestroyGeometry(Ogr_geometry);
    
    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);
    Vect_destroy_list(cat_list);
    Vect_destroy_list(line_list);
    Vect_destroy_list(lcats);
    
    return n_exported;
}
Пример #4
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);
}
Пример #5
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;
}
Пример #6
0
int
Vect_break_lines_list(struct Map_info *Map, struct ilist *List_break,
		      struct ilist *List_ref, int type, struct Map_info *Err)
{
    struct line_pnts *APoints, *BPoints, *Points;
    struct line_pnts **AXLines, **BXLines;
    struct line_cats *ACats, *BCats, *Cats;
    int j, k, l, ret, atype, btype, aline, bline, found, iline, nlines;
    int naxlines, nbxlines, nx;
    double *xx = NULL, *yx = NULL, *zx = NULL;
    struct bound_box ABox, BBox;
    struct boxlist *List;
    int nbreaks;
    int touch1_n = 0, touch1_s = 0, touch1_e = 0, touch1_w = 0;	/* other vertices except node1 touching box */
    int touch2_n = 0, touch2_s = 0, touch2_e = 0, touch2_w = 0;	/* other vertices except node2 touching box */
    int is3d;
    int node, anode1, anode2, bnode1, bnode2;
    double nodex, nodey;

    APoints = Vect_new_line_struct();
    BPoints = Vect_new_line_struct();
    Points = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    BCats = Vect_new_cats_struct();
    Cats = Vect_new_cats_struct();
    List = Vect_new_boxlist(1);

    is3d = Vect_is_3d(Map);

    if (List_break) {
	nlines = List_break->n_values;
    }
    else {
	nlines = Vect_get_num_lines(Map);
    }
    G_debug(3, "nlines =  %d", nlines);

    /* TODO: It seems that lines/boundaries are not broken at intersections
     * with points/centroids. Check if true, if yes, skip GV_POINTS
     */

    /* To find intersection of two lines (Vect_line_intersection) is quite slow.
     * Fortunately usual lines/boundaries in GIS often forms a network where lines
     * are connected by end points, and touch by MBR. This function checks and occasionaly
     * skips such cases. This is currently done for 2D only
     */

    /* Go through all lines in vector, for each select lines which overlap MBR of
     * this line exclude those connected by one endpoint (see above)
     * and try to intersect, if lines intersect write new lines at the end of 
     * the file, and process next line (remaining lines overlapping box are skipped)
     */
    nbreaks = 0;

    for (iline = 0; iline < nlines; iline++) {
	G_percent(iline, nlines, 1);
	if (List_break) {
	    aline = List_break->value[iline];
	}
	else {
	    aline = iline + 1;
	}

	if (List_ref && !Vect_val_in_list(List_ref, aline))
	    continue;

	G_debug(3, "aline =  %d", aline);
	if (!Vect_line_alive(Map, aline))
	    continue;

	atype = Vect_read_line(Map, APoints, ACats, aline);
	if (!(atype & type))
	    continue;

	Vect_line_box(APoints, &ABox);

	/* Find which sides of the box are touched by intermediate (non-end) points of line */
	if (!is3d) {
	    touch1_n = touch1_s = touch1_e = touch1_w = 0;
	    for (j = 1; j < APoints->n_points; j++) {
		if (APoints->y[j] == ABox.N)
		    touch1_n = 1;
		if (APoints->y[j] == ABox.S)
		    touch1_s = 1;
		if (APoints->x[j] == ABox.E)
		    touch1_e = 1;
		if (APoints->x[j] == ABox.W)
		    touch1_w = 1;
	    }
	    G_debug(3, "touch1: n = %d s = %d e = %d w = %d", touch1_n,
		    touch1_s, touch1_e, touch1_w);
	    touch2_n = touch2_s = touch2_e = touch2_w = 0;
	    for (j = 0; j < APoints->n_points - 1; j++) {
		if (APoints->y[j] == ABox.N)
		    touch2_n = 1;
		if (APoints->y[j] == ABox.S)
		    touch2_s = 1;
		if (APoints->x[j] == ABox.E)
		    touch2_e = 1;
		if (APoints->x[j] == ABox.W)
		    touch2_w = 1;
	    }
	    G_debug(3, "touch2: n = %d s = %d e = %d w = %d", touch2_n,
		    touch2_s, touch2_e, touch2_w);
	}

	Vect_select_lines_by_box(Map, &ABox, type, List);
	G_debug(3, "  %d lines selected by box", List->n_values);

	for (j = 0; j < List->n_values; j++) {
	    bline = List->id[j];
	    if (List_break && !Vect_val_in_list(List_break, bline)) {
		continue;
	    }
	    G_debug(3, "  j = %d bline = %d", j, bline);

	    btype = Vect_read_line(Map, BPoints, BCats, bline);

	    /* Check if thouch by end node only */
	    if (!is3d) {
		Vect_get_line_nodes(Map, aline, &anode1, &anode2);
		Vect_get_line_nodes(Map, bline, &bnode1, &bnode2);
		BBox = List->box[j];

		if (anode1 == bnode1 || anode1 == bnode2)
		    node = anode1;
		else if (anode2 == bnode1 || anode2 == bnode2)
		    node = anode2;
		else
		    node = 0;

		if (node) {
		    Vect_get_node_coor(Map, node, &nodex, &nodey, NULL);
		    if ((node == anode1 && nodey == ABox.N &&
		         !touch1_n && nodey == BBox.S) ||
		        (node == anode2 && nodey == ABox.N &&
			 !touch2_n && nodey == BBox.S) ||
			(node == anode1 && nodey == ABox.S &&
			 !touch1_s && nodey == BBox.N) ||
			(node == anode2 && nodey == ABox.S &&
			 !touch2_s && nodey == BBox.N) ||
			(node == anode1 && nodex == ABox.E &&
			 !touch1_e && nodex == BBox.W) ||
			(node == anode2 && nodex == ABox.E &&
			 !touch2_e && nodex == BBox.W) ||
			(node == anode1 && nodex == ABox.W &&
			 !touch1_w && nodex == BBox.E) ||
			(node == anode2 && nodex == ABox.W &&
			 !touch2_w && nodex == BBox.E)) {

			G_debug(3,
				"lines %d and %d touching by end nodes only -> no intersection",
				aline, bline);
			continue;
		    }
		}
	    }

	    AXLines = NULL;
	    BXLines = NULL;
	    Vect_line_intersection(APoints, BPoints, &AXLines, &BXLines,
				   &naxlines, &nbxlines, 0);
	    G_debug(3, "  naxlines = %d nbxlines = %d", naxlines, nbxlines);

	    /* This part handles a special case when aline == bline, no other intersection was found
	     * and the line is forming collapsed loop, for example  0,0;1,0;0,0 should be broken at 1,0.
	     * ---> */
	    if (aline == bline && naxlines == 0 && nbxlines == 0 &&
		APoints->n_points >= 3) {
		int centre;
		int i;

		G_debug(3, "  Check collapsed loop");
		if (APoints->n_points % 2) {	/* odd number of vertices */
		    centre = APoints->n_points / 2;	/* index of centre */
		    if (APoints->x[centre - 1] == APoints->x[centre + 1] && APoints->y[centre - 1] == APoints->y[centre + 1] && APoints->z[centre - 1] == APoints->z[centre + 1]) {	/* -> break */
			AXLines =
			    (struct line_pnts **)G_malloc(2 *
							  sizeof(struct
								 line_pnts
								 *));
			AXLines[0] = Vect_new_line_struct();
			AXLines[1] = Vect_new_line_struct();

			for (i = 0; i <= centre; i++)
			    Vect_append_point(AXLines[0], APoints->x[i],
					      APoints->y[i], APoints->z[i]);

			for (i = centre; i < APoints->n_points; i++)
			    Vect_append_point(AXLines[1], APoints->x[i],
					      APoints->y[i], APoints->z[i]);

			naxlines = 2;
		    }
		}
	    }
	    /* <--- */

	    if (Err) {		/* array for intersections (more than needed */
		xx = (double *)G_malloc((naxlines + nbxlines) *
					sizeof(double));
		yx = (double *)G_malloc((naxlines + nbxlines) *
					sizeof(double));
		zx = (double *)G_malloc((naxlines + nbxlines) *
					sizeof(double));
	    }
	    nx = 0;		/* number of intersections to be written to Err */
	    if (naxlines > 0) {	/* intersection -> write out */
		Vect_delete_line(Map, aline);
		for (k = 0; k < naxlines; k++) {
		    /* Write new line segments */
		    /* line may collapse, don't write zero length lines */
		    Vect_line_prune(AXLines[k]);
		    if ((atype & GV_POINTS) || AXLines[k]->n_points > 1) {
			ret = Vect_write_line(Map, atype, AXLines[k], ACats);
			if (List_ref) {
			    Vect_list_append(List_ref, ret);
			}
			G_debug(3, "Line %d written, npoints = %d", ret,
				AXLines[k]->n_points);
			if (List_break) {
			    Vect_list_append(List_break, ret);
			}
		    }

		    /* Write intersection points */
		    if (Err) {
			if (k > 0) {
			    xx[nx] = AXLines[k]->x[0];
			    yx[nx] = AXLines[k]->y[0];
			    zx[nx] = AXLines[k]->z[0];
			    nx++;
			}
		    }
		    Vect_destroy_line_struct(AXLines[k]);
		}
		nbreaks += naxlines - 1;
	    }
	    if (AXLines)
		G_free(AXLines);

	    if (nbxlines > 0) {
		if (aline != bline) {	/* Self intersection, do not write twice, TODO: is it OK? */
		    Vect_delete_line(Map, bline);
		    for (k = 0; k < nbxlines; k++) {
			/* Write new line segments */
			/* line may collapse, don't write zero length lines */
			Vect_line_prune(BXLines[k]);
			if ((btype & GV_POINTS) || BXLines[k]->n_points > 1) {
			    ret =
				Vect_write_line(Map, btype, BXLines[k],
						BCats);
			    G_debug(5, "Line %d written", ret);
			    if (List_break) {
				Vect_list_append(List_break, ret);
			    }
			}

			/* Write intersection points */
			if (Err) {
			    if (k > 0) {
				found = 0;
				for (l = 0; l < nx; l++) {
				    if (xx[l] == BXLines[k]->x[0] &&
					yx[l] == BXLines[k]->y[0] &&
					zx[l] == BXLines[k]->z[0]) {
					found = 1;
					break;
				    }
				}
				if (!found) {
				    xx[nx] = BXLines[k]->x[0];
				    yx[nx] = BXLines[k]->y[0];
				    zx[nx] = BXLines[k]->z[0];
				    nx++;
				}
			    }
			}
			Vect_destroy_line_struct(BXLines[k]);
		    }
		    nbreaks += nbxlines - 1;
		}
		else {
		    for (k = 0; k < nbxlines; k++)
			Vect_destroy_line_struct(BXLines[k]);
		}
	    }
	    if (BXLines)
		G_free(BXLines);
	    if (Err) {
		for (l = 0; l < nx; l++) {	/* Write out errors */
		    Vect_reset_line(Points);
		    Vect_append_point(Points, xx[l], yx[l], zx[l]);
		    ret = Vect_write_line(Err, GV_POINT, Points, Cats);
		}

		G_free(xx);
		G_free(yx);
		G_free(zx);
	    }
	    if (naxlines > 0)
		break;		/* first line was broken and deleted -> take the next one */
	}

	if (List_break) {
	    nlines = List_break->n_values;
	}
	else {
	    nlines = Vect_get_num_lines(Map);
	}
	G_debug(3, "nlines =  %d", nlines);
    }				/* for each line */
    G_percent(nlines, nlines, 1); /* finish it */

    G_verbose_message(_("Intersections: %d"), nbreaks);

    Vect_destroy_line_struct(APoints);
    Vect_destroy_line_struct(BPoints);
    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(ACats);
    Vect_destroy_cats_struct(BCats);
    Vect_destroy_cats_struct(Cats);
    Vect_destroy_boxlist(List);

    return nbreaks;
}
Пример #7
0
/*!
   \brief Overlay 2 vector maps with AND.

   AND supports:point line area
   point  +     -    +
   line   -     -    -
   area   +     -    -

   \param AMap vector map A
   \param atype feature type for A
   \param AList unused ?
   \param AAList unused ?
   \param BMap vector map B
   \param btype feature type for B
   \param BList unused ?
   \param BAList unused ?
   \param operator operator code

   \return 1 on success
   \return 0 on error
 */
int
Vect_overlay_and(struct Map_info *AMap, int atype, struct ilist *AList,
		 struct ilist *AAList, struct Map_info *BMap, int btype,
		 struct ilist *BList, struct ilist *BAList,
		 struct Map_info *OMap)
{
    int i, j, k, node, line, altype, bltype, oltype, area, centr;
    struct line_pnts *Points;
    struct line_cats *ACats, *BCats, *OCats;
    struct ilist *AOList, *BOList;

    /* TODO: support Lists */

    Points = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    BCats = Vect_new_cats_struct();
    OCats = Vect_new_cats_struct();
    AOList = Vect_new_list();
    BOList = Vect_new_list();

    /* TODO: support all types; at present only point x point, area x point and point x area supported  */
    if ((atype & GV_LINES) || (btype & GV_LINES))
	G_warning(_("Overlay: line/boundary types not supported by AND operator"));

    if ((atype & GV_AREA) && (btype & GV_AREA))
	G_warning(_("Overlay: area x area types not supported by AND operator"));

    /* TODO: more points in one node in one map */

    /* point x point: select all points with identical coordinates in both maps */
    if ((atype & GV_POINTS) && (btype & GV_POINTS)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: point x point");
	for (i = 1; i <= Vect_get_num_lines(AMap); i++) {
	    altype = Vect_read_line(AMap, Points, ACats, i);
	    if (!(altype & GV_POINTS))
		continue;

	    node =
		Vect_find_node(BMap, Points->x[0], Points->y[0], Points->z[0],
			       0, 1);
	    G_debug(3, "overlay: node = %d", node);
	    if (node == 0)
		continue;

	    Vect_reset_cats(OCats);

	    for (j = 0; j < Vect_get_node_n_lines(BMap, node); j++) {
		line = Vect_get_node_line(BMap, node, j);
		bltype = Vect_read_line(BMap, NULL, BCats, line);
		if (!(bltype & GV_POINTS))
		    continue;

		/* Identical points found -> write out */
		/* TODO: do something if fields in ACats and BCats are identical */
		for (k = 0; k < ACats->n_cats; k++)
		    Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);

		for (k = 0; k < BCats->n_cats; k++)
		    Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);

		/* TODO: what to do if one type is GV_POINT and second GV_CENTROID */
		oltype = altype;
		Vect_write_line(OMap, oltype, Points, OCats);
		Vect_list_append(AOList, i);	/* add to list of written lines */
		Vect_list_append(BOList, line);
		break;
	    }
	}
    }

    /* TODO: check only labeled areas */
    /* point x area: select points from A in areas in B */
    if ((atype & GV_POINTS) && (btype & GV_AREA)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: point x area");

	for (i = 1; i <= Vect_get_num_lines(AMap); i++) {
	    altype = Vect_read_line(AMap, Points, ACats, i);
	    if (!(altype & GV_POINTS))
		continue;

	    area = Vect_find_area(BMap, Points->x[0], Points->y[0]);
	    if (area == 0)
		continue;

	    Vect_reset_cats(OCats);

	    /* TODO: do something if fields in ACats and BCats are identical */
	    for (k = 0; k < ACats->n_cats; k++)
		Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);

	    centr = Vect_get_area_centroid(BMap, area);
	    if (centr > 0) {
		bltype = Vect_read_line(BMap, NULL, BCats, centr);
		for (k = 0; k < BCats->n_cats; k++)
		    Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);
	    }

	    /* Check if not yet written */
	    if (!(Vect_val_in_list(AOList, i))) {
		Vect_write_line(OMap, altype, Points, OCats);
		Vect_list_append(AOList, i);
	    }

	}
    }
    /* area x point: select points from B in areas in A */
    if ((btype & GV_POINTS) && (atype & GV_AREA)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: area x point");

	for (i = 1; i <= Vect_get_num_lines(BMap); i++) {
	    bltype = Vect_read_line(BMap, Points, BCats, i);
	    if (!(bltype & GV_POINTS))
		continue;

	    area = Vect_find_area(AMap, Points->x[0], Points->y[0]);
	    if (area == 0)
		continue;

	    Vect_reset_cats(OCats);

	    /* TODO: do something if fields in ACats and BCats are identical */
	    for (k = 0; k < BCats->n_cats; k++)
		Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);

	    centr = Vect_get_area_centroid(AMap, area);
	    if (centr > 0) {
		altype = Vect_read_line(AMap, NULL, ACats, centr);
		for (k = 0; k < ACats->n_cats; k++)
		    Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);
	    }

	    /* Check if not yet written */
	    if (!(Vect_val_in_list(BOList, i))) {
		Vect_write_line(OMap, bltype, Points, OCats);
		Vect_list_append(BOList, i);
	    }

	}
    }

    return 0;
}