/*! \brief Set attribute source \param gs pointer to geosurf struct \param desc attribute id (descriptor) \param src source id \return -1 on error \return 0 on success */ int gs_set_att_src(geosurf * gs, int desc, int src) { if (gs) G_debug(5, "gs_set_att_src(): id=%d desc=%d src=%d", gs->gsurf_id, desc, src); /* check if old source was MAP_ATT, free buff */ if (MAP_ATT == gs_get_att_src(gs, desc)) { if (1 == gs_num_datah_reused(gs->att[desc].hdata)) { /* only reference */ G_debug(5, "gs_set_att_src(): replacing existing map"); gsds_free_datah(gs->att[desc].hdata); } if (ATT_TOPO == desc) { if (gs->norms) { G_free(gs->norms); } gs->norms = NULL; gs->norm_needupdate = 0; } } if (gs && LEGAL_SRC(src)) { gs->att[desc].att_src = src; return (0); } return (-1); }
/*! \brief Get all segments \param gs surface (geosurf) \param bgn begin point \param end end point \param num \return pointer to Point3 struct */ Point3 *gsdrape_get_allsegments(geosurf * gs, float *bgn, float *end, int *num) { gsdrape_set_surface(gs); if (!seg_intersect_vregion(gs, bgn, end)) { *num = 0; return (NULL); } if (bgn[X] == end[X] && bgn[Y] == end[Y]) { float f[3], l[3]; interp_first_last(gs, bgn, end, f, l); GS_v3eq(I3d[0], f); GS_v3eq(I3d[1], l); *num = 2; return (I3d); } if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) { Flat = 1; } else { Flat = 0; } return (_gsdrape_get_segments(gs, bgn, end, num)); }
/*! \brief ADD \param gs surface (geosurf) \param bgn begin point (x,y) \param end end point (x,y) \param num \return pointer to Point3 struct */ Point3 *gsdrape_get_segments(geosurf * gs, float *bgn, float *end, int *num) { gsdrape_set_surface(gs); if (!seg_intersect_vregion(gs, bgn, end)) { *num = 0; return (NULL); } if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) { /* will probably want a force_drape option to get all intersects */ I3d[0][X] = bgn[X]; I3d[0][Y] = bgn[Y]; I3d[0][Z] = gs->att[ATT_TOPO].constant; I3d[1][X] = end[X]; I3d[1][Y] = end[Y]; I3d[1][Z] = gs->att[ATT_TOPO].constant; *num = 2; return (I3d); } if (bgn[X] == end[X] && bgn[Y] == end[Y]) { float f[3], l[3]; interp_first_last(gs, bgn, end, f, l); GS_v3eq(I3d[0], f); GS_v3eq(I3d[1], l); /* CHANGE (*num = 1) to reflect degenerate line ? */ *num = 2; return (I3d); } Flat = 0; return (_gsdrape_get_segments(gs, bgn, end, num)); }
/*! \brief Update no_zero ranges for attribute (actually no_null now) \param gs pointer to geosurf struct \param desc attribute id (descriptor) \return -1 on error \return 1 on success */ int Gs_update_attrange(geosurf * gs, int desc) { long size; float min, max; typbuff *tb; struct BM *nm; int found; gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].range_nz = 0.0; if (CONST_ATT == gs_get_att_src(gs, desc)) { gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].constant; min = max = gs->att[desc].constant; gs->att[desc].range_nz = 0.0; } else if (CF_COLOR_PACKED & gsds_get_changed(gs->att[desc].hdata)) { gs->att[desc].max_nz = 0xFFFFFF; gs->att[desc].min_nz = 0x010101; gs->att[desc].range_nz = 0xFFFFFF; } else { if (NULL == (tb = gsds_get_typbuff(gs->att[desc].hdata, 0))) { return (-1); } nm = tb->nm; if (tb->ib) { int *p; size = gs->rows * gs->cols; p = tb->ib; INIT_MINMAX(p, nm, size, min, max, found); if (!found) { /* all nulls! */ return (-1); } size = gs->rows * gs->cols; p = tb->ib; SET_MINMAX(p, nm, size, min, max); } else if (tb->sb) { short *p; size = gs->rows * gs->cols; p = tb->sb; INIT_MINMAX(p, nm, size, min, max, found); if (!found) { /* all nulls! */ return (-1); } size = gs->rows * gs->cols; p = tb->sb; SET_MINMAX(p, nm, size, min, max); } else if (tb->cb) { char *p; size = gs->rows * gs->cols; p = (char *)tb->cb; INIT_MINMAX(p, nm, size, min, max, found); if (!found) { /* all nulls! */ return (-1); } size = gs->rows * gs->cols; p = (char *)tb->cb; SET_MINMAX(p, nm, size, min, max); } else if (tb->fb) { float *p; size = gs->rows * gs->cols; p = tb->fb; INIT_MINMAX(p, nm, size, min, max, found); if (!found) { /* all nulls! */ return (-1); } size = gs->rows * gs->cols; p = tb->fb; SET_MINMAX(p, nm, size, min, max); } gs->att[desc].max_nz = max; gs->att[desc].min_nz = min; gs->att[desc].range_nz = gs->att[desc].max_nz - gs->att[desc].min_nz; } if (ATT_TOPO == desc) { gs->zmin = min; gs->zmax = max; gs->zrange = gs->zmax - gs->zmin; gs->zminmasked = gs->zmin; gs->zmax_nz = gs->zmax; gs->zmin_nz = gs->zmin; gs->zrange_nz = gs->zmax_nz - gs->zmin_nz; } G_debug(3, "Gs_update_attrange(): min=%f max=%f", gs->zmin, gs->zmax); return (1); }
/*! \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); }