/****************************************************************************
- * RRDtool 1.2.15 Copyright by Tobi Oetiker, 1997-2006
+ * RRDtool 1.2.19 Copyright by Tobi Oetiker, 1997-2007
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
#include <sys/stat.h>
+#ifdef WIN32
+#include "strftime.h"
+#endif
#include "rrd_tool.h"
-#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
#include <io.h>
#include <fcntl.h>
#endif
{1200, 0, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%d"},
{1800, 0, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a %d"},
{2400, 0, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a"},
- {3600, 0, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %V"},
- {3*3600, 0, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %V"},
+ {3600, 0, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %V"},
+ {3*3600, 0, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %V"},
{6*3600, 0, TMT_MONTH,1, TMT_MONTH,1, TMT_MONTH,1, 30*24*3600,"%b"},
{48*3600, 0, TMT_MONTH,1, TMT_MONTH,3, TMT_MONTH,3, 30*24*3600,"%b"},
+ {315360, 0, TMT_MONTH,3, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%Y"},
{10*24*3600, 0, TMT_YEAR,1, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%y"},
{-1,0,TMT_MONTH,0,TMT_MONTH,0,TMT_MONTH,0,0,""}
};
** relevant for min and max
*/
if (finite(paintval) && im->gdes[ii].gf != GF_TICK ) {
- if (isnan(minval) || paintval < minval)
- minval = paintval;
+ if ((isnan(minval) || paintval < minval ) &&
+ ! (im->logarithmic && paintval <= 0.0))
+ minval = paintval;
if (isnan(maxval) || paintval > maxval)
maxval = paintval;
}
} else {
prt_fctn = '\0';
}
+ /* only valid control codes */
+ if (prt_fctn != 'l' &&
+ prt_fctn != 'n' && /* a synonym for l */
+ prt_fctn != 'r' &&
+ prt_fctn != 'j' &&
+ prt_fctn != 'c' &&
+ prt_fctn != 's' &&
+ prt_fctn != 't' &&
+ prt_fctn != '\0' &&
+ prt_fctn != 'g' ) {
+ free(legspace);
+ rrd_set_error("Unknown control code at the end of '%s\\%c'",im->gdes[i].legend,prt_fctn);
+ return -1;
+
+ }
+
/* remove exess space */
+ if ( prt_fctn == 'n' ){
+ prt_fctn='l';
+ }
+
while (prt_fctn=='g' &&
leg_cc > 0 &&
im->gdes[i].legend[leg_cc-1]==' '){
return mnt;
}
+static int AlmostEqual2sComplement (float A, float B, int maxUlps)
+{
+
+ int aInt = *(int*)&A;
+ int bInt = *(int*)&B;
+ int intDiff;
+ /* Make sure maxUlps is non-negative and small enough that the
+ default NAN won't compare as equal to anything. */
+
+ /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
+
+ /* Make aInt lexicographically ordered as a twos-complement int */
+
+ if (aInt < 0)
+ aInt = 0x80000000l - aInt;
+
+ /* Make bInt lexicographically ordered as a twos-complement int */
+
+ if (bInt < 0)
+ bInt = 0x80000000l - bInt;
+
+ intDiff = abs(aInt - bInt);
+
+ if (intDiff <= maxUlps)
+ return 1;
+
+ return 0;
+}
+
/* logaritmic horizontal grid */
int
horizontal_log_grid(image_desc_t *im)
{1.0, 5.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{1.0, 2.0, 5.0, 7.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0},
{1.0, 2.0, 4.0, 6.0, 8.0, 10., 0.0, 0.0, 0.0, 0.0},
- {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.}};
+ {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.},
+ {0,0,0,0,0, 0,0,0,0,0} /* last line */ };
int i, j, val_exp, min_exp;
double nex; /* number of decades in data */
int mid = -1; /* row in yloglab for major grid */
double mspac; /* smallest major grid spacing (pixels) */
int flab; /* first value in yloglab to use */
- double value, tmp;
+ double value, tmp, pre_value;
double X0,X1,Y0;
char graph_label[100];
mid++;
for(i = 0; yloglab[mid][i + 1] < 10.0; i++);
mspac = logscale * log10(10.0 / yloglab[mid][i]);
- } while(mspac > 2 * im->text_prop[TEXT_PROP_LEGEND].size && mid < 5);
+ } while(mspac > 2 * im->text_prop[TEXT_PROP_LEGEND].size && yloglab[mid][0] > 0);
if(mid) mid--;
/* find first value in yloglab */
- for(flab = 0; frexp10(im->minval, &tmp) > yloglab[mid][flab]; flab++);
+ for(flab = 0; yloglab[mid][flab] < 10 && frexp10(im->minval, &tmp) > yloglab[mid][flab] ; flab++);
if(yloglab[mid][flab] == 10.0) {
tmp += 1.0;
flab = 0;
X1=im->xorigin+im->xsize;
/* draw grid */
- while(1) {
+ pre_value = DNAN;
+ while(1) {
+
value = yloglab[mid][flab] * pow(10.0, val_exp);
+ if ( AlmostEqual2sComplement(value,pre_value,4) ) break; /* it seems we are not converging */
+
+ pre_value = value;
Y0 = ytr(im, value);
if(Y0 <= im->yorigin - im->ysize) break;
/* yes we are loosing precision by doing tos with floats instead of doubles
but it seems more stable this way. */
-static int AlmostEqual2sComplement (float A, float B, int maxUlps)
-{
-
- int aInt = *(int*)&A;
- int bInt = *(int*)&B;
- int intDiff;
- /* Make sure maxUlps is non-negative and small enough that the
- default NAN won't compare as equal to anything. */
-
- /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
-
- /* Make aInt lexicographically ordered as a twos-complement int */
-
- if (aInt < 0)
- aInt = 0x80000000l - aInt;
-
- /* Make bInt lexicographically ordered as a twos-complement int */
-
- if (bInt < 0)
- bInt = 0x80000000l - bInt;
-
- intDiff = abs(aInt - bInt);
-
- if (intDiff <= maxUlps)
- return 1;
-
- return 0;
-}
/* draw that picture thing ... */
int