using DevExpress.Drawing; using DevExpress.Pdf.Native; using DevExpress.XtraCharts; using System.Data; using Yw.DAL.Basic; using Yw.EPAnet; using Yw.Hydro; using Yw.Model; namespace Yw.WinFrmUI { public partial class HydroLossCurveInteropCtrl : DevExpress.XtraEditors.XtraUserControl { public HydroLossCurveInteropCtrl() { InitializeComponent(); this.layoutControl1.SetupLayoutControl(); } /// /// 水力点击事件 /// public event Action HydroClickEvent; /// /// 水力特殊显示事件 /// public event Action> HydroSpecialDisplayEvent; /// /// 水力取消特殊显示事件 /// public event Action HydroCancelSpecialDisplayEvent; private Yw.Model.HydroModelInfo _hydroInfo = null;//水力信息 private HydroWorkingVmo _working = null;//工况 private Yw.Model.HydroNodeInfo _node = null;//节点 private HydroCalcuResult _calcuResult = null;//计算结果 /// /// 绑定数据 /// public void SetBindingData ( Yw.Model.HydroModelInfo hydroInfo, HydroWorkingVmo working, HydroNodeInfo node, HydroCalcuResult calcuResult = null, bool isHead = false, List allEvaluationList = null ) { if (hydroInfo == null) { return; } if (working == null) { return; } if (node == null) { return; } _hydroInfo = hydroInfo; _working = working; _node = node; if (calcuResult == null) { hydroInfo.UpdateWorkingInfo(working.WorkingInfo); calcuResult = hydroInfo.Calcu(Yw.EPAnet.CalcuMode.MinorLoss, isHead, allEvaluationList); } _calcuResult = calcuResult; Analy(); } /// /// 绑定数据 /// private void SetBindingData(HydroLossCurveViewModel vm) { AutoFitAxises(vm?.Items); this.elevBindingSource.DataSource = vm?.Elev?.Items; this.elevBindingSource.ResetBindings(false); this.lossBindingSource.DataSource = vm?.Lower; this.lossBindingSource.ResetBindings(false); if (vm?.Total != null) { var sb = new StringBuilder(); sb.AppendLine($"水头损失:{vm?.Total.HeadLoss:N2}m"); sb.AppendLine($"局部损失:{vm?.Total.MinorLoss:N2}m"); sb.AppendLine($"沿程损失:{vm?.Total.FrictionLoss:N2}m"); var anno = this.chartControl1.AnnotationRepository[0] as DevExpress.XtraCharts.TextAnnotation; anno.Text = sb.ToString(); anno.AutoSize = true; } } //自动适应刻度 private void AutoFitAxises(List items) { if (items == null || items.Count < 1) { return; } var diagram = this.chartControl1.Diagram as XYDiagram; #region X轴 var allDistances = items.Select(x => x.Distance).Distinct().ToList(); var distanceMax = allDistances.Max(); diagram.AxisX.Tickmarks.MinorVisible = false; diagram.AxisX.WholeRange.SideMarginsValue = 0; if (distanceMax <= 10) { var maxValue = Math.Ceiling(distanceMax); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue; diagram.AxisX.NumericScaleOptions.GridSpacing = 1; } else if (distanceMax <= 50) { var maxValue = Math.Ceiling(distanceMax / 10); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 10; diagram.AxisX.NumericScaleOptions.GridSpacing = 5; } else if (distanceMax <= 100) { var maxValue = Math.Ceiling(distanceMax / 10); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 10; diagram.AxisX.NumericScaleOptions.GridSpacing = 10; } else if (distanceMax <= 500) { var maxValue = Math.Ceiling(distanceMax / 100); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 100; diagram.AxisX.NumericScaleOptions.GridSpacing = 50; } else if (distanceMax <= 3000) { var maxValue = Math.Ceiling(distanceMax / 100); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 100; diagram.AxisX.NumericScaleOptions.GridSpacing = 100; } else if (distanceMax <= 5000) { var maxValue = Math.Ceiling(distanceMax / 1000); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 1000; diagram.AxisX.NumericScaleOptions.GridSpacing = 200; } else if (distanceMax <= 10000) { var maxValue = Math.Ceiling(distanceMax / 1000); diagram.AxisX.WholeRange.MinValue = 0; diagram.AxisX.WholeRange.MaxValue = maxValue * 1000; diagram.AxisX.NumericScaleOptions.GridSpacing = 1000; } else { } #endregion #region 压力 var allPressMinList = items.Select(x => Math.Min(Math.Min(x.StartHead, x.EndHead), x.Elev)).ToList(); var allPressMaxList = items.Select(x => Math.Max(Math.Max(x.StartHead, x.EndHead), x.Elev)).ToList(); var pressMin = allPressMinList.Min(); var pressMax = allPressMaxList.Max(); diagram.AxisY.Tickmarks.MinorVisible = false; diagram.AxisY.WholeRange.SideMarginsValue = 0; diagram.AxisY.CrosshairAxisLabelOptions.EnableAntialiasing = DevExpress.Utils.DefaultBoolean.True; if (pressMax <= 10) { diagram.AxisY.WholeRange.MinValue = Math.Floor(pressMin); diagram.AxisY.WholeRange.MaxValue = 10; diagram.AxisY.NumericScaleOptions.GridSpacing = 1; diagram.AxisY.VisualRange.SetMinMaxValues(0, 10); } else if (pressMax <= 100) { var maxValue = Math.Ceiling(pressMax / 10); diagram.AxisY.WholeRange.MinValue = Math.Floor(pressMin); diagram.AxisY.WholeRange.MaxValue = maxValue * 10; diagram.AxisY.NumericScaleOptions.GridSpacing = 5; diagram.AxisY.VisualRange.SetMinMaxValues(0, maxValue * 10); } else if (pressMax <= 3000) { var maxValue = Math.Ceiling(pressMax / 100); diagram.AxisY.WholeRange.MinValue = Math.Floor(pressMin); diagram.AxisY.WholeRange.MaxValue = maxValue * 100; diagram.AxisY.NumericScaleOptions.GridSpacing = 50; diagram.AxisY.VisualRange.SetMinMaxValues(0, maxValue * 100); } else if (pressMax <= 6000) { var maxValue = Math.Ceiling(pressMax / 1000); diagram.AxisY.WholeRange.MinValue = Math.Floor(pressMin); diagram.AxisY.WholeRange.MaxValue = maxValue * 1000; diagram.AxisY.NumericScaleOptions.GridSpacing = 100; diagram.AxisY.VisualRange.SetMinMaxValues(0, maxValue * 1000); } else { } #endregion } //提示 private void chartControl1_CustomDrawCrosshair(object sender, CustomDrawCrosshairEventArgs e) { // Specify the crosshair argument line color, dash style and thickness. e.CrosshairLineElement.Color = Color.Green; e.CrosshairLineElement.LineStyle.DashStyle = DashStyle.DashDot; e.CrosshairLineElement.LineStyle.Thickness = 3; // Specify the back color for the crosshair argument axis label. foreach (CrosshairAxisLabelElement axisLabelElement in e.CrosshairAxisLabelElements) { axisLabelElement.BackColor = Color.Blue; axisLabelElement.Text = $"{axisLabelElement.AxisValue:N2}"; } foreach (CrosshairElementGroup group in e.CrosshairElementGroups) { CrosshairGroupHeaderElement groupHeaderElement = group.HeaderElement; var pt = group.HeaderElement.SeriesPoints.FirstOrDefault(); if (pt != null) { var model = pt.Tag as HydroLossCurvePointVieModel; if (model != null) { groupHeaderElement.Text = model.Name; } } // Specify the text, text color and font for the crosshair group header element. groupHeaderElement.TextColor = Color.Green; groupHeaderElement.DXFont = new DXFont("SegoeUI", 12, DXFontStyle.Bold); //groupHeaderElement.Text = group.CrosshairElements[0].AxisLabelElement.Text; foreach (var ele in group.CrosshairElements) { ele.AxisLabelElement.Text = $"{ele.AxisLabelElement.AxisValue:N1}"; ele.AxisLabelElement.DXFont = new DXFont(this.Font.Name, 6); } //// Obtain the first series. //CrosshairElement element = group.CrosshairElements[0]; //// Specify the color, dash style and thickness for the crosshair value lines. //element.LineElement.Color = Color.DarkViolet; //element.LineElement.LineStyle.DashStyle = DashStyle.Dash; //element.LineElement.LineStyle.Thickness = 2; //// Specify the text color and back color for the crosshair value labels. //element.AxisLabelElement.TextColor = Color.Red; //element.AxisLabelElement.BackColor = Color.Yellow; //// Format the text shown for the series in the crosshair cursor label. Specify the text color and marker size. //element.LabelElement.TextColor = Color.Red; //element.LabelElement.MarkerSize = new Size(15, 15); //element.LabelElement.Text = $"高程:{element.SeriesPoint.Values[0]}m"; } } //点击事件 private void chartControl1_MouseClick(object sender, MouseEventArgs e) { ChartHitInfo hitInfo = this.chartControl1.CalcHitInfo(e.Location); if (hitInfo.Series != null) { if (hitInfo.SeriesPoint != null) { var vm = hitInfo.SeriesPoint.Tag as HydroLossCurvePointVieModel; if (vm != null) { this.HydroClickEvent?.Invoke(vm.Code); } } } } /// /// 导出图片 /// public void ExportToImage(string filePath) { this.chartControl1.ExportToImage(filePath, DXImageFormat.Png); } //上游追踪选择 private void ckStart_CheckedChanged(object sender, EventArgs e) { Analy(); } //下游追踪选择 private void ckEnd_CheckedChanged(object sender, EventArgs e) { Analy(); } //高亮显示 private void ckSpecial_CheckedChanged(object sender, EventArgs e) { Analy(); } //分析 private void Analy() { if (_hydroInfo == null) { return; } if (_working == null) { return; } if (_node == null) { return; } if (_calcuResult == null) { return; } var network = _hydroInfo.ToNetwork(); if (network == null) { return; } var epaNode = network.GetAllNodes()?.Find(x => x.Id == _node.Code); if (epaNode == null) { return; } var allStartPathList = new List(); if (this.ckStart.Checked) { allStartPathList = network.AnalyzeUpstreamPath(epaNode, _calcuResult?.EPAnetCalcuResult); if (allStartPathList == null) { allStartPathList = new List(); } } var allEndPathList = new List(); if (this.ckEnd.Checked) { allEndPathList = network.AnalyzeDownstreamPath(epaNode, _calcuResult?.EPAnetCalcuResult); if (allEndPathList == null) { allEndPathList = new List(); } } var allPathList = allStartPathList.Concat(allEndPathList).ToList(); var allEpaLossList = network.GetChartNodeByPathLinks(allPathList, _calcuResult?.EPAnetCalcuResult); var allVisualDict = _hydroInfo.GetVisualDict(); var vm = new HydroLossCurveViewModel(); vm.Items = new List(); allEpaLossList?.ForEach(x => { var visualNode = allVisualDict?.GetValue(x.Id); if (visualNode != null) { vm.Items.Add(new HydroLossCurveItemViewModel(x, visualNode)); } }); vm.Elev = new HydroLossCurveElevViewModel(vm.Items); vm.Start = new HydroLossCurveStartViewModel(vm.Items); vm.End = new HydroLossCurveEndViewModel(vm.Items); vm.Lower = new HydroLossCurveLowerViewModel(vm.Items); vm.Total = new HydroLossCurveTotalViewModel(vm.Items); SetBindingData(vm); if (this.ckSpecial.Checked) { var allCodeList = new List(); allPathList?.ForEach(x => allCodeList.Add(x.Id)); vm.Items?.ForEach(x => allCodeList.Add(x.Code)); this.HydroSpecialDisplayEvent?.Invoke(allCodeList); } else { this.HydroCancelSpecialDisplayEvent?.Invoke(); } } } }