using DevExpress.XtraEditors; using System.ComponentModel.DataAnnotations; using Yw.Geometry; namespace Yw.WinFrmUI.Phart { public partial class PumpImportByPictureCtrl : XtraUserControl { public PumpImportByPictureCtrl() { InitializeComponent(); this.pumpPictureBoxCtrl1.ReloadPickPointsEvent += CurvePictureBoxCtrl1_ReloadPickPointsEvent; this.pumpPictureBoxCtrl1.ReloadBoundaryEvent += CurvePictureBoxCtrl1_ReloadBoundaryEvent; InitialPictureSizeMode(); SetBindingData(); } //初始化图片显示模式 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.pumpPictureBoxCtrl1.SetPictureSizeMode(sizeMode); }; this.barSubPictureSizeMode.AddItem(barCheckItem); if (sizeMode == PictureBoxSizeMode.StretchImage) { barCheckItem.Checked = true; this.barSubPictureSizeMode.Caption = sizeMode.ToString(); this.pumpPictureBoxCtrl1.SetPictureSizeMode(sizeMode); } } } private enum eCurveGetWay { [Display(Name = "全部")] All, [Display(Name = "流量扬程/功率,分析效率")] QhQpAnaQe, [Display(Name = "流量扬程/效率,分析功率")] QhQeAnaQp, [Display(Name = "仅流量扬程线")] OnlyQh } private eCurveGetWay _curveGetWay = eCurveGetWay.All; private Yw.Ahart.eCurveType _curveType = Yw.Ahart.eCurveType.QH; private List _picQHPoints = null; private List _picQPPoints = null; private List _picQEPoints = null; private Rectangle? _rectQH, _rectQP, _rectQE; /// /// 初始化数据 /// public void SetBindingData() { this.repimgCmbGetWay.AddEnum(typeof(eCurveGetWay), false); this.barEditImgCmbGetWay.EditValue = _curveGetWay; this.repImgCmbUnitQ.AddEnum(typeof(Unit.eUnitQ), false); this.barEditImgCmbUnitQ.EditValue = this.pumpPictureBoxCtrl1.UnitQ; } //曲线获取方法 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.pumpPictureBoxCtrl1.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.pumpPictureBoxCtrl1.SetBindingData(dlg.FileName); this.pumpPictureBoxCtrl1.Enabled = true; } //框选坐标 private void barBtnSetCoordinates_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.pumpPictureBoxCtrl1.StartSelectionRange(); this.barCekPickPoint.Checked = false; } //坐标框选完成 private void CurvePictureBoxCtrl1_ReloadBoundaryEvent(System.Drawing.Rectangle? obj) { switch (_curveType) { case Yw.Ahart.eCurveType.QH: _rectQH = obj; break; case Yw.Ahart.eCurveType.QE: _rectQE = obj; break; case Yw.Ahart.eCurveType.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.pumpPictureBoxCtrl1.StartPickPoint(); } else { this.pumpPictureBoxCtrl1.EndPickPoint(); } } //刷新图表坐标 private bool ReloadChartCoordinate() { if (this.barEditTxtMinQ.EditValue == null || this.barEditTxtMaxQ.EditValue == null) return false; this.pumpPictureBoxCtrl1.ChartMinX = Convert.ToDouble(this.barEditTxtMinQ.EditValue); this.pumpPictureBoxCtrl1.ChartMaxX = Convert.ToDouble(this.barEditTxtMaxQ.EditValue); switch (_curveType) { case Yw.Ahart.eCurveType.QH: { if (this.txtMaxH.EditValue == null || this.txtMinH.EditValue == null) { return false; } this.pumpPictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxH.EditValue); this.pumpPictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinH.EditValue); } break; case Yw.Ahart.eCurveType.QE: { if (this.txtMaxE.EditValue == null || this.txtMinE.EditValue == null) { return false; } this.pumpPictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxE.EditValue); this.pumpPictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinE.EditValue); } break; case Yw.Ahart.eCurveType.QP: { if (this.txtMaxP.EditValue == null || this.txtMinP.EditValue == null) { return false; } this.pumpPictureBoxCtrl1.ChartMaxY = Convert.ToDouble(this.txtMaxP.EditValue); this.pumpPictureBoxCtrl1.ChartMinY = Convert.ToDouble(this.txtMinP.EditValue); } break; } return true; } //清空点 private void barBtnClear_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.pumpPictureBoxCtrl1.ClearPickPoint(); } //预览曲线 private void barBtnPreviewCurve_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (!Get(out string other_name, out Yw.Pump.CurveQH qh, out Yw.Pump.CurveQE qe, out Yw.Pump.CurveQP qp)) return; var line_qh = new Yw.Geometry.CubicSpline2d(qh?.FeatCurve.GetPointList()); var line_qe = new Yw.Geometry.CubicSpline2d(qe?.FeatCurve.GetPointList()); var line_qp = new Yw.Geometry.CubicSpline2d(qp?.FeatCurve.GetPointList()); var ctrl = new PumpViewChart(); ctrl.SetBindingData(line_qh, line_qe, line_qp); ctrl.Dock = DockStyle.Fill; var dlg = new XtraForm(); dlg.IconOptions.Icon = Yw.WinFrmUI.GlobalParas.AppIcon; dlg.Text = "预览"; dlg.StartPosition = FormStartPosition.CenterScreen; dlg.Size = new Size(900, 900); dlg.Controls.Add(ctrl); dlg.ShowDialog(); } //选择曲线变换时 private void tabbedControlGroup1_SelectedPageChanging(object sender, DevExpress.XtraLayout.LayoutTabPageChangingEventArgs e) { this.pumpPictureBoxCtrl1.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 = Yw.Ahart.eCurveType.QH; ReloadChartCoordinate(); this.pumpPictureBoxCtrl1.CurrentCaptureCruve = Yw.Ahart.eCurveType.QH; this.pumpPictureBoxCtrl1.RefreshPictureShape(_picQHPoints, _rectQH); } else if (e.Page == this.layoutControlGroupQP) { _curveType = Yw.Ahart.eCurveType.QP; ReloadChartCoordinate(); this.pumpPictureBoxCtrl1.CurrentCaptureCruve = Yw.Ahart.eCurveType.QP; this.pumpPictureBoxCtrl1.RefreshPictureShape(_picQPPoints, _rectQP); } else if (e.Page == this.layoutControlGroupQE) { _curveType = Yw.Ahart.eCurveType.QE; ReloadChartCoordinate(); this.pumpPictureBoxCtrl1.CurrentCaptureCruve = Yw.Ahart.eCurveType.QE; this.pumpPictureBoxCtrl1.RefreshPictureShape(_picQEPoints, _rectQE); } } //打点等效线 private void cekCaputueEtaPtInEqupCurve_CheckedChanged(object sender, EventArgs e) { this.pumpPictureBoxCtrl1.IsCaputueEtaPtInEqupCurve = this.cekCaputueEtaPtInEqupCurve.Checked; } //打点更新数据 private void CurvePictureBoxCtrl1_ReloadPickPointsEvent(List list) { switch (_curveType) { case Yw.Ahart.eCurveType.QH: _picQHPoints = list; break; case Yw.Ahart.eCurveType.QE: _picQEPoints = list; break; case Yw.Ahart.eCurveType.QP: _picQPPoints = list; break; } } /// /// 回调事件 /// public event Action ReloadDataEvent; private void barBtnSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (!Get(out string other_name, out Yw.Pump.CurveQH qh, out Yw.Pump.CurveQE qe, out Yw.Pump.CurveQP qp)) return; this?.ReloadDataEvent.Invoke(other_name, qh, qe, qp); } #region 方法 //获取曲线 public bool Get(out string other_name, out Yw.Pump.CurveQH qh, out Yw.Pump.CurveQE qe, out Yw.Pump.CurveQP qp) { other_name = null; qh = null; qe = null; qp = null; if (this.barEditTxtCurveCode.EditValue == null) { XtraMessageBox.Show("请输入曲线编码!"); return false; } other_name = this.barEditTxtCurveCode.EditValue.ToString(); 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 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.pumpPictureBoxCtrl1.UnitQ; double MinQ = 0; double MaxQ = 0; if (this.pumpPictureBoxCtrl1.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 = picPointsQH.GetFitPointList().GetInterPointsY(Q).Last(); curvePointsQH.Add(new Yw.Geometry.Point2d(Q, H)); if (_curveGetWay != eCurveGetWay.OnlyQh) { switch (_curveGetWay) { case eCurveGetWay.All: { P = picPointsQP.GetFitPointList().GetInterPointsY(Q)?.LastOrDefault() ?? 0; E = picPointsQE.GetFitPointList().GetInterPointsY(Q)?.LastOrDefault() ?? 0; } break; case eCurveGetWay.QhQpAnaQe: { P = picPointsQP.GetFitPointList().GetInterPointsY(Q)?.LastOrDefault() ?? 0; E = PumpCalcHelper.CalculateE(Q, H, P); } break; case eCurveGetWay.QhQeAnaQp: { E = picPointsQE.GetFitPointList().GetInterPointsY(Q)?.LastOrDefault() ?? 0; P = PumpCalcHelper.CalculateP(Q, H, E); } break; } curvePointsQP.Add(new Yw.Geometry.Point2d(Q, P)); curvePointsQE.Add(new Yw.Geometry.Point2d(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 = LineHelper.GetYbyX(curvePointsQH[0].X, curvePointsQH[0].Y, curvePointsQH[1].X, curvePointsQH[1].Y, MinQ); curvePointsQH.Insert(0, new Yw.Geometry.Point2d(MinQ, startH)); int point_num = curvePointsQH.Count;//不一定和insert_num一样 double endH = LineHelper.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 Yw.Geometry.Point2d(MaxQ, endH)); if (curvePointsQE != null && curvePointsQE.Count > 0) { //流量效率首尾两点 double startE = 0;//起始点 if (MinQ > 0.2) startE = LineHelper.GetYbyX(curvePointsQE[0].X, curvePointsQE[0].Y, curvePointsQE[1].X, curvePointsQE[1].Y, MinQ); else startE = 0; curvePointsQE.Insert(0, new Yw.Geometry.Point2d(MinQ, startE)); point_num = curvePointsQE.Count;//末尾点 double endE = LineHelper.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 Yw.Geometry.Point2d(MaxQ, endE)); } if (curvePointsQP != null && curvePointsQP.Count > 0) { //流量功率首尾两点 double startP = LineHelper.GetYbyX(curvePointsQP[0].X, curvePointsQP[0].Y, curvePointsQP[1].X, curvePointsQP[1].Y, MinQ); curvePointsQP.Insert(0, new Yw.Geometry.Point2d(MinQ, startP)); point_num = curvePointsQP.Count; double endP = LineHelper.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 Yw.Geometry.Point2d(MaxQ, endP)); } #endregion //圆整 curvePointsQH = Regulate(curvePointsQH, 2); curvePointsQE = Regulate(curvePointsQE, 2); curvePointsQP = Regulate(curvePointsQP, 2); qh = new Pump.CurveQH(Yw.Ahart.eFeatType.Cubic, curvePointsQH); qe = new Pump.CurveQE(Yw.Ahart.eFeatType.Cubic, curvePointsQE); qp = new Pump.CurveQP(Yw.Ahart.eFeatType.Cubic, curvePointsQP); 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 Yw.Geometry.Point2d(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 Yw.Geometry.Point2d(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 } }