using DevExpress.Utils; using DevExpress.XtraCharts; using Yw.WinFrmUI.Phart; namespace PBS.WinFrmUI.Hydro { public partial class SystemCurveChartCtrl : DevExpress.XtraEditors.XtraUserControl { public SystemCurveChartCtrl() { InitializeComponent(); this.layoutControl1.SetupLayoutControl(); this.gridView1.SetNormalView(); this.sidePanel1.Visible = false; InitialChart(); } public void InitialChart() { this.chartControl1.Legend.Direction = LegendDirection.LeftToRight; this.chartControl1.RuntimeHitTesting = true; _xyDiagram = this.chartControl1.Diagram as XYDiagram; _xyDiagramPane = _xyDiagram.DefaultPane; _seriesWaterPoint = this.chartControl1.GetSeriesByName("SeriesWaterPoint"); _seriesUpperPressure = this.chartControl1.GetSeriesByName("SeriesUpperPressure"); _seriesLowerPressure = this.chartControl1.GetSeriesByName("SeriesLowerPressure"); _seriesAveragePressure = this.chartControl1.GetSeriesByName("SeriesAveragePressure"); _constantLineDynamicPressure = _xyDiagram.AxisY.ConstantLines.GetElementByName("ConstantLineDynamicPressure") as ConstantLine; _constantLineStaticPressure = _xyDiagram.AxisY.ConstantLines.GetElementByName("ConstantLineStaticPressure") as ConstantLine; _seriesWaterPoint.LegendTextPattern = "用水点"; _seriesUpperPressure.LegendTextPattern = "压力-上限"; _seriesLowerPressure.LegendTextPattern = "压力-下限"; _seriesAveragePressure.LegendTextPattern = "压力-平均"; _seriesWaterPoint.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.False; _seriesUpperPressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; _seriesLowerPressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; _seriesAveragePressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; this.chartControl1.CrosshairOptions.ShowOnlyInFocusedPane = false; this.chartControl1.CrosshairOptions.GroupHeaderPattern = "{A:N2}"; this.chartControl1.CrosshairOptions.GroupHeaderTextOptions.EnableAntialiasing = DevExpress.Utils.DefaultBoolean.True; _seriesUpperPressure.CrosshairLabelPattern = "{V:N2}"; _seriesLowerPressure.CrosshairLabelPattern = "{V:N2}"; _seriesAveragePressure.CrosshairLabelPattern = "{V:N2}"; _constantLineDynamicPressure.ShowInLegend = false; _constantLineStaticPressure.ShowInLegend = false; _constantLineDynamicPressure.Title.Alignment = ConstantLineTitleAlignment.Far; _constantLineStaticPressure.Title.Alignment = ConstantLineTitleAlignment.Far; _constantLineDynamicPressure.LineStyle.Thickness = 2; _constantLineStaticPressure.LineStyle.Thickness = 2; _xyDiagram.EnableAxisXZooming = true; _xyDiagram.EnableAxisYZooming = true; _xyDiagram.EnableAxisXScrolling = true; _xyDiagram.EnableAxisYScrolling = true; } private XYDiagram _xyDiagram; private XYDiagramDefaultPane _xyDiagramPane; private Series _seriesWaterPoint; private Series _seriesUpperPressure; private Series _seriesLowerPressure; private Series _seriesAveragePressure; private ConstantLine _constantLineDynamicPressure; private ConstantLine _constantLineStaticPressure; /// /// 刷新数据事件 /// public event Action RefreshDataEvent; public event Action RefreshCurveEvent; /// /// 清空 /// public void Clear() { this.chartControl1.BeginInit(); _seriesWaterPoint.Points.Clear(); _seriesUpperPressure.Points.Clear(); _seriesLowerPressure.Points.Clear(); _seriesAveragePressure.Points.Clear(); this.chartControl1.CrosshairEnabled = DefaultBoolean.False; this.chartControl1.CrosshairOptions.ShowArgumentLine = false; _constantLineDynamicPressure.Visible = false; _constantLineStaticPressure.Visible = false; _xyDiagram.AxisX.Visibility = DefaultBoolean.False; _xyDiagram.AxisX.GridLines.Visible = false; _xyDiagram.AxisY.Visibility = DefaultBoolean.False; _xyDiagram.AxisY.GridLines.Visible = false; _xyDiagram.EnableAxisXZooming = false; _xyDiagram.EnableAxisYZooming = false; _xyDiagram.EnableAxisXScrolling = false; _xyDiagram.EnableAxisYScrolling = false; this.chartControl1.EndInit(); this.RefreshCurveEvent?.Invoke(null, null, null); } /// /// 绑定数据 /// public void SetBindingData(List waterPointCalcList) { if (waterPointCalcList == null || !waterPointCalcList.Any()) { Clear(); return; } this.chartControl1.BeginInit(); _xyDiagram.EnableAxisXZooming = true; _xyDiagram.EnableAxisYZooming = true; _xyDiagram.EnableAxisXScrolling = true; _xyDiagram.EnableAxisYScrolling = true; this.chartControl1.CrosshairOptions.ShowArgumentLine = true; _seriesWaterPoint.Points.Clear(); _seriesUpperPressure.Points.Clear(); _seriesLowerPressure.Points.Clear(); _seriesAveragePressure.Points.Clear(); _constantLineDynamicPressure.Visible = false; _constantLineStaticPressure.Visible = false; var upperPressurePtList = new List(); var lowerPressurePtList = new List(); var averagePressurePtList = new List(); var waterPointGroup = waterPointCalcList.GroupBy(x => Math.Round(x.TotalFlow, 1)); foreach (var item in waterPointGroup) { var x = item.Key; var yList = item.Select(x => x.EndPressure).OrderBy(x => x).ToList(); var yUpper = CalculatePercentile(yList, 0.95); var yLower = CalculatePercentile(yList, 0.05); var yNumList = yList.Where(x => x >= yLower && x <= yUpper); if (yNumList == null || !yNumList.Any()) { continue; } var yAverage = yNumList.Where(x => x >= yLower && x <= yUpper).Average(); upperPressurePtList.Add(new Yw.Geometry.Point2d(x, yUpper)); lowerPressurePtList.Add(new Yw.Geometry.Point2d(x, yLower)); averagePressurePtList.Add(new Yw.Geometry.Point2d(x, yAverage)); } if (averagePressurePtList.Count > 4) { var curveUpperPressure = new Yw.Ahart.CubicCurve(upperPressurePtList); var curveLowerPressure = new Yw.Ahart.CubicCurve(lowerPressurePtList); var curveAveragePressure = new Yw.Ahart.CubicCurve(averagePressurePtList); var upperPressureCurvePtList = curveUpperPressure.GetPointList(100); var lowerPressureCurvePtList = curveLowerPressure.GetPointList(100); var averagePressureCurvePtList = curveAveragePressure.GetPointList(100); foreach (var item in waterPointCalcList) { _seriesWaterPoint.Points.Add(new SeriesPoint(item.TotalFlow, item.EndPressure)); } foreach (var item in upperPressureCurvePtList) { _seriesUpperPressure.Points.Add(new SeriesPoint(item.X, item.Y)); } foreach (var item in lowerPressureCurvePtList) { _seriesLowerPressure.Points.Add(new SeriesPoint(item.X, item.Y)); } foreach (var item in averagePressureCurvePtList) { _seriesAveragePressure.Points.Add(new SeriesPoint(item.X, item.Y)); } this.RefreshCurveEvent?.Invoke(curveUpperPressure, curveLowerPressure, curveAveragePressure); } var minX = waterPointCalcList.Min(x => x.TotalFlow); var maxX = waterPointCalcList.Max(x => x.TotalFlow); var minY = waterPointCalcList.Min(x => x.EndPressure); var maxY = waterPointCalcList.Max(x => x.EndPressure); SetChartAxis(minX, maxX, minY, maxY); this.chartControl1.EndInit(); } //计算百分位数 private double CalculatePercentile(List sortedData, double percentile) { int n = sortedData.Count; double index = (n - 1) * percentile; int lower = (int)Math.Floor(index); int upper = (int)Math.Ceiling(index); double fraction = index - lower; return sortedData[lower] * (1 - fraction) + sortedData[upper] * fraction; } #region Set Axis /// /// 设置图表轴 /// private void SetChartAxis(double minX, double maxX, double minY, double maxY) { var coordinate = Yw.WinFrmUI.Phart.UniversalCoordinate.CalcCoordinate(minX, maxX, minY, maxY); if (coordinate == null) { _xyDiagram.AxisX.Visibility = DefaultBoolean.False; _xyDiagram.AxisX.GridLines.Visible = false; _xyDiagram.AxisY.Visibility = DefaultBoolean.False; _xyDiagram.AxisY.GridLines.Visible = false; return; } if (coordinate.CoordMinX + coordinate.CoordSpaceX * coordinate.GridNumberX < maxX * 1.05) coordinate.GridNumberX++; //计算刻度 X var axis_x_labels = new List(); var display_x = coordinate.CoordMinX; for (int i = 0; i < coordinate.GridNumberX + 1; i++) { axis_x_labels.Add(new CustomAxisLabel(display_x.ToString("N0"), display_x)); display_x = display_x + coordinate.CoordSpaceX; } _xyDiagram.AxisX.CustomLabels.Clear(); _xyDiagram.AxisX.CustomLabels.AddRange(axis_x_labels.ToArray()); _xyDiagram.AxisX.Visibility = DefaultBoolean.True; _xyDiagram.AxisX.GridLines.Visible = true; //计算刻度 Y var axis_y_labels = new List(); var display_y = coordinate.CoordMinY + coordinate.CoordSpaceY * coordinate.StartLineNoY; for (int i = coordinate.StartLineNoY; i < coordinate.EndLineNoY + 1; i++) { axis_y_labels.Add(new CustomAxisLabel(display_y.ToString(), display_y)); display_y = display_y + coordinate.CoordSpaceY; } _xyDiagram.AxisY.CustomLabels.Clear(); _xyDiagram.AxisY.CustomLabels.AddRange(axis_y_labels.ToArray()); _xyDiagram.AxisY.Visibility = DefaultBoolean.True; _xyDiagram.AxisY.GridLines.Visible = true; _xyDiagram.AxisY.SetAxisRange(coordinate.CoordMinX, coordinate.DispMaxX()); _xyDiagram.AxisY.SetAxisRange(coordinate.DispMinY(), coordinate.DispMaxY()); } #endregion } }