Broken auto-range in stacked area charts: StackedXYAreaRenderer(2) ignore dataBoundsIncludesVisibleSeriesOnly property

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Post Reply
NeonMika
Posts: 1
Joined: Tue Feb 19, 2019 4:55 pm
antibot: No, of course not.

Broken auto-range in stacked area charts: StackedXYAreaRenderer(2) ignore dataBoundsIncludesVisibleSeriesOnly property

Post by NeonMika » Tue Feb 19, 2019 5:45 pm

I have been digging into this quite hard now, and I finally found the answer to the following problem:

I have multiple charts, line charts, as well as stacked area charts.
We allow users to zoom on the x-axis (domain axis), and we want to use auto-range for the y-axis (range axis).
While auto-range works fine for line charts, it does not work correctly for the stacked area charts.

Basically, the code looks like this:

Code: Select all

xyPlot.getDomainAxis().setRange(lowerBound, upperBound);
xyPlot.getRangeAxis().setUpperMargin(0.05);
xyPlot.getRangeAxis().setAutoRange(true);
This auto-range on the y-axis should only take into account data points that are visible on the zoomed chart.
And this works fine for line charts, and I will list why:
Line charts use an XYLineAndShapeRenderer, which inherit from AbstractXYItemRender, which in turn inherits from AbstractRenderer.

The AbstractRenderer defines the property dataBoundsIncludeVisibleSeriesOnly:

Code: Select all

/**
 * A flag that controls whether or not the renderer will include the
 * non-visible series when calculating the data bounds.
 *
 * @since 1.0.13
 */
private boolean dataBoundsIncludesVisibleSeriesOnly = true;
This property is correctly used in AbstractXYItemRender to calculate range bounds (which is done when auto-range calculation is triggered, i.e., when the new range of the y-axis has to be calculated). Please see the call to getDataBoundsIncludesVisibleSeriesOnly:

Code: Select all

/**
 * Returns the range of values the renderer requires to display all the
 * items from the specified dataset.
 *
 * @param dataset  the dataset ({@code null} permitted).
 * @param includeInterval  include the interval (if any) for the dataset?
 *
 * @return The range ({@code null} if the dataset is {@code null}
 *         or empty).
 *
 * @since 1.0.13
 */
protected Range findRangeBounds(XYDataset dataset, boolean includeInterval) {
	if (dataset == null) {
		return null;
	}
	if (getDataBoundsIncludesVisibleSeriesOnly()) {
		List visibleSeriesKeys = new ArrayList();
		int seriesCount = dataset.getSeriesCount();
		for (int s = 0; s < seriesCount; s++) {
			if (isSeriesVisible(s)) {
				visibleSeriesKeys.add(dataset.getSeriesKey(s));
			}
		}
		// the bounds should be calculated using just the items within
		// the current range of the x-axis...if there is one
		Range xRange = null;
		XYPlot p = getPlot();
		if (p != null) {
			ValueAxis xAxis = null;
			int index = p.getIndexOf(this);
			if (index >= 0) {
				xAxis = this.plot.getDomainAxisForDataset(index);
			}
			if (xAxis != null) {
				xRange = xAxis.getRange();
			}
		}
		if (xRange == null) {
			xRange = new Range(Double.NEGATIVE_INFINITY,
					Double.POSITIVE_INFINITY);
		}
		return DatasetUtils.findRangeBounds(dataset,
				visibleSeriesKeys, xRange, includeInterval);
	}
	return DatasetUtils.findRangeBounds(dataset, includeInterval);
} 
XYLineAndShapeRenderer does not override findRangeBounds, everything is fine, the bounds calculation during auto-range works for line charts.

Yet, things look differently for StackedXYAreaRenderer and StackedXYAreaRenderer2, which are used in stacked area charts.

Both are also child classes of AbstractXYItemRender, but they override findRangeBounds in such a fashion that dataBoundsIncludeVisibleSeriesOnly is not taken into account anymore.

This leads to the problem that data points that are outside of the currently visible chart part are taken into account for bounds calculation even if they shouldn't.
For example, if the highest visible y-point in a zoomed stacked area chart is 1, but somewhere outside the currently visible range there is a y-point of 10, the auto-range would still scale the y-axis to 10.

This is my first time writing on this forum and I do not know how this is handled in other cases...
I think this is a bug that should be fixed (and should not be that hard to fix).
Is it the best to also open an issue on the GitHub page?


Best wishes,
M

John Matthews
Posts: 482
Joined: Wed Sep 12, 2007 3:18 pm

Re: Broken auto-range in stacked area charts: StackedXYAreaRenderer(2) ignore dataBoundsIncludesVisibleSeriesOnly proper

Post by John Matthews » Fri Feb 22, 2019 12:08 am

It might help to post a short example or cite a demo that reproduces the problem. Is this pull request relevant?

Post Reply