📄 grid.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.**********//* Routines to draw the various sorts of grids -- linear, log, polar.*/#include "spice.h"#include "util.h"#include "ftegraph.h"#include "cpdefs.h"#include "ftedefs.h"#include "ftedata.h"#include "fteparse.h"#include "suffix.h"#define RAD_TO_DEG (180.0 / M_PI)#define LABEL_CHARS 20static double *lingrid(), *loggrid();static void polargrid(), smithgrid();static void drawpolargrid( );static void drawsmithgrid( );static void arcset();static double cliparc();static void adddeglabel(), addradlabel();typedef enum { x_axis, y_axis } Axis;/* note: scaleunits is static and never changed in this file ie, can get rid of it */static bool scaleunits = true;voidgr_fixgrid(graph, xdelta, ydelta, xtype, ytype) GRAPH *graph; double xdelta, ydelta; int xtype, 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: %lg, %lg, %lg, %lg\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;}gr_redrawgrid(graph)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, lo, hi, delta, type, axis) GRAPH *graph; double lo, hi; double delta; int type; Axis axis;{ int mag, mag2, mag3; double hmt, lmt, dst; int nsp; double tenpowmag, 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -