/* PN static */ void drawlingrid(GRAPH *graph, char *units, int spacing, int nsp, double dst, double lmt, double hmt, bool onedec, int mult, double mag, int digits, Axis axis) { int i, j; double m, step; char buf[LABEL_CHARS]; /* i counts how many pixels we have drawn, and j counts which unit * we are at. */ SetLinestyle(1); step = floor((double) dst / nsp * 100.0 + 0.000001); for (i = 0, m = lmt * 100.0; m - 0.001 <= hmt * 100.0; i += spacing, m += step) { j = m; if (j == 0) SetLinestyle(0); if (graph->grid.gridtype != GRID_NONE) { if (axis == x_axis) DrawLine(graph->viewportxoff + i, graph->viewportyoff, graph->viewportxoff + i, graph->viewport.height + graph->viewportyoff); else DrawLine(graph->viewportxoff, graph->viewportyoff + i, graph->viewport.width + graph->viewportxoff, graph->viewportyoff + i); } if (j == 0) SetLinestyle(1); (void) sprintf(buf, "%.*f", digits + 1, m * mag / 100.0); if (axis == x_axis) Text(buf, graph->viewportxoff + i - strlen(buf) / 2 * graph->fontwidth, (int) (graph->fontheight * 2.5)); else Text(buf, graph->viewportxoff - graph->fontwidth * (strlen(buf)), graph->viewportyoff + i - graph->fontheight / 2); /* This is to make sure things work when delta > hi - lo. */ if (nsp == 1) j += 1000; } if (axis == x_axis) Text(units, (int) (graph->absolute.width * 0.6), graph->fontheight); else Text(units, graph->fontwidth, (int) (graph->absolute.height - 2 * graph->fontheight)); Update(); }
/* PN static */ void drawlegend(GRAPH *graph, int plotno, struct dvec *dv) { int x, y, i; char buf[16]; x = ((plotno % 2) ? graph->viewportxoff : ((graph->viewport.width) / 2)); y = graph->absolute.height - graph->fontheight - ((plotno + 2) / 2) * (graph->fontheight); i = y + graph->fontheight / 2 + 1; SetColor(dv->v_color); if (graph->plottype == PLOT_POINT) { (void) sprintf(buf, "%c : ", dv->v_linestyle); DevDrawText(buf, x + graph->viewport.width / 20 - 3 * graph->fontwidth, y, 0); } else { SetLinestyle(dv->v_linestyle); DevDrawLine(x, i, x + graph->viewport.width / 20, i); } SetColor(1); DevDrawText(dv->v_name, x + graph->viewport.width / 20 + graph->fontwidth, y, 0); }
void DrawXTicks(Graph *graph) { int sx1, sy1; int sx2, sy2; int i; float yint; float val; float scale; int tmp; int axisx; int j; if (graph->xaxis_desired_nticks == 0) { graph->xaxis_nticks = 1; return; } /* * Get the screen coordinates of the axis. */ SetColor(graph->foreground); yint = graph->xaxis_yintcpt; ScreenTransform(graph, graph->wxmin, yint, &sx1, &sy1); ScreenTransform(graph, graph->wxmax, yint, &sx2, &sy2); scale = 1.0 / pow((double) 10.0, (double) graph->xaxis_exponent); ScreenTransform(graph, graph->yaxis_xintcpt, 0.0, &axisx, &tmp); for (i = 0; i < graph->xaxis_nticks; i++) { for (j = 0; j < graph->xaxis_nsubticks + 1; j++) { val = i * graph->xaxis_tickinc + graph->xaxis_tickstart + j * graph->xaxis_tickinc / (graph->xaxis_nsubticks + 1); ScreenTransform(graph, val, graph->xaxis_yintcpt, &sx1, &sy1); /* * Either draw a grid or just tick marks at the tick intervals. */ if (graph->show_xgrid) { SetColor(graph->gridcolor); SetLinestyle((BasicWindow *)graph, 1); DrawLine(sx1, 0, sx1, graph->wheight); SetLinestyle((BasicWindow *)graph, 0); SetColor(graph->foreground); } if (!(graph->quadrants & 0x1) && !(graph->quadrants & 0x4)) continue; /* * Check for quadrants I. */ if (!(graph->quadrants & 0x1) && sx1 > axisx) continue; /* * Check for quadrants III. */ if (!(graph->quadrants & 0x4) && sx1 < axisx) continue; if (j == 0) { DrawLine(sx1, sy1 - graph->ticksize, sx1, sy2 + graph->ticksize); /* * label the ticks */ if (graph->show_xlabels) { DrawXTickLabel(graph, sx1, sy1, val, scale, graph->xaxis_leftdp, graph->xaxis_rightdp); } } else { DrawLine(sx1, sy1 - (int) (0.5 * graph->ticksize), sx1, sy2 + (int) (0.5 * graph->ticksize)); } } } }
void DrawYTicks(Graph *graph) { int sx1, sy1; int sx2, sy2; int i; float xint; float val; float scale; int tmp; int axisy; int j; if (graph->yaxis_desired_nticks == 0) { graph->yaxis_nticks = 1; return; } /* * Get the screen coordinates of the axis. */ SetColor(graph->foreground); xint = graph->yaxis_xintcpt; ScreenTransform(graph, xint, graph->wymin, &sx1, &sy1); ScreenTransform(graph, xint, graph->wymax, &sx2, &sy2); /* * Get the axis exponent. */ scale = 1.0 / pow((double) 10.0, (double) graph->yaxis_exponent); ScreenTransform(graph, 0.0, graph->xaxis_yintcpt, &tmp, &axisy); /* * Loop over all the tick marks. */ for (i = 0; i < graph->yaxis_nticks; i++) { for (j = 0; j < graph->yaxis_nsubticks + 1; j++) { /* * Get the actual value of the tick. */ val = i * graph->yaxis_tickinc + graph->yaxis_tickstart + j * graph->yaxis_tickinc / (graph->yaxis_nsubticks + 1); /* * Locate its screen position in the window. */ ScreenTransform(graph, graph->yaxis_xintcpt, val, &sx1, &sy1); /* * Either draw a grid or just tick marks at the tick intervals. */ if (graph->show_ygrid) { SetColor(graph->gridcolor); SetLinestyle((BasicWindow *)graph, 1); DrawLine(0, sy1, graph->wwidth, sy1); SetLinestyle((BasicWindow *)graph, 0); SetColor(graph->foreground); } if (!(graph->quadrants & 0x2) && !(graph->quadrants & 0x8)) continue; /* * Check for quadrants II. */ if (!(graph->quadrants & 0x2) && sy1 < axisy) continue; /* * Check for quadrants IV. */ if (!(graph->quadrants & 0x8) && sy1 > axisy) continue; if (j == 0) { DrawLine(sx1 - graph->ticksize, sy1, sx2 + graph->ticksize, sy1); /* * Label the ticks. */ if (graph->show_ylabels) { DrawYTickLabel(graph, sx1, sy1, val, scale, graph->yaxis_leftdp, graph->yaxis_rightdp); } } else { DrawLine(sx1 - (int) (0.5 * graph->ticksize), sy1, sx2 + (int) (0.5 * graph->ticksize), sy1); } } } }
/* * Add a point to the curve we're currently drawing. * Should be in between a gr_init() and a gr_end() * expect when iplotting, very bad hack * Differences from old gr_point: * We save points here, instead of in lower levels. * Assume we are in right context * Save points in data space (not screen space). * We pass two points in so we can multiplex plots. * */ void gr_point(struct dvec *dv, double newx, double newy, double oldx, double oldy, int np) { int oldtox, oldtoy; /* value before clipping */ char pointc[2]; int fromx, fromy, tox, toy; int ymin, dummy; DatatoScreen(currentgraph, oldx, oldy, &fromx, &fromy); DatatoScreen(currentgraph, newx, newy, &tox, &toy); /* note: we do not particularly want to clip here */ oldtox = tox; oldtoy = toy; if (!currentgraph->grid.circular) { if (clip_line(&fromx, &fromy, &tox, &toy, currentgraph->viewportxoff, currentgraph->viewportyoff, currentgraph->viewport.width + currentgraph->viewportxoff, currentgraph->viewport.height + currentgraph->viewportyoff)) return; } else { if (clip_to_circle(&fromx, &fromy, &tox, &toy, currentgraph->grid.xaxis.circular.center, currentgraph->grid.yaxis.circular.center, currentgraph->grid.xaxis.circular.radius)) return; } if (currentgraph->plottype != PLOT_POINT) { SetLinestyle(dv->v_linestyle); } else { /* if PLOT_POINT, don't want to plot an endpoint which have been clipped */ if (tox != oldtox || toy != oldtoy) return; } SetColor(dv->v_color); switch (currentgraph->plottype) { double *tics; case PLOT_LIN: case PLOT_MONOLIN: /* If it's a linear plot, ignore first point since we don't want to connect with oldx and oldy. */ if (np) DevDrawLine(fromx, fromy, tox, toy); if ((tics = currentgraph->ticdata) != NULL) { for (; *tics < HUGE; tics++) if (*tics == (double) np) { DevDrawText("x", (int) (tox - currentgraph->fontwidth / 2), (int) (toy - currentgraph->fontheight / 2), 0); /* gr_redraw will redraw this w/o our having to save it Guenther Roehrich 22-Jan-99 */ /* SaveText(currentgraph, "x", (int) (tox - currentgraph->fontwidth / 2), (int) (toy - currentgraph->fontheight / 2)); */ break; } } else if ((currentgraph->ticmarks >0) && (np > 0) && (np % currentgraph->ticmarks == 0)) { /* Draw an 'x' */ DevDrawText("x", (int) (tox - currentgraph->fontwidth / 2), (int) (toy - currentgraph->fontheight / 2), 0); /* gr_redraw will redraw this w/o our having to save it Guenther Roehrich 22-Jan-99 */ /* SaveText(currentgraph, "x", (int) (tox - currentgraph->fontwidth / 2), (int) (toy - currentgraph->fontheight / 2)); */ } break; case PLOT_COMB: DatatoScreen(currentgraph, 0.0, currentgraph->datawindow.ymin, &dummy, &ymin); DevDrawLine(tox, ymin, tox, toy); break; case PLOT_POINT: /* Here, gi_linestyle is the character used for the point. */ pointc[0] = (char) dv->v_linestyle; pointc[1] = '\0'; DevDrawText(pointc, (int) (tox - currentgraph->fontwidth / 2), (int) (toy - currentgraph->fontheight / 2), 0); default: break; } }
static void drawpolargrid(GRAPH *graph) { double tenpowmag, theta; int hmt, lmt, i, step, mag; int relcx, relcy, relrad, dist, degs; int x1, y1, x2, y2; double minrad, maxrad, pixperunit; char buf[64]; hmt = graph->grid.xaxis.circular.hmt; lmt = graph->grid.xaxis.circular.lmt; mag = graph->grid.xaxis.circular.mag; tenpowmag = pow(10.0, (double) mag); maxrad = hmt * tenpowmag; minrad = lmt * tenpowmag; if ((minrad == 0) && ((hmt - lmt) > 5)) { if (!((hmt - lmt) % 2)) step = 2; else if (!((hmt - lmt) % 3)) step = 3; else step = 1; } else step = 1; pixperunit = graph->grid.xaxis.circular.radius * 2 / (graph->datawindow.xmax - graph->datawindow.xmin); relcx = - (graph->datawindow.xmin + graph->datawindow.xmax) / 2 * pixperunit; relcy = - (graph->datawindow.ymin + graph->datawindow.ymax) / 2 * pixperunit; /* The distance from the center of the plotting area to the center of * the logical area. */ dist = sqrt((double) (relcx * relcx + relcy * relcy)); SetLinestyle(0); Arc(graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center, graph->grid.xaxis.circular.radius, (double) 0.0, (double) 0.0); SetLinestyle(1); /* Now draw the circles. */ for (i = lmt; (relrad = i * tenpowmag * pixperunit) <= dist + graph->grid.xaxis.circular.radius; i += step) { cliparc((double) graph->grid.xaxis.circular.center + relcx, (double) graph->grid.yaxis.circular.center + relcy, (double) relrad, 0.0, 0.0, graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center, graph->grid.xaxis.circular.radius, 0); /* Toss on the label */ if (relcx || relcy) theta = atan2((double) relcy, (double) relcx); else theta = M_PI; if (i && (relrad > dist - graph->grid.xaxis.circular.radius)) addradlabel(graph, i, theta, (int) (graph->grid.xaxis.circular.center - (relrad - dist) * cos(theta)), (int) (graph->grid.yaxis.circular.center - (relrad - dist) * sin(theta))); } /* Now draw the spokes. We have two possible cases -- first, the * origin may be inside the area -- in this case draw 12 spokes. * Otherwise, draw several spokes at convenient places. */ if ((graph->datawindow.xmin <= 0.0) && (graph->datawindow.xmax >= 0.0) && (graph->datawindow.ymin <= 0.0) && (graph->datawindow.ymax >= 0.0)) { for (i = 0; i < 12; i++) { x1 = graph->grid.xaxis.circular.center + relcx; y1 = graph->grid.yaxis.circular.center + relcy; x2 = x1 + graph->grid.xaxis.circular.radius * 2 * cos(i * M_PI / 6); y2 = y1 + graph->grid.xaxis.circular.radius * 2 * sin(i * M_PI / 6); if (!clip_to_circle(&x1, &y1, &x2, &y2, graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center, graph->grid.xaxis.circular.radius)) { DrawLine(x1, y1, x2, y2); /* Add a label here */ /*XXXX*/ adddeglabel(graph, i * 30, x2, y2, x1, y1, graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center); } } } else { /* Figure out the angle that we have to fill up */ theta = 2 * asin((double) graph->grid.xaxis.circular.radius / dist); theta = theta * 180 / M_PI; /* Convert to degrees. */ /* See if we should put lines at 30, 15, 5, or 1 degree * increments. */ if (theta / 30 > 3) degs = 30; else if (theta / 15 > 3) degs = 15; else if (theta / 5 > 3) degs = 5; else degs = 1; /* We'll be cheap */ for (i = 0; i < 360; i+= degs) { x1 = graph->grid.xaxis.circular.center + relcx; y1 = graph->grid.yaxis.circular.center + relcy; x2 = x1 + dist * 2 * cos(i * M_PI / 180); y2 = y1 + dist * 2 * sin(i * M_PI / 180); if (!clip_to_circle(&x1, &y1, &x2, &y2, graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center, graph->grid.xaxis.circular.radius)) { DrawLine(x1, y1, x2, y2); /* Put on the label */ adddeglabel(graph, i, x2, y2, x1, y1, graph->grid.xaxis.circular.center, graph->grid.yaxis.circular.center); } } } (void) sprintf(buf, "e%d", mag); Text(buf, graph->grid.xaxis.circular.center + graph->grid.xaxis.circular.radius, graph->grid.yaxis.circular.center - graph->grid.xaxis.circular.radius); Update(); return; }
/* PN static */ void drawloggrid(GRAPH *graph, char *units, int hmt, int lmt, int decsp, int subs, int pp, Axis axis) { int i, j, k, m; double t; char buf[LABEL_CHARS]; /* Now plot every pp'th decade line, with subs lines between them. */ if (subs > 1) SetLinestyle(0); for (i = 0, j = lmt; j <= hmt; i += decsp * pp, j += pp) { /* Draw the decade line */ if (graph->grid.gridtype != GRID_NONE) { if (axis == x_axis) DrawLine(graph->viewportxoff + i, graph->viewportyoff, graph->viewportxoff + i, graph->viewport.height +graph->viewportyoff); else DrawLine(graph->viewportxoff, graph->viewportyoff + i, graph->viewport.width + graph->viewportxoff, graph->viewportyoff + i); } if (j == -2) (void) sprintf(buf, "0.01"); else if (j == -1) (void) sprintf(buf, "0.1"); else if (j == 0) (void) sprintf(buf, "1"); else if (j == 1) (void) sprintf(buf, "10"); else if (j == 2) (void) sprintf(buf, "100"); else (void) sprintf(buf, "10^%d", j); if (axis == x_axis) Text(buf, graph->viewportxoff + i - strlen(buf) / 2, (int) (graph->fontheight * 2.5)); else Text(buf, graph->viewportxoff - graph->fontwidth * (strlen(buf) + 1), graph->viewportyoff + i - graph->fontheight / 2); if (j >= hmt) break; /* Now draw the subdivision lines */ if (subs > 1) { SetLinestyle(1); t = 10.0 / subs; for (k = ceil(subs / 10.0) + 1; k < subs; k++) { m = i + decsp * log10((double) t * k); if (graph->grid.gridtype != GRID_NONE) { if (axis == x_axis) DrawLine(graph->viewportxoff + m, graph->viewportyoff, graph->viewportxoff + m, graph->viewport.height + graph->viewportyoff); else DrawLine(graph->viewportxoff, graph->viewportyoff + m, graph->viewport.width + graph->viewportxoff, graph->viewportyoff + m); } } SetLinestyle(0); } } if (axis == x_axis) Text(units, (int) (graph->absolute.width * 0.6), graph->fontheight); else Text(units, graph->fontwidth, (int) (graph->absolute.height - 2 * graph->fontheight)); Update(); }
void gr_fixgrid(GRAPH *graph, double xdelta, double ydelta, int xtype, int ytype) { double *dd; if (graph->grid.gridtype == GRID_NONE) { graph->grid.gridtype = GRID_LIN; } SetColor(1); SetLinestyle(1); if ((graph->data.xmin > graph->data.xmax) || (graph->data.ymin > graph->data.ymax)) { fprintf(cp_err, "gr_fixgrid: Internal Error - bad limits: %g, %g, %g, %g\r\n", graph->data.xmin, graph->data.xmax, graph->data.ymin, graph->data.ymax); return; } if (graph->grid.gridtype == GRID_POLAR) { graph->grid.circular = TRUE; polargrid(graph); return; } else if (graph->grid.gridtype == GRID_SMITH || graph->grid.gridtype == GRID_SMITHGRID) { graph->grid.circular = TRUE; smithgrid(graph); return; } graph->grid.circular = FALSE; if ((graph->grid.gridtype == GRID_YLOG) || (graph->grid.gridtype == GRID_LOGLOG)) dd = loggrid(graph, graph->data.ymin, graph->data.ymax, ytype, y_axis); else dd = lingrid(graph, graph->data.ymin, graph->data.ymax, ydelta, ytype, y_axis); graph->datawindow.ymin = dd[0]; graph->datawindow.ymax = dd[1]; if ((graph->grid.gridtype == GRID_XLOG) || (graph->grid.gridtype == GRID_LOGLOG)) dd = loggrid(graph, graph->data.xmin, graph->data.xmax, xtype, x_axis); else dd = lingrid(graph, graph->data.xmin, graph->data.xmax, xdelta, xtype, x_axis); graph->datawindow.xmin = dd[0]; graph->datawindow.xmax = dd[1]; /* do we really need this? */ /* SetLinestyle(0); DrawLine(graph->viewportxoff, graph->viewportyoff, graph->viewport.width + graph->viewportxoff, graph->viewportyoff); DrawLine(graph->viewportxoff, graph->viewportyoff, graph->viewportxoff, graph->viewport.height + graph->viewportyoff); SetLinestyle(1); */ return; }
void gr_redrawgrid(GRAPH *graph) { SetColor(1); SetLinestyle(1); /* draw labels */ if (graph->grid.xlabel) { Text(graph->grid.xlabel, (int) (graph->absolute.width * 0.35), graph->fontheight); } if (graph->grid.ylabel) { if (graph->grid.gridtype == GRID_POLAR || graph->grid.gridtype == GRID_SMITH || graph->grid.gridtype == GRID_SMITHGRID) { Text(graph->grid.ylabel, graph->fontwidth, (graph->absolute.height * 3) / 4 ); } else { Text(graph->grid.ylabel, graph->fontwidth, graph->absolute.height / 2 ); } } switch( graph->grid.gridtype ) { case GRID_POLAR: drawpolargrid(graph); break; case GRID_SMITH: drawsmithgrid(graph); break; case GRID_SMITHGRID: drawsmithgrid(graph); break; case GRID_XLOG: case GRID_LOGLOG: drawloggrid(graph, graph->grid.xaxis.log.units, graph->grid.xaxis.log.hmt, graph->grid.xaxis.log.lmt, graph->grid.xaxis.log.decsp, graph->grid.xaxis.log.subs, graph->grid.xaxis.log.pp, x_axis); break; default: drawlingrid(graph, graph->grid.xaxis.lin.units, graph->grid.xaxis.lin.spacing, graph->grid.xaxis.lin.numspace, graph->grid.xaxis.lin.distance, graph->grid.xaxis.lin.lowlimit, graph->grid.xaxis.lin.highlimit, graph->grid.xaxis.lin.onedec, graph->grid.xaxis.lin.mult, graph->grid.xaxis.lin.tenpowmag / graph->grid.xaxis.lin.tenpowmagx, graph->grid.xaxis.lin.digits, x_axis); break; } switch( graph->grid.gridtype ) { case GRID_POLAR: case GRID_SMITH: case GRID_SMITHGRID: break; case GRID_YLOG: case GRID_LOGLOG: drawloggrid(graph, graph->grid.yaxis.log.units, graph->grid.yaxis.log.hmt, graph->grid.yaxis.log.lmt, graph->grid.yaxis.log.decsp, graph->grid.yaxis.log.subs, graph->grid.yaxis.log.pp, y_axis); break; default: drawlingrid(graph, graph->grid.yaxis.lin.units, graph->grid.yaxis.lin.spacing, graph->grid.yaxis.lin.numspace, graph->grid.yaxis.lin.distance, graph->grid.yaxis.lin.lowlimit, graph->grid.yaxis.lin.highlimit, graph->grid.yaxis.lin.onedec, graph->grid.yaxis.lin.mult, graph->grid.yaxis.lin.tenpowmag / graph->grid.yaxis.lin.tenpowmagx, graph->grid.yaxis.lin.digits, y_axis); break; } }
static void drawsmithgrid(GRAPH *graph) { double mx, my, tenpowmag, d, dphi[CMAX], minrad, maxrad, rnorm[CMAX]; double pixperunit; int mag, i = 0, j = 0, k; double ir[CMAX], rr[CMAX], ki[CMAX], kr[CMAX], ks[CMAX]; int xoff, yoff, zheight; int basemag, plen; char buf[64], plab[32], nlab[32]; /* Figure out the minimum and maximum radii we're dealing with. */ mx = (graph->datawindow.xmin + graph->datawindow.xmax) / 2; my = (graph->datawindow.ymin + graph->datawindow.ymax) / 2; d = sqrt(mx * mx + my * my); maxrad = d + (graph->datawindow.xmax - graph->datawindow.xmin) / 2; minrad = d - (graph->datawindow.xmax - graph->datawindow.xmin) / 2; mag = floor(mylog10(maxrad)); tenpowmag = pow(10.0, (double) mag); pixperunit = graph->viewport.width / (graph->datawindow.xmax - graph->datawindow.xmin); xoff = - pixperunit * (graph->datawindow.xmin + graph->datawindow.xmax) / 2; yoff = - pixperunit * (graph->datawindow.ymin + graph->datawindow.ymax) / 2; /* Sweep the range from 10e-20 to 10e20. If any arcs fall into the * picture, plot the arc set. */ for (mag = -20; mag < 20; mag++) { i = gr_radius * pow(10.0, (double) mag) / maxrad; if (i > 10) { j = 1; break; } else if (i > 5) { j = 2; break; } else if (i > 2) { j = 5; break; } } k = 1; /* SetLinestyle(1); takes too long */ /* Problems with Suns on very large radii && linestyle */ SetLinestyle(0); /* Now plot all the arc sets. Go as high as 5 times the radius that * will fit on the screen. The base magnitude is one more than * the least magnitude that will fit... */ if (i > 20) basemag = mag; else basemag = mag + 1; /* Go back one order of magnitude and have a closer look */ mag -= 2; j *= 10; while (mag < 20) { i = j * pow(10.0, (double) mag) * pixperunit / 2; if (i / 5 > gr_radius + ((xoff > 0) ? xoff : - xoff)) break; rnorm[k] = j * pow(10.0, (double) (mag - basemag)); dphi[k] = 2.0 * atan(rnorm[k]); ir[k] = pixperunit * (1 + cos(dphi[k])) / sin(dphi[k]); rr[k] = pixperunit * 0.5 * (((1 - rnorm[k]) / (1 + rnorm[k])) + 1); (void) sprintf(plab, "%g", rnorm[k]); plen = strlen(plab); /* See if the label will fit on the upper xaxis */ /* wait for some k, so we don't get fooled */ if (k > 6) { if ((int) (gr_radius - xoff - pixperunit + 2 * rr[k]) < plen * gi_fntwidth + 2) break; } /* See if the label will fit on the lower xaxis */ /* First look at the leftmost circle possible*/ if ((int) (pixperunit - 2 * rr[k] + gr_radius + xoff + fabs((double) yoff)) < plen * gi_fntwidth + 4) { if (j == 95) { j = 10; mag++; } else { if (j < 20) j += 1; else j += 5; } continue; } /* Then look at the circles following in the viewport */ if (k>1 && (int) 2 * (rr[k-1] - rr[k]) < plen * gi_fntwidth + 4) { if (j == 95) { j = 10; mag++; } else { if (j < 20) j += 1; else j += 5; } continue; } if (j == 95) { j = 10; mag++; } else { if (j < 20) j += 1; else j += 5; } ki[k-1] = ir[k]; kr[k-1] = rr[k]; k++; if (k == CMAX) { printf("drawsmithgrid: grid too complex\n"); break; } } k--; /* Now adjust the clipping radii */ for (i = 0; i < k; i++) ks[i] = ki[i]; for (i = k-1, j = k-1; i >= 0; i -= 2, j--) { ki[i] = ks[j]; if (i > 0) ki[i-1] = ks[j]; } for (i = 0; i < k; i++) ks[i] = kr[i]; for (i = k-1, j = k-1; (i >= 0) && (dphi[i] > M_PI / 2); i -= 2, j--) { kr[i] = ks[j]; if (i > 0) kr[i-1] = ks[j]; } for ( ; i >= 0; i--, j--) kr[i] = ks[j]; if ((yoff > - gr_radius) && (yoff < gr_radius)) { zheight = gr_radius * cos(asin((double) yoff / gr_radius)); zheight = (zheight > 0) ? zheight : - zheight; } else { zheight = gr_radius; } for (ki[k] = kr[k] = (double) 0; k > 0; k--) { (void) sprintf(plab, "%g", rnorm[k]); (void) sprintf(nlab, "-%g", rnorm[k]); arcset(graph, rr[k], kr[k], ir[k], ki[k], pixperunit, gr_radius, gr_xcenter, gr_ycenter, xoff, yoff, plab, nlab, (int) (0.5 + RAD_TO_DEG * (M_PI - dphi[k])), (int) (0.5 + RAD_TO_DEG * (M_PI + dphi[k])), gr_xcenter - zheight, gr_xcenter + zheight); } if (mag == 20) { fprintf(cp_err, "smithgrid: Internal Error: screwed up\n"); return; } SetLinestyle(0); Arc(gr_xcenter, gr_ycenter, gr_radius, 0.0, 0.0); /* if ((xoff > - gr_radius) && (xoff < gr_radius)) { zheight = gr_radius * sin(acos((double) xoff / gr_radius)); if (zheight < 0) zheight = - zheight; DrawLine(gr_xcenter + xoff, gr_ycenter - zheight, gr_xcenter + xoff, gr_ycenter + zheight); } */ if ((yoff > - gr_radius) && (yoff < gr_radius)) { zheight = gr_radius * cos(asin((double) yoff / gr_radius)); if (zheight < 0) zheight = - zheight; DrawLine(gr_xcenter - zheight, gr_ycenter + yoff, gr_xcenter + zheight, gr_ycenter + yoff); Text("0", gr_xcenter + zheight + gi_fntwidth, gr_ycenter + yoff - gi_fntheight / 2); Text("o", gr_xcenter + zheight + gi_fntwidth * 2, gr_ycenter + yoff); Text("180", gr_xcenter - zheight - gi_fntwidth * 5, gr_ycenter + yoff - gi_fntheight / 2); Text("o", gr_xcenter - zheight - gi_fntwidth * 2, gr_ycenter + yoff); } /* (void) sprintf(buf, "e%d", basemag); */ (void) sprintf(buf, "e%d", 0); Text(buf, gr_xcenter + gr_radius, gr_ycenter - gr_radius); Update(); return; }
static void smithgrid(GRAPH *graph) { double mx, my; bool centered = FALSE; SetLinestyle(0); /* Make sure that our area is square. */ if (graph->viewport.width > graph->viewport.height) { graph->viewport.width = graph->viewport.height; } else { graph->viewport.height = graph->viewport.width; } /* Make sure that the borders are even */ if (graph->viewport.width & 1) { graph->viewport.width += 1; graph->viewport.height += 1; } graph->grid.xaxis.circular.center = graph->viewport.width / 2 + graph->viewportxoff; graph->grid.yaxis.circular.center = graph->viewport.height / 2 + graph->viewportyoff; graph->grid.xaxis.circular.radius = graph->viewport.width / 2; /* We have to make sure that the range is square. */ graph->datawindow.xmin = graph->data.xmin; graph->datawindow.xmax = graph->data.xmax; graph->datawindow.ymin = graph->data.ymin; graph->datawindow.ymax = graph->data.ymax; if (graph->datawindow.ymin > 0) graph->datawindow.ymin *= -1; if (graph->datawindow.xmin > 0) graph->datawindow.xmin *= -1; if (graph->datawindow.ymax < 0) graph->datawindow.ymax *= -1; if (graph->datawindow.xmax < 0) graph->datawindow.xmax *= -1; if (fabs(graph->datawindow.ymin) > fabs(graph->datawindow.ymax)) graph->datawindow.ymax = - graph->datawindow.ymin; else graph->datawindow.ymin = - graph->datawindow.ymax; if (fabs(graph->datawindow.xmin) > fabs(graph->datawindow.xmax)) graph->datawindow.xmax = - graph->datawindow.xmin; else graph->datawindow.xmin = - graph->datawindow.xmax; mx = graph->datawindow.xmax - graph->datawindow.xmin; my = graph->datawindow.ymax - graph->datawindow.ymin; if (mx > my) { graph->datawindow.ymin -= (mx - my) / 2; graph->datawindow.ymax += (mx - my) / 2; } else if (mx < my) { graph->datawindow.xmin -= (my - mx) / 2; graph->datawindow.xmax += (my - mx) / 2; } if ((graph->datawindow.xmin == - graph->datawindow.xmax) && (graph->datawindow.ymin == - graph->datawindow.ymax) && (graph->datawindow.xmin == graph->datawindow.ymin)) centered = TRUE; /* Issue a warning if our data range is not normalized */ if (graph->datawindow.ymax > 1.1) { printf("\nwarning: exceeding range for smith chart"); printf("\nplease normalize your data to -1 < r < +1\n"); } }