cloudflight
2023-12-02 c3b1e8241a0456eed42c3278c9616d6500859272
Hydro.Inp/NetWork.cs
@@ -2,6 +2,7 @@
//using Hydro.HydraulicModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
@@ -174,20 +175,20 @@
            nozzles.ForEach(nozzle => { AddNozzle(nozzle); });
        }
        private void CheckNodesExist(NodeModel node)
        private void CheckNodesExist(NodeCalcModel node)
        {
            if (Nodes.Any(d => d.ID == node.ID))
                throw new Exception("已存在重复的对象");
        }
        private void CheckLinksExist(LinkModel link)
        private void CheckLinksExist(LinkCalcModel link)
        {
            if (Links.Any(d => d.ID == link.ID))
                throw new Exception("已存在重复的对象");
        }
        public List<NodeModel> Nodes { get; set; } = new List<NodeModel>();
        public List<LinkModel> Links { get; set; } = new List<LinkModel>();
        public List<NodeCalcModel> Nodes { get; set; } = new List<NodeCalcModel>();
        public List<LinkCalcModel> Links { get; set; } = new List<LinkCalcModel>();
        /// <summary>
        /// 根据INP文件生成
@@ -405,86 +406,94 @@
                }
                sr.Close();
                //读取坐标
                Junctions.ForEach(o =>
                {
                    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                    if (p != null)
                    {
                        o.X = p.Position.X;
                        o.Y = p.Position.Y;
                    }
                });
                #region 坐标匹配方法
                #endregion
                Reservos.ForEach(o =>
                {
                    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                    if (p != null)
                    {
                        o.X = p.Position.X;
                        o.Y = p.Position.Y;
                    }
                });
                #region 删除
                //[Cloudflight修改]2023-11-27    二重循环匹配坐标速度太慢
                ////读取坐标
                //Junctions.ForEach(o =>
                //{
                //    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                //    if (p != null)
                //    {
                //        o.X = p.Position.X;
                //        o.Y = p.Position.Y;
                //    }
                //});
                Tanks.ForEach(o =>
                {
                    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                    if (p != null)
                    {
                        o.X = p.Position.X;
                        o.Y = p.Position.Y;
                    }
                });
                //Reservos.ForEach(o =>
                //{
                //    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                //    if (p != null)
                //    {
                //        o.X = p.Position.X;
                //        o.Y = p.Position.Y;
                //    }
                //});
                Meters.ForEach(o =>
                {
                    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                    if (p != null)
                    {
                        o.X = p.Position.X;
                        o.Y = p.Position.Y;
                    }
                });
                //Tanks.ForEach(o =>
                //{
                //    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                //    if (p != null)
                //    {
                //        o.X = p.Position.X;
                //        o.Y = p.Position.Y;
                //    }
                //});
                Nozzles.ForEach(o =>
                {
                    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                    if (p != null)
                    {
                        o.X = p.Position.X;
                        o.Y = p.Position.Y;
                    }
                });
                //Meters.ForEach(o =>
                //{
                //    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                //    if (p != null)
                //    {
                //        o.X = p.Position.X;
                //        o.Y = p.Position.Y;
                //    }
                //});
                //Nozzles.ForEach(o =>
                //{
                //    var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
                //    if (p != null)
                //    {
                //        o.X = p.Position.X;
                //        o.Y = p.Position.Y;
                //    }
                //});
                #endregion
                #region 优化方案
                int k1 = 0;
                int k2 = 0;
                #region delete
                //Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
                //points.Sort((a, b) => string.Compare(a.ID, b.ID));
                //k1 = 0;
                //k2 = 0;
                //while (k1 < Nodes.Count)
                //{
                //    var J = Nodes[k1];
                //    var coor = points[k2];
                //    while (J.ID != coor.ID && k2 < points.Count)
                //    {
                //        k2++;
                //        if (k2 < points.Count) coor = points[k2];
                Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
                points.Sort((a, b) => string.Compare(a.ID, b.ID));
                k1 = 0;
                k2 = 0;
                while (k1 < Nodes.Count)
                {
                    var J = Nodes[k1];
                    var coor = points[k2];
                //    }
                //    if (k2 == points.Count)
                //    {
                //        throw new Exception($"未找到Node[{J.ID}]的坐标");
                //    }
                //    J.X = coor.Position.X;
                //    J.Y = coor.Position.Y;
                    while (J.ID != coor.ID && k2 < points.Count)
                    {
                        k2++;
                        if (k2 < points.Count) coor = points[k2];
                //    k1++;
                //}
                    }
                    if (k2 == points.Count)
                    {
                        throw new Exception($"未找到Node[{J.ID}]的坐标");
                    }
                    J.X = coor.Position.X;
                    J.Y = coor.Position.Y;
                    k1++;
                }
                #endregion
                //建立点线关系链表StartNode,先将管线以Node1(节点1的ID)排序,再将Nodes按ID排序,建立两个游标k1、k2,正向一次循环,建立链表关系
@@ -534,7 +543,6 @@
                    //if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
                    //J.Links.Add(p);
                    k2++;
                }
                return true;
            }
@@ -546,7 +554,7 @@
        /// <param name="InpPath">Inp文件路径</param>
        /// <param name="TemplateInpFullPath">Inp模板文件绝对路径,如果为空就用系统默认模板文件</param>
        /// <exception cref="Exception"></exception>
        public virtual void BuildToInp(string InpPath, string TemplateInpFullPath = "")
        public virtual void BuildToInp(string InpPath, string TemplateInpFullPath = "", string sourcePath = null, bool isReplace = false)
        {
            string tempString = "";
@@ -596,7 +604,7 @@
            });
            Meters.ForEach(m =>
            {
                junctionStringBuilder.AppendLine(m.ToString() + $"0\tJunction");
                junctionStringBuilder.AppendLine(m.ToString() + $"0\tMeters");
                coorStringBuilder.AppendLine(m.ToCoorString());
            });
            Nozzles.ForEach(no =>
@@ -625,7 +633,7 @@
            Tanks.ForEach(o =>
            {
                tankStringBuilder.AppendLine(o.ToString());// + $"{o.Level}");
                tankStringBuilder.AppendLine(o.ToString());// + $"0");
                coorStringBuilder.AppendLine(o.ToCoorString());
            });
            string tankString = tankStringBuilder.ToString();
@@ -648,7 +656,7 @@
            Valves.ForEach(o =>
            {
                valveStringBuilder.AppendLine(o.ToString());// + $"{o.Level}");
                valveStringBuilder.AppendLine(o.ToString());// + $"0");
                statusStringBuilder.Append(o.ToStatusString());
            });
            string valveString = valveStringBuilder.ToString();
@@ -659,7 +667,7 @@
            Pumps.ForEach(o =>
            {
                pumpStringBuilder.AppendLine(o.ToString());// + $"{o.Level}");
                pumpStringBuilder.AppendLine(o.ToString());// + $"0");
                statusStringBuilder.Append(o.ToStatusString());
            });
            string pumpString = pumpStringBuilder.ToString();
@@ -729,7 +737,215 @@
            //Global.ClearFileReadOnly(InpPath);
            File.WriteAllText(InpPath, output);
        }
        //public void BuildToInp(string filePath, string userCoorString = null, string sourcePath = null, bool isReplace = false)
        //{
        //    if (sourcePath == null) sourcePath = filePath;
        //    string tempString = "";
        //    if (!isReplace)
        //    {
        //        var tempPath = Path.Combine(Directory.GetCurrentDirectory(), @"template\inp\导出模板.inp");
        //        if (!File.Exists(tempPath))
        //        {
        //            //MessageBox.Show($"模板文件不存在[{tempPath}]");
        //            return;
        //        }
        //        tempString = File.ReadAllText(tempPath);
        //    }
        //    else
        //    {
        //        tempString = File.ReadAllText(sourcePath);
        //    }
        //    Dictionary<string, string> dictExchange = new Dictionary<string, string>() {
        //        {"{junctions}","{0}" },
        //        {"{reservoirs}","{1}" },
        //        {"{tanks}","{2}" },
        //        {"{pipes}","{3}" },
        //        {"{valves}","{4}" },
        //        {"{pumps}","{5}" },
        //        {"{coor}","{6}" },
        //        {"{curve}","{7}" },
        //    };
        //    dictExchange.ToList().ForEach(m => tempString = tempString.Replace(m.Key, m.Value));
        //    StringBuilder junctionStringBuilder = new StringBuilder();
        //    junctionStringBuilder.AppendLine(";ID                 Elev           Demand         Pattern         Type");
        //    Nodes.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        if (o is JunctionModel j)
        //            junctionStringBuilder.AppendLine(j.ToString() + $"0\tJunction");
        //        else if (o is MeterModel m)
        //            junctionStringBuilder.AppendLine(m.ToString() + $"0\tMeter");
        //        else if (o is NozzleModel no)
        //            junctionStringBuilder.AppendLine(no.ToString() + $"0\tNozzle\t{no.FlowCoefficient}");
        //    });
        //    string junctionString = junctionStringBuilder.ToString();
        //    StringBuilder reservoirStringBuilder = new StringBuilder();
        //    reservoirStringBuilder.AppendLine(";ID                 Head           Pattern ");
        //    Reservos.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        reservoirStringBuilder.AppendLine(o.ToString() + $"0\t{o.Elev}");
        //    });
        //    string reserverString = reservoirStringBuilder.ToString();
        //    StringBuilder tankStringBuilder = new StringBuilder();
        //    tankStringBuilder.AppendLine(";ID                 Elevation      InitLevel      MinLevel       MaxLevel       Diameter       MinVol         VolCurve           Overflow");
        //    Tanks.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        tankStringBuilder.AppendLine(o.ToString() + $"0");
        //    });
        //    string tankString = tankStringBuilder.ToString();
        //    StringBuilder pipeStringBuilder = new StringBuilder();
        //    pipeStringBuilder.AppendLine(";ID                 Node1              Node2              Length         Diameter       Roughness      MinorLoss      Status");
        //    Links.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        if (o is PipeModel p)
        //            pipeStringBuilder.AppendLine(p.ToString() + $"0");
        //        //else if (o is RepeaterViewModel r)
        //        //    pipeStringBuilder.AppendLine(r.ToString());
        //    });
        //    string pipeString = pipeStringBuilder.ToString();
        //    StringBuilder valveStringBuilder = new StringBuilder();
        //    valveStringBuilder.AppendLine(";ID                 Node1              Node2              Diameter       Type   Setting        MinorLoss  ");
        //    Valves.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        valveStringBuilder.AppendLine(o.ToString() + $"0");
        //    });
        //    string valveString = valveStringBuilder.ToString();
        //    StringBuilder pumpStringBuilder = new StringBuilder();
        //    pumpStringBuilder.AppendLine(";ID                 Node1              Node2              Diameter       Type   Setting        MinorLoss  ");
        //    Pumps.ForEach(o =>
        //    {
        //        //if (!o.Visible) return;
        //        pumpStringBuilder.AppendLine(o.ToString() + $"0");
        //    });
        //    string pumpString = pumpStringBuilder.ToString();
        //    StringBuilder curveStringBuilder = new StringBuilder();
        //    //pumps.ForEach(o =>
        //    //{
        //    //    if (!o.Visible || !o.Datasets.ContainsKey("流量扬程曲线")) return;
        //    //    curveStringBuilder.AppendLine(o.Datasets["流量扬程曲线"].ToString());
        //    //});
        //    if (dict_dataset != null)
        //        foreach (var kp in dict_dataset)
        //        {
        //            curveStringBuilder.AppendLine(kp.Value.ToString());
        //        }
        //    string curveString = curveStringBuilder.ToString();
        //    StringBuilder coorStringBuilder = new StringBuilder();
        //    if (userCoorString == null)
        //    {
        //        coorStringBuilder.AppendLine(";Node               X-Coord              Y-Coord");
        //        Nodes.ForEach(o => coorStringBuilder.AppendLine(o.ToCoorString()));
        //    }
        //    else
        //    {
        //        coorStringBuilder.Append(userCoorString);
        //    }
        //    string coorString = coorStringBuilder.ToString();
        //    string output = "";
        //    StringBuilder emitterStringBuilder = new StringBuilder();
        //    emitterStringBuilder.AppendLine(";Junction        \tCoefficient");
        //    Nodes.ForEach(o => emitterStringBuilder.Append(o.ToEmitterString()));
        //    string emitterString = emitterStringBuilder.ToString();
        //    StringBuilder statusStringBuilder = new StringBuilder();
        //    statusStringBuilder.AppendLine(";ID              \tStatus/Setting\r\n");
        //    Links.ForEach(o => statusStringBuilder.Append(o.ToStatusString()));
        //    string statusString = statusStringBuilder.ToString();
        //    output = tempString;
        //    output = ReplaceContent(output, "JUNCTIONS", junctionString);
        //    output = ReplaceContent(output, "RESERVOIRS", reserverString);
        //    output = ReplaceContent(output, "TANKS", tankString);
        //    output = ReplaceContent(output, "PIPES", pipeString);
        //    output = ReplaceContent(output, "VALVES", valveString);
        //    output = ReplaceContent(output, "PUMPS", pumpString);
        //    output = ReplaceContent(output, "CURVES", curveString);
        //    output = ReplaceContent(output, "COORDINATES", coorString);
        //    output = ReplaceContent(output, "EMITTERS", emitterString);
        //    output = ReplaceContent(output, "STATUS", statusString);
        //    string backupFolderPath = Path.Combine(Path.GetDirectoryName(filePath), "bk");
        //    if (!Directory.Exists(backupFolderPath))
        //    {
        //        Directory.CreateDirectory(backupFolderPath);
        //    }
        //    string backupFileName = $"{Path.GetFileNameWithoutExtension(filePath)}_{DateTime.Now:yyyyMMddHHmmss}{Path.GetExtension(filePath)}";
        //    string backupFilePath = Path.Combine(backupFolderPath, backupFileName);
        //    if (File.Exists(filePath)) File.Copy(filePath, backupFilePath, true);
        //    // 检查文件是否存在
        //    try
        //    {
        //        Global.ClearFileReadOnly(filePath);
        //        File.WriteAllText(filePath, output);
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(ex.Message);
        //    }
        //    //MessageBox.Show($"保存成功!");
        //}
        /// <summary>
        /// 根据Inp文件计算
        /// </summary>
@@ -739,9 +955,15 @@
            HydraulicModel.Epanet epanet = new HydraulicModel.Epanet();
            var result = new List<TimePoint>();
            var err = epanet.open(InpPath, "d:\\5.log", "");
            if (err != 0)
            {
                throw new Exception($"计算失败:{err}");
                throw new Exception($"打开计算文件失败:{err}");
            }
            var errCal = epanet.solveH();
            if (errCal != 0)
            {
                throw new Exception($"计算失败:{errCal}");
            }
            int nodeCount = 0, linkCount = 0;
            epanet.getcount((int)CountType.Node, ref nodeCount);
@@ -792,7 +1014,7 @@
        /// <returns></returns>
        public virtual List<TimePoint> Calc()
        {
            var inpPath = Path.Combine(Directory.GetCurrentDirectory(), @"data\inp\calc.inp");
            var inpPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\inp\calc.inp");
            BuildToInp(inpPath);
            return Calc(inpPath);
        }
@@ -810,17 +1032,24 @@
        private string ReplaceContent(string text, string content, string replaceString)
        {
            string str = replaceString;
            string replacedText = ReplaceCoordinatesSection(text, content, str);
            return replacedText;
            //Console.WriteLine(replacedText);
        }
        private string ReplaceCoordinatesSection(string text, string content, string str)
        public static string ReplaceCoordinatesSection(string text, string content, string str)
        {
            string pattern = $@"(\[{content}\]).*?(\[|$)";
            string replacedText = Regex.Replace(text, pattern, match =>
            {
                string section = match.Groups[2].Value.Trim();
                if (!string.IsNullOrEmpty(section))
                {
                    return $"{match.Groups[1].Value}\n{str}\n[";
@@ -830,7 +1059,9 @@
                    return $"{match.Groups[1].Value}\n{str}\n[";
                }
            }, RegexOptions.Singleline);
            return replacedText;
        }
    }
}