namespace Yw.Epanet { /// /// 管网路径分析拓展 /// public static class NetworkAnalysePathExtensions { /// /// 遍历下游主要供水路径 /// /// 节点 /// 所有管段计算字典 /// public static List TraverseMainDownStreamPath(this Node node, Dictionary allCalcuLinkDict) { if (node == null) { return default; } if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1) { return default; } var visited = new HashSet(); var queue = new Queue(); queue.Enqueue(node); var pathLinks = new List(); while (queue.Count > 0) { var current = queue.Dequeue(); if (visited.Contains(current)) { break; } visited.Add(current); if (current.Links != null && current.Links.Count > 0) { var linkDict = new Dictionary(); foreach (var link in current.Links) { var calcuLink = allCalcuLinkDict.GetValue(link.Id); if (calcuLink != null) { if (link.StartNodeId == current.Id) { if (calcuLink.Flow > 0) { linkDict.Add(link, calcuLink); } } else if (link.EndNodeId == current.Id) { if (calcuLink.Flow < 0) { linkDict.Add(link, calcuLink); } } } } if (linkDict.Count > 0) { var linkKeyValue = linkDict.OrderBy(x => Math.Abs(x.Value.Flow)).LastOrDefault(); pathLinks.Add(linkKeyValue.Key); var nextNode = linkKeyValue.Key.GetEndNode(linkKeyValue.Value); if (nextNode != null) { queue.Enqueue(nextNode); } } } } return pathLinks; } /// /// 遍历下游主要供水路径 /// /// 节点 /// 所有管段计算列表 /// public static List TraverseMainDownStreamPath(this Node node, List allCalcuLinkList) { var dict = allCalcuLinkList?.ToDictionary(x => x.Id); return node.TraverseMainDownStreamPath(dict); } /// /// 遍历上游主要供水路径 /// /// 节点 /// 所有管段计算字典 /// public static List TraverseMainUpStreamPath(this Node node, Dictionary allCalcuLinkDict) { if (node == null) { return default; } if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1) { return default; } var visited = new HashSet(); var queue = new Queue(); queue.Enqueue(node); var pathLinks = new List(); while (queue.Count > 0) { var current = queue.Dequeue(); if (visited.Contains(current)) { break; } visited.Add(current); if (current.Links != null && current.Links.Count > 0) { var linkDict = new Dictionary(); foreach (var link in current.Links) { var calcuLink = allCalcuLinkDict.GetValue(link.Id); if (calcuLink != null) { if (link.StartNodeId == current.Id) { if (calcuLink.Flow < 0) { linkDict.Add(link, calcuLink); } } else if (link.EndNodeId == current.Id) { if (calcuLink.Flow > 0) { linkDict.Add(link, calcuLink); } } } } if (linkDict.Count > 0) { var linkKeyValue = linkDict.OrderBy(x => Math.Abs(x.Value.Flow)).LastOrDefault(); pathLinks.Add(linkKeyValue.Key); var nextNode = linkKeyValue.Key.GetStartNode(linkKeyValue.Value); if (nextNode != null) { queue.Enqueue(nextNode); } } } } return pathLinks; } /// /// 遍历上游主要供水路径 /// /// 节点 /// 所有管段计算列表 /// public static List TraverseMainUpStreamPath(this Node node, List allCalcuLinkList) { var dict = allCalcuLinkList?.ToDictionary(x => x.Id); return node.TraverseMainUpStreamPath(dict); } /// /// 遍历主要供水路径 /// /// 节点 /// 所有管段计算字典 /// 方向 /// public static List TraverseMainStreamPath(this Node node, Dictionary allCalcuLinkDict, eTraverseDirection direction = eTraverseDirection.All) { if (node == null) { return default; } if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1) { return default; } List pathLinks = null; switch (direction) { case eTraverseDirection.Up: { pathLinks = TraverseMainUpStreamPath(node, allCalcuLinkDict); } break; case eTraverseDirection.Down: { pathLinks = TraverseMainDownStreamPath(node, allCalcuLinkDict); } break; case eTraverseDirection.All: { pathLinks = new List(); var pathUpLinks = TraverseMainUpStreamPath(node, allCalcuLinkDict); if (pathUpLinks != null && pathUpLinks.Count > 0) { pathLinks.AddRange(pathUpLinks); } var pathDownLinks = TraverseMainDownStreamPath(node, allCalcuLinkDict); if (pathDownLinks != null && pathDownLinks.Count > 0) { pathLinks.AddRange(pathDownLinks); } } break; default: break; } return pathLinks; } /// /// 遍历主要供水路径 /// /// 节点 /// 所有管段计算列表 /// 方向 /// public static List TraverseMainStreamPath(this Node node, List allCalcuLinkList, eTraverseDirection direction = eTraverseDirection.All) { var dict = allCalcuLinkList?.ToDictionary(x => x.Id); return node.TraverseMainStreamPath(dict, direction); } /// /// 获取路径损失节点列表 /// /// 管网 /// 管段路径 /// 计算结果 /// public static List GetPathLossNodeList(this Network nw, List pathLinks, CalcuResult calcuResult) { #region 验证 if (nw == null) { return default; } if (pathLinks == null || pathLinks.Count < 1) { return default; } if (calcuResult == null) { return default; } if (!calcuResult.Succeed) { return default; } var allCalcuNodeDict = calcuResult.GetNodeDict(); if (allCalcuNodeDict == null || allCalcuNodeDict.Count < 1) { return default; } var allCalcuLinkDict = calcuResult.GetLinkDict(); if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1) { return default; } #endregion double distance = 0; var allPathLossNodeList = new List(); for (int i = 0; i < pathLinks.Count; i++) { var link = pathLinks[i]; var calcuLink = allCalcuLinkDict.GetValue(link.Id); if (calcuLink == null) { continue; } var startNode = link.GetStartNode(calcuLink); if (startNode == null) { continue; } var startCalcuNode = allCalcuNodeDict.GetValue(startNode.Id); if (startCalcuNode == null) { continue; } var startPathLossNode = new PathLossNode() { Id = startNode.Id, Elev = startNode.GetElev(), Distance = distance, Head = startCalcuNode.Head, MinorLoss = startCalcuNode.MinorLoss }; allPathLossNodeList.Add(startPathLossNode); if (link is Pipe pipe) { distance += pipe.Length; } else if (link is Pump pump) { distance += ConstParas.DefaultPumpLength; } else if (link is Valve) { distance += ConstParas.DefaultValveLength; } if (i == pathLinks.Count - 1) { var endNode = link.GetEndNode(calcuLink); if (endNode == null) { continue; } var endCalcuNode = allCalcuNodeDict.GetValue(endNode.Id); if (endCalcuNode == null) { continue; } var endPathLossNode = new PathLossNode() { Id = endNode.Id, Elev = endNode.GetElev(), Distance = distance, Head = endCalcuNode.Head, MinorLoss = endCalcuNode.MinorLoss }; allPathLossNodeList.Add(endPathLossNode); } } return allPathLossNodeList; } } }