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; }
}
}