Exemplo n.º 1
0
/*!
  \brief Reads next unread line each time called.  Use Vect_rewind to reset.
  
  This function implements sequential access on level 2.

  \param Map vector map layer
  \param[out] line_p container used to store line points within
  \param[out] line_c container used to store line categories within
  
  \return line type ( > 0 )
  \return 0 dead line
  \return -1 out of memory
  \return -2 end of file
*/
int V2_read_next_line_nat(struct Map_info *Map,
			  struct line_pnts *line_p, struct line_cats *line_c)
{
    register int line, ret;
    register struct P_line *Line;
    struct bound_box lbox, mbox;

    G_debug(3, "V2_read_next_line_nat()");

    if (Map->Constraint_region_flag)
	Vect_get_constraint_box(Map, &mbox);

    while (1) {
	line = Map->next_line;

	if (line > Map->plus.n_lines)
	    return (-2);

	Line = Map->plus.Line[line];
	if (Line == NULL) {	/* Dead line */
	    Map->next_line++;
	    continue;
	}

	if ((Map->Constraint_type_flag &&
	     !(Line->type & Map->Constraint_type))) {
	    Map->next_line++;
	    continue;
	}

	ret = V2_read_line_nat(Map, line_p, line_c, Map->next_line++);
	if (Map->Constraint_region_flag) {
	    Vect_line_box(line_p, &lbox);
	    if (!Vect_box_overlap(&lbox, &mbox)) {
		continue;
	    }
	}

	return ret;
    }

    /* NOTREACHED */ }
Exemplo n.º 2
0
/*!
  \brief Read next line from coor file.
  
  This function implements sequential access on level 1.
    
  \param Map vector map layer
  \param[out] line_p container used to store line points within
  \param[out] line_c container used to store line categories within
  
  \return line type
  \return 0 dead line
  \return -2 end of table (last row)
  \return -1 out of memory
*/
int V1_read_next_line_nat(struct Map_info *Map,
			  struct line_pnts *line_p, struct line_cats *line_c)
{
    int itype;
    off_t offset;
    struct bound_box lbox, mbox;

    G_debug(3, "V1_read_next_line_nat()");

    if (Map->Constraint_region_flag)
	Vect_get_constraint_box(Map, &mbox);

    while (1) {
	offset = dig_ftell(&(Map->dig_fp));
	itype = read_line_nat(Map, line_p, line_c, offset);
	if (itype < 0)
	    return (itype);

	if (itype == 0)		/* is it DEAD? */
	    continue;

	/* Constraint on Type of line 
	 * Default is all of  Point, Line, Area and whatever else comes along
	 */
	if (Map->Constraint_type_flag) {
	    if (!(itype & Map->Constraint_type))
		continue;
	}

	/* Constraint on specified region */
	if (Map->Constraint_region_flag) {
	    Vect_line_box(line_p, &lbox);

	    if (!Vect_box_overlap(&lbox, &mbox))
		continue;
	}

	return (itype);
    }
    /* NOTREACHED */
}
Exemplo n.º 3
0
/*!
  \brief Read next feature from OGR layer. Skip empty features (level 1)
  
  This function implements sequential access.
  
  The action of this routine can be modified by:
   - Vect_read_constraint_region()
   - Vect_read_constraint_type()
   - Vect_remove_constraints()
  
  \param Map pointer to Map_info structure
  \param[out] line_p container used to store line points within
  \param[out] line_c container used to store line categories within
  
  \return feature type
  \return -2 no more features (EOF)
  \return -1 out of memory
*/
int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
			  struct line_cats *line_c)
{
    int itype;
    struct bound_box lbox, mbox;
    OGRFeatureH hFeature;
    OGRGeometryH hGeom;

    G_debug(3, "V1_read_next_line_ogr()");

    if (line_p != NULL)
	Vect_reset_line(line_p);
    if (line_c != NULL)
	Vect_reset_cats(line_c);

    if (Map->Constraint_region_flag)
	Vect_get_constraint_box(Map, &mbox);

