예제 #1
0
파일: gs.c 프로젝트: caomw/grass
/*!
   \brief Calculate distance on surface

   \param gs pointer to geosurf struct
   \param p1 from point
   \param p2 to point
   \param[out] dist distnace
   \param use_exag use exag for calculation

   \return 0 on error (points not in region)
   \return 1 on success
 */
int gs_distance_onsurf(geosurf * gs, float *p1, float *p2, float *dist,
		       int use_exag)
{
    Point3 *tmp;
    int np, i;
    float exag, length;

    if (in_vregion(gs, p1) && in_vregion(gs, p2)) {
	if (NULL == (tmp = gsdrape_get_segments(gs, p1, p2, &np))) {
	    return (0);
	}

	length = 0.;

	if (use_exag) {
	    exag = GS_global_exag();
	    tmp[0][Z] *= exag;

	    for (i = 0; i < (np - 1); i++) {
		tmp[i + 1][Z] *= exag;
		length += GS_distance(tmp[i], tmp[i + 1]);
	    }
	}
	else {
	    for (i = 0; i < (np - 1); i++) {
		length += GS_distance(tmp[i], tmp[i + 1]);
	    }
	}

	*dist = length;

	return (1);
    }

    return (0);
}
예제 #2
0
/*!
   \brief ADD

   After all the intersections between the segment and triangle
   edges have been found, they are in three lists.  (intersections
   with vertical, horizontal, and diagonal triangle edges)

   Each list is ordered in space from first to last segment points, 
   but now the lists need to be woven together.  This routine 
   starts with the first point of the segment and then checks the
   next point in each list to find the closest, eliminating duplicates
   along the way and storing the result in I3d.

   \param gs surface (geosurf)
   \param first first point
   \param last last point
   \param vi
   \param hi
   \param di

   \return
 */
int order_intersects(geosurf * gs, Point3 first, Point3 last, int vi, int hi,
		     int di)
{
    int num, i, found, cv, ch, cd, cnum;
    float dv, dh, dd, big, cpoint[2];

    cv = ch = cd = cnum = 0;
    num = vi + hi + di;

    cpoint[X] = first[X];
    cpoint[Y] = first[Y];

    if (in_vregion(gs, first)) {
	I3d[cnum][X] = first[X];
	I3d[cnum][Y] = first[Y];
	I3d[cnum][Z] = first[Z];
	cnum++;
    }

    /* TODO: big could still be less than first dist */
    big = gs->yrange * gs->yrange + gs->xrange * gs->xrange;	/*BIG distance */
    dv = dh = dd = big;

    for (i = 0; i < num; i = cv + ch + cd) {
	if (cv < vi) {
	    dv = dist_squared_2d(Vi[cv], cpoint);

	    if (dv < EPSILON) {
		cv++;
		continue;
	    }
	}
	else {
	    dv = big;
	}

	if (ch < hi) {
	    dh = dist_squared_2d(Hi[ch], cpoint);

	    if (dh < EPSILON) {
		ch++;
		continue;
	    }
	}
	else {
	    dh = big;
	}

	if (cd < di) {
	    dd = dist_squared_2d(Di[cd], cpoint);

	    if (dd < EPSILON) {
		cd++;
		continue;
	    }
	}
	else {
	    dd = big;
	}

	found = 0;

	if (cd < di) {
	    if (dd <= dv && dd <= dh) {
		found = 1;
		cpoint[X] = I3d[cnum][X] = Di[cd][X];
		cpoint[Y] = I3d[cnum][Y] = Di[cd][Y];
		I3d[cnum][Z] = Di[cd][Z];
		cnum++;

		if (EQUAL(dd, dv)) {
		    cv++;
		}

		if (EQUAL(dd, dh)) {
		    ch++;
		}

		cd++;
	    }
	}

	if (!found) {
	    if (cv < vi) {
		if (dv <= dh) {
		    found = 1;
		    cpoint[X] = I3d[cnum][X] = Vi[cv][X];
		    cpoint[Y] = I3d[cnum][Y] = Vi[cv][Y];
		    I3d[cnum][Z] = Vi[cv][Z];
		    cnum++;

		    if (EQUAL(dv, dh)) {
			ch++;
		    }

		    cv++;
		}
	    }
	}

	if (!found) {
	    if (ch < hi) {
		cpoint[X] = I3d[cnum][X] = Hi[ch][X];
		cpoint[Y] = I3d[cnum][Y] = Hi[ch][Y];
		I3d[cnum][Z] = Hi[ch][Z];
		cnum++;
		ch++;
	    }
	}

	if (i == cv + ch + cd) {
	    G_debug(5, "order_intersects(): stuck on %d", cnum);
	    G_debug(5, "order_intersects(): cv = %d, ch = %d, cd = %d", cv,
		    ch, cd);
	    G_debug(5, "order_intersects(): dv = %f, dh = %f, dd = %f", dv,
		    dh, dd);

	    break;
	}
    }

    if (EQUAL(last[X], cpoint[X]) && EQUAL(last[Y], cpoint[Y])) {
	return (cnum);
    }

    if (in_vregion(gs, last)) {
	/* TODO: check for last point on corner ? */
	I3d[cnum][X] = last[X];
	I3d[cnum][Y] = last[Y];
	I3d[cnum][Z] = last[Z];
	++cnum;
    }

    return (cnum);
}
예제 #3
0
/*!
   \brief Check if segment intersect vector region

   Clipping performed:
   - bgn and end are replaced so that both points are within viewregion
   - if seg intersects  

   \param gs surface (geosurf)
   \param bgn begin point
   \param end end point

   \return 0 if segment doesn't intersect the viewregion, or intersects only at corner
   \return otherwise returns 1
 */
