From 0f5eaa62a6ce8c24c056e2d690bc2e6a9958637e Mon Sep 17 00:00:00 2001
From: ningshuxia <ningshuxia0927@outlook.com>
Date: 星期四, 27 三月 2025 11:51:17 +0800
Subject: [PATCH] 供水分析

---
 WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs |  394 +++++++++----------------------------------------------
 1 files changed, 68 insertions(+), 326 deletions(-)

diff --git a/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs b/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs
index cf4b184..a00c6e4 100644
--- a/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs
+++ b/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs
@@ -1,150 +1,26 @@
-锘縰sing DevExpress.Mvvm.Native;
-using DevExpress.XtraCharts;
-
-namespace PBS.WinFrmUI.Hydro
+锘縩amespace PBS.WinFrmUI.Hydro
 {
     public partial class SystemCurvePage : DocumentPage
     {
         public SystemCurvePage()
         {
             InitializeComponent();
-            this.facilityTreeListCtrl1.SelectFacilityEvent += FacilityTreeListCtrl1_SelectFacilityEvent; 
+            this.facilityTreeListCtrl1.SelectFacilityEvent += FacilityTreeListCtrl1_SelectFacilityEvent;
             this.facilityTreeListCtrl1.RefreshDataEvent += () => { RefreshData(); };
-        }
-
-      
-
-        private class ChartPressurePointViewModel
-        {
-            public ChartPressurePointViewModel()
-            {
-            }
-            public ChartPressurePointViewModel(double totalFlow, double upperPressure, double lowerPressure, double averagePressure)
-            {
-                this.TotalFlow = totalFlow;
-                this.UpperPressure = upperPressure;
-                this.LowerPressure = lowerPressure;
-                this.AveragePressure = averagePressure;
-            }
-
-            public double TotalFlow { get; set; }
-            public double UpperPressure { get; set; }
-            public double LowerPressure { get; set; }
-            public double AveragePressure { get; set; }
-        }
-
-        private class PointViewModel
-        {
-            public PointViewModel()
-            {
-
-            }
-            public PointViewModel(double x, double y)
-            {
-                this.X = x;
-                this.Y = y;
-            }
-
-            public double X { get; set; }
-            public double Y { get; set; }
-        }
-
-        public class CalcResultViewModel
-        {
-            public double TotalFlow { get; set; }
-            public double EndPressure { get; set; }
-            public List<CalcNodeViewModel> CalcNodeList { get; set; }
-
-        }
-
-        public class CalcNodeViewModel
-        {
-            public int NodeIndex { get; set; }
-            public double Elevation { get; set; }
-            public double Flow { get; set; }
-            public double Pressure { get; set; }
-        }
-
-
-        private XYDiagram _xyDiagram;
-        private XYDiagramDefaultPane _xyDiagramPane;
-
-        private Series _seriesWaterPoint;
-        private Series _seriesUpperPressure;
-        private Series _seriesLowerPressure;
-        private Series _seriesAveragePressure;
-
-        private ConstantLine _constantLineDynamicPressure;
-        private ConstantLine _constantLineStaticPressure;
-
-
-        private Yw.Ahart.CubicCurve _curveUpperPressure = null;
-        private Yw.Ahart.CubicCurve _curveLowerPressure = null;
-        private Yw.Ahart.CubicCurve _curveAveragePressure = null;
-        private List<PointViewModel> _waterPointList = null;
-
-
-        private FacilityVmo _facility = null; 
-
-
-        public override async void InitialDataSource()
-        {
-            var overlay = this.ShowOverlay();
-
-            this.chartControl1.Legend.Direction = LegendDirection.LeftToRight;
-            //this.chartControl1.AnimationStartMode = ChartAnimationMode.OnDataChanged;
-            this.chartControl1.RuntimeHitTesting = true;
-            //this.chartControl1.CrosshairEnabled =  DevExpress.Utils.DefaultBoolean.False;  
-
-            _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 FacilityVmo _facility = null;  
+
+        /// <summary>
+        /// 鍒濆鍖栨暟鎹簮
+        /// </summary>
+        public override async void InitialDataSource()
+        { 
             base.InitialDataSource(); 
 
             var allFacilityList = await BLLFactory<BLL.Facility>.Instance.GetAll();
-            this.facilityTreeListCtrl1.SetBindingData(allFacilityList);
-
-            overlay.Close();
+            this.facilityTreeListCtrl1.SetBindingData(allFacilityList); 
 
         }
 
@@ -153,21 +29,15 @@
         {
             InitialData(obj);
         }
-
-
-
+         
         /// <summary>
         /// 鍒濆鍖栨暟鎹�
         /// </summary> 
         public void InitialData(FacilityVmo obj)
         {
-            if (obj == null)
-            {
-                _facility = null;
-                return;
-            }
-
             _facility = obj;
+            this.facilityPropertyCtrl1.SetBindingData(obj);
+            this.systemCurveChartCtrl1.Clear(); 
 
         }
 
@@ -179,52 +49,58 @@
                 TipFormHelper.ShowWarn("璇烽�夋嫨璁炬柦!");
                 return;
             }
-
-            //鍢夊畾
-            ////var file_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "1843913603388936192.inp"); 
-            //var minDemand = 0;   // 鏈�灏忔�婚渶姘撮噺(m鲁/h)
-            //var maxDemand = 43;  // 鏈�澶ф�婚渶姘撮噺(m鲁/h)
-            //var reservoirElevation = -4; //姘存睜鏍囬珮
-            //var calcCount = 1000;           // 璁$畻娆℃暟
-            //var staticPressure = 22.5; //闈欏帇
-            //var requiredEndPressure = 18; //闈欏帇 
-
+ 
 
             var file_path = _facility.ModelPath;
             var minDemand = 0;   // 鏈�灏忔�婚渶姘撮噺(m鲁/h)
-            var maxDemand = _facility.MaxWaterDemand??45;  // 鏈�澶ф�婚渶姘撮噺(m鲁/h)
-            var reservoirElevation = -4; //姘存睜鏍囬珮
-            var calcCount = 10;           // 璁$畻娆℃暟
-            var staticPressure = 22.5; //闈欏帇
-            var requiredEndPressure = _facility.TerminalPressure??15; //闈欏帇
-
-            CalcSystemCurve(file_path, minDemand, maxDemand, reservoirElevation, staticPressure, requiredEndPressure, calcCount);
+            var maxDemand = _facility.MaxWaterDemand??45;  // 鏈�澶ф�婚渶姘撮噺(m鲁/h) 
+            var calcCount = 20000;           // 璁$畻娆℃暟
+            var maxHeight = 22.5; //椤舵ゼ鏍囬珮
+            var requiredEndPressure = _facility.TerminalPressure ?? 15; //闈欏帇 
+            CalcSystemCurve(file_path, minDemand, maxDemand, maxHeight, requiredEndPressure, calcCount); 
+       
         }
 
+        /// <summary>
+        /// 璁$畻绯荤粺鏇茬嚎
+        /// </summary>
+        /// <param name="inpFilePath"></param>
+        /// <param name="minDemand"></param>
+        /// <param name="maxDemand"></param>
+        /// <param name="reservoirElevation"></param>
+        /// <param name="maxHeight"></param>
+        /// <param name="requiredEndPressure"></param>
+        /// <param name="calcCount"></param>
         private void CalcSystemCurve(
             string inpFilePath,
             double minDemand,
             double maxDemand,
-            double reservoirElevation,
-            double staticPressure,
+            //double reservoirElevation,
+            double maxHeight,
             double requiredEndPressure,
             int calcCount)
         {
             
             var pressure = 0d;
             var nodeConfig = new List<WaterDistributionCalculator.NodeConfig>();
-            var calcResultList = new List<CalcResultViewModel>(calcCount);
+            var waterPointCalcList = new List<WaterPointCalcViewModel>(calcCount);
             using (var helper = new Yw.Epanet.InteropXHelper())
             {
                 var code = helper.Open(inpFilePath, "", "");
+                CheckCode(code);
                 code = helper.GetCount(Yw.Epanet.eCountType.Node, out int totalNodeCount);
-
+                CheckCode(code);
                 var rand = new Random();
                 for (int nodeIndex = 1; nodeIndex <= totalNodeCount; nodeIndex++)
                 {
                     helper.GetNodeType(nodeIndex, out Yw.Epanet.eNodeType nodeType);
                     if (nodeType == Yw.Epanet.eNodeType.Junction)
                     {
+                        code = helper.GetNodeId(nodeIndex, out string id);
+                        if (!id.Contains("M"))
+                        {
+                            continue;
+                        }
                         helper.GetNodeValue(nodeIndex, Yw.Epanet.eNodeProperty.Elevation, out double elevation);
                         nodeConfig.Add(new WaterDistributionCalculator.NodeConfig()
                         {
@@ -233,12 +109,7 @@
                             MinFlow = 0,
                             MaxFlow = rand.NextDouble() * 5
                         });
-                    }
-                    else if (nodeType == Yw.Epanet.eNodeType.Reservoir)
-                    {
-                        code = helper.SetNodeValue(nodeIndex, Yw.Epanet.eNodeProperty.Elevation, reservoirElevation);
-                        CheckCode(code);
-                    }
+                    } 
                 }
 
                 var userNodeCount = nodeConfig.Count;
@@ -246,12 +117,14 @@
                 var allDemands = calculator.CalculateDistributions();
 
                 code = helper.OpenH();
+                CheckCode(code);
                 for (int count = 0; count < allDemands.Count; count++)
                 {
-                    var calcNodelDict = new Dictionary<int, CalcNodeViewModel>(userNodeCount);
+                    var calcNodelDict = new Dictionary<int, WaterPointNodeViewModel>(userNodeCount);
                     var calcEndPressure = double.MaxValue;
 
                     code = helper.InitH(false);
+                    CheckCode(code);
                     var demands = allDemands[count];
                     foreach (var node in nodeConfig)
                     {
@@ -260,194 +133,63 @@
                         code = helper.SetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.BaseDemand, demand);
                         CheckCode(code);
 
-                        calcNodelDict[userNodeIndex] = new CalcNodeViewModel()
+                        calcNodelDict[userNodeIndex] = new WaterPointNodeViewModel()
                         {
-                            NodeIndex = userNodeIndex,
+                            Index = userNodeIndex,
                             Flow = demand
                         };
                     }
 
                     code = helper.RunH(out long t);
-
+                    CheckCode(code);
 
                     foreach (var node in nodeConfig)
                     {
                         var userNodeIndex = node.NodeIndex;
                         pressure = 0;
 
-                        //code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Pressure, out pressure);
-                        //CheckCode(code);
-                        //var endPressure = pressure + node.Elevation;
-
-                        code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Pressure, out pressure);
+                        //鑷敱鍘嬪姏=缁濆鍘嬪姏-鏍囬珮
+                        //榛樿璧峰鐐瑰帇鍔涗负鏈�浣庢按浣嶏紝鎵�浠ョ敤 缁濆鍘嬪姏 褰撹嚜鐢卞帇鍔� 锛堢粷瀵瑰帇鍔�=鑷敱鍘嬪姏+鏍囬珮锛�
+                        code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Head, out double head);
                         CheckCode(code);
-                        var endPressure = pressure + node.Elevation;
+                        var endPressure = head;
                         calcNodelDict[userNodeIndex].Pressure = endPressure;
-
                         if (calcEndPressure > endPressure)
                         {
                             calcEndPressure = endPressure;
-                        }
-
-                        if (Math.Abs(calcEndPressure) > 100)
-                        {
-                            code = helper.GetNodeId(userNodeIndex, out string id);
-                            var b = id;
                         }
                     }
 
 
                     code = helper.NextH(out long tstep);
