Skip to content
Open
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
115 changes: 66 additions & 49 deletions maui/src/Charts/Area/Partial/CartesianChartArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,10 @@ internal void UpdateSBS()
double totalWidth = GetTotalWidth() / SideBySideSeriesPosition.Count;
double startPosition = 0, end = 0;

for (int i = 0; i < SideBySideSeriesPosition.Count; i++)
var seriesGroups = SideBySideSeriesPosition.Values.ToList();
for (int i = 0; i < seriesGroups.Count; i++)
{
var seriesGroup = SideBySideSeriesPosition.Values.ToList()[i];
var seriesGroup = seriesGroups[i];
double sbsMaxWidth = GetSBSMaxWidth(seriesGroup);

foreach (ChartSeries chartSeries in seriesGroup)
Expand Down Expand Up @@ -370,10 +371,11 @@ double GetTotalWidth()

if (SideBySideSeriesPosition != null)
{
for (int i = 0; i < SideBySideSeriesPosition.Count; i++)
var valuesList = SideBySideSeriesPosition.Values.ToList();
for (int i = 0; i < valuesList.Count; i++)
{
double maxWidth = 0;
foreach (ChartSeries sideBySideSeries in SideBySideSeriesPosition.Values.ToList()[i])
foreach (ChartSeries sideBySideSeries in valuesList[i])
{
CartesianSeries cartesianSeries = (CartesianSeries)sideBySideSeries;
double width = cartesianSeries.GetActualWidth();
Expand Down Expand Up @@ -483,73 +485,88 @@ static void CalculateStackingValues(Dictionary<string, List<StackingSeriesBase>>
}

foreach (var series in seriesList)
{
var xValues = series.GetXValues();
var yValues = series.YValues;
var bottomValues = new List<double>();
var topValues = new List<double>();
var seriesTypeName = series.GetType().Name;
bool is100Series = seriesTypeName.Contains("Stacking", StringComparison.Ordinal) && seriesTypeName.Contains("100Series", StringComparison.Ordinal);

if (xValues != null)
{
var xValues = series.GetXValues();
var yValues = series.YValues;
var bottomValues = new List<double>();
var topValues = new List<double>();

if (xValues != null)
for (int i = 0; i < xValues.Count; i++)
{
for (int i = 0; i < xValues.Count; i++)
{
var xValue = xValues[i];
var yValue = i < yValues.Count ? yValues[i] : 0;
yValue = double.IsNaN(yValue) ? 0 : yValue;
var xValue = xValues[i];
var yValue = i < yValues.Count ? yValues[i] : 0;
yValue = double.IsNaN(yValue) ? 0 : yValue;

if (yValue >= 0)
if (yValue >= 0)
{
if (positiveYValues.TryGetValue(xValue, out double currentValue))
{
if (positiveYValues.TryGetValue(xValue, out double currentValue))
{
bottomValues.Add((axisCross > currentValue) ? axisCross : currentValue);
if (series.GetType().Name.Contains("Stacking", StringComparison.Ordinal) && series.GetType().Name.Contains("100Series", StringComparison.Ordinal))
{
yValue = GetYValue(seriesList, yValue, i);
}
positiveYValues[xValue] = currentValue + yValue;
}
else
bottomValues.Add((axisCross > currentValue) ? axisCross : currentValue);
if (is100Series)
{
bottomValues.Add(axisCross);
if (series.GetType().Name.Contains("Stacking", StringComparison.Ordinal) && series.GetType().Name.Contains("100Series", StringComparison.Ordinal))
{
yValue = GetYValue(seriesList, yValue, i);
}
positiveYValues.Add(xValue, yValue);
yValue = GetYValue(seriesList, yValue, i);
}

topValues.Add(positiveYValues[xValue]);
positiveYValues[xValue] = currentValue + yValue;
}
else
{
if (!negativeYValues.TryAdd(xValue, yValue))
bottomValues.Add(axisCross);
if (is100Series)
{
bottomValues.Add((axisCross < negativeYValues[xValue]) ? axisCross : negativeYValues[xValue]);
if (series.GetType().Name.Contains("Stacking", StringComparison.Ordinal) && series.GetType().Name.Contains("100Series", StringComparison.Ordinal))
{
yValue = GetYValue(seriesList, yValue, i);
}
negativeYValues[xValue] += yValue;
yValue = GetYValue(seriesList, yValue, i);
}
else
positiveYValues.Add(xValue, yValue);
}

topValues.Add(positiveYValues[xValue]);
}
else
{
if (!negativeYValues.TryAdd(xValue, yValue))
{
bottomValues.Add((axisCross < negativeYValues[xValue]) ? axisCross : negativeYValues[xValue]);
if (is100Series)
{
bottomValues.Add(axisCross);
yValue = GetYValue(seriesList, yValue, i);
}

topValues.Add(negativeYValues[xValue]);
negativeYValues[xValue] += yValue;
}
else
{
bottomValues.Add(axisCross);
}
}

series.BottomValues = bottomValues;
series.TopValues = topValues;
topValues.Add(negativeYValues[xValue]);
}
}

series.BottomValues = bottomValues;
series.TopValues = topValues;
}
}
}
}

static double GetYValue(List<StackingSeriesBase> SeriesList, double yValue, int index)
{
double total = SeriesList.Where(series => series != null && series.YValues.Count > index).Sum(series => double.IsNaN(series.YValues[index]) ? 0 : Math.Abs(series.YValues[index]));
double total = 0;
for (int i = 0; i < SeriesList.Count; i++)
{
var series = SeriesList[i];
if (series != null && series.YValues.Count > index)
{
double val = series.YValues[index];
if (!double.IsNaN(val))
{
total += Math.Abs(val);
}
}
}

if (yValue != 0)
{
yValue = (yValue / total) * 100;
Expand Down
26 changes: 21 additions & 5 deletions maui/src/Charts/Axis/CategoryAxis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ internal void GroupData()
{
if (groupedDatas.Count != 0)
{
for (int j = 0; j <= xValues.Count - 1; j++)
var seen = new HashSet<string>(groupingValues);
for (int j = 0; j < xValues.Count; j++)
{
if (!groupingValues.Contains(xValues[j]))
if (seen.Add(xValues[j]))
{
groupingValues.Add(xValues[j]);
}
Expand All @@ -65,16 +66,31 @@ internal void GroupData()
}

var distinctXValues = groupingValues.Distinct().ToList();
var indexLookup = new Dictionary<string, int>(distinctXValues.Count);
for (int i = 0; i < distinctXValues.Count; i++)
{
indexLookup[distinctXValues[i]] = i;
}

foreach (CartesianSeries series in RegisteredSeries.Cast<CartesianSeries>())
{
if (series.ActualXValues is List<string> list)
{
series.GroupedXValuesIndexes = (from val in list select (double)distinctXValues.IndexOf(val)).ToList();
var indexes = new List<double>(list.Count);
for (int i = 0; i < list.Count; i++)
{
indexes.Add(indexLookup.TryGetValue(list[i], out int idx) ? idx : -1);
}
series.GroupedXValuesIndexes = indexes;
}
else if (series.ActualXValues != null)
else if (series.ActualXValues is List<double> doubleValues)
{
series.GroupedXValuesIndexes = (from val in series.ActualXValues as List<double> select (double)distinctXValues.IndexOf(val.ToString())).ToList();
var indexes = new List<double>(doubleValues.Count);
for (int i = 0; i < doubleValues.Count; i++)
{
indexes.Add(indexLookup.TryGetValue(doubleValues[i].ToString(), out int idx) ? idx : -1);
}
series.GroupedXValuesIndexes = indexes;
}

series.GroupedXValues = distinctXValues;
Expand Down
13 changes: 10 additions & 3 deletions maui/src/Charts/Axis/Layouts/CartesianAxisLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,17 @@ void InternalCreateSegments(ChartSeries series)

static ChartAxis? GetAxisByName(string name, ObservableCollection<ChartAxis>? axes)
{
var item = (from x in axes where x.Name == name select x).ToList();
if (item != null && item.Count > 0)
if (axes == null)
{
return null;
}

for (int i = 0; i < axes.Count; i++)
{
return item[0];
if (axes[i].Name == name)
{
return axes[i];
}
}

return null;
Expand Down
93 changes: 72 additions & 21 deletions maui/src/Charts/Segment/ErrorBarSegment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,30 @@ internal override void SetData(IList xList, IList yList)
break;
}

double xMin = xValues.Where(v => !double.IsNaN(v)).DefaultIfEmpty(0).Min();
double xMax = xValues.Where(v => !double.IsNaN(v)).DefaultIfEmpty(0).Max();
double yMin = yValues.Where(v => !double.IsNaN(v)).DefaultIfEmpty(0).Min();
double yMax = yValues.Where(v => !double.IsNaN(v)).DefaultIfEmpty(0).Max();
double xMin = double.MaxValue, xMax = double.MinValue;
double yMin = double.MaxValue, yMax = double.MinValue;
for (int i = 0; i < xValues.Count; i++)
{
double xVal = xValues[i];
if (!double.IsNaN(xVal))
{
if (xVal < xMin) xMin = xVal;
if (xVal > xMax) xMax = xVal;
}
}
for (int i = 0; i < yValues.Count; i++)
{
double yVal = yValues[i];
if (!double.IsNaN(yVal))
{
if (yVal < yMin) yMin = yVal;
if (yVal > yMax) yMax = yVal;
}
}
if (xMin == double.MaxValue) xMin = 0;
if (xMax == double.MinValue) xMax = 0;
if (yMin == double.MaxValue) yMin = 0;
if (yMax == double.MinValue) yMax = 0;

double leftPointMin = xMin - _horizontalErrorValue;
double leftPointMax = xMax - _horizontalErrorValue;
Expand Down Expand Up @@ -192,12 +212,35 @@ internal override void SetData(IList xList, IList yList)

if (errorBarSeries.Type == ErrorBarType.Percentage)
{
var validTopPoints = _topPointCollection.Where(p => !double.IsNaN(p.Y)).Select(p => p.Y);
var validBottomPoints = _bottomPointCollection.Where(p => !double.IsNaN(p.Y)).Select(p => p.Y);
double rangeMin = double.MaxValue;
double rangeMax = double.MinValue;
bool hasValid = false;

if (validTopPoints.Any() && validBottomPoints.Any())
for (int i = 0; i < _topPointCollection.Count; i++)
{
YRange = new DoubleRange(Math.Min(validBottomPoints.Min(), validTopPoints.Min()), Math.Max(validBottomPoints.Max(), validTopPoints.Max()));
double y = _topPointCollection[i].Y;
if (!double.IsNaN(y))
{
if (y < rangeMin) rangeMin = y;
if (y > rangeMax) rangeMax = y;
hasValid = true;
}
}

for (int i = 0; i < _bottomPointCollection.Count; i++)
{
double y = _bottomPointCollection[i].Y;
if (!double.IsNaN(y))
{
if (y < rangeMin) rangeMin = y;
if (y > rangeMax) rangeMax = y;
hasValid = true;
}
}

if (hasValid)
{
YRange = new DoubleRange(rangeMin, rangeMax);
}
}
else
Expand Down Expand Up @@ -383,28 +426,36 @@ double[] GetSdErrorValue(IList<double> values)
return valueDoubles;
}

var validValues = values.Where(v => !double.IsNaN(v)).ToList();
double sum = 0;
int validCount = 0;
for (int i = 0; i < values.Count; i++)
{
if (!double.IsNaN(values[i]))
{
sum += values[i];
validCount++;
}
}

if (validValues.Count <= 1)
if (validCount <= 1)
{
return valueDoubles;
}

var sum = validValues.Sum();
var mean = sum / validValues.Count;
var dev = new List<double>();
var sQDev = new List<double>();
double mean = sum / validCount;
double sumSqDev = 0;

for (var i = 0; i < validValues.Count; i++)
for (int i = 0; i < values.Count; i++)
{
dev.Add(validValues[i] - mean);
sQDev.Add(dev[i] * dev[i]);
if (!double.IsNaN(values[i]))
{
double dev = values[i] - mean;
sumSqDev += dev * dev;
}
}

var sumSqDev = sQDev.Sum(x => x);

var sDValue = Math.Sqrt(sumSqDev / (validValues.Count - 1));
var sDErrorValue = sDValue / Math.Sqrt(validValues.Count);
var sDValue = Math.Sqrt(sumSqDev / (validCount - 1));
var sDErrorValue = sDValue / Math.Sqrt(validCount);

valueDoubles[0] = mean;
valueDoubles[1] = errorBarSeries.Type == ErrorBarType.StandardDeviation ? sDValue : sDErrorValue;
Expand Down
24 changes: 21 additions & 3 deletions maui/src/Charts/Series/CartesianSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,18 +1027,36 @@ internal override void UpdateRange()
return null;
}

double xIndexValues = 0d;
var xValues = ActualXValues as List<double>;

if (IsIndexed || xValues == null)
{
if (ActualXAxis is CategoryAxis categoryAxis && !categoryAxis.ArrangeByIndex || ActualXAxis == null)
{
xValues = GroupedXValuesIndexes.Count > 0 ? GroupedXValuesIndexes : (from val in (ActualXValues as List<string>) select (xIndexValues++)).ToList();
if (GroupedXValuesIndexes.Count > 0)
{
xValues = GroupedXValuesIndexes;
}
else
{
var stringValues = ActualXValues as List<string>;
int count = stringValues?.Count ?? 0;
xValues = new List<double>(count);
for (int i = 0; i < count; i++)
{
xValues.Add(i);
}
}
}
else
{
xValues = xValues != null ? (from val in xValues select (xIndexValues++)).ToList() : (from val in (ActualXValues as List<string>) select (xIndexValues++)).ToList();
int count = xValues?.Count ?? (ActualXValues as List<string>)?.Count ?? 0;
var indexValues = new List<double>(count);
for (int i = 0; i < count; i++)
{
indexValues.Add(i);
}
xValues = indexValues;
}
}

Expand Down