// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) 2014 OxyPlot contributors // // // Represents an error series. // // -------------------------------------------------------------------------------------------------------------------- namespace ExampleLibrary { using System; using System.Collections.Generic; using OxyPlot; using OxyPlot.Series; /// /// Represents an error series. /// public class ErrorSeries : XYAxisSeries { /// /// The list of error items. /// private readonly List points = new List(); /// /// Initializes a new instance of the class. /// public ErrorSeries() { this.Color = OxyColors.Black; this.StrokeThickness = 1; } /// /// Gets or sets the color. /// /// The color. public OxyColor Color { get; set; } /// /// Gets the list of points. /// /// A list of . public List Points { get { return this.points; } } /// /// Gets or sets the stroke thickness. /// /// The stroke thickness. public double StrokeThickness { get; set; } /// /// Renders the series on the specified render context. /// /// The rendering context. public override void Render(IRenderContext rc) { var points = this.Points; if (points.Count == 0) { return; } this.VerifyAxes(); int n = points.Count; // Transform all points to screen coordinates var segments = new List(n * 6); for (int i = 0; i < n; i++) { var sp = XAxis.Transform(points[i].X, points[i].Y, YAxis); var ei = points[i]; double errorx = ei != null ? ei.XError * XAxis.Scale : 0; double errory = ei != null ? ei.YError * Math.Abs(YAxis.Scale) : 0; double d = 4; if (errorx > 0) { var p0 = new ScreenPoint(sp.X - (errorx * 0.5), sp.Y); var p1 = new ScreenPoint(sp.X + (errorx * 0.5), sp.Y); segments.Add(p0); segments.Add(p1); segments.Add(new ScreenPoint(p0.X, p0.Y - d)); segments.Add(new ScreenPoint(p0.X, p0.Y + d)); segments.Add(new ScreenPoint(p1.X, p1.Y - d)); segments.Add(new ScreenPoint(p1.X, p1.Y + d)); } if (errory > 0) { var p0 = new ScreenPoint(sp.X, sp.Y - (errory * 0.5)); var p1 = new ScreenPoint(sp.X, sp.Y + (errory * 0.5)); segments.Add(p0); segments.Add(p1); segments.Add(new ScreenPoint(p0.X - d, p0.Y)); segments.Add(new ScreenPoint(p0.X + d, p0.Y)); segments.Add(new ScreenPoint(p1.X - d, p1.Y)); segments.Add(new ScreenPoint(p1.X + d, p1.Y)); } } // clip the line segments with the clipping rectangle for (int i = 0; i + 1 < segments.Count; i += 2) { rc.DrawReducedLine( new[] { segments[i], segments[i + 1] }, 0, this.GetSelectableColor(this.Color), this.StrokeThickness, this.EdgeRenderingMode, null, LineJoin.Bevel); } } /// /// Renders the legend symbol on the specified rendering context. /// /// The rendering context. /// The legend rectangle. public override void RenderLegend(IRenderContext rc, OxyRect legendBox) { double xmid = (legendBox.Left + legendBox.Right) * 0.5; double ymid = (legendBox.Top + legendBox.Bottom) * 0.5; var pts = new[] { new ScreenPoint(legendBox.Left, ymid), new ScreenPoint(legendBox.Right, ymid), new ScreenPoint(legendBox.Left, ymid - 2), new ScreenPoint(legendBox.Left, ymid + 3), new ScreenPoint(legendBox.Right, ymid - 2), new ScreenPoint(legendBox.Right, ymid + 3), new ScreenPoint(xmid, legendBox.Top), new ScreenPoint(xmid, legendBox.Bottom), new ScreenPoint(xmid - 2, legendBox.Top), new ScreenPoint(xmid + 3, legendBox.Top), new ScreenPoint(xmid - 2, legendBox.Bottom), new ScreenPoint(xmid + 3, legendBox.Bottom) }; rc.DrawLineSegments(pts, this.GetSelectableColor(this.Color), this.StrokeThickness, this.EdgeRenderingMode, null, LineJoin.Miter); } /// /// Updates the maximum and minimum values of the series. /// protected override void UpdateMaxMin() { base.UpdateMaxMin(); this.InternalUpdateMaxMin(this.points, p => p.X - p.XError, p => p.X + p.XError, p => p.Y - p.YError, p => p.Y + p.YError); } } }