/*! \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 ADD Need to think about translations - If user translates surface, sites should automatically go with it, but translating sites should translate it relative to surface on which it's displayed Handling mask checking here \todo prevent scaling by 0 \param gp site (geosite) \param gs surface (geosurf) \param do_fast (unused) \return 0 \return 1 */ int gpd_2dsite(geosite * gp, geosurf * gs, int do_fast) { float site[3], konst; float size; int src, check, marker, color; geopoint *gpt; typbuff *buf; GLdouble modelMatrix[16], projMatrix[16]; GLint viewport[4]; GLint window[4]; if (GS_check_cancel()) { return (0); } if (gs) { gs_update_curmask(gs); src = gs_get_att_src(gs, ATT_TOPO); if (src == CONST_ATT) { konst = gs->att[ATT_TOPO].constant; } else { buf = gs_get_att_typbuff(gs, ATT_TOPO, 0); } /* Get viewport parameters for view check */ gsd_getwindow(window, viewport, modelMatrix, projMatrix); gsd_pushmatrix(); gsd_do_scale(1); gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans); gsd_linewidth(gp->width); check = 0; color = gp->color; marker = gp->marker; size = gp->size; for (gpt = gp->points; gpt; gpt = gpt->next) { if (!(++check % CHK_FREQ)) { if (GS_check_cancel()) { gsd_linewidth(1); gsd_popmatrix(); return (0); } } site[X] = gpt->p3[X] + gp->x_trans - gs->ox; site[Y] = gpt->p3[Y] + gp->y_trans - gs->oy; if (gs_point_is_masked(gs, site)) { continue; } /* TODO: set other dynamic attributes */ if (gp->attr_mode & ST_ATT_COLOR) { color = gpt->iattr; } if (src == MAP_ATT) { if (viewcell_tri_interp(gs, buf, site, 1)) { /* returns 0 if outside or masked */ site[Z] += gp->z_trans; if (gsd_checkpoint (site, window, viewport, modelMatrix, projMatrix)) continue; else /* ACS_MODIFY_OneLine site_attr management - was: gpd_obj(gs, color, size, marker, site); */ gpd_obj_site_attr(gs, gp, gpt, site); } } else if (src == CONST_ATT) { if (gs_point_in_region(gs, site, NULL)) { site[Z] = konst + gp->z_trans; if (gsd_checkpoint (site, window, viewport, modelMatrix, projMatrix)) continue; else /* ACS_MODIFY_OneLine site_attr management - was: gpd_obj(NULL, color, size, marker, site); */ gpd_obj_site_attr(NULL, gp, gpt, site); } } } gsd_linewidth(1); gsd_popmatrix(); } return (1); }