using System.Data; namespace Yw.EPAnet { /// /// 管网路径分析拓展 /// public static class NetworkPathAnalyseExtensions { internal class InnerLossNode { public string Id { get; set; } /// /// 起始水头 /// public double StartHead { get; set; } /// /// 结束水头 /// public double EndHead { get; set; } /// /// 高程 /// public double Elev { get; set; } /// /// 水头 /// public double Head { get; internal set; } /// /// 局部水头损失 /// public double MinorHeadLoss { get; set; } = 0; public double Distance { get; set; } } public static List GetChartNodeByPathLinks(this Network network, List links, CalcuResult calcuResult) { var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); double length = 0; InnerLossNode nodeEnd = new InnerLossNode(); List chartNodes = new List(); for (int i = 0; i < links.Count; i++) { var link = links[i]; var node = dictLinks[link.Id].Flow > 0 ? link.StartNode : link.EndNode; double elev = getElev(node); var Cnode = new InnerLossNode() { Id = node.Id, StartHead = dictNodes[node.Id].Head, Head = dictNodes[node.Id].Head, EndHead = dictNodes[node.Id].Head, Elev = elev, Distance = length }; chartNodes.Add(Cnode); var nodeEnd0 = dictLinks[link.Id].Flow > 0 ? link.EndNode : link.StartNode; nodeEnd.Id = nodeEnd0.Id; nodeEnd.Head = nodeEnd.StartHead = nodeEnd.EndHead = dictNodes[nodeEnd0.Id].Head; nodeEnd.Elev = getElev(nodeEnd0); if (link is Pipe p) length += p.Length; } nodeEnd.Distance = length; chartNodes.Add(nodeEnd); for (int i = 0; i < links.Count; i++) { var link = links[i]; Pipe p = link as Pipe; if (p != null) { //根据p.diameter和p.flow计算流速 double velocity = dictLinks[p.Id].Flow / (Math.PI * Math.Pow(p.Diameter / 2, 2)); //根据流速计算局部水头损失 double minorloss1 = dictLinks[p.Id].StartMinorLoss; double minorloss2 = dictLinks[p.Id].EndMinorLoss; if (i < links.Count - 1) { chartNodes[i].EndHead = chartNodes[i].Head - minorloss1; chartNodes[i].MinorHeadLoss += minorloss1; chartNodes[i + 1].StartHead = chartNodes[i + 1].Head + minorloss2; chartNodes[i + 1].MinorHeadLoss += minorloss2; } else { chartNodes[i].EndHead = chartNodes[i].Head - minorloss1; chartNodes[i].MinorHeadLoss += minorloss1; } } } List lossNodes = new List(); for (int i = 0; i < chartNodes.Count; i++) { var node = chartNodes[i]; LossNode lossNode = new LossNode() { Id = node.Id, Elev = node.Elev, Head = node.StartHead, MinorLoss = node.MinorHeadLoss, Distance = node.Distance, }; lossNodes.Add(lossNode); } return lossNodes; } private static double getElev(Node node) { double elev = 0; if (node is Tank tank) { elev = tank.PoolElev + tank.InitLevel; } else if (node is Reservoir reser) { elev = reser.Head; } else if (node is Junction junc) { elev = junc.Elev; } return elev; } /// /// 分析下游主要供水路径 /// public static List AnalyzeDownstreamPath(this Network network, Node startJunc, CalcuResult calcuResult) { var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); var visitedNodes = new HashSet(); visitedNodes.Add(startJunc); var nextLinks = startJunc.GetNextLinks(calcuResult.LinkList); if (nextLinks == null || nextLinks.Count <= 0) return nextLinks; var maxlink = nextLinks.OrderByDescending(o => Math.Abs(dictLinks[o.Id].Flow)).ToList()[0]; return network.TraversePipeNetworkALL(maxlink, visitedNodes, 1, true, calcuResult); } /// /// 分析上游主要供水路径 /// /// /// /// public static List AnalyzeUpstreamPath(this Network network, Node startJunc, CalcuResult calcuResult) { var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); var visitedNodes = new HashSet(); visitedNodes.Add(startJunc); var prevLinks = startJunc.GetPrevLinks(calcuResult.LinkList); if (prevLinks == null || prevLinks.Count <= 0) return prevLinks; var maxlink = prevLinks.OrderByDescending(o => Math.Abs(dictLinks[o.Id].Flow)).ToList()[0]; return network.TraversePipeNetworkALL(maxlink, visitedNodes, -1, true, calcuResult); } /// /// 宽度搜索遍历管网 /// /// /// 起始管线 /// 遍历的哈希表(用于多点遍历) /// 遍历方向,0表示双向,1表示正向,-1表示反向 /// 是否只取最大流量的分支 /// public static List TraversePipeNetworkALL(this Network network, Link startLink, HashSet visitedNodes, int direction = 0, bool isOnlyMax = false, CalcuResult calcuResult = null) { var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); var _links主要路径 = new List(); if (isOnlyMax) _links主要路径.Add(startLink); Queue queue = new Queue(); queue.Enqueue(startLink); while (queue.Count > 0) { Link currentLink = queue.Dequeue(); if (isOnlyMax) _links主要路径.Add(currentLink); foreach (var node in new Node[] { currentLink.StartNode, currentLink.EndNode }) { if (direction == 1 && dictLinks[currentLink.Id].Flow >= 0 && node == currentLink.StartNode) continue; if (direction == -1 && dictLinks[currentLink.Id].Flow <= 0 && node == currentLink.EndNode) continue; if (node != null && !visitedNodes.Contains(node)) { visitedNodes.Add(node); List list = new List(); foreach (var link in node.Links) { if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode)) { list.Add(link); } } if (!isOnlyMax) { foreach (var link in list) { queue.Enqueue(link); } } else { if (list.Count >= 1) { var maxlist = list.OrderByDescending(p => Math.Abs(dictLinks[p.Id].Flow)).ToList()[0]; queue.Enqueue(maxlist); } } } } } if (direction <0) { _links主要路径.Reverse(); } return _links主要路径; } } public class LossNode { public string Id { get; set; } /// /// 高程 /// public double Elev { get; set; } /// /// 水头 /// public double Head { get; set; } /// /// 局部水头损失 /// public double MinorLoss { get; set; } /// /// 距离 /// public double Distance { get; set; } } }