namespace Yw.EPAnet
|
{
|
/// <summary>
|
/// 管网检查拓展
|
/// </summary>
|
public static class NetworkCheckExtensions
|
{
|
/// <summary>
|
/// 根据Inp文件计算
|
/// </summary>
|
public static CheckResult Check(this Network network)
|
{
|
var result = new CheckResult();
|
|
//Network 为 null 验证
|
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,
|
CheckType = CheckType.SourceLack,
|
FailReason = "缺少水源,至少需包含一座水库或水池(水箱)"
|
});
|
}
|
|
//缺少连接节点
|
var allJunctionList = network.GetAllJunctions();
|
if (allJunctionList == null || allJunctionList.Count < 1)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = string.Empty,
|
CheckType = CheckType.JunctionLack,
|
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,
|
CheckType = CheckType.NodeAlone,
|
FailReason = $"孤立节点[{node.Name}],没有任何管段连接"
|
});
|
}
|
else if (node is Elbow)
|
{
|
if (node.Links.Count != 2)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"弯头[{node.Name}]连接管段数异常,连接管段数必须为2"
|
});
|
}
|
else
|
{
|
var pipe1 = node.Links[0] as Pipe;
|
var pipe2 = node.Links[1] as Pipe;
|
if (pipe1 == null || pipe2 == null || pipe1.Diameter != pipe2.Diameter)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"弯头[{node.Name}]必须连接2跟管段,且两根管段管径需一致"
|
});
|
}
|
}
|
}
|
else if (node is Threelink)
|
{
|
if (node.Links.Count != 3)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"三通[{node.Name}]连接管段数异常,连接管段数必须为3"
|
});
|
}
|
else
|
{
|
var pipe1 = node.Links[0] as Pipe;
|
var pipe2 = node.Links[1] as Pipe;
|
var pipe3 = node.Links[2] as Pipe;
|
if (pipe1 == null || pipe2 == null || pipe3 == null || pipe1.Diameter != pipe2.Diameter && pipe2.Diameter != pipe3.Diameter && pipe3.Diameter != pipe1.Diameter)
|
{
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"弯头[{node.Name}]必须连接3跟管线,且至少两根管线管径需一致"
|
});
|
}
|
}
|
}
|
else if (node is Fourlink)
|
{
|
if (node.Links.Count != 4)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"四通点[{node.Name}]连接管线数异常,连接管线数必须为4"
|
});
|
}
|
else
|
{
|
var pipe1 = node.Links[0] as Pipe;
|
var pipe2 = node.Links[1] as Pipe;
|
var pipe3 = node.Links[2] as Pipe;
|
var pipe4 = node.Links[3] as Pipe;
|
if (pipe1 == null || pipe2 == null || pipe3 == null || pipe4 == null || pipe1.Diameter != pipe2.Diameter || pipe1.Diameter != pipe3.Diameter || pipe1.Diameter != pipe4.Diameter)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = node.Id,
|
CheckType = CheckType.NodeAbnormalConnected,
|
FailReason = $"四通点[{node.Name}]必须连接4跟管线,且所有连接管线管径需一致"
|
});
|
}
|
}
|
}
|
|
}
|
|
//验证管段
|
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,
|
CheckType = CheckType.LinkAlone,
|
FailReason = "孤立管段,没有连接任何管段"
|
});
|
}
|
else
|
{
|
if (link.StartNode == null)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
CheckType = CheckType.LinkLackNode,
|
FailReason = "管段缺少节点,缺少上游节点"
|
});
|
}
|
else if (link.EndNode == null)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
CheckType = CheckType.LinkLackNode,
|
FailReason = "管段缺少节点,缺少下游节点"
|
});
|
}
|
else
|
{
|
if (link.StartNode.Id == link.EndNode.Id)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = link.Id,
|
CheckType = CheckType.LinkAbnormalConnected,
|
FailReason = "管段异常连接,上游与下游节点相同"
|
});
|
}
|
}
|
}
|
|
//验证管道
|
if (link is Pipe pipe)
|
{
|
if (pipe.Length <= 0)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
CheckType = CheckType.PropSetError,
|
FailReason = "属性设置错误,管道长度必须大于0"
|
});
|
}
|
if (pipe.Roughness <= 5 || pipe.Roughness > 10000)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
CheckType = CheckType.PropSetError,
|
FailReason = "属性设置错误,粗糙系数区间(5,10000】"
|
});
|
}
|
if (pipe.Diameter <= 10 || pipe.Diameter > 10000)
|
{
|
result.Succeed = false;
|
result.FailedList.Add(new CheckFailed()
|
{
|
ParterId = pipe.Id,
|
CheckType = CheckType.PropSetError,
|
FailReason = "属性设置错误,管径区间(10,10000】"
|
});
|
}
|
}
|
}
|
|
//验证连通性
|
var objs = network.GetAllLinks().ToList();
|
objs = objs.Distinct().ToList();
|
var visitedNodes = new HashSet<Node>();
|
var FindObjs = new HashSet<Visual>();
|
var resultObjs = new List<List<Visual>>();
|
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,
|
CheckType = CheckType.Disconnected,
|
FailReason = $"管网中有{resultObjs.Count}个独立连通性区域,其中{NumErrRegion}个没有包含水池或水库"
|
});
|
}
|
|
|
|
return result;
|
}
|
|
/// <summary>
|
/// 遍历管网
|
/// </summary>
|
private static List<Visual> TraversePipeNetworkALL(Link startLink, HashSet<Node> visitedNodes, HashSet<Visual> FindObjs)
|
{
|
List<Visual> result = new List<Visual>();
|
Queue<Link> queue = new Queue<Link>();
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<Node>();
|
//visitedNodes.Add(startLink.StartNode);
|
//visitedNodes.Add(startLink.EndNode);
|
|
while (queue.Count > 0)
|
{
|
Link currentLink = queue.Dequeue();
|
//Console.WriteLine("Traversing Link: " + currentLink.ID);
|
|
foreach (var node in new Node[] { 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;
|
|
|
}
|
|
|
}
|
}
|