Stacked Bar Chart and Marks

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Stacked Bar Chart and Marks

Post by Errol » Thu Feb 20, 2014 5:14 am

Lithology_Chart_Labels.png
Lithology_Chart_Labels.png (12.22 KiB) Viewed 20757 times
I am using a Stacked Bar Chart to represent a lithology column from a well. As an alternative to drawing a legend, I want to be able to put labels directly on the bar chart. However, they always draw in the next lithology, and there does not appear to be a command akin to Marks | Arrows | Distance in the Chart Editor that I could set to a negative value and shift the labels to the centre of the strata. As a result, the labels end up as in the attachment. Any suggestions welcomed.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Narcís » Thu Feb 20, 2014 9:44 am

Hi Errol,

Yes, you can do this:

Code: Select all

  Series1.Marks.ArrowLength:=-20;
However, there's new MarksOnBar property to achieve what you request:

Code: Select all

  Series1.MarksOnBar:=True;
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Thu Feb 20, 2014 10:56 pm

Narcis

Thanks for your reply. I agree that Marks.ArrowLength can be set to a negative value (I had a code error before) but I am still unable to individually position each mark. The marks offset is always the same and in pixels so that when I zoom the label is no longer in the centre of the bar. The MarksOnBar command worked but put the marks just below each bar rather than in the centre of the bar. The code I use is shown below (Depth is the vertical length of each bar in the stack), and the results are in the attachment.

Clearly I am doing something wrong - what might it be?

Code: Select all

procedure TUnitBarSeries.DrawBar(BarIndex, StartPos, EndPos: Integer);

begin
  // go to dataset record for this index
  TkbmMemTable(self.DataSource).RecNo := BarIndex + 1;
  Brush.Style :=
    TBrushStyle(TkbmMemTable(self.DataSource).FieldByName('Pattern').asInteger); 
  Brush.Color :=
    TColor(TkbmMemTable(self.DataSource).FieldByName('Background').asInteger);
  Marks.Visible := True;
  Marks.ArrowLength :=
    -(TkbmMemTable(self.DataSource).FieldByName('Depth').asInteger) div 2;
  ShowInLegend := False;

  inherited DrawBar(BarIndex,StartPos,EndPos);

end;
Lithology_Chart_Labels002.png
Lithology_Chart_Labels002.png (6.82 KiB) Viewed 20717 times

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Narcís » Fri Feb 21, 2014 9:45 am

Hi Errol,

You can use custom marks position, something as the example Yeray Alonso made here.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Yeray » Fri Feb 21, 2014 10:16 am

Hi Errol,

You can also try with:

Code: Select all

MarksLocation:=mlCenter;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Mon Feb 24, 2014 3:16 am

Hi Yeray and Narcis

I am pleased to report that the following code places the marks in the center of each bar, and they remain in place when the chart is zoomed.

Many thanks

Errol

Code: Select all

procedure TQSCollection.InsertGeologicalSeries(aCodeFld,aFld:string);

begin

// code here to load data from dataset into kbmMemTable and calculate depth increments

  SeriesListB.AddObject(sTitle, TUnitBarSeries.Create(Owner));
  iIndex := SeriesListB.IndexOf(sTitle);
  with TUnitBarSeries(SeriesListB.Objects[iIndex]) do
  begin
    AutoMarkPosition := false;
    MultiBar := mbSelfStack;
    CustomBarWidth := 80;
    Marks.Visible := True;
    MarksLocation := mlCenter;
    MarksOnBar := True;

// additional code here

  end;
end;


Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Thu Mar 06, 2014 3:22 am

I am able to place marks in the center of each bar on my stacked bar chart as required, and they stay in the correct place when I pan or zoom the chart. However, if I first drag one of the marks, this appears to lock the marks in the chart (see attachments). The only way to reset is to select another data set. How can I reset the marks to auto as I pan or zoom? I use an OnAfterDraw event to allow marks dragging (see code snippet).
Marks_Dragged_1.png
Marks_Dragged_1.png (8.26 KiB) Viewed 20655 times
BarChart_Panned_2.png
BarChart_Panned_2.png (7.57 KiB) Viewed 20666 times

Code: Select all

procedure TQSCollection.ChartAfterDraw(Sender: TObject);
var
  DragTool: TDragMarksTool;
begin
  self.Owner.Chart.Tools.Add(TDragMarksTool);
  DragTool.Active := true;
end;

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Yeray » Thu Mar 06, 2014 3:03 pm

Hi Errol,
Errol wrote:I am able to place marks in the center of each bar on my stacked bar chart as required, and they stay in the correct place when I pan or zoom the chart. However, if I first drag one of the marks, this appears to lock the marks in the chart (see attachments). The only way to reset is to select another data set. How can I reset the marks to auto as I pan or zoom?
Take a look at the answer here:
http://www.teechart.net/support/viewtop ... 033#p34033
Errol wrote:I use an OnAfterDraw event to allow marks dragging (see code snippet).

Code: Select all

procedure TQSCollection.ChartAfterDraw(Sender: TObject);
var
  DragTool: TDragMarksTool;
begin
  self.Owner.Chart.Tools.Add(TDragMarksTool);
  DragTool.Active := true;
end;
Is this code working for you? Note the AfterDraw event is fired every time the chart is redrawn. This could be many times if you allow scroll or zoom. In that case, you could be creating more and more TDragMarksTool objects and adding to the chart list of tools. I'd strongly suggest you to move that code to the Form.Create or similar.
Even more, you are defining a variable (DragTool) and not initializing it. I guess the program doesn't crash because the compiler probably detects setting DragTool.Active:=true has little sense and skips it.
Sounds better to me like this:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var
  DragTool: TDragMarksTool;
begin
  Chart1.AddSeries(TBarSeries).FillSampleValues();

  DragTool:=Chart1.Tools.Add(TDragMarksTool) as TDragMarksTool;
  DragTool.Active := true;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Fri Mar 07, 2014 6:01 am

Yeray

Thanks for the suggestion regarding the OnAfterDraw event. I inherited this code and hadn't really thought about it, but zooming and panning now works much better since I adopted your suggestions.

I have overcome the "sticky" marks by simply calling Chart.RefreshData on Zoom, UndoZoom and Scroll. However, it would be nice to do this only if a mark has been dragged. Is there a Marks.HasBeenDragged boolean that I can interrogate to see if I need to refresh the chart?

Thanks and regards

Errol

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Yeray » Fri Mar 07, 2014 9:59 am

Hi Errol,
Errol wrote:Thanks for the suggestion regarding the OnAfterDraw event. I inherited this code and hadn't really thought about it, but zooming and panning now works much better since I adopted your suggestions.
You're welcome! :)
Errol wrote:I have overcome the "sticky" marks by simply calling Chart.RefreshData on Zoom, UndoZoom and Scroll. However, it would be nice to do this only if a mark has been dragged. Is there a Marks.HasBeenDragged boolean that I can interrogate to see if I need to refresh the chart?
No but you can create you own boolean, initialize it at OnCreate and change it at with the TDragMarksTool OnDraggedMark event. Ie:

Code: Select all

var HasBeenDragged: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.Legend.Visible:=false;
  Chart1.View3D:=false;

  Chart1.AddSeries(TBarSeries).FillSampleValues;

  HasBeenDragged:=false;
  (Chart1.Tools.Add(TDragMarksTool) as TDragMarksTool).OnDraggedMark:=DraggedMark;
end;

procedure TForm1.DraggedMark(Sender:TDragMarksTool; Index:Integer; Button:TMouseButton; Shift: TShiftState; X,Y: Integer);
begin
  HasBeenDragged:=true;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Sat Mar 15, 2014 5:12 am

