Page 1 of 1

stacked bars

Posted: Mon Aug 13, 2012 11:01 am
by 10051902
Hi,

I have groups of bar series in a chart, with 2 stack groups.
Each color and group is a bar series.
I have the MultiBar property set to mbStacked, and StackGroup set to 0 for first group and 1 for the second.
Each group is on a custom y-axis, bottom axis is shared for all series.
The bars of the groups do not lign up on the bottom axis, while with a single group they do. See attachments.

Is there any way to make them lign up when stacked ?

Re: stacked bars

Posted: Mon Aug 13, 2012 2:19 pm
by yeray
Hi,
strobbekoen wrote:Is there any way to make them lign up when stacked ?
The stacked style wasn't thought to be split in different axes. That's why an offset is applied to the groups. However, this offset could be undone ie using the OnGetBarStyle as follows (having 2 stack groups):

Code: Select all

Procedure TForm1.SeriesGetBarStyle(Sender:TCustomBarSeries; ValueIndex:Integer; var TheBarStyle:TBarStyle);
begin
  if Sender.StackGroup=0 then
    Sender.OffsetPercent:=50
  else
    Sender.OffsetPercent:=-50;
end;
Note an extra repaint may be needed for the change to be applied to the first two columns too.
FYI, here it is the code of my Create method, where I set up the chart and the series in my testing program:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var nGroup, nSeries: Integer;
begin
  Chart1.Legend.Visible:=false;
  Chart1.MarginLeft:=10;

  for nGroup:=0 to 1 do
  begin
    with Chart1.CustomAxes.Add as TChartAxis do
    begin
      StartPosition:=nGroup * (100 div 2);
      EndPosition:=(nGroup + 1) * (100 div 2);
    end;

    for nSeries:=0 to 4 do
      with Chart1.AddSeries(TBarSeries) as TBarSeries do
      begin
        CustomVertAxis:=Chart1.CustomAxes[nGroup];
        MultiBar:=mbStacked;
        StackGroup:=nGroup;
        Marks.Visible:=false;
        Transparency:=20;
        FillSampleValues(10);

        OnGetBarStyle:=SeriesGetBarStyle;
      end;
  end;

  Chart1.Draw;
end;

Re: stacked bars

Posted: Mon Aug 13, 2012 3:23 pm
by 10051902
Thank you for the helpful answer, it works.

Since I create the series at run time, I set the OffsetPercent directly when creating the series instead of using the event.

I attached a few more shots:

iqo2_periodic3 and iqo2_periodic4 display the same period in weeks, but one with a single stackgroup, the other with two.
You can see the bar width has changed, I assume because the chart calculates the bar width thinking the bars of the two stackgroups will not be aligned on the bottom axis (as was the issue originally); so there is more white space.
Is it possible to remove this white space and get the same bar widths as for the single stackgroup ?

iqo2_periodic4 displays the same period as above in days (so there are more points).
I use Chart3DPercent (set to 5) to display the bars in 3D.
The bottom axis ticks (with the labels) are in the center of the front of the bars, while the grid is aligned to the center of the back of the bars.
As the bars get more narrow, this creates a visual effect that the bars are slightly misaligned (alignment is actually correct though).
As far as I can think of is to calibrate the 3D percentage according to the number of data points instead of a fixed value.
Or maybe you have a better alternative ?

Many thanks.

Re: stacked bars

Posted: Mon Aug 13, 2012 3:25 pm
by 10051902
Sorry, I forgot the attachments.

Re: stacked bars

Posted: Tue Aug 14, 2012 9:26 am
by yeray
Hi,
strobbekoen wrote:iqo2_periodic3 and iqo2_periodic4 display the same period in weeks, but one with a single stackgroup, the other with two.
You can see the bar width has changed, I assume because the chart calculates the bar width thinking the bars of the two stackgroups will not be aligned on the bottom axis (as was the issue originally); so there is more white space.
Is it possible to remove this white space and get the same bar widths as for the single stackgroup ?
You could use the CustomBarWidth property to define the bars width. However, it means this width should be calculated by you. Find below an example of it:

Code: Select all

uses Series;

procedure TForm1.FormCreate(Sender: TObject);
var nGroup, nSeries, tmpWidth: Integer;
begin
  Chart1.Legend.Visible:=false;
  Chart1.MarginLeft:=10;

  for nGroup:=0 to 1 do
  begin
    with Chart1.CustomAxes.Add as TChartAxis do
    begin
      StartPosition:=nGroup * (100 div 2);
      EndPosition:=(nGroup + 1) * (100 div 2);
    end;

    for nSeries:=0 to 4 do
      with Chart1.AddSeries(TBarSeries) as TBarSeries do
      begin
        CustomVertAxis:=Chart1.CustomAxes[nGroup];
        OffsetPercent:=50+(nGroup*-1)*100;
        MultiBar:=mbStacked;
        StackGroup:=nGroup;
        Marks.Visible:=false;
        Transparency:=20;
        FillSampleValues(10);

        if nSeries=0 then
        begin
          Chart1.Draw;
          tmpWidth:=Round((BarWidthPercent*0.01)*(GetHorizAxis.IAxisSize div 11));
          Chart1.Axes.Bottom.MinimumOffset:=tmpWidth;
          Chart1.Axes.Bottom.MaximumOffset:=tmpWidth;
        end;

        CustomBarWidth:=tmpWidth;
      end;
  end;
end;
strobbekoen wrote:iqo2_periodic4 displays the same period as above in days (so there are more points).
I use Chart3DPercent (set to 5) to display the bars in 3D.
The bottom axis ticks (with the labels) are in the center of the front of the bars, while the grid is aligned to the center of the back of the bars.
As the bars get more narrow, this creates a visual effect that the bars are slightly misaligned (alignment is actually correct though).
As far as I can think of is to calibrate the 3D percentage according to the number of data points instead of a fixed value.
Or maybe you have a better alternative ?
I don't know what will be the best alternative, but I can think on:

- Use the AxisBehind (true by default) to move the grid to the front:

Code: Select all

  Chart1.AxisBehind:=false;
- Move the bottom axis to the back. Note you may need to increment the TickLength too.
All this still gives an unaligned aspect.

Code: Select all

  Chart1.Chart3DPercent:=5;
  with Chart1.Axes.Bottom do
  begin
    ZPosition:=100;
    TickLength:=10;
  end;
- Use the grid centered property to move the grid between the bars.

Code: Select all

  Chart1.Axes.Bottom.Grid.Centered:=true;
- Simply hide the bottom axis grid:

Code: Select all

  Chart1.Axes.Bottom.Grid.Visible:=false;
And congratulations for the application. Looks promising :!:

Re: stacked bars

Posted: Tue Aug 14, 2012 10:21 am
by 10051902
Thank you for the suggestions and the compliment.
I will try your suggestions and see which one works best. Thanks for the help :)