在最近的c#wpf应用程序中,我使用了氧气图进行趋势分析。它是一个很好的工具,具有高性能的体积数据。我从LiveChart搬到了Oxyplot。如何根据轴范围实现截面背景? TargetEffect
我尝试过修改了ThreeColorLineSeries,现在我可以根据设置的上限和下限来渲染线条。但对于背景而言,它并不起作用。
using System.Collections.Generic;
/// <summary>
/// Represents a two-color line series.
/// </summary>
public class FourColorLineSeries : LineSeries
{
/// <summary>
/// The default low color.
/// </summary>
private OxyColor defaultColorLoPre;
/// <summary>
/// The default low color.
/// </summary>
private OxyColor defaultColorLo;
/// <summary>
/// The default hi color.
/// </summary>
private OxyColor defaultColorLoLo;
/// <summary>
/// The default low color.
/// </summary>
private OxyColor defaultColorHiPre;
/// <summary>
/// The default low color.
/// </summary>
private OxyColor defaultColorHi;
/// <summary>
/// The default hi color.
/// </summary>
private OxyColor defaultColorHiHi;
/// <summary>
/// Initializes a new instance of the <see cref = "FourColorLineSeries" /> class.
/// </summary>
public FourColorLineSeries()
{
this.LimitHiPre = 1.0;
this.ColorHiPre = OxyColors.Green;
this.LineStyleHiPre = LineStyle.Solid;
this.LimitHi = 2.0;
this.ColorHi = OxyColors.Yellow;
this.LineStyleHi = LineStyle.Solid;
this.LimitHiHi = 5.0;
this.ColorHiHi = OxyColors.Red;
this.LineStyleHiHi = LineStyle.Solid;
this.LimitLoPre = -1.0;
this.ColorLoPre = OxyColors.Green;
this.LineStyleLoPre = LineStyle.Solid;
this.LimitLo = -2.0;
this.ColorLo = OxyColors.Yellow;
this.LineStyleLo = LineStyle.Solid;
this.LimitLoLo = -5.0;
this.ColorLoLo = OxyColors.Red;
this.LineStyleLoLo = LineStyle.Solid;
}
/// <summary>
/// Gets or sets the color for the part of the line that is below the limit.
/// </summary>
public OxyColor ColorLoPre { get; set; }
/// <summary>
/// Gets or sets the color for the part of the line that is below the limit.
/// </summary>
public OxyColor ColorLo { get; set; }
/// <summary>
/// Gets or sets the color for the part of the line that is above the limit.
/// </summary>
public OxyColor ColorLoLo { get; set; }
/// <summary>
/// Gets or sets the color for the part of the line that is below the limit.
/// </summary>
public OxyColor ColorHiPre { get; set; }
/// <summary>
/// Gets or sets the color for the part of the line that is below the limit.
/// </summary>
public OxyColor ColorHi { get; set; }
/// <summary>
/// Gets or sets the color for the part of the line that is above the limit.
/// </summary>
public OxyColor ColorHiHi { get; set; }
/// <summary>
/// Gets the actual low pre color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorLoPre
{
get { return this.ColorLoPre.GetActualColor(this.defaultColorLoPre); }
}
/// <summary>
/// Gets the actual low color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorLo
{
get { return this.ColorLo.GetActualColor(this.defaultColorLo); }
}
/// <summary>
/// Gets the actual low low color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorLoLo
{
get { return this.ColorLoLo.GetActualColor(this.defaultColorLoLo); }
}
/// <summary>
/// Gets the actual hi pre color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorHiPre
{
get { return this.ColorHiPre.GetActualColor(this.defaultColorHiPre); }
}
/// <summary>
/// Gets the actual hi color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorHi
{
get { return this.ColorHi.GetActualColor(this.defaultColorHi); }
}
/// <summary>
/// Gets the actual low color.
/// </summary>
/// <value>The actual color.</value>
public OxyColor ActualColorHiHi
{
get { return this.ColorHiHi.GetActualColor(this.defaultColorHiHi); }
}
/// <summary>
/// Gets or sets the high limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorHi.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitLoPre { get; set; }
/// <summary>
/// Gets or sets the low limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorLo.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitLo { get; set; }
/// <summary>
/// Gets or sets the pre limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorPre.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitLoLo { get; set; }
/// <summary>
/// Gets or sets the high limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorHi.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitHiPre { get; set; }
/// <summary>
/// Gets or sets the low limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorLo.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitHi { get; set; }
/// <summary>
/// Gets or sets the pre limit.
/// </summary>
/// <remarks>The parts of the line that is below this limit will be rendered with ColorPre.
/// The parts of the line that is above the limit will be rendered with Color.</remarks>
public double LimitHiHi { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is above the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesHi { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesLo { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesLoPre { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is above the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesLoLo { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesHiPre { get; set; }
/// <summary>
/// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />).
/// </summary>
/// <value>The dash array.</value>
/// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks>
public double[] DashesHiHi { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleLoPre { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleLo { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleLoLo { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleHiPre { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleHi { get; set; }
/// <summary>
/// Gets or sets the line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle LineStyleHiHi { get; set; }
/// <summary>
/// Gets the actual line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleHi
{
get
{
return this.LineStyleHi != LineStyle.Automatic ? this.LineStyleHi : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleHiHi
{
get
{
return this.LineStyleHiHi != LineStyle.Automatic ? this.LineStyleHiHi : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleHiPre
{
get
{
return this.LineStyleHiPre != LineStyle.Automatic ? this.LineStyleHiPre : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual line style for the part of the line that is above the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleLoPre
{
get
{
return this.LineStyleLoPre != LineStyle.Automatic ? this.LineStyleLoPre : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleLo
{
get
{
return this.LineStyleLo != LineStyle.Automatic ? this.LineStyleLo : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual line style for the part of the line that is below the limit.
/// </summary>
/// <value>The line style.</value>
public LineStyle ActualLineStyleLoLo
{
get
{
return this.LineStyleLoLo != LineStyle.Automatic ? this.LineStyleLoLo : LineStyle.Solid;
}
}
/// <summary>
/// Gets the actual dash array for the line that is above the limit.
/// </summary>
protected double[] ActualDashArrayHi
{
get
{
return this.DashesHi ?? this.ActualLineStyleHi.GetDashArray();
}
}
/// <summary>
/// Gets the actual dash array for the line that is below the limit.
/// </summary>
protected double[] ActualDashArrayLo
{
get
{
return this.DashesLo ?? this.ActualLineStyleLo.GetDashArray();
}
}
/// <summary>
/// Gets the actual dash array for the line that is below the limit.
/// </summary>
protected double[] ActualDashArrayLoPre
{
get
{
return this.DashesLoPre ?? this.ActualLineStyleLoPre.GetDashArray();
}
}
/// <summary>
/// Gets the actual dash array for the line that is above the limit.
/// </summary>
protected double[] ActualDashArrayHiHi
{
get
{
return this.DashesHiHi ?? this.ActualLineStyleHiHi.GetDashArray();
}
}
/// <summary>
/// Gets the actual dash array for the line that is below the limit.
/// </summary>
protected double[] ActualDashArrayLoLo
{
get
{
return this.DashesLoLo ?? this.ActualLineStyleLoLo.GetDashArray();
}
}
/// <summary>
/// Gets the actual dash array for the line that is below the limit.
/// </summary>
protected double[] ActualDashArrayHiPre
{
get
{
return this.DashesHiPre ?? this.ActualLineStyleHiPre.GetDashArray();
}
}
/// <summary>
/// Sets the default values.
/// </summary>
protected internal override void SetDefaultValues()
{
base.SetDefaultValues();
if (this.ColorLoPre.IsAutomatic())
{
this.defaultColorLoPre = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleLoPre == LineStyle.Automatic)
{
this.LineStyleLoPre = this.PlotModel.GetDefaultLineStyle();
}
if (this.ColorHiPre.IsAutomatic())
{
this.defaultColorHiPre = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleHiPre == LineStyle.Automatic)
{
this.LineStyleHiPre = this.PlotModel.GetDefaultLineStyle();
}
if (this.ColorLo.IsAutomatic())
{
this.defaultColorLo = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleLo == LineStyle.Automatic)
{
this.LineStyleLo = this.PlotModel.GetDefaultLineStyle();
}
if (this.ColorLoLo.IsAutomatic())
{
this.defaultColorLoLo = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleLoLo == LineStyle.Automatic)
{
this.LineStyleLoLo = this.PlotModel.GetDefaultLineStyle();
}
if (this.ColorHi.IsAutomatic())
{
this.defaultColorHi = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleHi == LineStyle.Automatic)
{
this.LineStyleHi = this.PlotModel.GetDefaultLineStyle();
}
if (this.ColorHiHi.IsAutomatic())
{
this.defaultColorHiHi = this.PlotModel.GetDefaultColor();
}
if (this.LineStyleHiHi == LineStyle.Automatic)
{
this.LineStyleHiHi = this.PlotModel.GetDefaultLineStyle();
}
}
/// <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)
{
var bottom = clippingRect.Bottom;
var top = clippingRect.Top;
// todo: this does not work when y axis is reversed
var yLoPre = this.YAxis.Transform(this.LimitLoPre);
var yLo = this.YAxis.Transform(this.LimitLo);
var yLoLo = this.YAxis.Transform(this.LimitLoLo);
var yHiPre = this.YAxis.Transform(this.LimitHiPre);
var yHi = this.YAxis.Transform(this.LimitHi);
var yHiHi = this.YAxis.Transform(this.LimitHiHi);
if (yLoPre< clippingRect.Top)
{
yLoPre = clippingRect.Top;
}
if (yLoPre > clippingRect.Bottom)
{
yLoPre = clippingRect.Bottom;
}
if (yHiPre < clippingRect.Top)
{
yHiPre = clippingRect.Top;
}
if (yHiPre > clippingRect.Bottom)
{
yHiPre = clippingRect.Bottom;
}
if (yLo < clippingRect.Top)
{
yLo = clippingRect.Top;
}
if (yLo > clippingRect.Bottom)
{
yLo = clippingRect.Bottom;
}
if (yLoLo < clippingRect.Top)
{
yLoLo = clippingRect.Top;
}
if (yLoLo > clippingRect.Bottom)
{
yLoLo = clippingRect.Bottom;
}
if (yHi < clippingRect.Top)
{
yHi = clippingRect.Top;
}
if (yHi > clippingRect.Bottom)
{
yHi = clippingRect.Bottom;
}
if (yHiHi < clippingRect.Top)
{
yHiHi = clippingRect.Top;
}
if (yHiHi > clippingRect.Bottom)
{
yHiHi = clippingRect.Bottom;
}
clippingRect = new OxyRect(clippingRect.Left, top, clippingRect.Width, yHiHi - top);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorHiHi),
this.StrokeThickness,
this.ActualDashArrayHiHi,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yHiHi, clippingRect.Width, yHi - yHiHi);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorHi),
this.StrokeThickness,
this.ActualDashArrayHi,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yHi, clippingRect.Width, yHiPre - yHi);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorHiPre),
this.StrokeThickness,
this.ActualDashArrayHiPre,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yHiPre, clippingRect.Width, yLoPre - yHiPre);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColor),
this.StrokeThickness,
this.ActualDashArray,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yLoPre, clippingRect.Width, yLo - yLoPre);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorLoPre),
this.StrokeThickness,
this.ActualDashArrayLoPre,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yLo, clippingRect.Width, yLoLo - yLo);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorLo),
this.StrokeThickness,
this.ActualDashArrayLo,
this.LineJoin,
false);
clippingRect = new OxyRect(clippingRect.Left, yLoLo, clippingRect.Width, bottom - yLoLo);
rc.DrawClippedLine(
clippingRect,
pointsToRender,
this.MinimumSegmentLength * this.MinimumSegmentLength,
this.GetSelectableColor(this.ActualColorLoLo),
this.StrokeThickness,
this.ActualDashArrayLoLo,
this.LineJoin,
false);
}
}
}
答案 0 :(得分:1)
在阅读并在两天内使用oxyplot源代码进行挣扎之后,我最终修改了现有的oxyplot RangeColorAxis.cs并制作了一个wpf包装器。完成这些操作后,我可以使用2个重建的dll(OxyPlot.dll和Oxyplot.Wpf.dll)文件获取以下图像。
LineSeries with axis value based range colors
修改了RangeColorAxis.cs
namespace OxyPlot.Axes
{
using System;
using System.Collections.Generic;
/// <summary>
/// Represents a color axis that contains colors for specified ranges.
/// </summary>
public class RangeColorAxis : LinearAxis, IColorAxis
{
/// <summary>
/// The ranges
/// </summary>
private readonly List<ColorRange> ranges = new List<ColorRange>();
/// <summary>
/// Initializes a new instance of the <see cref="RangeColorAxis" /> class.
/// </summary>
public RangeColorAxis()
{
this.Position = AxisPosition.None;
this.AxisDistance = 20;
this.LowColor = OxyColors.Undefined;
this.HighColor = OxyColors.Undefined;
this.InvalidNumberColor = OxyColors.Gray;
this.IsPanEnabled = false;
this.IsZoomEnabled = false;
}
/// <summary>
/// Gets or sets the color used to represent NaN values.
/// </summary>
/// <value>A <see cref="OxyColor" /> that defines the color. The default value is <c>OxyColors.Gray</c>.</value>
public OxyColor InvalidNumberColor { get; set; }
/// <summary>
/// Gets or sets the color of values above the maximum value.
/// </summary>
/// <value>The color of the high values.</value>
public OxyColor HighColor { get; set; }
/// <summary>
/// Gets or sets the color of values below the minimum value.
/// </summary>
/// <value>The color of the low values.</value>
public OxyColor LowColor { get; set; }
/// <summary>
/// Adds a range.
/// </summary>
/// <param name="lowerBound">The lower bound.</param>
/// <param name="upperBound">The upper bound.</param>
/// <param name="color">The color.</param>
public void AddRange(double lowerBound, double upperBound, OxyColor color)
{
this.ranges.Add(new ColorRange { LowerBound = lowerBound, UpperBound = upperBound, Color = color });
}
/// <summary>
/// Clears the ranges.
/// </summary>
public void ClearRanges()
{
this.ranges.Clear();
}
/// <summary>
/// Gets the palette index of the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The palette index.</returns>
/// <remarks>If the value is less than minimum, 0 is returned. If the value is greater than maximum, Palette.Colors.Count+1 is returned.</remarks>
public int GetPaletteIndex(double value)
{
if (!this.LowColor.IsUndefined() && value < this.ranges[0].LowerBound)
{
return -1;
}
if (!this.HighColor.IsUndefined() && value > this.ranges[this.ranges.Count - 1].UpperBound)
{
return this.ranges.Count;
}
// TODO: change to binary search?
for (int i = 0; i < this.ranges.Count; i++)
{
var range = this.ranges[i];
if (range.LowerBound <= value && range.UpperBound > value)
{
return i;
}
}
return int.MinValue;
}
/// <summary>
/// Gets the color.
/// </summary>
/// <param name="paletteIndex">The color map index.</param>
/// <returns>The color.</returns>
public OxyColor GetColor(int paletteIndex)
{
if (paletteIndex == int.MinValue)
{
return this.InvalidNumberColor;
}
if (paletteIndex == -1)
{
return this.LowColor;
}
if (paletteIndex == this.ranges.Count)
{
return this.HighColor;
}
return this.ranges[paletteIndex].Color;
}
/// <summary>
/// Renders the axis on the specified render context.
/// </summary>
/// <param name="rc">The render context.</param>
/// <param name="pass">The render pass.</param>
public override void Render(IRenderContext rc, int pass)
{
if (this.Position == AxisPosition.None)
{
return;
}
if (pass == 0)
{
double distance = this.AxisDistance;
double left = this.PlotModel.PlotArea.Left;
double top = this.PlotModel.PlotArea.Top;
double width = this.MajorTickSize - 2;
double height = this.MajorTickSize - 2;
double plotwidth = this.PlotModel.PlotArea.Width;
double plotheight = this.PlotModel.PlotArea.Height;
const int TierShift = 0;
switch (this.Position)
{
case AxisPosition.Left:
left = this.PlotModel.PlotArea.Left - TierShift - width - distance;
top = this.PlotModel.PlotArea.Top;
break;
case AxisPosition.Right:
left = this.PlotModel.PlotArea.Right + TierShift + distance;
top = this.PlotModel.PlotArea.Top;
break;
case AxisPosition.Top:
left = this.PlotModel.PlotArea.Left;
top = this.PlotModel.PlotArea.Top - TierShift - height - distance;
break;
case AxisPosition.Bottom:
left = this.PlotModel.PlotArea.Left;
top = this.PlotModel.PlotArea.Bottom + TierShift + distance;
break;
}
Action<double, double, OxyColor> drawColorRect = (ylow, yhigh, color) =>
{
double ymin = Math.Min(ylow, yhigh);
double ymax = Math.Max(ylow, yhigh);
rc.DrawRectangle(
this.IsHorizontal()
? new OxyRect(ymin, top, ymax - ymin, plotheight)
: new OxyRect(left, ymin, plotwidth, ymax - ymin),
color,
OxyColors.Undefined);
};
// if the axis is reversed then the min and max values need to be swapped.
double effectiveMaxY = this.Transform(this.IsReversed ? this.ActualMinimum : this.ActualMaximum);
double effectiveMinY = this.Transform(this.IsReversed ? this.ActualMaximum : this.ActualMinimum);
foreach (ColorRange range in this.ranges)
{
double ylow = this.Transform(range.LowerBound);
double yhigh = this.Transform(range.UpperBound);
if (this.IsHorizontal())
{
if (ylow < effectiveMinY)
{
ylow = effectiveMinY;
}
if (yhigh > effectiveMaxY)
{
yhigh = effectiveMaxY;
}
}
else
{
if (ylow > effectiveMinY)
{
ylow = effectiveMinY;
}
if (yhigh < effectiveMaxY)
{
yhigh = effectiveMaxY;
}
}
drawColorRect(ylow, yhigh, range.Color);
}
double highLowLength = 10;
if (this.IsHorizontal())
{
highLowLength *= -1;
}
if (!this.LowColor.IsUndefined())
{
double ylow = this.Transform(this.ActualMinimum);
drawColorRect(ylow, ylow + highLowLength, this.LowColor);
}
if (!this.HighColor.IsUndefined())
{
double yhigh = this.Transform(this.ActualMaximum);
drawColorRect(yhigh, yhigh - highLowLength, this.HighColor);
}
}
var r = new HorizontalAndVerticalAxisRenderer(rc, this.PlotModel);
r.Render(this, pass);
}
/// <summary>
/// Defines a range.
/// </summary>
private class ColorRange
{
/// <summary>
/// Gets or sets the color.
/// </summary>
/// <value>The color.</value>
public OxyColor Color { get; set; }
/// <summary>
/// Gets or sets the lower bound.
/// </summary>
/// <value>The lower bound.</value>
public double LowerBound { get; set; }
/// <summary>
/// Gets or sets the upper bound.
/// </summary>
/// <value>The upper bound.</value>
public double UpperBound { get; set; }
}
}
}
RangeColorAxis.cs的WPF包装
namespace OxyPlot.Wpf
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media;
/// <summary>
/// This is a WPF wrapper for the <see cref="OxyPlot.Axes.RangeColorAxis"/>
/// </summary>
public class RangeColorAxis : Axis
{
/// <summary>
/// Identifies the <see cref="InvalidNumberColor"/> dependency property.
/// </summary>
public static readonly DependencyProperty InvalidNumberColorProperty =
DependencyProperty.Register(
"InvalidNumberColor",
typeof(Color),
typeof(RangeColorAxis),
new PropertyMetadata(Colors.Orange, AppearanceChanged));
/// <summary>
/// Identifies the <see cref="HighColor"/> dependency property.
/// </summary>
public static readonly DependencyProperty HighColorProperty = DependencyProperty.Register(
"HighColor", typeof(Color), typeof(RangeColorAxis), new PropertyMetadata(Colors.White, AppearanceChanged));
/// <summary>
/// Identifies the <see cref="LowColor"/> dependency property.
/// </summary>
public static readonly DependencyProperty LowColorProperty = DependencyProperty.Register(
"LowColor", typeof(Color), typeof(RangeColorAxis), new PropertyMetadata(Colors.Black, AppearanceChanged));
/// <summary>
/// Identifies the <see cref="Ranges"/> dependency property.
/// </summary>
public static readonly DependencyProperty RangesProperty = DependencyProperty.Register(
"Ranges", typeof(IList<Tuple<double, double, Color>>), typeof(RangeColorAxis), new PropertyMetadata(new List<Tuple<double,double,Color>>(), DataChanged));
/// <summary>
/// Initializes a new instance of the <see cref="RangeColorAxis"/> class.
/// </summary>
public RangeColorAxis()
{
this.InternalAxis = new Axes.RangeColorAxis();
}
/// <summary>
/// Initializes a new instance of the <see cref="InvalidNumberColor"/> class.
/// </summary>
public Color InvalidNumberColor
{
get
{
return (Color)this.GetValue(InvalidNumberColorProperty);
}
set
{
this.SetValue(InvalidNumberColorProperty, value);
}
}
/// <summary>
/// Gets or sets the high color.
/// </summary>
public Color HighColor
{
get
{
return (Color)this.GetValue(HighColorProperty);
}
set
{
this.SetValue(HighColorProperty, value);
}
}
/// <summary>
/// Gets or sets the low color.
/// </summary>
public Color LowColor
{
get
{
return (Color)this.GetValue(LowColorProperty);
}
set
{
this.SetValue(LowColorProperty, value);
}
}
/// <summary>
/// Gets or sets Labels.
/// </summary>
public IList<Tuple<double, double, Color>> Ranges
{
get
{
return (IList<Tuple<double, double, Color>>)this.GetValue(RangesProperty);
}
set
{
this.SetValue(RangesProperty, value);
}
}
/// <summary>
/// Creates the model.
/// </summary>
/// <returns>
/// An axis object.
/// </returns>
public override Axes.Axis CreateModel()
{
this.SynchronizeProperties();
return this.InternalAxis;
}
/// <summary>
/// Synchronizes the properties.
/// </summary>
protected override void SynchronizeProperties()
{
base.SynchronizeProperties();
var axis = this.InternalAxis as Axes.RangeColorAxis;
Trace.Assert(axis != null);
//if (this.GradientStops != null)
//{
// axis.Palette = this.GradientStops.Count > 2
// ? Interpolate(this.GradientStops.ToList(), this.PaletteSize)
// : new OxyPalette();
//}
axis.HighColor = this.HighColor.ToOxyColor();
axis.LowColor = this.LowColor.ToOxyColor();
axis.InvalidNumberColor = this.InvalidNumberColor.ToOxyColor();
axis.Minimum = this.Minimum;
axis.Maximum = this.Maximum;
if (Ranges != null)
{
axis.ClearRanges();
foreach (var range in Ranges)
{
axis.AddRange(range.Item1, range.Item2, range.Item3.ToOxyColor());
}
}
}
}
}
XAML文件:
<oxyPlot:Plot.Axes>
<oxyPlot:DateTimeAxis StringFormat="HH:mm:ss"></oxyPlot:DateTimeAxis>
<oxyPlot:RangeColorAxis
Ranges="{Binding ColorRanges}"
Unit="{Binding Unit}"
AbsoluteMinimum="{Binding DisplayMin}"
AbsoluteMaximum="{Binding DisplayMax}"
MinimumRange="{Binding DisplayMax}"/>
</oxyPlot:Plot.Axes>
查看模型
...
/// <summary>
/// The <see cref="ColorRanges" /> property's name.
/// </summary>
public const string ColorRangesPropertyName = "ColorRanges";
private List<Tuple<double, double, System.Windows.Media.Color>> _colorRanges = new List<Tuple<double, double, System.Windows.Media.Color>>();
/// <summary>
/// Sets and gets the ColorRanges property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public List<Tuple<double, double, System.Windows.Media.Color>> ColorRanges
{
get
{
return _colorRanges;
}
set
{
if (_colorRanges == value)
{
return;
}
_colorRanges = value;
RaisePropertyChanged(ColorRangesPropertyName);
}
}
...
//usage
ColorRanges.Clear();
if (DisplayMin < LevelThresholdLoLo)
{
ColorRanges.Add(new Tuple<double, double, Color>(DisplayMin, LevelThresholdLoLo, Color.FromArgb(127,255,68,0)));
}
if (LevelThresholdLoLo < LevelThresholdLo)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLoLo, LevelThresholdLo, Color.FromArgb(127, 255, 140, 0)));
}
if (LevelThresholdLo < LevelThresholdLoPre)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLo, LevelThresholdLoPre, Color.FromArgb(127, 65,105,225)));
}
if (LevelThresholdLoPre < LevelThresholdHiPre)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLoPre, LevelThresholdHiPre, Color.FromArgb(127, 50, 205, 50)));
}
if (LevelThresholdHiPre < LevelThresholdHi)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHiPre, LevelThresholdHi, Color.FromArgb(127, 65, 105, 225)));
}
if (LevelThresholdHi < LevelThresholdHiHi)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHi, LevelThresholdHiHi, Color.FromArgb(127,255,140,0)));
}
if (LevelThresholdHiHi < DisplayMax)
{
ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHiHi, DisplayMax, Color.FromArgb(127, 255, 68, 0)));
}