namespace Yw.EPAnet
|
{
|
/// <summary>
|
/// 管网检查拓展
|
/// </summary>
|
public static class NetworkCheckExtensions
|
{
|
/// <summary>
|
/// 根据Inp文件计算
|
/// </summary>
|
/// <returns></returns>
|
public static CheckResult Check(this Network network)
|
{
|
var result = new CheckResult();
|
if (network == null)
|
{
|
result.Succeed = false;
|
return result;
|
}
|
|
//验证水源
|
var allSourceList = network.GetAllSources();
|
if (allSourceList == null || allSourceList.Count < 1)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = string.Empty,
|
FailType = eCheckFailType.LackSource,
|
FailReason = "缺少水源,至少需包含一座水库或水池"
|
});
|
}
|
|
//验证连接节点
|
var allJunctionList = network.GetAllJunctions();
|
if (allJunctionList == null || allJunctionList.Count < 1)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = string.Empty,
|
FailType = eCheckFailType.LackJunction,
|
FailReason = "缺少连接节点,至少需包含一个连接节点"
|
});
|
}
|
|
//验证节点
|
var allNodeList = network.GetAllNodes();
|
foreach (var node in allNodeList)
|
{
|
if (node.Links == null || node.Links.Count < 1)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
FailType = eCheckFailType.AloneNode,
|
FailReason = "孤立节点,没有任何管段连接"
|
});
|
}
|
else
|
{
|
if (node.Links.Exists(x => x is INode))
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
FailType = eCheckFailType.NodeAbnormalConnected,
|
FailReason = "节点异常连接,存在节点连接"
|
});
|
}
|
}
|
}
|
|
//验证管段
|
var allLinkList = network.GetAllLinks();
|
foreach (var link in allLinkList)
|
{
|
if (link.StartNode == null && link.EndNode == null)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.AloneLink,
|
FailReason = "孤立管段,没有连接任何管段"
|
});
|
}
|
else
|
{
|
if (link.StartNode == null)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.LinkLossNode,
|
FailReason = "管段缺少节点,缺少上游节点"
|
});
|
}
|
else if (link.EndNode == null)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.LinkLossNode,
|
FailReason = "管段缺少节点,缺少下游节点"
|
});
|
}
|
else
|
{
|
if (link.StartNode.Id == link.EndNode.Id)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.LinkAbnormalConnected,
|
FailReason = "管段异常连接,上游与下游节点相同"
|
});
|
}
|
if (link.StartNode is not INode)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.LinkAbnormalConnected,
|
FailReason = "管段异常连接,上游未连接节点"
|
});
|
}
|
if (link.EndNode is not INode)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
FailType = eCheckFailType.LinkAbnormalConnected,
|
FailReason = "管段异常连接,下游未连接节点"
|
});
|
}
|
}
|
}
|
|
//验证管道
|
if (link is Pipe pipe)
|
{
|
if (pipe.Length <= 0)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
FailType = eCheckFailType.PropSetError,
|
FailReason = "属性设置错误,管道长度必须大于0"
|
});
|
}
|
if (pipe.Roughness <= 5 || pipe.Roughness > 10000)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
FailType = eCheckFailType.PropSetError,
|
FailReason = "属性设置错误,粗糙系数区间(5,10000】"
|
});
|
}
|
if (pipe.Diameter <= 10 || pipe.Diameter > 10000)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
FailType = eCheckFailType.PropSetError,
|
FailReason = "属性设置错误,管径区间(10,10000】"
|
});
|
}
|
}
|
}
|
|
//验证连通性
|
var objs = network.GetAllLinks().Select(o => o as ILink).ToList();
|
objs = objs.Distinct().ToList();
|
var visitedNodes = new HashSet<INode>();
|
var FindObjs = new HashSet<IParter>();
|
var resultObjs = new List<List<IParter>>();
|
objs.ForEach(o =>
|
{
|
//如果o的两个端点都已经被访问过,则不再访问
|
if (visitedNodes.Contains(o.StartNode) && visitedNodes.Contains(o.EndNode))
|
return;
|
var list=TraversePipeNetworkALL(o, visitedNodes, FindObjs);
|
if (list.Count > 0)
|
resultObjs.Add(list);
|
});
|
int NumErrRegion = 0;
|
resultObjs.ForEach(o =>
|
{
|
//验证o中是否包含水池或者水库,如果不包含不通过
|
if (o.Exists(x => x is Reservoir || x is Tank)) return;
|
NumErrRegion++;
|
});
|
if (NumErrRegion > 0)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = string.Empty,
|
FailType = eCheckFailType.Disconnected,
|
FailReason = $"管网中有{resultObjs.Count}个独立连通性区域,其中{NumErrRegion}个没有包含水池或水库"
|
});
|
}
|
|
|
|
return result;
|
}
|
|
|
/// <summary>
|
/// 遍历管网
|
/// </summary>
|
|
private static List<IParter> TraversePipeNetworkALL(ILink startLink, HashSet<INode> visitedNodes , HashSet<IParter> FindObjs)
|
{
|
List<IParter> result=new List<IParter>();
|
Queue<ILink> queue = new Queue<ILink>();
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<INode>();
|
//visitedNodes.Add(startLink.StartNode);
|
//visitedNodes.Add(startLink.EndNode);
|
|
while (queue.Count > 0)
|
{
|
ILink currentLink = queue.Dequeue();
|
//Console.WriteLine("Traversing Link: " + currentLink.ID);
|
|
foreach (var node in new INode[] { currentLink.StartNode, currentLink.EndNode })
|
{
|
if (visitedNodes.Contains(node))
|
{
|
result.Add(node);
|
}
|
if (node != null && !visitedNodes.Contains(node))
|
{
|
visitedNodes.Add(node);
|
result.Add(node);
|
if (!FindObjs.Contains(node)) FindObjs.Add(node);
|
|
foreach (var link in node.Links)
|
{
|
if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode))
|
{
|
if (!FindObjs.Contains(link)) FindObjs.Add(link);
|
queue.Enqueue(link);
|
result.Add(link);
|
|
}
|
}
|
}
|
}
|
|
}
|
return result;
|
|
|
}
|
|
|
}
|
}
|