/// <summary> /// Converts from chart values to chart control size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation to scale value at</param> /// <param name="chart">chart model to scale value at</param> /// <param name="axis">axis model instance</param> /// <returns></returns> public static double ToPlotArea(double value, AxisOrientationNew source, ChartCore chart, AxisCoreNew axis) { var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientationNew.Y) { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Top; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height; } else { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return(m * (value - p1.X) + p1.Y); }
/// <summary> /// Ases the core element. /// </summary> /// <param name="axis">The axis.</param> /// <param name="source">The source.</param> /// <returns></returns> public AxisSectionCoreNew AsCoreElement(AxisCoreNew axis, AxisOrientationNew source) { var model = new AxisSectionCoreNew(this, axis.Chart); model.View.Model = model; return(model); }
/// <summary> /// /// </summary> internal override CoreMargin PrepareChart(AxisOrientationNew source, ChartCore chart) { if (!(Math.Abs(TopLimit - BotLimit) > S * .01) || !ShowLabels) { return(new CoreMargin()); } var currentMargin = new CoreMargin(); var tolerance = S / 10; InitializeGarbageCollector(); // Determine which magnitude and unit to use var m = (!double.IsNaN(View.Unit) ? View.Unit : Magnitude); var u = (!double.IsNaN(View.Unit) ? View.Unit : 1); // Calculate the separator indices var indices = CalculateSeparatorIndices(chart, source, u); // Draw the separators foreach (var index in indices) { DrawSeparator(index, tolerance, currentMargin, source); } return(currentMargin); }
internal double FromPreviousState(double value, AxisOrientationNew source, ChartCore chart) { if (LastAxisMax == null) { return(0); } var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientationNew.Y) { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Top; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Top + LastPlotArea.Height; } else { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Width + LastPlotArea.Left; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); var d = m * (value - p1.X) + p1.Y; return(d); }
/// <summary> /// Converts from chart values to chart draw margin size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to scale the value at</param> /// <param name="axis">axis instance to scale the value at</param> /// <returns></returns> public static double ToDrawMargin(double value, AxisOrientationNew source, ChartCore chart, AxisCoreNew axis) { var o = source == AxisOrientationNew.X ? chart.DrawMargin.Left : chart.DrawMargin.Top; return(ToPlotArea(value, source, chart, axis) - o); }
internal override CoreMargin PrepareChart(AxisOrientationNew source, ChartCore chart) { // Get the current configued values from the view _initialDateTime = ((IDateAxisView)View).InitialDateTime; _period = ((IDateAxisView)View).Period; return(base.PrepareChart(source, chart)); }
/// <summary> /// Ases the core element. /// </summary> /// <param name="axis">The axis.</param> /// <param name="source">The source.</param> /// <returns></returns> public SeparatorConfigurationCore AsCoreElement(AxisCoreNew axis, AxisOrientationNew source) { AxisOrientation = source; Chart = axis.Chart; Axis = axis; return(new SeparatorConfigurationCore(axis) { IsEnabled = IsEnabled, Step = Step, Source = source }); }
internal virtual CoreMargin PrepareChart(AxisOrientationNew source, ChartCore chart) { if (!(Math.Abs(TopLimit - BotLimit) > S * .01) || !ShowLabels) { return(new CoreMargin()); } CalculateSeparator(chart, source); var f = GetFormatter(); var currentMargin = new CoreMargin(); var tolerance = S / 10; InitializeGarbageCollector(); var m = !double.IsNaN(View.BarUnit) ? View.BarUnit : (!double.IsNaN(View.Unit) ? View.Unit : Magnitude); var u = !double.IsNaN(View.BarUnit) ? View.BarUnit : (!double.IsNaN(View.Unit) ? View.Unit : 1); if (TopLimit <= 0 && BotLimit < 0) { var l = TopLimit - (EvaluatesUnitWidth ? u : 0); LastSeparator = l; for (var i = l; i >= Math.Truncate(BotLimit / m) * m; i -= S) { FirstSeparator = i; DrawSeparator(i, tolerance, currentMargin, f, source); } } else { var l = Math.Truncate(BotLimit / m) * m; FirstSeparator = l; for (var i = l; i <= TopLimit - (EvaluatesUnitWidth ? u : 0); i += S) { LastSeparator = i; DrawSeparator(i, tolerance, currentMargin, f, source); } } return(currentMargin); }
internal virtual void CalculateSeparator(ChartCore chart, AxisOrientationNew source) { var range = TopLimit - BotLimit; range = range <= 0 ? 1 : range; //ToDO: Improve this according to current labels! var separations = source == AxisOrientationNew.Y ? Math.Round(chart.ControlSize.Height / ((12) * CleanFactor), 0) // at least 3 font 12 labels per separator. : Math.Round(chart.ControlSize.Width / (50 * CleanFactor), 0); // at least 150 pixels per separator. separations = separations < 2 ? 2 : separations; var minimum = range / separations; Magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10))); if (!double.IsNaN(Separator.Step)) { S = Separator.Step; return; } var residual = minimum / Magnitude; double tick; if (residual > 5) { tick = 10 * Magnitude; } else if (residual > 2) { tick = 5 * Magnitude; } else if (residual > 1) { tick = 2 * Magnitude; } else { tick = Magnitude; } S = tick; if (Labels != null) { S = S < 1 ? 1 : S; } }
public override AxisCoreNew AsCoreElement(ChartCore chart, AxisOrientationNew source) { if (Model == null) { Model = new WindowAxisCore(this); } Model.ShowLabels = ShowLabels; Model.Chart = chart; Model.IsMerged = IsMerged; Model.Labels = Labels; Model.LabelFormatter = LabelFormatter; Model.MaxValue = MaxValue; Model.MinValue = MinValue; Model.Title = Title; Model.Position = Position; Model.Separator = Separator.AsCoreElement(Model, source); Model.DisableAnimations = DisableAnimations; Model.Sections = Sections.Select(x => x.AsCoreElement(Model, source)).ToList(); ((WindowAxisCore)Model).Windows = Windows.ToList(); return(Model); }
/// <summary> /// Gets the width of a unit in the chart /// </summary> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to get the scale at</param> /// <param name="axis">axis instance</param> /// <returns></returns> public static double GetUnitWidth(AxisOrientationNew source, ChartCore chart, AxisCoreNew axis) { double min; double u = !double.IsNaN(axis.View.BarUnit) ? axis.View.BarUnit : (!double.IsNaN(axis.View.Unit) ? axis.View.Unit : 1); if (source == AxisOrientationNew.Y) { min = axis.BotLimit; return(ToDrawMargin(min, AxisOrientationNew.Y, chart, axis) - ToDrawMargin(min + u, AxisOrientationNew.Y, chart, axis)); } min = axis.BotLimit; return(ToDrawMargin(min + u, AxisOrientationNew.X, chart, axis) - ToDrawMargin(min, AxisOrientationNew.X, chart, axis)); }
internal IEnumerable <double> CalculateSeparatorIndices(ChartCore chart, AxisOrientationNew source, double unit) { if (!double.IsNaN(Separator.Step)) { throw new Exception("Step should be NaN for WindowAxis separators"); } if (Windows == null) { return(Enumerable.Empty <double>()); } // Holder for the calculated separator indices and the proposed window var supportedSeparatorCount = 0; var separatorIndices = new List <double>(); IAxisWindow proposedWindow = AxisWindows.EmptyWindow; // Build a range of possible separator indices var rangeIndices = Enumerable.Range((int)Math.Floor(BotLimit), (int)Math.Floor(TopLimit - (EvaluatesUnitWidth ? unit : 0) - BotLimit)).Select(i => (double)i).ToList(); // Make sure we have at least 2 separators to show if (Windows != null && rangeIndices.Count > 1) { foreach (var window in Windows) { IEnumerable <double> proposedSeparatorIndices; // Calculate the number of supported separators. supportedSeparatorCount = (int)Math.Floor(chart.ControlSize.Width / (window.MinimumSeparatorWidth * CleanFactor)); // Try go get separators. Continue if the window invalidated. if (!window.TryGetSeparatorIndices(rangeIndices, supportedSeparatorCount, out proposedSeparatorIndices)) { continue; } // Double check whether the window exceeded the maximum separator count. // It might be it does not respect the supportedSeparatorCount parameter. separatorIndices = proposedSeparatorIndices.ToList(); if (supportedSeparatorCount < separatorIndices.Count) { continue; } // Pick this window. It is the first who passed both validations and our best candidate proposedWindow = window; break; } } if (proposedWindow == null) { // All variables are still set to defaults } // Force the step of 1, as our prepare chart will filter the X axis for valid separators, and will skip a few S = 1; Magnitude = Math.Pow(10, Math.Floor(Math.Log(supportedSeparatorCount) / Math.Log(10))); SelectedWindow = proposedWindow; return(separatorIndices); }
/// <summary> /// Draws the or move. /// </summary> /// <param name="source">The source.</param> /// <param name="axis">The axis.</param> public void DrawOrMove(AxisOrientationNew source, int axis) { _rectangle.Fill = Fill; _rectangle.Stroke = Stroke; _rectangle.StrokeDashArray = StrokeDashArray; _rectangle.StrokeThickness = StrokeThickness; Panel.SetZIndex(_rectangle, Panel.GetZIndex(this)); BindingOperations.SetBinding(_rectangle, VisibilityProperty, new Binding { Path = new PropertyPath(VisibilityProperty), Source = this }); var ax = source == AxisOrientationNew.X ? Model.Chart.AxisX[axis] : Model.Chart.AxisY[axis]; var uw = ax.EvaluatesUnitWidth ? ChartFunctionsNew.GetUnitWidth(source, Model.Chart, axis) / 2 : 0; if (Parent == null) { _label = ((AxisNew)ax.View).BindATextBlock(); _label.Padding = new Thickness(5, 2, 5, 2); Model.Chart.View.AddToView(this); Model.Chart.View.AddToDrawMargin(_rectangle); Model.Chart.View.AddToView(_label); _rectangle.Height = 0; _rectangle.Width = 0; Canvas.SetLeft(_rectangle, 0d); Canvas.SetTop(_rectangle, Model.Chart.DrawMargin.Height); #region Obsolete Canvas.SetTop(_label, Model.Chart.DrawMargin.Height); Canvas.SetLeft(_label, 0d); #endregion } #pragma warning disable 618 var from = ChartFunctionsNew.ToDrawMargin(double.IsNaN(FromValue) ? Value + SectionOffset : FromValue, source, Model.Chart, axis) + uw; #pragma warning restore 618 #pragma warning disable 618 var to = ChartFunctionsNew.ToDrawMargin(double.IsNaN(ToValue) ? Value + SectionOffset + SectionWidth : ToValue, source, Model.Chart, axis) + uw; #pragma warning restore 618 if (from > to) { var temp = to; to = from; from = temp; } var anSpeed = Model.Chart.View.AnimationsSpeed; if (DataLabel) { if (DataLabelForeground != null) { _label.Foreground = DataLabelForeground; } _label.UpdateLayout(); _label.Background = Stroke ?? Fill; PlaceLabel(ax.GetFormatter()(Value), ax, source); } if (source == AxisOrientationNew.X) { var w = to - from; w = StrokeThickness > w ? StrokeThickness : w; Canvas.SetTop(_rectangle, 0); _rectangle.Height = Model.Chart.DrawMargin.Height; if (Model.Chart.View.DisableAnimations || DisableAnimations) { _rectangle.Width = w > 0 ? w : 0; Canvas.SetLeft(_rectangle, from - StrokeThickness / 2); } else { _rectangle.BeginAnimation(WidthProperty, new DoubleAnimation(w > 0 ? w : 0, anSpeed)); _rectangle.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(from - StrokeThickness / 2, anSpeed)); } return; } var h = to - from; h = StrokeThickness > h ? StrokeThickness : h; Canvas.SetLeft(_rectangle, 0d); _rectangle.Width = Model.Chart.DrawMargin.Width; if (Model.Chart.View.DisableAnimations || DisableAnimations) { Canvas.SetTop(_rectangle, from - StrokeThickness / 2); _rectangle.Height = h > 0 ? h : 0; } else { _rectangle.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(from, anSpeed)); _rectangle.BeginAnimation(HeightProperty, new DoubleAnimation(h, anSpeed)); } }
private void DrawSeparator(double x, double tolerance, CoreMargin currentMargin, AxisOrientationNew source) { SeparatorElementCore elementCore; var key = Math.Round(x / tolerance) * tolerance; if (!Cache.TryGetValue(key, out elementCore)) { elementCore = new DateSeparatorElementCore { IsNew = true }; Cache[key] = elementCore; } else { elementCore.IsNew = false; } // Determine whether this separator is a header now ((DateSeparatorElementCore)elementCore).IsHeader = SelectedWindow.IsHeader(x); View.RenderSeparator(elementCore, Chart); elementCore.Key = key; elementCore.Value = x; elementCore.GarbageCollectorIndex = GarbageCollectorIndex; var labelsMargin = elementCore.View.UpdateLabel(SelectedWindow.FormatAxisLabel(x), this, source); currentMargin.Width = labelsMargin.TakenWidth > currentMargin.Width ? labelsMargin.TakenWidth : currentMargin.Width; currentMargin.Height = labelsMargin.TakenHeight > currentMargin.Height ? labelsMargin.TakenHeight : currentMargin.Height; currentMargin.Left = labelsMargin.Left > currentMargin.Left ? labelsMargin.Left : currentMargin.Left; currentMargin.Right = labelsMargin.Right > currentMargin.Right ? labelsMargin.Right : currentMargin.Right; currentMargin.Top = labelsMargin.Top > currentMargin.Top ? labelsMargin.Top : currentMargin.Top; currentMargin.Bottom = labelsMargin.Bottom > currentMargin.Bottom ? labelsMargin.Bottom : currentMargin.Bottom; if (LastAxisMax == null) { elementCore.State = SeparationState.InitialAdd; return; } elementCore.State = SeparationState.Keep; }
internal override CoreMargin PrepareChart(AxisOrientationNew source, ChartCore chart) { if (!(Math.Abs(TopLimit - BotLimit) > S * .01) || !ShowLabels) { return(new CoreMargin()); } CalculateSeparator(chart, source); var f = GetFormatter(); var currentMargin = new CoreMargin(); if (S < 1) { S = 1; } var tolerance = S / 10; InitializeGarbageCollector(); var bl = Math.Ceiling(BotLimit / Magnitude) * Magnitude; var @base = ((ILogarithmicAxisView)View).Base; for (var i = bl; i <= TopLimit - (EvaluatesUnitWidth ? 1 : 0); i += S) { var minTolerance = tolerance / 10; if (Math.Abs(i - bl) > tolerance) { var step = Math.Pow(@base, i - 1); for (var j = Math.Pow(@base, i - 1) + step; j < Math.Pow(@base, i); j += step) { SeparatorElementCore minorAsc; var scaledJ = Math.Log(j, @base); var minorKey = Math.Round(scaledJ / minTolerance) * minTolerance; if (!Cache.TryGetValue(minorKey, out minorAsc)) { minorAsc = new SeparatorElementCore { IsNew = true }; Cache[minorKey] = minorAsc; } else { minorAsc.IsNew = false; } View.RenderSeparator(minorAsc, Chart); minorAsc.Key = minorKey; minorAsc.Value = scaledJ; minorAsc.GarbageCollectorIndex = GarbageCollectorIndex; minorAsc.View.UpdateLabel(string.Empty, this, source); if (LastAxisMax == null) { minorAsc.State = SeparationState.InitialAdd; continue; } minorAsc.State = SeparationState.Keep; } } SeparatorElementCore asc; var key = Math.Round(i / tolerance) * tolerance; if (!Cache.TryGetValue(key, out asc)) { asc = new SeparatorElementCore { IsNew = true }; Cache[key] = asc; } else { asc.IsNew = false; } View.RenderSeparator(asc, Chart); asc.Key = key; asc.Value = i; asc.GarbageCollectorIndex = GarbageCollectorIndex; var labelsMargin = asc.View.UpdateLabel(f(i), this, source); currentMargin.Width = labelsMargin.TakenWidth > currentMargin.Width ? labelsMargin.TakenWidth : currentMargin.Width; currentMargin.Height = labelsMargin.TakenHeight > currentMargin.Height ? labelsMargin.TakenHeight : currentMargin.Height; currentMargin.Left = labelsMargin.Left > currentMargin.Left ? labelsMargin.Left : currentMargin.Left; currentMargin.Right = labelsMargin.Right > currentMargin.Right ? labelsMargin.Right : currentMargin.Right; currentMargin.Top = labelsMargin.Top > currentMargin.Top ? labelsMargin.Top : currentMargin.Top; currentMargin.Bottom = labelsMargin.Bottom > currentMargin.Bottom ? labelsMargin.Bottom : currentMargin.Bottom; if (LastAxisMax == null) { asc.State = SeparationState.InitialAdd; continue; } asc.State = SeparationState.Keep; } return(currentMargin); }
private void PlaceLabel(string text, AxisCoreNew axis, AxisOrientationNew source) { _label.Text = text; var formattedText = new FormattedText( _label.Text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(_label.FontFamily, _label.FontStyle, _label.FontWeight, _label.FontStretch), _label.FontSize, Brushes.Black); var transform = new LabelEvaluation(axis.View.LabelsRotation, formattedText.Width + 10, formattedText.Height, axis, source); _label.RenderTransform = Math.Abs(transform.LabelAngle) > 1 ? new RotateTransform(transform.LabelAngle) : null; var toLine = ChartFunctionsNew.ToPlotArea(Value + SectionOffset + SectionWidth * .5, source, Model.Chart, axis); var direction = source == AxisOrientationNew.X ? 1 : -1; toLine += axis.EvaluatesUnitWidth ? direction * ChartFunctionsNew.GetUnitWidth(source, Model.Chart, axis) / 2 : 0; var toLabel = toLine + transform.GetOffsetBySource(source); var chart = Model.Chart; if (axis.IsMerged) { const double padding = 4; if (source == AxisOrientationNew.Y) { if (toLabel + transform.ActualHeight > chart.DrawMargin.Top + chart.DrawMargin.Height) { toLabel -= transform.ActualHeight + padding; } } else { if (toLabel + transform.ActualWidth > chart.DrawMargin.Left + chart.DrawMargin.Width) { toLabel -= transform.ActualWidth + padding; } } } var labelTab = axis.Tab; labelTab += transform.GetOffsetBySource(source.Invert()); if (source == AxisOrientationNew.Y) { labelTab += 8 * (axis.Position == AxisPositionNew.LeftBottom ? 1 : -1); if (Model.View.DisableAnimations || DisableAnimations) { Canvas.SetLeft(_label, labelTab); Canvas.SetTop(_label, toLabel); return; } _label.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(toLabel, chart.View.AnimationsSpeed)); _label.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(labelTab, chart.View.AnimationsSpeed)); } else { if (Model.View.DisableAnimations || DisableAnimations) { Canvas.SetLeft(_label, toLabel); Canvas.SetTop(_label, labelTab); return; } _label.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(toLabel, chart.View.AnimationsSpeed)); _label.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(labelTab, chart.View.AnimationsSpeed)); } }
/// <summary> /// Gets the width of a unit in the chart /// </summary> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to get the scale at</param> /// <param name="axis">axis index in the axes collection</param> /// <returns></returns> public static double GetUnitWidth(AxisOrientationNew source, ChartCore chart, int axis = 0) { return(GetUnitWidth(source, chart, (source == AxisOrientationNew.X ? chart.AxisX : chart.AxisY)[axis])); }
internal void UpdateSeparators(AxisOrientationNew source, ChartCore chart, int axisIndex) { foreach (var element in Cache.Values.ToArray()) { if (element.GarbageCollectorIndex < GarbageCollectorIndex) { element.State = SeparationState.Remove; Cache.Remove(element.Key); } var toLine = ChartFunctionsNew.ToPlotArea(element.Value, source, chart, axisIndex); var direction = source == AxisOrientationNew.X ? 1 : -1; toLine += EvaluatesUnitWidth ? direction * ChartFunctionsNew.GetUnitWidth(source, chart, this) / 2 : 0; var toLabel = toLine + element.View.LabelModel.GetOffsetBySource(source); if (IsMerged) { const double padding = 4; if (source == AxisOrientationNew.Y) { if (toLabel + element.View.LabelModel.ActualHeight > chart.DrawMargin.Top + chart.DrawMargin.Height) { toLabel -= element.View.LabelModel.ActualHeight + padding; } } else { if (toLabel + element.View.LabelModel.ActualWidth > chart.DrawMargin.Left + chart.DrawMargin.Width) { toLabel -= element.View.LabelModel.ActualWidth + padding; } } } var labelTab = Tab; labelTab += element.View.LabelModel.GetOffsetBySource(source.Invert()); switch (element.State) { case SeparationState.Remove: if (!chart.View.DisableAnimations && !View.DisableAnimations) { element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); element.View.FadeOutAndRemove(chart); } else { element.View.Remove(chart); } break; case SeparationState.Keep: if (!chart.View.DisableAnimations && !View.DisableAnimations) { if (element.IsNew) { var toLinePrevious = FromPreviousState(element.Value, source, chart); toLinePrevious += EvaluatesUnitWidth ? ChartFunctionsNew.GetUnitWidth(source, chart, this) / 2 : 0; var toLabelPrevious = toLinePrevious + element.View.LabelModel.GetOffsetBySource(source); element.View.Place(chart, this, source, axisIndex, toLabelPrevious, toLinePrevious, labelTab); element.View.FadeIn(this, chart); } element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); } else { element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); } break; case SeparationState.InitialAdd: element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); break; default: throw new ArgumentOutOfRangeException(); } } LastAxisMax = TopLimit; LastAxisMin = BotLimit; LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top, chart.DrawMargin.Width, chart.DrawMargin.Height); }
private void DrawSeparator(double i, double tolerance, CoreMargin currentMargin, Func <double, string> f, AxisOrientationNew source) { if (i < BotLimit) { return; } SeparatorElementCore asc; var key = Math.Round(i / tolerance) * tolerance; if (!Cache.TryGetValue(key, out asc)) { asc = new SeparatorElementCore { IsNew = true }; Cache[key] = asc; } else { asc.IsNew = false; } View.RenderSeparator(asc, Chart); asc.Key = key; asc.Value = i; asc.GarbageCollectorIndex = GarbageCollectorIndex; var labelsMargin = asc.View.UpdateLabel(f(i), this, source); currentMargin.Width = labelsMargin.TakenWidth > currentMargin.Width ? labelsMargin.TakenWidth : currentMargin.Width; currentMargin.Height = labelsMargin.TakenHeight > currentMargin.Height ? labelsMargin.TakenHeight : currentMargin.Height; currentMargin.Left = labelsMargin.Left > currentMargin.Left ? labelsMargin.Left : currentMargin.Left; currentMargin.Right = labelsMargin.Right > currentMargin.Right ? labelsMargin.Right : currentMargin.Right; currentMargin.Top = labelsMargin.Top > currentMargin.Top ? labelsMargin.Top : currentMargin.Top; currentMargin.Bottom = labelsMargin.Bottom > currentMargin.Bottom ? labelsMargin.Bottom : currentMargin.Bottom; if (LastAxisMax == null) { asc.State = SeparationState.InitialAdd; return; } asc.State = SeparationState.Keep; }