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 CommonBase; namespace Hydro.MapView { public class MapViewNetWork : NetWork { public string Name; public NodeViewModel StartPoint { get; set; } public NodeViewModel EndPoint { get; set; } /// /// 核心承载字段 /// public new List Nodes = new List(); /// /// 核心承载字段 /// public new List Links = new List(); public Dictionary dict_dataset;// = new Dictionary(); 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 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; 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(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) { 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 = 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 = 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); }); //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; } } 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 => //{ // r.Load(); // Add(r); //}); repeaters.ForEach(r => { if (!r.Load(MaxLevel, param, viewModel, ViewMode)) { r.Status = RepeaterViewModel.RepeatStatus.收起; r.Visible = true; } else { Add(r); r.Visible = false; } //if (r.Status == Repeater.RepeatStatus.显示) //{ //} }); } 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(); 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); } 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"); 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 = 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, 2); break; case "Head": J.EN_HEAD = (float)Math.Round(re.Value, 2); break; case "Demand": J.EN_DEMAND = (float)Math.Round(re.Value, 2); 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 = 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.Abs(Math.Round(re.Value, 2)); break; case "Velocity": J.EN_VELOCITY = (float)Math.Round(re.Value, 2); break; case "Headloss": J.EN_HEADLOSS = (float)Math.Round(re.Value, 2); break; } } k1++; } } } }