-
-                    var result = new CalcResultViewModel();
-                    result.TotalFlow = demands.TotalDemand;
-                    result.EndPressure = Math.Abs(calcEndPressure);
-                    result.CalcNodeList = calcNodelDict.Values.ToList();
-                    calcResultList.Add(result);
+                    CheckCode(code);
+                    var waterPointCalc = new WaterPointCalcViewModel();
+                    waterPointCalc.TotalFlow = demands.TotalDemand;
+                    waterPointCalc.EndPressure = Math.Abs(calcEndPressure) + maxHeight + requiredEndPressure;
+                    waterPointCalc.NodeList = calcNodelDict.Values.ToList();
+                    waterPointCalcList.Add(waterPointCalc);
 
                 }
 
 
                 code = helper.Close();
+                CheckCode(code);
             }
-
-
-
-            this.chartControl1.BeginInit();
-
-
-            _curveUpperPressure = null;
-            _curveLowerPressure = null;
-            _curveAveragePressure = null;
-            _waterPointList = null;
-
-
-            _seriesWaterPoint.Points.Clear();
-            _seriesUpperPressure.Points.Clear();
-            _seriesLowerPressure.Points.Clear();
-            _seriesAveragePressure.Points.Clear();
-
-            _constantLineDynamicPressure.Visible = false;
-            _constantLineStaticPressure.Visible = false;
-
-            if (calcResultList.Any())
-            {
-                _waterPointList = calcResultList.Select(x => new PointViewModel(x.TotalFlow, x.EndPressure + staticPressure + requiredEndPressure)).ToList();
-                //_waterPointList = calcResultList.Select(x => new PointViewModel(x.TotalFlow, x.EndPressure + staticPressure)).ToList();
-
-                var waterPointGroup = _waterPointList.GroupBy(x => Math.Round(x.X, 1));
-                var upperPressurePtList = new List<Yw.Geometry.Point2d>();
-                var lowerPressurePtList = new List<Yw.Geometry.Point2d>();
-                var averagePressurePtList = new List<Yw.Geometry.Point2d>();
-
-                foreach (var item in waterPointGroup)
-                {
-                    var x = item.Key;
-                    var yList = item.Select(x => x.Y).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));
-
-                }
-
-                _curveUpperPressure = new Yw.Ahart.CubicCurve(upperPressurePtList);
-                _curveLowerPressure = new Yw.Ahart.CubicCurve(lowerPressurePtList);
-                _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 _waterPointList)
-                {
-                    _seriesWaterPoint.Points.Add(new SeriesPoint(item.X, item.Y));
-                }
-                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));
-                }
-
-                var minX = _waterPointList.Min(x => x.X);
-                var maxX = _waterPointList.Max(x => x.X);
-
-                var minY = _waterPointList.Min(x => x.Y);
-                var maxY = _waterPointList.Max(x => x.Y);
-
-
-                //var minDynamicPressure = minY;
-                //_constantLineDynamicPressure.AxisValue = minDynamicPressure;
-                //_constantLineDynamicPressure.Title.Text = $"鏈�浣庝緵姘村帇鍔�:{minDynamicPressure:N2}m";
-                //_constantLineDynamicPressure.Visible = true;
-
-                //var totalStaticPressure = staticPressure + Math.Abs(reservoirElevation);
-                //_constantLineStaticPressure.AxisValue = totalStaticPressure;
-                //_constantLineStaticPressure.Title.Text = $"鏈�楂樻ゼ灞傞珮搴�:{totalStaticPressure:N2}m";
-                //_constantLineStaticPressure.Visible = true;
-
-                //minY = Math.Min(staticPressure, minY);
-                //maxY = Math.Max(staticPressure, maxY);
-
-                //minY = Math.Min(staticPressure, minY);
-                //maxY = Math.Max(staticPressure, maxY);
-
-                //maxY = Math.Floor(maxY);
-                //maxX = Math.Floor(maxX);
-
-                //_xyDiagram.AxisX.WholeRange.Auto = true;
-                //_xyDiagram.AxisX.VisualRange.Auto = true;
-                //_xyDiagram.AxisX.WholeRange.SideMarginsValue = 0;
-                //_xyDiagram.AxisX.VisualRange.SideMarginsValue = 0;
-                //_xyDiagram.AxisX.NumericScaleOptions.AutoGrid = true;
-                //_xyDiagram.AxisX.WholeRange.SetMinMaxValues(minX, 50);
-                //_xyDiagram.AxisX.VisualRange.SetMinMaxValues(minX, 50);
-
-                //_xyDiagram.AxisY.WholeRange.Auto = true;
-                //_xyDiagram.AxisY.VisualRange.Auto = true;
-                //_xyDiagram.AxisY.NumericScaleOptions.AutoGrid = true;
-                //_xyDiagram.AxisY.WholeRange.SideMarginsValue = 0;
-                //_xyDiagram.AxisY.VisualRange.SideMarginsValue = 0;
-                //_xyDiagram.AxisY.WholeRange.SetMinMaxValues(minY, 70);
-                //_xyDiagram.AxisY.VisualRange.SetMinMaxValues(minY, 70);
-
-            }
-            this.chartControl1.EndInit();
+             
+            this.systemCurveChartCtrl1.SetBindingData(waterPointCalcList);
         }
-
-        private double CalculatePercentile(List<double> 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;
-        }
+ 
 
         private void CheckCode(Yw.Epanet.eErrorCode code)
         {
             if (code != Yw.Epanet.eErrorCode.OK)
             {
-                var msg = code.GetDisplayText();
-                throw new Exception(msg);
+                if ((int)code>100)
+                {
+                    var msg = code.GetDisplayText();
+                    throw new Exception(msg);
+                }
+             
             }
         }
 

--
Gitblit v1.9.3