初探oxyplot
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using DLVisionH; using OxyPlot; using OxyPlot.Annotations; using OxyPlot.Axes; using OxyPlot.Series; using OxyPlot.WindowsForms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrayNotify; using Annotation = OxyPlot.Annotations.Annotation; using ArrowAnnotation = OxyPlot.Annotations.ArrowAnnotation; using DataPoint = OxyPlot.DataPoint; using EllipseAnnotation = OxyPlot.Annotations.EllipseAnnotation; using HitTestResult = OxyPlot.HitTestResult; using LineAnnotation = OxyPlot.Annotations.LineAnnotation; using RectangleAnnotation = OxyPlot.Annotations.RectangleAnnotation; using TextAnnotation = OxyPlot.Annotations.TextAnnotation; using TickStyle = OxyPlot.Axes.TickStyle; namespace WindowsFormsApp2 { public partial class Formoxyplot : Form { enum CrossSectionBaseUnitType { MaxPoint, MinPoint, MeanPoint, FitLine, FitCircle, None } static List<PointAnnotation> GrapPoints { get; set; } = new List<PointAnnotation>(); static List<PointAnnotation> SelectPoints { get; set; } = new List<PointAnnotation>(); #region CommonFuncation //读取txt文件获取点数据 public static double[] ReadTxtFile() { List<double> data = new List<double>(); OpenFileDialog openFileDialog = new OpenFileDialog(); if (openFileDialog.ShowDialog() == DialogResult.OK) { string[] lines = File.ReadAllLines(openFileDialog.FileName); data.Clear(); foreach (string s in lines) { data.Add(Convert.ToDouble(s.Trim())); } } return data == null ? new double[0] : data.ToArray(); } // n 生成随机数个数 public static double[] GenerateUniqueRandom(int minValue, int maxValue, int n) { // Random.Nex(1, 10) 只能产生到 9 的随机数,若要产生到 10 的随机数, maxValue 要加 1 maxValue++; // Random.Nex(1, 10) 只能产生 9 个随机数,因此 n 不能大于 10 - 1 //if (n > maxValue - minValue) // n = maxValue - minValue; double[] arr = new double[n]; Random ran = new Random(); bool flag = true; for (int i = 0; i < n; i++) { do { double val = ran.NextDouble() * (maxValue - minValue) + minValue; if (!IsDuplicates(ref arr, val)) { arr[i] = val; flag = false; } } while (flag); if (!flag) flag = true; } return arr; } // 查检当前生成的随机数是否重复 public static bool IsDuplicates(ref double[] arr, double currRandNum) { bool flag = false; for (int i = 0; i < arr.Length; i++) { if (arr[i] == currRandNum) { flag = true; break; } } return flag; } // //调用方法: // int[] arr = GenerateUniqueRandom(1, 10, 10);// 生成 10 个 1 到 10 的随机数 //for (int i = 0; i<arr.Length; i++) //Response.Write(arr[i] + ", ");// 结果 10, 7, 9, 4, 3, 5, 1, 2, 6, 8 //GenerateUniqueRandom(1, 10, 5);// 生成 5 个 1 到 10 的随机数,结果 9, 1, 7, 2, 10 #endregion #region CommonVariable static CrossSectionBaseUnitType BaseUnitType = CrossSectionBaseUnitType.None; #endregion public Formoxyplot() { InitializeComponent(); InitPlot(); this.Load += Formoxyplot_Load; } private PlotView plot1; private void InitPlot() { this.plot1 = new OxyPlot.WindowsForms.PlotView(); this.SuspendLayout(); this.plot1.Dock = System.Windows.Forms.DockStyle.Fill; this.plot1.Location = new System.Drawing.Point(0, 0); this.plot1.Name = "profile"; this.plot1.TabIndex = 0; this.plot1.Margin = new System.Windows.Forms.Padding(0); this.panel1.Controls.Add(this.plot1); this.ResumeLayout(); } //private PlotModel _myPlotModel; //private DateTimeAxis _dateAxis; //private LinearAxis _valueAxis; //private Random rand = new Random(); int samples = 5; int distance = 179; int rectPad = 34; PlotModel model = null; static float PixelRate = 0.01975f; public static PlotModel MouseEvents() { var model = new PlotModel { Title = "Mouse events", Subtitle = "Left click and drag" }; var yaxis = new LinearAxis { Position = AxisPosition.Left, Minimum = -1, Maximum = 1 }; var xaxis = new LinearAxis { Position = AxisPosition.Bottom, Minimum = -1, Maximum = 1 }; model.Axes.Add(yaxis); model.Axes.Add(xaxis); LineSeries s1 = null; // Subscribe to the mouse down event on the line series model.MouseDown += (s, e) => { // only handle the left mouse button (right button can still be used to pan) if (e.ChangedButton == OxyMouseButton.Left) { // Add a line series s1 = new LineSeries { Title = "LineSeries" + (model.Series.Count + 1), MarkerType = MarkerType.None, StrokeThickness = 2 }; s1.Points.Add(xaxis.InverseTransform(e.Position.X, e.Position.Y, yaxis)); model.Series.Add(s1); model.InvalidatePlot(false); e.Handled = true; } }; model.MouseMove += (s, e) => { if (s1 != null) { s1.Points.Add(xaxis.InverseTransform(e.Position.X, e.Position.Y, yaxis)); model.InvalidatePlot(false); e.Handled = true; } }; model.MouseUp += (s, e) => { if (s1 != null) { s1 = null; e.Handled = true; } }; return model; } static List<OxyPlot.DataPoint> GetPoints(double[] zValues) { List<OxyPlot.DataPoint> points = new List<OxyPlot.DataPoint>(); for (int i = 0; i < zValues.Length; i++) { points.Add(new OxyPlot.DataPoint( (i+1), zValues[i])); } return points; } private static PlotModel CreateGridlinesModel(PlotModel model, LineStyle horizontal, LineStyle vertical) { model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, MajorGridlineStyle = vertical, MinorGridlineStyle = vertical == LineStyle.Solid ? LineStyle.Dot : LineStyle.None, MaximumPadding = 0, MinimumPadding = 0 }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, MajorGridlineStyle = horizontal, MinorGridlineStyle = horizontal == LineStyle.Solid ? LineStyle.Dot : LineStyle.None, MaximumPadding = 0, MinimumPadding = 0 }); return model; } public static PlotModel ToolTips() { var model = new PlotModel { Title = "Tool tips" }; model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left }); model.Annotations.Add(new LineAnnotation { Slope = 0.1, Intercept = 1, Text = "LineAnnotation", ToolTip = "This is a tool tip for the LineAnnotation" }); model.Annotations.Add(new RectangleAnnotation { MinimumX = 20, MaximumX = 70, MinimumY = 10, MaximumY = 40, TextRotation = 10, Text = "RectangleAnnotation", ToolTip = "This is a tooltip for the RectangleAnnotation", Fill = OxyColor.FromAColor(99, OxyColors.Blue), Stroke = OxyColors.Black, StrokeThickness = 2 }); model.Annotations.Add(new EllipseAnnotation { X = 20, Y = 60, Width = 20, Height = 15, Text = "EllipseAnnotation", ToolTip = "This is a tool tip for the EllipseAnnotation", TextRotation = 10, Fill = OxyColor.FromAColor(99, OxyColors.Green), Stroke = OxyColors.Black, StrokeThickness = 2 }); model.Annotations.Add(new PointAnnotation { X = 50, Y = 50, Text = "P1", ToolTip = "This is a tool tip for the PointAnnotation" }); model.Annotations.Add(new ArrowAnnotation { StartPoint = new DataPoint(8, 4), EndPoint = new DataPoint(0, 0), Color = OxyColors.Green, Text = "ArrowAnnotation", ToolTip = "This is a tool tip for the ArrowAnnotation" }); model.Annotations.Add(new TextAnnotation { TextPosition = new DataPoint(60, 60), Text = "TextAnnotation", ToolTip = "This is a tool tip for the TextAnnotation" }); return model; } public static PlotModel InvisibleVerticalAxis() { var model = new PlotModel { Title = "Invisible vertical axis" }; model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, IsAxisVisible = false }); model.Series.Add(new FunctionSeries(x => Math.Sin(x) / x, -5, 5, 0.1)); return model; } private static void SmoothContour(List<DataPoint> points, int level = 1, int severity = 1) { for (int ii = 0; ii < level; ii++) { for (int i = 1; i < points.Count; i++) { var start = (i - severity > 0 ? i - severity + 1 : 0); var end = (i + severity < points.Count ? i + severity + 1 : points.Count); double sumX = 0, sumY = 0; for (int j = start; j < end; j++) { sumX += points[j].X; sumY += points[j].Y; } DataPoint sum = new DataPoint(sumX, sumY); DataPoint avg = new DataPoint(sum.X / (end - start), sum.Y / (end - start)); points[i] = avg; } } } //("Select range")] public static PlotModel SelectRange() { //初始化X轴/Y轴 var model = new PlotModel { Title = "", Subtitle = "轮廓线" }; model.PlotType = PlotType.Cartesian; //make sure x/y axis have the same ratio LineSeries ls = new LineSeries(); ls.Color = OxyColors.Cyan; ///ls.LineStyle = LineStyle.Dot; ls.StrokeThickness = 1; ls.MarkerType = MarkerType.Circle; ls.MarkerSize = 1; ls.MarkerStroke = OxyColors.Cyan; //ls.MarkerFill = OxyColors.SkyBlue; ls.MarkerStrokeThickness = 1; double[] data = ReadTxtFile(); List<OxyPlot.DataPoint> points = GetPoints(data); SmoothContour(points,1); double abs = data.Max() - data.Min(); double max = data.Max()+abs; double min = data.Min()-abs; foreach (OxyPlot.DataPoint p in points) { ls.Points.Add(p); } model.Series.Add(ls); var yaxis = new LinearAxis { Position = AxisPosition.Left, //坐标轴位置,左 PositionTier = 0, //坐标轴离图表位置 IsAxisVisible= true, //坐标轴是否显示 Layer = AxisLayer.BelowSeries, //坐标轴层级 //视图缩放平移最大值 FilterMinValue = min, FilterMaxValue = max, //坐标轴绝对最大最小值 AbsoluteMinimum = min, AbsoluteMaximum = max, //坐标轴固定范围最大最小值 Minimum = min, Maximum = max, MinorStep = 0.05, //辅刻线间隔 MajorStep = 0.5, //主刻线间隔 MinimumMinorStep = 0.0001, //辅刻线最小间隔 MinimumMajorStep = 0.001, //主刻线最小间隔 MinimumPadding = 0.01, //最小值额外空间(0.01表示1%)(设置了Minimum则此处无效) MaximumPadding = 0.01, //最大值额外空间 MinimumRange = 0, //最小范围(ActualMaximum-ActualMinimum > MinimumRange) MaximumRange = double.PositiveInfinity, //最大范围(ActualMaximum-ActualMinimum < MinimumRange) MinimumDataMargin = 0, //最小值的屏幕空间数据边距 MaximumDataMargin = 0, //最大值的屏幕空间数据边距 MinimumMargin = 0, //最小值的屏幕空间边距 MaximumMargin = 0, //最大值的屏幕空间边距 TickStyle = TickStyle.Outside, //刻度样式 TicklineColor = OxyColors.White, //刻度线颜色 MinorTicklineColor = OxyColors.White, //辅刻度线颜色 AxislineStyle = LineStyle.None, //坐标轴线样式 AxislineColor = OxyColors.White, //坐标轴线颜色 AxislineThickness = 1.0, //坐标轴线粗细 MajorGridlineStyle = LineStyle.None, //主网格线样式 MajorGridlineColor = OxyColor.FromArgb(0x40, 0, 0, 0), //主网格线颜色 MajorGridlineThickness = 1, //主网格线粗细 MinorGridlineStyle = LineStyle.None, //辅网格线样式 MinorGridlineColor = OxyColor.FromArgb(0x20, 0, 0, 0x00), //辅网格线颜色 MinorGridlineThickness = 1, //辅网格线粗细 ExtraGridlineStyle = LineStyle.Solid, //额外网格线样式 ExtraGridlineColor = OxyColors.White, //额外网格线颜色 ExtraGridlineThickness = 1, //额外网格线粗细 //MinorTickSize = 4, //辅刻度大小 //MajorTickSize = 7, //主刻度大小 StartPosition = 0, //坐标轴在图表区的起点(0-1) EndPosition = 1, //坐标轴在图表区的终点(0-1) TitlePosition = 0.5, //标题位置(0-1) TitleFormatString = "{0} [{1}]", //标题格式化字符串(0代表Title,1代表Unit) TitleClippingLength = 0.9, //标题长度(0-1) TitleColor = OxyColors.White, //标题颜色 TitleFontSize = double.NaN, //标题字体大小 TitleFontWeight = FontWeights.Normal, //标题字重 ClipTitle = true, //是否截断标题 Angle = 0, //坐标轴标签角度 IsZoomEnabled = true, //是否允许缩放 IsPanEnabled = false, //是否允许平移 //FilterMinValue = double.MinValue, //可显示的最小值(小等于该值将不会显示) //FilterMaxValue = double.MaxValue, //可显示的最大值(大等于该值将不会显示) FilterFunction = null, //过滤方法 IntervalLength = 60, //主刻度划分份数 AxisDistance = 0, //坐标轴和图表的距离 AxisTitleDistance = 4, //坐标轴标题和标签的距离 AxisTickToLabelDistance = 4, //坐标轴刻度和标签的距离 //DataMaximum = double.NaN, //数据最大值 //DataMinimum = double.NaN, //数据最小值 }; var xaxis = new LinearAxis { Position = AxisPosition.Bottom, //坐标轴位置,底部 PositionTier = 0, //坐标轴离图表位置 IsAxisVisible = true, //坐标轴是否显示 Layer = AxisLayer.BelowSeries, //坐标轴层级 //视图缩放平移最大值 FilterMaxValue = points.Count, FilterMinValue = 0, //坐标轴绝对最大最小值 AbsoluteMinimum = 0, AbsoluteMaximum = points.Count, //坐标轴固定范围最大最小值 Minimum = 0, Maximum = points.Count, MinorStep = 5, //辅刻线间隔 MajorStep = 50, //主刻线间隔 MinimumMinorStep = 1 , //辅刻线最小间隔 MinimumMajorStep = 10, //主刻线最小间隔 MinimumPadding = 0.01 , //最小值额外空间(0.01表示1%)(设置了Minimum则此处无效) MaximumPadding = 0.01 , //最大值额外空间 MinimumRange = 0, //最小范围(ActualMaximum-ActualMinimum > MinimumRange) MaximumRange = double.PositiveInfinity, //最大范围(ActualMaximum-ActualMinimum < MinimumRange) MinimumDataMargin = 0, //最小值的屏幕空间数据边距 MaximumDataMargin = 0, //最大值的屏幕空间数据边距 MinimumMargin = 0, //最小值的屏幕空间边距 MaximumMargin = 0, //最大值的屏幕空间边距 TickStyle = TickStyle.None, //刻度样式 TicklineColor = OxyColors.Cyan, //刻度线颜色 MinorTicklineColor = OxyColors.Automatic, //辅刻度线颜色 AxislineStyle = LineStyle.None, //坐标轴线样式 AxislineColor = OxyColors.White, //坐标轴线颜色 AxislineThickness = 1.0, //坐标轴线粗细 MajorGridlineStyle = LineStyle.None, //主网格线样式 MajorGridlineColor = OxyColor.FromArgb(0x40, 0, 0, 0), //主网格线颜色 MajorGridlineThickness = 1, //主网格线粗细 MinorGridlineStyle = LineStyle.None, //辅网格线样式 MinorGridlineColor = OxyColor.FromArgb(0x20, 0, 0, 0x00), //辅网格线颜色 MinorGridlineThickness = 1, //辅网格线粗细 ExtraGridlineStyle = LineStyle.Solid, //额外网格线样式 ExtraGridlineColor = OxyColors.White, //额外网格线颜色 ExtraGridlineThickness = 1, //额外网格线粗细 //MinorTickSize = 4, //辅刻度大小 //MajorTickSize = 7, //主刻度大小 StartPosition = 0, //坐标轴在图表区的起点(0-1) EndPosition = 1, //坐标轴在图表区的终点(0-1) TitlePosition = 0.5, //标题位置(0-1) TitleFormatString = "{0} [{1}]", //标题格式化字符串(0代表Title,1代表Unit) TitleClippingLength = 0.9, //标题长度(0-1) TitleColor = OxyColors.White, //标题颜色 TitleFontSize = double.NaN, //标题字体大小 TitleFontWeight = FontWeights.Normal, //标题字重 ClipTitle = true, //是否截断标题 Angle = 0, //坐标轴标签角度 IsZoomEnabled = true, //是否允许缩放 IsPanEnabled = true, //是否允许平移 //FilterMinValue = double.MinValue, //可显示的最小值(小等于该值将不会显示) //FilterMaxValue = double.MaxValue, //可显示的最大值(大等于该值将不会显示) FilterFunction = null, //过滤方法 IntervalLength = 60, //主刻度划分份数 AxisDistance = 0, //坐标轴和图表的距离 AxisTitleDistance = 4, //坐标轴标题和标签的距离 AxisTickToLabelDistance = 4, //坐标轴刻度和标签的距离 //DataMaximum = double.NaN, //数据最大值 //DataMinimum = double.NaN, //数据最小值 }; model.Axes.Add(yaxis); model.Axes.Add(xaxis); model.Background = OxyColors.Black; model.PlotAreaBorderColor = OxyColors.White; model.TextColor = OxyColors.White; //model.PlotAreaBackground= OxyColors.Black; var range = new RectangleAnnotation { Fill = OxyColor.FromAColor(120, OxyColors.Green), MinimumX = 0, MaximumX = 0 }; range.FontSize = 18; model.Annotations.Add(range); double startx = double.NaN; model.MouseDown += (s, e) => { if (e.ChangedButton == OxyMouseButton.Left) { startx = range.InverseTransform(e.Position).X; range.MinimumX = startx; range.MaximumX = startx; model.InvalidatePlot(true); e.Handled = true; } else if (e.ChangedButton == OxyMouseButton.Right) // { if (BaseUnitType == CrossSectionBaseUnitType.None) return; else { switch (BaseUnitType) { case CrossSectionBaseUnitType.MaxPoint: DataPoint p = GetMaxPoint(data,points.ToArray(),(int)range.MinimumX, (int)range.MaximumX); //draw a point GrapPoints.Add(new PointAnnotation { X = p.X, Y = p.Y, Text = "P"+(GrapPoints.Count+1).ToString()}); //model.Annotations.Add(new PointAnnotation { X = p.X, Y = p.Y, Text = "P1", ToolTip = "This is a tool tip for the PointAnnotation" }); //reset BaseUnitType = CrossSectionBaseUnitType.None; break; case CrossSectionBaseUnitType.MinPoint: GetMinPoint(data,points.ToArray(),(int)range.MinimumX, (int)range.MaximumX); BaseUnitType = CrossSectionBaseUnitType.None; break; case CrossSectionBaseUnitType.MeanPoint: GetMeanPoint(data,points.ToArray(),(int)range.MinimumX, (int)range.MaximumX); BaseUnitType = CrossSectionBaseUnitType.None; break; case CrossSectionBaseUnitType.FitLine: FitLine(points.ToArray(),(int)range.MinimumX, (int)range.MaximumX); BaseUnitType = CrossSectionBaseUnitType.None; break; case CrossSectionBaseUnitType.FitCircle: FitCircle(points.ToArray(),(int)range.MinimumX, (int)range.MaximumX); BaseUnitType = CrossSectionBaseUnitType.None; break; default: break; } } } }; model.MouseMove += (s, e) => { if (!double.IsNaN(startx)) { var x = range.InverseTransform(e.Position).X; //var y = range.InverseTransform(e.Position).Y; range.MinimumX = Math.Min(x, startx); range.MaximumX = Math.Max(x, startx); if((int)x<points.Count && (int)x >=0) range.Text = string.Format("(X:{0:0.000},Z:{1:0.000})", x, points[(int)x].Y); model.Subtitle = string.Format("X: {0:0.000} >> {1:0.000}", range.MinimumX, range.MaximumX); ////////////////////////////////////// //test draw a line LineSeries l = new LineSeries(); l.Color = OxyColors.White; l.Points.Add(new DataPoint(range.MinimumX, points[(int)range.MinimumX].Y)); l.Points.Add(new DataPoint(range.MaximumX, points[(int)range.MaximumX].Y)); l.MarkerType = MarkerType.Circle; for(int i=1;i< model.Series.Count;i++) { model.Series.Remove(model.Series[i]); } model.Series.Add(l); ////////////////////////////////////////////////////////////////////// ////test draw a circle ////model.Annotations.Clear(); ////model.Annotations.Add(new EllipseAnnotation { X = range.MinimumX, Y = points[(int)range.MinimumX].Y, Width = 0.3*(xaxis.MinorStep/yaxis.MinorStep), Height = 0.3, Fill = OxyColors.Transparent, Stroke = OxyColors.Cyan, StrokeThickness = 1 }); ////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////// ////draw a point //model.Annotations.Add(new PointAnnotation { X = 50, Y = 50, Text = "P1", ToolTip = "This is a tool tip for the PointAnnotation" }); //////////////////////////////////////////////////////////////////////////////////////// model.InvalidatePlot(true); e.Handled = true; } }; model.MouseUp += (s, e) => { startx = double.NaN; }; return model; } public static PlotModel EllipseAnnotation() { var model = new PlotModel { Title = "EllipseAnnotation" }; model.PlotType = PlotType.Cartesian; model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left }); model.Annotations.Add(new EllipseAnnotation { X = 20, Y = 60, Width = 20, Height = 15, Text = "EllipseAnnotation", TextRotation = 10, Fill = OxyColor.FromAColor(99, OxyColors.Green), Stroke = OxyColors.Black, StrokeThickness = 2 }); model.Annotations.Add(new EllipseAnnotation { X = 20, Y = 20, Width = 20, Height = 20, Fill = OxyColor.FromAColor(99, OxyColors.Green), Stroke = OxyColors.Black, StrokeThickness = 2 }); model.Annotations.Add(new EllipseAnnotation { X = 30, Y = 20, Width = 20, Height = 20, Fill = OxyColor.FromAColor(99, OxyColors.Red), Stroke = OxyColors.Black, StrokeThickness = 2 }); model.Annotations.Add(new EllipseAnnotation { X = 25, Y = 30, Width = 20, Height = 20, Fill = OxyColor.FromAColor(99, OxyColors.Blue), Stroke = OxyColors.Black, StrokeThickness = 2 }); return model; } private void Formoxyplot_Load(object sender, EventArgs e) { plot1.Model = SelectRange(); //plot1.Model = CreateGridlinesModel(plot1.Model, LineStyle.Solid, LineStyle.None); //plot1.Model = EllipseAnnotation(); } private void Model_KeyDown(object sender, OxyKeyEventArgs e) { if(e.Key == OxyKey.Right) { plot1.InvalidatePlot(true); } } enum MouseState { } private void Model_MouseUp(object sender, OxyMouseEventArgs e) { OxyPlot.DataPoint p = OxyPlot.Axes.Axis.InverseTransform(e.Position, plot1.Model.DefaultXAxis, plot1.Model.DefaultYAxis); if (TwoPointFs.Count == 2) { var rect1 = new RectangleAnnotation() { MinimumX = TwoPointFs[0].X, MaximumX = TwoPointFs[1].X, MinimumY = TwoPointFs[0].Y, MaximumY = TwoPointFs[1].Y, Fill = OxyColor.FromRgb(155, 188, 243),//sky blue Stroke = OxyColors.Transparent }; rect1.Selectable = true; model.Annotations.Add(rect1); TwoPointFs.Clear(); } else { TwoPointFs.Add(new PointF((float)p.X, (float)p.Y)); } } private void Model_MouseMove(object sender, OxyMouseEventArgs e) { throw new NotImplementedException(); } List<PointF> TwoPointFs = new List<PointF>(); private void Model_MouseDown(object sender, OxyMouseDownEventArgs e) { double x = e.Position.X; double y = e.Position.Y; OxyPlot.DataPoint p = OxyPlot.Axes.Axis.InverseTransform(e.Position, plot1.Model.DefaultXAxis, plot1.Model.DefaultYAxis); this.Text = ($"X is {x} and Y is {y} and Inverse is {p.ToString()}"); if (TwoPointFs.Count == 2) { var rect1 = new RectangleAnnotation() { MinimumX = TwoPointFs[0].X, MaximumX = TwoPointFs[1].X, MinimumY = TwoPointFs[0].Y, MaximumY = TwoPointFs[1].Y, Fill = OxyColor.FromRgb(155, 188, 243),//sky blue Stroke = OxyColors.Transparent }; model.Annotations.Add(rect1); TwoPointFs.Clear(); } else { TwoPointFs.Add(new PointF((float)p.X,(float)p.Y)); } } private void 最高点ToolStripMenuItem_Click(object sender, EventArgs e) { BaseUnitType = CrossSectionBaseUnitType.MaxPoint; } private void 最低点ToolStripMenuItem_Click(object sender, EventArgs e) { BaseUnitType = CrossSectionBaseUnitType.MinPoint; } private void 平均点ToolStripMenuItem_Click(object sender, EventArgs e) { BaseUnitType = CrossSectionBaseUnitType.MeanPoint; } private static void FitCircle(DataPoint[] ps,int startX, int endX) { DataPoint[] data = GetPointsByRange(ps,startX,endX); } private static void FitLine(DataPoint[] ps,int startX, int endX) { DataPoint[] data = GetPointsByRange(ps, startX, endX); } private static DataPoint GetMeanPoint(double[] data, DataPoint[] dataPoints,int startX, int endX) { double[] getData = GetDataByRange(data, startX, endX); List<double> tmpList = getData.ToList(); tmpList.Sort(); double value = tmpList[(int)(tmpList.Count/2.0)]; int index = data.ToList().IndexOf(value); return dataPoints[index]; } private static DataPoint GetMinPoint(double[] data, DataPoint[] dataPoints, int startX,int endX) { double[] getData = GetDataByRange(data, startX, endX); List<double> tmpList = getData.ToList(); tmpList.Sort(); double value = double.MaxValue; if (tmpList[0] < 0) value = tmpList[tmpList.Count - 1]; else value = tmpList[0]; int index = data.ToList().IndexOf(value); return dataPoints[index]; } private static DataPoint GetMaxPoint(double[] data, DataPoint[] dataPoints,int startX,int endX) { double[] getData = GetDataByRange(data,startX,endX); List<double> tmpList = getData.ToList(); tmpList.Sort(); double value = double.MaxValue; if (tmpList[0] > 0) value=tmpList[tmpList.Count-1]; else value = tmpList[0]; int index = data.ToList().IndexOf(value); return dataPoints[index]; } private static DataPoint[] GetPointsByRange(DataPoint[] points,int startX,int endX) { try { if (endX - startX <= 0) return new DataPoint[0]; } catch { return new DataPoint[0]; } DataPoint[] getPoints = new DataPoint[endX-startX]; if (points != null) { getPoints = (points.ToList().GetRange(startX, endX-startX)).ToArray(); } else return new DataPoint[0]; return getPoints; } private static double[] GetDataByRange(double[] data, int startX, int endX) { try { if (endX - startX <= 0) return new double[0]; } catch { return new double[0]; } double[] getData = new double[endX - startX]; if (data != null) { getData = (data.ToList().GetRange(startX, endX - startX)).ToArray(); } else return new double[0]; return getData; } void Refresh() { //点显示 if (GrapPoints.Count > 0 && plot1.Model != null) { plot1.Model.Annotations.Clear(); foreach (var point in GrapPoints) { plot1.Model.Annotations.Add(point); } plot1.Model.MouseMove += (s, ee) => { foreach (var ann in plot1.Model.Annotations) { HitTestResult hitTestResult = ann.HitTest(new HitTestArguments(ee.Position, 10)); if (hitTestResult != null) { switch (ann.GetType().Name) { case "PointAnnotation": int i = Convert.ToInt32(((PointAnnotation)(hitTestResult.Element)).Text.Replace("P", "")) - 1; PointAnnotation p = (PointAnnotation)(plot1.Model.Annotations[i]); p.TextColor = OxyColors.Green; //plot1.Model.Annotations.Add(p); //plot1.Model.Annotations.RemoveAt(i); //ann.TextColor = OxyColors.Red; break; } return; } } }; //plot1.Model.MouseDown += (s, ee) => //{ // var args = new HitTestArguments(ee.Position, 10); // foreach (var result in plot1.Model.Annotations[0].HitTest(args)) // { // ee.HitTestResult = result; // result.Element.OnMouseDown(e); // if (ee.Handled) // { // this.currentMouseEventElement = result.Element; // return; // } // } //if (!ee.Handled) //{ // point.OnMouseDown(sender, ee); //} //}; } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> //[Obsolete] private void timer1_Tick(object sender, EventArgs e) { //点显示 if (GrapPoints.Count > 0 && plot1.Model != null) { plot1.Model.Annotations.Clear(); foreach(var point in GrapPoints) { plot1.Model.Annotations.Add(point); } plot1.Model.MouseMove += (s, ee) => { foreach (var ann in plot1.Model.Annotations) { HitTestResult hitTestResult = ann.HitTest(new HitTestArguments(ee.Position, 10)); if (hitTestResult != null) { switch(ann.GetType().Name) { case "PointAnnotation": int i = Convert.ToInt32(((PointAnnotation)(hitTestResult.Element)).Text.Replace("P",""))-1; PointAnnotation p = (PointAnnotation)(plot1.Model.Annotations[i]); p.TextColor = OxyColors.Green; p.FontSize = 30; //plot1.Model.Annotations.Add(p); //plot1.Model.Annotations.RemoveAt(i); //ann.TextColor = OxyColors.Red; SelectPoints.Add(p); break; } return; } } }; //plot1.Model.MouseDown += (s, ee) => //{ // var args = new HitTestArguments(ee.Position, 10); // foreach (var result in plot1.Model.Annotations[0].HitTest(args)) // { // ee.HitTestResult = result; // result.Element.OnMouseDown(e); // if (ee.Handled) // { // this.currentMouseEventElement = result.Element; // return; // } // } //if (!ee.Handled) //{ // point.OnMouseDown(sender, ee); //} //}; } } private void toolStripSplitButtonPPHeight_ButtonClick(object sender, EventArgs e) { if (SelectPoints.Count >= 2) { //test draw a line LineSeries l1 = new LineSeries(); l1.Color = OxyColors.White; l1.Points.Add(new DataPoint(SelectPoints[0].X, SelectPoints[0].Y)); l1.Points.Add(new DataPoint(SelectPoints[0].X, SelectPoints[SelectPoints.Count-1].Y)); l1.MarkerType = MarkerType.Circle; LineSeries l2 = new LineSeries(); l2.Color = OxyColors.White; l2.Points.Add(new DataPoint(SelectPoints[0].X, SelectPoints[SelectPoints.Count - 1].Y)); l2.Points.Add(new DataPoint(SelectPoints[SelectPoints.Count - 1].X, SelectPoints[SelectPoints.Count - 1].Y)); l2.MarkerType = MarkerType.Circle; for (int i = 1; i < plot1.Model.Series.Count; i++) { plot1.Model.Series.Remove(plot1.Model.Series[i]); } plot1.Model.Series.Add(l1); plot1.Model.Series.Add(l2); plot1.Model.Annotations.Add(new DelegateAnnotation(rc => { const double FontSize = 20d; const double D = FontSize * 1.6; const double X = 20; double y = 20 - D; rc.DrawText(new ScreenPoint(X, y += D), "Default font", OxyColors.Black, null, FontSize); //rc.DrawText(new ScreenPoint(X, y += D), "Helvetica", OxyColors.Black, "Helvetica", FontSize); //rc.DrawText(new ScreenPoint(X, y += D), "Arial", OxyColors.Black, "Arial", FontSize); //rc.DrawText(new ScreenPoint(X, y += D), "Courier", OxyColors.Black, "Courier", FontSize); //rc.DrawText(new ScreenPoint(X, y += D), "Courier New", OxyColors.Black, "Courier New", FontSize); //rc.DrawText(new ScreenPoint(X, y += D), "Times", OxyColors.Black, "Times", FontSize); //rc.DrawText(new ScreenPoint(X, y + D), "Times New Roman", OxyColors.Black, "Times New Roman", FontSize); })); } } } /// <summary> /// Represents an annotation that renders by a delegate. /// </summary> public class DelegateAnnotation : Annotation { /// <summary> /// Initializes a new instance of the <see cref="DelegateAnnotation"/> class. /// </summary> /// <param name="rendering">The rendering delegate.</param> public DelegateAnnotation(Action<IRenderContext> rendering) { this.Rendering = rendering; } /// <summary> /// Gets the rendering delegate. /// </summary> /// <value> /// The rendering. /// </value> public Action<IRenderContext> Rendering { get; private set; } /// <summary> /// Renders the annotation on the specified context. /// </summary> /// <param name="rc">The render context.</param> public override void Render(IRenderContext rc) { base.Render(rc); this.Rendering(rc); } /// <inheritdoc/> public override OxyRect GetClippingRect() { return OxyRect.Everything; } } }
------------------------------------
承接
**视觉检测软件开发及调试
**工业软件开发
**上位机软件开发
wechat:luoran2024
qq:565934058
email:taoyuansu@qq.com
海量教育资源及影视资源下载
微信公众号:EFun科技
------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!