namespace Yw.Epanet
|
{
|
/// <summary>
|
/// 管网路径分析拓展
|
/// </summary>
|
public static class NetworkAnalysePathExtensions
|
{
|
|
/// <summary>
|
/// 遍历下游主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkDict">所有管段计算字典</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainDownStreamPath(this Node node, Dictionary<string, CalcuLink> allCalcuLinkDict)
|
{
|
if (node == null)
|
{
|
return default;
|
}
|
if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1)
|
{
|
return default;
|
}
|
|
var visited = new HashSet<Node>();
|
var queue = new Queue<Node>();
|
queue.Enqueue(node);
|
|
var pathLinks = new List<Link>();
|
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<Link, CalcuLink>();
|
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;
|
}
|
|
/// <summary>
|
/// 遍历下游主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkList">所有管段计算列表</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainDownStreamPath(this Node node, List<CalcuLink> allCalcuLinkList)
|
{
|
var dict = allCalcuLinkList?.ToDictionary(x => x.Id);
|
return node.TraverseMainDownStreamPath(dict);
|
}
|
|
/// <summary>
|
/// 遍历上游主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkDict">所有管段计算字典</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainUpStreamPath(this Node node, Dictionary<string, CalcuLink> allCalcuLinkDict)
|
{
|
if (node == null)
|
{
|
return default;
|
}
|
if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1)
|
{
|
return default;
|
}
|
|
var visited = new HashSet<Node>();
|
var queue = new Queue<Node>();
|
queue.Enqueue(node);
|
|
var pathLinks = new List<Link>();
|
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<Link, CalcuLink>();
|
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;
|
}
|
|
/// <summary>
|
/// 遍历上游主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkList">所有管段计算列表</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainUpStreamPath(this Node node, List<CalcuLink> allCalcuLinkList)
|
{
|
var dict = allCalcuLinkList?.ToDictionary(x => x.Id);
|
return node.TraverseMainUpStreamPath(dict);
|
}
|
|
/// <summary>
|
/// 遍历主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkDict">所有管段计算字典</param>
|
/// <param name="direction">方向</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainStreamPath(this Node node, Dictionary<string, CalcuLink> allCalcuLinkDict, eTraverseDirection direction = eTraverseDirection.All)
|
{
|
if (node == null)
|
{
|
return default;
|
}
|
if (allCalcuLinkDict == null || allCalcuLinkDict.Count < 1)
|
{
|
return default;
|
}
|
List<Link> 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<Link>();
|
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;
|
}
|
|
/// <summary>
|
/// 遍历主要供水路径
|
/// </summary>
|
/// <param name="node">节点</param>
|
/// <param name="allCalcuLinkList">所有管段计算列表</param>
|
/// <param name="direction">方向</param>
|
/// <returns></returns>
|
public static List<Link> TraverseMainStreamPath(this Node node, List<CalcuLink> allCalcuLinkList, eTraverseDirection direction = eTraverseDirection.All)
|
{
|
var dict = allCalcuLinkList?.ToDictionary(x => x.Id);
|
return node.TraverseMainStreamPath(dict, direction);
|
}
|
|
/// <summary>
|
/// 获取路径损失节点列表
|
/// </summary>
|
/// <param name="nw">管网</param>
|
/// <param name="pathLinks">管段路径</param>
|
/// <param name="calcuResult">计算结果</param>
|
/// <returns></returns>
|
public static List<PathLossNode> GetPathLossNodeList(this Network nw, List<Link> 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<PathLossNode>();
|
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;
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|