int seg_intersect_vregion(geosurf * gs, float *bgn, float *end)
{
    float *replace, xl, yb, xr, yt, xi, yi;
    int inside = 0;

    xl = 0.0;
    xr = VCOL2X(gs, VCOLS(gs));
    yt = VROW2Y(gs, 0);
    yb = VROW2Y(gs, VROWS(gs));

    if (in_vregion(gs, bgn)) {
	replace = end;
	inside++;
    }

    if (in_vregion(gs, end)) {
	replace = bgn;
	inside++;
    }

    if (inside == 2) {
	return (1);
    }
    else if (inside) {
	/* one in & one out - replace gets first intersection */
	if (segs_intersect
	    (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xl, yt, &xi, &yi)) {
	    /* left */
	}
	else if (segs_intersect
		 (bgn[X], bgn[Y], end[X], end[Y], xr, yb, xr, yt, &xi, &yi)) {
	    /* right */
	}
	else if (segs_intersect
		 (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yb, &xi, &yi)) {
	    /* bottom */
	}
	else if (segs_intersect
		 (bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yt, &xi, &yi)) {
	    /* top */
	}

	replace[X] = xi;
	replace[Y] = yi;
    }
    else {
	/* both out - find 2 intersects & replace both */
	float pt1[2], pt2[2];

	replace = pt1;
	if (segs_intersect
	    (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xl, yt, &xi, &yi)) {
	    replace[X] = xi;
	    replace[Y] = yi;
	    replace = pt2;
	    inside++;
	}

	if (segs_intersect
	    (bgn[X], bgn[Y], end[X], end[Y], xr, yb, xr, yt, &xi, &yi)) {
	    replace[X] = xi;
	    replace[Y] = yi;
	    replace = pt2;
	    inside++;
	}

	if (inside < 2) {
	    if (segs_intersect
		(bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yb, &xi, &yi)) {
		replace[X] = xi;
		replace[Y] = yi;
		replace = pt2;
		inside++;
	    }
	}

	if (inside < 2) {
	    if (segs_intersect
		(bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yt, &xi, &yi)) {
		replace[X] = xi;
		replace[Y] = yi;
		inside++;
	    }
	}

	if (inside < 2) {
	    return (0);		/* no intersect or only 1 point on corner */
	}

	/* compare dist of intersects to bgn - closest replaces bgn */
	if (GS_P2distance(bgn, pt1) < GS_P2distance(bgn, pt2)) {
	    bgn[X] = pt1[X];
	    bgn[Y] = pt1[Y];
	    end[X] = pt2[X];
	    end[Y] = pt2[Y];
	}
	else {
	    bgn[X] = pt2[X];
	    bgn[Y] = pt2[Y];
	    end[X] = pt1[X];
	    end[Y] = pt1[Y];
	}
    }

    return (1);
}