Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/LiveChartsCore/CoreLineSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

Comment thread
beto-rodriguez marked this conversation as resolved.
using System;
using System.Collections.Generic;
using System.Linq;
using LiveChartsCore.Drawing;
using LiveChartsCore.Drawing.Segments;
using LiveChartsCore.Kernel;
Expand Down Expand Up @@ -798,6 +795,14 @@ protected internal override void SoftDeleteOrDisposePoint(ChartPoint point, Scal
visual.XError.RemoveOnCompleted = true;
}

foreach (var pathCollection in _strokePathHelperDictionary.Values)
foreach (var path in pathCollection)
_ = path.Commands.Remove(visual.Segment);

foreach (var pathCollection in _fillPathHelperDictionary.Values)
foreach (var path in pathCollection)
_ = path.Commands.Remove(visual.Segment);
Comment thread
beto-rodriguez marked this conversation as resolved.

DataFactory.DisposePoint(point);

var label = (TLabel?)point.Context.Label;
Expand Down
12 changes: 10 additions & 2 deletions src/LiveChartsCore/CoreStepLineSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public abstract class CoreStepLineSeries<TModel, TVisual, TLabel, TPathGeometry,
where TLabel : BaseLabelGeometry, new()
where TLineGeometry : BaseLineGeometry, new()
{
private readonly Dictionary<object, List<TPathGeometry>> _fillPathHelperDictionary = [];
private readonly Dictionary<object, List<TPathGeometry>> _strokePathHelperDictionary = [];
internal readonly Dictionary<object, List<TPathGeometry>> _fillPathHelperDictionary = [];
internal readonly Dictionary<object, List<TPathGeometry>> _strokePathHelperDictionary = [];
private float _geometrySize = 14f;

/// <summary>
Expand Down Expand Up @@ -553,6 +553,14 @@ protected internal override void SoftDeleteOrDisposePoint(ChartPoint point, Scal
visual.Geometry.Opacity = 0;
visual.Geometry.RemoveOnCompleted = true;

foreach (var pathCollection in _strokePathHelperDictionary.Values)
foreach (var path in pathCollection)
_ = path.Commands.Remove(visual.Segment);

foreach (var pathCollection in _fillPathHelperDictionary.Values)
foreach (var path in pathCollection)
_ = path.Commands.Remove(visual.Segment);

DataFactory.DisposePoint(point);

var label = (TLabel?)point.Context.Label;
Expand Down
118 changes: 114 additions & 4 deletions tests/CoreTests/SeriesTests/LineSeriesTest.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using System;
using System.Linq;
using CoreTests.MockedObjects;
using CoreTests.MockedObjects;
using LiveChartsCore.Drawing;
using LiveChartsCore.Drawing.Segments;
using LiveChartsCore.Kernel;
using LiveChartsCore.Measure;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.SKCharts;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SkiaSharp;

namespace CoreTests.SeriesTests;
Expand Down Expand Up @@ -422,4 +420,116 @@ public void ShouldPlaceDataLabel()

Assert.IsTrue(!chart.CoreCanvas.ContainsPaintTask(previousPaint));
}

[TestMethod]
public void ShouldScaleBeziersOnAddRemoveOrInsert()
{
var values = new List<double> { 1, 2, 3, 4, 5 };

var series = new LineSeries<double>
{
Values = values,
GeometrySize = 10
};

var chart = new SKCartesianChart
{
Width = 1000,
Height = 1000,
Series = [series]
};

void AssertIsStraightLine(ChartPoint[] points)
{
Assert.IsTrue(points.Length > 0);

CubicBezierSegment? previous = null;
var slope = 0f;

foreach (var p in points)
{
var tp = series.ConvertToTypedChartPoint(p);
var segment = (CubicSegmentVisualPoint?)tp.Context.AdditionalVisuals;

Assert.IsNotNull(segment);

if (previous is null)
{
previous = segment?.Segment;
continue;
}

if (slope == 0f)
Comment thread
beto-rodriguez marked this conversation as resolved.
{
var dx = segment!.Segment.Xj - previous.Xj;
var dy = segment.Segment.Yj - previous.Yj;
slope = dx / dy;
}

var currentSlope = (segment!.Segment.Xj - previous.Xj) / (segment.Segment.Yj - previous.Yj);

Assert.IsTrue(Math.Abs(slope - currentSlope) < 0.1);
previous = segment.Segment;
}
Comment thread
beto-rodriguez marked this conversation as resolved.
}

ChartPoint[] points;
int segments;
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if a the first point is removed, it should still be a straight line
Comment thread
beto-rodriguez marked this conversation as resolved.
values.RemoveAt(0);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 4);

// if we insert a point at the start that keeps the straight line, it should be a straight line
values.Insert(0, 1);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if the last point is removed, it should still be a straight line
values.RemoveAt(values.Count - 1);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 4);

