?? grid.c
字號:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Modified: 2001 AlansFixes$Id: grid.c,v 1.5 2005/05/30 20:28:44 sjborley Exp $**********//* Routines to draw the various sorts of grids -- linear, log, polar.*/#include <ngspice.h>#include <graph.h>#include <cpdefs.h>#include <ftedefs.h>#include "grid.h"#include "../display.h"#define RAD_TO_DEG (180.0 / M_PI)#define LABEL_CHARS 20/* static declarations */static double * lingrid(GRAPH *graph, double lo, double hi, double delta, int type, Axis axis);static double * loggrid(GRAPH *graph, double lo, double hi, int type, Axis axis);static void polargrid(GRAPH *graph);static void drawpolargrid(GRAPH *graph);static void adddeglabel(GRAPH *graph, int deg, int x, int y, int cx, int cy, int lx, int ly);static void addradlabel(GRAPH *graph, int lab, double theta, int x, int y);static void smithgrid(GRAPH *graph);static void drawsmithgrid(GRAPH *graph);static void arcset(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);static double cliparc(double cx, double cy, double rad, double start, double end, int iclipx, int iclipy, int icliprad, int flag);/* note: scaleunits is static and never changed in this file ie, can get rid of it */static bool scaleunits = TRUE;voidgr_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;}voidgr_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; }}/* Plot a linear grid. Returns the new hi and lo limits. */static double *lingrid(GRAPH *graph, double lo, double hi, double delta, int type, Axis axis){ int mag, mag2, mag3; double hmt, lmt, dst; int nsp; double tenpowmag = 0.0, tenpowmag2, step, spacing; bool onedec = FALSE; int margin; int max; static double dd[2]; int mult = 1; char buf[LABEL_CHARS], *s; int slim, digits; if (axis == y_axis && graph->grid.ysized) { lmt = graph->grid.yaxis.lin.lowlimit; hmt = graph->grid.yaxis.lin.highlimit; tenpowmag = graph->grid.yaxis.lin.tenpowmag; dd[0] = lmt * tenpowmag; dd[1] = hmt * tenpowmag; return dd; } if (axis == x_axis && graph->grid.xsized) { lmt = graph->grid.xaxis.lin.lowlimit; hmt = graph->grid.xaxis.lin.highlimit; tenpowmag = graph->grid.xaxis.lin.tenpowmag; dd[0] = lmt * tenpowmag; dd[1] = hmt * tenpowmag; return dd; } if (delta < 0.0) { fprintf(cp_err, "Warning: %cdelta is negative -- reversed\n", (axis == x_axis) ? 'x' : 'y'); delta = -delta; } mag2 = floor(log10(fabs(hi - lo))); tenpowmag2 = pow(10.0, (double) mag2); /* Round lo down, and hi up */ /* First, round lo _up_ and hi _down_ out to the 3rd digit of accuracy */ lmt = (ceil(1000 * lo / tenpowmag2)) / 1000.0; hmt = (floor(1000 * hi / tenpowmag2 + 0.9)) / 1000.0; lmt = floor(10.0 * lmt) / 10.0; hmt = ceil(10.0 * hmt) / 10.0; lo = lmt * tenpowmag2; hi = hmt * tenpowmag2; if (fabs(hi) > fabs(lo)) mag = floor(log10(fabs(hi))); else mag = floor(log10(fabs(lo))); if (mag >= 0) mag3 = ((int) (mag / 3)) * 3; else mag3 = - ((int) ((2 - mag) / 3)) * 3; if (scaleunits) digits = mag3 - mag2; else { digits = mag - mag2; mag3 = mag; } if (digits < 1) digits = 0; if (axis == x_axis) { margin = graph->viewportxoff; /*max = graph->viewport.width + graph->viewportxoff;*/ max = graph->absolute.width - graph->viewportxoff; } else { graph->viewportxoff = (digits + 5 + mag - mag3) * graph->fontwidth; margin = graph->viewportyoff; /*max = graph->viewport.height + graph->viewportyoff;*/ max = graph->absolute.height - graph->viewportyoff; } /* Express the difference between the high and low values as * diff = d * 10^mag. We know diff >= 0.0. If scaleunits is * set then make sure that mag is modulo 3. */ dst = hmt - lmt; /* We have to go from lmt to hmt, so think of some useful places * to put grid lines. We will have a total of nsp lines, one * every spacing pixels, which is every dst / nsp units. */ if (scaleunits) { static char scaleletters[ ] = "afpnum\0kMGT"; char *p; int i, j; tenpowmag = pow(10.0, (double) mag3); *buf = 0; i = (mag3 + 18) / 3; if (i < 0) i = 6; /* No scale units */ else if (i >= sizeof(scaleletters) - 1) { /* sizeof includes '\0' at end, which is useless */ /* i = sizeof(scaleletters) - 2; */ i = 6; /* No scale units */ } j = mag3 - i * 3 + 18; if (j == 1) (void) sprintf(buf, "x10 "); else if (j == 2) (void) sprintf(buf, "x100 "); else if (j) (void) sprintf(buf, "x10^%d ", j); if (scaleletters[i]) { for (p = buf; *p; p++) ; *p++ = scaleletters[i]; *p++ = 0; } } else if (mag > 1) { tenpowmag = pow(10.0, (double) mag); (void) sprintf(buf, "x10^%d ", mag); } if ((s = ft_typabbrev(type))) { (void) strcat(buf, s); } else { (void) strcat(buf, "Units"); } if (delta == 0.0) { int i; double step; static struct { float div_lim, step; } div_list[ ] = { { 100.0, 10.0 }, { 50.0, 5.0 }, { 20.0, 2.0 }, { 6.0, 1.0 }, { 3.0, 0.5 }, { 1.0, 0.2 }, { 0.5, 0.1 }, { 0.0, 0.05 }, { 0.0, 0.01 } }; for (i = 0; i < NUMELEMS(div_list); i++) { if (dst > div_list[i].div_lim) { break; } } do { step = div_list[i].step; nsp = (dst + step - 0.0001) / step; spacing = (max - margin) / nsp; i += 1; } while (i < NUMELEMS(div_list) && spacing > 50); if (axis == x_axis) { slim = digits + 5 + mag - mag3; slim = graph->fontwidth * (slim + 1); } else slim = graph->fontheight * 3; while (i > 0 && spacing < slim + 3) { i -= 1; step = div_list[i].step; nsp = (dst + step - 0.0001) / step; spacing = (max - margin) / nsp; } if (lmt < 0) lmt = - ceil(-lmt / step) * step; else lmt = floor(lmt / step) * step; if (hmt < 0) hmt = - floor(-hmt / step) * step; else hmt = ceil(hmt / step) * step; dst = hmt - lmt; lo = lmt * tenpowmag2; hi = hmt * tenpowmag2; nsp = (dst + step - 0.0001) / step; } else { /* The user told us where to put the grid lines. They will * not be equally spaced in this case (i.e, the right edge * won't be a line). */ nsp = (hi - lo) / delta; if (nsp > 100) nsp = 100; step = (max - margin) * delta / (hi - lo); } spacing = (max - margin) / nsp; dd[0] = lo; dd[1] = hi; /* Reset the max coordinate to deal with round-off error. */ if (nsp && (delta == 0.0)) { if (axis == x_axis) graph->viewport.width = spacing * nsp; else graph->viewport.height = spacing * nsp; } else if (!nsp) { nsp = 1; } /* have to save non-intuitive variables left over from old algorithms for redraws */ if (axis == x_axis) { graph->grid.xsized = 1; graph->grid.xaxis.lin.onedec = onedec; graph->grid.xaxis.lin.mult = mult; graph->grid.xaxis.lin.tenpowmag = tenpowmag2; graph->grid.xaxis.lin.tenpowmagx = tenpowmag; graph->grid.xaxis.lin.digits = digits; (void) strcpy(graph->grid.xaxis.lin.units, buf); graph->grid.xaxis.lin.distance = dst; graph->grid.xaxis.lin.lowlimit = lmt; graph->grid.xaxis.lin.highlimit = hmt; graph->grid.xaxis.lin.spacing = spacing; graph->grid.xaxis.lin.numspace = nsp; } else { graph->grid.ysized = 1; graph->grid.yaxis.lin.onedec = onedec; graph->grid.yaxis.lin.mult = mult; graph->grid.yaxis.lin.tenpowmag = tenpowmag2; graph->grid.yaxis.lin.tenpowmagx = tenpowmag; graph->grid.yaxis.lin.digits = digits; (void) strcpy(graph->grid.yaxis.lin.units, buf); graph->grid.yaxis.lin.distance = dst; graph->grid.yaxis.lin.lowlimit = lmt; graph->grid.yaxis.lin.highlimit = hmt; graph->grid.yaxis.lin.spacing = spacing; graph->grid.yaxis.lin.numspace = nsp; } return (dd);}/* PN static */voiddrawlingrid(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);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -