/* * ACE/vis - Visualization of Flow and Transport * * Paul J. Turner and Antonio M. Baptista * * Copyright 1990-2003 Oregon Health and Science University * All Rights Reserved * */ /* * * graph utilities * */ #ifndef lint static char RCSid[] = "$Id: graphutils.c,v 1.4 2004/08/05 21:32:17 pturner Exp $"; #endif #include <stdio.h> #include <math.h> #include "defines.h" #include "globals.h" void push_world(void); void update_all(int gno); int graph_active(int k) { return g[k].active == ON; } void get_graph_box(int i, boxtype * b) { memcpy(b, &boxes[i], sizeof(boxtype)); } void get_graph_line(int i, linetype * l) { memcpy(l, &lines[i], sizeof(linetype)); } void get_graph_string(int i, plotstr * s) { memcpy(s, &pstr[i], sizeof(plotstr)); } void get_graph_framep(int gno, framep * f) { memcpy(f, &g[gno].f, sizeof(framep)); } void get_graph_world(int gno, world * w) { memcpy(w, &g[gno].w, sizeof(world)); } void get_graph_view(int gno, view * v) { memcpy(v, &g[gno].v, sizeof(view)); } void get_graph_labels(int gno, labels * labs) { memcpy(labs, &g[gno].labs, sizeof(labels)); } void get_graph_tickmarks(int gno, tickmarks * t, int a) { memcpy(t, &g[gno].t[a], sizeof(tickmarks)); } /* * * set graph props * */ void set_graph_box(int i, boxtype * b) { memcpy(&boxes[i], b, sizeof(boxtype)); } void set_graph_line(int i, linetype * l) { memcpy(&lines[i], l, sizeof(linetype)); } void set_graph_string(int i, plotstr * s) { memcpy(&pstr[i], s, sizeof(plotstr)); } void set_graph_active(int gno) { g[gno].active = ON; } void set_graph_framep(int gno, framep * f) { memcpy(&g[gno].f, f, sizeof(framep)); } void set_graph_world(int gno, world * w) { memcpy(&g[gno].w, w, sizeof(world)); } void set_graph_view(int gno, view * v) { memcpy(&g[gno].v, v, sizeof(view)); } void set_graph_labels(int gno, labels * labs) { memcpy(&g[gno].labs, labs, sizeof(labels)); } void set_graph_tickmarks(int gno, tickmarks * t, int a) { memcpy(&g[gno].t[a], t, sizeof(tickmarks)); } void set_axis_prop(int whichgraph, int naxis, int prop, double val) { int i, j, startg, stopg; if (whichgraph == -1) { startg = 0; stopg = maxgraph - 1; } else { startg = whichgraph; stopg = whichgraph; } for (j = startg; j <= stopg; j++) { switch (prop) { case ON: case OFF: switch (naxis) { case 6: for (i = 0; i < 6; i++) { g[j].t[i].active = (int) val; } break; case 7: for (i = 0; i < 6; i += 2) { g[j].t[i].active = (int) val; } break; case 8: for (i = 1; i < 6; i += 2) { g[j].t[i].active = (int) val; } break; } break; case COLOR: switch (naxis) { case 6: for (i = 0; i < 6; i++) { g[j].t[i].tl_color = (int) val; g[j].t[i].t_drawbarcolor = (int) val; g[j].t[i].t_color = (int) val; g[j].t[i].t_mcolor = (int) val; g[j].t[i].label.color = (int) val; } break; case 7: for (i = 0; i < 6; i += 2) { g[j].t[i].tl_color = (int) val; g[j].t[i].t_drawbarcolor = (int) val; g[j].t[i].t_color = (int) val; g[j].t[i].t_mcolor = (int) val; g[j].t[i].label.color = (int) val; } break; case 8: for (i = 1; i < 6; i += 2) { g[j].t[i].tl_color = (int) val; g[j].t[i].t_drawbarcolor = (int) val; g[j].t[i].t_color = (int) val; g[j].t[i].t_mcolor = (int) val; g[j].t[i].label.color = (int) val; } break; } break; case LINEWIDTH: switch (naxis) { case 6: for (i = 0; i < 6; i++) { g[j].t[i].tl_linew = (int) val; g[j].t[i].t_linew = (int) val; g[j].t[i].t_mlinew = (int) val; g[j].t[i].t_drawbarlinew = (int) val; } break; case 7: for (i = 0; i < 6; i += 2) { g[j].t[i].tl_linew = (int) val; g[j].t[i].t_linew = (int) val; g[j].t[i].t_mlinew = (int) val; g[j].t[i].t_drawbarlinew = (int) val; } break; case 8: for (i = 1; i < 6; i += 2) { g[j].t[i].tl_linew = (int) val; g[j].t[i].t_linew = (int) val; g[j].t[i].t_mlinew = (int) val; g[j].t[i].t_drawbarlinew = (int) val; } break; } break; case FONTP: switch (naxis) { case 6: for (i = 0; i < 6; i++) { g[j].t[i].tl_font = (int) val; g[j].t[i].label.font = (int) val; } break; case 7: for (i = 0; i < 6; i += 2) { g[j].t[i].tl_font = (int) val; g[j].t[i].label.font = (int) val; } break; case 8: for (i = 1; i < 6; i += 2) { g[j].t[i].tl_font = (int) val; g[j].t[i].label.font = (int) val; } break; } break; case CHAR: switch (naxis) { case 6: for (i = 0; i < 6; i++) { g[j].t[i].tl_charsize = val; g[j].t[i].label.charsize = val; } break; case 7: for (i = 0; i < 6; i += 2) { g[j].t[i].tl_charsize = val; g[j].t[i].label.charsize = val; } break; case 8: for (i = 1; i < 6; i += 2) { g[j].t[i].tl_charsize = val; g[j].t[i].label.charsize = val; } break; } break; } } } int iscontained(int gno, double wx, double wy) { int i; double xconv(), yconv(); double x = xconv(wx), y = yconv(wy); for (i = 0; i < maxgraph; i++) { if (g[i].active == ON) { if ((g[i].v.xv1 <= x && g[i].v.xv2 >= x) && (g[i].v.yv1 <= y && g[i].v.yv2 >= y)) { return i; } } } return gno; } int islogx(int gno) { return (g[gno].type == LOGX || g[gno].type == LOGXY); } int islogy(int gno) { return (g[gno].type == LOGY || g[gno].type == LOGXY); } char *graph_types(int it, int which) { static char s[128]; strcpy(s, "UNKNOWN"); switch (it) { case XYFIXED: if (which) { strcpy(s, "xyfixed"); } else { strcpy(s, "XYFIXED"); } break; case XY: if (which) { strcpy(s, "xy"); } else { strcpy(s, "XY"); } break; case LOGX: if (which) { strcpy(s, "logx"); } else { strcpy(s, "LOG-LINEAR"); } break; case LOGY: if (which) { strcpy(s, "logy"); } else { strcpy(s, "LINEAR-LOG"); } break; case LOGXY: if (which) { strcpy(s, "logxy"); } else { strcpy(s, "LOG-LOG"); } break; case POLAR: strcpy(s, "polar"); break; case BAR: if (which) { strcpy(s, "bar"); } else { strcpy(s, "BAR"); } break; case HBAR: if (which) { strcpy(s, "hbar"); } else { strcpy(s, "HORIZONTAL BAR"); } break; case PIE: strcpy(s, "pie"); break; case STACKEDBAR: if (which) { strcpy(s, "stackedbar"); } else { strcpy(s, "STACKED BAR"); } break; case STACKEDHBAR: if (which) { strcpy(s, "stackedhbar"); } else { strcpy(s, "STACKED HORIZONTAL BAR"); } break; case STACKEDLINE: strcpy(s, "STACKED LINE"); break; } return s; } int get_format_index(int f) { int i = 0; while (f != format_types[i] && format_types[i] != 0) i++; return i; } char *get_format_types(int f) { static char s[128]; strcpy(s, "decimal"); switch (f) { case DECIMAL: strcpy(s, "decimal"); break; case EXPONENTIAL: strcpy(s, "exponential"); break; case POWER: strcpy(s, "power"); break; case GENERAL: strcpy(s, "general"); break; case DDMMYY: strcpy(s, "ddmmyy"); break; case MMDDYY: strcpy(s, "mmddyy"); break; case MMYY: strcpy(s, "mmyy"); break; case MMDD: strcpy(s, "mmdd"); break; case MONTHDAY: strcpy(s, "monthday"); break; case DAYMONTH: strcpy(s, "daymonth"); break; case MONTHS: strcpy(s, "months"); break; case MONTHL: strcpy(s, "monthl"); break; case DAYOFWEEKS: strcpy(s, "dayofweeks"); break; case DAYOFWEEKL: strcpy(s, "dayofweekl"); break; case DAYOFYEAR: strcpy(s, "dayofyear"); break; case HMS: strcpy(s, "hms"); break; case MMDDHMS: strcpy(s, "mmddhms"); break; case MMDDYYHMS: strcpy(s, "mmddyyhms"); break; case DEGREESLON: strcpy(s, "degreeslon"); break; case DEGREESMMLON: strcpy(s, "degreesmmlon"); break; case DEGREESMMSSLON: strcpy(s, "degreesmmsslon"); break; case MMSSLON: strcpy(s, "mmsslon"); break; case DEGREESLAT: strcpy(s, "degreeslat"); break; case DEGREESMMLAT: strcpy(s, "degreesmmlat"); break; case DEGREESMMSSLAT: strcpy(s, "degreesmmsslat"); break; case MMSSLAT: strcpy(s, "mmsslat"); break; } return s; } void kill_graph(int gno) { int i, j; if (gno == maxgraph) { for (i = 0; i < maxgraph; i++) { set_default_graph(i); } } else { set_default_graph(gno); } } void copy_graph(int from, int to) { int i, j; kill_graph(to); memcpy(&g[to], &g[from], sizeof(graph)); set_graph_active(to); /* TODO compare maxplots */ } void swap_graph(int from, int to) { graph gtmp; memcpy(>mp, &g[from], sizeof(graph)); memcpy(&g[from], &g[to], sizeof(graph)); memcpy(&g[to], >mp, sizeof(graph)); } /* * for flipping */ void flipxy(int gno) { int i, j; tickmarks t; double *x, *y; for (i = 0; i < 6; i += 2) { memcpy(&t, &g[gno].t[i], sizeof(tickmarks)); memcpy(&g[gno].t[i], &g[gno].t[i + 1], sizeof(tickmarks)); memcpy(&g[gno].t[i + 1], &t, sizeof(tickmarks)); if (g[gno].t[i].t_op == RIGHT) { g[gno].t[i].t_op = TOP; } else if (g[gno].t[i].t_op == LEFT) { g[gno].t[i].t_op = BOTTOM; } if (g[gno].t[i].tl_op == RIGHT) { g[gno].t[i].tl_op = TOP; } else if (g[gno].t[i].tl_op == LEFT) { g[gno].t[i].tl_op = BOTTOM; } if (g[gno].t[i + 1].t_op == TOP) { g[gno].t[i + 1].t_op = RIGHT; } else if (g[gno].t[i + 1].t_op == BOTTOM) { g[gno].t[i + 1].t_op = LEFT; } if (g[gno].t[i + 1].tl_op == TOP) { g[gno].t[i + 1].tl_op = RIGHT; } else if (g[gno].t[i + 1].tl_op == BOTTOM) { g[gno].t[i + 1].tl_op = LEFT; } } if (g[gno].type == LOGX) { g[gno].type = LOGY; } else if (g[gno].type == LOGY) { g[gno].type = LOGX; } fswap(&g[gno].w.xg1, &g[gno].w.yg1); fswap(&g[gno].w.xg2, &g[gno].w.yg2); fswap(&g[gno].dsx, &g[gno].dsy); iswap(&g[gno].fx, &g[gno].fy); iswap(&g[gno].px, &g[gno].py); update_all(gno); drawgraph(); } void invertx(int gno) { int i, j; double *x; if (!islogx(gno)) { fswap(&g[gno].w.xg1, &g[gno].w.xg2); g[gno].w.xg1 = -g[gno].w.xg1; g[gno].w.xg2 = -g[gno].w.xg2; g[gno].dsx = -g[gno].dsx; for (i = 0; i < 6; i += 2) { if (g[gno].t[i].tl_sign == NORMAL) { g[gno].t[i].tl_sign = NEGATE; } else { g[gno].t[i].tl_sign = NORMAL; } } update_all(gno); drawgraph(); } else { errwin("Can't invert log axes"); } } void inverty(int gno) { int i, j; double *y; if (!islogy(gno)) { fswap(&g[gno].w.yg1, &g[gno].w.yg2); g[gno].w.yg1 = -g[gno].w.yg1; g[gno].w.yg2 = -g[gno].w.yg2; g[gno].dsy = -g[gno].dsy; for (i = 1; i < 6; i += 2) { if (g[gno].t[i].tl_sign == NORMAL) { g[gno].t[i].tl_sign = NEGATE; } else { g[gno].t[i].tl_sign = NORMAL; } } update_all(gno); drawgraph(); } else { errwin("Can't invert log axes"); } } void do_flipxy(void) { flipxy(cg); } void do_invertx(void) { invertx(cg); } void do_inverty(void) { inverty(cg); } /* the following routines determine default scaling and tickmarks */ void defaultgraph(int gno) { double x1, x2, y1, y2; double xgmax, xgmin, ygmax, ygmin; int i, first = 1; xgmax = xgmin = ygmax = ygmin = 0.0; for (i = 0; i < g[gno].maxplot; i++) { if (first) { xgmin = x1; xgmax = x2; ygmin = y1; ygmax = y2; first = 0; } else { xgmin = (x1 < xgmin) ? x1 : xgmin; xgmax = (x2 > xgmax) ? x2 : xgmax; ygmin = (y1 < ygmin) ? y1 : ygmin; ygmax = (y2 > ygmax) ? y2 : ygmax; } } if (xgmin != xgmax) { g[gno].w.xg2 = xgmax; g[gno].w.xg1 = xgmin; } else { g[gno].w.xg1 = xgmin - 1.0; g[gno].w.xg2 = xgmin + 1.0; } if (ygmin != ygmax) { g[gno].w.yg2 = ygmax; g[gno].w.yg1 = ygmin; } else { g[gno].w.yg1 = ygmin - 1.0; g[gno].w.yg2 = ygmin + 1.0; } switch (g[gno].type) { case LOGX: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph type to log-linear, X minimum = 0.0"); g[gno].type = XY; } break; case LOGY: if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to linear-log, Y minimum = 0.0"); g[gno].type = XY; } break; case LOGXY: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph to log-log, X minimum <= 0.0"); g[gno].type = XY; } else if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to log-log, Y minimum <= 0.0"); g[gno].type = XY; } break; } } void defaultx(int gno, int setno) { int i, first = 1; double xgmin, xgmax, xmax, xmin, tmp; xgmin = xgmax = 0.0; if (setno < 0) { for (i = 0; i < g[gno].maxplot; i++) { if (first) { xgmin = xmin; xgmax = xmax; first = 0; } else { xgmin = (xmin < xgmin) ? xmin : xgmin; xgmax = (xmax > xgmax) ? xmax : xgmax; } } } else { } if (xgmin != xgmax) { g[gno].w.xg2 = xgmax; g[gno].w.xg1 = xgmin; } else { if ((xgmin == 0.0) && (xgmax == 0.0)) { xgmin = 1.0; } g[gno].w.xg1 = xgmin - 0.1 * fabs(xgmin); g[gno].w.xg2 = xgmin + 0.1 * fabs(xgmin); } switch (g[gno].type) { case LOGX: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph type to log-linear, X minimum = 0.0"); g[gno].type = XY; } break; case LOGY: if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to linear-log, Y minimum = 0.0"); g[gno].type = XY; } break; case LOGXY: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph to log-log, X minimum <= 0.0"); g[gno].type = XY; } else if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to log-log, Y minimum <= 0.0"); g[gno].type = XY; } break; } } void defaulty(int gno, int setno) { int i, first = 1; double ygmax, ygmin, ymin, ymax, tmp; ygmin = ygmax = 0.0; if (setno < 0) { for (i = 0; i < g[gno].maxplot; i++) { if (first) { ygmin = ymin; ygmax = ymax; first = 0; } else { ygmin = (ymin < ygmin) ? ymin : ygmin; ygmax = (ymax > ygmax) ? ymax : ygmax; } } } else { } if (ygmin != ygmax) { g[gno].w.yg2 = ygmax; g[gno].w.yg1 = ygmin; } else { if ((ygmin == 0.0) && (ygmax == 0.0)) { ygmin = 1.0; } g[gno].w.yg1 = ygmin - 0.1 * fabs(ygmin); g[gno].w.yg2 = ygmin + 0.1 * fabs(ygmin); } switch (g[gno].type) { case LOGX: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph type to log-linear, X minimum = 0.0"); g[gno].type = XY; } break; case LOGY: if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to linear-log, Y minimum = 0.0"); g[gno].type = XY; } break; case LOGXY: if (g[gno].w.xg1 <= 0.0) { errwin("can't set graph to log-log, X minimum <= 0.0"); g[gno].type = XY; } else if (g[gno].w.yg1 <= 0.0) { errwin("can't set graph type to log-log, Y minimum <= 0.0"); g[gno].type = XY; } break; } } /* * label: test program to demonstrate nice graph axis labeling * * Paul Heckbert, 2 Dec 88 */ double expt(double a, register int n), nicenum(double x, int round); void default_ticks(int gno, int axis, double *gmin, double *gmax) { tickmarks t; double range, d, tmpmax = *gmax, tmpmin = *gmin; get_graph_tickmarks(gno, &t, axis); if (axis % 2 && (g[gno].type == LOGY || g[gno].type == LOGXY)) { tmpmax = ceil(log10(tmpmax)); tmpmin = floor(log10(tmpmin)); } else if ((axis % 2 == 0) && (g[gno].type == LOGX || g[gno].type == LOGXY)) { tmpmax = ceil(log10(tmpmax)); tmpmin = floor(log10(tmpmin)); } range = nicenum(tmpmax - tmpmin, 0); d = nicenum(range / (t.t_num - 1), 1); tmpmin = floor(tmpmin / d) * d; tmpmax = ceil(tmpmax / d) * d; if (axis % 2 && (g[gno].type == LOGY || g[gno].type == LOGXY)) { *gmax = pow(10.0, tmpmax); *gmin = pow(10.0, tmpmin); t.tmajor = (int) d; if (t.tmajor == 0.0) { t.tmajor = 1.0; } if ((int) t.tmajor < 2) { t.tminor = 1.0; } else { t.tminor = 0.0; } if (fabs(tmpmax) > 6.0 || fabs(tmpmin) > 6.0) { t.tl_format = POWER; t.tl_prec = 0; } else { t.tl_format = DECIMAL; t.tl_prec = 0; } } else if ((axis % 2 == 0) && (g[gno].type == LOGX || g[gno].type == LOGXY)) { *gmax = pow(10.0, tmpmax); *gmin = pow(10.0, tmpmin); t.tmajor = (int) d; if (t.tmajor == 0.0) { t.tmajor = 1.0; } if (fabs(tmpmax) > 6.0 || fabs(tmpmin) > 6.0) { t.tl_format = POWER; t.tl_prec = 0; } else { t.tl_format = DECIMAL; t.tl_prec = 0; } if ((int) t.tmajor < 2) { t.tminor = 1.0; } else { t.tminor = 0.0; } } else { *gmax = tmpmax; *gmin = tmpmin; t.tmajor = d; t.tminor = d * 0.5; } set_graph_tickmarks(gno, &t, axis); } /* * nicenum: find a "nice" number approximately equal to x * round if round=1, ceil if round=0 */ double nicenum(double x, int round) { int exp; double f, y; exp = floor(log10(x)); f = x / expt(10., exp); /* fraction between 1 and 10 */ if (round) if (f < 1.5) y = 1.; else if (f < 3.) y = 2.; else if (f < 7.) y = 5.; else y = 10.; else if (f <= 1.) y = 1.; else if (f <= 2.) y = 2.; else if (f <= 5.) y = 5.; else y = 10.; return y * expt(10., exp); } /* * expt(a,n)=a^n for integer n * roundoff errors in pow were causing problems, so I wrote my own */ double expt(double a, register int n) { double x; x = 1.; if (n > 0) for (; n > 0; n--) x *= a; else for (; n < 0; n++) x /= a; return x; } void defaultsetgraph(int gno, int setno) { double xmax, xmin, ymax, ymin; /* getsetminmax(gno, setno, &xmin, &xmax, &ymin, &ymax); */ /* TODO need to hook up to data in xmvis */ xmin = ymin = 0.0; xmax = ymax = 1.0; if (xmin != xmax) { g[gno].w.xg2 = xmax; g[gno].w.xg1 = xmin; } else { if ((xmin == 0.0) && (xmax == 0.0)) { xmin = 1.0; } g[gno].w.xg1 = xmin - 0.1 * fabs(xmin); g[gno].w.xg2 = xmin + 0.1 * fabs(xmin); } if (ymin != ymax) { g[gno].w.yg2 = ymax; g[gno].w.yg1 = ymin; } else { if ((ymin == 0.0) && (ymax == 0.0)) { ymin = 1.0; } g[gno].w.yg1 = ymin - 0.1 * fabs(ymin); g[gno].w.yg2 = ymin + 0.1 * fabs(ymin); } } void default_axis(int gno, int method, int axis) { int cx; tickmarks t; world w; double llim, ulim; get_graph_tickmarks(gno, &t, axis); get_graph_world(gno, &w); if (axis % 2) { llim = w.yg1; ulim = w.yg2; } else { llim = w.xg1; ulim = w.xg2; } t.tmajor = (ulim - llim) / t.t_num; t.tminor = t.tmajor / 2.0; cx = (int) log10(t.tmajor); t.tl_prec = ((cx < 0) ? -cx + 1 : 1); if (t.tl_prec > 9) { t.tl_prec = 2; t.tl_format = EXPONENTIAL; } set_graph_tickmarks(gno, &t, axis); if (method == AUTO) { default_ticks(gno, axis, &llim, &ulim); if (axis % 2) { w.yg1 = llim; w.yg2 = ulim; } else { w.xg1 = llim; w.xg2 = ulim; } set_graph_world(gno, &w); } if (g[gno].type == XYFIXED) { setfixedscale(g[gno].v.xv1, g[gno].v.yv1, g[gno].v.xv2, g[gno].v.yv2, &g[gno].w.xg1, &g[gno].w.yg1, &g[gno].w.xg2, &g[gno].w.yg2); } } void autoscale_graph(int gno, int axis) { if (activeset(gno)) { switch (axis) { case -3: defaultgraph(gno); default_axis(gno, g[gno].auto_type, X_AXIS); default_axis(gno, g[gno].auto_type, ZX_AXIS); default_axis(gno, g[gno].auto_type, Y_AXIS); default_axis(gno, g[gno].auto_type, ZY_AXIS); break; case -2: defaultx(gno, -1); default_axis(gno, g[gno].auto_type, X_AXIS); default_axis(gno, g[gno].auto_type, ZX_AXIS); break; case -1: defaulty(gno, -1); default_axis(gno, g[gno].auto_type, Y_AXIS); default_axis(gno, g[gno].auto_type, ZY_AXIS); break; default: if (axis % 2) { defaulty(gno, -1); } else { defaultx(gno, -1); } default_axis(gno, g[gno].auto_type, axis); break; } update_all(gno); } } void autoscale_proc(void) { if (activeset(cg)) { defaultgraph(cg); default_axis(cg, g[cg].auto_type, X_AXIS); default_axis(cg, g[cg].auto_type, ZX_AXIS); default_axis(cg, g[cg].auto_type, Y_AXIS); default_axis(cg, g[cg].auto_type, ZY_AXIS); update_all(cg); drawgraph(); } else { errwin("No active sets!"); } } void autoticks_proc(void) { default_axis(cg, g[cg].auto_type, X_AXIS); default_axis(cg, g[cg].auto_type, ZX_AXIS); default_axis(cg, g[cg].auto_type, Y_AXIS); default_axis(cg, g[cg].auto_type, ZY_AXIS); update_all(cg); drawgraph(); } void autoscale_set(int gno, int setno, int axis) { } void wipeout(int ask) { if (ask && !yesno("Kill all graphs, sets, and annotation?", "", "YES", "NO")) { return; } kill_graph(maxgraph); do_clear_lines(); do_clear_boxes(); do_clear_text(); cg = 0; drawgraph(); } void update_all(int gno) { set_display_pixmaps(); /* also calls update_display_items() */ update_teanl_flow(); update_adcirc_flow(); update_draw(); update_graph_items(); update_world(gno); update_view(gno); /* update_status(gno, cur_statusitem, -1); update_label_proc(); update_editp_proc(gno, -1); */ update_ticks(gno); update_autos(gno); update_locator_items(gno); update_draw(); update_frame_items(gno); update_graph_items(); } int object_isactive(int obj, int w, int w2) { switch (obj) { case GRID: return grid[w].active == ON; case BOUNDARY: return bounds[w].active == ON; case TEANL: return flowf[w].active == ON; case ADCIRC: if (w == FLOW) { return ((flowt[w2].active == ON) && (flowt[w2].f != NULL) && (flowt[w2].f[0].u != NULL)); } else if (w == ELEV) { return (flowt[w2].active == ON && flowt[w2].f != NULL && flowt[w2].f[0].e != NULL); } case TRANSECT: return trans[w].active == ON; case ADCIRC3DFLOW: return adc3d[w].active == ON; case HISTORY: if (w == FLOW) { return flowh[w2].active == ON; } else { return hist[w2].active == ON; } case ELA: return elaconc[w].active == ON; case STATION: if (nsta > 0 && sta != NULL && w < nsta) { return sta[w].active == ON; } else { return 0; } case TIDESTATION: if (tidestat == NULL || tidestat[w] == NULL) { return 0; } return 1; case DROGUES: return drogues[w].active == ON; case TRACK: return track[w].active == ON; default: fprintf(stderr, "Object not found: %d\n", obj); return 0; } } int display_object(int gno, int obj, int w1, int w2, int w3) { switch (obj) { case GRID: if (w1 == GRID) { return g[gno].grid[w2].display != OFF; } if (w1 == BOUNDARY) { return g[gno].grid[w2].display_boundary != OFF; } break; case BATH: return g[gno].grid[w1].display_bath != OFF; case BOUNDARY: return g[gno].bounds[w1].display != OFF; case TEANL: if (w1 == ELEV) { return g[gno].flowf[w2].display_elev != OFF; } if (w1 == FLOW) { return g[gno].flowf[w2].display != OFF; } if (w1 == PHASE) { return g[gno].flowf[w2].display_phase != OFF; } if (w1 == AMP) { return g[gno].flowf[w2].display_amp != OFF; } if (w1 == MAG) { return g[gno].flowf[w2].display_mag != OFF; } if (w1 == MARKERS) { return g[gno].flowf[w2].display_elevmarkers != OFF; } if (w1 == WETDRY) { return g[gno].flowf[w2].display_inun != OFF; } break; case ADCIRC: if (w1 == ELEV && w2 == MAXP) { return g[gno].flowt[w3].display_maxelev != OFF; } if (w1 == ELEV && w2 == NODES) { return g[gno].flowt[w3].display_maxelevval != OFF; } if (w1 == ELEV) { return g[gno].flowt[w2].display_elev != OFF; } if (w1 == FLOW) { return g[gno].flowt[w2].display != OFF; } if (w1 == MAG) { return g[gno].flowt[w2].display_mag != OFF; } if (w1 == MARKERS) { return g[gno].flowt[w2].display_elevmarkers != OFF; } break; case ADCIRC3DFLOW: if (w1 == FLOW) { return g[gno].flow3d[w2].display != OFF; } break; case HISTORY: if (w1 == ELEV) { return g[gno].flowh[w2].display_elev != OFF; } else if (w1 == FLOW) { return g[gno].flowh[w2].display != OFF; } else if (w1 == MARKERS) { return g[gno].flowh[w2].display_elevmarkers != OFF; } else { return g[gno].hbox[w2].display != OFF; } case TRANSECT: return g[gno].trans[w1].display != OFF; case ELA: return g[gno].elaconc[w1].display != OFF; case STATION: if (nsta > 0 && sta != NULL && w1 < nsta) { return sta[w1].display != OFF; } else { return 0; } case TIDESTATION: if (tidestat == NULL || tidestat[w1] == NULL || g[gno].tidestat == NULL) { return 0; } return g[gno].tidestat[w1].display != OFF; case DROGUES: return g[gno].drogues[w1].display != OFF; case TRACK: return g[gno].track[w1].display != OFF; case SLICE: return g[gno].sbox[w1].display_slice != OFF || g[gno].sbox[w1].display_marker != OFF; case FLUX: return g[gno].fbox[w1].display_slice != OFF || g[gno].fbox[w1].display_marker != OFF; case ZOOM: return g[gno].zbox[w1].display != OFF || g[gno].zbox[w1].display_marker != OFF; case TIDALCLOCK: return g[gno].tidalclock.active == ON; case TIMEINFO: return g[gno].timeinfo.active == ON; case MAPSCALE: return g[gno].mapscale.active == ON; case VSCALE: return g[gno].vl.active == ON; case WSCALE: return g[gno].wl.active == ON; case FLOW: return g[gno].fl.active == ON; case TIMELINE: return g[gno].timeline.active == ON; default: break; } return 0; } void set_display_object(int gno, int obj, int w1, int w2, int w3) { /* g[gno].grid[i].display_boundary = OFF; g[gno].grid[i].display_nodes = OFF; g[gno].grid[i].display_elements = OFF; g[gno].grid[i].display_depths = OFF; g[gno].grid[i].display_courant = OFF; g[gno].grid[i].display_dimw = OFF; g[gno].grid[i].display_gridf = OFF; g[gno].grid[i].display_flags[EDIT_GRID_FILLED] = 0; g[gno].grid[i].display_flags[EDIT_GRID_NODE_NUMBERS] = 0; g[gno].grid[i].display_flags[EDIT_GRID_ELEMENT_NUMBERS] = 0; g[gno].grid[i].display_flags[EDIT_GRID_DEPTHS] = 0; } g[gno].grid[0].display_flags[EDIT_GRID_ISOLINES] = 1; */ switch (obj) { case GRID: g[gno].grid[w1].display = w2; g[gno].grid[w1].display_flags[EDIT_GRID] = (w2 == ON); break; case BATH: g[gno].grid[w1].display_bath = w2; g[gno].grid[w1].display_flags[EDIT_GRID_ISOLINES] = (w2 == ON); break; case BOUNDARY: g[gno].grid[w1].display_boundary = w2; g[gno].grid[w1].display_flags[EDIT_BOUNDARY] = (w2 == ON); break; } /* case TEANL: if (w1 == ELEV) { return g[gno].flowf[w2].display_elev != OFF; } if (w1 == FLOW) { return g[gno].flowf[w2].display != OFF; } if (w1 == PHASE) { return g[gno].flowf[w2].display_phase != OFF; } if (w1 == AMP) { return g[gno].flowf[w2].display_amp != OFF; } if (w1 == MARKERS) { return g[gno].flowf[w2].display_elevmarkers != OFF; } break; case ADCIRC: if (w1 == ELEV && w2 == MAXP) { return g[gno].flowt[w3].display_maxelev != OFF; } if (w1 == ELEV) { return g[gno].flowt[w2].display_elev != OFF; } if (w1 == FLOW) { return g[gno].flowt[w2].display != OFF; } if (w1 == MARKERS) { return g[gno].flowt[w2].display_elevmarkers != OFF; } break; case HISTORY: if (w1 == ELEV) { return g[gno].flowh[w2].display_elev != OFF; } if (w1 == FLOW) { return g[gno].flowh[w2].display != OFF; } if (w1 == MARKERS) { return g[gno].flowh[w2].display_elevmarkers != OFF; } break; case ELA: return g[gno].elaconc[w1].display != OFF; break; case STATION: return stations[w1].display != OFF; break; case FISH: return fishes[w1].display != OFF; break; case DROGUES: return g[gno].drogues[w1].display != OFF; break; case SLICE: return g[gno].sbox[w1].display_slice != OFF || g[gno].sbox[w1].display_marker != OFF; break; case FLUX: return g[gno].fbox[w1].display_slice != OFF || g[gno].fbox[w1].display_marker != OFF; break; case ZOOM: return g[gno].zbox[w1].display != OFF || g[gno].zbox[w1].display_marker != OFF; break; case TIDALCLOCK: return g[gno].tidalclock.active == ON; break; case MAPSCALE: return g[gno].mapscale.active == ON; break; case VSCALE: return g[gno].vl.active == ON; break; case TIMELINE: return g[gno].timeline.active == ON; break; default: return 0; break; } */ } void page(double p, int dir) { int restart = 0; double dx = scrollper * (g[cg].w.xg2 - g[cg].w.xg1); double dy = scrollper * (g[cg].w.yg2 - g[cg].w.yg1); if (isrunning()) { restart = 1; setistop(); } switch (dir) { case 0: g[cg].w.xg1 += dx; g[cg].w.xg2 += dx; break; case 1: g[cg].w.xg1 -= dx; g[cg].w.xg2 -= dx; break; case 2: g[cg].w.yg1 += dy; g[cg].w.yg2 += dy; break; case 3: g[cg].w.yg1 -= dy; g[cg].w.yg2 -= dy; break; case 4: dx = shexper * (g[cg].w.xg2 - g[cg].w.xg1) / 2.0; dy = shexper * (g[cg].w.yg2 - g[cg].w.yg1) / 2.0; g[cg].w.xg1 += dx; g[cg].w.xg2 -= dx; g[cg].w.yg1 += dy; g[cg].w.yg2 -= dy; break; case 5: dx = shexper * (g[cg].w.xg2 - g[cg].w.xg1); dy = shexper * (g[cg].w.yg2 - g[cg].w.yg1); g[cg].w.xg1 -= dx; g[cg].w.xg2 += dx; g[cg].w.yg1 -= dy; g[cg].w.yg2 += dy; break; } set_up_world(cg); if (!no_display) { setredraw_world(); } if (restart) { setirun(); } } int check_err = 0; #define MAX_FONT 10 #define MAX_JUST 2 #define MAX_ARROW 3 #define MAX_PATTERN 30 #define MAX_PREC 10 int checkon(int prop, int old_val, int new_val) { char buf[256]; int retval = old_val; check_err = 0; switch (prop) { case LINEWIDTH: if (new_val >= 0 && new_val <= MAX_LINEWIDTH) { retval = new_val; } else { sprintf(buf, "LINEWIDTH out of bounds, should be from 0 to %d", MAX_LINEWIDTH); check_err = 1; } break; case LINESTYLE: if (new_val >= 0 && new_val <= MAX_LINESTYLE) { retval = new_val; } else { sprintf(buf, "LINESTYLE out of bounds, should be from 0 to %d", MAX_LINESTYLE); check_err = 1; } break; case COLOR: /* TODO use MAX_COLOR */ if (new_val >= 0 && new_val < 16) { retval = new_val; } else { sprintf(buf, "COLOR out of bounds, should be from 0 to %d", 16 - 1); check_err = 1; } break; case JUST: if (new_val >= 0 && new_val <= MAX_JUST) { retval = new_val; } else { sprintf(buf, "JUST out of bounds, should be from 0 to %d", MAX_JUST); check_err = 1; } break; case FONTP: if (new_val >= 0 && new_val < MAX_FONT) { retval = new_val; } else { sprintf(buf, "FONT out of bounds, should be from 0 to %d", MAX_FONT - 1); check_err = 1; } break; case ARROW: if (new_val >= 0 && new_val <= MAX_ARROW) { retval = new_val; } else { sprintf(buf, "ARROW out of bounds, should be from 0 to %d", MAX_ARROW); check_err = 1; } break; case PATTERN: if (new_val >= 0 && new_val < MAX_PATTERN) { retval = new_val; } else { sprintf(buf, "PATTERN out of bounds, should be from 0 to %d", MAX_PATTERN - 1); check_err = 1; } break; case SYMBOL: if (new_val >= 0 && new_val < MAXSYM) { retval = new_val; } else { sprintf(buf, "SYMBOL out of bounds, should be from 0 to %d", MAXSYM - 1); check_err = 1; } break; case PREC: if (new_val >= 0 && new_val < MAX_PREC) { retval = new_val; } else { sprintf(buf, "PREC out of bounds, should be from 0 to %d", MAX_PREC - 1); check_err = 1; } break; } if (check_err) { errwin(buf); } return retval; }