using Hydro.Core.Model; using Hydro.Inp; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Numerics; using System.Text; using System.Threading; using System.Threading.Tasks; using static Hydro.Core.ObjectEnum; using Hydro.MapView.Common; using static Hydro.MapView.MapViewEnum; using Hydro.CommonBase; using TimePoint = Hydro.CommonBase.TimePoint; using System.Runtime.InteropServices; using Hydro.HydraulicOptimizer; using Hydro.Core; using System.Xml.Linq; namespace Hydro.MapView { [Serializable] public partial class MapViewNetWork : NetWork { bool use_old = false; public string Name; private LinkViewModelList _links=new LinkViewModelList(); public LinkViewModelList Links { get { return _links; } set { base.Links= _links = value; } } private NodeViewModelList _nodes = new NodeViewModelList(); public NodeViewModelList Nodes { get { return _nodes; }set { base.Nodes = _nodes = value; } } public NodeViewModel StartPoint { get; set; } public NodeViewModel EndPoint { get; set; } public double[] getMinMax(ColourType colourType) { //根据当前选中的ColourType,判断是否有对应的网络数据 double max = 0; double min = 0; switch (colourType) { case ColourType.节点自由压力: max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_PRESSURE); min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_PRESSURE); break; case ColourType.节点绝对压力: max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_PRESSURE); min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_PRESSURE); break; case ColourType.节点需水量: max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_DEMAND); min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_DEMAND); break; case ColourType.管线流量: max = Links.Max(link => link.EN_FLOW); min = Links.Min(link => link.EN_FLOW); break; case ColourType.管线流速: max = Links.Max(link => link.EN_VELOCITY); min = Links.Min(link => link.EN_VELOCITY); break; default: break; } return new double[] { min, max }; } /// /// 当量集合,当量模板ID,<器具ID,数量> /// //public Dictionary> DlList { get; set; } /// /// 核心承载字段 /// //public new List Nodes = new List(); /// /// 核心承载字段 /// //public new List Links = new List(); [JsonIgnore] public Dictionary dict_dataset = new Dictionary(); [JsonIgnore] public HashSet Hash_ID; [JsonIgnore] public List junctions { get { return Nodes.FindAll(n => n is JunctionViewModel).Select(n => n as JunctionViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is JunctionViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List reservoirs { get { return Nodes.FindAll(n => n is ReservoirViewModel).Select(n => n as ReservoirViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is ReservoirViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List tanks { get { return Nodes.FindAll(n => n is TankViewModel).Select(n => n as TankViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is TankViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List meters { get { return Nodes.FindAll(n => n is MeterViewModel).Select(n => n as MeterViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is MeterViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List nozzles { get { return Nodes.FindAll(n => n is NozzleViewModel).Select(n => n as NozzleViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is NozzleViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List pipes { get { return Links.FindAll(n => n is PipeViewModel).Select(n => n as PipeViewModel).ToList(); } set { if (value == null) return; Links.RemoveAll(n => n is PipeViewModel); Links.AddRange(value); } } [JsonIgnore] public List valves { get { return Links.FindAll(n => n is ValveViewModel).Select(n => n as ValveViewModel).ToList(); } set { if (value == null) return; Links.RemoveAll(n => n is ValveViewModel); Links.AddRange(value); } } [JsonIgnore] public List valveNodes { get { return Nodes.FindAll(n => n is ValveNodeViewModel).Select(n => n as ValveNodeViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is ValveNodeViewModel); Nodes.AddRange(value); } } [JsonIgnore] public List repeaters { get { return Links.FindAll(n => n is RepeaterViewModel).Select(n => n as RepeaterViewModel).ToList(); } set { if (value == null) return; Links.RemoveAll(n => n is RepeaterViewModel); Links.AddRange(value); } } [JsonIgnore] public List pumps { get { return Links.FindAll(n => n is PumpViewModel).Select(n => n as PumpViewModel).ToList(); } set { if (value == null) return; Links.RemoveAll(n => n is PumpViewModel); Links.AddRange(value); } } [JsonIgnore] public List pumpNodes { get { return Nodes.FindAll(n => n is PumpNodeViewModel).Select(n => n as PumpNodeViewModel).ToList(); } set { if (value == null) return; Nodes.RemoveAll(n => n is PumpNodeViewModel); Nodes.AddRange(value); } } public List Deserialized_junctions { get; set; } public List Deserialized_tanks { get; set; } public List Deserialized_reservoirs { get; set; } public List Deserialized_meters { get; set; } public List Deserialized_nozzles { get; set; } public List Deserialized_pipes { get; set; } public List Deserialized_valves { get; set; } public List Deserialized_valveNodes { get; set; } public List Deserialized_repeaters { get; set; } public List Deserialized_pumps { get; set; } public List Deserialized_pumpNodes { get; set; } public List areas = new List(); public bool ReadFromJson(string json) { try { var net = JsonConvert.DeserializeObject(json); //net.junctions.Clear(); //net.Nodes.Clear(); junctions = net.Deserialized_junctions; tanks = net.Deserialized_tanks; reservoirs = net.Deserialized_reservoirs; meters = net.Deserialized_meters; nozzles = net.Deserialized_nozzles; pipes = net.Deserialized_pipes; valves = net.Deserialized_valves; valveNodes = net.Deserialized_valveNodes; repeaters = net.Deserialized_repeaters; pumps = net.Deserialized_pumps; pumpNodes = net.Deserialized_pumpNodes; StartPoint = net.StartPoint; EndPoint = net.EndPoint; return true; } catch { return false; } } public string WriteToJson() { var net = new MapViewNetWork(); net.Deserialized_junctions = junctions; net.Deserialized_tanks = tanks; net.Deserialized_reservoirs = reservoirs; net.Deserialized_meters = meters; net.Deserialized_nozzles = nozzles; net.Deserialized_pipes = pipes; net.Deserialized_valves = valves; //net.Deserialized_valveNodes = valveNodes; net.Deserialized_repeaters = repeaters; net.Deserialized_pumps = pumps; net.StartPoint = StartPoint; net.EndPoint = EndPoint; //net.Deserialized_pumpNodes = pumpNodes; string json = JsonConvert.SerializeObject(net); return json; } public JunctionViewModel AddJunction(string ID, PointF position, float z = 0) { JunctionViewModel j = new JunctionViewModel(); j.ID = ID; j.Demand = 0; j.PatternID = ""; j.Elev = z; j.X = position.X; j.Y = position.Y; Nodes.Add(j); return j; } public JunctionViewModel AddJunction(PointF position, float z = 0) { JunctionViewModel j = new JunctionViewModel(); int i = 0; string ID = $"{Default.GetPreString(j)}{i}"; while (Nodes.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(j)}{i}"; } j.ID = ID; j.Elev = 0; j.Demand = 0; j.PatternID = ""; j.Elev = z; j.X = position.X; j.Y = position.Y; Nodes.Add(j); return j; } public MeterViewModel AddMeter(PointF position) { MeterViewModel j = new MeterViewModel(); int i = 0; string ID = $"{Default.GetPreString(j)}{i}"; while (Nodes.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(j)}{i}"; } j.ID = ID; j.Elev = 0; j.Demand = 0; j.PatternID = ""; j.X = position.X; j.Y = position.Y; Nodes.Add(j); return j; } public ReservoirViewModel AddReservoir(PointF position) { ReservoirViewModel j = new ReservoirViewModel(); int i = 0; string ID = $"{Default.GetPreString(j)}{i}"; while (Nodes.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(j)}{i}"; } j.ID = ID; j.Elev = 0; j.Demand = 0; j.PatternID = ""; j.Head = 100; j.X = position.X; j.Y = position.Y; Nodes.Add(j); return j; } public TankViewModel AddTank(PointF position) { TankViewModel j = new TankViewModel(); int i = 0; string ID = $"{Default.GetPreString(j)}{i}"; while (Nodes.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(j)}{i}"; } j.ID = ID; j.Elev = 0; j.Demand = 0; j.PatternID = ""; j.X = position.X; j.Y = position.Y; Nodes.Add(j); return j; } public PipeViewModel AddPipe(NodeViewModel node1, NodeViewModel node2) { PipeViewModel pipe = new PipeViewModel(); int i = 0; string ID = $"{Default.GetPreString(pipe)}{i}"; while (Links.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(pipe)}{i}"; } pipe.ID = ID; pipe.Diameter = 100; pipe.MinorLoss = 0; pipe.Roughness = 100; pipe.Status = StatusType.DEFAULT; pipe.StartNode = node1; pipe.EndNode = node2; pipe.Length = -1; Links.Add(pipe); return pipe; } public ValveViewModel AddValve(NodeViewModel node1, NodeViewModel node2) { ValveViewModel valve = new ValveViewModel(); int i = 0; string ID = $"{Default.GetPreString(valve)}{i}"; while (Links.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(valve)}{i}"; } valve.ID = ID; valve.Diameter = 100; valve.Status = StatusType.DEFAULT; valve.StartNode = node1; valve.EndNode = node2; Links.Add(valve); return valve; } public RepeaterViewModel AddRepeater(NodeViewModel node1, NodeViewModel node2) { RepeaterViewModel repeater = new RepeaterViewModel(); int i = 0; string ID = $"{Default.GetPreString(repeater)}{i}"; while (Links.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(repeater)}{i}"; } repeater.ID = ID; repeater.StartNode = node1; repeater.EndNode = node2; Links.Add(repeater); return repeater; } public PumpViewModel AddPump(NodeViewModel node1, NodeViewModel node2) { PumpViewModel pump = new PumpViewModel(); int i = 0; string ID = $"{Default.GetPreString(pump)}{i}"; while (Links.Find(p0 => p0.ID == ID) != null) { i++; ID = $"{Default.GetPreString(pump)}{i}"; } pump.ID = ID; pump.StartNode = node1; pump.EndNode = node2; Links.Add(pump); return pump; } public List Remove(List list) { List objs = new List(); list.ForEach(o => { if (o == null) return; o.Selected = false; if (o is NodeViewModel n) { n.Links.ForEach(l => { if (this.Links.Remove(l)) objs.Add((LinkViewModel)l); }); if (this.Nodes.Remove(n)) objs.Add(n); } else if (o is LinkViewModel l) { if (this.Links.Remove(l)) objs.Add(l); } }); //BuildRelation(); return objs; } public void ChangePoint(NodeViewModel source, NodeViewModel newPoint) { Links.ForEach(l => { if (l.StartNode == source) { l.StartNode = newPoint; } else if (l.EndNode == source) { l.EndNode = newPoint; } }); source.Visible = false; //Nodes.Remove(source); } public void ChangeNodeID(NodeViewModel node, string ID) { node.ID = ID; node.Links.ForEach(l => { if (l.StartNode == node) { l.Node1 = node.ID; } else { l.Node2 = node.ID; } }); } public string GetValidID(IBaseViewModel obj) { string DefaultString = Default.GetPreString(obj); int i = 0; string ID = obj.ID; //List objs; ID = $"{DefaultString}{i}"; //while ((objs = MapObjects.FindAll(p0 => p0.ID == ID)).Count>1 && objs[0]!=obj) while (Hash_ID.Contains(ID)) { ID = $"{DefaultString}{i}"; i++; } return ID; } public MapViewNetWork CreateNew(PointF3D basepoint) { MapViewNetWork net = this.DeepCopy(); var BasePos = StartPoint.Position3D; net.Nodes.ForEach(n => { n.X += basepoint.X - BasePos.X; n.Y += basepoint.Y - BasePos.Y; n.Elev += basepoint.Z - BasePos.Z; }); return net; } public void AddJoinNet(MapViewNetWork network) { if (Nodes.Count == 0) { Nodes.AddRange(network.Nodes); Links.AddRange(network.Links); StartPoint = network.StartPoint; EndPoint = network.EndPoint; } else { ChangePoint(EndPoint, network.StartPoint); Nodes.AddRange(network.Nodes); Links.AddRange(network.Links); //MapObjects.ForEach(n => n.ID = GetValidID(n)); EndPoint = network.EndPoint; } } public List Add(MapViewNetWork net0, PointF3D offset = null, bool isCopy = false,NodeViewModel ConnectNode=null) { if (offset == null) { offset = new PointF3D(0, 0, 0); } List list = new List(); if (Hash_ID == null) Hash_ID = new HashSet(); MapViewNetWork net = isCopy ? net0.DeepCopy() : net0; net.Nodes.ForEach(n0 => { NodeViewModel n = (NodeViewModel)n0; if (Hash_ID.Contains(n.ID)) { string ID = GetValidID(n); net.ChangeNodeID(n, ID); } n.X += offset.X; n.Y += offset.Y; n.Elev += offset.Z; Nodes.Add(n); Hash_ID.Add(n.ID); list.Add(n); if (n0 == net.EndPoint && list[0] != n) { int index = list.IndexOf(n); var o = list[0]; list[0] = n; list[index] = o; } }); net.Links.ForEach(l0 => { LinkViewModel l = (LinkViewModel)l0; if (Hash_ID.Contains(l.ID)) { string ID = GetValidID(l); l.ID = ID; } Links.Add(l); Hash_ID.Add(l.ID); list.Add(l); }); if (ConnectNode!=null) { var l = AddPipe(ConnectNode, net.StartPoint); list.Add(l); Hash_ID.Add(l.ID); } //BuildRelation(); return list; } #region treat public void MatchAndTreat(List listA_source, List listB_source, Action treat) { //var item = listA[0]; //var propertyDescriptor = TypeDescriptor.GetProperties(item)[PropertyDescriptorName]; //listA.Sort(); //listB.Sort(); // 对 List A 和 List B 按 Key 进行排序 var listA = listA_source.OrderBy(a => a.ID).ToList(); var listB = listB_source.OrderBy(b => b.ID).ToList(); int indexA = 0; int indexB = 0; while (indexA < listA.Count && indexB < listB.Count) { //dynamic valueA = propertyDescriptor.GetValue(listA[indexA]); //dynamic valueB = propertyDescriptor.GetValue(listB[indexB]); var valueA = listA[indexA].ID; var valueB = listB[indexB].ID; var cResult = string.Compare(valueA, valueB); if (cResult == 0) { treat(listA[indexA], listB[indexB]); indexA++; indexB++; } else if (string.Compare(valueA, valueB) < 0) { indexA++; } else { indexB++; } } } public void MatchAndTreat(List listA_source, List listB_source, Action treat) { //var item = listA[0]; //var propertyDescriptor = TypeDescriptor.GetProperties(item)[PropertyDescriptorName]; //listA.Sort(); //listB.Sort(); // 对 List A 和 List B 按 Key 进行排序 var listA = listA_source.OrderBy(a => a.ID).ToList(); var listB = listB_source.OrderBy(b => b.ID).ToList(); int indexA = 0; int indexB = 0; while (indexA < listA.Count && indexB < listB.Count) { //dynamic valueA = propertyDescriptor.GetValue(listA[indexA]); //dynamic valueB = propertyDescriptor.GetValue(listB[indexB]); var valueA = listA[indexA].ID; var valueB = listB[indexB].ID; var cResult = string.Compare(valueA, valueB); if (cResult == 0) { treat(listA[indexA], listB[indexB]); indexA++; indexB++; } else if (string.Compare(valueA, valueB) < 0) { indexA++; } else { indexB++; } } } #endregion public void Add(List objects) { Nodes.AddRange(objects.FindAll(o => o is NodeViewModel).Select(o => (NodeViewModel)o)); Links.AddRange(objects.FindAll(o => o is LinkViewModel).Select(o => (LinkViewModel)o)); //BuildRelation(); } public void Clear() { Nodes.Clear(); Links.Clear(); } [JsonIgnore] public List MapObjects { get { List objects = new List(); objects.AddRange(Nodes); objects.AddRange(Links); return objects.Select(o=>(IBaseViewModel)o).ToList(); } } public void Rename() { MapObjects.ForEach(o => o.ID = $"{Name}_{o.ID}"); } public void Add(RepeaterViewModel repeater) { ChangePoint(repeater.StartNode, repeater.StartNode_inner); MoveDownNetwork(repeater); ChangePoint(repeater.EndNode, repeater.EndNode_inner); Nodes.AddRange(repeater.netList.Nodes); Links.AddRange(repeater.netList.Links); } public void LoadRepeaters(int MaxLevel, dict param, Dictionary viewModel, bool ViewMode = true) { repeaters.ForEach(r => { if (!r.Load(MaxLevel, param, viewModel, ViewMode)) { r.Status = RepeaterViewModel.RepeatStatus.收起; r.Visible = true; } else { Add(r); r.Visible = false; } }); } public void MoveDownNetwork(RepeaterViewModel repeater) { visited = new Dictionary(); visited.Add(repeater.StartNode, true); var p1 = repeater.EndNode_inner; var p2 = repeater.EndNode; PointF3D p = new PointF3D(p1.X - p2.X, p1.Y - p2.Y, p1.Elev - p2.Elev); BFS(this, repeater.EndNode, new Vector3(p.X, p.Y, p.Z)); } // 定义 visited 字典记录已访问过的节点和待访问的节点队列 Dictionary visited;//= new Dictionary(); private bool _isCalculated=false; public void BFS(MapViewNetWork net, NodeViewModel startNode, Vector3 vector) { Queue queue = new Queue(); // 标记起始节点为已访问,并加入队列 visited[startNode] = true; queue.Enqueue(startNode); // 不断从队列中取出节点进行访问,直到队列为空 while (queue.Count > 0) { // 取出队首节点并输出 NodeViewModel node = queue.Dequeue(); node.Move(vector); // 遍历当前节点的所有未访问邻居节点,并标记为已访问 foreach (LinkViewModel link in net.Links) { if (link.StartNode == node && !visited.ContainsKey(link.EndNode)) { visited[link.EndNode] = true; queue.Enqueue(link.EndNode); } else if (link.EndNode == node && !visited.ContainsKey(link.StartNode)) { visited[link.StartNode] = true; queue.Enqueue(link.StartNode); } } } } public List GetNode(string node) { return Nodes.FindAll(n => n.ID == node).Select(n=> (NodeViewModel)n).ToList(); } public List Calc(string inpPath, string configPath = null) { WdnmoParam wdnmoParam = new WdnmoParam(); Nodes.ForEach(n => { //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" }); } }); Links.ForEach(n => { //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" }); } }); calc c = new calc(); var list = c.GetCalcResult(inpPath, wdnmoParam, configPath); if (list == null) return list; list.Sort((a, b) => string.Compare(a.Key, b.Key)); Nodes.Sort((a, b) => string.Compare(a.ID, b.ID)); Links.Sort((a, b) => string.Compare(a.ID, b.ID)); SetNodeFromWparam(this, list, "Press"); SetNodeFromWparam(this, list, "Head"); SetNodeFromWparam(this, list, "Demand"); SetLinkFromWparam(this, list, "Flow"); SetLinkFromWparam(this, list, "Velocity"); SetLinkFromWparam(this, list, "Headloss"); Links.ForEach(l=> { l.EN_HEADLOSS_MINOR = (float)Math.Round(l.MinorLoss * Math.Pow(l.EN_VELOCITY, 2) / 2 / 9.8, 4); l.EN_HEADLOSS_LINE = l.EN_HEADLOSS - l.EN_HEADLOSS_MINOR; }); this._isCalculated = true; return list; //return new List(); } public List WaterDistribution(string inpPath, string configPath = null,List settings=null,double TotalDemand=-1,double InitPress=100) { if (TotalDemand < 0) { throw new Exception("TotalDemand must be set"); } WdnmoParam wdnmoParam = new WdnmoParam(); wdnmoParam.UpdateWParamByWaterEquivalentSettings(settings, TotalDemand); wdnmoParam.ScadaPoints.Add(new TimePoint { Key = "initPress", Value= InitPress }); Nodes.ForEach(n => { //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" }); } }); Links.ForEach(n => { //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" }); } }); calc c = new calc(); var list = c.GetCalcResult(inpPath, wdnmoParam, configPath); if (list == null) return list; list.Sort((a, b) => string.Compare(a.Key, b.Key)); Nodes.Sort((a, b) => string.Compare(a.ID, b.ID)); Links.Sort((a, b) => string.Compare(a.ID, b.ID)); SetNodeFromWparam(this, list, "Press"); SetNodeFromWparam(this, list, "Head"); SetNodeFromWparam(this, list, "Demand"); SetLinkFromWparam(this, list, "Flow"); SetLinkFromWparam(this, list, "Velocity"); SetLinkFromWparam(this, list, "Headloss"); Links.ForEach(l => { l.EN_HEADLOSS_MINOR = (float)Math.Round(l.MinorLoss * Math.Pow(l.EN_VELOCITY, 2) / 2 / 9.8, 4); l.EN_HEADLOSS_LINE = l.EN_HEADLOSS - l.EN_HEADLOSS_MINOR; }); Nodes.ForEach(n => n.Demand = n.EN_DEMAND); this._isCalculated = true; return list; //return new List(); } public List CalcByVal(WDNModelOptimizer wdo, Result val) { WdnmoParam wdnmoParam = new WdnmoParam(); Nodes.ForEach(n => { //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" }); } }); Links.ForEach(n => { //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" }); } }); calcParam calcParam = new calcParam(); calcParam.vars = val.arrayTryValue; calcParam.setVars = new List(); reservoirs.ForEach(r => { calcParam.setVars.Add(new SetVar (r.ID,true,(int)EpanetEnum.NodeValueType.水池水位,(float)val.ObjFunctionValue)); }); wdnmoParam =wdo.CalcbyResult(calcParam, wdnmoParam); var list = wdnmoParam.ResultPoints; if (list == null) return list; list.Sort((a, b) => string.Compare(a.Key, b.Key)); Nodes.Sort((a, b) => string.Compare(a.ID, b.ID)); Links.Sort((a, b) => string.Compare(a.ID, b.ID)); SetNodeFromWparam(this, list, "Press"); SetNodeFromWparam(this, list, "Head"); SetNodeFromWparam(this, list, "Demand"); SetLinkFromWparam(this, list, "Flow"); SetLinkFromWparam(this, list, "Velocity"); SetLinkFromWparam(this, list, "Headloss"); this._isCalculated = true; return list; //return new List(); } public string CheckValidate() { BuildRelation(); string result = null; StringBuilder result_sb=new StringBuilder(); //to-do var objs = new List() { Links[0] }; //Links.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList(); //objs去掉重复的元素 objs = objs.Distinct().ToList(); var visitedNodes = new HashSet(); FindObjs = new HashSet(); objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes)); for(int i=0;i { if (p.StartNode == null || p.EndNode == null) { result_sb.AppendLine($"{p.ID}管道未连接"); } if (p.Length<=0) { result_sb.AppendLine($"{p.ID}管道长度小于等于0"); } if (p.Roughness<=0.1 || p.Roughness>10000) { result_sb.AppendLine($"{p.ID}粗糙系数设置错误"); } if (p.Diameter<=0.1 || p.Diameter>10000) { result_sb.AppendLine($"{p.ID}管径设置错误"); } }); return result_sb.ToString(); } HashSet FindObjs; private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet visitedNodes = null, int direction = 0) { Queue queue = new Queue(); queue.Enqueue(startLink); if (visitedNodes == null) visitedNodes = new HashSet(); //visitedNodes.Add(startLink.StartNode); //visitedNodes.Add(startLink.EndNode); while (queue.Count > 0) { LinkViewModel currentLink = queue.Dequeue(); //Console.WriteLine("Traversing Link: " + currentLink.ID); foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode }) { if (direction == 1 && currentLink.EN_FLOW >= 0 && node == currentLink.StartNode) continue; if (direction == -1 && currentLink.EN_FLOW <= 0 && node == currentLink.EndNode) continue; if (node != null && !visitedNodes.Contains(node)) { visitedNodes.Add(node); if (!FindObjs.Contains(node)) FindObjs.Add(node); //Console.WriteLine("Visiting Node: " + node.ID); foreach (var link in node.ViewLinks) { if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode)) { if (!FindObjs.Contains(link)) FindObjs.Add(link); queue.Enqueue(link); } } } } } } public List CalcByValAndHead(WDNModelOptimizer wdo, Result val,double Head) { WdnmoParam wdnmoParam = new WdnmoParam(); Nodes.ForEach(n => { //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" }); } }); Links.ForEach(n => { //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel) { wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" }); wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" }); } }); calcParam calcParam = new calcParam(); calcParam.vars = val.arrayTryValue; calcParam.setVars = new List(); reservoirs.ForEach(r => { calcParam.setVars.Add(new SetVar(r.ID, true, (int)EpanetEnum.NodeValueType.水池水位, (float)Head)); }); wdnmoParam = wdo.CalcbyResult(calcParam, wdnmoParam); var list = wdnmoParam.ResultPoints; if (list == null) return list; list.Sort((a, b) => string.Compare(a.Key, b.Key)); Nodes.Sort((a, b) => string.Compare(a.ID, b.ID)); Links.Sort((a, b) => string.Compare(a.ID, b.ID)); SetNodeFromWparam(this, list, "Press"); SetNodeFromWparam(this, list, "Head"); SetNodeFromWparam(this, list, "Demand"); SetLinkFromWparam(this, list, "Flow"); SetLinkFromWparam(this, list, "Velocity"); SetLinkFromWparam(this, list, "Headloss"); this._isCalculated = true; return list; //return new List(); } private void SetNodeFromWparam(MapViewNetWork net, List list, string valueType) { int k1 = 0; int k2 = 0; k1 = 0; k2 = 0; while (k1 < net.Nodes.Count) { var J = (NodeViewModel)net.Nodes[k1]; //if (J is JunctionViewModel || J is NozzleViewModel || J is MeterViewModel) { var re = list[k2]; while ($"{valueType}_{J.ID}" != re.Key && k2 < list.Count) { k2++; if (k2 < list.Count) re = list[k2]; } if (k2 == list.Count) { throw new Exception($"未找到Node[{J.ID}]的{valueType}"); } switch (valueType) { case "Press": J.EN_PRESSURE = (float)Math.Round(re.Value, 4); break; case "Head": J.EN_HEAD = (float)Math.Round(re.Value, 4); break; case "Demand": J.EN_DEMAND = (float)Math.Round(re.Value, 4); break; } } k1++; } } private static void SetLinkFromWparam(MapViewNetWork net, List list, string valueType) { int k1 = 0; int k2 = 0; k1 = 0; k2 = 0; while (k1 < net.Links.Count) { var J = (LinkViewModel)net.Links[k1]; //if (J is PipeViewModel || J is ValveViewModel || J is PumpViewModel) { var re = list[k2]; while ($"{valueType}_{J.ID}" != re.Key && k2 < list.Count) { k2++; if (k2 < list.Count) re = list[k2]; } if (k2 == list.Count) { throw new Exception($"未找到Link[{J.ID}]的{valueType}"); } switch (valueType) { case "Flow": J.EN_FLOW = (float)Math.Round(re.Value, 4); break; case "Velocity": J.EN_VELOCITY = (float)Math.Round(re.Value, 4); break; case "Headloss": J.EN_HEADLOSS = (float)Math.Round(re.Value, 4); break; } } k1++; } } public void SetNodeDemand() { Nodes.ForEach(n => { if (n is NodeViewModel node && node.Demand == 0) { node.Demand = 0.01f; } else if (n is MeterViewModel meter && meter.Demand == 0) { meter.Demand = 0.01f; } else if (n is NozzleViewModel nozzle && nozzle.Demand == 0) { nozzle.Demand = 0.01f; } }); } } //构造一个List类,能够实现List的所有功能 [Serializable] public class LinkViewModelList:List { //List base; Dictionary dict;// public LinkViewModelList() : base() { this.dict = new Dictionary(); } //public LinkViewModelList(List links) //{ // base = links; // base.ForEach(link => // { // if (!dict.ContainsKey(link.ID)) // dict.Add(link.ID,link); // }); //} public List ViewLinks { get { var list = new List(); base.ForEach(l => { //if (l is LinkViewModel) list.Add((LinkViewModel)l); }); return list; //return base.Select(l => (LinkViewModel)l).ToList(); } } /// /// 更新字典 /// public void UpdateDict() { this.dict= new Dictionary(); base.ForEach(link => { if (!dict.ContainsKey(link.ID)) dict.Add(link.ID, (LinkViewModel)link); }); } /// /// 修改某个oldID至newID,同时更新字典 /// /// /// public void ChangeID(string oldID,string newID) { if (dict.ContainsKey(oldID)) { dict[oldID].ID = newID; dict.Add(newID, dict[oldID]); dict.Remove(oldID); } } /// /// 实现Add方法,同时更新字典 /// public void Add(LinkViewModel linkCalcModel) { base.Add(linkCalcModel); if (!dict.ContainsKey(linkCalcModel.ID)) dict.Add(linkCalcModel.ID, linkCalcModel); } /// /// 实现AddRange方法,同时更新字典 /// /// public void AddRange(List linkCalcModels) { base.AddRange(linkCalcModels); linkCalcModels.ForEach(link => { if (!dict.ContainsKey(link.ID)) dict.Add(link.ID, link); }); } public bool RemoveAt(int index) { if (index < 0 || index >= base.Count) return false; var link = base[index]; base.RemoveAt(index); if (dict.ContainsKey(link.ID)) dict.Remove(link.ID); return true; } /// /// 统计数量 /// public int Count { get { return base.Count; } } public LinkViewModel this[string ID] { get { if (dict.ContainsKey(ID)) return dict[ID]; else return (LinkViewModel)base.Find(l => l.ID == ID); } } public LinkViewModel this[int index] { get { return (LinkViewModel)base[index]; } } public void Sort() { base.Sort(); } //实现Sort(Comparison comparison)方法 public void Sort(Comparison comparison) { base.Sort(comparison); } //实现Select方法 public void Select(Action action) { //base.ForEach(action); //base.ForEach(action); ViewLinks.ForEach(action); } //实现Find方法 public LinkViewModel Find(Predicate match) { //base.Find(match); return ViewLinks.Find(match); } //实现FindAll方法 public List FindAll(Predicate match) { return ViewLinks.FindAll(match); } //实现ForEach方法 public void ForEach(Action action) { ViewLinks.ForEach(action); } //实现RemoveAll方法 public int RemoveAll(Predicate match) { return base.RemoveAll(match); } /// /// 实现Remove方法,同时更新字典 /// public bool Remove(LinkViewModel linkCalcModel) { if (base.Remove(linkCalcModel)) { if (dict.ContainsKey(linkCalcModel.ID)) dict.Remove(linkCalcModel.ID); return true; } else return false; } } //构造一个List类,能够实现List的所有功能 [Serializable] public class NodeViewModelList : List { //List base; Dictionary dict;//=new Dictionary();// public NodeViewModelList():base() { this.dict = new Dictionary(); } //public NodeViewModelList(List nodes) //{ // base = nodes; // base.ForEach(node => // { // if (!dict.ContainsKey(node.ID)) // dict.Add(node.ID,node); // }); //} /// /// 更新字典 /// public void UpdateDict() { this.dict = new Dictionary(); base.ForEach(node => { if (!dict.ContainsKey(node.ID)) dict.Add(node.ID, node); }); } /// /// 修改某个oldID至newID,同时更新字典 /// /// /// public void ChangeID(string oldID, string newID) { if (dict.ContainsKey(oldID)) { dict[oldID].ID = newID; dict.Add(newID, dict[oldID]); dict.Remove(oldID); } } /// /// 实现Add方法,同时更新字典 /// public void Add(NodeViewModel nodeCalcModel) { base.Add(nodeCalcModel); if (!dict.ContainsKey(nodeCalcModel.ID)) dict.Add(nodeCalcModel.ID, nodeCalcModel); } /// /// 实现AddRange方法,同时更新字典 /// /// public void AddRange(List nodeCalcModels) { base.AddRange(nodeCalcModels); nodeCalcModels.ForEach(node => { if (!dict.ContainsKey(node.ID)) dict.Add(node.ID, node); }); } /// /// 实现Remove方法,同时更新字典 /// public bool Remove(NodeViewModel nodeCalcModel) { if (base.Remove(nodeCalcModel)) { if (dict.ContainsKey(nodeCalcModel.ID)) dict.Remove(nodeCalcModel.ID); return true; } else return false; } public bool RemoveAt(int index) { if (index < 0 || index >= base.Count) return false; var node = base[index]; base.RemoveAt(index); if (dict.ContainsKey(node.ID)) dict.Remove(node.ID); return true; } /// /// 统计数量 /// public int Count { get { return base.Count; } } public NodeViewModel this[string ID] { get { if (dict.ContainsKey(ID)) return (NodeViewModel)dict[ID]; else return (NodeViewModel)base.Find(l => l.ID == ID); } } public NodeViewModel this[int index] { get { return (NodeViewModel)base[index]; } } //public List ToList() //{ // return base; //} //实现Sort方法 public List ViewNodes { get { //将NodeCalcModel转换为NodeViewModel //return this.Select(l => (NodeViewModel)l).ToList(); List list = new List(); foreach (var item in this) { list.Add((NodeViewModel)item); } return list; } } public void Sort() { base.Sort(); } //实现Sort(Comparison comparison)方法 public void Sort(Comparison comparison) { base.Sort(comparison); } //实现Select方法 public void Select(Action action) { ViewNodes.ForEach(action); //base.ForEach(action); } //实现Find方法 public NodeViewModel Find(Predicate match) { return ViewNodes.Find(match); } //实现FindAll方法 public List FindAll(Predicate match) { return ViewNodes.FindAll(match); } //实现ForEach方法 public void ForEach(Action action) { ViewNodes.ForEach(action); } //实现RemoveAll方法 public int RemoveAll(Predicate match) { return base.RemoveAll(match); } } }