Question

I am using OxyPlot in a C# winforms app. My axese are LinearAxis type.

I am trying to plot some real-time data which i have managed to do by adding points to my series and refreshing the plot as data becomes available. However, I am having trouble figuring out how to make the plot move to the right with the time series.

Each time series data point has an X value incremented by (int) 1 and I have tried to get the auto scrolling to happen using .Pan() like so:

xAxis.Pan(-1);

Obviously this hasn't worked since I am assuming the method takes pixel inputs or something and consequently the panning is much slower than the data incrementation.

I have also tried replacing -1 with -MajorTIckSize and -MajorStepSize with no luck as these are generally too small of a move.

My question is, how can i determine the delta i need to be using to pan with the real-data? I am assuming this will depend on the zoom level and obviously it would be nice if it would continue to work as I zoomed in and out.I imagine the solution involves some sort of function that relies on the pixel width of the tick interval or something but I can't figure it out.

PS: I've asked this question on OxyPlot discussion page as well

Thanks,

Armen

Was it helpful?

Solution

Thanks to decatf for posting an answer to my question here and said:

The Transform function in the Axis class will convert data coordinates to screen coordinates. There is an InverseTransform to do the opposite.

So you could try:

double panStep = xAxis.Transform(-1 + xAxis.Offset);
xAxis.Pan(panStep); 

There is some offset from the axis zero position (I think?) so we need to account for that in the transform to get a unit step.

OTHER TIPS

This is my solution, assuming you are using a DateTimeAxis for the X coordinates.

The code will pan you axis, in one direction depending on the time difference between your two values. It also considers the zoom factor, so you don't need to worry about this as well.

You should use the Axis Transform and Pan methods:

//Assuming you've got two data points, 1 minute apart
//and you want to pan only the time axis of your plot (in this example the x-Axis).
double firstValue = DateTime.Now.ToOADate();
double secondValue = DateTime.Now.AddMinutes(1).ToOADate();

//Transfrom the x-Values (DateTime-Value in OLE Automation format) to screen-coordinates
double transformedfirstValue = YourAxis.Transform(firstValue);
double transformedsecondValue = YourAxis.Transform(secondValue);

//the pan method will calculate the screen coordinate difference/distance and will pan you axsis based on this amount
//if you are planing on panning your y-Axis or both at the same time, you  will need to create different ScreenPoints accordingly
YourAxis.Pan(
  new ScreenPoint(transformedfirstValue,0),
  new ScreenPoint(transformedsecondValue,0)
);

//Afterwards you will need to refresh you plot

I searched for a while and found a few solutions that are outdated or just don't work as expected. After some experimenting, I determined that Axes.ActualMaximum is the current visible max value. Axes.DataMaximum is the maximum of data (as the name suggests). You want to take the difference of the two and multiply by the scale value Axes.Scale. You then call Axes.Pan with the calculated value. Like so:

public PlotModel GraphModel { get; private set; }

    public void AddPoints(double xPoint, double yPoint)
    {
        (this.GraphModel.Series[0] as LineSeries).Points.Add(new DataPoint(xPoint, yPoint));
        GraphModel.InvalidatePlot(true);

        //if autopan is on and actually neccessary
        if ((AutoPan) && (xPoint > GraphModel.Axes[0].Maximum))
        {
            //the pan is the actual max position of the observed Axis minus the maximum data position times the scaling factor
            var xPan = (GraphModel.Axes[0].ActualMaximum - GraphModel.Axes[0].DataMaximum) * GraphModel.Axes[0].Scale;
            GraphModel.Axes[0].Pan(xPan);
        }          
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top