From b5ae2154604744662ecc16fb52591d7c608019c3 Mon Sep 17 00:00:00 2001 From: ztt Date: Thu, 13 Nov 2025 17:33:56 +0800 Subject: [PATCH 1/3] fix Add a symbol on the ErrorBarItem to indicate statistical significance --- .../Series/ErrorBarSeriesExamples.cs | 166 +++++++++++++++++- .../OxyPlot/Series/BarSeries/ErrorBarItem.cs | 41 +++++ .../Series/BarSeries/ErrorBarSeries.cs | 17 ++ 3 files changed, 223 insertions(+), 1 deletion(-) diff --git a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs index c1f11918c..17c75b2fc 100644 --- a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs +++ b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs @@ -8,8 +8,9 @@ namespace ExampleLibrary { using OxyPlot; using OxyPlot.Axes; - using OxyPlot.Series; using OxyPlot.Legends; + using OxyPlot.Series; + using System; [Examples("ErrorBarSeries"), Tags("Series")] public class ErrorBarSeriesExamples @@ -72,5 +73,168 @@ public static PlotModel GetErrorBarSeriesThickErrorLines() return model; } + + [Example("MarkerErrorBarSeries")] + [DocumentationExample("Series/MarkerErrorBarSeries")] + public static PlotModel GetMarkerErrorBarSeries() + { + var model = new PlotModel + { + Title = "MarkerErrorBarSeries" + }; + var l = new Legend + { + LegendPlacement = LegendPlacement.Outside, + LegendPosition = LegendPosition.BottomCenter, + LegendOrientation = LegendOrientation.Horizontal, + LegendBorderThickness = 0 + }; + + model.Legends.Add(l); + + var s1 = new ErrorBarSeries { Title = "Series 1", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; + s1.Items.Add(new ErrorBarItem + { + Value = 25, + Error = 2, + IsMarkerVisible = true, + MarkerColor = OxyColors.Red, + MarkerType = MarkerType.Star, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(5, 0), + MarkerStrokeColor = OxyColors.Blue, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem + { + Value = 137, + Error = 25, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Cross, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.Red, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem + { + Value = 18, + Error = 4, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Diamond, + MarkerSize = 8, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem { Value = 40, Error = 29, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Custom, + CustomOutline=GetSpiralStar(), + MarkerSize = 30, + MarkerOffset = new ScreenPoint(50, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + + var s2 = new ErrorBarSeries { Title = "Series 2", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; + s2.Items.Add(new ErrorBarItem + { + Value = 25, + Error = 2, + IsMarkerVisible = true, + MarkerColor = OxyColors.Red, + MarkerType = MarkerType.Square, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(5, 0), + MarkerStrokeColor = OxyColors.Blue, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 137, + Error = 25, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Triangle, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.Red, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 18, + Error = 4, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Plus, + MarkerSize = 8, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 40, + Error = 29, + IsMarkerVisible = true, + MarkerColor = OxyColors.GreenYellow, + MarkerType = MarkerType.Custom, + CustomOutline = GetHeartbeat(), + MarkerSize = 30, + MarkerOffset = new ScreenPoint(50, 0), + MarkerStrokeColor = OxyColors.BlueViolet, + MarkerStrokeThickness = 1, + }); + + var categoryAxis = new CategoryAxis { Position = AxisPosition.Left }; + categoryAxis.Labels.Add("Category A"); + categoryAxis.Labels.Add("Category B"); + categoryAxis.Labels.Add("Category C"); + categoryAxis.Labels.Add("Category D"); + + var valueAxis = new LinearAxis { Position = AxisPosition.Bottom, MinimumPadding = 0, MaximumPadding = 0.06, AbsoluteMinimum = 0 }; + model.Series.Add(s1); + model.Series.Add(s2); + model.Axes.Add(categoryAxis); + model.Axes.Add(valueAxis); + + return model; + } + public static ScreenPoint[] GetHeartbeat(int points = 20) + { + var outline = new ScreenPoint[points]; + for (int i = 0; i < points; i++) + { + double x = 2.0 * i / (points - 1) - 1; // -1 到 1 + double y = Math.Sin(x * Math.PI * 3) * Math.Exp(-Math.Abs(x)) * 0.8; + + // 添加一些随机脉冲效果 + y += Math.Sin(x * Math.PI * 8) * 0.1 * Math.Exp(-x * x * 4); + + outline[i] = new ScreenPoint(x, y); + } + return outline; + } + public static ScreenPoint[] GetSpiralStar(int points = 24, double tightness = 0.1) + { + var outline = new ScreenPoint[points]; + for (int i = 0; i < points; i++) + { + double progress = (double)i / points; + double radius = 0.2 + 0.8 * progress; // 半径逐渐增大 + double angle = 2 * Math.PI * (5 * progress + tightness * i); + + outline[i] = new ScreenPoint( + Math.Cos(angle) * radius, + Math.Sin(angle) * radius + ); + } + return outline; + } } } diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs index 04079c6f9..9b05c887a 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs @@ -41,6 +41,47 @@ public ErrorBarItem(double value, double error, int categoryIndex = -1) /// public double Error { get; set; } + /// + /// Gets or sets the color of marker + /// + public OxyColor MarkerColor { get; set; } + + + /// + /// Gets or sets the marker Type + /// + public MarkerType MarkerType { get; set; } + + /// + /// Gets or sets a custom polygon outline for the point marker. + /// + public ScreenPoint[] CustomOutline { get; set; } + + /// + /// Gets or sets the marker size + /// + public int MarkerSize { get; set; } + + /// + /// Gets or sets the marker visible + /// + public bool IsMarkerVisible { get; set; } + + /// + /// Gets or sets the marker offset + /// + public ScreenPoint MarkerOffset { get; set; } + + /// + /// Gets or sets the marker stroke color + /// + public OxyColor MarkerStrokeColor { get; set; } + + /// + /// Gets or sets the marker stroke thickness + /// + public double MarkerStrokeThickness { get; set; } + /// /// Returns c# code that generates this instance. /// diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs index 0d96d1823..db90727ee 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs @@ -172,6 +172,23 @@ protected override void RenderItem( null, LineJoin.Miter); } + ErrorBarItem errorBarItem = item as ErrorBarItem; + if (errorBarItem != null) + { + if (errorBarItem.IsMarkerVisible) + { + ScreenPoint screenPoint = new ScreenPoint(upperErrorPoint.X + errorBarItem.MarkerOffset.X, + upperErrorPoint.Y + errorBarItem.MarkerOffset.Y); + rc.DrawMarker(screenPoint, + errorBarItem.MarkerType, + errorBarItem.CustomOutline, + errorBarItem.MarkerSize, + errorBarItem.MarkerColor, + errorBarItem.MarkerStrokeColor, + errorBarItem.MarkerStrokeThickness, + this.EdgeRenderingMode); + } + } } } } From 6c92776cd33aaf5b6fdd03a80f59bd660a6ca4df Mon Sep 17 00:00:00 2001 From: ztt Date: Thu, 13 Nov 2025 17:43:30 +0800 Subject: [PATCH 2/3] Revert "fix Add a symbol on the ErrorBarItem to indicate statistical significance" This reverts commit b5ae2154604744662ecc16fb52591d7c608019c3. --- .../Series/ErrorBarSeriesExamples.cs | 166 +----------------- .../OxyPlot/Series/BarSeries/ErrorBarItem.cs | 41 ----- .../Series/BarSeries/ErrorBarSeries.cs | 17 -- 3 files changed, 1 insertion(+), 223 deletions(-) diff --git a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs index 17c75b2fc..c1f11918c 100644 --- a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs +++ b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs @@ -8,9 +8,8 @@ namespace ExampleLibrary { using OxyPlot; using OxyPlot.Axes; - using OxyPlot.Legends; using OxyPlot.Series; - using System; + using OxyPlot.Legends; [Examples("ErrorBarSeries"), Tags("Series")] public class ErrorBarSeriesExamples @@ -73,168 +72,5 @@ public static PlotModel GetErrorBarSeriesThickErrorLines() return model; } - - [Example("MarkerErrorBarSeries")] - [DocumentationExample("Series/MarkerErrorBarSeries")] - public static PlotModel GetMarkerErrorBarSeries() - { - var model = new PlotModel - { - Title = "MarkerErrorBarSeries" - }; - var l = new Legend - { - LegendPlacement = LegendPlacement.Outside, - LegendPosition = LegendPosition.BottomCenter, - LegendOrientation = LegendOrientation.Horizontal, - LegendBorderThickness = 0 - }; - - model.Legends.Add(l); - - var s1 = new ErrorBarSeries { Title = "Series 1", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; - s1.Items.Add(new ErrorBarItem - { - Value = 25, - Error = 2, - IsMarkerVisible = true, - MarkerColor = OxyColors.Red, - MarkerType = MarkerType.Star, - MarkerSize = 5, - MarkerOffset = new ScreenPoint(5, 0), - MarkerStrokeColor = OxyColors.Blue, - MarkerStrokeThickness = 1, - }); - s1.Items.Add(new ErrorBarItem - { - Value = 137, - Error = 25, - IsMarkerVisible = true, - MarkerColor = OxyColors.Yellow, - MarkerType = MarkerType.Cross, - MarkerSize = 5, - MarkerOffset = new ScreenPoint(0, 0), - MarkerStrokeColor = OxyColors.Red, - MarkerStrokeThickness = 1, - }); - s1.Items.Add(new ErrorBarItem - { - Value = 18, - Error = 4, - IsMarkerVisible = true, - MarkerColor = OxyColors.Yellow, - MarkerType = MarkerType.Diamond, - MarkerSize = 8, - MarkerOffset = new ScreenPoint(0, 0), - MarkerStrokeColor = OxyColors.LightGreen, - MarkerStrokeThickness = 1, - }); - s1.Items.Add(new ErrorBarItem { Value = 40, Error = 29, - IsMarkerVisible = true, - MarkerColor = OxyColors.Yellow, - MarkerType = MarkerType.Custom, - CustomOutline=GetSpiralStar(), - MarkerSize = 30, - MarkerOffset = new ScreenPoint(50, 0), - MarkerStrokeColor = OxyColors.LightGreen, - MarkerStrokeThickness = 1, - }); - - var s2 = new ErrorBarSeries { Title = "Series 2", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; - s2.Items.Add(new ErrorBarItem - { - Value = 25, - Error = 2, - IsMarkerVisible = true, - MarkerColor = OxyColors.Red, - MarkerType = MarkerType.Square, - MarkerSize = 5, - MarkerOffset = new ScreenPoint(5, 0), - MarkerStrokeColor = OxyColors.Blue, - MarkerStrokeThickness = 1, - }); - s2.Items.Add(new ErrorBarItem - { - Value = 137, - Error = 25, - IsMarkerVisible = true, - MarkerColor = OxyColors.Yellow, - MarkerType = MarkerType.Triangle, - MarkerSize = 5, - MarkerOffset = new ScreenPoint(0, 0), - MarkerStrokeColor = OxyColors.Red, - MarkerStrokeThickness = 1, - }); - s2.Items.Add(new ErrorBarItem - { - Value = 18, - Error = 4, - IsMarkerVisible = true, - MarkerColor = OxyColors.Yellow, - MarkerType = MarkerType.Plus, - MarkerSize = 8, - MarkerOffset = new ScreenPoint(0, 0), - MarkerStrokeColor = OxyColors.LightGreen, - MarkerStrokeThickness = 1, - }); - s2.Items.Add(new ErrorBarItem - { - Value = 40, - Error = 29, - IsMarkerVisible = true, - MarkerColor = OxyColors.GreenYellow, - MarkerType = MarkerType.Custom, - CustomOutline = GetHeartbeat(), - MarkerSize = 30, - MarkerOffset = new ScreenPoint(50, 0), - MarkerStrokeColor = OxyColors.BlueViolet, - MarkerStrokeThickness = 1, - }); - - var categoryAxis = new CategoryAxis { Position = AxisPosition.Left }; - categoryAxis.Labels.Add("Category A"); - categoryAxis.Labels.Add("Category B"); - categoryAxis.Labels.Add("Category C"); - categoryAxis.Labels.Add("Category D"); - - var valueAxis = new LinearAxis { Position = AxisPosition.Bottom, MinimumPadding = 0, MaximumPadding = 0.06, AbsoluteMinimum = 0 }; - model.Series.Add(s1); - model.Series.Add(s2); - model.Axes.Add(categoryAxis); - model.Axes.Add(valueAxis); - - return model; - } - public static ScreenPoint[] GetHeartbeat(int points = 20) - { - var outline = new ScreenPoint[points]; - for (int i = 0; i < points; i++) - { - double x = 2.0 * i / (points - 1) - 1; // -1 到 1 - double y = Math.Sin(x * Math.PI * 3) * Math.Exp(-Math.Abs(x)) * 0.8; - - // 添加一些随机脉冲效果 - y += Math.Sin(x * Math.PI * 8) * 0.1 * Math.Exp(-x * x * 4); - - outline[i] = new ScreenPoint(x, y); - } - return outline; - } - public static ScreenPoint[] GetSpiralStar(int points = 24, double tightness = 0.1) - { - var outline = new ScreenPoint[points]; - for (int i = 0; i < points; i++) - { - double progress = (double)i / points; - double radius = 0.2 + 0.8 * progress; // 半径逐渐增大 - double angle = 2 * Math.PI * (5 * progress + tightness * i); - - outline[i] = new ScreenPoint( - Math.Cos(angle) * radius, - Math.Sin(angle) * radius - ); - } - return outline; - } } } diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs index 9b05c887a..04079c6f9 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs @@ -41,47 +41,6 @@ public ErrorBarItem(double value, double error, int categoryIndex = -1) /// public double Error { get; set; } - /// - /// Gets or sets the color of marker - /// - public OxyColor MarkerColor { get; set; } - - - /// - /// Gets or sets the marker Type - /// - public MarkerType MarkerType { get; set; } - - /// - /// Gets or sets a custom polygon outline for the point marker. - /// - public ScreenPoint[] CustomOutline { get; set; } - - /// - /// Gets or sets the marker size - /// - public int MarkerSize { get; set; } - - /// - /// Gets or sets the marker visible - /// - public bool IsMarkerVisible { get; set; } - - /// - /// Gets or sets the marker offset - /// - public ScreenPoint MarkerOffset { get; set; } - - /// - /// Gets or sets the marker stroke color - /// - public OxyColor MarkerStrokeColor { get; set; } - - /// - /// Gets or sets the marker stroke thickness - /// - public double MarkerStrokeThickness { get; set; } - /// /// Returns c# code that generates this instance. /// diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs index db90727ee..0d96d1823 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs @@ -172,23 +172,6 @@ protected override void RenderItem( null, LineJoin.Miter); } - ErrorBarItem errorBarItem = item as ErrorBarItem; - if (errorBarItem != null) - { - if (errorBarItem.IsMarkerVisible) - { - ScreenPoint screenPoint = new ScreenPoint(upperErrorPoint.X + errorBarItem.MarkerOffset.X, - upperErrorPoint.Y + errorBarItem.MarkerOffset.Y); - rc.DrawMarker(screenPoint, - errorBarItem.MarkerType, - errorBarItem.CustomOutline, - errorBarItem.MarkerSize, - errorBarItem.MarkerColor, - errorBarItem.MarkerStrokeColor, - errorBarItem.MarkerStrokeThickness, - this.EdgeRenderingMode); - } - } } } } From 8171420cf16cbf3a72d54e7cec65258cfda511c6 Mon Sep 17 00:00:00 2001 From: ztt Date: Thu, 13 Nov 2025 17:59:23 +0800 Subject: [PATCH 3/3] Add a symbol on the ErrorBarItem to indicate statistical significance --- CHANGELOG.md | 2 + CONTRIBUTORS | 1 + .../Series/ErrorBarSeriesExamples.cs | 168 +++++++++++++++++- .../OxyPlot/Series/BarSeries/ErrorBarItem.cs | 41 +++++ .../Series/BarSeries/ErrorBarSeries.cs | 17 ++ 5 files changed, 228 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db04efa8..8e5e84fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,11 @@ All notable changes to this project will be documented in this file. ### Added - Example to demonstrate how to create vertical BarSeries +- Example to demonstrate how to create ErrorBarSeries Marker ### Fixed - DateTimeAxis converting local time rather than UTC to TimeZone +- ErrorBarItem add marker ## [2.2.0] - 2024-09-03 diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 9fa613c74..4b5c35ff6 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -156,3 +156,4 @@ Dmytro Shaurin Rustam Sayfutdinov Konstantin Stukov jorgectf +tangmanger diff --git a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs index c1f11918c..84425b87c 100644 --- a/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs +++ b/Source/Examples/ExampleLibrary/Series/ErrorBarSeriesExamples.cs @@ -8,8 +8,9 @@ namespace ExampleLibrary { using OxyPlot; using OxyPlot.Axes; - using OxyPlot.Series; using OxyPlot.Legends; + using OxyPlot.Series; + using System; [Examples("ErrorBarSeries"), Tags("Series")] public class ErrorBarSeriesExamples @@ -72,5 +73,170 @@ public static PlotModel GetErrorBarSeriesThickErrorLines() return model; } + [Example("MarkerErrorBarSeries")] + [DocumentationExample("Series/MarkerErrorBarSeries")] + public static PlotModel GetMarkerErrorBarSeries() + { + var model = new PlotModel + { + Title = "MarkerErrorBarSeries" + }; + var l = new Legend + { + LegendPlacement = LegendPlacement.Outside, + LegendPosition = LegendPosition.BottomCenter, + LegendOrientation = LegendOrientation.Horizontal, + LegendBorderThickness = 0 + }; + + model.Legends.Add(l); + + var s1 = new ErrorBarSeries { Title = "Series 1", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; + s1.Items.Add(new ErrorBarItem + { + Value = 25, + Error = 2, + IsMarkerVisible = true, + MarkerColor = OxyColors.Red, + MarkerType = MarkerType.Star, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(5, 0), + MarkerStrokeColor = OxyColors.Blue, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem + { + Value = 137, + Error = 25, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Cross, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.Red, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem + { + Value = 18, + Error = 4, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Diamond, + MarkerSize = 8, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + s1.Items.Add(new ErrorBarItem + { + Value = 40, + Error = 29, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Custom, + CustomOutline = GetSpiralStar(), + MarkerSize = 30, + MarkerOffset = new ScreenPoint(50, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + + var s2 = new ErrorBarSeries { Title = "Series 2", IsStacked = false, StrokeColor = OxyColors.Black, StrokeThickness = 1 }; + s2.Items.Add(new ErrorBarItem + { + Value = 25, + Error = 2, + IsMarkerVisible = true, + MarkerColor = OxyColors.Red, + MarkerType = MarkerType.Square, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(5, 0), + MarkerStrokeColor = OxyColors.Blue, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 137, + Error = 25, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Triangle, + MarkerSize = 5, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.Red, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 18, + Error = 4, + IsMarkerVisible = true, + MarkerColor = OxyColors.Yellow, + MarkerType = MarkerType.Plus, + MarkerSize = 8, + MarkerOffset = new ScreenPoint(0, 0), + MarkerStrokeColor = OxyColors.LightGreen, + MarkerStrokeThickness = 1, + }); + s2.Items.Add(new ErrorBarItem + { + Value = 40, + Error = 29, + IsMarkerVisible = true, + MarkerColor = OxyColors.GreenYellow, + MarkerType = MarkerType.Custom, + CustomOutline = GetHeartbeat(), + MarkerSize = 30, + MarkerOffset = new ScreenPoint(50, 0), + MarkerStrokeColor = OxyColors.BlueViolet, + MarkerStrokeThickness = 1, + }); + + var categoryAxis = new CategoryAxis { Position = AxisPosition.Left }; + categoryAxis.Labels.Add("Category A"); + categoryAxis.Labels.Add("Category B"); + categoryAxis.Labels.Add("Category C"); + categoryAxis.Labels.Add("Category D"); + + var valueAxis = new LinearAxis { Position = AxisPosition.Bottom, MinimumPadding = 0, MaximumPadding = 0.06, AbsoluteMinimum = 0 }; + model.Series.Add(s1); + model.Series.Add(s2); + model.Axes.Add(categoryAxis); + model.Axes.Add(valueAxis); + + return model; + } + public static ScreenPoint[] GetHeartbeat(int points = 20) + { + var outline = new ScreenPoint[points]; + for (int i = 0; i < points; i++) + { + double x = 2.0 * i / (points - 1) - 1; // -1 到 1 + double y = Math.Sin(x * Math.PI * 3) * Math.Exp(-Math.Abs(x)) * 0.8; + + // 添加一些随机脉冲效果 + y += Math.Sin(x * Math.PI * 8) * 0.1 * Math.Exp(-x * x * 4); + + outline[i] = new ScreenPoint(x, y); + } + return outline; + } + public static ScreenPoint[] GetSpiralStar(int points = 24, double tightness = 0.1) + { + var outline = new ScreenPoint[points]; + for (int i = 0; i < points; i++) + { + double progress = (double)i / points; + double radius = 0.2 + 0.8 * progress; // 半径逐渐增大 + double angle = 2 * Math.PI * (5 * progress + tightness * i); + + outline[i] = new ScreenPoint( + Math.Cos(angle) * radius, + Math.Sin(angle) * radius + ); + } + return outline; + } } } diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs index 04079c6f9..0bc121130 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarItem.cs @@ -41,6 +41,47 @@ public ErrorBarItem(double value, double error, int categoryIndex = -1) /// public double Error { get; set; } + /// + /// Gets or sets the color of marker + /// + public OxyColor MarkerColor { get; set; } + + + /// + /// Gets or sets the marker Type + /// + public MarkerType MarkerType { get; set; } + + /// + /// Gets or sets a custom polygon outline for the point marker. + /// + public ScreenPoint[] CustomOutline { get; set; } + + /// + /// Gets or sets the marker size + /// + public int MarkerSize { get; set; } + + /// + /// Gets or sets the marker visible + /// + public bool IsMarkerVisible { get; set; } + + /// + /// Gets or sets the marker offset + /// + public ScreenPoint MarkerOffset { get; set; } + + /// + /// Gets or sets the marker stroke color + /// + public OxyColor MarkerStrokeColor { get; set; } + + /// + /// Gets or sets the marker stroke thickness + /// + public double MarkerStrokeThickness { get; set; } + /// /// Returns c# code that generates this instance. /// diff --git a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs index 0d96d1823..db90727ee 100644 --- a/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs +++ b/Source/OxyPlot/Series/BarSeries/ErrorBarSeries.cs @@ -172,6 +172,23 @@ protected override void RenderItem( null, LineJoin.Miter); } + ErrorBarItem errorBarItem = item as ErrorBarItem; + if (errorBarItem != null) + { + if (errorBarItem.IsMarkerVisible) + { + ScreenPoint screenPoint = new ScreenPoint(upperErrorPoint.X + errorBarItem.MarkerOffset.X, + upperErrorPoint.Y + errorBarItem.MarkerOffset.Y); + rc.DrawMarker(screenPoint, + errorBarItem.MarkerType, + errorBarItem.CustomOutline, + errorBarItem.MarkerSize, + errorBarItem.MarkerColor, + errorBarItem.MarkerStrokeColor, + errorBarItem.MarkerStrokeThickness, + this.EdgeRenderingMode); + } + } } } }