// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) 2014 OxyPlot contributors // // // Provides utility functions for PlotModel used in examples. // // -------------------------------------------------------------------------------------------------------------------- namespace ExampleLibrary.Utilities { using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using OxyPlot; using OxyPlot.Axes; using OxyPlot.Series; /// /// Provides utility functions for PlotModel used in examples. /// public static class PlotModelUtilities { private const string XAXIS_KEY = "x"; private const string YAXIS_KEY = "y"; /// /// Lists all XYAxisSeries from the core library that are NOT reversible. /// private static readonly HashSet NonReversibleSeriesTypes = new HashSet { }; /// /// Lists all Annotations that need axes and are NOT reversible. /// private static readonly HashSet NonReversibleDataSpaceAnnotationTypes = new HashSet { typeof(TileMapAnnotation), }; /// /// Lists all XYAxisSeries from the core library that are NOT transposable. /// private static readonly HashSet NonTransposableSeriesTypes = new HashSet { typeof(CandleStickAndVolumeSeries), typeof(OldCandleStickSeries), }; /// /// Lists all Annotations that need axes and are NOT transposable. /// private static readonly HashSet NonTransposableDataSpaceAnnotationTypes = new HashSet { }; /// /// Returns a value indicating whether a plot model is reversible. /// /// The plot model. /// True if the plot model in reversible; false otherwise. public static bool IsReversible(this PlotModel model) { return (model.Axes.Count > 0 || model.Series.Count > 0) && model.Axes.All(a => a.Position != AxisPosition.None) && model.Series.All(s => { var type = s.GetType(); return s is XYAxisSeries && type.GetTypeInfo().Assembly == typeof(PlotModel).GetTypeInfo().Assembly && !NonReversibleSeriesTypes.Contains(type); }) && model.Annotations.All(a => { var type = a.GetType(); return !NonReversibleDataSpaceAnnotationTypes.Contains(type); }); } /// /// Returns a value indicating whether a plot model is transposable. /// /// The plot model. /// True if the plot model in transposable; false otherwise. public static bool IsTransposable(this PlotModel model) { return (model.Axes.Count > 0 || model.Series.Count > 0) && model.Axes.All(a => a.Position != AxisPosition.None) && model.Series.All(s => s is ITransposablePlotElement && !NonTransposableSeriesTypes.Contains(s.GetType())) && model.Annotations.All(a => a is ITransposablePlotElement && !NonTransposableDataSpaceAnnotationTypes.Contains(a.GetType())); } /// /// Reverses the X Axis of a PlotModel. The given PlotModel is mutated and returned for convenience. /// /// The PlotModel. /// The PlotModel with reversed X Axis. public static PlotModel ReverseXAxis(this PlotModel model) { if (!string.IsNullOrEmpty(model.Title)) { model.Title += " (reversed X Axis)"; } var foundXAxis = false; foreach (var axis in model.Axes) { switch (axis.Position) { case AxisPosition.Bottom: axis.StartPosition = 1 - axis.StartPosition; axis.EndPosition = 1 - axis.EndPosition; foundXAxis = true; break; case AxisPosition.Left: case AxisPosition.Right: case AxisPosition.Top: case AxisPosition.None: break; default: throw new ArgumentOutOfRangeException(); } } if (!foundXAxis) { model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, StartPosition = 1, EndPosition = 0}); } return model; } /// /// Reverses the Y Axis of a PlotModel. The given PlotModel is mutated and returned for convenience. /// /// The PlotModel. /// The PlotModel with reversed Y Axis. public static PlotModel ReverseYAxis(this PlotModel model) { if (!string.IsNullOrEmpty(model.Title)) { model.Title += " (reversed Y Axis)"; } var foundYAxis = false; foreach (var axis in model.Axes) { switch (axis.Position) { case AxisPosition.Left: axis.StartPosition = 1 - axis.StartPosition; axis.EndPosition = 1 - axis.EndPosition; foundYAxis = true; break; case AxisPosition.Bottom: case AxisPosition.Right: case AxisPosition.Top: case AxisPosition.None: break; default: throw new ArgumentOutOfRangeException(); } } if (!foundYAxis) { model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, StartPosition = 1, EndPosition = 0}); } return model; } /// /// Reverses X and Y Axes of a PlotModel. The given PlotModel is mutated and returned for convenience. /// /// The PlotModel. /// The PlotModel with reversed X and Y Axis. public static PlotModel ReverseXandYAxes(this PlotModel model) { var title = model.Title; if (!string.IsNullOrEmpty(title)) { title += " (reversed both Axes)"; } model = model.ReverseXAxis().ReverseYAxis(); model.Title = title; return model; } /// /// Reverses all axes of a PlotModel. The given PlotModel is mutated and returned for convenience. /// /// The PlotModel. /// The PlotModel with reversed axes. public static PlotModel ReverseAllAxes(this PlotModel model) { if (!string.IsNullOrEmpty(model.Title)) { model.Title += " (reversed all Axes)"; } // Update plot to generate default axes etc. ((IPlotModel)model).Update(false); foreach (var axis in model.Axes) { switch (axis.Position) { case AxisPosition.Left: case AxisPosition.Bottom: case AxisPosition.Right: case AxisPosition.Top: axis.StartPosition = 1 - axis.StartPosition; axis.EndPosition = 1 - axis.EndPosition; break; case AxisPosition.None: break; default: throw new ArgumentOutOfRangeException(); } } return model; } /// /// Transposes a PlotModel. The given PlotModel is mutated and returned for convenience. /// /// The PlotModel. /// The transposed PlotModel. public static PlotModel Transpose(this PlotModel model) { if (!string.IsNullOrEmpty(model.Title)) { model.Title += " (transposed)"; } // Update plot to generate default axes etc. ((IPlotModel)model).Update(false); foreach (var axis in model.Axes) { switch (axis.Position) { case AxisPosition.Bottom: axis.Position = AxisPosition.Left; break; case AxisPosition.Left: axis.Position = AxisPosition.Bottom; break; case AxisPosition.Right: axis.Position = AxisPosition.Top; break; case AxisPosition.Top: axis.Position = AxisPosition.Right; break; case AxisPosition.None: break; default: throw new ArgumentOutOfRangeException(); } } foreach (var annotation in model.Annotations) { if (annotation.XAxis != null && annotation.XAxisKey == null) { if (annotation.XAxis.Key == null) { annotation.XAxis.Key = XAXIS_KEY; } annotation.XAxisKey = annotation.XAxis.Key; } if (annotation.YAxis != null && annotation.YAxisKey == null) { if (annotation.YAxis.Key == null) { annotation.YAxis.Key = YAXIS_KEY; } annotation.YAxisKey = annotation.YAxis.Key; } } foreach (var series in model.Series.OfType()) { if (series.XAxisKey == null) { if (series.XAxis == null) // this can happen if the series is invisible initially { series.XAxisKey = XAXIS_KEY; } else { if (series.XAxis.Key == null) { series.XAxis.Key = XAXIS_KEY; } series.XAxisKey = series.XAxis.Key; } } if (series.YAxisKey == null) { if (series.YAxis == null) { series.YAxisKey = YAXIS_KEY; } else { if (series.YAxis.Key == null) { series.YAxis.Key = YAXIS_KEY; } series.YAxisKey = series.YAxis.Key; } } } return model; } } }