Ejemplo n.º 1
0
Archivo: gs.c Proyecto: caomw/grass
/*!
   \brief Check if point is masked

   \param gs pointer to geosurf struct
   \param pt point coordinates (X,Y,Z)

   \return 1 masked
   \return 0 not masked
 */
int gs_point_is_masked(geosurf * gs, float *pt)
{
    int vrow, vcol, drow, dcol;
    int retmask = 0, npts = 0;
    float p2[2];

    if (!gs->curmask) {
	return (0);
    }

    vrow = Y2VROW(gs, pt[Y]);
    vcol = X2VCOL(gs, pt[X]);

    /* check right & bottom edges */
    if (pt[X] == VCOL2X(gs, VCOLS(gs))) {
	/* right edge */
	vcol -= 1;
    }

    if (pt[Y] == VROW2Y(gs, VROWS(gs))) {
	/* bottom edge */
	vrow -= 1;
    }

    drow = VROW2DROW(gs, vrow);
    dcol = VCOL2DCOL(gs, vcol);

    if (BM_get(gs->curmask, dcol, drow)) {
	retmask |= MASK_TL;
	npts++;
    }

    dcol = VCOL2DCOL(gs, vcol + 1);

    if (BM_get(gs->curmask, dcol, drow)) {
	retmask |= MASK_TR;
	npts++;
    }

    drow = VROW2DROW(gs, vrow + 1);

    if (BM_get(gs->curmask, dcol, drow)) {
	retmask |= MASK_BR;
	npts++;
    }

    dcol = VCOL2DCOL(gs, vcol);

    if (BM_get(gs->curmask, dcol, drow)) {
	retmask |= MASK_BL;
	npts++;
    }

    if (npts != 1) {
	/* zero or masked */
	return (retmask | npts);
    }

    p2[X] = VCOL2X(gs, vcol);
    p2[Y] = VROW2Y(gs, vrow + 1);

    switch (retmask) {
    case MASK_TL:
	if ((pt[X] - p2[X]) / VXRES(gs) > (pt[Y] - p2[Y]) / VYRES(gs)) {
	    /* lower triangle */
	    return (0);
	}

	return (retmask | npts);
    case MASK_TR:

	return (retmask | npts);
    case MASK_BR:
	if ((pt[X] - p2[X]) / VXRES(gs) <= (pt[Y] - p2[Y]) / VYRES(gs)) {
	    /* upper triangle */
	    return (0);
	}

	return (retmask | npts);
    case MASK_BL:

	return (retmask | npts);
    }

    /* Assume that if we get here it is an error */
    return (0);
}
Ejemplo n.º 2
0
/*!
   \brief Get horizontal intersects

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

   \return number of intersects
 */
int get_horz_intersects(geosurf * gs, float *bgn, float *end, float *dir)
{
    int frow, lrow, incr, hits, num, offset, dcol1, dcol2;
    float xl, yb, xr, yt, z1, z2, alpha;
    float xres, yres, xi, yi;
    int bgnrow, endrow, rows, cols;

    xres = VXRES(gs);
    yres = VYRES(gs);
    cols = VCOLS(gs);
    rows = VROWS(gs);

    bgnrow = Y2VROW(gs, bgn[Y]);
    endrow = Y2VROW(gs, end[Y]);
    if (bgnrow == endrow) {
	return 0;
    }

    if (bgnrow > rows && endrow > rows) {
	return 0;
    }

    frow = dir[Y] > 0 ? bgnrow : bgnrow + 1;
    lrow = dir[Y] > 0 ? endrow + 1 : endrow;

    /* assuming only showing FULL rows */
    incr = lrow - frow > 0 ? 1 : -1;

    while (frow > rows || frow < 0) {
	frow += incr;
    }

    while (lrow > rows || lrow < 0) {
	lrow -= incr;
    }

    num = abs(lrow - frow) + 1;

    xl = 0.0 - EPSILON;
    xr = xres * cols + EPSILON;

    for (hits = 0; hits < num; hits++) {
	yb = yt = VROW2Y(gs, frow);

	if (segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yb,
			   &xi, &yi)) {
	    Hi[hits][X] = xi;
	    Hi[hits][Y] = yi;

	    /* find data cols */
	    if (Flat) {
		Hi[hits][Z] = gs->att[ATT_TOPO].constant;
	    }
	    else {
		dcol1 = X2VCOL(gs, Hi[hits][X]) * gs->x_mod;
		dcol2 = (1 + X2VCOL(gs, Hi[hits][X])) * gs->x_mod;

		if (dcol2 >= gs->cols) {
		    dcol2 = gs->cols - 1;	/* right edge */
		}

		alpha = (Hi[hits][X] - (dcol1 * gs->xres)) / xres;

		offset = DRC2OFF(gs, frow * gs->y_mod, dcol1);
		GET_MAPATT(Ebuf, offset, z1);
		offset = DRC2OFF(gs, frow * gs->y_mod, dcol2);
		GET_MAPATT(Ebuf, offset, z2);
		Hi[hits][Z] = LERP(alpha, z1, z2);
	    }
	}

	/* if they don't intersect, something's wrong! */
	/* should only happen on endpoint, so it will be added later */
	else {
	    hits--;
	    num--;
	}

	frow += incr;
    }

    return (hits);
}
Ejemplo n.º 3
0
/*!
   \brief ADD

   In gsd_surf, tmesh draws polys like so:
   <pre>
   --------------
   |           /|
   |          / |          
   |         /  |         
   |        /   |        
   |       /    |       
   |      /     |      
   |     /      |     
   |    /       |    
   |   /        |   
   |  /         |  
   | /          | 
   |/           |
   --------------
   </pre>

   UNLESS the top right or bottom left point is masked, in which case a
   single triangle with the opposite diagonal is drawn.  This case is
   not yet handled here & should only occur on edges. 
   pt has X & Y coordinates in it, we interpolate Z here

   This could probably be much shorter, but not much faster.   

   \return 1 if point is in view region
   \return otherwise 0 (if masked)
 */
int viewcell_tri_interp(geosurf * gs, typbuff * buf, Point3 pt,
			int check_mask)
{
    Point3 p1, p2, p3;
    int offset, drow, dcol, vrow, vcol;
    float xmax, ymin, ymax, alpha;

    xmax = VCOL2X(gs, VCOLS(gs));
    ymax = VROW2Y(gs, 0);
    ymin = VROW2Y(gs, VROWS(gs));

    if (check_mask) {
	if (gs_point_is_masked(gs, pt)) {
	    return (0);
	}
    }

    if (pt[X] < 0.0 || pt[Y] > ymax) {
	/* outside on left or top */
	return (0);
    }

    if (pt[Y] < ymin || pt[X] > xmax) {
	/* outside on bottom or right */
	return (0);
    }

    if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
	pt[Z] = gs->att[ATT_TOPO].constant;

	return (1);
    }
    else if (MAP_ATT != gs_get_att_src(gs, ATT_TOPO)) {
	return (0);
    }

    vrow = Y2VROW(gs, pt[Y]);
    vcol = X2VCOL(gs, pt[X]);

    if (vrow < VROWS(gs) && vcol < VCOLS(gs)) {
	/*not on bottom or right edge */
	if (pt[X] > 0.0 && pt[Y] < ymax) {
	    /* not on left or top edge */
	    p1[X] = VCOL2X(gs, vcol + 1);
	    p1[Y] = VROW2Y(gs, vrow);
	    drow = VROW2DROW(gs, vrow);
	    dcol = VCOL2DCOL(gs, vcol + 1);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p1[Z]);	/* top right */

	    p2[X] = VCOL2X(gs, vcol);
	    p2[Y] = VROW2Y(gs, vrow + 1);
	    drow = VROW2DROW(gs, vrow + 1);
	    dcol = VCOL2DCOL(gs, vcol);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p2[Z]);	/* bottom left */

	    if ((pt[X] - p2[X]) / VXRES(gs) > (pt[Y] - p2[Y]) / VYRES(gs)) {
		/* lower triangle */
		p3[X] = VCOL2X(gs, vcol + 1);
		p3[Y] = VROW2Y(gs, vrow + 1);
		drow = VROW2DROW(gs, vrow + 1);
		dcol = VCOL2DCOL(gs, vcol + 1);
		offset = DRC2OFF(gs, drow, dcol);
		GET_MAPATT(buf, offset, p3[Z]);	/* bottom right */
	    }
	    else {
		/* upper triangle */
		p3[X] = VCOL2X(gs, vcol);
		p3[Y] = VROW2Y(gs, vrow);
		drow = VROW2DROW(gs, vrow);
		dcol = VCOL2DCOL(gs, vcol);
		offset = DRC2OFF(gs, drow, dcol);
		GET_MAPATT(buf, offset, p3[Z]);	/* top left */
	    }

	    return (Point_on_plane(p1, p2, p3, pt));
	}
	else if (pt[X] == 0.0) {
	    /* on left edge */
	    if (pt[Y] < ymax) {
		vrow = Y2VROW(gs, pt[Y]);
		drow = VROW2DROW(gs, vrow);
		offset = DRC2OFF(gs, drow, 0);
		GET_MAPATT(buf, offset, p1[Z]);

		drow = VROW2DROW(gs, vrow + 1);
		offset = DRC2OFF(gs, drow, 0);
		GET_MAPATT(buf, offset, p2[Z]);

		alpha = (VROW2Y(gs, vrow) - pt[Y]) / VYRES(gs);
		pt[Z] = LERP(alpha, p1[Z], p2[Z]);
	    }
	    else {
		/* top left corner */
		GET_MAPATT(buf, 0, pt[Z]);
	    }

	    return (1);
	}
	else if (pt[Y] == gs->yrange) {
	    /* on top edge, not a corner */
	    vcol = X2VCOL(gs, pt[X]);
	    dcol = VCOL2DCOL(gs, vcol);
	    GET_MAPATT(buf, dcol, p1[Z]);

	    dcol = VCOL2DCOL(gs, vcol + 1);
	    GET_MAPATT(buf, dcol, p2[Z]);

	    alpha = (pt[X] - VCOL2X(gs, vcol)) / VXRES(gs);
	    pt[Z] = LERP(alpha, p1[Z], p2[Z]);

	    return (1);
	}
    }
    else if (vrow == VROWS(gs)) {
	/* on bottom edge */
	drow = VROW2DROW(gs, VROWS(gs));

	if (pt[X] > 0.0 && pt[X] < xmax) {
	    /* not a corner */
	    vcol = X2VCOL(gs, pt[X]);
	    dcol = VCOL2DCOL(gs, vcol);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p1[Z]);

	    dcol = VCOL2DCOL(gs, vcol + 1);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p2[Z]);

	    alpha = (pt[X] - VCOL2X(gs, vcol)) / VXRES(gs);
	    pt[Z] = LERP(alpha, p1[Z], p2[Z]);

	    return (1);
	}
	else if (pt[X] == 0.0) {
	    /* bottom left corner */
	    offset = DRC2OFF(gs, drow, 0);
	    GET_MAPATT(buf, offset, pt[Z]);

	    return (1);
	}
	else {
	    /* bottom right corner */
	    dcol = VCOL2DCOL(gs, VCOLS(gs));
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, pt[Z]);

	    return (1);
	}
    }
    else {
	/* on right edge, not bottom corner */
	dcol = VCOL2DCOL(gs, VCOLS(gs));

	if (pt[Y] < ymax) {
	    vrow = Y2VROW(gs, pt[Y]);
	    drow = VROW2DROW(gs, vrow);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p1[Z]);

	    drow = VROW2DROW(gs, vrow + 1);
	    offset = DRC2OFF(gs, drow, dcol);
	    GET_MAPATT(buf, offset, p2[Z]);

	    alpha = (VROW2Y(gs, vrow) - pt[Y]) / VYRES(gs);
	    pt[Z] = LERP(alpha, p1[Z], p2[Z]);

	    return (1);
	}
	else {
	    /* top right corner */
	    GET_MAPATT(buf, dcol, pt[Z]);

	    return (1);
	}
    }

    return (0);
}
Ejemplo n.º 4
0
/*!
   \brief ADD

   \todo For consistancy, need to decide how last row & last column are
   displayed - would it look funny to always draw last row/col with
   finer resolution if necessary, or would it be better to only show
   full rows/cols?

   Colinear already eliminated

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

   \return
 */
int get_vert_intersects(geosurf * gs, float *bgn, float *end, float *dir)
{
    int fcol, lcol, incr, hits, num, offset, drow1, drow2;
    float xl, yb, xr, yt, z1, z2, alpha;
    float xres, yres, xi, yi;
    int bgncol, endcol, cols, rows;

    xres = VXRES(gs);
    yres = VYRES(gs);
    cols = VCOLS(gs);
    rows = VROWS(gs);

    bgncol = X2VCOL(gs, bgn[X]);
    endcol = X2VCOL(gs, end[X]);

    if (bgncol > cols && endcol > cols) {
	return 0;
    }

    if (bgncol == endcol) {
	return 0;
    }

    fcol = dir[X] > 0 ? bgncol + 1 : bgncol;
    lcol = dir[X] > 0 ? endcol : endcol + 1;

    /* assuming only showing FULL cols */
    incr = lcol - fcol > 0 ? 1 : -1;

    while (fcol > cols || fcol < 0) {
	fcol += incr;
    }

    while (lcol > cols || lcol < 0) {
	lcol -= incr;
    }

    num = abs(lcol - fcol) + 1;

    yb = gs->yrange - (yres * rows) - EPSILON;
    yt = gs->yrange + EPSILON;

    for (hits = 0; hits < num; hits++) {
	xl = xr = VCOL2X(gs, fcol);

	if (segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yb,
			   &xi, &yi)) {
	    Vi[hits][X] = xi;
	    Vi[hits][Y] = yi;

	    /* find data rows */
	    if (Flat) {
		Vi[hits][Z] = gs->att[ATT_TOPO].constant;
	    }
	    else {
		drow1 = Y2VROW(gs, Vi[hits][Y]) * gs->y_mod;
		drow2 = (1 + Y2VROW(gs, Vi[hits][Y])) * gs->y_mod;

		if (drow2 >= gs->rows) {
		    drow2 = gs->rows - 1;	/*bottom edge */
		}

		alpha =
		    ((gs->yrange - drow1 * gs->yres) - Vi[hits][Y]) / yres;

		offset = DRC2OFF(gs, drow1, fcol * gs->x_mod);
		GET_MAPATT(Ebuf, offset, z1);
		offset = DRC2OFF(gs, drow2, fcol * gs->x_mod);
		GET_MAPATT(Ebuf, offset, z2);
		Vi[hits][Z] = LERP(alpha, z1, z2);
	    }
	}

	/* if they don't intersect, something's wrong! */
	/* should only happen on endpoint, so it will be added later */
	else {
	    hits--;
	    num--;
	}

	fcol += incr;
    }

    return (hits);
}
Ejemplo n.º 5
0
/*!
   \brief Get diagonal intersects

   Colinear already eliminated

   \param gs surface (geosurf)
   \param bgn begin point
   \param end end point
   \param dir ? (unused)

   \return number of intersects
 */
