|
Weird overlap in enumerated scale bar chart |
Posted by Seppo on May-26-2014 23:42 |
|
I?m trying to create a chart which would show number of items in bar chart. Purpose is to
visualize how many items are there in each step hence the enumerated scale (setXData).
The problem is that the bar gap calculation depends on how many items are there in the
chart. If there are enough data, the chart looks on, but in smaller data amount the bars
overlap and the chart looks messy. I can adjust the bar gap with setBarGap, but the value
required depends on the data.
Is there anything that could be done here?
You will see the difference by toggling $small_set from true to false.
<?php
require_once("../lib/phpchartdir.php");
$small_set = true;
# The data for the bar chart
if ($small_set) {
$data = array(6,9,7,9,1);
$labels = array(14,15,16,20,22);
$title = 'small set overlaps';
} else {
$data = array(6,9,7,8,9,10,9,1);
$labels = array(14,15,16,17,18,19,20,22);
$title = 'bigger set does not overlap';
}
# The labels for the bar chart
# Create a XYChart object of size 250 x 250 pixels
$c = new XYChart(600, 300);
$c->addTitle($title);
# Set the plotarea at (30, 20) and of size 200 x 200 pixels
$c->setPlotArea(30, 20, 550, 250);
# Add a bar chart layer using the given data
$layer = $c->addBarLayer($data);
$layer->setXData($labels);
# Output the chart
header("Content-type: image/png");
print($c->makeChart2(PNG));
?>
|
Re: Weird overlap in enumerated scale bar chart |
Posted by Peter Kwan on May-27-2014 03:58 |
|
Hi Seppo,
For unevenly spaced bars, there are always confusion on how wide is the bar.
For example, if there are 5 bars at x = 2, 4, 6, 8, 12, should each bar be 2 x-unit wide, or
should they be 1 x-unit wide (with some empty space between the bars) ? It is often
difficult or impossible to determine automatically, and setBarWidth has to be used to
inform ChartDirector of the intended bar width.
For your case, if the scale is enumerated, it means each position is supposed to have a
bar (if we also include empty or zero bar). Instead of using setXData, you can simply
insert NoValue for the empty bars. As there are no x-coordinates for the bars,
ChartDirector will assume they are evenly spaced and can determine the width without
confusion.
For your first case,
$data = array(6,9,7,9,1);
$labels = array(14,15,16,20,22);
you can change the arrays to be:
$enumeratedData = array(6, 9, 7, NoValue, NoValue, NoValue, 9, NoValue, 1);
$enumeratedLabels = array(14, 15, 16, 17, 18, 19, 20, 21, 22);
and then use:
$layer = $c->addBarLayer($enumeratedData);
$c->xAxis->setLabels($enumeratedLabels);
To convert from your original data arrays to the new data arrays, you may use something
like:
$minX = min($labels);
$enumeratedData= array_pad(array(), max($labels) - $minX + 1, NoValue);
$enumeratedLabels = array(array(), count($enumeratedData), 0);
for ($i = 0; $i < count($data); ++$i) $enumeratedData[$labels[$i] - $minX] = $data[$i];
for ($i = 0; $i < count($enumeratedLabels); ++$i) $enumeratedLabels[$i] = $minX + $i;
Hope this can help.
Regards
Peter Kwan |
Re: Weird overlap in enumerated scale bar chart |
Posted by Seppo on May-27-2014 04:17 |
|
Peter,
thanks for the fast answer.
the reason for using the setXData is that I do not know what the data is. There might be
random gaps between labels, and using setXData I am trying to make the x-axis numeric (to
include all numbers between min and max). The assumption was that I would get bar for
each number in the chart's scale where there is label/data pair. The bar width would be fitted
as if there was a bar in each x-axis number.
If you look at the bigger set example, it works as expected. Even if I do not have label/data
pair for number 21, the widths of bars for other labels are just fine. When gaps between
labels get bigger (smaller set), the bar widths grow. Now that both charts have same scale
(from 14 to 22) I was expecting the bar widths to be the same. What is the logic for the bar
width calculation in the smaller set case?
Other than filling the data with the missing label/NoValue pairs, is there a way to use
setXData (or similar) to do this automatically. I've tried to use setBarWidth, but the value
required seems to be dependent on number of label/data pairs in the data.
--
Seppo |
Re: Weird overlap in enumerated scale bar chart |
Posted by Peter Kwan on May-27-2014 16:51 |
|
Hi Seppo,
If you know that each integer x-coordinates are supposed to have a bar (if we also count
empty bars), so the number of bars must be max($labels) - min($labels) + 1. Therefore, the
bar width must be (assume the bar gap is 20%):
$barWidth = $c->getPlotArea()->getWidth() / (max($labels) - min($labels) + 1) * 0.8;
$layer->setBarWidth($barWidth);
Hope this can help.
Regards
Peter Kwan |
Re: Weird overlap in enumerated scale bar chart |
Posted by Seppo on May-27-2014 17:19 |
|
Peter,
that did the trick. I used:
$layer->setBarWidth($c->getPlotArea()->getWidth() / ($c->xAxis->getMaxValue() - $c-
>xAxis->getMinValue() + 1) * 0.8);
Thank you.
--
Seppo |
|