📄 grid.c
字号:
/* Routines to draw the various sorts of grids -- linear, log, polar. (no smiths)*/#include "prefix.h"#include "FTEgraph.h"#include "CPdefs.h"#include "FTEdefs.h"#include "FTEdata.h"#include "FTEparse.h"/* gtri - delete - wbk - 10/8/90 - duplicates include in CPdefs.h:CPstd.h *//* #include <math.h> */ /* for modf() *//* gtri - end - wbk - 10/8/90 */#include "suffix.h"#define PI 3.1415926535897932384static double *lingrid(), *loggrid();static void polargrid(), smithgrid();#ifdef notdefstatic void arcset(), cliparc();static void adddeglabel(), addradlabel();#endiftypedef 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->datawindow.xmin > graph->datawindow.xmax) || (graph->datawindow.ymin > graph->datawindow.ymax)) { fprintf(cp_err, "gr_fixgrid: Internal Error: bad limits %lg, %lg, %lg, %lg...\r\n", graph->datawindow.xmin, graph->datawindow.xmax, graph->datawindow.ymin, graph->datawindow.xmax); return; } if (graph->grid.gridtype == GRID_POLAR) { graph->grid.circular = true; polargrid(); return; } else if (graph->grid.gridtype == GRID_SMITH) { graph->grid.circular = true; smithgrid(); return; } graph->grid.circular = false; if ((graph->grid.gridtype == GRID_XLOG) || (graph->grid.gridtype == GRID_LOGLOG)) dd = loggrid(graph, graph->datawindow.xmin, graph->datawindow.xmax, xtype, x_axis); else dd = lingrid(graph, graph->datawindow.xmin, graph->datawindow.xmax, xdelta, xtype, x_axis); graph->datawindow.xmin = dd[0]; graph->datawindow.xmax = dd[1]; if ((graph->grid.gridtype == GRID_YLOG) || (graph->grid.gridtype == GRID_LOGLOG)) dd = loggrid(graph, graph->datawindow.ymin, graph->datawindow.ymax, ytype, y_axis); else dd = lingrid(graph, graph->datawindow.ymin, graph->datawindow.ymax, ydelta, ytype, y_axis); graph->datawindow.ymin = dd[0]; graph->datawindow.ymax = 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, graph->absolute.width - (strlen(graph->grid.xlabel) + 3) * graph->fontwidth, graph->fontheight); } if (graph->grid.ylabel) { Text(graph->grid.ylabel, graph->fontwidth, graph->absolute.height / 2); } if ((graph->grid.gridtype == GRID_XLOG) || (graph->grid.gridtype == GRID_LOGLOG)) drawloggrid(graph, 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); else 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, x_axis); if ((graph->grid.gridtype == GRID_YLOG) || (graph->grid.gridtype == GRID_LOGLOG)) drawloggrid(graph, 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); else 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, y_axis);}/* 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, hmt, lmt, nsp, spacing, dst; double tenpowmag; bool onedec = false; int margin; int max; static double dd[2]; int mult = 1; char buf[16], *s; if (axis == x_axis) { margin = graph->viewportxoff; max = graph->viewport.width + graph->viewportxoff; } else { margin = graph->viewportyoff; max = graph->viewport.height + graph->viewportyoff; } if (delta < 0.0) { fprintf(cp_err, "Warning: %cdelta is negative -- ignored\n", (axis == x_axis) ? 'x' : 'y'); delta = 0; }/* note: not idempotent, fix some other way XXX */ /* This is a hack to fix a problem on the HP 9000 ... */ if (!((axis == x_axis) ? graph->grid.xaxis.lin.hacked : graph->grid.yaxis.lin.hacked) && hi - lo < 1e-6) { if (axis == x_axis) graph->grid.xaxis.lin.hacked = 1; else graph->grid.yaxis.lin.hacked = 1; hi += 1e-6 * fabs(hi); lo -= 1e-6 * fabs(lo); } /* 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 a multiple of 3. */ mag = floor(mylog10(hi - lo)); tenpowmag = pow(10.0, (double) mag); if (scaleunits) { if ((mag % 3) && !((mag - 1) % 3)) { mult = 10; mag--; } else if ((mag % 3) && !((mag + 1) % 3)) { onedec = true; mag++; } } /* Now we have to round lo down, and hi up... */ lmt = (int) floor(lo / tenpowmag); hmt = (int) ceil(hi / tenpowmag); if (fabs(hi - tenpowmag) < 10e-20) { /* This is a hack to fix a strange case... */ hmt = 1; } dst = hmt - lmt; /* This is a strange case. */ if (dst == 1) { dst = 10; mag--; tenpowmag /= 10; hmt *= 10.0; lmt *= 10.0; } dd[0] = lo = lmt * tenpowmag; dd[1] = hi = hmt * tenpowmag; /* 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 (delta == 0.0) { for (nsp = 5; nsp < 10; nsp++) if (!(dst % nsp)) break; if (nsp == 10) for (nsp = 2; nsp < 5; nsp++) if (!(dst % nsp)) break; /* Aaaaaghhh... */ if ((dst == 11) || (dst == 13) || (dst == 17) || (dst == 19)) nsp = dst; spacing = (max - margin) / nsp; } 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; spacing = (max - margin) * delta / (hi - lo); } /* In case we have a relatively small delta... */ while (nsp > dst) { dst *= 10; mag--; hmt *= 10.0; lmt *= 10.0; } /* Reset the max X 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; } if (scaleunits) { /* Figure out what to put here... */ switch (mag) { case -18: /* atto */ (void) strcpy(buf, "a"); break; case -15: /* femto */ (void) strcpy(buf, "f"); break; case -12: /* pico */ (void) strcpy(buf, "p"); break; case -9: /* nano */ (void) strcpy(buf, "n"); break; case -6: /* micro */ (void) strcpy(buf, "u"); break; case -3: /* milli */ (void) strcpy(buf, "m"); break; case 0: /* -- */ (void) strcpy(buf, ""); break; case 3: /* kilo */ (void) strcpy(buf, "K"); break; case 6: /* mega */ (void) strcpy(buf, "M"); break; case 9: /* giga */ (void) strcpy(buf, "G"); break; case 12: /* terra */ (void) strcpy(buf, "T"); break; case 15: /* peta */ (void) strcpy(buf, "P"); break; case 18: /* exa */ (void) strcpy(buf, "E"); break; default: (void) sprintf(buf, "e%d", mag); break; } if (s = ft_typabbrev(type)) (void) strcat(buf, s); else /* Get rid of the prefix... */ (void) sprintf(buf, "e%d", mag); } else (void) sprintf(buf, "e%d", mag); /* have to save non-intuitive variables left over from old algorithms for redraws */ if (axis == x_axis) { graph->grid.xaxis.lin.spacing = spacing; graph->grid.xaxis.lin.numspace = nsp; graph->grid.xaxis.lin.distance = dst; graph->grid.xaxis.lin.lowlimit = lmt; graph->grid.xaxis.lin.highlimit = hmt; graph->grid.xaxis.lin.onedec = onedec; graph->grid.xaxis.lin.mult = mult; (void) strcpy(graph->grid.xaxis.lin.units, buf); } else { graph->grid.yaxis.lin.spacing = spacing; graph->grid.yaxis.lin.numspace = nsp; graph->grid.yaxis.lin.distance = dst; graph->grid.yaxis.lin.lowlimit = lmt; graph->grid.yaxis.lin.highlimit = hmt; graph->grid.yaxis.lin.onedec = onedec; graph->grid.yaxis.lin.mult = mult; (void) strcpy(graph->grid.yaxis.lin.units, buf); } return (dd);}staticdrawlingrid(graph, units, spacing, nsp, dst, lmt, hmt, onedec, mult, axis)GRAPH *graph;char units[16];bool onedec;int hmt, lmt, nsp, spacing, dst, mult;Axis axis;{ int i, j; char buf[16]; /* i counts how many pixels we have drawn, and j counts which unit * we are at. */ for (i = 0, j = lmt; j <= hmt; i += spacing, j += dst / nsp) { if (j == 0) SetLinestyle(0); if (graph->grid.gridtype != GRID_NONE) {/* note: get rid of this parameter and draw both axes at once */ 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); if (onedec)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -