How to best draw (custom) legend with used Pointers

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
axrDegen
Newbie
Newbie
Posts: 31
Joined: Mon Jan 14, 2019 12:00 am

How to best draw (custom) legend with used Pointers

Post by axrDegen » Thu Jun 27, 2019 3:28 pm

Hi,

We have a 3D plot where for the points different Pointer styles are used:
3DPlotCapture.PNG
3DPlotCapture.PNG (220.18 KiB) Viewed 12810 times
What is the best way to draw/add a (custom) legend showing the different used Pointers with some custom text?
The requirement is to display (legend like) what the meaning of the different pointers is.

best regards

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

Re: How to best draw (custom) legend with used Pointers

Post by Yeray » Fri Jun 28, 2019 2:26 pm

Hello,

The easier would probably be to hide all your series from the legend (ShowInLegend:=False) and then create as many new series as pointers+text you want to show in the legend. These new series won't have any value but you can set them your pointers and titles to show them in the legend.
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

axrDegen
Newbie
Newbie
Posts: 31
Joined: Mon Jan 14, 2019 12:00 am

Re: How to best draw (custom) legend with used Pointers

Post by axrDegen » Mon Jul 01, 2019 2:49 pm

Hi Yeray,

indeed that works nicely:
WorkingPointersCapture.PNG
WorkingPointersCapture.PNG (54.71 KiB) Viewed 12790 times
It's just that the pointers in the legend a painted 2D and in the graphics these are
painted 3D. Is there a way to get 3D pointers in legend too ?

Thanks and best regards,

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

Re: How to best draw (custom) legend with used Pointers

Post by Yeray » Tue Jul 02, 2019 9:38 am

Hello,

Drawing legend items in 3D as the series using OpenGL is not so easy because all the objects are drawn following the view (rotation and elevation) except for the default legend, where we disable the 3D to draw it as a plane.

This means you can't use the Legend.Symbols.OnDraw event to draw 3D figures.
Instead, you could hide the default legend and manually draw it at OnAfterDraw event.

Code: Select all

uses TeePoin3, Math;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var i: Integer;
    R1, R2: TRect;
    maxTitleWidth: Integer;
    maxTitleHeight: Integer;
    tmpZ: Integer;
begin
  tmpZ:=Round(Chart1.DepthAxis.IAxisSize/2);
  maxTitleWidth:=0;
  maxTitleHeight:=0;
  for i:=0 to Chart1.SeriesCount-1 do
  begin
    maxTitleWidth:=Max(maxTitleWidth, Chart1.Canvas.TextWidth(Chart1.SeriesTitleLegend(i))+TPoint3DSeries(Chart1[i]).Pointer.Size+15);
    maxTitleHeight:=Max(Chart1.Canvas.TextHeight(Chart1.SeriesTitleLegend(i)),TPoint3DSeries(Chart1[i]).Pointer.Size);
  end;

  R1:=Rect(Chart1.ChartRect.Right+10,Chart1.ChartRect.Top,
          Chart1.ChartRect.Right+10+maxTitleWidth,
          Chart1.ChartRect.Top+5+Chart1.SeriesCount*(maxTitleHeight+5));

  Chart1.Canvas.Rectangle(R1, tmpZ);

  R1.Offset(3,5);

  for i:=0 to Chart1.SeriesCount-1 do
  begin
    if Chart1[i] is TPoint3DSeries then
      with Chart1.Canvas,TPoint3DSeries(Chart1[i]) do
      begin
        Pointer.PrepareCanvas(Chart1.Canvas,Color);

        R2:=R1;
        R2.Width:=Pointer.Size;
        R2.Height:=Pointer.Size;
        R2.Offset(0,3);
        case Pointer.Style of
          psRectangle: Cube(R2.Left,R2.Right,R2.Top,R2.Bottom,tmpZ-Pointer.Depth,tmpZ,True,0);
          psCircle: Sphere(R2.Left+Pointer.Size div 2,R2.Top+Pointer.Size div 2,tmpZ-Pointer.Depth div 2,Pointer.Size div 2);
          psTriangle: Pyramid(True,R2.Left,R2.Top,R2.Right,R2.Bottom,tmpZ-Pointer.Depth,tmpZ,True);
          psDownTriangle: Pyramid(True,R2.Left,R2.Bottom,R2.Right,R2.Top,tmpZ-Pointer.Depth,tmpZ,True);
          psCross: ;
          psDiagCross: ;
          psStar: ;
          psDiamond: ;
          psSmallDot: ;
          psNothing: ;
          psLeftTriangle: ;
          psRightTriangle: ;
          psHexagon: ;
          psVisual: ;
          psDonut: ;
          psArrow: ;
        end;

        TextOut3D(R1.Left+Pointer.Size+5,R1.Top,tmpZ,Chart1.SeriesTitleLegend(i));
      end;

    R1.Offset(0,maxTitleHeight+5);
  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

axrDegen
Newbie
Newbie
Posts: 31
Joined: Mon Jan 14, 2019 12:00 am

Re: How to best draw (custom) legend with used Pointers

Post by axrDegen » Wed Jul 03, 2019 8:03 am

Hi Yeray,

thank you for the code, in principle that works.
But looking at the plot this still needs serious tweaking:
3DLegendCapture.PNG
3DLegendCapture.PNG (56.89 KiB) Viewed 12766 times
Distance and sizes are not Ok and also some pointers are missing.
I may for the next release rather stay with the 2D legend.

best regards

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

Re: How to best draw (custom) legend with used Pointers

Post by Yeray » Wed Jul 03, 2019 10:28 am

Hello,
axrDegen wrote:
Wed Jul 03, 2019 8:03 am
Distance and sizes are not Ok
This is probably due to some difference between your application and my test app.
Please arrange a simple example project we can run as-is to reproduce the problem here.
axrDegen wrote:
Wed Jul 03, 2019 8:03 am
some pointers are missing
I only implemented a few pointer styles (psRectangle, psCircle, psTriangle and psDownTriangle). I see you also use psCross and psStar.
Here I'm adding psCross, psDiagCross and psStar:

Code: Select all

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var R2: TRect;
    tmpZ: Integer;

  procedure DrawCross;
  begin
    with Chart1.Canvas do
    begin
      VertLine3D(R2.Left+(R2.Right-R2.Left) div 2,R2.Top,R2.Bottom,tmpZ);
      HorizLine3D(R2.Left,R2.Right,R2.Top+(R2.Bottom-R2.Top) div 2,tmpZ);
    end;
  end;

  procedure DrawDiagonalCross;
  begin
    with Chart1.Canvas do
    begin
      LineWithZ(R2.Left,R2.Top,R2.Right,R2.Bottom,tmpZ);
      LineWithZ(R2.Right,R2.Top,R2.Left,R2.Bottom,tmpZ);
    end;
  end;

var i: Integer;
    R1: TRect;
    maxTitleWidth: Integer;
    maxTitleHeight: Integer;
begin
  tmpZ:=Round(Chart1.DepthAxis.IAxisSize/2);
  maxTitleWidth:=0;
  maxTitleHeight:=0;
  for i:=0 to Chart1.SeriesCount-1 do
  begin
    maxTitleWidth:=Max(maxTitleWidth, Chart1.Canvas.TextWidth(Chart1.SeriesTitleLegend(i))+TPoint3DSeries(Chart1[i]).Pointer.Size+15);
    maxTitleHeight:=Max(Chart1.Canvas.TextHeight(Chart1.SeriesTitleLegend(i)),TPoint3DSeries(Chart1[i]).Pointer.Size);
  end;

  R1:=Rect(Chart1.ChartRect.Right+10,Chart1.ChartRect.Top,
          Chart1.ChartRect.Right+10+maxTitleWidth,
          Chart1.ChartRect.Top+5+Chart1.SeriesCount*(maxTitleHeight+5));

  Chart1.Canvas.Rectangle(R1, tmpZ);

  R1.Offset(3,5);

  for i:=0 to Chart1.SeriesCount-1 do
  begin
    if Chart1[i] is TPoint3DSeries then
      with Chart1.Canvas,TPoint3DSeries(Chart1[i]) do
      begin
        Pointer.PrepareCanvas(Chart1.Canvas,Color);

        R2:=R1;
        R2.Width:=Pointer.Size;
        R2.Height:=Pointer.Size;
        R2.Offset(0,3);
        case Pointer.Style of
          psRectangle: Cube(R2.Left,R2.Right,R2.Top,R2.Bottom,tmpZ-Pointer.Depth,tmpZ,True,0);
          psCircle: Sphere(R2.Left+Pointer.Size div 2,R2.Top+Pointer.Size div 2,tmpZ-Pointer.Depth div 2,Pointer.Size div 2);
          psTriangle: Pyramid(True,R2.Left,R2.Top,R2.Right,R2.Bottom,tmpZ-Pointer.Depth,tmpZ,True);
          psDownTriangle: Pyramid(True,R2.Left,R2.Bottom,R2.Right,R2.Top,tmpZ-Pointer.Depth,tmpZ,True);
          psCross: DrawCross;
          psDiagCross: DrawDiagonalCross;
          psStar: begin
                    DrawCross;
                    DrawDiagonalCross;
                  end;
          psDiamond: ;
          psSmallDot: ;
          psNothing: ;
          psLeftTriangle: ;
          psRightTriangle: ;
          psHexagon: ;
          psVisual: ;
          psDonut: ;
          psArrow: ;
        end;

        TextOut3D(R1.Left+Pointer.Size+5,R1.Top,tmpZ,Chart1.SeriesTitleLegend(i));
      end;

    R1.Offset(0,maxTitleHeight+5);
  end;
end;
Project1_2019-07-03_12-27-37.png
Project1_2019-07-03_12-27-37.png (7.34 KiB) Viewed 12762 times
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