⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grid.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -