/*! \brief ADD \param gs surface (geosurf) \return 1 \return 0 */ int in_vregion(geosurf * gs, float *pt) { if (pt[X] >= 0.0 && pt[Y] <= gs->yrange) { if (pt[X] <= VCOL2X(gs, VCOLS(gs))) { return (pt[Y] >= VROW2Y(gs, VROWS(gs))); } } return (0); }
/*! \brief Check if point is in region Check for cancel every CHK_FREQ points \param gs surface (geosurf) \param pt point (array(X,Y,Z)) \param region region settings (array (top,bottom,left,right)) \return 0 point outside of region \return 1 point inside region */ int gs_point_in_region(geosurf * gs, float *pt, float *region) { float top, bottom, left, right; if (!region) { top = gs->yrange; bottom = VROW2Y(gs, VROWS(gs)); left = 0.0; right = VCOL2X(gs, VCOLS(gs)); } else { top = region[0]; bottom = region[1]; left = region[2]; right = region[3]; } return (pt[X] >= left && pt[X] <= right && pt[Y] >= bottom && pt[Y] <= top); }
/*! \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); }
/*! \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); }
/*! \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); }
/*! \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); }
/*! \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); }