    while (TRUE) {
	/* Read feature to cache if necessary */
	while (Map->fInfo.ogr.lines_next == Map->fInfo.ogr.lines_num) {
	    hFeature = OGR_L_GetNextFeature(Map->fInfo.ogr.layer);

	    if (hFeature == NULL) {
		return -2;
	    }			/* no more features */

	    hGeom = OGR_F_GetGeometryRef(hFeature);
	    if (hGeom == NULL) {	/* feature without geometry */
		OGR_F_Destroy(hFeature);
		continue;
	    }

	    Map->fInfo.ogr.feature_cache_id = (int)OGR_F_GetFID(hFeature);
	    if (Map->fInfo.ogr.feature_cache_id == OGRNullFID) {
		G_warning(_("OGR feature without ID"));
	    }

	    /* Cache the feature */
	    Map->fInfo.ogr.lines_num = 0;
	    cache_feature(Map, hGeom, -1);
	    G_debug(4, "%d lines read to cache", Map->fInfo.ogr.lines_num);
	    OGR_F_Destroy(hFeature);

	    Map->fInfo.ogr.lines_next = 0;	/* next to be read from cache */
	}

	/* Read next part of the feature */
	G_debug(4, "read next cached line %d", Map->fInfo.ogr.lines_next);
	itype = Map->fInfo.ogr.lines_types[Map->fInfo.ogr.lines_next];

	/* Constraint on Type of line 
	 * Default is all of  Point, Line, Area and whatever else comes along
	 */
	if (Map->Constraint_type_flag) {
	    if (!(itype & Map->Constraint_type)) {
		Map->fInfo.ogr.lines_next++;
		continue;
	    }
	}

	/* Constraint on specified region */
	if (Map->Constraint_region_flag) {
	    Vect_line_box(Map->fInfo.ogr.lines[Map->fInfo.ogr.lines_next],
			  &lbox);

	    if (!Vect_box_overlap(&lbox, &mbox)) {
		Map->fInfo.ogr.lines_next++;
		continue;
	    }
	}

	if (line_p != NULL)
	    Vect_append_points(line_p,
			       Map->fInfo.ogr.lines[Map->fInfo.ogr.
						    lines_next], GV_FORWARD);

	if (line_c != NULL && Map->fInfo.ogr.feature_cache_id != OGRNullFID)
	    Vect_cat_set(line_c, 1, Map->fInfo.ogr.feature_cache_id);

	Map->fInfo.ogr.lines_next++;
	G_debug(4, "next line read, type = %d", itype);
	
	return itype;
    }
    return -2;			/* not reached */
}
Exemplo n.º 4
0
/*!
   \brief Remove duplicate features from vector map.

   Remove duplicate lines of given types from vector map. Duplicate
   lines may be optionally written to error map. Input map must be
   opened on level 2 for update. Categories are merged.
   GV_BUILD_BASE is sufficient.

   \param[in,out] Map vector map where duplicate lines will be deleted
   \param type type of line to be delete
   \param[out] Err vector map where duplicate lines will be written or NULL

   \return void
 */
void
Vect_remove_duplicates(struct Map_info *Map, int type, struct Map_info *Err)
{
    struct line_pnts *APoints, *BPoints;
    struct line_cats *ACats, *BCats, *Cats;
    int i, j, c, atype, btype, bline;
    int nlines, nbcats_orig;
    struct bound_box ABox;
    struct boxlist *List;
    int ndupl;


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

    nlines = Vect_get_num_lines(Map);

    G_debug(1, "nlines =  %d", nlines);
    /* Go through all lines in vector, for each select lines which overlap MBR of
     *  this line and check if some of them is identical. If someone is identical
     *  remove current line. (In each step just one line is deleted)
     */

    ndupl = 0;

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

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

	Vect_line_box(APoints, &ABox);
	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];
	    G_debug(3, "  j = %d bline = %d", j, bline);
	    if (i == bline)
		continue;

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

	    /* check for duplicates */
	    if (!Vect_line_check_duplicate(APoints, BPoints, Vect_is_3d(Map)))
		continue;

	    /* Lines area identical -> remove current */
	    if (Err) {
		Vect_write_line(Err, atype, APoints, ACats);
	    }

	    Vect_delete_line(Map, i);

	    /* Merge categories */
	    nbcats_orig = BCats->n_cats;

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

	    if (BCats->n_cats > nbcats_orig) {
		G_debug(4, "cats merged: n_cats %d -> %d", nbcats_orig,
			BCats->n_cats);
		Vect_rewrite_line(Map, bline, btype, BPoints, BCats);
	    }

	    ndupl++;

	    break;		/* line was deleted -> take the next one */
	}
	nlines = Vect_get_num_lines(Map);	/* For future when lines with cats will be rewritten */
	G_debug(3, "nlines =  %d\n", nlines);
    }
    G_verbose_message("Removed duplicates: %d", ndupl);
}
Exemplo n.º 5
0
Arquivo: misc.c Projeto: caomw/grass
/* check topology corruption by boundary modification
 * return 0 on corruption, 1 if modification is ok */
