using Microsoft.AspNetCore.Components; namespace Connected.Components; partial class Line : Chart { private const int MaxHorizontalGridLines = 100; [CascadingParameter] public Chart ChartParent { get; set; } private List _horizontalLines = new(); private List _horizontalValues = new(); private List _verticalLines = new(); private List _verticalValues = new(); private List _legends = new(); private List _series = new(); private List _chartLines = new(); protected override void OnParametersSet() { base.OnParametersSet(); _horizontalLines.Clear(); _verticalLines.Clear(); _horizontalValues.Clear(); _verticalValues.Clear(); _legends.Clear(); _chartLines.Clear(); if (ChartParent != null) _series = ChartParent.ChartSeries; var maxY = 0.0; var numValues = 0; var numXLabels = XAxisLabels.Length; foreach (var item in _series) { if (numValues < item.Data.Length) { numValues = item.Data.Length; } foreach (int i in item.Data) { if (maxY < i) { maxY = i; } } } var boundHeight = 350.0; var boundWidth = 650.0; double gridYUnits = ChartParent?.ChartOptions.YAxisTicks ?? 20; if (gridYUnits <= 0) gridYUnits = 20; int maxYTicks = ChartParent?.ChartOptions.MaxNumYAxisTicks ?? 100; double gridXUnits = 30; var numVerticalLines = numValues - 1; var numHorizontalLines = ((int)(maxY / gridYUnits)) + 1; // this is a safeguard against millions of gridlines which might arise with very high values while (numHorizontalLines > maxYTicks) { gridYUnits *= 2; numHorizontalLines = ((int)(maxY / gridYUnits)) + 1; } var verticalStartSpace = 25.0; var horizontalStartSpace = 30.0; var verticalEndSpace = 25.0; var horizontalEndSpace = 30.0; var verticalSpace = (boundHeight - verticalStartSpace - verticalEndSpace) / (numHorizontalLines); var horizontalSpace = (boundWidth - horizontalStartSpace - horizontalEndSpace) / (numVerticalLines); var interpolationOption = ChartParent?.ChartOptions.InterpolationOption ?? InterpolationOption.Straight; //Horizontal Grid Lines var y = verticalStartSpace; double startGridY = 0; for (var counter = 0; counter <= numHorizontalLines; counter++) { var line = new SvgPath() { Index = counter, Data = $"M {ToS(horizontalStartSpace)} {ToS((boundHeight - y))} L {ToS((boundWidth - horizontalEndSpace))} {ToS((boundHeight - y))}" }; _horizontalLines.Add(line); var lineValue = new SvgText() { X = (horizontalStartSpace - 10), Y = (boundHeight - y + 5), Value = ToS(startGridY, ChartParent?.ChartOptions.YAxisFormat) }; _horizontalValues.Add(lineValue); startGridY += gridYUnits; y += verticalSpace; } //Vertical Grid Lines var x = horizontalStartSpace; double startGridX = 0; for (var counter = 0; counter <= numVerticalLines; counter++) { var line = new SvgPath() { Index = counter, Data = $"M {ToS(x)} {ToS((boundHeight - verticalStartSpace))} L {ToS(x)} {ToS(verticalEndSpace)}" }; _verticalLines.Add(line); var xLabels = ""; if (counter < numXLabels) { xLabels = XAxisLabels[counter]; } var lineValue = new SvgText() { X = x, Y = boundHeight - 2, Value = xLabels }; _verticalValues.Add(lineValue); startGridX += gridXUnits; x += horizontalSpace; } //Chart Lines var colorcounter = 0; foreach (var item in _series) { var chartLine = ""; double gridValueX = 0; double gridValueY = 0; var firstTime = true; double[] XValues = new double[item.Data.Length]; double[] YValues = new double[item.Data.Length]; ILineInterpolator interpolator; for (var i = 0; i <= item.Data.Length - 1; i++) { if (i == 0) XValues[i] = 30; else XValues[i] = XValues[i - 1] + horizontalSpace; var gridValue = (item.Data[i]) * verticalSpace / gridYUnits; YValues[i] = boundHeight - (verticalStartSpace + gridValue); } switch (interpolationOption) { case InterpolationOption.NaturalSpline: interpolator = new NaturalSpline(XValues, YValues); break; case InterpolationOption.EndSlope: interpolator = new EndSlopeSpline(XValues, YValues); break; case InterpolationOption.Periodic: interpolator = new PeriodicSpline(XValues, YValues); break; case InterpolationOption.Straight: default: interpolator = new NoInterpolation(); break; } if (interpolator?.InterpolationRequired == true) { horizontalSpace = (boundWidth - horizontalStartSpace - horizontalEndSpace) / interpolator.InterpolatedXs.Length; foreach (var yValue in interpolator.InterpolatedYs) { if (firstTime) { chartLine += "M "; firstTime = false; gridValueX = horizontalStartSpace; gridValueY = verticalStartSpace; } else { chartLine += " L "; gridValueX += horizontalSpace; gridValueY = verticalStartSpace; } gridValueY = yValue; chartLine = chartLine + ToS(gridValueX) + " " + ToS(gridValueY); } } else { foreach (var dataLine in item.Data) { if (firstTime) { chartLine += "M "; firstTime = false; gridValueX = horizontalStartSpace; gridValueY = verticalStartSpace; } else { chartLine += " L "; gridValueX += horizontalSpace; gridValueY = verticalStartSpace; } var gridValue = ((double)dataLine) * verticalSpace / gridYUnits; gridValueY = boundHeight - (gridValueY + gridValue); chartLine = chartLine + ToS(gridValueX) + " " + ToS(gridValueY); } } var line = new SvgPath() { Index = colorcounter, Data = chartLine }; var legend = new SvgLegend() { Index = colorcounter, Labels = item.Name }; colorcounter++; _chartLines.Add(line); _legends.Add(legend); } } }