protected void StackPoints(IEnumerable<ISeriesView> stackables, AxisOrientation stackAt, int stackIndex,
StackMode mode = StackMode.Values)
{
var stackedColumns = stackables.SelectMany(x => x.ActualValues.GetPoints(x))
.GroupBy(x => stackAt == AxisOrientation.X ? x.Y : x.X);
double mostLeft = 0, mostRight = 0;
foreach (var column in stackedColumns)
{
double sumLeft = 0, sumRight = 0;
foreach (var item in column)
{
var s = stackAt == AxisOrientation.X ? item.X : item.Y;
if (s < 0)
sumLeft += s;
else
sumRight += s;
}
var lastLeft = 0d;
var lastRight = 0d;
var leftPart = 0d;
var rightPart = 0d;
foreach (var point in column)
{
var pulled = stackAt == AxisOrientation.X ? point.X : point.Y;
//notice using (pulled < 0) or (pulled <= 0) could cause an issue similar to
//https://github.com/beto-rodriguez/Live-Charts/issues/231
//from that issue I changed <= to <
//only because it is more common to use positive values than negative
//you could face a similar issue if you are stacking only negative values
//a work around is forcing (pulled < 0) to be true,
//instead of using zero values, use -0.000000001/
if (pulled < 0)
{
point.From = lastLeft;
point.To = lastLeft + pulled;
point.Sum = sumLeft;
point.Participation = (point.To - point.From) / point.Sum;
point.Participation = double.IsNaN(point.Participation)
? 0
: point.Participation;
leftPart += point.Participation;
point.StackedParticipation = leftPart;
lastLeft = point.To;
}
else
{
point.From = lastRight;
point.To = lastRight + pulled;
point.Sum = sumRight;
point.Participation = (point.To - point.From) / point.Sum;
point.Participation = double.IsNaN(point.Participation)
? 0
: point.Participation;
rightPart += point.Participation;
point.StackedParticipation = rightPart;
lastRight = point.To;
}
}
if (sumLeft < mostLeft) mostLeft = sumLeft;
if (sumRight > mostRight) mostRight = sumRight;
}
if (stackAt == AxisOrientation.X)
{
if (mode == StackMode.Percentage)
{
AxisX[stackIndex].BotLimit = 0;
AxisX[stackIndex].TopLimit = 1;
}
else
{
if (mostLeft < AxisX[stackIndex].BotLimit)
// ReSharper disable once CompareOfFloatsByEqualityOperator
AxisX[stackIndex].BotLimit = mostLeft == 0
? 0
: ((int) (mostLeft/AxisX[stackIndex].S) - 1)*AxisX[stackIndex].S;
if (mostRight > AxisX[stackIndex].TopLimit)
// ReSharper disable once CompareOfFloatsByEqualityOperator
AxisX[stackIndex].TopLimit = mostRight == 0
? 0
: ((int) (mostRight/AxisX[stackIndex].S) + 1)*AxisX[stackIndex].S;
}
}
if (stackAt == AxisOrientation.Y)
{
if (mode == StackMode.Percentage)
{
AxisY[stackIndex].BotLimit = 0;
AxisY[stackIndex].TopLimit = 1;
}
else
{
if (mostLeft < AxisY[stackIndex].BotLimit)
// ReSharper disable once CompareOfFloatsByEqualityOperator
AxisY[stackIndex].BotLimit = mostLeft == 0
? 0
: ((int) (mostLeft/AxisY[stackIndex].S) - 1)*AxisY[stackIndex].S;
if (mostRight > AxisY[stackIndex].TopLimit)
// ReSharper disable once CompareOfFloatsByEqualityOperator
AxisY[stackIndex].TopLimit = mostRight == 0
? 0
: ((int) (mostRight/AxisY[stackIndex].S) + 1)*AxisY[stackIndex].S;
}
}
}