int check_topo(struct Map_info *Out, int line, struct line_pnts *APoints,
               struct line_pnts *Points, struct line_cats *Cats)
{
    int i, j, intersect, newline, left_old, right_old,
	left_new, right_new;
    struct bound_box box;
    struct line_pnts **AXLines, **BXLines;
    int naxlines, nbxlines;
    static struct line_pnts *BPoints = NULL;
    static struct boxlist *List = NULL;

    if (!BPoints)
	BPoints = Vect_new_line_struct();
    if (!List)
	List = Vect_new_boxlist(1);

    Vect_line_box(Points, &box);

    /* Check the modified boundary for self-intersection */
    AXLines = BXLines = NULL;
    Vect_line_intersection2(Points, NULL, &box, &box, &AXLines, &BXLines,
			   &naxlines, &nbxlines, 0);
    /* Free */
    if (naxlines > 0) {
	for (j = 0; j < naxlines; j++) {
	    Vect_destroy_line_struct(AXLines[j]);
	}
    }
    if (AXLines)
	G_free(AXLines);
    if (naxlines > 0)
	return 0;

    /* Check intersection of the modified boundary with other boundaries */
    Vect_select_lines_by_box(Out, &box, GV_BOUNDARY, List);

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

	bline = List->id[i];
	if (bline == line)
	    continue;

	Vect_read_line(Out, BPoints, NULL, bline);

	/* Vect_line_intersection is quite slow, hopefully not so bad because only few 
	 * intersections should be found if any */

	AXLines = BXLines = NULL;
	Vect_line_intersection2(Points, BPoints, &box, &List->box[i],
	                        &AXLines, &BXLines,
			        &naxlines, &nbxlines, 0);

	G_debug(4,
		"bline = %d intersect = %d naxlines = %d nbxlines = %d",
		bline, intersect, naxlines, nbxlines);

	/* Free */
	if (naxlines > 0) {
	    for (j = 0; j < naxlines; j++) {
		Vect_destroy_line_struct(AXLines[j]);
	    }
	}
	if (AXLines)
	    G_free(AXLines);
	if (nbxlines > 0) {
	    for (j = 0; j < nbxlines; j++) {
		Vect_destroy_line_struct(BXLines[j]);
	    }
	}
	if (BXLines)
	    G_free(BXLines);

