Page 1 of 1

How to create a real smooth curve?

Posted: Tue Jul 11, 2017 12:01 pm
by 16579037
Hi,

I have the following simple code based on a chart with two line series:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.BottomAxis.Logarithmic := true;
  Chart1.BottomAxis.Automatic := false;
  Chart1.BottomAxis.Maximum := 10000;
  Chart1.BottomAxis.Minimum := 10;
  Chart1.LeftAxis.Maximum := 6;
  Chart1.LeftAxis.Minimum := -6;
  Series1.Pointer.Visible := true;
  Series2.DataSource := Series1;
  Series2.Color := clRed;
  Series1.Clear;
  Series1.AddXY(10,2,'',clTeeColor);
  Series1.AddXY(32,2,'',clTeeColor);
  Series1.AddXY(600,2.5,'',clTeeColor);
  Series1.AddXY(1000,0,'',clTeeColor);
  Series1.AddXY(2000,-2,'',clTeeColor);
  Series1.AddXY(8000,-1.5,'',clTeeColor);
  Series1.AddXY(10000,-1.5,'',clTeeColor);
  Series2.CheckDataSource;
  Series2.Smoothed := true;
end;
The target is to get a smooth Series2 through the data points given by Series1.

But it does not look smooth at all:
Smoothing.PNG
Smoothing.PNG (14.12 KiB) Viewed 11009 times
Without interpolation the curve is smooth but is does not go thru the points.

How to fix it?

BR
Uli

PS: using TSmoothingFunction leads to the same result

Re: How to create a real smooth curve?

Posted: Tue Jul 11, 2017 1:45 pm
by yeray
Hello,

I see there's a problem in the TSmoothingFunction. I've added it to the public tracker:
http://bugs.teechart.net/show_bug.cgi?id=1890

As you can see, I can think on two workarounds:
- To use THorizLineSeries instead of TLineSeries.
- To use this code:

Code: Select all

  Series2.XValues.Order:=loNone;
  Series2.HasZValues:=True;

Re: How to create a real smooth curve?

Posted: Tue Jul 11, 2017 2:38 pm
by 16579037
Hello Yeray,

THorizLineSeries seems not to work properly.

Code: Select all

  Series2.XValues.Order:=loNone;
  Series2.HasZValues:=True;
seems to work.

But adding e.g. another point by

Code: Select all

  Series1.AddXY(1300,-1.2,'',clTeeColor);
between X=1000 and X=2000 (is ascending X sequence) creates a picture like
Smoothing2.PNG
Smoothing2.PNG (14.04 KiB) Viewed 10999 times
So the smoothing seems to have some tendency for oscillations.

BR
Uli

Re: How to create a real smooth curve?

Posted: Wed Jul 12, 2017 7:57 am
by yeray
Hello Uli,
UliBru wrote:THorizLineSeries seems not to work properly.
This is what I get with TeeChart v2017.22 and the code below:
Project2_2017-07-12_08-24-01.png
Project2_2017-07-12_08-24-01.png (13.76 KiB) Viewed 10995 times

Code: Select all

uses Series;

var Series1, Series2: THorizLineSeries;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D:=False;

  Series1:=Chart1.AddSeries(THorizLineSeries) as THorizLineSeries;
  Series2:=Chart1.AddSeries(THorizLineSeries) as THorizLineSeries;

  Chart1.Axes.Bottom.Logarithmic := true;
  Chart1.Axes.Bottom.SetMinMax(10, 10000);
  Chart1.Axes.Left.SetMinMax(-6, 6);

  Series1.Pointer.Visible := true;
  Series2.DataSource := Series1;
  Series2.Color := clRed;
  Series1.Clear;

  Series1.AddXY(10,2,'',clTeeColor);
  Series1.AddXY(32,2,'',clTeeColor);
  Series1.AddXY(600,2.5,'',clTeeColor);
  Series1.AddXY(1000,0,'',clTeeColor);
  Series1.AddXY(2000,-2,'',clTeeColor);
  Series1.AddXY(8000,-1.5,'',clTeeColor);
  Series1.AddXY(10000,-1.5,'',clTeeColor);

  Series2.CheckDataSource;
  Series2.Smoothed := true;
end;
UliBru wrote:

Code: Select all

  Series2.XValues.Order:=loNone;
  Series2.HasZValues:=True;
seems to work.

But adding e.g. another point by

Code: Select all

  Series1.AddXY(1300,-1.2,'',clTeeColor);
between X=1000 and X=2000 (is ascending X sequence) creates a picture like

So the smoothing seems to have some tendency for oscillations.
I'm not sure why this is happening but it seems the BSpline is giving a different result when using those series values and when transforming those values to screen pixels.
You can use the TBSpline as follows to use pixel values, transform the result back to axis values to add them into Series2:
Project2_2017-07-12_10-33-47.png
Project2_2017-07-12_10-33-47.png (13.94 KiB) Viewed 10995 times

Code: Select all

uses Series, TeeSpLine;

var Series1, Series2: TLineSeries;

procedure TForm1.FormCreate(Sender: TObject);
var BSpline : TBSpline;
    i: Integer;
    ParameterValue : single;
    V       : TVertex;
begin
  Chart1.View3D:=False;

  Series1:=Chart1.AddSeries(TLineSeries) as TLineSeries;
  Series2:=Chart1.AddSeries(TLineSeries) as TLineSeries;

  Chart1.Axes.Bottom.Logarithmic := true;
  Chart1.Axes.Bottom.SetMinMax(10, 10000);
  Chart1.Axes.Left.SetMinMax(-6, 6);

  Series1.Pointer.Visible := true;

  Series1.AddXY(10,2,'',clTeeColor);
  Series1.AddXY(32,2,'',clTeeColor);
  Series1.AddXY(600,2.5,'',clTeeColor);
  Series1.AddXY(1000,0,'',clTeeColor);
  Series1.AddXY(1300,-1.2,'',clTeeColor);
  Series1.AddXY(2000,-2,'',clTeeColor);
  Series1.AddXY(8000,-1.5,'',clTeeColor);
  Series1.AddXY(10000,-1.5,'',clTeeColor);

  Chart1.Draw;

  BSpline:=TBSpline.Create;

  for i:=0 to Series1.Count-1 do
    BSpline.AddPoint(Series1.CalcXPos(i), Series1.CalcYPos(i));

  BSpline.Interpolated:=True;
  BSpline.Fragments:=64;

  Series2.Color:=clRed;
  Series2.XValues.Order:=loNone;

  For i:=0 to BSpline.Fragments do
  begin
    ParameterValue:=(i/BSpline.Fragments);
    V:=BSpline.Value(ParameterValue);

    with Series2 do
      AddXY(GetHorizAxis.CalcPosPoint(Round(V.X)),GetVertAxis.CalcPosPoint(Round(V.Y)));
  end;
end;;

Re: How to create a real smooth curve?

Posted: Wed Jul 12, 2017 8:34 am
by 16579037
Hello Yeray,

many thanks.

- Uli

Re: How to create a real smooth curve?

Posted: Wed Jul 12, 2017 8:38 am
by yeray
Hello Uli,

Note I've just edited my last post to calculate the spline at OnCreate and use the output in Series2 instead of having to recalculate it at every repaint at OnAfterDraw event.