Page 1 of 1
TChart Line Chart Series with DrawStyle Curve Dips Below Zero - How to Fix?
Posted: Wed Sep 06, 2023 6:24 am
by 16894501
I am facing an issue with the Line chart series of TChart when using the DrawStyle Curve. The line is going below 0, even though none of the values are below zero (please refer to the attached image). I am looking for a solution to prevent the line from dipping below zero and maintain the curve style. Any help would be greatly appreciated, and thank you in advance for your responses.
Re: TChart Line Chart Series with DrawStyle Curve Dips Below Zero - How to Fix?
Posted: Wed Sep 06, 2023 9:41 am
by yeray
Hello,
I'd say this is something to expect if you want the curve to pass through the points.
If you don't need the curve to pass though the points, you can use a
TSmoothingFunction
with
Interpolate:=false
as follows:
Code: Select all
uses Chart, Series, TeeSpline;
var Chart1: TChart;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1:=TChart.Create(Self);
with Chart1 do
begin
Parent:=Self;
Align:=alClient;
Color:=clWhite;
Gradient.Visible:=False;
Walls.Back.Color:=clWhite;
Walls.Back.Gradient.Visible:=False;
Legend.Hide;
View3D:=False;
Axes.Left.SetMinMax(-1, 4);
Axes.Left.Increment:=1;
Axes.Bottom.Grid.Hide;
end;
with TLineSeries(Chart1.AddSeries(TLineSeries)) do
begin
Pointer.Show;
Pointer.Size:=2;
DrawStyle:=dsCurve;
Add(0);
Add(0);
Add(3);
Add(0);
Add(0);
Add(2);
Add(2);
Add(0);
Add(1);
Add(0);
Add(0);
end;
with TLineSeries(Chart1.AddSeries(TLineSeries)) do
begin
FunctionType:=TSmoothingFunction.Create(Self);
with TSmoothingFunction(FunctionType) do
begin
Interpolate:=False;
Factor:=6;
end;
DataSource:=Chart1[0];
end;
end;
- curvedLine.png (17.79 KiB) Viewed 16963 times
Re: TChart Line Chart Series with DrawStyle Curve Dips Below Zero - How to Fix?
Posted: Tue Sep 12, 2023 9:06 am
by 16894501
Thank you so much for the response.
Please note, that I am expecting the curve to pass through the points because it will affect the presented information.
Thank you
V
Re: TChart Line Chart Series with DrawStyle Curve Dips Below Zero - How to Fix?
Posted: Tue Sep 12, 2023 10:22 am
by yeray
Hello,
I've tried with a custom cubic spline, but it doesn't give the result I'd expect:
- Project3_2023-09-12_12-21-08.png (10.15 KiB) Viewed 16830 times
Code: Select all
uses Chart, Series;
var Chart1: TChart;
type TCoeficient = record
X, Y, b, c, d: Double;
end;
type TCoeficients = array of TCoeficient;
type TPoints = array of TPointFloat;
procedure CalculateCubicSplineCoefficients(const Points: TPoints; var Coefficients: TCoeficients);
var
N, i: Integer;
h: array of Double;
alpha, l, mu, z: array of Double;
c, b, d: array of Double;
begin
N := Length(Points) - 1;
SetLength(h, N);
SetLength(alpha, N);
SetLength(l, N);
SetLength(mu, N);
SetLength(z, N);
SetLength(c, N);
SetLength(b, N);
SetLength(d, N);
// Calculate h values
for i := 0 to N - 1 do
h[i] := Points[i + 1].X - Points[i].X;
// Calculate alpha, l, mu, and z values
for i := 1 to N - 1 do
begin
alpha[i] := (3.0 / h[i]) * (Points[i + 1].Y - Points[i].Y) - (3.0 / h[i - 1]) * (Points[i].Y - Points[i - 1].Y);
l[i] := 2.0 * (Points[i + 1].X - Points[i - 1].X) - h[i - 1] * mu[i - 1];
mu[i] := h[i] / l[i];
z[i] := (alpha[i] - h[i - 1] * z[i - 1]) / l[i];
end;
// Calculate c, b, and d values
for i := N - 1 downto 0 do
begin
c[i] := z[i] - mu[i] * c[i + 1];
b[i] := (Points[i + 1].Y - Points[i].Y) / h[i] - h[i] * (c[i + 1] + 2.0 * c[i]) / 3.0;
d[i] := (c[i + 1] - c[i]) / (3.0 * h[i]);
end;
// Store the coefficients
SetLength(Coefficients, N);
for i := 0 to N - 1 do
begin
Coefficients[i].X := Points[i].X;
Coefficients[i].Y := Points[i].Y;
Coefficients[i].c := c[i];
Coefficients[i].b := b[i];
Coefficients[i].d := d[i];
end;
end;
procedure GenerateSmoothCurve(const Coefficients: TCoeficients; var SmoothCurve: TPoints);
var
i, j: Integer;
t: Double;
begin
// Calculate the smooth points along the curve
SetLength(SmoothCurve, 0);
for i := 0 to High(Coefficients) - 1 do
begin
for j := 0 to 100 do // 100 points between each pair of input points
begin
t := j / 100;
SetLength(SmoothCurve, Length(SmoothCurve) + 1);
SmoothCurve[High(SmoothCurve)].X := Coefficients[i].X + t * (Coefficients[i + 1].X - Coefficients[i].X);
SmoothCurve[High(SmoothCurve)].Y :=
Coefficients[i].Y + t * (Coefficients[i + 1].Y + t * (Coefficients[i + 1].b + t * Coefficients[i + 1].c)) + t * t *
(Coefficients[i + 1].d);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
data: TPoints;
coeficients: TCoeficients;
begin
Chart1:=TChart.Create(Self);
with Chart1 do
begin
Parent:=Self;
Align:=alClient;
Color:=clWhite;
Gradient.Visible:=False;
Walls.Back.Color:=clWhite;
Walls.Back.Gradient.Visible:=False;
Legend.Hide;
View3D:=False;
Axes.Left.SetMinMax(-1, 4);
Axes.Left.Increment:=1;
Axes.Bottom.Grid.Hide;
end;
with TPointSeries(Chart1.AddSeries(TPointSeries)) do
begin
Pointer.Size:=2;
Add(0);
Add(0);
Add(3);
Add(0);
Add(0);
Add(2);
Add(2);
Add(0);
Add(1);
Add(0);
Add(0);
end;
// Calculate cubic spline
SetLength(data, Chart1[0].Count);
for i:=0 to Chart1[0].Count-1 do
begin
data[i].X:=Chart1[0].XValue[i];
data[i].Y:=Chart1[0].YValue[i];
end;
CalculateCubicSplineCoefficients(data, coeficients);
GenerateSmoothCurve(coeficients, data);
with TLineSeries(Chart1.AddSeries(TLineSeries)) do
for i:=0 to High(data) do
AddXY(data[i].x, data[i].y);
end;
You could try to modify that algorithm or implement your own.