/****************************************************************************
- * RRDtool 1.2.10 Copyright by Tobi Oetiker, 1997-2005
+ * RRDtool 1.2.11 Copyright by Tobi Oetiker, 1997-2005
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
/* reserve space for main and/or pie */
im->yimg = Ymain + Yxlabel;
-
+
#ifdef WITH_PIECHART
if (im->yimg < Ypie) im->yimg = Ypie;
#endif
im->yorigin = im->yimg - Yxlabel;
- ytr(im,DNAN);
/* reserve space for the title *or* some padding above the graph */
if (Ytitle) {
}
/* reserve space for padding below the graph */
im->yimg += Yspacing;
-
+
/* Determine where to place the legends onto the image.
** Adjust im->yimg to match the space requirements.
*/
}
#endif
+ ytr(im,DNAN);
return 0;
}
if (im->gdes[i].col != 0x0){
/* GF_LINE and friend */
if(stack_gf == GF_LINE ){
+ double last_y=0;
node = NULL;
- for(ii=1;ii<im->xsize;ii++){
+ for(ii=1;ii<im->xsize;ii++){
if (isnan(im->gdes[i].p_data[ii]) || (im->slopemode==1 && isnan(im->gdes[i].p_data[ii-1]))){
node = NULL;
continue;
}
if ( node == NULL ) {
+ last_y = ytr(im,im->gdes[i].p_data[ii]);
if ( im->slopemode == 0 ){
node = gfx_new_line(im->canvas,
- ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
- ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+ ii-1+im->xorigin,last_y,
+ ii+im->xorigin,last_y,
im->gdes[i].linewidth,
im->gdes[i].col);
} else {
node = gfx_new_line(im->canvas,
ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]),
- ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+ ii+im->xorigin,last_y,
im->gdes[i].linewidth,
im->gdes[i].col);
}
} else {
- if ( im->slopemode==0 ){
- gfx_add_point(node,ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
+ double new_y = ytr(im,im->gdes[i].p_data[ii]);
+ if ( im->slopemode==0 && new_y != last_y){
+ gfx_add_point(node,ii-1+im->xorigin,new_y);
+ last_y = new_y;
};
- gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
+ gfx_add_point(node,ii+im->xorigin,new_y);
};
}
case 'n':{
char prop[15];
double size = 1;
- char font[1024];
+ char font[1024] = "";
if(sscanf(optarg,
"%10[A-Z]:%lf:%1000s",
else if (!strcmp("TOTAL", func)) gdes->vf.op = VDEF_TOTAL;
else if (!strcmp("FIRST", func)) gdes->vf.op = VDEF_FIRST;
else if (!strcmp("LAST", func)) gdes->vf.op = VDEF_LAST;
+ else if (!strcmp("LSLSLOPE", func)) gdes->vf.op = VDEF_LSLSLOPE;
+ else if (!strcmp("LSLINT", func)) gdes->vf.op = VDEF_LSLINT;
+ else if (!strcmp("LSLCORREL",func)) gdes->vf.op = VDEF_LSLCORREL;
else {
rrd_set_error("Unknown function '%s' in VDEF '%s'\n"
,func
case VDEF_TOTAL:
case VDEF_FIRST:
case VDEF_LAST:
+ case VDEF_LSLSLOPE:
+ case VDEF_LSLINT:
+ case VDEF_LSLCORREL:
if (isnan(param)) {
gdes->vf.param = DNAN;
gdes->vf.val = DNAN;
dst->vf.when = src->start + (step+1)*src->step;
}
break;
+ case VDEF_LSLSLOPE:
+ case VDEF_LSLINT:
+ case VDEF_LSLCORREL:{
+ /* Bestfit line by linear least squares method */
+
+ int cnt=0;
+ double SUMx, SUMy, SUMxy, SUMxx, SUMyy, slope, y_intercept, correl ;
+ SUMx = 0; SUMy = 0; SUMxy = 0; SUMxx = 0; SUMyy = 0;
+
+ for (step=0;step<steps;step++) {
+ if (finite(data[step*src->ds_cnt])) {
+ cnt++;
+ SUMx += step;
+ SUMxx += step * step;
+ SUMxy += step * data[step*src->ds_cnt];
+ SUMy += data[step*src->ds_cnt];
+ SUMyy += data[step*src->ds_cnt]*data[step*src->ds_cnt];
+ };
+ }
+
+ slope = ( SUMx*SUMy - cnt*SUMxy ) / ( SUMx*SUMx - cnt*SUMxx );
+ y_intercept = ( SUMy - slope*SUMx ) / cnt;
+ correl = (SUMxy - (SUMx*SUMy)/cnt) / sqrt((SUMxx - (SUMx*SUMx)/cnt)*(SUMyy - (SUMy*SUMy)/cnt));
+
+ if (cnt) {
+ if (dst->vf.op == VDEF_LSLSLOPE) {
+ dst->vf.val = slope;
+ dst->vf.when = cnt*src->step;
+ } else if (dst->vf.op == VDEF_LSLINT) {
+ dst->vf.val = y_intercept;
+ dst->vf.when = cnt*src->step;
+ } else if (dst->vf.op == VDEF_LSLCORREL) {
+ dst->vf.val = correl;
+ dst->vf.when = cnt*src->step;
+ };
+
+ } else {
+ dst->vf.val = DNAN;
+ dst->vf.when = 0;
+ }
+ }
+ break;
}
return 0;
}