Search code examples
c#oxyplot

Oxyplot to interrupt DateTimeAxis serie


How can I interrupt serie at certain point, then continue from later point? For example I have date time axis as Y, then the data exist until certain date, then there is no data and later again I have data. What I want is NOT interpolate last data point where data has been interrupted with continuation, but I want to stop the plot and continue once data still there.

enter image description here

In the screenshot above the linear slope is due to missing data. What I want is to avoid that line. Still I want all that interrupted data to be within the same serie.

Update:

foreach (var dp in readings)
{
    data.Add(new DateValue {
        Date = dp.Date,
        Temperature = dp.Data.Where(y => y.Cell == c.Number).
                              Select(x => Convert.ToDouble(x.GetType().GetProperty(sensor.PropertyName).GetValue(x, null))).
                              FirstOrDefault() });

    if (lastDate != null && (dp.Date - lastDate).TotalMinutes > 10)
    {
        data.Add(new DateValue
        {
            Date = dp.Date,
            Temperature = double.NaN
        });
        Console.WriteLine("break");
    }

    lastDate = dp.Date;
}
mode1Data.Add(c.Number, data);

Solution

  • Adding a DataPoint.Undefined, creates a break in the line. You could also style the "broken line" (code example taken from oxyplot LineSeriesExample.cs):

    Without data binding:

     var model = new PlotModel("Broken line");
    
     var s1 = new LineSeries
         {
             // If you want to style
             //BrokenLineColor = OxyColors.Gray,
             //BrokenLineThickness = 1,
             //BrokenLineStyle = LineStyle.Dash
             BrokenLineStyle = LineStyle.None
         };
    
     s1.Points.Add(new DataPoint(0, 26));
     s1.Points.Add(new DataPoint(10, 30));
     s1.Points.Add(DataPoint.Undefined);
     s1.Points.Add(new DataPoint(10, 25));
     s1.Points.Add(new DataPoint(20, 26));
     s1.Points.Add(new DataPoint(25, 36));
     s1.Points.Add(new DataPoint(30, 40));
     s1.Points.Add(DataPoint.Undefined);
     s1.Points.Add(new DataPoint(30, 20));
     s1.Points.Add(new DataPoint(40, 10));
     model.Series.Add(s1);
    

    enter image description here

    With data binding:

    xaml:

    <oxy:Plot x:Name="plot1" Title="Binding ItemsSource" Subtitle="{Binding Subtitle}">
      <oxy:Plot.Series>
        <oxy:LineSeries Title="Maximum" DataFieldX="Time" DataFieldY="Maximum" Color="Red" LineStyle="Solid" StrokeThickness="2" ItemsSource="{Binding Measurements}"/>
      </oxy:Plot.Series>
    </oxy:Plot>
    

    Model:

    Measurements = new Collection<Measurement>();
    int N = 500;
    Subtitle = "N = " + N;
    
    var r = new Random(385);
    double dy = 0;
    double y = 0;
    for (int i = 0; i < N; i++)
    {
        dy += r.NextDouble() * 2 - 1;
        y += dy;
    
        // Create a line break
        if (i % 10 == 0)
        {
            Measurements.Add(new Measurement
            {
                Time = double.NaN, // For DateTime put DateTime.MinValue
                Value = double.NaN
            });   
        }
        else
        {
            Measurements.Add(new Measurement
            {
                Time = 2.5 * i / (N - 1),
                Value = y / (N - 1),
            });   
        }
    }
    

    Result: enter image description here