Modifications to two color series

Oystein Bjorke 10 aastat tagasi uuendaja ChevyCP 9 aastat tagasi 3
This discussion was imported from CodePlex

ChevyCP wrote at 2012-03-19 21:36:

Hi,

   The two color series is great, but I was wondering if it could be used exactly the same, but have the limit on the X axis instead of the Y axis (so it would be a vertical split instead of just horizontal split).

 

Also, it would be cool if it could have two limits.  So that below a min limit and above a max limit would be color2, but between the limits would be color1. 

 

Thanks!


objo wrote at 2012-03-20 18:22:

See the implementation of the TwoColorLineSeries, it is easy to create similar custom series that support vertical or multiple limits. The TwoColorLineSeries could also be extended to support all these cases!


ChevyCP wrote at 2012-03-20 21:02:

Cool, I'm working on it now and think I've got it.... except that I'm having a problem with using the axis.transform function on the datetime axis.  Even though I converted my "limit"  to a double using DateTimeAxis.ToDouble from a datetime, I'm having problems getting the screen coordinates for the position I want.  Any thoughts?


ChevyCP wrote at 2012-03-22 15:27:

I was able to find a way to get this to work on a datetime axis.  I created a vertical annotation and bound the limit of the custom two color series to the X property of the annotation.  That worked fine.  If you want to add a 2 color vertical line series that uses a max and min limit, this is the code I used.  Feel free to clean it up and add it to oxyplot if you think it would help. I only tested this for wpf, but it worked perfectly.  First I created copies TwoColorLineSeries.cs in oxyplot/series and TwoColorLineSeries in oxyplot.wpf/series in their respective folders and called them both TwoColorVerticalLineSeries.  After updating the files to allow for a MinLimit and MaxLimit and changing the names when needed, the only important code that was any different came from the .cs in the main oxyplot TwoColorVerticalLineSeries with the RenderSmoothefLine function.  This is the code I used in place of what was in there.  I don't think it will work for a reversed X axis, and might need an error check on the max/min limit, but here it is:

 

protected override void RenderSmoothedLine(IRenderContext rc, OxyRect clippingRect, IList<ScreenPoint> pointsToRender)
{
     double right = clippingRect.Right;
     double minX = this.XAxis.Transform(this.MinLimit);
     double maxX = this.XAxis.Transform(this.MaxLimit);
         
     if (minX < clippingRect.Left) minX = clippingRect.Left;
     if (minX > right) minX = right;
     if (maxX < clippingRect.Left) maxX = clippingRect.Left;
     if (maxX > right) maxX = right;
     if (maxX < minX) maxX = minX;
                     
     clippingRect.Right = minX;
     rc.DrawClippedLine(
          pointsToRender, 
          clippingRect, 
          this.MinimumSegmentLength * this.MinimumSegmentLength, 
          this.Color2, 
          this.StrokeThickness, 
          this.LineStyle2, 
          this.LineJoin, 
          false);
         
     clippingRect.Left = minX;
     clippingRect.Width = maxX - minX;
     rc.DrawClippedLine(
          pointsToRender, 
          clippingRect, 
          this.MinimumSegmentLength * this.MinimumSegmentLength, 
          this.Color, 
          this.StrokeThickness, 
          this.LineStyle, 
          this.LineJoin, 
          false);

     clippingRect.Left = maxX;
     clippingRect.Width = right - maxX;
     rc.DrawClippedLine(
          pointsToRender,
          clippingRect,
          this.MinimumSegmentLength * this.MinimumSegmentLength,
          this.Color2,
          this.StrokeThickness,
          this.LineStyle2,
          this.LineJoin,
          false);
}

 


objo wrote at 2012-03-30 13:38:

thanks, I will try to create a "LimitedLineSeries" later :) see http://oxyplot.codeplex.com/workitem/9951

Hi,
   This worked for the version that was out when I posted this 3 years ago.  Going back to it, I haven't been able to successfully make this work.  I put in a customTwoColorLineSeries class in both the main series section and in the wpf series so I could use it in xaml.  It compiled fine but is not displaying data despite the code not really changing.  Any suggestions as to why this new class would fail.   It is just a line series where below a certain limit, the line is green.  Then it is a user defined color and a max limit is set when above that the line is red.  I'm really stuck on this and it is critical for software we use on a research vessel.  Thanks for all your hard work!

