📄 graf.c
字号:
{ if (!graph->grid.xsized) graph->viewport.width = graph->absolute.width - 1.4 * graph->viewportxoff; if (!graph->grid.ysized) graph->viewport.height = graph->absolute.height - 2 * graph->viewportyoff; gr_fixgrid(graph, graph->grid.xdelta, graph->grid.ydelta, graph->grid.xdatatype, graph->grid.ydatatype); /* cache width and height info to make DatatoScreen go fast */ /* note: XXX see if this is actually used anywhere */ graph->datawindow.width = graph->datawindow.xmax - graph->datawindow.xmin; graph->datawindow.height = graph->datawindow.ymax - graph->datawindow.ymin; /* cache (datawindow size) / (viewport size) */ graph->aspectratiox = graph->datawindow.width / graph->viewport.width; graph->aspectratioy = graph->datawindow.height / graph->viewport.height;}/* redraw everything in struct graph */voidgr_redraw(GRAPH *graph){ struct dveclist *link; /* establish current graph so default graphic calls will work right */ PushGraphContext(graph); DevClear(); /* redraw grid */ gr_redrawgrid(graph); for (link=graph->plotdata, plotno = 0; link; link = link->next, plotno++) { /* redraw legend */ drawlegend(graph, plotno, link->vector); /* replot data if onevalue, pass it a NULL scale otherwise, if vec has its own scale, pass that else pass vec's plot's scale */ ft_graf(link->vector, graph->onevalue ? (struct dvec *) NULL : (link->vector->v_scale ? link->vector->v_scale : link->vector->v_plot->pl_scale), TRUE); } gr_restoretext(graph); PopGraphContext();}voidgr_restoretext(GRAPH *graph){ struct _keyed *k; /* restore text */ for (k=graph->keyed; k; k = k->next) { SetColor(k->colorindex); Text(k->text, k->x, k->y); }}/* Do some incremental plotting. There are 3 cases: * * First, if length < IPOINTMIN, don't do anything. * * Second, if length = IPOINTMIN, plot what we have so far. * * Third, if length > IPOINTMIN, plot the last points and resize if * needed. * * Note we don't check for pole / zero because they are of length 1. * * FIXME: there is a problem with multiple iplots that use the same * vector, namely, that vector has the same color throughout. This is * another reason why we need to pull color and linestyle out of dvec * XXX Or maybe even something more drastic ?? */static intiplot(struct plot *pl, int id){ int len = pl->pl_scale->v_length; struct dvec *v, *xs = pl->pl_scale; double *lims, dy; double start, stop, step; register int j; bool changed = FALSE; int yt; char *yl = NULL; double xlims[2], ylims[2]; static REQUEST reqst = { checkup_option, 0 }; int inited = 0; char commandline[513]; for (j = 0, v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) j++; if (!j) return(0); if (ft_grdb) fprintf(cp_err, "Entering iplot, len = %d\n\r", len); if (len < IPOINTMIN) { /* Nothing yet */ return(0); } else if (len == IPOINTMIN || !id) { resumption = FALSE; /* Draw the grid for the first time, and plot everything. */ lims = ft_minmax(xs, TRUE); xlims[0] = lims[0]; xlims[1] = lims[1]; ylims[0] = HUGE; ylims[1] = - ylims[0]; for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { lims = ft_minmax(v, TRUE); if (lims[0] < ylims[0]) ylims[0] = lims[0]; if (lims[1] > ylims[1]) ylims[1] = lims[1]; if (!yl) yl = v->v_name; } if (ft_grdb) fprintf(cp_err, "iplot: after 5, xlims = %G, %G, ylims = %G, %G\n\r", xlims[0], xlims[1], ylims[0], ylims[1]); for (yt = pl->pl_dvecs->v_type, v = pl->pl_dvecs->v_next; v; v = v->v_next) if ((v->v_flags & VF_PLOT) && (v->v_type != yt)) { yt = 0; break; } /* note: have command options for iplot to specify xdelta, etc. So don't need static variables hack. Assume default values for now. */ sprintf(commandline, "iplot %s", xs->v_name); (void) gr_init(xlims, ylims, xs->v_name, pl->pl_title, (char *) NULL, j, 0.0, 0.0, GRID_LIN, PLOT_LIN, xs->v_name, yl, xs->v_type, yt, plot_cur->pl_typename, commandline); for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { gr_start_internal(v, FALSE); ft_graf(v, xs, TRUE); } inited = 1; } else { Input(&reqst, 0); /* First see if we have to make the screen bigger */ dy = (isreal(xs) ? xs->v_realdata[len - 1] : realpart(&xs->v_compdata[len - 1])); if (ft_grdb) fprintf(cp_err, "x = %G\n\r", dy); if (!if_tranparams(ft_curckt, &start, &stop, &step) || !ciprefix("tran", pl->pl_typename)) { stop = HUGE; start = - stop; } while (dy < currentgraph->data.xmin) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: xlo %G -> %G\n\r", currentgraph->data.xmin, currentgraph->data.xmin - (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR); currentgraph->data.xmin -= (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR; if (currentgraph->data.xmin < start) { currentgraph->data.xmin = start; break; } } if (currentgraph->data.xmax < currentgraph->data.xmin) currentgraph->data.xmax = currentgraph->data.xmin; while (dy > currentgraph->data.xmax) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: xhi %G -> %G\n\r", currentgraph->data.xmax, currentgraph->data.xmax + (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR); currentgraph->data.xmax += (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR; if (currentgraph->data.xmax > stop) { currentgraph->data.xmax = stop; break; } } for (v = pl->pl_dvecs; v; v = v->v_next) { if (!(v->v_flags & VF_PLOT)) continue; dy = (isreal(v) ? v->v_realdata[len - 1] : realpart(&v->v_compdata[len - 1])); if (ft_grdb) fprintf(cp_err, "y = %G\n\r", dy); while (dy < currentgraph->data.ymin) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: ylo %G -> %G\n\r", currentgraph->data.ymin, currentgraph->data.ymin - (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR); currentgraph->data.ymin -= (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR; } if (currentgraph->data.ymax < currentgraph->data.ymin) currentgraph->data.ymax = currentgraph->data.ymin; while (dy > currentgraph->data.ymax) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: yhi %G -> %G\n\r", currentgraph->data.ymax, currentgraph->data.ymax + (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR); currentgraph->data.ymax += (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR; } } if (changed) { /* Redraw everything. */ gr_pmsg("Resizing screen"); gr_resize(currentgraph); gr_redraw(currentgraph); } else { /* Just connect the last two points. This won't be done * with curve interpolation, so it might look funny. */ for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { gr_point(v, (isreal(xs) ? xs->v_realdata[len - 1] : realpart(&xs->v_compdata[len - 1])), (isreal(v) ? v->v_realdata[len - 1] : realpart(&v->v_compdata[len - 1])), (isreal(xs) ? xs->v_realdata[len - 2] : realpart(&xs->v_compdata[len - 2])), (isreal(v) ? v->v_realdata[len - 2] : realpart(&v->v_compdata[len - 2])), len - 1); } } } Update(); return(inited);}static voidset(struct plot *plot, struct dbcomm *db, bool unset, int mode){ struct dvec *v; struct dbcomm *dc; if (db->db_type == DB_IPLOTALL || db->db_type == DB_TRACEALL) { for (v = plot->pl_dvecs; v; v = v->v_next) { if (unset) v->v_flags &= ~mode; else v->v_flags |= mode; } return; } for (dc = db; dc; dc = dc->db_also) { v = vec_fromplot(dc->db_nodename1, plot); if (!v || v->v_plot != plot) { if (!eq(dc->db_nodename1, "0") && !unset) { fprintf(cp_err, "Warning: node %s non-existent in %s.\n", dc->db_nodename1, plot->pl_name); /* note: XXX remove it from dbs, so won't get further errors */ } continue; } if (unset) v->v_flags &= ~mode; else v->v_flags |= mode; } return;}static char *getitright(char *buf, double num){ char *p; int k; sprintf(buf, " % .5g", num); p =strchr(buf, '.'); if (p) { return p - 4; } else { k = strlen(buf); if (k > 8) return buf + 4; else /* k >= 4 */ return buf + k - 4; }}static int hit, hit2;void reset_trace(void){ hit = -1; hit2 = -1;}voidgr_iplot(struct plot *plot){ struct dbcomm *db; int dontpop; /* So we don't pop w/o push. */ char buf[30]; hit = 0; for (db = dbs; db; db = db->db_next) { if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) { if (db->db_graphid) PushGraphContext(FindGraph(db->db_graphid)); set(plot, db, FALSE, VF_PLOT); dontpop = 0; if (iplot(plot, db->db_graphid)) { /* graph just assigned */ db->db_graphid = currentgraph->graphid; dontpop = 1; } set(plot, db, TRUE, VF_PLOT); if (!dontpop && db->db_graphid) PopGraphContext(); } else if (db->db_type == DB_TRACENODE || db->db_type == DB_TRACEALL) { struct dvec *v, *u; int len; set(plot, db, FALSE, VF_PRINT); len = plot->pl_scale->v_length; dontpop = 0; for (v = plot->pl_dvecs; v; v = v->v_next) { if (v->v_flags & VF_PRINT) { u = plot->pl_scale; if (len <= 1 || hit <= 0 || hit2 < 0) { if (len <= 1 || hit2 < 0) term_clear( ); else term_home( ); hit = 1; hit2 = 1; printf( "\tExecution trace (remove with the \"delete\" command)"); term_cleol( ); printf("\n"); if (u) { printf("%12s:", u->v_name); if (isreal(u)) { printf("%s", getitright(buf, u->v_realdata[len - 1])); } else { /* MW. Complex data here, realdata is NULL (why someone use realdata here again) */ printf("%s", getitright(buf, u->v_compdata[len - 1].cx_real)); printf(", %s", getitright(buf, u->v_compdata[len - 1].cx_imag)); } term_cleol( ); printf("\n"); } } if (v == u) continue; printf("%12s:", v->v_name); if (isreal(v)) { printf("%s", getitright(buf, v->v_realdata[len - 1])); } else { /* MW. Complex data again */ printf("%s", getitright(buf, v->v_compdata[len - 1].cx_real)); printf(", %s", getitright(buf, v->v_compdata[len - 1].cx_imag)); } term_cleol( ); printf("\n"); } } set(plot, db, TRUE, VF_PRINT); } }}/* This gets called after iplotting is done. We clear out the * db_graphid fields. Copy the dvecs, which we referenced by * reference, so DestroyGraph gets to free its own copy. * * Note: This is a clear case for separating the linestyle and color * fields from dvec. */voidgr_end_iplot(void){ struct dbcomm *db, *prev, *next; GRAPH *graph; struct dveclist *link; struct dvec *dv; prev = NULL; for (db = dbs; db; prev = db, db = next) { next = db->db_next; if (db->db_type == DB_DEADIPLOT) { if (db->db_graphid) { DestroyGraph(db->db_graphid); if (prev) prev->db_next = next; else dbs = next; dbfree(db); } } else if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) { if (db->db_graphid) { /* get private copy of dvecs */ graph = FindGraph(db->db_graphid); link = graph->plotdata; while (link) { dv = link->vector; link->vector = vec_copy(dv); /* vec_copy doesn't set v_color or v_linestyle */ link->vector->v_color = dv->v_color; link->vector->v_linestyle = dv->v_linestyle; link->vector->v_flags |= VF_PERMANENT; link = link->next; } db->db_graphid = 0; } else { /* warn that this wasn't plotted */ fprintf(cp_err, "Warning: iplot %d was not executed.\n", db->db_number); } } } return;}double *readtics(char *string){ int i, k; char *words, *worde; double *tics, *ticsk; tics = (double *) tmalloc(MAXTICS * sizeof(double)); ticsk = tics; words = string; for (i = k = 0; *words && k < MAXTICS; words = worde) { while (isspace(*words)) words++; worde = words; while (isalpha(*worde) || isdigit(*worde)) worde++; if (*worde) *worde++ = '\0'; sscanf(words, "%lf", ticsk++); k++; } *ticsk = HUGE; return(tics);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -