/*
Programmazione II - Esempio di codice
Simple service routines for plotting graphs (20000816 prelz@mi.infn.it)
*/
#include
#include
#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; inval; 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;
}