/* Programmazione II - Esempio di codice Simple service routines for plotting graphs (20000816 prelz@mi.infn.it) */ #include <stdio.h> #include <stdlib.h> #include "graph_helper.h" graph *graph_create_new(char *display, char *title, int xws, int yws, char *xlabel, char *ylabel) { graph *newgraph; if (XHLP_open_display(display) < 0) return(NULL); if ((newgraph = (graph *)malloc(sizeof(graph))) == NULL) { fprintf(stderr,"Out of Memory.\n"); XHLP_close_display(); return(NULL); } if ((newgraph->wid = XHLP_open_window(xws, yws, title)) < 0) { free(newgraph); XHLP_close_display(); return(NULL); } strncpy(newgraph->lx, xlabel, sizeof(newgraph->lx)); strncpy(newgraph->ly, ylabel, sizeof(newgraph->ly)); newgraph->cx = xws/2; newgraph->cy = yws/2; newgraph->xal = xws - 2*WIN_BORDER; newgraph->yal = yws - 2*WIN_BORDER; newgraph->xmax = 1E-8; newgraph->ymax = 1E-8; newgraph->xmin = -1E-8; newgraph->ymin = -1E-8; newgraph->dx = (newgraph->xmax - newgraph->xmin)/(double)(newgraph->xal); newgraph->dy = (newgraph->ymax - newgraph->ymin)/(double)(newgraph->yal); newgraph->nval = 0; newgraph->vx = NULL; newgraph->vy = NULL; graph_draw_axis(newgraph); return(newgraph); } void graph_draw_axis(graph *graph) { char val[20]; if (graph == NULL) return; XHLP_set_color(graph->wid,"black"); XHLP_draw_line(graph->wid, WIN_BORDER, graph->cy, WIN_BORDER+graph->xal, graph->cy); XHLP_draw_line(graph->wid, graph->cx, WIN_BORDER, graph->cx, WIN_BORDER+graph->yal); /* Print maximum values */ sprintf(val, "%15.10e", - (double)(graph->cx - WIN_BORDER) * graph->dx); XHLP_print(graph->wid, WIN_BORDER, graph->cy+10, val); sprintf(val, "%15.10e", (double)(graph->xal - graph->cx + WIN_BORDER) * graph->dx); XHLP_print(graph->wid, WIN_BORDER + graph->xal - 80, graph->cy+10, val); sprintf(val, "%15.10e", (double)(graph->cy - WIN_BORDER) * graph->dy); XHLP_print(graph->wid, graph->cx+5, WIN_BORDER + 10, val); sprintf(val, "%15.10e", - (double)(graph->yal - graph->cy + WIN_BORDER) * graph->dy); XHLP_print(graph->wid, graph->cx+5, WIN_BORDER + graph->yal, val); /* Print axis labels */ XHLP_print(graph->wid, WIN_BORDER + graph->xal - 80, graph->cy-5, graph->lx); XHLP_print(graph->wid, graph->cx+5, WIN_BORDER, graph->ly); return; } int graph_add_point(graph *graph, double x, double y) { if (graph == NULL) return(-1); graph->nval++; graph->vx = (double *)realloc(graph->vx, graph->nval*sizeof(double)); graph->vy = (double *)realloc(graph->vy, graph->nval*sizeof(double)); if (graph->vx == NULL || graph->vy == NULL) { if (graph->vx != NULL) free(graph->vx); if (graph->vy != NULL) free(graph->vy); graph->nval = 0; } else { graph->vx[graph->nval-1] = x; graph->vy[graph->nval-1] = y; /* Adjust graph scales */ if (x > graph->xmax) { graph->xmax = x; graph->dx = (graph->xmax - graph->xmin)/(double)(graph->xal); graph->cx = WIN_BORDER - graph->xmin/graph->dx; } if (x < graph->xmin) { graph->xmin = x; graph->dx = (graph->xmax - graph->xmin)/(double)(graph->xal); graph->cx = WIN_BORDER - graph->xmin/graph->dx; } if (y > graph->ymax) { graph->ymax = y; graph->dy = (graph->ymax - graph->ymin)/(double)(graph->yal); graph->cy = WIN_BORDER + graph->ymax/graph->dy; } if (y < graph->ymin) { graph->ymin = y; graph->dy = (graph->ymax - graph->ymin)/(double)(graph->yal); graph->cy = WIN_BORDER + graph->ymax/graph->dy; } } return(graph->nval); } void graph_set_scale(graph *graph, double xmin, double xmax, double ymin, double ymax) { if (graph == NULL) return; graph->xmin = xmin; graph->xmax = xmax; graph->ymin = ymin; graph->ymax = ymax; graph->dx = (graph->xmax - graph->xmin)/(double)(graph->xal); graph->dy = (graph->ymax - graph->ymin)/(double)(graph->yal); graph->cx = WIN_BORDER - graph->xmin/graph->dx; graph->cy = WIN_BORDER + graph->ymax/graph->dy; return; } void graph_plot(graph *graph, char *color) { int xold,yold,xnew,ynew; int i; if (graph == NULL) return; XHLP_set_color(graph->wid,color); if (graph->nval <= 0) return; xold = graph->cx + graph->vx[0]/graph->dx; yold = graph->cy - graph->vy[0]/graph->dy; XHLP_plot(graph->wid, xold, yold); for(i=1; i<graph->nval; i++) { xnew = graph->cx + graph->vx[i]/graph->dx; ynew = graph->cy - graph->vy[i]/graph->dy; XHLP_draw_line(graph->wid, xold, yold, xnew, ynew); xold = xnew; yold = ynew; } return; } void graph_plot_last(graph *graph, char *color) { int x1,y1,x2,y2; int i; if (graph == NULL) return; XHLP_set_color(graph->wid,color); i = graph->nval - 2; if (i<0) return; x1 = graph->cx + graph->vx[i]/graph->dx; y1 = graph->cy - graph->vy[i]/graph->dy; x2 = graph->cx + graph->vx[i+1]/graph->dx; y2 = graph->cy - graph->vy[i+1]/graph->dy; XHLP_draw_line(graph->wid, x1, y1, x2, y2); return; } int graph_add_and_plot(graph *graph, double x, double y, char *color) { int retval; double save_dx, save_dy; save_dx = graph->dx; save_dy = graph->dy; retval = graph_add_point(graph, x, y); if (retval > 1) { if (graph->dx != save_dx || graph->dy != save_dy) { /* The scale changed! Redraw plot */ graph_clear(graph); graph_plot(graph, color); } else graph_plot_last(graph, color); } return(retval); } void graph_clear(graph *graph) { if (graph == NULL) return; XHLP_clear_window(graph->wid); graph_draw_axis(graph); return; } void graph_clear_values(graph *graph) { if (graph == NULL) return; if (graph->vx != NULL) free(graph->vx); if (graph->vy != NULL) free(graph->vy); graph->vx = NULL; graph->vy = NULL; graph->nval = 0; return; } void graph_free(graph *graph) { if (graph == NULL) return; graph_clear_values(graph); XHLP_close_window(graph->wid); free(graph); return; } void graph_pick_values(graph *graph, double *rx, double *ry) { int px,py; if (graph == NULL) return; XHLP_get_click(graph->wid, &px, &py); *rx = (double)(px - graph->cx) * graph->dx; *ry = (double)(graph->cy - py) * graph->dy; return; }