using DevExpress.XtraCharts; using DevExpress.XtraEditors; using IStation.WinFrmUI.Curve; using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace IStation.WinFrmUI.Monitor { public partial class CurveAnalyzePacketMgrPage : DocumentPage { public CurveAnalyzePacketMgrPage() { InitializeComponent(); this.PageTitle.Caption = "曲线分析"; this.repCmbCurveFitType.Items.Add("二次拟合", 1, -1); this.repCmbCurveFitType.Items.Add("三次拟合", 0, -1); this.repCmbCurveFitType.Items.Add("四次拟合", 4, -1); this.repCmbCurveType.Items.Add("流量扬程", 1, -1); this.repCmbCurveType.Items.Add("流量功率", 3, -1); this.repCmbCurveType.Items.Add("流量效率", 2, -1); _boxSelHelper = new ChartBoxSelHelper(this.chartControl1); _boxSelHelper.BoxSelCompletedEvent += _boxSelHelper_BoxSelCompletedEvent; this.chartControl1.RuntimeHitTesting = true; } #region ViewModel 暂时无用 private class FeatCurveExpressGroupEx : Model.FeatCurveExpressGroup { public FeatCurveExpressGroupEx() { } public FeatCurveExpressGroupEx(string dsString) : base(dsString) { this.IsEmpty = string.IsNullOrEmpty(dsString); if (this.IsEmpty) return; if (this.CurveQH != null) FitTypeQH = this.CurveQH.FitType; if (this.CurveQE != null) FitTypeQE = this.CurveQE.FitType; if (this.CurveQP != null) FitTypeQP = this.CurveQP.FitType; } public bool IsEmpty { get; set; } public IStation.Model.eCurveFitType FitTypeQH = Model.eCurveFitType.CubicCurve; public IStation.Model.eCurveFitType FitTypeQE = Model.eCurveFitType.CubicCurve; public IStation.Model.eCurveFitType FitTypeQP = Model.eCurveFitType.CubicCurve; public void SetPickSelPoint(Model.eFeatCurveType currentCurveType, List points) { if (currentCurveType == Model.eFeatCurveType.QH) { this.CurveQH = new Model.CurveExpress(points, FitTypeQH, true); this.PointMethodQH = Model.eCurveFitPointMethod.ManuPick; } if (currentCurveType == Model.eFeatCurveType.QE) { this.CurveQE = new Model.CurveExpress(points, FitTypeQE, true); this.PointMethodQE = Model.eCurveFitPointMethod.ManuPick; } if (currentCurveType == Model.eFeatCurveType.QP) { this.CurveQP = new Model.CurveExpress(points, FitTypeQP, true); this.PointMethodQP = Model.eCurveFitPointMethod.ManuPick; } } public void SetBoxSelPoint(Model.eFeatCurveType currentCurveType, List points) { if (currentCurveType == Model.eFeatCurveType.QH) { this.CurveQH = new Model.CurveExpress(points, FitTypeQH, true); this.PointMethodQH = Model.eCurveFitPointMethod.ManuBox; } if (currentCurveType == Model.eFeatCurveType.QE) { this.CurveQE = new Model.CurveExpress(points, FitTypeQE, true); this.PointMethodQE = Model.eCurveFitPointMethod.ManuBox; } if (currentCurveType == Model.eFeatCurveType.QP) { this.CurveQP = new Model.CurveExpress(points, FitTypeQP, true); this.PointMethodQP = Model.eCurveFitPointMethod.ManuBox; } } //拟合线 public List GetFitCurvePointInfo(Model.eFeatCurveType currentCurveType, List _allAnaPoints) { if (_allAnaPoints == null || _allAnaPoints.Count < 4) return null; switch (currentCurveType) { case Model.eFeatCurveType.QH: { if (this.CurveQH != null && this.CurveQH.DefinePoints != null) { if (this.PointMethodQH == Model.eCurveFitPointMethod.ManuPick || this.PointMethodQH == Model.eCurveFitPointMethod.ManuBox) return Model.FitCurveHelper.GetFitPoints(this.CurveQH.DefinePoints, this.FitTypeQH, 10); } var allPoints = _allAnaPoints.Select(x => new Model.CurvePoint(x.Q, x.H)).ToList(); var points = Model.FitCurveHelper.GetFitPoints(allPoints, this.FitTypeQH, 10); this.CurveQH = new Model.CurveExpress(points, this.FitTypeQH); return points; } case Model.eFeatCurveType.QE: { if (this.CurveQE != null && this.CurveQE.DefinePoints != null) { if (this.PointMethodQE == Model.eCurveFitPointMethod.ManuPick || this.PointMethodQE == Model.eCurveFitPointMethod.ManuBox) return Model.FitCurveHelper.GetFitPoints(this.CurveQE.DefinePoints, this.FitTypeQE, 10); if (this.PointMethodQE == Model.eCurveFitPointMethod.QHEP) return Model.FitCurveHelper.GetFitPoints(this.CurveQE.DefinePoints, this.FitTypeQE, 10); } var allPoints = _allAnaPoints.Select(x => new Model.CurvePoint(x.Q, x.E)).ToList(); var points = Model.FitCurveHelper.GetFitPoints(allPoints, this.FitTypeQE, 10); this.CurveQE = new Model.CurveExpress(points, this.FitTypeQE); return points; } case Model.eFeatCurveType.QP: { if (this.CurveQP != null && this.CurveQP.DefinePoints != null) { if (this.PointMethodQP == Model.eCurveFitPointMethod.ManuPick || this.PointMethodQP == Model.eCurveFitPointMethod.ManuBox) return Model.FitCurveHelper.GetFitPoints(this.CurveQP.DefinePoints, this.FitTypeQP, 10); if (this.PointMethodQP == Model.eCurveFitPointMethod.QHEP) return Model.FitCurveHelper.GetFitPoints(this.CurveQP.DefinePoints, this.FitTypeQP, 10); } var allPoints = _allAnaPoints.Select(x => new Model.CurvePoint(x.Q, x.P)).ToList(); var points = Model.FitCurveHelper.GetFitPoints(allPoints, this.FitTypeQP, 10); this.CurveQP = new Model.CurveExpress(points, this.FitTypeQP); return points; } } return null; } } #endregion public event Action UpdatePacketEvent; private List _allValidBindingList = null; private Model.eFeatCurveType _curveType = Model.eFeatCurveType.QH; private List _fitCurvePoints = null; private FeatCurveExpressGroupEx _curveInfo = null; private BLL.CurveAnalyzePoint _bllPoint = new BLL.CurveAnalyzePoint(); //图 #region Chart private XYDiagram _diagram = null; private Series _seriesCurve, _seriesCurvePoint, _seriesReferenceCurve; private AxisX _axisX = null; private AxisY _axisY = null; #endregion private ChartBoxSelHelper _boxSelHelper = null;//框选辅助类 private long _monitorDataSourcesId, _curveAnalyzeId, _curveAnalyzePacketId; /// /// 初始化 /// public void Initial(long monitorDataSourcesId, long curveAnalyzeId, long curveAnalyzePacketId, string curveInfo) { _monitorDataSourcesId = monitorDataSourcesId; _curveAnalyzeId = curveAnalyzeId; _curveAnalyzePacketId = curveAnalyzePacketId; _curveInfo = new FeatCurveExpressGroupEx(curveInfo); _diagram = this.chartControl1.Diagram as XYDiagram; _axisX = _diagram.AxisX; _axisY = _diagram.AxisY; //_axisX.WholeRange.SideMarginsValue = 0; //_axisX.VisualRange.SideMarginsValue = 0; //_axisY.WholeRange.SideMarginsValue = 0; //_axisY.VisualRange.SideMarginsValue = 0; _seriesCurve = this.chartControl1.GetSeriesByName("SeriesCurve"); _seriesCurve.Visible = this.barCekFitCurve.Checked; _seriesCurvePoint = this.chartControl1.GetSeriesByName("SeriesCurvePoint"); _seriesReferenceCurve = this.chartControl1.GetSeriesByName("SeriesReferenceCurve"); this.barEditCurveType.EditValue = (int)Model.eFeatCurveType.QH; this.barEditCurveFitType.EditValue = _curveInfo.IsEmpty ? (int)Model.eCurveFitType.CubicCurve : (int)_curveInfo.FitTypeQH; } /// /// 初始化数据 /// public override void InitialDataSource() { LoadCurveAnalyzePoints(_monitorDataSourcesId, _curveAnalyzeId, _curveAnalyzePacketId); LoadCurvePoints(_curveType, _allValidBindingList); } //加载数据 private void LoadCurveAnalyzePoints(long monitorDataSourcesId, long curveAnalyzeId, long curveAnalyzePacketId) { var lays = this.chartControl1.ShowOverlay(); _allValidBindingList = _bllPoint.GetValid(monitorDataSourcesId, curveAnalyzeId, curveAnalyzePacketId); if (_allValidBindingList == null) _allValidBindingList = new List(); lays.Close(); } //曲线类型变换 private void barEditCurveType_EditValueChanged(object sender, EventArgs e) { _curveType = (Model.eFeatCurveType)this.barEditCurveType.EditValue; LoadCurvePoints(_curveType, _allValidBindingList); } //拟合方式变换 private void barEditCurveFitType_EditValueChanged(object sender, EventArgs e) { var curveFitType = (Model.eCurveFitType)this.barEditCurveFitType.EditValue; LoadFeatCurve(_curveType, curveFitType, _allValidBindingList); } // 验证点 private bool Verify(List analyzePoints) { if (analyzePoints == null || !analyzePoints.Any()) { _seriesCurvePoint.Points.BeginUpdate(); _seriesCurvePoint.Points.Clear(); _seriesCurvePoint.Points.EndUpdate(); _fitCurvePoints = null; _seriesCurve.Points.BeginUpdate(); _seriesCurve.Points.Clear(); _seriesCurve.Points.EndUpdate(); return false; } return true; } // 加载点 private void LoadCurvePoints(Model.eFeatCurveType curveType, List analyzePoints) { if (!Verify(analyzePoints)) return; Model.eCurveFitType curveFitType = Model.eCurveFitType.CubicCurve; double minX = analyzePoints.Min(x => x.Q); double maxX = analyzePoints.Max(x => x.Q); double minY = 0, maxY = 100; string axisYTitle = "扬程(m)"; _seriesCurvePoint.Points.BeginUpdate(); switch (curveType) { case Model.eFeatCurveType.QH: { _seriesCurvePoint.BindToData(analyzePoints, "Q", "H"); _seriesCurvePoint.CrosshairLabelPattern = "流量:{A:N0} 扬程:{V:N1}"; _seriesCurvePoint.View.Color = CurveChartDisplay.PointColorQH; minY = analyzePoints.Min(x => x.H); maxY = analyzePoints.Max(x => x.H); curveFitType = _curveInfo.FitTypeQH; } break; case Model.eFeatCurveType.QE: { axisYTitle = "效率(%)"; _seriesCurvePoint.BindToData(analyzePoints, "Q", "E"); _seriesCurvePoint.CrosshairLabelPattern = "流量:{A:N0} 效率:{V:N1}"; _seriesCurvePoint.View.Color = CurveChartDisplay.PointColorQE; minY = analyzePoints.Min(x => x.E); maxY = analyzePoints.Max(x => x.E); curveFitType = _curveInfo.FitTypeQE; } break; case Model.eFeatCurveType.QP: { axisYTitle = "功率(kw)"; _seriesCurvePoint.BindToData(analyzePoints, "Q", "P"); _seriesCurvePoint.CrosshairLabelPattern = "流量:{A:N0} 功率:{V:N0}"; _seriesCurvePoint.View.Color = CurveChartDisplay.PointColorQP; minY = analyzePoints.Min(x => x.P); maxY = analyzePoints.Max(x => x.P); curveFitType = _curveInfo.FitTypeQP; } break; default: break; } _seriesCurvePoint.Points.EndUpdate(); this.chartControl1.BeginInit(); minX *= 0.95; maxX *= 1.05; minY *= 0.95; maxY *= 1.05; minX = Math.Round(minX); maxX = Math.Floor(maxX); minY = Math.Round(minY); maxY = Math.Floor(maxY); _axisX.WholeRange.SetMinMaxValues(minX, maxX); _axisX.VisualRange.SetMinMaxValues(minX, maxX); _axisY.WholeRange.SetMinMaxValues(minY, maxY); _axisY.VisualRange.SetMinMaxValues(minY, maxY); _axisY.Title.Text = axisYTitle; this.chartControl1.EndInit(); var currentCurveFitType = this.barEditCurveFitType.EditValue; if (currentCurveFitType != null && (int)currentCurveFitType != (int)curveFitType) { this.barEditCurveFitType.EditValue = (int)curveFitType; } else { LoadFeatCurve(curveType, curveFitType, analyzePoints); } } //加载点 private void LoadFeatCurve(Model.eFeatCurveType curveType, Model.eCurveFitType curveFitType, List analyzePoints) { if (!Verify(analyzePoints)) return; switch (curveType) { case Model.eFeatCurveType.QH: { var curvePoints = analyzePoints.Select(x => new Model.CurvePoint(x.Q, x.H)).ToList(); _fitCurvePoints = Model.FitCurveHelper.GetFitPoints(curvePoints, curveFitType, 10); _curveInfo.FitTypeQH = curveFitType; } break; case Model.eFeatCurveType.QE: { var curvePoints = analyzePoints.Select(x => new Model.CurvePoint(x.Q, x.E)).ToList(); _fitCurvePoints = Model.FitCurveHelper.GetFitPoints(curvePoints, curveFitType, 10); _curveInfo.FitTypeQE = curveFitType; } break; case Model.eFeatCurveType.QP: { var curvePoints = analyzePoints.Select(x => new Model.CurvePoint(x.Q, x.P)).ToList(); _fitCurvePoints = Model.FitCurveHelper.GetFitPoints(curvePoints, curveFitType, 10); _curveInfo.FitTypeQP = curveFitType; } break; default: break; } _seriesCurve.Points.BeginUpdate(); _seriesCurve.BindToData(_fitCurvePoints, "X", "Y"); _seriesCurve.Points.EndUpdate(); } private void barBtnBoxSelect_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _diagram.EnableAxisXScrolling = false; _diagram.EnableAxisXZooming = false; _boxSelHelper.StartBoxSel(); } //框选结束 private void _boxSelHelper_BoxSelCompletedEvent(System.Windows.Forms.MouseEventArgs obj) { _diagram.EnableAxisXScrolling = true; _diagram.EnableAxisXZooming = true; var boxSelSeriesPoints = _boxSelHelper.CalcuNumericalSelSeriesPoints(new List() { _seriesCurvePoint }); if (boxSelSeriesPoints == null || boxSelSeriesPoints.Count < 1) { _boxSelHelper.CloseBoxSel(); } else { popMenu.ShowPopup(MousePosition); _boxSelPoints = boxSelSeriesPoints.Select(x => x.Tag as Model.CurveAnalyzePoint).ToList(); } } private void barBtnViewData_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_boxSelPoints == null || _boxSelPoints.Count < 1) return; var dlg = new BoxSelectPointsDlg(); dlg.Set(_boxSelPoints.ToList()); dlg.RemovePointEvent += (time) => { DeletePoints(new List() { time }); return true; }; dlg.ShowDialog(); } #region 删除点 private List _boxSelPoints = null; //框选删除 private void barBtnBoxDeletion_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _diagram.EnableAxisXScrolling = false; _diagram.EnableAxisXZooming = false; _boxSelHelper.StartBoxSel(); } //删除 private void barBtnDelete_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_boxSelPoints == null || _boxSelPoints.Count < 1) return; var timeList = _boxSelPoints.Select(x => x.Time).ToList(); DeletePoints(timeList); } //筛选删除 异常流量 private void barBtnAbnormalQ_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_allValidBindingList == null || !_allValidBindingList.Any()) { XtraMessageBox.Show("无数据!"); return; } var timeList = _allValidBindingList.Where(x => x.Q <= 0).Select(x => x.Time).ToList(); DeletePoints(timeList); } //筛选删除 异常功率 private void barBtnAbnormalP_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_allValidBindingList == null || !_allValidBindingList.Any()) { XtraMessageBox.Show("无数据!"); return; } var timeList = _allValidBindingList.Where(x => x.P == IStation.Error.Default).Select(x => x.Time).ToList(); DeletePoints(timeList); } //筛选删除 异常效率 private void barBtnAbnormalE_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_allValidBindingList == null || !_allValidBindingList.Any()) { XtraMessageBox.Show("无数据!"); return; } var timeList = _allValidBindingList.Where(x => x.E == IStation.Error.Default).Select(x => x.Time).ToList(); DeletePoints(timeList); } /// /// 删除点 /// private void DeletePoints(List timeList) { if (timeList == null || timeList.Count < 1) { XtraMessageBox.Show("无数据!"); return; } var lays = this.chartControl1.ShowOverlay(); timeList = timeList.OrderByDescending(x => x).ToList(); var result = _bllPoint.SetInvalid(_monitorDataSourcesId, _curveAnalyzeId, _curveAnalyzePacketId, timeList); if (!result) { lays.Close(); XtraMessageBox.Show("删除失败!"); return; } var minTime = timeList.Min(); var maxTime = timeList.Max(); var minIndex = _allValidBindingList.FindIndex(x => x.Time == minTime); var maxIndex = _allValidBindingList.FindIndex(x => x.Time == maxTime); var delIndex = 0; for (int i = maxIndex; i >= minIndex; i--) { var item = _allValidBindingList[i]; for (int j = delIndex; j < timeList.Count; j++) { var delItem = timeList[j]; if (item.Time == delItem) { _allValidBindingList.RemoveAt(i); delIndex = j++; break; } } } lays.Close(); LoadCurvePoints(_curveType, _allValidBindingList); lays.Close(); } //菜单关闭 private void popMenu_CloseUp(object sender, EventArgs e) { _boxSelPoints = null; _boxSelHelper?.CloseBoxSel(); } #endregion #region Menu //重置数据 private void barBtnRestore_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (XtraMessageBox.Show($"是否还原所有删除点并清空已有曲线?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) != DialogResult.OK) return; var bol = _bllPoint.Reset(_monitorDataSourcesId, _curveAnalyzeId, _curveAnalyzePacketId); if (!bol) { XtraMessageBox.Show("重置失败!"); return; } var bll = new BLL.CurveAnalyzePacket(); var analyzePacket = bll.GetByID(_monitorDataSourcesId, _curveAnalyzePacketId); analyzePacket.CurveInfo = string.Empty; if (bll.Update(_monitorDataSourcesId, analyzePacket)) { this?.UpdatePacketEvent.Invoke(); } LoadCurveAnalyzePoints(_monitorDataSourcesId, _curveAnalyzeId, _curveAnalyzePacketId); LoadCurvePoints(_curveType, _allValidBindingList); } //拟合曲线 private void barCekFitCurve_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _seriesCurve.Visible = this.barCekFitCurve.Checked; } //更新曲线信息 private void UpdateCurveInfo(List analyzePoints) { if (analyzePoints != null && analyzePoints.Count > 4) { var curvePointsQH = _allValidBindingList.Select(x => new Model.CurvePoint(x.Q, x.H)).ToList(); var fitPointsQH = Model.FitCurveHelper.GetFitPoints(curvePointsQH, _curveInfo.FitTypeQH, 10); _curveInfo.CurveQH = new Model.CurveExpress(fitPointsQH, _curveInfo.FitTypeQH); var curvePointsQE = _allValidBindingList.Select(x => new Model.CurvePoint(x.Q, x.E)).ToList(); var fitPointsQE = Model.FitCurveHelper.GetFitPoints(curvePointsQE, _curveInfo.FitTypeQE, 10); _curveInfo.CurveQE = new Model.CurveExpress(fitPointsQE, _curveInfo.FitTypeQE); var curvePointsQP = _allValidBindingList.Select(x => new Model.CurvePoint(x.Q, x.P)).ToList(); var fitPointsQP = Model.FitCurveHelper.GetFitPoints(curvePointsQP, _curveInfo.FitTypeQP, 10); _curveInfo.CurveQP = new Model.CurveExpress(fitPointsQP, _curveInfo.FitTypeQP); _curveInfo.IsEmpty = false; } else { _curveInfo.IsEmpty = true; } } //预览 private void barBtnPreview_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { UpdateCurveInfo(_allValidBindingList); var dlg = new PreviewCurveDlg(); dlg.SetBindingData(_curveInfo); dlg.ShowDialog(); } //保存 private void barBtnSaveCurve_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { UpdateCurveInfo(_allValidBindingList); var bll = new BLL.CurveAnalyzePacket(); var analyzePacket = bll.GetByID(_monitorDataSourcesId, _curveAnalyzePacketId); analyzePacket.CurveInfo = _curveInfo.IsEmpty ? string.Empty : _curveInfo.ToDsString(); var bol = bll.Update(_monitorDataSourcesId, analyzePacket); if (!bol) { XtraMessageBox.Show("保存失败!"); return; } this?.UpdatePacketEvent.Invoke(); XtraMessageBox.Show("保存成功!"); } // 刷新数据 private void barBtnRefresh_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { InitialDataSource(); } #endregion } }