Here is the code from the main series class (sorry the formatting is off, I'm not sure how to post code here):
namespace OxyPlot.Series
{
using System.Collections.Generic;

/// <summary>
/// Represents a two-color line series.
/// </summary>
public class CustomTwoColorLineSeries : LineSeries
{
/// <summary>
/// Initializes a new instance of the <see cref = "CustomTwoColorLineSeries" /> class.
/// </summary>
public CustomTwoColorLineSeries()
{
this.MinLimit = 0.0;
this.MaxLimit = 0.0;
}

/// <summary>
/// Gets or sets the min limit.
/// </summary>
/// <remarks>
/// The parts of the line that is below this limit will be rendered with green.
/// </remarks>
public double MinLimit { get; set; }

/// <summary>
/// Gets or sets the max limit.
/// </summary>
/// <remarks>
/// The parts of the line that is above the limit will be rendered with red.
/// </remarks>
public double MaxLimit { get; set; }

/// <summary>
/// Sets the default values.
/// </summary>
/// <param name="model">The model.</param>
protected internal override void SetDefaultValues(PlotModel model)
{
base.SetDefaultValues(model);
}

/// <summary>
/// Renders the smoothed line.
/// </summary>
/// <param name="rc">The render context.</param>
/// <param name="clippingRect">The clipping rectangle.</param>
/// <param name="pointsToRender">The points.</param>
protected override void RenderLine(IRenderContext rc, OxyRect clippingRect, IList<ScreenPoint> pointsToRender)
{
double right = clippingRect.Right;
double left = clippingRect.Left;
double minX = this.XAxis.Transform(this.MinLimit);
double maxX = this.XAxis.Transform(this.MaxLimit);

if (minX < left)
{
minX = left;
}

if (minX > right)
{
minX = right;
}

if (maxX < left)
{
maxX = left;
}

if (maxX > right)
{
maxX = right;
}

if (maxX < minX)
{
maxX = minX;
}

clippingRect.Right = minX;

rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
OxyColors.Green,
this.StrokeThickness,
this.Dashes,
this.LineJoin,
false);

clippingRect.Left = minX;
clippingRect.Width = maxX - minX;
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.Color,
this.StrokeThickness,
this.Dashes,
this.LineJoin,
false);

clippingRect.Left = maxX;
clippingRect.Width = right - maxX;
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
OxyColors.Red,
this.StrokeThickness,
this.Dashes,
this.LineJoin,
false);
}
}
}


And the code from the wpf wrapper:
namespace OxyPlot.Wpf
{
using System.Windows;
using System.Windows.Media;

/// <summary>
/// The WPF wrapper for OxyPlot.CustomTwoColorLineSeries.
/// </summary>
public class CustomTwoColorLineSeries : LineSeries
{
/// <summary>
/// The min limit property.
/// </summary>
public static readonly DependencyProperty MinLimitProperty = DependencyProperty.Register(
"MinLimit", typeof(double), typeof(CustomTwoColorLineSeries), new UIPropertyMetadata(0.0, AppearanceChanged));

/// <summary>
/// The max limit property.
/// </summary>
public static readonly DependencyProperty MaxLimitProperty = DependencyProperty.Register(
"MaxLimit", typeof(double), typeof(CustomTwoColorLineSeries), new UIPropertyMetadata(0.0, AppearanceChanged));

/// <summary>
/// Initializes a new instance of the <see cref = "CustomTwoColorLineSeries" /> class.
/// </summary>
public CustomTwoColorLineSeries()
{
this.InternalSeries = new OxyPlot.Series.CustomTwoColorLineSeries();
}

/// <summary>
/// Gets or sets Min Limit.
/// </summary>
public double MinLimit
{
get
{
return (double)this.GetValue(MinLimitProperty);
}
set
{
this.SetValue(MinLimitProperty, value);
}
}

/// <summary>
/// Gets or sets Max Limit.
/// </summary>
public double MaxLimit
{
get
{
return (double)this.GetValue(MaxLimitProperty);
}
set
{
this.SetValue(MaxLimitProperty, value);
}
}

/// <summary>
/// Synchronizes the properties.
/// </summary>
/// <param name="series">The series.</param>
protected override void SynchronizeProperties(OxyPlot.Series.Series series)
{
base.SynchronizeProperties(series);
var s = series as OxyPlot.Series.CustomTwoColorLineSeries;
s.MinLimit = this.MinLimit;
s.MaxLimit = this.MaxLimit;
}
}
}
Also, does it matter if I use .net 4, 4.5, or 4.5.1 for this?  I know if I use 4.0 I would have to compile using the wpf 4.0 project, but is there any functional differences between 4 and 4.5 in oxyplot?
Sorry, it does work just fine.  I just needed to set a trigger to update the chart when a new data source was selected.  I didn't need to do this before, but the code works great.  Thanks for making a great product!