コード例 #1
0
ファイル: break_lines.c プロジェクト: AsherBond/MondocosmOS
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;
}
コード例 #2
0
ファイル: zbulk.c プロジェクト: rashadkm/grass_cmake
/*!
  \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;
}