I was seeing weird behavior after enabling domain panning on a chart with a domain PeriodAxis. On each panning tick the chart's domain axis would grow a little bit. After some googling I found this post:
http://sourceforge.net/p/jfreechart/bugs/1089/
I subclassed PeriodAxis, overrode it's pan method and put some Sys.outs in it, and I am seeing something like the link above describes. In a nutshell, the Range of my PeriodAxis is expanding by exactley 60,000 every pan tick. I assume its due to Range's strictfp arithmetic??
Maybe this is fixed in the latest version of JFreeChart? But unfortunately we're kind of stuck with an older version of JFreeChart due to circumstances outside my control. So, I'm trying to determine the best way to fix it in my version. Interestingly, it kind of works if I just add 30,000 to the lower bound and subtract 30,000 from the upper bound. Any suggestions for a better fix? The link above suggests a fix, but I don't really understand how to implement it.
Panning on PeriodAxis -- double rounding, range expanding
-
- JFreeChart Project Leader
- Posts: 11734
- Joined: Fri Mar 14, 2003 10:29 am
- antibot: No, of course not.
- Contact:
Re: Panning on PeriodAxis -- double rounding, range expandin
It is not fixed in the current release, but I will take a look at it and see if it can be fixed for the next release.
David Gilbert
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
JFreeChart Project Leader


Re: Panning on PeriodAxis -- double rounding, range expandin
Here's the temporary fix I'm going with, that seems to work for our use case. Our PeriodAxis's Range is showing 16 minutes worth of data.
It's far from perfect, as it normalizes all spanning ticks to move the same amount, and assumes that adding 30000 to lower and subtracting 30000 to upper is ok to do.
It's far from perfect, as it normalizes all spanning ticks to move the same amount, and assumes that adding 30000 to lower and subtracting 30000 to upper is ok to do.

Code: Select all
PeriodAxis axisDomain = new PanFixPeriodAxis(null);
axisDomain.setAutoRangeTimePeriodClass(Minute.class);
axisDomain.setMajorTickTimePeriodClass(Minute.class);
...
plot.setDomainAxis(axisDomain);
class PanFixPeriodAxis extends PeriodAxis
{
public PanFixPeriodAxis(String label) {
super(label);
}
// DecimalFormat df2 = new DecimalFormat( "#,###,###,###,##0.0000" ); // more readable debug stmts.
/**
* Slides the axis range by the specified percentage.
*
* @param percent the percentage.
* @since 1.0.13
*/
public void pan(double percent)
{
/* Problem -- Period Axis's range expands when panning due to strictfp double rounding
* in Range class. In our specific case, it expands by exactley 60,000 (1 minute?) each span tick.
*/
Range range = getRange();
// double length = range.getLength();
// double adj = length * percent;
// long adj2 = (long)(adj);
double adj = 60000;
if ( percent < 0 ) adj = -60000;
//System.out.println( "pan() percent=" + df2.format(percent) +
// ", lowerBound=" + df2.format(range.getLowerBound()) + ", upperBound=" + df2.format(range.getUpperBound()) +
// ", adj=" + df2.format(adj) + ", adj2=" + adj2 + ", length=" + df2.format(length) );
// double lower = range.getLowerBound() + adj2;
// double upper = range.getUpperBound() + adj2;
long lower = (long) (range.getLowerBound() + adj);
long upper = (long) (range.getUpperBound() + adj);
// horrible hack, but this kind of fixes it.
upper -= 30000;
lower += 30000;
// setRange(lower, upper);
setLowerBound( lower );
setUpperBound( upper );
Range r2 = getRange();
// System.out.println( "New Vals: lower=" + df2.format(lower) + ", upper=" + df2.format(upper) );
// System.out.println( " r2.lower=" + df2.format(r2.getLowerBound()) + ", r2.upper" + df2.format(r2.getUpperBound()) +
// ", length" + getRange().getLength() );
}
}
Re: Panning on PeriodAxis -- double rounding, range expandin
Just thought I'd pass on a slightly better solution we found for this problem. Turns out that panning worked much better using Seconds rather than Minutes. It still has rounding errors and expands most panning ticks, but the expansion is by the second instead of by the minute, so it's not so noticeable. We switched over to code like this and most of our panning problems went away:
The only issue after the change was the grid was showing way too many lines for our taste. Not sure if we solved that problem in the most elegant way, but we ended up overriding XYPlot's drawDomainGridlines() to only draw grid lines on minute boundries:
and then we had to create our chart by calling a custom version ChartFactory.createTimeSeriesChart() that instantiated the custom XYPlot class instead of XYPlot.
Only thing left is to figure out how to customize the tick marks to what we want...
Code: Select all
PeriodAxis axisDomain = new PeriodAxis(null);
axisDomain.setAutoRangeTimePeriodClass(Second.class);
axisDomain.setMajorTickTimePeriodClass(Second.class);
PeriodAxisLabelInfo[] info = new PeriodAxisLabelInfo[1];
info[0] = new PeriodAxisLabelInfo(Second.class,
new SimpleDateFormat("K:mm a"), new RectangleInsets(2, 2, 2, 2),
new Font("SansSerif", Font.BOLD, 10), Color.blue, false,
new BasicStroke(0.0f), Color.lightGray);
axisDomain.setLabelInfo(info);
plot.setDomainAxis(axisDomain);
Code: Select all
// Only show grid lines per minute
if ( t%60000 == 0 )
{
((AbstractXYItemRenderer) r).drawDomainLine(g2, this,
getDomainAxis(), dataArea, tick.getValue(),
gridPaint, gridStroke);
}
Only thing left is to figure out how to customize the tick marks to what we want...
Re: Panning on PeriodAxis -- double rounding, range expandin
After facing the same problem I've found that setting the autorange time period class to Millisecond.class solved the issue:
PeriodAxis axis = ....
axis.setAutoRangeTimePeriodClass( Millisecond.class );
Note that even having set it to Millisecond I'm using the axis to display bigger periods (such as hours, days, etc) and still works fine. Note that I haven't tested the auto range feature in the chart because I use my own implementation.
PeriodAxis axis = ....
axis.setAutoRangeTimePeriodClass( Millisecond.class );
Note that even having set it to Millisecond I'm using the axis to display bigger periods (such as hours, days, etc) and still works fine. Note that I haven't tested the auto range feature in the chart because I use my own implementation.