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);
}
}
}