Recent

Author Topic: TLineSeries display every n'th point  (Read 425 times)

mtanner

  • Sr. Member
  • ****
  • Posts: 269
TLineSeries display every n'th point
« on: January 16, 2021, 09:02:47 am »
I have touched on this idea some time ago, but I don't think I explained my query very well. Those familiar with LaTex/PGFPlots will know that when you plot a line series with PGFPlots, you can have markers (=pointer in TaGraph) or not, or you can use a parameter that causes every n'th point to be shown as a marker(pointer) and other points without a marker(pointer). This is very useful with very non-linear plots, because you can show the shape of the line accurately without overcrowding the chart with too many markers(pointers), using just a few markers(pointers) to distinguish one line from another.

I cannot see such an option in the TAGraph documentation, but it's possible I have just failed to find it. The only way I can see of achieving the PGFPlots effect is to plot a composite line, one TLineSeries with lots of points but no markers, to get the shape right. Then overlay that with another, pointers-only, series to distinguish the line. Could I please request such an option, if it would not be too hard to implement? One way would be to add a parameter to the Series.AddXY routine saying whether a pointer should displayed or not, and let the application use this parameter to achieve the every-nth-pointer effect.

wp

  • Hero Member
  • *****
  • Posts: 8088
Re: TLineSeries display every n'th point
« Reply #1 on: January 16, 2021, 12:23:10 pm »
It's already there, just a bit hidden: There is a Series event OnGetPointerStyle in which you can decide which pointer type will be used for each data point. Since there is a PointerStyle psNone ("no pointer") you can achieve your request by

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1LineSeries1GetPointerStyle(ASender: TChartSeries;
  2.   AValueIndex: Integer; var AStyle: TSeriesPointerStyle);
  3. begin
  4.   if AValueIndex mod 100 <> 0 then AStyle := psNone;  // Draw only every 100th pointer
  5. end;

Another option would be to use the the event OnCustomDrawPointer - see demo folder components/tachart/demo/line of your Lazarus installation.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

mtanner

  • Sr. Member
  • ****
  • Posts: 269
Re: TLineSeries display every n'th point
« Reply #2 on: January 17, 2021, 11:50:58 am »
Thanks, allways impressed with Lazarus. 

mtanner

  • Sr. Member
  • ****
  • Posts: 269
Re: TLineSeries display every n'th point
« Reply #3 on: January 18, 2021, 09:55:46 am »
I can work with those suggestions. However, can I ask a supplementary. Where my application calls the AddXY for a series, it is in a coding context where the information needed to decide pointer/no pointer is readily available. If I have to make the decision in an On... method, then not all the info is so easily available, just the point number within the series. Is it possible to append some info of any kind to each point, and access the info from the On.. method? I could then use a fairly generic On.. method just looking at the extra info for a point.

I'm thinking of TTreeNodes, where you can attach an object to a tree node if you wish (or say an integer typecast to an object reference). Maybe use a ListSource with 3 values instead of 2- would that work?

wp

  • Hero Member
  • *****
  • Posts: 8088
Re: TLineSeries display every n'th point
« Reply #4 on: January 18, 2021, 10:40:42 am »
Since adding one more field to TChartDataItem (the data point record) affects all uses of TAChart and increases memory consumption I am very hesitant to do so.

Do not use a second y value to store additional information because I do not see a way to prevent a LineSeries from plotting the second y value as a second curve assigned to the same x values.

There is, however, the possibility to add a second x value (set XCount of the chart source to 2). TLineSeries, so far, always uses the first x value only and ignores all other x values of a data point -- hmmm, well, maybe a future extension to 3D might take the 2nd x value... Anyway, here is code to show you how to add and read a second x value:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   i: Integer;
  4. begin
  5.   for i := 0 to 50 do
  6.     ListChartSource1.AddXListY([i, i mod 5], i*i);
  7.   Chart1LineSeries1.Source := ListChartsource1;
  8. end;
  9.  
  10. procedure TForm1.Chart1LineSeries1GetPointerStyle(ASender: TChartSeries;
  11.   AValueIndex: Integer; var AStyle: TSeriesPointerStyle);
  12. begin
  13.   if ListChartSource1.Item[AValueIndex]^.XList[0] <> 0 then AStyle := psNone;
  14. end;

Or you could "abuse" the Color field of the TChartDataItem for additional information. When you remove the ocBrush and ocPen options from the series' Pointer OverrideColor property the colors assigned to the individual data points will be ignored.
Code: Pascal  [Select][+][-]
  1.   if (some_condition) then
  2.     Chart1LineSeries1.AddXY(x, y, '', clRed)  // red is supposed to mean: "draw this point"
  3.   else
  4.     Chart1LineSeries1.AddXY(x, y);

Likewise, you can pick the Text field of the TChartDataItem unless you do not display data point labels.
Code: Pascal  [Select][+][-]
  1.   if some_condition then
  2.     Chart1LineSeries1.AddXY(x, y, 'draw')
  3.   else
  4.     Chart1LineSeries1.AddXY(x, y, 'do not draw');
« Last Edit: January 18, 2021, 11:12:44 am by wp »
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

mtanner

  • Sr. Member
  • ****
  • Posts: 269
Re: TLineSeries display every n'th point
« Reply #5 on: January 18, 2021, 12:03:18 pm »
Thanks for those suggestions, I will give them a try. I did not mean to ask you to modify the TAChart code , just what was possible with existing code. I think maybe the labels method would be the most straightforward.

wp

  • Hero Member
  • *****
  • Posts: 8088
Re: TLineSeries display every n'th point
« Reply #6 on: January 18, 2021, 12:35:34 pm »
In this case you can even use the labels for their intentional purpose because the series has an OnGetmark event in which you can shape the text before being displayed, i.e. you can remove characters which you added to provide additional information on how to display the data point while keeping the data point's original Text.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

 

TinyPortal © 2005-2018