简体   繁体   中英

OxyPlot AutoScale

AutoScale OxyPlot Chart. For example i have something like this.

using OxyPlot;
using OxyPlot.Axes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OxyPlot.Wpf;
using PlotControllerTest.Properties;
using System.Diagnostics;
namespace PlotControllerTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
/// 
public class Chart
{
    public PlotController myController { get; set; }
    private OxyPlot.Series.LineSeries LS;
    OxyPlot.Axes.LinearAxis LAY;
    OxyPlot.Axes.LinearAxis LAX;
    private int i = 0;
    public PlotModel PlotModel {get;set;}
    public Chart()
    {

        PlotModel = new PlotModel();
        myController = new PlotController();
        myController.UnbindAll();
        myController.BindMouseDown(OxyMouseButton.Left, OxyPlot.PlotCommands.PanAt);
        LS = new OxyPlot.Series.LineSeries();
        LAY = new OxyPlot.Axes.LinearAxis()
        {
            Position = OxyPlot.Axes.AxisPosition.Left,
            AbsoluteMaximum = 100,
            AbsoluteMinimum = 1,
        };
        LAX = new OxyPlot.Axes.LinearAxis()
        {
            Position = OxyPlot.Axes.AxisPosition.Bottom,
            AbsoluteMaximum = 200,
            AbsoluteMinimum = 1,
            MinorStep=5,
        };
        PlotModel.Series.Add(LS);
        PlotModel.Axes.Add(LAY);
        PlotModel.Axes.Add(LAX);
    }
    public void BeginAddPoints()
    {
        Random rnd = new Random();
        do
        {
            int temp=rnd.Next(1, 100);
            LS.Points.Add(new DataPoint( ++i,temp));
            System.Threading.Thread.Sleep(100);

            Update();
        } while (i<30);
        Update();
    }
    public void Update()
    {
        PlotModel.InvalidatePlot(true);
    }
}
public partial class MainWindow : Window
{
    Chart TChart;
    delegate void BeginUpdate();
    private Stopwatch stopwatch = new Stopwatch();
    private long lastUpdateMilliSeconds;
    public MainWindow()
    {

        TChart = new Chart();
        BeginUpdate BU = new BeginUpdate(TChart.BeginAddPoints);
        IAsyncResult result = BU.BeginInvoke(null,null);
        DataContext = TChart;
        CompositionTarget.Rendering += CompositionTargetRendering;
        InitializeComponent();
    }
    private void CompositionTargetRendering(object sender, EventArgs e)
    {
        if (stopwatch.ElapsedMilliseconds > lastUpdateMilliSeconds + 300)
        {
            TChart.Update();
        }
    }
}

}

Xaml code look's like

<Window x:Class="PlotControllerTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:oxy="http://oxyplot.org/wpf"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <oxy:PlotView Model="{Binding PlotModel}" DefaultTrackerTemplate="{x:Null}" Controller="{Binding myController}"></oxy:PlotView>
</Grid>

How to implement autoscale of Y Axes after dragging? For example when i drag chart in window, and there appears only one Line ((1,2),(4,4)). Y axis will show from 2 to 4.Thanks.

If you would like to reset just the Y Axis, you would need to set a Key to your Y-Axis first.

 LAX = new OxyPlot.Axes.LinearAxis()
    {
        Key = "YAxis",
        Position = OxyPlot.Axes.AxisPosition.Bottom,
        AbsoluteMaximum = 200,
        AbsoluteMinimum = 1,
        MinorStep=5,
    };

Then you could get a reference to it by using LINQ. Call the following after your dragging event.

 Axis yAxis = PlotModel.Axes.FirstOrDefault(s => s.Key == "YAxis");
 yAxis.Reset();

If you would like to reset both the X and Y Axis then, you could just call

PlotModel.ResetAllAxes();

First thing, you will not have anything to rescale with the controller you are using as it blocks any panning/zooming abilities. By default panning is on the right click and zooming on mouse wheel. Also you plotmodel at creation will automatically plot all your points, so there is nothing to rescale. But let's assume you have a way to pan and zoom, what you can do to auto recalculate the maximum values you should have on your y axis is as following :

Let's first create a AdustYExtent method :

private void AdjustYExtent(OxyPlot.Series.LineSeries lserie, OxyPlot.Axes.LinearAxis xaxis, OxyPlot.Axes.LinearAxis yaxis)
    {
        if (xaxis != null && yaxis != null && lserie.Points.Count() != 0)
        {
            double istart = xaxis.ActualMinimum;
            double iend = xaxis.ActualMaximum;

            var ptlist = lserie.Points.FindAll(p => p.X >= istart && p.X <= iend);

            double ymin = double.MaxValue; 
            double ymax = double.MinValue;
            for (int i = 0; i <= ptlist.Count()-1; i++)
            {
                ymin = Math.Min(ymin, ptlist[i].Y);
                ymax = Math.Max(ymax, ptlist[i].Y);
            }

            var extent = ymax - ymin;
            var margin = extent * 0; //change the 0 by a value to add some extra up and down margin

            yaxis.Zoom(ymin - margin, ymax + margin);
        }
    }

What it does is first to find all your points that fit in the XAxis range currently seen and store them in the ptlist value. Then it iterates this list and find the corresponding max and min y. Then you just have to apply those maximum and minimum to your y axis. Note the margin value that I use to allow to put extra space on top and bottom.

Now you have to bind this method to the AxisChanged event of the x axis. In Chart() before adding your axes to the plot, add

LAX.AxisChanged += (sender, e) => AdjustYExtent(LS, LAX, LAY); ;

It should now auto scale your y axis depending on your x axis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM