"Carpet Plot" Labels

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Paul Holden
Newbie
Newbie
Posts: 11
Joined: Wed Dec 01, 2021 12:00 am

"Carpet Plot" Labels

Post by Paul Holden » Thu Nov 03, 2022 11:28 am

I am trying to build a "Carpet Plot" of 2 intersecting groups of "Iso Lines" with labels on the lines showing the Iso value of the line. As the data grid is based on the 2 Iso parameters, I can't plot them as contours in TeeChart, so I have created a grid of XY Line series. I could not find any way to add a single label to a line series, so I created an invisible grid of single point Point Series and used the point label to display the line Iso value. The problem with this approach was that the point series labels hijacked the bottom axis and I had to tie them to an invisible top axis. See attached screen shots.

My questions are:
Is there a better way to create the Carpet Plot?
Is there a way to add a label to an arbitrary position (preferably in XY coordinates) on a Line Series?
Is there a way to add labels to a series point that does not mess up the XY axis?
2022-11-03 09_36_19-Window.png
Layout as required
2022-11-03 09_36_19-Window.png (45.29 KiB) Viewed 4094 times
2022-11-03 09_54_20-Window.png
Messed up X Axis
2022-11-03 09_54_20-Window.png (41.9 KiB) Viewed 4094 times

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

Re: "Carpet Plot" Labels

Post by Yeray » Mon Nov 07, 2022 3:04 pm

Hello,

You could use TAnnotationTools to draw your texts. Ie:

Code: Select all

uses Series, TeeTools;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=False;
  Chart1.Gradient.Visible:=False;
  Chart1.Color:=clWhite;
  Chart1.Walls.Back.Gradient.Visible:=False;
  Chart1.Walls.Back.Color:=clWhite;

  Chart1.AddSeries(TLineSeries).FillSampleValues;

  Chart1.Draw;

  with TAnnotationTool(Chart1.Tools.Add(TAnnotationTool)) do
  begin
    Text:='Text for ValueIndex 5';
    Left:=Chart1[0].CalcXPos(5);
    Top:=Chart1[0].CalcYPos(5);
    Shape.Transparent:=True;
  end;
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

Paul Holden
Newbie
Newbie
Posts: 11
Joined: Wed Dec 01, 2021 12:00 am

Re: "Carpet Plot" Labels

Post by Paul Holden » Tue Nov 08, 2022 11:54 am

Is there a best practice for managing Annotations created at run-time as in your example? The main problem I am having is coping with repaints/rebuilds creating multiple copies of the same thing. The annotations don't seem to have a fixed name and selective deletion from the Tools array would rely on knowing the array position. The Annotation Text is not generally known at design time, so I can't use that without keeping a shadow copy of text somewhere. Or maybe I need to keep a local pointer to the annotation? It would be much easier if I could delete/remove in design-time code with a known name.

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

Re: "Carpet Plot" Labels

Post by Yeray » Tue Nov 08, 2022 1:11 pm

Hello,

Indeed, you could store the annotations in variables, or in an array. Or you could just use the Tools array.
Find here an example showing how to add an annotation tool every time the chart is clicked and how to remove the annotation that is right-clicked:

Code: Select all

uses Series, TeeTools;

var mouseDownPos: TPoint;

procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  mouseDownPos:=Point(X,Y);
end;

procedure TForm1.Chart1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var i: Integer;
    annotation: TAnnotationTool;
begin
  if (mouseDownPos.X = X) and (mouseDownPos.Y = Y) then
    if Button = mbRight then
    begin
      for i:=Chart1.Tools.Count-1 downto 0 do
        if Chart1.Tools[i] is TAnnotationTool then
        begin
          annotation:=TAnnotationTool(Chart1.Tools[i]);

          if annotation.Clicked(X, Y) then
          begin
            Chart1.Tools.Delete(Chart1.Tools.IndexOf(annotation));
            Chart1.Draw;
            Exit;
          end;
        end;
    end
    else
    if Button = mbLeft then
      with TAnnotationTool(Chart1.Tools.Add(TAnnotationTool)) do
      begin
        Text:='Annotation at X: ' + IntToStr(X) + ', Y: ' + IntToStr(Y);
        Left:=X;
        Top:=Y;
      end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=False;
  Chart1.Gradient.Visible:=False;
  Chart1.Color:=clWhite;
  Chart1.Walls.Back.Gradient.Visible:=False;
  Chart1.Walls.Back.Color:=clWhite;
  Chart1.Legend.Hide;

  Chart1.AddSeries(TLineSeries).FillSampleValues;
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

Paul Holden
Newbie
Newbie
Posts: 11
Joined: Wed Dec 01, 2021 12:00 am

Re: "Carpet Plot" Labels

Post by Paul Holden » Tue Nov 08, 2022 2:14 pm

Thanks, but it isn't really what I need. I am now thinking of using the component Tag property to mark sets of annotations for deletion, which should work. But in some cases it would still be better to have a fixed annotation "Name" available rather than having to store a link to the annotation so that I can access it directly for edit/deletion. Is it possible to add this feature?

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

Re: "Carpet Plot" Labels

Post by Yeray » Wed Nov 09, 2022 12:14 pm

Hello,

Since the TAnnotationTool is a TComponent, it already has a Name property you can use. Ie:

Code: Select all

uses TeeTools;

procedure TForm1.BDeleteCheckedClick(Sender: TObject);
var i, j: Integer;
begin
  for i:=CheckListBox1.Items.Count-1 downto 0 do
    if CheckListBox1.Checked[i] then
      for j:=Chart1.Tools.Count-1 downto 0 do
        if Chart1.Tools[j].Name=CheckListBox1.Items[i] then
        begin
          Chart1.Tools.Delete(j);
          CheckListBox1.Items.Delete(i);
          break;
        end;

  Chart1.Draw;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  for i:=0 to 9 do
  begin
    with TAnnotationTool(Chart1.Tools.Add(TAnnotationTool)) do
    begin
      Name:='Annotation'+IntToStr(i);
      Text:='Annotation'+IntToStr(i);
      Left:=20+(i div 5)*80;
      Top:=20+(i mod 5)*24;
    end;

    CheckListBox1.Items.Add(Chart1.Tools[i].Name);
  end;
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

Post Reply