Good afternoon Yeray

Is there any way to left justify and offset marks on a (vertical) stacked bar chart. Properties such as MarksLocation and Marks.TextAlignment seem to control placement in the vertical direction, but I would like to control in the horizontal direction.

Regards

Errol

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Yeray » Mon Mar 17, 2014 3:35 pm

Hi Errol,

Here you have an example of custom positioning for the Bar Marks:

Code: Select all

uses Series;

procedure TForm1.FormCreate(Sender: TObject);
var s, i: Integer;
begin
  Chart1.Legend.Visible:=false;
  Chart1.View3D:=false;

  for s:=0 to 4 do
    with Chart1.AddSeries(TBarSeries) as TBarSeries do
    begin
      for i:=0 to 4 do
        Add(25+random*75, 'S' + IntToStr(s) + ', I' + IntToStr(i));

      MultiBar:=mbStacked;
      MarksLocation:=mlCenter;
      MarksOnBar:=true;
    end;

  PlaceMarks;
end;

procedure TForm1.PlaceMarks;
var s, i, tmpSize: Integer;
begin
  Chart1.Draw;

  for s:=0 to Chart1.SeriesCount-1 do
    if Chart1[s] is TBarSeries then
      with Chart1[s] as TBarSeries do
      begin
        for i:=0 to Count-1 do
          with Marks.Positions[i] do
          begin
            Custom:=true;
            LeftTop.X:=CalcXPos(i);

            if MarksLocation=mlEnd then
              LeftTop.Y:=CalcYPos(i)
            else
            begin
              tmpSize:=CalcYSizeValue(YValue[i]);
              if MarksLocation=mlStart then
                LeftTop.Y:=CalcYPos(i)+tmpSize-Marks.Height
              else
                LeftTop.Y:=CalcYPos(i)+(tmpSize div 2)-(Marks.Height div 2);
            end;
          end;
      end;
end;

procedure TForm1.Chart1Scroll(Sender: TObject);
begin
  PlaceMarks;
end;

procedure TForm1.Chart1Zoom(Sender: TObject);
begin
  PlaceMarks;
end;

procedure TForm1.Chart1UndoZoom(Sender: TObject);
begin
  PlaceMarks;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked Bar Chart and Marks

Post by Yeray » Wed Mar 19, 2014 9:48 am

Hi again Errol,

I added the possibility to have some property to horizontally align the marks in the Bars into the wish list so it can be considered for inclusion in future releases:
http://bugs.teechart.net/show_bug.cgi?id=645
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Sun Mar 23, 2014 10:57 pm

Good morning Yeray

Thanks for all your help on this topic, and I look forward to tools to control basic marks positioning without having to go down the custom positioning route.

I have another problem which puzzles me - I am unable to hide the marks on my self-stacked bar chart. In the code snippet, the font size changes but the Marks.Visible setting is ignored, regardless of the value of the boolean ShowLabelText. Any ideas why this might be occurring?

Best regards

Errol

Code: Select all

  with TUnitBarSeries(SeriesListB.Objects[iIndex]) do
  begin
    MultiBar := mbSelfStack;
    CustomBarWidth := 80;
    MarksLocation := mlCenter;
    MarksOnBar := True;
    Marks.Visible := self.owner.ShowLabelText;
    Marks.Font.Size := self.owner.LabelFont;
    ShowInLegend := false;
    HorizAxis := aBottomAxis;
    VertAxis := aLeftAxis;
...
    active := true;
  end;

Errol
Newbie
Newbie
Posts: 75
Joined: Thu Jul 11, 2013 12:00 am

Re: Stacked Bar Chart and Marks

Post by Errol » Sun Mar 23, 2014 11:18 pm

Hi Yeray

Can you please abandon my last request regarding hiding marks. I see that the program calls an override version of DrawBar that overrides the Marks visible setting. Sorry about this.

Regards

Errol

Post Reply