Page 1 of 1

Displaying Dashed Lines with data-dense series

Posted: Sat Sep 01, 2018 2:32 am
by 16583932
Good morning
I use TeeChart to present scientific data measured down a geothermal well. With modern equipment, data can be collected at very closeintervals, as small as 6 inches (15 cm) which would result in over 13,000 data points in a series! If all data points are displayed, a solid dark line is displayed.
AllDataPoints.png
AllDataPoints.png (13.63 KiB) Viewed 17119 times
To overcome this, I have to generate 3 series, a line series, a fastline series and a point series. The line series is not plotted and only used for the legend. I can then limit the number of points that are plotted as shown.
SelectedDataPoints.png
SelectedDataPoints.png (12.61 KiB) Viewed 17119 times
On a typical graph, I might plot up to 20 series. to be able to clearly differentiate, it is necessary to use the full range of presentation features, which includes line type (e.g. solid, dotted, dashed, etc.) However, because of the data density, the dashed line in the example plots as a solid line.
I know this issue has been raised before, and the only solution was to reduce the number of points displayed, using a DownSampling tool. I have not tried this, but I presume it thins the number of points and therefore the fine detail in the curve. I like to display all the data, especially given the very powerful tool in TeeChart where a user can zoom in and examine fine detail very easily.
I think it is time that the FastLine series, at least, was modified to print a uniformly dashed line regardless of the data density. I do not understand why this should be so difficult and it would definitely raise TeeChart credentials as a scientific data charting tool.
I look forward to your comments on this issue.
Best regards
Errol

Re: Displaying Dashed Lines with data-dense series

Posted: Mon Sep 03, 2018 2:12 pm
by yeray
Hello,

I've done a simple example where I'm using the TDownSamplingFunction with the minimum Tolerance needed to draw line segments of a minimum of 5 pixels wide, so they can be drawn in the Dashed style:

Code: Select all

uses Series, TeeDownSampling, Math;

var oSeries, dSeries: TFastLineSeries;
    dFunc: TDownSamplingFunction;
    minSector: Integer;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=False;
  Chart1.Legend.Hide;

  Chart1.Axes.Bottom.Grid.Hide;
  Chart1.Axes.Left.Grid.Hide;
  Chart1.Axes.Left.SetMinMax(0,2000);

  oSeries:=Chart1.AddSeries(TFastLineSeries) as TFastLineSeries;
  with oSeries do
  begin
    Pen.Style:=psDash;

    Add(1000);
    for i:=0 to 400-1 do
      Add(YValue[Count-1]+Random*10-5);

    Active:=False;
  end;

  dSeries:=Chart1.AddSeries(TFastLineSeries) as TFastLineSeries;
  dFunc:=TDownSamplingFunction.Create(Self);
  dFunc.DownSampleMethod:=dsAverage;
  dSeries.SetFunction(dFunc);
  dSeries.Pen.Style:=oSeries.Pen.Style;
  dSeries.Color:=oSeries.Color;
  dSeries.DataSource:=oSeries;
  dSeries.CheckDataSource;

  Chart1.OnZoom:=ChartZoom;
  Chart1.OnUndoZoom:=ChartUndoZoom;

  CalcTolerance;
end;


procedure TForm1.ChartZoom(Sender: TObject);
begin
  CalcTolerance;
end;

procedure TForm1.ChartUndoZoom(Sender: TObject);
begin
  CalcTolerance;
end;

procedure TForm1.CalcTolerance;
begin
  dFunc.Tolerance:=1;
  Chart1.Draw;

  if dSeries.Count>0 then
    while (Chart1.ChartRect.Right-Chart1.ChartRect.Left) div (dSeries.LastDisplayedIndex-dSeries.FirstDisplayedIndex) < 5 do
    begin
      dFunc.Tolerance:=dFunc.Tolerance+1;
      dSeries.CalcFirstLastVisibleIndex;
    end;

  Caption:=FormatFloat('#,##0', dFunc.Tolerance);
end;

Re: Displaying Dashed Lines with data-dense series

Posted: Tue Sep 04, 2018 2:35 am
by 16583932
Good morning
Thanks for your suggestion. I will certainly try this although I cannot get your code to work because of some conflict between VCLTee.TeCanvas and TeCanvas which I do not understand. Here is the error I get when trying to run the test program attached. I appreciate your assistance here.

[dcc32 Error] TeCanvas.pas(5692): E2010 Incompatible types: 'VCLTee.TeCanvas.TTeeCanvas' and 'TeCanvas.TTeeCanvas'
[dcc32 Error] TeCanvas.pas(8496): E2010 Incompatible types: 'TTeeCanvas' and 'TTeeCanvas3D'

However, I still expect that a FastLine series should draw an evenly-spaced dotted, dashed or dot-dashed line regardless of the number of data points, and without having to write extra code. If you wish to retain the behaviour of the current FastLine series, then perhaps a new series (FastLineX or similar) could be introduced to satisfy user expectations. Can this be introduced as a new feature?

Best regards

Errol

Re: Displaying Dashed Lines with data-dense series

Posted: Tue Sep 04, 2018 8:10 am
by yeray
Hello,
Errol wrote:
Tue Sep 04, 2018 2:35 am
some conflict between VCLTee.TeCanvas and TeCanvas which I do not understand
Please make sure the "VCLTee" prefix is present in the "unit scope names" in the project options or the IDE options.
Errol wrote:
Tue Sep 04, 2018 2:35 am
However, I still expect that a FastLine series should draw an evenly-spaced dotted, dashed or dot-dashed line regardless of the number of data points, and without having to write extra code. If you wish to retain the behaviour of the current FastLine series, then perhaps a new series (FastLineX or similar) could be introduced to satisfy user expectations. Can this be introduced as a new feature?
Yes, it could be controlled by a new property in the TFastLineSeries. Or, as you suggest, if a new series type if the TFastLineSeries performance is affected by this addition.
Please, confirm if the code I suggested above works as you expected so I can open a detailed ticket in our public tracker

Re: Displaying Dashed Lines with data-dense series

Posted: Wed Oct 03, 2018 5:02 am
by 16583932
Hello
Thank you for your suggestions in the previous post and apologies for the long delay before replying.
I have implemented the down-sampling code in the attached project, but it does not work as well as hoped. Values are omitted, so that the down-sampled line does not match the measured line. Also for a noisy line (the WHP series) the procedure seems to omit all points except for the first and one other. I would be grateful for assistance with this as I do not adequately understand the downsampling procedure.
I still feel the down-sampling procedure is likely to be time-consuming for series with many data points. Already I have to generate a point series and a fastline series to be able to have the required control on point display - I do not wish to generate another series for the downsampling procedure. With up to 20 series each with 20,000 points, there is an impact on graph drawing speed.
I presume the fastline series draws the specified line type from data point to data point. Ii is not clear to me why it has to re-start the line type at each data point. I hope Steema can modify the fastline series so that the dash intervals are dependent only on the path length, and ignore the occurrence of a point in the path.
I look forward to your comments
Best regards
Errol

Re: Displaying Dashed Lines with data-dense series

Posted: Thu Oct 04, 2018 10:21 am
by yeray
Hello,

There is also the option to draw the line/fastline series as a polyline. This can be done setting the DrawStyle property to flAll (flSegments is the default). However, as you can see in this simple example doesn't solve the problem:
Project3_2018-10-04_11-57-19.png
Project3_2018-10-04_11-57-19.png (65.16 KiB) Viewed 17057 times

Code: Select all

uses Series, TeeDownSampling;

var dFunc: TDownSamplingFunction;
    dSeries: TFastLineSeries;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.Legend.Hide;
  Chart1.View3D:=False;
  Chart1.Hover.Visible:=False;

  Chart1.Axes.Left.EndPosition:=33;
  Chart1.Axes.Left.Title.Caption:='Original';

  with Chart1.CustomAxes.Add do
  begin
    StartPosition:=33;
    EndPosition:=66;
    LabelsFont.Assign(Chart1.Axes.Left.LabelsFont);
    Title.Font.Assign(Chart1.Axes.Left.Title.Font);
    Title.Caption:='DrawStyle=flAll';
  end;
  with Chart1.CustomAxes.Add do
  begin
    StartPosition:=66;
    LabelsFont.Assign(Chart1.Axes.Left.LabelsFont);
    Title.Font.Assign(Chart1.Axes.Left.Title.Font);
    Title.Caption:='DownSampling';
  end;

  for i:=0 to 2 do
  begin
    with Chart1.AddSeries(TFastLineSeries) as TFastLineSeries do
    begin
      if i=0 then
        FillSampleValues(10000)
      else
      begin
        DataSource:=Chart1[0];
        CustomVertAxis:=Chart1.CustomAxes[i-1];
        Color:=Chart1[0].Color;

        if i=1 then
          DrawStyle:=flAll
        else if i=2 then
        begin
          dSeries:=Chart1[i] as TFastLineSeries;
          dFunc:=TDownSamplingFunction.Create(Self);
          dFunc.DownSampleMethod:=dsAverage;
          dSeries.SetFunction(dFunc);
        end;
      end;

      Pen.Style:=psDash;
    end;
  end;

  CalcTolerance;
end;

procedure TForm1.CalcTolerance;
begin
  dFunc.Tolerance:=1;
  Chart1.Draw;

  if dSeries.Count>0 then
    while (Chart1.ChartRect.Right-Chart1.ChartRect.Left) div (dSeries.LastDisplayedIndex-dSeries.FirstDisplayedIndex) < 5 do
    begin
      dFunc.Tolerance:=dFunc.Tolerance+1;
      dSeries.CalcFirstLastVisibleIndex;
    end;

  Caption:='DownSampling Tolerance: ' + FormatFloat('#,##0', dFunc.Tolerance);
end;
The problem is when you have points so close that there isn't space between them to draw a line and a leave a white space (to have a dash). The only way around I can think on is by reducing the number of points... and thus loosing some precision.

Re: Displaying Dashed Lines with data-dense series

Posted: Mon Oct 15, 2018 2:54 am
by 16583932
Good afternoon
I seem to have solved the problem of displaying dashed line with data-dense series, and that is to use a Line Series rather than a Fast Line Series, and to set DrawStyles to dsAll and Pointer.Visible to False. See attached DashedLines example program. I then use a Point series to draw points at a user-defined density.
I am surprised that a line series has the capability of displaying dashed lines independent of the data density, whereas a Fast Line Series cannot do this. Intuitively, I would have expected the opposite to be true, but I appreciate there is a solution.
My (hopefully final) question is this. Will the chart drawing be significantly slower using Line Series rather than Fast line Series, assuming say 10 series on a graph each with 10,000 data points (but perhaps only 10 points/symbols drawn per series)?
I look forward to your comments.
Best regards
Errol

Re: Displaying Dashed Lines with data-dense series

Posted: Wed Oct 17, 2018 12:08 pm
by yeray
Hello,

I believe you missed to include the .pas.

I've done some tests with this simple example and the application needs about 122ms to repaint using TLineSeries vs about 78ms using TFastLineSeries:

Code: Select all

uses Series, Diagnostics;

const nValues=10000;
      nPoints=10;

var Stopwatch: TStopwatch;
    tmp1, tmp2: Double;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
begin
  tmp1:=Stopwatch.Elapsed.TotalMilliseconds;
  tmp2:=Stopwatch.Elapsed.TotalSeconds;

  if Stopwatch.Elapsed.TotalSeconds>1 then
     Caption:=FormatFloat('#,##0.##', Stopwatch.Elapsed.TotalSeconds)+'s'
  else
     Caption:=FormatFloat('#,##0.##', Stopwatch.Elapsed.TotalMilliseconds)+'ms';
end;

procedure TForm1.Chart1BeforeDrawChart(Sender: TObject);
begin
  Stopwatch := TStopwatch.StartNew;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i, j: Integer;
    diff: Double;
begin
  Chart1.View3D:=False;
  Chart1.Legend.Hide;
  Chart1.Title.Hide;
  Chart1.Hover.Visible:=False;

  (Chart1.AddSeries(TPointSeries) as TPointSeries).Pointer.Size:=2;

  diff:=nValues/nPoints;

  for i:=0 to 9 do
  begin
    Chart1.AddSeries(TLineSeries).FillSampleValues(nValues);
    //Chart1.AddSeries(TFastLineSeries).FillSampleValues(nValues);

    j:=0;
    repeat
      Chart1[0].AddXY(j*diff, Chart1[Chart1.SeriesCount-1].YValue[round(j*diff)], '', Chart1[Chart1.SeriesCount-1].Color);
      Inc(j);
    until (j*diff>=nValues);

  end;

  Chart1.ExchangeSeries(0, Chart1.SeriesCount-1);
end;

Re: Displaying Dashed Lines with data-dense series

Posted: Wed Oct 31, 2018 3:36 am
by 16583932
Hi Yeray

Thanks for the tests. I think I can live with the slower paint time. Such big data sets are reasonably rare. I have attached the Dashed Lines project, this time with the missing .pas file, just in case anyone wants to review it.
Best regards
Errol