protected Range GetRangeFromChildren(Axis2D axis) { Range range = new Range(0, 0); Plot2DItem child; bool rangeUpdated = false; for (int i = 0; i < plotItems.Count; ++i) { child = plotItems[i]; if ((child.XAxis != axis) && (child.YAxis != axis)) continue; Rect bounds = child.PaddedBounds; if (bounds == Rect.Empty) continue; if (rangeUpdated == false) { range = (axis is XAxis) ? new Range(bounds.Left, bounds.Right) : new Range(bounds.Top, bounds.Bottom); rangeUpdated = true; } else range = range.Union((axis is XAxis) ? new Range(bounds.Left, bounds.Right) : new Range(bounds.Top, bounds.Bottom)); } return range; }
protected Range GetRangeFromChildren(Axis2D axis) { Range range = new Range(0, 0); Plot2DItem child; bool rangeUpdated = false; for (int i = 0; i < plotItems.Count; ++i) { child = plotItems[i]; if ((child.XAxis != axis) && (child.YAxis != axis)) { continue; } Rect bounds = child.PaddedBounds; if (rangeUpdated == false) { range = (axis is XAxis) ? new Range(bounds.Left, bounds.Right) : new Range(bounds.Top, bounds.Bottom); rangeUpdated = true; } else { range = range.Union((axis is XAxis) ? new Range(bounds.Left, bounds.Right) : new Range(bounds.Top, bounds.Bottom)); } } return(range); }
public GridLines(Axis2D axis) { this.axis = axis; gridLinesGeometry = new StreamGeometry(); this.Stroke = Brushes.LightGray; this.StrokeThickness = 1; this.StrokeLineJoin = PenLineJoin.Miter; }
/// <summary> /// Bind the Max and Min of this axis to another axis. /// </summary> /// <param name="bindingAxis"></param> public void BindToAxis(Axis2D bindingAxis) { axisBinding = new Binding("Range") { Source = this, Mode = BindingMode.TwoWay }; bindingAxis.SetBinding(Axis2D.RangeProperty, axisBinding); }
internal static void OnLabelsVisibleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue == (bool)e.OldValue) { return; } Axis2D axis = ((Axis2D)obj); if ((bool)e.NewValue == false) { foreach (LabelCacheItem item in axis.TickLabelCache) { axis.canvas.Children.Remove(item.Label); } axis.TickLabelCache.Clear(); } }
protected static void OnRangeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { Axis2D axis2DLocal = ((Axis2D)obj); Range desiredRange = (Range)e.NewValue; if (Double.IsNegativeInfinity(desiredRange.Min) || Double.IsNaN(desiredRange.Min) || Double.IsPositiveInfinity(desiredRange.Max) || Double.IsNaN(desiredRange.Max)) { axis2DLocal.SetValue(RangeProperty, e.OldValue); } if (axis2DLocal.AxisType == AxisType.Log) { if (desiredRange.Min <= 0 || desiredRange.Max <= 0) { axis2DLocal.SetValue(RangeProperty, e.OldValue); } } else if (axis2DLocal.AxisType == AxisType.Date) { if (desiredRange.Min < Axis.minDate || desiredRange.Max >= Axis.maxDate) { axis2DLocal.SetValue(RangeProperty, e.OldValue); } } double length = Math.Abs(desiredRange.Length); if ((Math.Abs(desiredRange.Min) / length > 1e10) || (Math.Abs(desiredRange.Max) / length > 1e10)) { axis2DLocal.SetValue(RangeProperty, e.OldValue); } axis2DLocal.DeriveTicks(); if (axis2DLocal.PlotPanel != null) { axis2DLocal.PlotPanel.InvalidateMeasure(); } }
/// <summary> /// Increase axis margins by amount necessary to ensure both that there is room /// for labels and that the necessary axes are aligned. /// </summary> /// <param name="alignedAxes">List of axes that need to be aligned.</param> private static void ExpandAxisMargins(List <Axis2D> alignedAxes, double plotLength) { // Calculate margins Thickness1D margin = new Thickness1D(alignedAxes.Max(axis => axis.AxisPadding.Lower), alignedAxes.Max(axis => axis.AxisPadding.Upper)); double minPlotLength = 1.0; if (plotLength > minPlotLength) { double newTotalLength = plotLength + margin.Total(); foreach (Axis2D axis in alignedAxes) { axis.AxisTotalLength = newTotalLength; } } else if ((alignedAxes[0].AxisTotalLength - margin.Total()) < minPlotLength) { foreach (Axis2D axis in alignedAxes) { axis.AxisTotalLength = margin.Total() + minPlotLength; } } // Set the margin and update Scale and Offset. foreach (Axis2D axis in alignedAxes) { axis.ResetAxisMargin(margin); } int tickIndex = 0; int maxTickIndex = alignedAxes.Max(axis => axis.Ticks.Length) / 2; int[] tickPair = new int[2]; Axis2D limitingLowerAxis = null; int limitingLowerTickIndex = 0; double limitingLowerSemiWidth = margin.Lower; Axis2D limitingUpperAxis = null; int limitingUpperTickIndex = 0; double limitingUpperSemiWidth = margin.Upper; double offsetLower = 0; double deltaLower = alignedAxes[0].MaxTransformed - alignedAxes[0].MinTransformed; double deltaUpper = deltaLower; double axisTotalLength = alignedAxes[0].AxisTotalLength; double offsetUpper = 0; int nRescales = 0; // for diagnosic purposes only while ((tickIndex <= maxTickIndex) && (nRescales < 10)) { bool reset = false; // if a rescaling is required, start again from the beginning. for (int i = 0; i < alignedAxes.Count; ++i) { Axis2D currentAxis = alignedAxes[i]; tickPair[0] = tickIndex; tickPair[1] = currentAxis.TicksTransformed.Length - 1 - tickIndex; if ((currentAxis.TicksTransformed.Length - 1 - tickIndex) < tickIndex) { continue; } for (int j = 0; j <= 1; ++j) { int index = tickPair[j]; if (!currentAxis.LabelsVisible || currentAxis.TickLabelCache[index].Label.Text == "" || !currentAxis.TickLabelCache[index].IsShown) { continue; } if ((currentAxis.Scale * currentAxis.TicksTransformed[index] - currentAxis.Offset - currentAxis.LimitingTickLabelSizeForLength(index) / 2) < -0.1) { // need to rescale axes limitingLowerAxis = currentAxis; limitingLowerTickIndex = index; limitingLowerSemiWidth = currentAxis.LimitingTickLabelSizeForLength(index) / 2; offsetLower = currentAxis.TicksTransformed[index] - currentAxis.MinTransformed; deltaLower = currentAxis.MaxTransformed - currentAxis.MinTransformed; } else if ((currentAxis.Scale * currentAxis.TicksTransformed[index] - currentAxis.Offset + currentAxis.LimitingTickLabelSizeForLength(index) / 2) > (currentAxis.AxisTotalLength + 0.1)) { // need to rescale axes limitingUpperAxis = currentAxis; limitingUpperTickIndex = index; limitingUpperSemiWidth = currentAxis.LimitingTickLabelSizeForLength(index) / 2; offsetUpper = currentAxis.MaxTransformed - currentAxis.TicksTransformed[index]; deltaUpper = currentAxis.MaxTransformed - currentAxis.MinTransformed; } else { continue; } // Reset required: reset = true; nRescales++; double offsetUpperPrime = offsetUpper * deltaLower / deltaUpper; // scale for lower-limiting axis double newScale = (axisTotalLength - limitingLowerSemiWidth - limitingUpperSemiWidth) / (deltaLower - offsetLower - offsetUpperPrime); if (plotLength > minPlotLength) { // Axis is fixed to plotLength. newScale = plotLength / deltaLower; margin = new Thickness1D(limitingLowerSemiWidth - offsetLower * newScale, limitingUpperSemiWidth - offsetUpperPrime * newScale); foreach (Axis2D axis in alignedAxes) { axis.AxisTotalLength = plotLength + margin.Total(); } } if (newScale * deltaLower <= minPlotLength) { // Axis is fixed to minPlotLength newScale = minPlotLength / deltaLower; margin = new Thickness1D(limitingLowerSemiWidth - offsetLower * newScale, limitingUpperSemiWidth - offsetUpperPrime * newScale); foreach (Axis2D axis in alignedAxes) { axis.AxisTotalLength = minPlotLength + margin.Total(); } } // otherwise, axis is unfixed. margin = new Thickness1D(limitingLowerSemiWidth - offsetLower * newScale, limitingUpperSemiWidth - offsetUpperPrime * newScale); foreach (Axis2D axis in alignedAxes) { axis.RescaleAxis(newScale * deltaLower / (axis.MaxTransformed - axis.MinTransformed), margin); } break; } if (reset == true) { break; } } if (reset == true) { tickIndex = 0; } else { tickIndex++; } } if (nRescales == 10) { Console.WriteLine("Many rescales..."); } }
/// <summary> /// Bind the Max and Min of this axis to another axis. /// </summary> /// <param name="bindingAxis"></param> public void BindToAxis(Axis2D bindingAxis) { var axisBinding = new Binding("Range") { Source = this, Mode = BindingMode.TwoWay }; bindingAxis.SetBinding(Axis2D.RangeProperty, axisBinding); }
public void AdjustRange(Axis2D axis) { Range axisRange = GetRangeFromChildren(axis); if (axisRange.Length != 0) axis.SetValue(Axis2D.RangeProperty, axisRange); }
internal override void BeforeArrange() { // Ensure that transform is updated with the latest axes values. imageRectangle.RenderTransform = Axis2D.GraphToCanvasLinear(xAxis, yAxis); }