namespace Yw.Epanet { /// /// 管网检查拓展 /// public static class NetworkCheckExtensions { /// /// 根据Inp文件计算 /// public static CheckResult Check(this Network nw) { if (nw == null) { return default; } var result = new CheckResult(); //构件重复 var allParterList = nw.GetAllParters(); if (allParterList != null && allParterList.Count > 0) { var parters = allParterList.Distinct().ToList(); if (parters.Count != allParterList.Count) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.RepeatParer, FailReason = "构件重复,请联系开发人员" }); } } //编码为空 if (allParterList != null && allParterList.Count > 0) { foreach (var parter in allParterList) { if (string.IsNullOrEmpty(parter.Id?.Trim())) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.EmptyId, FailReason = $"[{parter.Name}]构件编码为空,请联系开发人员" }); } } } //编码重复 if (allParterList != null && allParterList.Count > 0) { var parters = allParterList.Distinct().ToList(); var parterIds = parters.Select(x => x.Id).Distinct().ToList(); if (parters.Count != parterIds.Count) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.RepeatId, FailReason = $"构件编码重复,请联系开发人员" }); } } //缺少水源 var allSourceList = nw.GetAllSources(); if (allSourceList == null || allSourceList.Count < 1) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.LackSource, FailReason = "缺少水源,至少需包含一座水库或水池" }); } //缺少连接节点 var allJunctionList = nw.GetAllJunctions(); if (allJunctionList == null || allJunctionList.Count < 1) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.LackJunction, FailReason = "缺少连接节点,至少需包含一个连接节点" }); } //孤立节点 var allNodeList = nw.GetAllNodes(); if (allNodeList != null && allNodeList.Count > 0) { foreach (var node in allNodeList) { if (node.Links == null || node.Links.Count < 1) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = node.Id, CheckType = eCheckType.AloneNode, FailReason = $"孤立节点[{node.Name}],没有任何管段连接" }); } } } //节点连接异常 if (allNodeList != null && allNodeList.Count > 0) { foreach (var node in allNodeList) { if (node.Links != null && node.Links.Count > 0) { var links = node.Links.Distinct().ToList(); if (links.Count != node.Links.Count) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = node.Id, CheckType = eCheckType.AbnormalNodeConnected, FailReason = $"[{node.Name}]节点连接异常" }); } } } } //孤立管段 var allLinkList = nw.GetAllLinks(); if (allLinkList != null && allLinkList.Count > 0) { foreach (var link in allLinkList) { if (link.StartNode == null && link.EndNode == null) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = link.Id, CheckType = eCheckType.AloneLink, FailReason = $"孤立管段[{link.Name}],没有连接任何节点" }); } } } //管段缺少连接节点 if (allLinkList != null && allLinkList.Count > 0) { foreach (var link in allLinkList) { if (link.StartNode != null || link.EndNode != null) { if (link.StartNode == null) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = link.Id, CheckType = eCheckType.LackLinkNode, FailReason = $"[{link.Name}]缺少上游节点" }); } if (link.EndNode == null) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = link.Id, CheckType = eCheckType.LackLinkNode, FailReason = $"[{link.Name}]缺少下游节点" }); } } } } //管段异常连接 if (allLinkList != null && allLinkList.Count > 0) { foreach (var link in allLinkList) { if (link.StartNode == link.EndNode) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = link.Id, CheckType = eCheckType.AbnormalLinkConnected, FailReason = $"[{link.Name}]管段异常连接,上游与下游节点相同" }); } } } //属性设置错误 var allPipeList = nw.Pipes; if (allPipeList != null && allPipeList.Count > 0) { foreach (var pipe in allPipeList) { if (pipe.Length <= 0) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = pipe.Id, CheckType = eCheckType.ErrorPropSet, FailReason = $"[{pipe.Name}]属性设置错误,管道长度必须大于0" }); } if (pipe.Roughness <= 10 || pipe.Roughness >= 10000) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = pipe.Id, CheckType = eCheckType.ErrorPropSet, FailReason = $"[{pipe.Name}]属性设置错误,粗糙系数区间(10,10000)" }); } if (pipe.Diameter <= 10 || pipe.Diameter >= 10000) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = pipe.Id, CheckType = eCheckType.ErrorPropSet, FailReason = $"[{pipe.Name}]属性设置错误,管径区间(10,10000)" }); } } } //验证连通性 if (!IsConnectedBFS(nw)) { result.Succeed = false; result.FailedList.Add(new CheckFailed() { Id = string.Empty, CheckType = eCheckType.AbnormalConnectivity, FailReason = $"[广度优先搜索]判断管网连通性异常" }); } return result; } //采用广度优先搜索判断管网连通性 private static bool IsConnectedBFS(this Network nw) { if (nw == null) { return false; } //没有管段视为不连通 var allLinkList = nw.GetAllLinks(); if (allLinkList == null || allLinkList.Count < 1) { return false; } //管段开始节点或结束节点为空时视为不连通 if (allLinkList.Exists(x => x.StartNode == null || x.EndNode == null)) { return false; } //管段存在开始节点和结束节点相同视为不连通 if (allLinkList.Exists(x => x.StartNode == x.EndNode)) { return false; } //没有节点视为不连通 var allNodeList = nw.GetAllNodes(); if (allNodeList == null || allNodeList.Count < 1) { return false; } //收集所有出现在管道中的节点 HashSet nodes = new HashSet(); foreach (var link in allLinkList) { nodes.Add(link.StartNode); nodes.Add(link.EndNode); } // 空管网视为不连通 if (nodes.Count < 1) { return false; } //收集节点与管道所有节点不一致视为不连通 if (nodes.Count != allNodeList.Count) { return false; } // 构建邻接表 Dictionary> adjacencyList = new Dictionary>(); foreach (var node in nodes) { adjacencyList[node] = new List(); } foreach (var link in allLinkList) { adjacencyList[link.StartNode].Add(link.EndNode); adjacencyList[link.EndNode].Add(link.StartNode); } // BFS遍历 HashSet visited = new HashSet(); Queue queue = new Queue(); Node startNode = nodes.First(); queue.Enqueue(startNode); visited.Add(startNode); while (queue.Count > 0) { Node current = queue.Dequeue(); foreach (Node neighbor in adjacencyList[current]) { if (!visited.Contains(neighbor)) { visited.Add(neighbor); queue.Enqueue(neighbor); } } } // 检查是否所有节点都被访问 return visited.Count == nodes.Count; } //采用深度优先搜索判断管网连通性 private static bool IsConnectedDFS(this Network nw) { if (nw == null) { return false; } //没有管段视为不连通 var allLinkList = nw.GetAllLinks(); if (allLinkList == null || allLinkList.Count < 1) { return false; } //管段开始节点或结束节点为空时视为不连通 if (allLinkList.Exists(x => x.StartNode == null || x.EndNode == null)) { return false; } //管段存在开始节点和结束节点相同视为不连通 if (allLinkList.Exists(x => x.StartNode == x.EndNode)) { return false; } //没有节点视为不连通 var allNodeList = nw.GetAllNodes(); if (allNodeList == null || allNodeList.Count < 1) { return false; } //收集所有出现在管道中的节点 HashSet nodes = new HashSet(); foreach (var link in allLinkList) { nodes.Add(link.StartNode); nodes.Add(link.EndNode); } // 空管网视为不连通 if (nodes.Count < 1) { return false; } //收集节点与管道所有节点不一致视为不连通 if (nodes.Count != allNodeList.Count) { return false; } // 构建邻接表 Dictionary> adjacencyList = new Dictionary>(); foreach (var node in nodes) { adjacencyList[node] = new List(); } foreach (var link in allLinkList) { adjacencyList[link.StartNode].Add(link.EndNode); adjacencyList[link.EndNode].Add(link.StartNode); } // DFS遍历(迭代式实现) HashSet visited = new HashSet(); Stack stack = new Stack(); Node startNode = nodes.First(); stack.Push(startNode); visited.Add(startNode); while (stack.Count > 0) { Node current = stack.Pop(); foreach (Node neighbor in adjacencyList[current]) { if (!visited.Contains(neighbor)) { visited.Add(neighbor); stack.Push(neighbor); // 邻接节点入栈 } } } // 检查是否所有节点都被访问 return visited.Count == nodes.Count; } } }