How to clip drawn points in a chart ?

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Marck
Newbie
Newbie
Posts: 6
Joined: Fri Dec 13, 2002 5:00 am
Location: Netherlands

How to clip drawn points in a chart ?

Post by Marck » Tue May 20, 2008 7:54 am

Teechart 6.01 (with source), Delphi 7

I'm showing data in a TChart using TPointSeries. I'm showing it in a grid (I use TChartShape for each rectangle in that grid).

Now, when the user resizes a data point (Pointer.HorizSize, Pointer.VeriSize) those points will eventually draw outside a grid's rectangle.

(Also, depending on the order the points are added, it "seems" like points are being shifted.)

Is there functionality within tchart to clip the drawing of each point?

See below:

Left shows with point size 2

Middle shows with point size 8

Right shows what I want

Image

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

Post by Yeray » Tue May 20, 2008 10:32 am

Hi Marck,

Firs of all I'd like to say that this should be easier with teechart v8 since there is the SubChart tool and with it you could work as with 4 different charts in the same chart. So these separations should work by default as each chart would perform its own clipping.

In the following example I use 4 Shape series as in your picture but if you are using more, I think you wont' have too much troubles adapting it.
Also note that I use a UpDownButton associated to an Edit text box to control the increment of the pointers size.

Code: Select all

type
  TForm1 = class(TForm)
    Chart1: TChart;
    Series1: TChartShape;
    Series2: TChartShape;
    Series3: TChartShape;
    Series4: TChartShape;
    Series5: TPointSeries;
    Edit1: TEdit;
    UpDown1: TUpDown;
    procedure FormCreate(Sender: TObject);
    procedure UpDown1Click(Sender: TObject; Button: TUDBtnType);
    function Series5GetPointerStyle(Sender: TChartSeries;
      ValueIndex: Integer): TSeriesPointerStyle;

...


var
  Form1: TForm1;
  ClipRect: array [0..3] of TRect;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
  //some chart config
  with Chart1 do
  begin
    View3D := false;

    with Axes.Left do
    begin
      Automatic := false;
      Minimum := 0;
      Maximum := 100;
    end;

    with Axes.Bottom do
    begin
      Automatic := false;
      Minimum := 0;
      Maximum := 100;
    end;

    Legend.Visible := false;
  end;

  UpDown1.Position := Series5.Pointer.HorizSize;

  //drawing four rectangles to divide the chart in 4 zones
  for i := 0 to 3 do
    (Chart1[i] as TChartShape).Style := chasRectangle;

  with Series1 do //rectangle down-left
  begin
    X0 := 0;
    X1 := 30;
    Y0 := 0;
    Y1 := 70;
  end;

  with Series2 do //rectangle down-right
  begin
    X0 := 30;
    X1 := 100;
    Y0 := 0;
    Y1 := 70;
  end;

  with Series3 do //rectangle up-left
  begin
    X0 := 0;
    X1 := 30;
    Y0 := 70;
    Y1 := 100;
  end;

  with Series4 do //rectangle up-right
  begin
    X0 := 30;
    X1 := 100;
    Y0 := 70;
    Y1 := 100;
  end;

  //drawing the point series
  with Series5 do
  begin
    Color := clYellow;
    Pointer.Pen.Hide;

    //poits at down-left
    AddXY(5,50,'',clGray);
    AddXY(5,65,'',clGray);
    AddXY(25,50,'',clGray);
    AddXY(25,65,'',clGray);

    //points at down-right
    AddXY(35,50,'',clYellow);
    AddXY(35,65,'',clYellow);
    AddXY(55,50,'',clYellow);
    AddXY(55,65,'',clYellow);

    //points at up-left
    AddXY(5,75,'',clYellow);
    AddXY(5,95,'',clYellow);
    AddXY(25,75,'',clYellow);
    AddXY(25,95,'',clYellow);

    //points at up-right
    AddXY(35,75,'',clYellow);
    AddXY(35,95,'',clYellow);
    AddXY(55,75,'',clYellow);
    AddXY(55,95,'',clYellow);
  end;

  //we need the 4 coordinates of teh 4 rectangles in pixels, we store them in global array of rectangles
  Chart1.Draw;

  for i := 0 to 3 do
  begin
    with (Chart1[i] as TChartShape) do
    begin
      ClipRect[i].Left := CalcXPosValue(X0)+1;
      ClipRect[i].Right := CalcXPosValue(X1);
      ClipRect[i].Top := CalcYPosValue(Y0);
      ClipRect[i].Bottom := CalcYPosValue(Y1)+1;
    end;
  end;
end;

procedure TForm1.UpDown1Click(Sender: TObject; Button: TUDBtnType);
begin
  Series5.Pointer.HorizSize := UpDown1.Position;
  Series5.Pointer.VertSize := UpDown1.Position;
end;

function TForm1.Series5GetPointerStyle(Sender: TChartSeries;
  ValueIndex: Integer): TSeriesPointerStyle;
begin
  with Chart1.Canvas do
  begin
    UnClipRectangle;
    if (Series5.XValue[ValueIndex] < Series1.X1) then   //in left half
    begin
      if (Series5.YValue[ValueIndex] < Series1.Y1) then //in first rectangle
        ClipRectangle(ClipRect[0])
      else                                              //in 3rd rectangle
        ClipRectangle(ClipRect[2]);
    end
    else                                                //in right half
    begin
      if (Series5.YValue[ValueIndex] < Series1.Y1) then //in second rectangle
        ClipRectangle(ClipRect[1])
      else                                              //in 4thrd rectangle
        ClipRectangle(ClipRect[3]);
    end;
  end;

  Result := psRectangle;
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

Marck
Newbie
Newbie
Posts: 6
Joined: Fri Dec 13, 2002 5:00 am
Location: Netherlands

Post by Marck » Tue May 20, 2008 10:43 am

Thank you very much for your rapid and clear reply :!:

I'm sure your example will solve the problem for me :)

Have a nice day,

Marck

Post Reply