using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace IStation.WinFrmUI.Curve { public partial class ImportCurveByPictureDlg : DevExpress.XtraBars.Ribbon.RibbonForm { public ImportCurveByPictureDlg() { InitializeComponent(); this.curvePictureBoxCtrl1.ReloadPickPointsEvent += CurvePictureBoxCtrl1_ReloadPickPointsEvent; this.curvePictureBoxCtrl1.ReloadBoundaryEvent += CurvePictureBoxCtrl1_ReloadBoundaryEvent; InitialPictureSizeMode(); } //初始化图片显示模式 private void InitialPictureSizeMode() { foreach (PictureBoxSizeMode sizeMode in Enum.GetValues(typeof(PictureBoxSizeMode))) { var barCheckItem = new DevExpress.XtraBars.BarCheckItem(); barCheckItem.Caption = sizeMode.ToString(); barCheckItem.Id = (int)sizeMode; barCheckItem.Name = $"barBtn{barCheckItem.Caption}"; barCheckItem.ItemClick += (object sender, DevExpress.XtraBars.ItemClickEventArgs e) => { foreach (DevExpress.XtraBars.BarCheckItemLink link in this.barSubPictureSizeMode.ItemLinks) { ((DevExpress.XtraBars.BarCheckItem)link.Item).Checked = false; } var clickItem = (DevExpress.XtraBars.BarCheckItem)e.Item; clickItem.Checked = true; this.barSubPictureSizeMode.Caption = sizeMode.ToString(); this.curvePictureBoxCtrl1.SetPictureSizeMode(sizeMode); }; this.barSubPictureSizeMode.AddItem(barCheckItem); if (sizeMode == PictureBoxSizeMode.StretchImage) { barCheckItem.Checked = true; this.barSubPictureSizeMode.Caption = sizeMode.ToString(); this.curvePictureBoxCtrl1.SetPictureSizeMode(sizeMode); } } } private enum eCurveGetWay { [Display(Name = "全部")] All, [Display(Name = "流量扬程/功率,分析效率")] QhQpAnaQe, [Display(Name = "流量扬程/效率,分析功率")] QhQeAnaQp, [Display(Name = "仅流量扬程线")] OnlyQh } private eCurveGetWay _curveGetWay = eCurveGetWay.All; private Model.eFeatCurveType _curveType = Model.eFeatCurveType.QH; private List _picQHPoints = null; private List _picQPPoints = null; private List _picQEPoints = null; private Model.eCurveFitType _fitTypeQH, _fitTypeQP, _fitTypeQE; private Rectangle? _rectQH, _rectQP, _rectQE; public event Func ReloadFeatCurveDataEvent; /// /// 初始化数据 /// public void SetBindingData() { this.repimgCmbGetWay.AddEnum(typeof(eCurveGetWay), false); this.barEditImgCmbGetWay.EditValue = _curveGetWay; this.repimgCmbSourceFrom.AddEnum(typeof(Model.eCurveSourceFrom), false); this.barEditImgCmbSourceFrom.EditValue = Model.eCurveSourceFrom.厂家提供; this.repImgCmbUnitQ.AddEnum(typeof(Unit.eUnitQ), false); this.barEditImgCmbUnitQ.EditValue = this.curvePictureBoxCtrl1.UnitQ; this.imgCmbQHFitType.Properties.AddEnum(typeof(Model.eCurveFitType), false); this.imgCmbQHFitType.EditValue = Model.eCurveFitType.CubicCurve; this.imgCmbQPFitType.Properties.AddEnum(typeof(Model.eCurveFitType), false); this.imgCmbQPFitType.EditValue = Model.eCurveFitType.CubicCurve; this.imgCmbQEFitType.Properties.AddEnum(typeof(Model.eCurveFitType), false); this.imgCmbQEFitType.EditValue = Model.eCurveFitType.CubicCurve; } //曲线获取方法 private void repimgCmbGetWay_SelectedValueChanged(object sender, EventArgs e) { _curveGetWay = (eCurveGetWay)this.barEditImgCmbGetWay.EditValue; switch (_curveGetWay) { case eCurveGetWay.QhQpAnaQe: { _rectQE = null; _picQEPoints = null; this.layoutControlGroupQH.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQP.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQE.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never; } break; case eCurveGetWay.QhQeAnaQp: { _rectQP = null; _picQPPoints = null; this.layoutControlGroupQH.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQP.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never; this.layoutControlGroupQE.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; } break; case eCurveGetWay.OnlyQh: { _rectQE = null; _rectQP = null; _picQPPoints = null; _picQEPoints = null; this.layoutControlGroupQH.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQP.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never; this.layoutControlGroupQE.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never; } break; case eCurveGetWay.All: { this.layoutControlGroupQH.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQP.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; this.layoutControlGroupQE.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Always; } break; } } //流量单位变换 private void repImgCmbUnitQ_SelectedValueChanged(object sender, EventArgs e) { this.curvePictureBoxCtrl1.UnitQ = (Unit.eUnitQ)this.barEditImgCmbUnitQ.EditValue; } //导入图片 private void barBtnImportPicture_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { var dlg = new OpenFileDialog(); dlg.Filter = "*.BMP;*.JPG;*.GIF;*.PNG|*.BMP;*.JPG;*.GIF;*.PNG"; if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; this.curvePictureBoxCtrl1.SetBindingData(dlg.FileName); this.curvePictureBoxCtrl1.Enabled = true; } //框选坐标 private void barBtnSetCoordinates_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.curvePictureBoxCtrl1.StartSelectionRange(); this.barCekPickPoint.Checked = false; } //坐标框选完成 private void CurvePictureBoxCtrl1_ReloadBoundaryEvent(System.Drawing.Rectangle? obj) { switch (_curveType) { case Model.eFeatCurveType.QH: _rectQH = obj; break; case Model.eFeatCurveType.QE: _rectQE = obj; break; case Model.eFeatCurveType.QP: _rectQP = obj; break; } } //抓取点 private void barCekPickPoint_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (this.barCekPickPoint.Checked) { if (!ReloadChartCoordinate()) { this.barCekPickPoint.Checked = false; XtraMessageBox.Show("请输入坐标!"); return; } this.curvePictureBoxCtrl1.StartPickPoint(); } else { this.curvePictureBoxCtrl1.EndPickPoint(); } } //刷新图表坐标 private bool ReloadChartCoordinate() { if (this.barEditTxtMinQ.EditValue == null || this.barEditTxtMaxQ.EditValue == null) return false; this.curvePictureBoxCtrl1.ChartMinX = Convert.ToDouble(this.barEditTxtMinQ.EditValue); this.curvePictureBoxCtrl1.ChartMaxX = Convert.ToDouble(this.barEditTxtMaxQ.EditValue); switch (_curveType) { case Model.eFeatCurveType.QH: { if (this.txtMaxH.EditValue == null || this.txtMinH.EditValue == null) { return false; } this.curvePictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxH.EditValue); this.curvePictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinH.EditValue); } break; case Model.eFeatCurveType.QE: { if (this.txtMaxE.EditValue == null || this.txtMinE.EditValue == null) { return false; } this.curvePictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxE.EditValue); this.curvePictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinE.EditValue); } break; case Model.eFeatCurveType.QP: { if (this.txtMaxP.EditValue == null || this.txtMinP.EditValue == null) { return false; } this.curvePictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxP.EditValue); this.curvePictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinP.EditValue); } break; } return true; } //清空点 private void barBtnClear_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.curvePictureBoxCtrl1.ClearPickPoint(); } //预览曲线 private void barBtnPreviewCurve_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (!GetCurve(out Model.FeatCurvePointGroup featCurvePointGroup, out Model.FeatCurveExpressGroup featCurveExpressGroup)) return; var dlg = new PreviewCurveDlg(); dlg.SetBindingData(featCurveExpressGroup); dlg.ShowDialog(); } //选择曲线变换时 private void tabbedControlGroup1_SelectedPageChanging(object sender, DevExpress.XtraLayout.LayoutTabPageChangingEventArgs e) { this.curvePictureBoxCtrl1.GetPicPoints(out List clickPoints); if (e.PrevPage == this.layoutControlGroupQH) { _picQHPoints = clickPoints; } else if (e.PrevPage == this.layoutControlGroupQP) { _picQPPoints = clickPoints; } else if (e.PrevPage == this.layoutControlGroupQE) { _picQEPoints = clickPoints; } } //选择曲线变换 private void tabbedControlGroup1_SelectedPageChanged(object sender, DevExpress.XtraLayout.LayoutTabPageChangedEventArgs e) { this.barCekPickPoint.Checked = false; if (e.Page == this.layoutControlGroupQH) { _curveType = Model.eFeatCurveType.QH; ReloadChartCoordinate(); this.curvePictureBoxCtrl1.CurrentCaptureCruve = Model.eFeatCurveType.QH; this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQH; this.curvePictureBoxCtrl1.RefreshPictureShape(_picQHPoints, _rectQH); } else if (e.Page == this.layoutControlGroupQP) { _curveType = Model.eFeatCurveType.QP; ReloadChartCoordinate(); this.curvePictureBoxCtrl1.CurrentCaptureCruve = Model.eFeatCurveType.QP; this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQP; this.curvePictureBoxCtrl1.RefreshPictureShape(_picQPPoints, _rectQP); } else if (e.Page == this.layoutControlGroupQE) { _curveType = Model.eFeatCurveType.QE; ReloadChartCoordinate(); this.curvePictureBoxCtrl1.CurrentCaptureCruve = Model.eFeatCurveType.QE; this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQE; this.curvePictureBoxCtrl1.RefreshPictureShape(_picQEPoints, _rectQE); } } //打点等效线 private void cekCaputueEtaPtInEqupCurve_CheckedChanged(object sender, EventArgs e) { this.curvePictureBoxCtrl1.IsCaputueEtaPtInEqupCurve = this.cekCaputueEtaPtInEqupCurve.Checked; } //打点更新数据 private void CurvePictureBoxCtrl1_ReloadPickPointsEvent(List list) { switch (_curveType) { case Model.eFeatCurveType.QH: _picQHPoints = list; break; case Model.eFeatCurveType.QE: _picQEPoints = list; break; case Model.eFeatCurveType.QP: _picQPPoints = list; break; } } #region 拟合方式下拉变换 private void imgCmbQHFitType_SelectedValueChanged(object sender, EventArgs e) { this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQH = (Model.eCurveFitType)this.imgCmbQHFitType.EditValue; } private void imgCmbQPFitType_SelectedValueChanged(object sender, EventArgs e) { this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQP = (Model.eCurveFitType)this.imgCmbQPFitType.EditValue; } private void imgCmbQEFitType_SelectedValueChanged(object sender, EventArgs e) { this.curvePictureBoxCtrl1.CurrentCaptureCruveFitType = _fitTypeQE = (Model.eCurveFitType)this.imgCmbQEFitType.EditValue; } #endregion //保存 private void barBtnSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (this.ReloadFeatCurveDataEvent == null) { XtraMessageBox.Show("未注册保存事件!"); } if (!GetCurve(out Model.FeatCurvePointGroup featCurvePointGroup, out Model.FeatCurveExpressGroup featCurveExpressGroup)) { XtraMessageBox.Show("请检查数据!"); return; } if (XtraMessageBox.Show($"确认保存当前曲线?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) != DialogResult.OK) return; if (this.barEditTxtCurveCode.EditValue == null) { XtraMessageBox.Show("请输入曲线编码!"); return; } var code = this.barEditTxtCurveCode.EditValue.ToString(); var sourceFrom = (Model.eCurveSourceFrom)this.barEditImgCmbSourceFrom.EditValue; var bol = this.ReloadFeatCurveDataEvent.Invoke(code, sourceFrom, featCurveExpressGroup); if (!bol) { XtraMessageBox.Show("保存失败!"); return; } XtraMessageBox.Show("保存成功!"); this.DialogResult = DialogResult.OK; this.Close(); } #region 方法 //获取曲线 private bool GetCurve(out Model.FeatCurvePointGroup featCurvePointGroup, out Model.FeatCurveExpressGroup featCurveExpressGroup) { featCurvePointGroup = null; featCurveExpressGroup = null; switch (_curveGetWay) { case eCurveGetWay.All: { if (_picQHPoints == null || _picQHPoints.Count < 4) { XtraMessageBox.Show("请录入流量扬程点!"); return false; } if (_picQPPoints == null || _picQPPoints.Count < 4) { XtraMessageBox.Show("请录入流量功率点!"); return false; } if (_picQEPoints == null || _picQEPoints.Count < 4) { XtraMessageBox.Show("请录入流量效率点!"); return false; } } break; case eCurveGetWay.QhQpAnaQe: { if (_picQHPoints == null || _picQHPoints.Count < 4) { XtraMessageBox.Show("请录入流量扬程点!"); return false; } if (_picQPPoints == null || _picQPPoints.Count < 4) { XtraMessageBox.Show("请录入流量功率点!"); return false; } } break; case eCurveGetWay.QhQeAnaQp: { if (_picQHPoints == null || _picQHPoints.Count < 4) { XtraMessageBox.Show("请录入流量扬程点!"); return false; } if (_picQEPoints == null || _picQEPoints.Count < 4) { XtraMessageBox.Show("请录入流量效率点!"); return false; } } break; case eCurveGetWay.OnlyQh: { if (_picQHPoints == null || _picQHPoints.Count < 4) { XtraMessageBox.Show("请录入流量扬程点!"); return false; } } break; default: break; } var fitTypeQH = (Model.eCurveFitType)this.imgCmbQHFitType.EditValue; var fitTypeQP = (Model.eCurveFitType)this.imgCmbQPFitType.EditValue; var fitTypeQE = (Model.eCurveFitType)this.imgCmbQEFitType.EditValue; var curvePointsQH = new List(); var curvePointsQE = new List(); var curvePointsQP = new List(); var picPointsQH = new List(); var picPointsQE = new List(); var picPointsQP = new List(); var unitQ = this.curvePictureBoxCtrl1.UnitQ; double MinQ = 0; double MaxQ = 0; if (this.curvePictureBoxCtrl1.ChartMinX == 0) MinQ = 0; else MinQ = _picQHPoints.Min(x => x.X); MaxQ = _picQHPoints.Max(x => x.X); //换算单位 MinQ = Unit.UnitQHelper.Convert(unitQ, Unit.eUnitQ.M3H, MinQ); MaxQ = Unit.UnitQHelper.Convert(unitQ, Unit.eUnitQ.M3H, MaxQ); picPointsQH = ToM3H(unitQ, _picQHPoints); picPointsQE = ToM3H(unitQ, _picQEPoints); picPointsQP = ToM3H(unitQ, _picQPPoints); int insert_num = 15; double space = (MaxQ - MinQ) / (insert_num - 1); int i = 0; double Q = MinQ; double H, E = 0, P = 0; for (i = 1; i < insert_num - 1; i++) { Q = Q + space; H = Model.FitCurveHelper.GetFitPointY(picPointsQH, fitTypeQH, Q); curvePointsQH.Add(new Model.CurvePoint(Q, H)); if (_curveGetWay != eCurveGetWay.OnlyQh) { switch (_curveGetWay) { case eCurveGetWay.All: { P = Model.FitCurveHelper.GetFitPointY(picPointsQP, fitTypeQP, Q); E = Model.FitCurveHelper.GetFitPointY(picPointsQE, fitTypeQE, Q); } break; case eCurveGetWay.QhQpAnaQe: { P = Model.FitCurveHelper.GetFitPointY(picPointsQP, fitTypeQP, Q); E = Model.CurveCalcuHelper.CalculateE(Q, H, P); } break; case eCurveGetWay.QhQeAnaQp: { E = Model.FitCurveHelper.GetFitPointY(picPointsQE, fitTypeQE, Q); P = Model.CurveCalcuHelper.CalculateP(Q, H, E); } break; } curvePointsQP.Add(new Model.CurvePoint(Q, P)); curvePointsQE.Add(new Model.CurvePoint(Q, E)); } } if (_curveGetWay == eCurveGetWay.OnlyQh) { if (curvePointsQH.Count < 3) { XtraMessageBox.Show("未导入足够多的性能曲线点"); return false; } } else { if (curvePointsQH.Count < 3 || curvePointsQE.Count < 3 || curvePointsQP.Count < 3) { curvePointsQH = null; curvePointsQE = null; curvePointsQP = null; XtraMessageBox.Show("未导入足够多的性能曲线点"); return false; } } #region 首尾两点的处理:因为首尾2点按流量扬程获取范围,而点击不一定正好首尾2点流量一样 //流量扬程首尾两点 double startH = Model.CurveLineHelper.GetYbyX(curvePointsQH[0].X, curvePointsQH[0].Y, curvePointsQH[1].X, curvePointsQH[1].Y, MinQ); curvePointsQH.Insert(0, new Model.CurvePoint(MinQ, startH)); int point_num = curvePointsQH.Count;//不一定和insert_num一样 double endH = Model.CurveLineHelper.GetYbyX(curvePointsQH[point_num - 2].X, curvePointsQH[point_num - 2].Y, curvePointsQH[point_num - 1].X, curvePointsQH[point_num - 1].Y, MaxQ); curvePointsQH.Add(new Model.CurvePoint(MaxQ, endH)); if (curvePointsQE != null && curvePointsQE.Count > 0) { //流量效率首尾两点 double startE = 0;//起始点 if (MinQ > 0.2) startE = Model.CurveLineHelper.GetYbyX(curvePointsQE[0].X, curvePointsQE[0].Y, curvePointsQE[1].X, curvePointsQE[1].Y, MinQ); else startE = 0; curvePointsQE.Insert(0, new Model.CurvePoint(MinQ, startE)); point_num = curvePointsQE.Count;//末尾点 double endE = Model.CurveLineHelper.GetYbyX(curvePointsQE[point_num - 2].X, curvePointsQE[point_num - 2].Y, curvePointsQE[point_num - 1].X, curvePointsQE[point_num - 1].Y, MaxQ); curvePointsQE.Add(new Model.CurvePoint(MaxQ, endE)); } if (curvePointsQP != null && curvePointsQP.Count > 0) { //流量功率首尾两点 double startP = Model.CurveLineHelper.GetYbyX(curvePointsQP[0].X, curvePointsQP[0].Y, curvePointsQP[1].X, curvePointsQP[1].Y, MinQ); curvePointsQP.Insert(0, new Model.CurvePoint(MinQ, startP)); point_num = curvePointsQP.Count; double endP = Model.CurveLineHelper.GetYbyX(curvePointsQP[point_num - 2].X, curvePointsQP[point_num - 2].Y, curvePointsQP[point_num - 1].X, curvePointsQP[point_num - 1].Y, MaxQ); curvePointsQP.Add(new Model.CurvePoint(MaxQ, endP)); } #endregion //圆整 curvePointsQH = Regulate(curvePointsQH, 2); curvePointsQE = Regulate(curvePointsQE, 2); curvePointsQP = Regulate(curvePointsQP, 2); featCurvePointGroup = new Model.FeatCurvePointGroup(); featCurvePointGroup.PointQH = curvePointsQH; featCurvePointGroup.PointQE = curvePointsQE; featCurvePointGroup.PointQP = curvePointsQP; featCurveExpressGroup = new Model.FeatCurveExpressGroup(); featCurveExpressGroup.CurveQH = new Model.CurveExpress(curvePointsQH, fitTypeQH, true); featCurveExpressGroup.CurveQE = new Model.CurveExpress(curvePointsQE, fitTypeQE, true); featCurveExpressGroup.CurveQP = new Model.CurveExpress(curvePointsQP, fitTypeQP, true); return true; } //单位换算 private List ToM3H(Unit.eUnitQ unit, List points) { if (unit == Unit.eUnitQ.M3H) { return points; } if (points == null) { return null; } var list = new List(); for (int i = 0; i < points.Count; i++) { var point = new Model.CurvePoint(points[i]); point.X = Unit.UnitQHelper.Convert(unit, Unit.eUnitQ.M3H, point.X); list.Add(point); } return list; } //四舍五入圆整,如 0.44 -> 0.4 , 0.46 -> 0.5//flag--小数点后位数 public static List Regulate(List inPoints, int flag) { if (inPoints == null) return null; List outPoints = new List(); for (int i = 0; i < inPoints.Count(); i++) { outPoints.Add(new Model.CurvePoint(Regulate(inPoints[i].X, flag), Regulate(inPoints[i].Y, flag))); } return outPoints; } //四舍五入圆整,如 0.44 -> 0.4 , 0.46 -> 0.5//flag--小数点后位数 public static double Regulate(double v, int flag) { bool isNegative = false; //如果是负数 if (v < 0) { isNegative = true; v = Math.Abs(v); } else { isNegative = false; } double value = Math.Round(v, flag); if (isNegative) { value = -value; } return value; } #endregion } }