using Newtonsoft.Json;
|
using System.Numerics;
|
using System.Text;
|
|
namespace HydroUI
|
{
|
[Serializable]
|
public 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; } }
|
|
private List<AreaViewModel> _areas = new List<AreaViewModel>();
|
public List<AreaViewModel> Areas { get { return _areas; } set { _areas = 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 };
|
}
|
|
|
|
public HashSet<string> Hash_ID;
|
|
|
public List<JunctionViewModel> 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);
|
}
|
}
|
|
|
public List<ReservoirViewModel> 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);
|
}
|
}
|
|
public List<TankViewModel> 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);
|
}
|
}
|
|
public List<MeterViewModel> 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);
|
}
|
}
|
|
public List<NozzleViewModel> 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);
|
}
|
}
|
|
|
public List<PipeViewModel> 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);
|
}
|
}
|
|
public List<ValveViewModel> 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);
|
}
|
}
|
|
public List<ValveNodeViewModel> 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);
|
}
|
}
|
|
|
public List<RepeaterViewModel> 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);
|
}
|
}
|
|
public List<PumpViewModel> 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);
|
}
|
}
|
|
public List<PumpNodeViewModel> 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<JunctionViewModel> Deserialized_junctions { get; set; }
|
public List<TankViewModel> Deserialized_tanks { get; set; }
|
public List<ReservoirViewModel> Deserialized_reservoirs { get; set; }
|
public List<MeterViewModel> Deserialized_meters { get; set; }
|
public List<NozzleViewModel> Deserialized_nozzles { get; set; }
|
public List<PipeViewModel> Deserialized_pipes { get; set; }
|
public List<ValveViewModel> Deserialized_valves { get; set; }
|
public List<ValveNodeViewModel> Deserialized_valveNodes { get; set; }
|
public List<RepeaterViewModel> Deserialized_repeaters { get; set; }
|
public List<PumpViewModel> Deserialized_pumps { get; set; }
|
public List<PumpNodeViewModel> Deserialized_pumpNodes { get; set; }
|
|
public List<AreaViewModel> areas = new List<AreaViewModel>();
|
|
public bool ReadFromJson(string json)
|
{
|
try
|
{
|
var net = JsonConvert.DeserializeObject<MapViewNetWork>(json);
|
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_repeaters = repeaters;
|
net.Deserialized_pumps = pumps;
|
net.StartPoint = StartPoint;
|
net.EndPoint = EndPoint;
|
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<IBaseViewModel> Remove(List<IBaseViewModel> list)
|
{
|
|
List<IBaseViewModel> objs = new List<IBaseViewModel>();
|
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);
|
|
}
|
});
|
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;
|
}
|
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;
|
ID = $"{DefaultString}{i}";
|
while (Hash_ID.Contains(ID))
|
{
|
ID = $"{DefaultString}{i}";
|
i++;
|
}
|
return ID;
|
}
|
|
public MapViewNetWork CreateNew(PointF3D basepoint)
|
{
|
MapViewNetWork net = this.DeepCopy<MapViewNetWork>();
|
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);
|
EndPoint = network.EndPoint;
|
}
|
}
|
public List<IBaseViewModel> Add(MapViewNetWork net0, PointF3D offset = null, bool isCopy = false, NodeViewModel ConnectNode = null)
|
{
|
if (offset == null)
|
{
|
offset = new PointF3D(0, 0, 0);
|
}
|
List<IBaseViewModel> list = new List<IBaseViewModel>();
|
if (Hash_ID == null) Hash_ID = new HashSet<string>();
|
|
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);
|
}
|
return list;
|
}
|
|
|
public void Add(List<IBaseViewModel> 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));
|
}
|
|
public void Clear()
|
{
|
Nodes.Clear();
|
Links.Clear();
|
}
|
|
|
public List<IBaseViewModel> MapObjects
|
{
|
get
|
{
|
List<BaseModel> objects = new List<BaseModel>();
|
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<string, dynamic> param, Dictionary<PBS.eModelTemplateType, bool> viewModel, bool ViewMode = true)
|
{
|
|
|
repeaters.ForEach(r =>
|
{
|
|
if (!r.Load(MaxLevel, param, viewModel, ViewMode))
|
{
|
r.Status = RepeatStatus.收起;
|
r.Visible = true;
|
}
|
|
else
|
{
|
Add(r);
|
r.Visible = false;
|
}
|
|
|
});
|
}
|
|
public void MoveDownNetwork(RepeaterViewModel repeater)
|
{
|
visited = new Dictionary<NodeViewModel, bool>();
|
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<NodeViewModel, bool> visited;
|
private bool _isCalculated = false;
|
|
public void BFS(MapViewNetWork net, NodeViewModel startNode, Vector3 vector)
|
{
|
|
Queue<NodeViewModel> queue = new Queue<NodeViewModel>();
|
|
// 标记起始节点为已访问,并加入队列
|
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<NodeViewModel> GetNode(string node)
|
{
|
return Nodes.FindAll(n => n.ID == node).Select(n => (NodeViewModel)n)?.ToList();
|
}
|
|
|
public Dictionary<string, List<string>> CheckValidate()
|
{
|
BuildRelation();
|
string result = null;
|
Dictionary<string, List<string>> result_dict = new Dictionary<string, List<string>>();
|
StringBuilder result_sb = new StringBuilder();
|
//to-do
|
var objs = Links.Select(o => o as LinkViewModel)?.ToList();//new List<LinkViewModel>() { Links[0] }; //Links.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel)?.ToList();
|
//objs去掉重复的元素
|
objs = objs.Distinct()?.ToList();
|
var visitedNodes = new HashSet<NodeViewModel>();
|
FindObjs = new HashSet<IBaseViewModel>();
|
objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes));
|
List<string> list_孤立点 = new List<string>();
|
for (int i = 0; i < Nodes.Count; i++)
|
{
|
if (!FindObjs.Contains(Nodes[i]))
|
{
|
result_sb.AppendLine($"节点{Nodes[i].ID}是孤立点");
|
list_孤立点.Add(Nodes[i].ID);
|
}
|
|
}
|
if (list_孤立点.Count > 0) result_dict.Add("孤立点", list_孤立点);
|
//属性判断
|
var list_管道连接关系异常 = new List<string>();
|
var list_管道长度小于等于0 = new List<string>();
|
var list_粗糙系数设置错误 = new List<string>();
|
var list_管径设置错误 = new List<string>();
|
|
pipes.ForEach(p =>
|
{
|
if (p.StartNode == null || p.EndNode == null)
|
{
|
result_sb.AppendLine($"{p.ID}管道连接关系异常");
|
list_管道连接关系异常.Add(p.ID);
|
}
|
if (p.Length <= 0)
|
{
|
result_sb.AppendLine($"{p.ID}管道长度小于等于0");
|
list_管道长度小于等于0.Add(p.ID);
|
}
|
if (p.Roughness <= 0.1 || p.Roughness > 10000)
|
{
|
result_sb.AppendLine($"{p.ID}粗糙系数设置错误");
|
list_粗糙系数设置错误.Add(p.ID);
|
}
|
if (p.Diameter <= 0.1 || p.Diameter > 10000)
|
{
|
result_sb.AppendLine($"{p.ID}管径设置错误");
|
list_管径设置错误.Add(p.ID);
|
}
|
|
});
|
if (list_管道连接关系异常.Count > 0) result_dict.Add("管道连接关系异常", list_管道连接关系异常);
|
if (list_管道长度小于等于0.Count > 0) result_dict.Add("管道长度小于等于0", list_管道长度小于等于0);
|
if (list_粗糙系数设置错误.Count > 0) result_dict.Add("粗糙系数设置错误", list_粗糙系数设置错误);
|
if (list_管径设置错误.Count > 0) result_dict.Add("管径设置错误", list_管径设置错误);
|
return result_dict;
|
|
|
|
}
|
HashSet<IBaseViewModel> FindObjs;
|
private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null, int direction = 0)
|
{
|
|
Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
|
|
|
|
queue.Enqueue(startLink);
|
if (visitedNodes == null)
|
visitedNodes = new HashSet<NodeViewModel>();
|
|
while (queue.Count > 0)
|
{
|
LinkViewModel currentLink = queue.Dequeue();
|
|
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);
|
|
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 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;
|
}
|
});
|
}
|
|
|
|
public bool BuildFromInp(string filePath, bool use_old = false)
|
{
|
this.use_old = use_old;
|
if (this.use_old)
|
{
|
return loadInpFile_old(filePath);
|
}
|
if (filePath == null || !File.Exists(filePath)) return false;
|
List<Coor> points = new List<Coor>();
|
StreamReader sr = new StreamReader(filePath);
|
|
{
|
Nodes = new NodeViewModelList();
|
Links = new LinkViewModelList();
|
|
string line;
|
string section = "";
|
while ((line = sr.ReadLine()) != null)
|
{
|
if (line.Trim().StartsWith("["))
|
{
|
section = line.TrimStart('[').TrimEnd(']');
|
}
|
else
|
{
|
string s = line.Trim('\t').Trim(' ');
|
if (s.Length == 0 || s[0] == ';') continue;
|
Parts parts = new Parts(line);
|
section = section.ToUpper();
|
IBaseViewModel o = null;
|
switch (section)
|
{
|
case "JUNCTIONS":
|
{
|
NodeViewModel j = null;
|
if (parts[-2] == "Meter")
|
{
|
var m = new MeterViewModel();
|
j = m;
|
}
|
else if (parts[-2] == "Nozzle")
|
{
|
var n = new NozzleViewModel();
|
j = n;
|
n.FlowCoefficient = parts.ToFloat(-4, 0);
|
}
|
else
|
j = new JunctionViewModel();
|
|
o = j;
|
j.ID = parts.ToString(0, null);
|
j.Elev = parts.ToFloat(1, 0);
|
j.Demand = parts.ToFloat(2, 0);
|
j.PatternID = parts.ToString(3, null);
|
if (j.PatternID == "NONE") j.PatternID = null;
|
j.Level = parts.ToInt(-1, 0);
|
|
Nodes.Add(j);
|
}
|
break;
|
|
case "RESERVOIRS":
|
{
|
ReservoirViewModel r = new ReservoirViewModel();
|
o = r;
|
r.ID = parts.ToString(0, null);
|
r.Head = parts.ToFloat(1, 0);
|
r.PatternID = parts.ToString(2, null);
|
r.Level = parts.ToInt(-1, 0);
|
r.Elev = parts.ToFloat(-2, 0);
|
Nodes.Add(r);
|
}
|
break;
|
|
case "TANKS":
|
{
|
TankViewModel tank = new TankViewModel();
|
o = tank;
|
tank.ID = parts.ToString(0, null);
|
tank.Elev = parts.ToFloat(1, 0);
|
tank.InitLevel = parts.ToFloat(2, 0);
|
tank.MinLevel = parts.ToFloat(3, 0);
|
tank.MaxLevel = parts.ToFloat(4, 0);
|
tank.Diameter = parts.ToFloat(5, 0);
|
tank.MinVol = parts.ToFloat(6, 0);
|
tank.VolCurve = parts.ToString(7, null);
|
tank.Overflow = "";
|
tank.Level = parts.ToInt(-1, 0);
|
Nodes.Add(tank);
|
}
|
break;
|
|
case "PIPES":
|
{
|
if (parts[-2] == "Repeater")
|
{
|
RepeaterViewModel repeater = new RepeaterViewModel();
|
o = repeater;
|
repeater.ID = parts.ToString(0, null);
|
repeater.Node1 = parts.ToString(1, null);
|
repeater.Node2 = parts.ToString(2, null);
|
repeater.Length = parts.ToFloat(3, 0.1f);
|
repeater.Diameter = parts.ToFloat(4, 150f);
|
repeater.Roughness = parts.ToFloat(5, 100f);
|
repeater.MinorLoss = parts.ToFloat(6, 0);
|
repeater.Level = parts.ToInt(-1, 0);
|
repeater.TemplateID = parts.ToString(-3, null);
|
repeater.RepeatTimes = parts.ToInt(-4, 1);
|
RepeatStatus status;
|
if (Enum.TryParse(parts[-5], out status))
|
repeater.Status = status;
|
repeater.NetworkPreName = parts.ToString(-6, null);
|
repeater.NetworkPreStartNum = parts.ToInt(-7, 0);
|
repeater.NetworkIsAscNum = parts.ToBool(-8, false);
|
repeater.NetworkShowName = parts.ToString(-9, null);
|
|
Links.Add(repeater);
|
}
|
else
|
{
|
PipeViewModel p = new PipeViewModel();
|
o = p;
|
p.ID = parts.ToString(0, null);
|
p.Node1 = parts.ToString(1, null);
|
p.Node2 = parts.ToString(2, null);
|
p.Length = parts.ToFloat(3, 0.1f);
|
p.Diameter = parts.ToFloat(4, 150f);
|
p.Roughness = parts.ToFloat(5, 100f);
|
p.MinorLoss = parts.ToFloat(6, 0);
|
p.Status = StringToStatus(parts.ToString(7, "OPEN"));
|
|
p.Level = parts.ToInt(-1, 0);
|
Links.Add(p);
|
}
|
}
|
break;
|
|
case "VALVES":
|
{
|
ValveViewModel valve = new ValveViewModel();
|
o = valve;
|
valve.ID = parts.ToString(0, null);
|
|
valve.Node1 = parts.ToString(1, null);
|
valve.Node2 = parts.ToString(2, null);
|
valve.Diameter = parts.ToFloat(3, 0);
|
valve.Type = parts.ToString(4, null);
|
valve.Setting = parts.ToString(5, null);
|
valve.MinorLoss = parts.ToFloat(6, 0);
|
valve.Level = parts.ToInt(-1, 0);
|
Links.Add(valve);
|
}
|
break;
|
|
case "PUMPS":
|
{
|
PumpViewModel pump = new PumpViewModel();
|
o = pump;
|
pump.ID = parts.ToString(0, null);
|
|
pump.Node1 = parts.ToString(1, null);
|
pump.Node2 = parts.ToString(2, null);
|
int index = 3;
|
string label = null;
|
while ((label = parts.ToString(index, null)) != null)
|
{
|
label = label.ToUpper();
|
switch (label)
|
{
|
case "HEAD":
|
pump.HeadCurve = parts.ToString(index + 1, "PumpDefault");
|
break;
|
|
case "SPEED":
|
pump.当前转速 = parts.ToFloat(index + 1, 0);
|
break;
|
}
|
index += 2;
|
}
|
|
pump.Level = parts.ToInt(-1, 0);
|
Links.Add(pump);
|
}
|
break;
|
|
case "CURVES":
|
{
|
|
}
|
break;
|
|
case "COORDINATES":
|
{
|
string id = parts[0];
|
float x;
|
float y;
|
if (float.TryParse(parts[1], out x) && float.TryParse(parts[2], out y))
|
{
|
points.Add(new Coor(id, new PointF(x, y)));
|
}
|
}
|
break;
|
|
case "STATUS":
|
{
|
LinkViewModel link = Links.Find(l => l.ID == parts.ToString(0, null));
|
if (link != null)
|
link.Status = StringToStatus(parts.ToString(1, "OPEN"));
|
}
|
break;
|
}
|
if (o != null)
|
{
|
o.Tags = new TagList(parts.ToString(-3, null));
|
}
|
}
|
}
|
sr.Close();
|
|
|
|
|
//读取坐标
|
int k1 = 0;
|
int k2 = 0;
|
Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
|
points.Sort((a, b) => string.Compare(a.ID, b.ID));
|
k1 = 0;
|
k2 = 0;
|
while (k1 < Nodes.Count)
|
{
|
var J = Nodes[k1];
|
var coor = points[k2];
|
|
while (J.ID != coor.ID && k2 < points.Count)
|
{
|
k2++;
|
if (k2 < points.Count) coor = points[k2];
|
}
|
if (k2 == points.Count)
|
{
|
throw new Exception($"未找到Node[{J.ID}]的坐标");
|
}
|
J.X = coor.Position.X;
|
J.Y = coor.Position.Y;
|
|
k1++;
|
}
|
|
BuildRelation();
|
|
return true;
|
}
|
}
|
|
private StatusType StringToStatus(string status)
|
{
|
switch (status)
|
{
|
case "CLOESD":
|
case "0":
|
return StatusType.CLOSED;
|
|
case "OPEN":
|
case "1":
|
return StatusType.OPEN;
|
|
case "ACTIVE":
|
return StatusType.ACTIVE;
|
|
default:
|
return StatusType.DEFAULT;
|
}
|
}
|
|
public void BuildRelation()
|
{
|
//读取坐标
|
int k1 = 0;//表示管线索引
|
int k2 = 0;//表示节点索引
|
Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
|
|
|
|
Links.Sort((a, b) => string.Compare(a.Node1, b.Node1));
|
k2 = 0;
|
k1 = 0;
|
while (k1 < Links.Count)
|
{
|
var p = Links[k1];
|
var J = Nodes[k2];
|
var k0 = k2;
|
while (J.ID != p.Node1 && k2 < Nodes.Count)
|
{
|
k2++;
|
if (k2 < Nodes.Count) J = Nodes[k2];
|
}
|
if (k2 == Nodes.Count)
|
{
|
k2 = k0;
|
k1++;
|
p.Visible = false;
|
continue;
|
//throw new Exception($"未找到Link[{p.ID}]的起始节点[{p.Node1}]");
|
}
|
p.StartNode = J;
|
p.Node1 = J.ID;
|
if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
J.Links.Add(p);
|
k1++;
|
}
|
|
|
|
Links.Sort((a, b) => string.Compare(a.Node2, b.Node2));
|
k2 = 0;
|
k1 = 0;
|
while (k1 < Links.Count)
|
{
|
var p = Links[k1];
|
var J = Nodes[k2];
|
var k0 = k2;
|
while (J.ID != p.Node2 && k2 < Nodes.Count)
|
{
|
k2++;
|
if (k2 < Nodes.Count) J = Nodes[k2];
|
}
|
if (k2 == Nodes.Count)
|
{
|
k2 = k0;
|
k1++;
|
p.Visible = false;
|
|
continue;
|
}
|
p.EndNode = J;
|
p.Node2 = J.ID;
|
if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
J.Links.Add(p);
|
k1++;
|
}
|
|
foreach (ValveNodeViewModel vn in valveNodes?.ToList())
|
{
|
if (vn.Links.Count != 2) continue;
|
|
var junc1 = AddJunction("S__" + vn.ID, vn.Position, vn.Elev);
|
if (vn.Links[0].StartNode.ID == vn.ID)
|
{
|
vn.Links[0].StartNode = junc1;
|
}
|
else
|
{
|
vn.Links[0].EndNode = junc1;
|
}
|
junc1.Links.Add(vn.Links[0]);
|
|
var junc2 = AddJunction("E__" + vn.ID, vn.Position, vn.Elev);
|
if (vn.Links[1].StartNode.ID == vn.ID)
|
{
|
vn.Links[1].StartNode = junc2;
|
}
|
else
|
{
|
vn.Links[1].EndNode = junc2;
|
}
|
junc2.Links.Add(vn.Links[1]);
|
ValveViewModel valve = AddValve(junc1, junc2);
|
|
valve.ID = vn.ID;
|
valve.Status = vn.Status;
|
junc1.Links.Add(valve);
|
junc2.Links.Add(valve);
|
Nodes.Remove(vn);
|
}
|
|
foreach (PumpNodeViewModel pn in pumpNodes?.ToList())
|
{
|
if (pn.Links.Count != 2) continue;
|
if (pn.Links[0].ID != pn.Node1)
|
{
|
LinkViewModel temp0 = pn.Links[0] as LinkViewModel;
|
pn.Links.RemoveAt(0);
|
pn.Links.Add(temp0);
|
}
|
var junc1 = AddJunction("S__" + pn.ID, pn.Position, pn.Elev);
|
if (pn.Links[0].StartNode.ID == pn.ID)
|
{
|
pn.Links[0].StartNode = junc1;
|
}
|
else
|
{
|
pn.Links[0].EndNode = junc1;
|
}
|
junc1.Links.Add(pn.Links[0]);
|
|
var junc2 = AddJunction("E__" + pn.ID, pn.Position, pn.Elev);
|
if (pn.Links[1].StartNode.ID == pn.ID)
|
{
|
pn.Links[1].StartNode = junc2;
|
}
|
else
|
{
|
pn.Links[1].EndNode = junc2;
|
}
|
junc2.Links.Add(pn.Links[1]);
|
PumpViewModel pump = AddPump(junc1, junc2);
|
pump.Status = pn.Status;
|
pump.ID = pn.ID;
|
pump.额定功率 = pn.额定功率;
|
pump.额定扬程 = pn.额定扬程;
|
pump.额定流量 = pn.额定流量;
|
pump.HeadCurve = pn.HeadCurve;
|
pump.额定转速 = pn.额定转速;
|
pump.转速比 = pn.转速比;
|
junc1.Links.Add(pump);
|
junc2.Links.Add(pump);
|
Nodes.Remove(pn);
|
}
|
|
|
|
|
|
Hash_ID = new HashSet<string>();
|
Nodes.ForEach(o => Hash_ID.Add(o.ID));
|
Links.ForEach(o => Hash_ID.Add(o.ID));
|
|
var err = Links.Where(x => x.StartNode.ID == x.EndNode.ID).ToList();
|
Links.RemoveAll(x => x.StartNode.ID == x.EndNode.ID);
|
Links.RemoveAll(x => x.Length == 0);
|
var a = err;
|
}
|
|
public bool loadInpFile_old(string filePath)
|
{
|
if (filePath == null || !File.Exists(filePath)) return false;
|
List<Coor> points = new List<Coor>();
|
StreamReader sr = new StreamReader(filePath);
|
|
{
|
Nodes = new NodeViewModelList();
|
|
|
Links = new LinkViewModelList();
|
|
string line;
|
string section = "";
|
while ((line = sr.ReadLine()) != null)
|
{
|
if (line.Trim().StartsWith("["))
|
{
|
section = line.TrimStart('[').TrimEnd(']');
|
}
|
else
|
{
|
string s = line.Trim('\t').Trim(' ');
|
if (s.Length == 0 || s[0] == ';') continue;
|
line = line.Replace("\t\t", "\t_\t").Replace("\t \t", "\t_\t");
|
Parts parts = new Parts(line.Split(new char[] {
|
'\t', ' ', ';'
|
}, StringSplitOptions.RemoveEmptyEntries));
|
switch (section)
|
{
|
case "JUNCTIONS":
|
{
|
NodeViewModel j = null;
|
if (parts[4] == "Meter")
|
{
|
j = new MeterViewModel();
|
meters.Add((MeterViewModel)j);
|
}
|
else if (parts[4] == "Nozzle")
|
j = new NozzleViewModel();
|
else
|
j = new JunctionViewModel();
|
|
j.ID = parts[0];
|
float elev;
|
if (float.TryParse(parts[1], out elev))
|
j.Elev = elev;
|
float demand;
|
if (float.TryParse(parts[2], out demand))
|
j.Demand = demand;
|
j.PatternID = parts[3];
|
int level;
|
if (int.TryParse(parts[5], out level))
|
j.Level = level;
|
|
Nodes.Add(j);
|
}
|
break;
|
|
case "RESERVOIRS":
|
{
|
ReservoirViewModel r = new ReservoirViewModel();
|
r.ID = parts[0];
|
float head;
|
if (float.TryParse(parts[1], out head))
|
r.Head = head;
|
r.PatternID = parts.Length > 2 ? parts[2] : "";
|
int level;
|
if (int.TryParse(parts[3], out level))
|
r.Level = level;
|
Nodes.Add(r);
|
}
|
break;
|
|
case "TANKS":
|
{
|
TankViewModel tank = new TankViewModel(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7], parts[8]);
|
int level;
|
if (int.TryParse(parts[9], out level))
|
tank.Level = level;
|
Nodes.Add(tank);
|
}
|
break;
|
|
case "PIPES":
|
{
|
PipeViewModel p = new PipeViewModel();
|
p.ID = parts[0];
|
p.Node1 = parts[1];
|
p.Node2 = parts[2];
|
float length;
|
if (float.TryParse(parts[3], out length))
|
p.Length = length;
|
float diameter;
|
if (float.TryParse(parts[4], out diameter))
|
p.Diameter = diameter;
|
float roughness;
|
if (float.TryParse(parts[5], out roughness))
|
p.Roughness = roughness;
|
float minorLoss;
|
if (float.TryParse(parts[6], out minorLoss))
|
p.MinorLoss = minorLoss;
|
p.Status = parts.Length > 7 ? StringToStatus(parts[7]) : StatusType.DEFAULT;
|
int level;
|
if (int.TryParse(parts[8], out level))
|
p.Level = level;
|
Links.Add(p);
|
}
|
break;
|
|
case "VALVES":
|
{
|
ValveViewModel valve = new ValveViewModel();
|
valve.ID = parts[0];
|
|
valve.Node1 = parts[1];
|
valve.Node2 = parts[2];
|
|
float diameter;
|
if (float.TryParse(parts[3], out diameter))
|
valve.Diameter = diameter;
|
valve.Type = parts[4];
|
valve.Setting = parts[5];
|
float minorLoss;
|
if (float.TryParse(parts[6], out minorLoss))
|
valve.MinorLoss = minorLoss;
|
int level;
|
if (int.TryParse(parts[7], out level))
|
valve.Level = level;
|
Links.Add(valve);
|
}
|
break;
|
|
case "REPEATERS":
|
{
|
RepeaterViewModel repeater = new RepeaterViewModel();
|
repeater.ID = parts[0];
|
repeater.Node1 = parts[1];
|
repeater.Node2 = parts[2];
|
repeater.TemplateID = parts[3];
|
int repeatTimes;
|
if (int.TryParse(parts[4], out repeatTimes))
|
repeater.RepeatTimes = repeatTimes;
|
RepeatStatus status;
|
if (Enum.TryParse(parts[5], out status))
|
repeater.Status = status;
|
repeater.NetworkPreName = parts[6];
|
int networkPreStartNum;
|
if (int.TryParse(parts[7], out networkPreStartNum))
|
repeater.NetworkPreStartNum = networkPreStartNum;
|
bool networkIsAscNum;
|
if (bool.TryParse(parts[8], out networkIsAscNum))
|
repeater.NetworkIsAscNum = networkIsAscNum;
|
repeater.NetworkShowName = parts[9];
|
int level;
|
if (int.TryParse(parts[10], out level))
|
repeater.Level = level;
|
Links.Add(repeater);
|
}
|
break;
|
|
case "COORDINATES":
|
{
|
string id = parts[0];
|
float x;
|
float y;
|
if (float.TryParse(parts[1], out x) && float.TryParse(parts[2], out y))
|
{
|
points.Add(new Coor(id, new PointF(x, y)));
|
}
|
}
|
break;
|
}
|
}
|
}
|
sr.Close();
|
|
//读取坐标
|
int k1 = 0;
|
int k2 = 0;
|
Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
|
points.Sort((a, b) => string.Compare(a.ID, b.ID));
|
k1 = 0;
|
k2 = 0;
|
while (k1 < Nodes.Count)
|
{
|
var J = Nodes[k1];
|
var coor = points[k2];
|
|
while (J.ID != coor.ID && k2 < points.Count)
|
{
|
k2++;
|
if (k2 < points.Count) coor = points[k2];
|
}
|
if (k2 == points.Count)
|
{
|
throw new Exception($"未找到Node[{J.ID}]的坐标");
|
}
|
J.X = coor.Position.X;
|
J.Y = coor.Position.Y;
|
|
k1++;
|
}
|
|
|
|
Links.Sort((a, b) => string.Compare(a.Node1, b.Node1));
|
k1 = 0;
|
k2 = 0;
|
while (k2 < Links.Count)
|
{
|
var p = Links[k2];
|
var J = Nodes[k1];
|
while (J.ID != p.Node1 && k1 < Nodes.Count)
|
{
|
k1++;
|
if (k1 < Nodes.Count) J = Nodes[k1];
|
}
|
if (k1 == Nodes.Count)
|
{
|
throw new Exception($"未找到Link[{p.ID}]的起始节点[{p.Node1}]");
|
}
|
p.StartNode = J;
|
if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
J.Links.Add(p);
|
k2++;
|
}
|
|
|
|
Links.Sort((a, b) => string.Compare(a.Node2, b.Node2));
|
k1 = 0;
|
k2 = 0;
|
while (k2 < Links.Count)
|
{
|
var p = Links[k2];
|
var J = Nodes[k1];
|
while (J.ID != p.Node2 && k1 < Nodes.Count)
|
{
|
k1++;
|
if (k1 < Nodes.Count) J = Nodes[k1];
|
}
|
if (k1 == Nodes.Count)
|
{
|
throw new Exception($"未找到Link[{p.ID}]的终止节点[{p.Node2}]");
|
}
|
p.EndNode = J;
|
if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
J.Links.Add(p);
|
k2++;
|
}
|
|
return true;
|
}
|
}
|
|
public void ClearMinorLoss()
|
{
|
Links.ForEach(l => l.MinorLoss = 0);
|
}
|
|
public void CalcLinkMinorLoss()
|
{
|
Links.ForEach(l => l.MinorLoss = 0);
|
Nodes.ForEach(n =>
|
{
|
var links_Down = n.ViewLinks.FindAll(l => l.StartNode == n ? l.EN_FLOW > 0 : l.EN_FLOW < 0);
|
var links_Up = n.ViewLinks.FindAll(l => l.StartNode == n ? l.EN_FLOW < 0 : l.EN_FLOW > 0);
|
/*两侧均连接一个管线*/
|
if (links_Down.Count == 1 && links_Up.Count == 1)
|
{
|
var link_Down = links_Down[0];
|
var link_Up = links_Up[0];
|
double angle = GetAngle(link_Down, link_Up);
|
var minorLoss = 0f;
|
minorLoss += GetMinorLossByAngle(angle);
|
minorLoss += GetChangeDiameterMinorLoss(link_Down, link_Up);
|
link_Up.MinorLoss += minorLoss;
|
}
|
/*上游管线为1根,下游管线为多个*/
|
if (links_Up.Count == 1 && links_Down.Count > 1)
|
{
|
var link_Up = links_Up[0];
|
|
//计算两个管线的夹角,根据夹角计算损失系数
|
foreach (var link_Down in links_Down)
|
{
|
var angle = GetAngle(link_Down, link_Up);
|
var minorLoss = 0f;
|
minorLoss += GetMinorLossByAngle(angle);
|
minorLoss += GetChangeDiameterMinorLoss(link_Down, link_Up);
|
link_Down.MinorLoss += minorLoss;
|
}
|
}
|
|
/*下游管线为1根,上游管线为多个*/
|
if (links_Up.Count > 1 && links_Down.Count == 1)
|
{
|
var link_Down = links_Down[0];
|
|
//计算两个管线的夹角,根据夹角计算损失系数
|
foreach (var link_Up in links_Up)
|
{
|
var angle = GetAngle(link_Down, link_Up);
|
var minorLoss = 0f;
|
minorLoss += GetMinorLossByAngle(angle);
|
minorLoss += GetChangeDiameterMinorLoss(link_Down, link_Up);
|
link_Up.MinorLoss += minorLoss;
|
}
|
}
|
|
/*下游管线为多个,上游管线为多个*/
|
if (links_Up.Count > 1 && links_Down.Count > 1)
|
{
|
var UpCount = links_Up.Count;
|
|
//计算两个管线的夹角,根据夹角计算损失系数
|
foreach (var link_Up in links_Up)
|
{
|
foreach (var link_Down in links_Down)
|
{
|
var angle = GetAngle(link_Down, link_Up);
|
var minorLoss = 0f;
|
minorLoss += GetMinorLossByAngle(angle);
|
minorLoss += GetChangeDiameterMinorLoss(link_Down, link_Up);
|
link_Up.MinorLoss += minorLoss / UpCount;
|
}
|
}
|
}
|
});
|
}
|
|
private static float GetChangeDiameterMinorLoss(LinkViewModel link_Down, LinkViewModel link_Up)
|
{
|
var Diameter_Down = link_Down.Diameter;
|
var Diameter_Up = link_Up.Diameter;
|
//计算两个管线变径的损失系数
|
var minorLoss = 0f;
|
if (Diameter_Down >= Diameter_Up)//突然变粗
|
{
|
minorLoss = (float)Math.Pow(1 - Diameter_Up / Diameter_Down, 2);
|
}
|
else//突然变细
|
{
|
minorLoss = 0.5f * (1 - Diameter_Down / Diameter_Up);
|
}
|
|
return minorLoss;
|
}
|
|
private static double GetAngle(LinkViewModel link_Down, LinkViewModel link_Up)
|
{
|
//两个管线link_Down,link_Up的向量
|
Vector3D vector_Down = new Vector3D(link_Down.EndNode.X - link_Down.StartNode.X, link_Down.EndNode.Y - link_Down.StartNode.Y, link_Down.EndNode.Elev - link_Down.StartNode.Elev);
|
Vector3D vector_Up = new Vector3D(link_Up.EndNode.X - link_Up.StartNode.X, link_Up.EndNode.Y - link_Up.StartNode.Y, link_Up.EndNode.Elev - link_Up.StartNode.Elev);
|
//获取两个向量vector_Down,vector_Up的空间夹角
|
if (vector_Down.Length == 0 || vector_Up.Length == 0) return 0;
|
else
|
return Vector3D.CalculateAngle(vector_Down, vector_Up);
|
}
|
|
private static float GetMinorLossByAngle(double angle)
|
{
|
double minorLoss;
|
minorLoss = 0.946 * Math.Pow(Math.Sin(Math.Abs(angle) / 2), 2) + 2.05 * Math.Pow(Math.Sin(Math.Abs(angle) / 2), 4);
|
|
return (float)minorLoss;
|
}
|
|
public void BuildToInp(string filePath, string userCoorString = null, string sourcePath = null, bool isReplace = false)
|
{
|
if (sourcePath == null) sourcePath = filePath;
|
|
string tempString = "";
|
if (!isReplace)
|
{
|
var tempPath = Path.Combine(Directory.GetCurrentDirectory(), @"template\inp\导出模板.inp");
|
if (!File.Exists(tempPath))
|
{
|
throw new Exception($"模板文件不存在[{tempPath}]");
|
}
|
tempString = File.ReadAllText(tempPath);
|
}
|
else
|
{
|
tempString = File.ReadAllText(sourcePath);
|
}
|
|
Dictionary<string, string> dictExchange = new Dictionary<string, string>() {
|
{"{junctions}","{0}" },
|
{"{reservoirs}","{1}" },
|
{"{tanks}","{2}" },
|
{"{pipes}","{3}" },
|
{"{valves}","{4}" },
|
{"{pumps}","{5}" },
|
{"{coor}","{6}" },
|
{"{curve}","{7}" },
|
};
|
dictExchange?.ToList().ForEach(m => tempString = tempString.Replace(m.Key, m.Value));
|
|
StringBuilder junctionStringBuilder = new StringBuilder();
|
|
junctionStringBuilder.AppendLine(";ID Elev Demand Pattern Type");
|
|
Nodes.ForEach(o0 =>
|
{
|
var o = o0;
|
if (!o.Visible) return;
|
|
if (o is JunctionViewModel j)
|
junctionStringBuilder.AppendLine(j.ToString() + $"{j.Level}\tJunction\t{o.Tags}");
|
else if (o is MeterViewModel m)
|
junctionStringBuilder.AppendLine(m.ToString() + $"{o.Level}\tMeter\t{o.Tags}\t{m.DlTemplateID}");
|
else if (o is NozzleViewModel no)
|
junctionStringBuilder.AppendLine(no.ToString() + $"{o.Level}\tNozzle\t{o.Tags}\t{no.FlowCoefficient}");
|
});
|
string junctionString = junctionStringBuilder.ToString();
|
|
StringBuilder reservoirStringBuilder = new StringBuilder();
|
|
reservoirStringBuilder.AppendLine(";ID Head Pattern ");
|
|
reservoirs.ForEach(o =>
|
{
|
if (!o.Visible) return;
|
reservoirStringBuilder.AppendLine(o.ToString() + $"{o.Level}\t{o.Elev}\t{o.Tags}");
|
});
|
string reserverString = reservoirStringBuilder.ToString();
|
|
StringBuilder tankStringBuilder = new StringBuilder();
|
|
tankStringBuilder.AppendLine(";ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve Overflow");
|
|
tanks.ForEach(o =>
|
{
|
if (!o.Visible) return;
|
tankStringBuilder.AppendLine(o.ToString() + $"{o.Level}\tTank\t{o.Tags}");
|
});
|
string tankString = tankStringBuilder.ToString();
|
|
StringBuilder pipeStringBuilder = new StringBuilder();
|
|
pipeStringBuilder.AppendLine(";ID Node1 Node2 Length Diameter Roughness MinorLoss Status");
|
|
Links.ForEach(o0 =>
|
{
|
var o = (LinkViewModel)o0;
|
if (!o.Visible) return;
|
if (o is PipeViewModel p)
|
pipeStringBuilder.AppendLine(p.ToString() + $"{p.Level}\tPipe\t{p.Tags}");
|
else if (o is RepeaterViewModel r)
|
pipeStringBuilder.AppendLine(r.ToString());
|
});
|
string pipeString = pipeStringBuilder.ToString();
|
|
StringBuilder valveStringBuilder = new StringBuilder();
|
|
valveStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
valves.ForEach(o =>
|
{
|
if (!o.Visible) return;
|
valveStringBuilder.AppendLine(o.ToString() + $"{o.Level}\tValve\t{o.Tags}");
|
});
|
string valveString = valveStringBuilder.ToString();
|
|
StringBuilder pumpStringBuilder = new StringBuilder();
|
|
pumpStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
pumps.ForEach(o =>
|
{
|
if (!o.Visible) return;
|
pumpStringBuilder.AppendLine(o.ToString() + $"{o.Level}\tPump\t{o.Tags}");
|
});
|
string pumpString = pumpStringBuilder.ToString();
|
|
StringBuilder curveStringBuilder = new StringBuilder();
|
|
curveStringBuilder.AppendLine(@";ID X-Value Y-Value
|
;HEADLOSS:
|
GPVDefault 0 0
|
GPVDefault 100 0 ");
|
|
|
string curveString = curveStringBuilder.ToString();
|
|
StringBuilder coorStringBuilder = new StringBuilder();
|
if (userCoorString == null)
|
{
|
coorStringBuilder.AppendLine(";Node X-Coord Y-Coord");
|
Nodes.ForEach(o => coorStringBuilder.AppendLine(o.ToCoorString()));
|
}
|
else
|
{
|
coorStringBuilder.Append(userCoorString);
|
}
|
|
string coorString = coorStringBuilder.ToString();
|
string output = "";
|
|
StringBuilder emitterStringBuilder = new StringBuilder();
|
emitterStringBuilder.AppendLine(";Junction \tCoefficient");
|
Nodes.ForEach(o => emitterStringBuilder.Append((o).ToEmitterString()));
|
|
string emitterString = emitterStringBuilder.ToString();
|
|
StringBuilder statusStringBuilder = new StringBuilder();
|
statusStringBuilder.AppendLine(";ID \tStatus/Setting\r\n");
|
Links.ForEach(o => statusStringBuilder.Append(o.ToStatusString()));
|
|
string statusString = statusStringBuilder.ToString();
|
|
output = tempString;
|
|
output = replaceContent(output, "JUNCTIONS", junctionString);
|
output = replaceContent(output, "RESERVOIRS", reserverString);
|
output = replaceContent(output, "TANKS", tankString);
|
output = replaceContent(output, "PIPES", pipeString);
|
output = replaceContent(output, "VALVES", valveString);
|
output = replaceContent(output, "PUMPS", pumpString);
|
output = replaceContent(output, "CURVES", curveString);
|
|
output = replaceContent(output, "COORDINATES", coorString);
|
output = replaceContent(output, "EMITTERS", emitterString);
|
output = replaceContent(output, "STATUS", statusString);
|
string backupFolderPath = Path.Combine(Path.GetDirectoryName(filePath), "bk");
|
if (!Directory.Exists(backupFolderPath))
|
{
|
Directory.CreateDirectory(backupFolderPath);
|
}
|
|
string backupFileName = $"{Path.GetFileNameWithoutExtension(filePath)}_{DateTime.Now:yyyyMMddHHmmss}{Path.GetExtension(filePath)}";
|
string backupFilePath = Path.Combine(backupFolderPath, backupFileName);
|
HelperC.Copy(filePath, backupFilePath, true);
|
|
|
// 检查文件是否存在
|
try
|
{
|
HelperC.ClearFileReadOnly(filePath);
|
|
File.WriteAllText(filePath, output);
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show(ex.Message);
|
}
|
|
//MessageBox.Show($"保存成功!");
|
}
|
|
private string replaceContent(string text, string content, string replaceString)
|
{
|
string str = replaceString;
|
|
string replacedText = ReplaceCoordinatesSection(text, content, str);
|
|
return replacedText;
|
//Console.WriteLine(replacedText);
|
}
|
}
|
|
|
|
}
|