📄 grid.c
字号:
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"); }}/* maximum number of circles */#define CMAX 50static voiddrawsmithgrid(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;}/* 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 *graph, double rad, double prevrad, double irad, double iprevrad, double radoff, int maxrad, int centx, int centy, int xoffset, int yoffset, char *plab, char *nlab, int pdeg, int ndeg, int pxmin, int pxmax){ 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(double cx, double cy, double rad, double start, double end, int iclipx, int iclipy, int icliprad, int flag){ double clipx, clipy, cliprad; double sclip = 0.0, eclip = 0.0; double x, y, tx, ty, dist; double alpha, theta, phi, a1, a2, d, l; 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 + -