// if we add a point that keeps the straight line, it should be a straight line
values.Add(5);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if we insert a point in the middle that keeps the straight line, it should be a straight line
values.RemoveAt(1);
_ = chart.GetImage();
// at this point the values are [1,3,4,5] it is not a straight line
//AssertIsStraightLine([.. series.DataFactory.Fetch(series, chart.CoreChart)]);
Comment thread
beto-rodriguez marked this conversation as resolved.

values.Insert(1, 2);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);
}
}
118 changes: 114 additions & 4 deletions tests/CoreTests/SeriesTests/StepLineSeriesTest.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using System;
using System.Linq;
using CoreTests.MockedObjects;
using CoreTests.MockedObjects;
using LiveChartsCore.Drawing;
using LiveChartsCore.Drawing.Segments;
using LiveChartsCore.Kernel;
using LiveChartsCore.Measure;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.SKCharts;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SkiaSharp;

namespace CoreTests.SeriesTests;
Expand Down Expand Up @@ -420,4 +418,116 @@ public void ShouldPlaceDataLabel()

Assert.IsTrue(!chart.CoreCanvas.ContainsPaintTask(previousPaint));
}

[TestMethod]
public void ShouldScaleBeziersOnAddRemoveOrInsert()
{
var values = new List<double> { 1, 2, 3, 4, 5 };

var series = new StepLineSeries<double>
{
Values = values,
GeometrySize = 10
};

var chart = new SKCartesianChart
{
Width = 1000,
Height = 1000,
Series = [series]
};

void AssertIsStraightLine(ChartPoint[] points)
{
Assert.That(() => points.Length > 0);
Comment thread
beto-rodriguez marked this conversation as resolved.

Segment? previous = null;
var slope = 0f;

foreach (var p in points)
{
var tp = series.ConvertToTypedChartPoint(p);
var segment = (SegmentVisualPoint?)tp.Context.AdditionalVisuals;

Assert.IsNotNull(segment);

if (previous is null)
{
previous = segment?.Segment;
continue;
}

if (slope == 0f)
Comment thread
beto-rodriguez marked this conversation as resolved.
{
var dx = segment!.Segment.Xj - previous.Xj;
var dy = segment.Segment.Yj - previous.Yj;
slope = dx / dy;
}

var currentSlope = (segment!.Segment.Xj - previous.Xj) / (segment.Segment.Yj - previous.Yj);

Assert.IsTrue(Math.Abs(slope - currentSlope) < 0.1);
previous = segment.Segment;
}
Comment thread
beto-rodriguez marked this conversation as resolved.
}

ChartPoint[] points;
int segments;
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if a the first point is removed, it should still be a straight line
values.RemoveAt(0);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 4);

// if we insert a point at the start that keeps the straight line, it should be a straight line
values.Insert(0, 1);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if the last point is removed, it should still be a straight line
values.RemoveAt(values.Count - 1);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 4);

// if we add a point that keeps the straight line, it should be a straight line
values.Add(5);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);

// if we insert a point in the middle that keeps the straight line, it should be a straight line
values.RemoveAt(1);
_ = chart.GetImage();
// at this point the values are [1,3,4,5] it is not a straight line
//AssertIsStraightLine([.. series.DataFactory.Fetch(series, chart.CoreChart)]);

values.Insert(1, 2);
_ = chart.GetImage();

points = [.. series.DataFactory.Fetch(series, chart.CoreChart)];
segments = series._fillPathHelperDictionary.Sum(x => x.Value.Sum(y => y.Commands.Count));
AssertIsStraightLine(points);
Assert.IsTrue(segments == 5);
}
}
Loading