📄 grid.c
字号:
/* This is kind of wierd. If dist = 0, then this is the normal case, where * the labels should go along the positive X-axis. Otherwise, to make * sure that all circles drawn have labels, put the label near the circle * along the line from the logical center to the physical center. */voidaddradlabel(lab, theta, x, y) double theta; int lab, x, y;{ char buf[32]; (void) sprintf(buf, "%d", lab); if (theta == PI) { y = y - graph->fontheight - 2; x = x - graph->fontwidth * strlen(buf) - 3; } Text(buf, x, y); return;}#endif/* ... and smith charts. */static voidsmithgrid(){#ifdef notdef double mx, my, rad, tenpowmag, d, minrad, maxrad; double pixperunit; int relcx, relcy; int mt, mag, i, j, k, sp, xoff, yoff, zheight; int basemag; char buf[64], plab[32], nlab[32]; bool centered = false; gi_resetcolor(2, "Coral"); gi_resetcolor(3, "MediumAquamarine"); gi_setlinestyle(0); gi_maxx -= 2 * gi_fntwidth; gi_maxy -= 2 * gi_fntheight; /* Make sure that our area is square, etc. */ if ((gi_maxx - gr_xmargin) > (gi_maxy - gr_ymargin)) { i = (gi_maxx - gr_xmargin - gi_maxy + gr_ymargin) / 2; gi_maxx -= i; gr_xmargin += i; } else { i = (gi_maxy - gr_ymargin - gi_maxx + gr_xmargin) / 2; gi_maxy -= i; gr_ymargin += i; } gr_xcenter = (gi_maxx + gr_xmargin) / 2; gr_ycenter = (gi_maxy + gr_ymargin) / 2; gr_radius = (gi_maxx - gr_xmargin) / 2; /* We don't handle cases where the range isn't centered about the * X-axis. This is something that has to be fixed... */ if (fabs(graph->datawindow.ymin) > fabs(graph->datawindow.ymax)) graph->datawindow.ymax = - graph->datawindow.ymin; else graph->datawindow.ymin = - graph->datawindow.ymax; /* What a hassle. */ graph->datawindow.xmin *= sqrt(2.0); graph->datawindow.xmax *= sqrt(2.0); graph->datawindow.ymin *= sqrt(2.0); graph->datawindow.ymax *= sqrt(2.0); /* We have to make sure that the range is square... */ 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; /* 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 = gr_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; 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 = 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; while (mag < 20) { /* i = j * gr_radius * pow(10.0, (double) mag) / (maxrad * 2); */ i = j * pow(10.0, (double) mag) * pixperunit / 2; if (i / 5 > gr_radius + ((xoff > 0) ? xoff : - xoff)) break; (void) sprintf(plab, "%lg", j * pow(10.0, (double) (mag - basemag))); (void) sprintf(nlab, "-%lg", j * pow(10.0, (double) (mag - basemag))); arcset(i, k, gr_radius, gr_xcenter, gr_ycenter, xoff, yoff, plab, nlab); if (i * 2.5 < gr_radius + ((xoff > 0) ? xoff : - xoff)) k = i; if (j == 5) { j = 1; mag++; } else if (j == 2) j = 5; else if (j == 1) j = 2; } if (mag == 20) { fprintf(cp_err, "smithgrid: Internal Error: screwed up\n"); return; } gi_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; gi_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; gi_drawline(gr_xcenter - zheight, gr_ycenter + yoff, gr_xcenter + zheight, gr_ycenter + yoff); } (void) sprintf(buf, "e%d", basemag); gi_text(buf, gr_xcenter + gr_radius, gr_ycenter - gr_radius, 0, false);#ifdef notdef gi_text("0", gr_xcenter + gr_radius + gi_fntwidth, gr_ycenter - gi_fntheight / 2, 0, false); gi_text("o", gr_xcenter + gr_radius + gi_fntwidth * 2, gr_ycenter, 0, false); gi_text("90", gr_xcenter - gi_fntwidth, gr_ycenter + gr_radius + gi_fntheight / 2, 0, false); gi_text("o", gr_xcenter + gi_fntwidth, gr_ycenter + gr_radius + gi_fntheight, 0, false); gi_text("180", gr_xcenter - gr_radius - gi_fntwidth * 5, gr_ycenter - gi_fntheight / 2, 0, false); gi_text("o", gr_xcenter - gr_radius - gi_fntwidth * 2, gr_ycenter, 0, false); gi_text("-90", gr_xcenter - gi_fntwidth * 2, gr_ycenter - gr_radius - 2 * gi_fntheight, 0, false); gi_text("o", gr_xcenter + gi_fntwidth, gr_ycenter - gr_radius - gi_fntheight - gi_fntheight / 2, 0, false);#endif gi_update(); return;#endif}/* Draw one arc set. The arcs should have radius rad. The outermost circle is * described by (centx, centy) and maxrad, and the distance from the right side * of the bounding circle to the logical center of the other circles in pixels * is xoffset (positive brings the negative plane into the picture). * plab and nlab are the labels to put on the positive and negative X-arcs, * respectively... If the X-axis isn't on the screen, then we have to be * clever... */#ifdef notdefstatic voidarcset(rad, prevrad, maxrad, centx, centy, xoffset, yoffset, plab, nlab) int rad, prevrad, maxrad, centx, centy, xoffset, yoffset; char *plab, *nlab;{ double angle = atan((double) prevrad / rad); int x; /* Let's be lazy and just draw everything -- we won't get called too * much and the circles get clipped anyway... */ gi_setcolor(2); cliparc(centx + xoffset - rad, centy + yoffset, rad, 2 * angle, 2 * PI - 2 * angle, centx, centy, maxrad); cliparc(centx + xoffset + rad, centy + yoffset, rad, PI + 2 * angle, PI - 2 * angle, centx, centy, maxrad); /* Draw the upper and lower circles. */ gi_setcolor(3); cliparc(centx + xoffset, centy + yoffset + rad, rad, PI * 1.5 + 2 * angle, PI * 1.5 - 2 * angle, centx, centy, maxrad); cliparc(centx + xoffset, centy + yoffset - rad, rad, PI / 2 + 2 * angle, PI / 2 - 2 * angle, centx, centy, maxrad); /* Now toss the labels on... */ gi_setcolor(1); x = centx + xoffset - 2 * rad - gi_fntwidth * strlen(plab) - 2; if ((x > gr_xmargin) && (x < gi_maxx)) gi_text(plab, x, centy - gi_fntheight - 1, false, false); x = centx + xoffset + 2 * rad - gi_fntwidth * strlen(nlab) - 2; if ((x > gr_xmargin) && (x < gi_maxx)) gi_text(nlab, x, centy - gi_fntheight - 1, false, false); return;}/* This routine draws an arc and clips it to a circle. It's hard to figure * out how it works without looking at the piece of scratch paaper I have * in front of me, so let's hope it doesn't break... */static voidcliparc(cx, cy, rad, start, end, clipx, clipy, cliprad) int cx, cy, rad, clipx, clipy, cliprad; double start, end;{ int x, y, tx, ty, dist; double alpha, theta, phi, a1, a2, d, l; bool in; x = cx - clipx; y = cy - clipy; dist = sqrt((double) (x * x + y * y)); if (!rad || !cliprad) return; if (dist + rad < cliprad) { /* The arc is entirely in the boundary. */ gi_arc(cx, cy, rad, start, end); return; } else if ((dist - rad >= cliprad) || (rad - dist >= cliprad)) { /* The arc is outside of the boundary. */ return; } /* Now let's figure out the angles at which the arc crosses the * circle. We know dist != 0. */ if (x) phi = atan((double) y / x); else if (y > 0) phi = PI * 1.5; else phi = PI / 2; if (cx > clipx) theta = PI + phi; else theta = phi; alpha = acos((double) (dist * dist + rad * rad - cliprad * cliprad) / (2 * dist * rad)); a1 = theta + alpha; a2 = theta - alpha; while (a1 < 0) a1 += PI * 2; while (a2 < 0) a2 += PI * 2; while (a1 >= PI * 2) a1 -= PI * 2; while (a2 >= PI * 2) a2 -= PI * 2; tx = cos(start) * rad + x; ty = sin(start) * rad + y; d = sqrt((double) tx * tx + ty * ty); in = (d > cliprad) ? false : true; /* Now begin with start. If the point is in, draw to either end, a1, * or a2, whichever comes first. */ d = PI * 3; if ((end < d) && (end > start)) d = end; if ((a1 < d) && (a1 > start)) d = a1; if ((a2 < d) && (a2 > start)) d = a2; if (d == PI * 3) { d = end; if (a1 < d) d = a1; if (a2 < d) d = a2; } if (in) gi_arc(cx, cy, rad, start, d); if (d == end) return; if (a1 != a2) in = in ? false : true; /* Now go from here to the next point. */ l = d; d = PI * 3; if ((end < d) && (end > l)) d = end; if ((a1 < d) && (a1 > l)) d = a1; if ((a2 < d) && (a2 > l)) d = a2; if (d == PI * 3) { d = end; if (a1 < d) d = a1; if (a2 < d) d = a2; } if (in) gi_arc(cx, cy, rad, l, d); if (d == end) return; in = in ? false : true; /* And from here to the end. */ if (in) gi_arc(cx, cy, rad, d, end); return;}#endif#ifdef notdef/* These routines are wrong on a lot of systems. */doublefloor(d) double d;{ double fp, ip; if (d >= 0.0) { fp = modf(d, &ip); return (ip); } else { /* This is the case that lattice C screws up... */ fp = modf(-d, &ip); if (fp != 0.0) return (-ip - 1); else return (-ip); }}doubleceil(d) double d;{ return (- floor(-d));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -