📄 grid.c
字号:
} 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, "%lg", 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, "%lg", rnorm[k]); (void) sprintf(nlab, "-%lg", 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;}/* 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... */static voidarcset(graph, rad, prevrad, irad, iprevrad, radoff, maxrad, centx, centy, xoffset, yoffset, plab, nlab, pdeg, ndeg, pxmin, pxmax) GRAPH *graph; int ndeg, pdeg, pxmin, pxmax ; double rad, prevrad, irad, iprevrad, radoff; int maxrad, centx, centy, xoffset, yoffset; char *plab, *nlab;{ char buf[64]; double aclip; double angle = atan2((double) iprevrad, (double) rad); double iangle = atan2((double) prevrad, (double) irad); int x, xlab, ylab; /* Let's be lazy and just draw everything -- we won't get called too * much and the circles get clipped anyway... */ SetColor(18); cliparc((double) (centx + xoffset + radoff - rad), (double) (centy + yoffset), rad, 2*angle, 2 * M_PI - 2 * angle, centx, centy, maxrad, 0); /* These circles are not part of the smith chart * Let's draw them anyway */ cliparc((double) (centx + xoffset + radoff + rad), (double) (centy + yoffset), rad, M_PI + 2 * angle, M_PI - 2 * angle, centx, centy, maxrad, 0); /* Draw the upper and lower circles. */ SetColor(19); aclip = cliparc((double) (centx + xoffset + radoff), (double) (centy + yoffset + irad), irad, (double) (M_PI * 1.5 + 2 * iangle), (double) (M_PI * 1.5 - 2 * iangle), centx, centy, maxrad, 1); if ((aclip > M_PI / 180) && (pdeg > 1)) { xlab = centx + xoffset + radoff + irad * cos(aclip); ylab = centy + yoffset + irad * (1 + sin(aclip)); if ((ylab - gr_ycenter) > graph->fontheight) { SetColor(1); adddeglabel(graph, pdeg, xlab, ylab, gr_xcenter, gr_ycenter, gr_xcenter, gr_ycenter);/* ylab = centy + yoffset - irad * (1 + sin(aclip)); adddeglabel(graph, ndeg, xlab, ylab, gr_xcenter, gr_ycenter, gr_xcenter, gr_ycenter); */ SetColor(19); } } aclip = cliparc((double) (centx + xoffset + radoff), (double) (centy + yoffset - irad), irad, (double) (M_PI / 2 + 2 * iangle), (double) (M_PI / 2 - 2 * iangle), centx, centy, maxrad, (iangle == 0)?2:0); if ((aclip >= 0 && aclip < 2*M_PI - M_PI/180) && (pdeg < 359)) { xlab = centx + xoffset + radoff + irad * cos(aclip); ylab = centy + yoffset + irad * (sin(aclip) - 1); SetColor(1); adddeglabel(graph, ndeg, xlab, ylab, gr_xcenter, gr_ycenter, gr_xcenter, gr_ycenter); SetColor(19); } /* Now toss the labels on... */ SetColor(1); x = centx + xoffset + (int)radoff - 2 * (int)rad - gi_fntwidth * strlen(plab) - 2; if ((x > pxmin) && (x < pxmax)) { if ((yoffset > - gr_radius) && (yoffset < gr_radius)) Text(plab, x, centy + yoffset - gi_fntheight - 1); else Text(plab, x, gr_ymargin - 3 * gi_fntheight - 2); }/* x = centx + xoffset + (int) radoff + 2 * (int)rad - gi_fntwidth * strlen(nlab) - 2; if ((x > gr_xmargin) && (x < gi_maxx)) Text(nlab, x, centy + yoffset - gi_fntheight - 1); */ 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... * Converted to all doubles for CRAYs */static doublecliparc(cx, cy, rad, start, end, iclipx, iclipy, icliprad, flag) double cx, cy, rad; int iclipx, iclipy, icliprad, flag; double start, end;{ double clipx, clipy, cliprad; double x, y, tx, ty, dist; double alpha, theta, phi, a1, a2, d, l; double sclip, eclip; bool in; clipx = (double) iclipx; clipy = (double) iclipy; cliprad = (double) icliprad; x = cx - clipx; y = cy - clipy; dist = sqrt((double) (x * x + y * y)); if (!rad || !cliprad) return(-1); if (dist + rad < cliprad) { /* The arc is entirely in the boundary. */ Arc((int)cx, (int)cy, (int)rad, start, end); return(flag?start:end); } else if ((dist - rad >= cliprad) || (rad - dist >= cliprad)) { /* The arc is outside of the boundary. */ return(-1); } /* Now let's figure out the angles at which the arc crosses the * circle. We know dist != 0. */ if (x) phi = atan2((double) y, (double) x); else if (y > 0) phi = M_PI * 1.5; else phi = M_PI / 2; if (cx > clipx) theta = M_PI + phi; else theta = phi; alpha = (double) (dist * dist + rad * rad - cliprad * cliprad) / (2 * dist * rad); /* Sanity check */ if (alpha > 1.0) alpha = 0.0; else if (alpha < -1.0) alpha = M_PI; else alpha = acos(alpha); a1 = theta + alpha; a2 = theta - alpha; while (a1 < 0) a1 += M_PI * 2; while (a2 < 0) a2 += M_PI * 2; while (a1 >= M_PI * 2) a1 -= M_PI * 2; while (a2 >= M_PI * 2) a2 -= M_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 = M_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 == M_PI * 3) { d = end; if (a1 < d) d = a1; if (a2 < d) d = a2; } if (in) { if (start > d) { double tmp; tmp = start; start = d; d = tmp; } Arc((int)cx, (int)cy, (int)rad, start, d); sclip = start; eclip = d; } if (d == end) return(flag?sclip:eclip); if (a1 != a2) in = in ? false : true; /* Now go from here to the next point. */ l = d; d = M_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 == M_PI * 3) { d = end; if (a1 < d) d = a1; if (a2 < d) d = a2; } if (in) { Arc((int)cx, (int)cy, (int)rad, l, d); sclip = l; eclip = d; } if (d == end) return(flag?sclip:eclip); in = in ? false : true; /* And from here to the end. */ if (in) { Arc((int)cx, (int)cy, (int)rad, d, end); /* special case */ if (flag != 2) { sclip = d; eclip = end; } } return(flag%2?sclip:eclip);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -