BarChart: excluding NULL series from Category

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
zapfbier
Posts: 6
Joined: Fri Oct 19, 2007 3:25 pm

BarChart: excluding NULL series from Category

Post by zapfbier » Fri Oct 19, 2007 3:55 pm

Hi.

I think I am not the only one with this question: In a category bar chart (ChartFactory.createBarChart(...)), all categories have always the same width (in case of orientation = PlotOrientation.VERTICAL) or always the same height (PlotOrientation.HORIZONTAL). Even if a category has only 1 series, it takes up the same amount of width (height) as a category containing 30 series: There is width (height) reserved for the those series that aren't there.

Now if you imagine that you have a chart with 6 categories, the first one containing 30 series, and all the others containing only 1, the total amount of width (height) that is reserved is roughly equivalent to the width (height) that would be reserved if we had a chart with only 1 category containing 180 (!!!) series (=180 bars that will hardly fit inside a chart!). In the worst case, the reserved width (height) will be even more, if all the series happen to be disjunct (none of each contained in more than one category).

The goal to be achieved is that a category takes only the width (height) necessary to draw the series contained by it.

How can this be achieved? I've read through an through the internet, searched for hours and hours... and got nothing. I found suggestions telling me to extend/override BarRenderer, but I am not sure if this will do the thing. I have experimented a lot, overriding BarRenderer.calculateBarWidth(...) and BarRenderer.calculateSeriesWidth(...) but without any usefull results. Overriding BarRenderer.calculateBarW0(...) also doesn't seem to be a good approach because this controls only the position where the drawing of the bars is started.

I think that the solution would have something to do with overriding Axis or CategoryAxis. But I am not even sure what exactly I should override - in which way.

It comes to me that this might actually be quite a serious problem that's not easy to solve, because otherways it would've already been solved? :?:

Is any one out there with some good suggestions (please be VERY specific)? :(

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Fri Oct 19, 2007 4:25 pm

You should be able to create a CustomBarRenderer class that does this. You won't need to change the axis or any other code, it can all be done within the renderer.

For each category (column) you need to count how many series (rows) have non-null values. You might want to do this once in the renderer's initialise() method, because it would be less efficient to redo the calculation for every item in the dataset. You could also pre-calculate the bar width PER CATEGORY at this point (in the existing BarRenderer class, we pre-calculate the barWidth as a single value, because we assume that ALL categories have the same number of bars even if some of them aren't displayed (because they have null values)).

In the drawItem() method, you'll now need to calculate barW0 (the left edge of the bar for vertical bar charts) by taking into account the bar width for *that* category, and an index 'n' for the current item which is no longer the series index, but the 'series not containing null for this category' index.

After that (looking up the per-category bar width, and calculating barW0 appropriately), you can proceed as the existing code does.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

zapfbier
Posts: 6
Joined: Fri Oct 19, 2007 3:25 pm

Resizing Categories

Post by zapfbier » Mon Oct 22, 2007 6:23 pm

Hi,

I have done what you suggested, but I am not quite happy with the result. By overriding BarRenderer, the only thing that you can achive is getting larger (width) bars in those categories that do not have "all" series. Now you happen to see all bars, but this actually looks quite funny, because you get many bars with different widths, depending on how many series you have in a category.
What I actually want, is that the bars in the charts do all have the same width, but the categories "adapt" their width according to the amount of series they contain - a category containing only one series would only have the width of one bar (not considering the category margins, upper and lower margins, which would have to be added in case they're greater 0), while a category containing 2 bars would have width=2xbarwidth(+margins) and so on. You will actually have to override CategoryAxis.calculateCategorySize(...) and probably CategoryAxis.getCategoryStart(...) to achive this goal. I got the impression that it might not be the best approach to use a CategoryPlot for this requirement. Maybe it is better to use a XYPlot in combination with some kind of IntervalXYDataset?

If there is anyone interested in my custom BarRenderer, reply and I'll post it here for you.

Many greetings!

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Tue Oct 23, 2007 10:57 am

OK, for that you will need to create a custom CategoryAxis. I think that is achievable, but more difficult than the renderer change. You'd have to override getCategoryStart() and getCategoryEnd() at the minimum, and then probably do some debugging after that (I'm wondering if the labelling code might get messed up).

I'm not sure that switching to XYPlot will make this any easier.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

mausbull
Posts: 15
Joined: Wed Feb 22, 2006 3:36 pm
Contact:

Post by mausbull » Mon Jan 14, 2008 11:23 am

Hi,

since I've got a very similar problem (see http://www.jfree.org/phpBB2/viewtopic.php?t=23421) I wanted to know if you've found a solution to your problem.

thanks a lot

Locked