int get_diag_intersects(geosurf * gs, float *bgn, float *end, float *dir)
{
    int fdig, ldig, incr, hits, num, offset;
    int vrow, vcol, drow1, drow2, dcol1, dcol2;
    float xl, yb, xr, yt, z1, z2, alpha;
    float xres, yres, xi, yi, dx, dy;
    int diags, cols, rows, lower;
    Point3 pt;

    xres = VXRES(gs);
    yres = VYRES(gs);
    cols = VCOLS(gs);
    rows = VROWS(gs);
    diags = rows + cols;	/* -1 ? */

    /* determine upper/lower triangle for last */
    vrow = Y2VROW(gs, end[Y]);
    vcol = X2VCOL(gs, end[X]);
    pt[X] = VCOL2X(gs, vcol);
    pt[Y] = VROW2Y(gs, vrow + 1);
    lower = ((end[X] - pt[X]) / xres > (end[Y] - pt[Y]) / yres);
    ldig = lower ? vrow + vcol + 1 : vrow + vcol;

    /* determine upper/lower triangle for first */
    vrow = Y2VROW(gs, bgn[Y]);
    vcol = X2VCOL(gs, bgn[X]);
    pt[X] = VCOL2X(gs, vcol);
    pt[Y] = VROW2Y(gs, vrow + 1);
    lower = ((bgn[X] - pt[X]) / xres > (bgn[Y] - pt[Y]) / yres);
    fdig = lower ? vrow + vcol + 1 : vrow + vcol;

    /* adjust according to direction */
    if (ldig > fdig) {
	fdig++;
    }

    if (fdig > ldig) {
	ldig++;
    }

    incr = ldig - fdig > 0 ? 1 : -1;

    while (fdig > diags || fdig < 0) {
	fdig += incr;
    }

    while (ldig > diags || ldig < 0) {
	ldig -= incr;
    }

    num = abs(ldig - fdig) + 1;

    for (hits = 0; hits < num; hits++) {
	yb = gs->yrange - (yres * (fdig < rows ? fdig : rows)) - EPSILON;
	xl = VCOL2X(gs, (fdig < rows ? 0 : fdig - rows)) - EPSILON;
	yt = gs->yrange - (yres * (fdig < cols ? 0 : fdig - cols)) + EPSILON;
	xr = VCOL2X(gs, (fdig < cols ? fdig : cols)) + EPSILON;

	if (segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yt,
			   &xi, &yi)) {
	    Di[hits][X] = xi;
	    Di[hits][Y] = yi;

	    if (ISNODE(xi, xres)) {
		/* then it's also a ynode */
		num--;
		hits--;
		continue;
	    }

	    /* find data rows */
	    drow1 = Y2VROW(gs, Di[hits][Y]) * gs->y_mod;
	    drow2 = (1 + Y2VROW(gs, Di[hits][Y])) * gs->y_mod;

	    if (drow2 >= gs->rows) {
		drow2 = gs->rows - 1;	/* bottom edge */
	    }

	    /* find data cols */
	    if (Flat) {
		Di[hits][Z] = gs->att[ATT_TOPO].constant;
	    }
	    else {
		dcol1 = X2VCOL(gs, Di[hits][X]) * gs->x_mod;
		dcol2 = (1 + X2VCOL(gs, Di[hits][X])) * gs->x_mod;

		if (dcol2 >= gs->cols) {
		    dcol2 = gs->cols - 1;	/* right edge */
		}

		dx = DCOL2X(gs, dcol2) - Di[hits][X];
		dy = DROW2Y(gs, drow1) - Di[hits][Y];
		alpha =
		    sqrt(dx * dx + dy * dy) / sqrt(xres * xres + yres * yres);

		offset = DRC2OFF(gs, drow1, dcol2);
		GET_MAPATT(Ebuf, offset, z1);
		offset = DRC2OFF(gs, drow2, dcol1);
		GET_MAPATT(Ebuf, offset, z2);
		Di[hits][Z] = LERP(alpha, z1, z2);
	    }
	}

	/* if they don't intersect, something's wrong! */
	/* should only happen on endpoint, so it will be added later */
	else {
	    hits--;
	    num--;
	}

	fdig += incr;
    }

    return (hits);
}