	if (naxlines > 1 || nbxlines > 1) {
	    intersect = 1;
	    break;
	}
    }
    
    /* modified boundary intersects another boundary */
    if (intersect)
	return 0;

    /* Get centroids on the left and right side */
    Vect_get_line_areas(Out, line, &left_old, &right_old);
    if (left_old < 0)
	left_old = Vect_get_isle_area(Out, abs(left_old));
    if (left_old > 0)
	left_old = Vect_get_area_centroid(Out, left_old);
    if (right_old < 0)
	right_old = Vect_get_isle_area(Out, abs(right_old));
    if (right_old > 0)
	right_old = Vect_get_area_centroid(Out, right_old);

    /* OK, rewrite modified boundary */
    newline = Vect_rewrite_line(Out, line, GV_BOUNDARY, Points, Cats);

    /* Check position of centroids */
    Vect_get_line_areas(Out, newline, &left_new, &right_new);
    if (left_new < 0)
	left_new = Vect_get_isle_area(Out, abs(left_new));
    if (left_new > 0)
	left_new = Vect_get_area_centroid(Out, left_new);
    if (right_new < 0)
	right_new = Vect_get_isle_area(Out, abs(right_new));
    if (right_new > 0)
	right_new = Vect_get_area_centroid(Out, right_new);

    if (left_new != left_old || right_new != right_old) {
	G_debug(3,
		"The modified boundary changes attachment of centroid -> not modified");
	Vect_rewrite_line(Out, newline, GV_BOUNDARY, APoints, Cats);
	return 0;
    }
    
    return 1;
}
Exemplo n.º 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;
}
Exemplo n.º 7
0
/*!
  \brief Lines z-bulk labeling
  
  Automated labeling (z coordinate assignment) of vector lines (iso-lines).
  
  \param Map pointer to Map_info
  \param List list of selected lines
  \param point_start_end staring and ending point
  \param start starting value
  \param step step value
  
  \return number of modified features
  \return -1 on error
*/
int Vedit_bulk_labeling(struct Map_info *Map, struct ilist *List,
			double x1, double y1, double x2, double y2,
			double start, double step)
{
    int i, cv_i, p_i;
    int line, type, temp_line;
    int nlines_modified;
    double value, dist;

    struct line_cats *Cats;
    struct line_pnts *Points, *Points_se;	/* start - end */
    struct bound_box box, box_se;

    /* for intersection */
    struct line_pnts **Points_a, **Points_b;
    int nlines_a, nlines_b;

    dbCatValArray cv;		/* line_id / dist */

    nlines_modified = 0;

    value = start;

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

    db_CatValArray_alloc(&cv, List->n_values);
    cv.ctype = DB_C_TYPE_DOUBLE;
    cv.n_values = 0;

    Vect_append_point(Points_se, x1, y1, -PORT_DOUBLE_MAX);
    Vect_append_point(Points_se, x2, y2, PORT_DOUBLE_MAX);

    /* write temporaly line */
    temp_line = Vect_write_line(Map, GV_LINE, Points_se, Cats);
    if (temp_line < 0) {
	return -1;
    }
    
    Vect_line_box(Points_se, &box_se);

    /* determine order of lines */
    cv_i = 0;
    for (i = 0; i < List->n_values; i++) {
	line = List->value[i];

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

	type = Vect_read_line(Map, Points, NULL, line);

	if (!(type & GV_LINE))
	    continue;

	Vect_line_box(Points, &box);
	if (Vect_line_check_intersection(Points_se, Points, WITH_Z)) {
	    Vect_line_intersection(Points_se, Points, &box_se, &box,
				   &Points_a, &Points_b, &nlines_a, &nlines_b,
				   WITHOUT_Z);

	    if (nlines_a < 2 || nlines_b < 1)	/* should not happen */
		continue;

	    /* calculate distance start point -> point of intersection */
	    for (p_i = 0; p_i < Points_a[0]->n_points; p_i++) {
		Points_a[0]->z[p_i] = 0;
	    }
	    dist = Vect_line_length(Points_a[0]);	/* always first line in array? */

	    cv.value[cv_i].cat = line;
	    cv.value[cv_i++].val.d = dist;
	    cv.n_values++;
	}
    }

    /* sort array by distance */
    db_CatValArray_sort_by_value(&cv);

    /* z bulk-labeling */
    for (cv_i = 0; cv_i < cv.n_values; cv_i++) {
	line = cv.value[cv_i].cat;
	type = Vect_read_line(Map, Points, Cats, line);

	for (p_i = 0; p_i < Points->n_points; p_i++) {
	    Points->z[p_i] = value;
	}

	if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
	    return -1;
	}
	nlines_modified++;

	value += step;
    }

    if (Vect_delete_line(Map, temp_line) < 0) {
	return -1;
    }

    db_CatValArray_free(&cv);
    Vect_destroy_line_struct(Points);
    Vect_destroy_line_struct(Points_se);
    Vect_destroy_cats_struct(Cats);

    return nlines_modified;
}