forked from nicogis/Geometric-Network-Utility-SOE
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGeometricNetworkValveIsolation.cs
261 lines (220 loc) · 11.9 KB
/
GeometricNetworkValveIsolation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
//-----------------------------------------------------------------------
// <copyright file="GeometricNetworkValveIsolation.cs" company="Studio A&T s.r.l.">
// Copyright (c) Studio A&T s.r.l. All rights reserved.
// </copyright>
// <author>Nicogis</author>
//-----------------------------------------------------------------------
namespace Studioat.ArcGis.Soe.Rest
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.NetworkAnalysis;
using ESRI.ArcGIS.SOESupport;
/// <summary>
/// class GeometricNetworkValveIsolation
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "-")]
internal sealed class GeometricNetworkValveIsolation : GeometricNetwork, IGeometricNetworkValveIsolation
{
/// <summary>
/// Initializes a new instance of the GeometricNetworkValveIsolation class
/// </summary>
/// <param name="geometricNetwork">object geometricNetwork</param>
/// <param name="geometricNetworkParameters">object IGeometricNetworkParameters</param>
/// <param name="valve">feature class valve</param>
/// <param name="station">feature class station</param>
public GeometricNetworkValveIsolation(ESRI.ArcGIS.Geodatabase.IGeometricNetwork geometricNetwork, IGeometricNetworkParameters geometricNetworkParameters, IFeatureClass valve, IFeatureClass station)
: base(geometricNetwork, geometricNetworkParameters)
{
this.Valve = valve;
this.Station = station;
}
/// <summary>
/// Gets or sets feature class Station for Isolation Valve
/// </summary>
public IFeatureClass Station
{
get;
set;
}
/// <summary>
/// Gets or sets feature class Valve for Isolation Valve
/// </summary>
public IFeatureClass Valve
{
get;
set;
}
/// <summary>
/// solve isolation
/// </summary>
/// <returns>object JsonObject</returns>
public override JsonObject Solve()
{
try
{
if ((this.edgeFlags.Length == 0) && (this.junctionFlags.Length == 0))
{
string message = "No input valid flags found";
if (this.flagNotFound.Count == 0)
{
throw new GeometricNetworkException(message);
}
else
{
JsonObject error = (new ObjectError(message)).ToJsonObject();
error.AddArray("flagsNotFound", Helper.GetListJsonObjects(this.flagNotFound));
return error;
}
}
INetwork network = this.geometricNetwork.Network;
ITraceFlowSolverGEN traceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;
INetSolver netSolver = traceFlowSolver as INetSolver;
netSolver.SourceNetwork = network;
this.SetFlagsOrigin(ref traceFlowSolver);
////now create barries based on valves
INetElementBarriersGEN netElementBarriersGEN = new NetElementBarriersClass() as INetElementBarriersGEN;
netElementBarriersGEN.ElementType = esriElementType.esriETJunction;
netElementBarriersGEN.Network = network;
int[] userIds = Helper.GetOIDs(this.Valve);
netElementBarriersGEN.SetBarriers(this.Valve.FeatureClassID, ref userIds);
INetElementBarriers netElementBarriers = netElementBarriersGEN as INetElementBarriers;
netSolver.set_ElementBarriers(esriElementType.esriETJunction, netElementBarriers);
IEnumNetEID junctionEIDs;
IEnumNetEID edgeEIDs;
traceFlowSolver.FindFlowEndElements(esriFlowMethod.esriFMConnected, esriFlowElements.esriFEJunctionsAndEdges, out junctionEIDs, out edgeEIDs);
IEIDHelper eidHelper = new EIDHelperClass();
eidHelper.GeometricNetwork = this.geometricNetwork;
eidHelper.ReturnFeatures = true;
List<IEIDInfo> valveEIDInfoHT = Helper.GetEIDInfoListByFeatureClass(this.Valve.FeatureClassID, junctionEIDs, eidHelper);
traceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;
netSolver = traceFlowSolver as INetSolver;
netSolver.SourceNetwork = network;
this.SetFlagsOrigin(ref traceFlowSolver);
netSolver.DisableElementClass(this.Station.FeatureClassID);
traceFlowSolver.FindFlowEndElements(esriFlowMethod.esriFMConnected, esriFlowElements.esriFEJunctions, out junctionEIDs, out edgeEIDs);
List<IEIDInfo> sourceEIDInfoHT = Helper.GetEIDInfoListByFeatureClass(this.Station.FeatureClassID, junctionEIDs, eidHelper);
////set up trace to find directly reachable sources
traceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;
netSolver = traceFlowSolver as INetSolver;
netSolver.SourceNetwork = network;
this.SetFlagsOrigin(ref traceFlowSolver);
////set barriers in the network based on the saved valves
ISelectionSetBarriers netElementBarrier = new SelectionSetBarriersClass();
foreach (IEIDInfo eidInfo in valveEIDInfoHT)
{
netElementBarrier.Add(this.Valve.FeatureClassID, eidInfo.Feature.OID);
}
netSolver.SelectionSetBarriers = netElementBarrier;
////run trace to find directly reachable sources(without passing valve)
traceFlowSolver.FindFlowElements(esriFlowMethod.esriFMConnected, esriFlowElements.esriFEJunctionsAndEdges, out junctionEIDs, out edgeEIDs);
List<IEIDInfo> sourceDirectEIDInfoHT = Helper.GetEIDInfoListByFeatureClass(this.Station.FeatureClassID, junctionEIDs, eidHelper);
////remove directly reachable sources from source array
foreach (IEIDInfo eidInfo in sourceDirectEIDInfoHT)
{
sourceEIDInfoHT.RemoveAll(x => x.Feature.OID == eidInfo.Feature.OID);
}
List<IEIDInfo> noSourceValveHT = new List<IEIDInfo>();
List<IEIDInfo> hasSourceValveHT = new List<IEIDInfo>();
List<int> listBarrierIds;
bool foundSource;
foreach (IEIDInfo valve in valveEIDInfoHT)
{
foundSource = false;
////create array of all isolation valve excluding the current one
listBarrierIds = new List<int>();
if (valveEIDInfoHT.Count > 1)
{
listBarrierIds.AddRange(valveEIDInfoHT.ConvertAll<int>(i => i.Feature.OID));
if (listBarrierIds.Contains(valve.Feature.OID))
{
listBarrierIds.Remove(valve.Feature.OID);
}
}
////for each source attempt to trace
INetFlag netFlag1;
INetFlag netFlag2;
foreach (IEIDInfo source in sourceEIDInfoHT)
{
////setup trace to test each valve
traceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;
netSolver = traceFlowSolver as INetSolver;
netSolver.SourceNetwork = network;
////set the first junction flag for path finding based this current valve
netFlag1 = new JunctionFlagClass();
netFlag1.UserClassID = valve.Feature.Class.ObjectClassID;
netFlag1.UserID = valve.Feature.OID;
netFlag1.UserSubID = 0;
netFlag1.Label = "Origin";
////set the second and last trace flag at this source
netFlag2 = new JunctionFlagClass();
netFlag2.UserClassID = source.Feature.Class.ObjectClassID;
netFlag2.UserID = source.Feature.OID;
netFlag2.UserSubID = 0;
netFlag2.Label = "Destination";
Helper.AddTwoJunctionFlagsToTraceSolver(ref traceFlowSolver, netFlag1, netFlag2);
if (listBarrierIds.Count > 0)
{
netElementBarriersGEN = new NetElementBarriersClass() as INetElementBarriersGEN;
netElementBarriersGEN.ElementType = esriElementType.esriETJunction;
netElementBarriersGEN.Network = network;
int[] barrierIds = listBarrierIds.ToArray();
netElementBarriersGEN.SetBarriers(this.Valve.FeatureClassID, ref barrierIds);
netElementBarriers = netElementBarriersGEN as INetElementBarriers;
netSolver.set_ElementBarriers(esriElementType.esriETJunction, netElementBarriers);
}
////run trace
object[] segCosts = new object[1];
segCosts[0] = new object();
edgeEIDs = null;
traceFlowSolver.FindPath(esriFlowMethod.esriFMConnected, esriShortestPathObjFn.esriSPObjFnMinSum, out junctionEIDs, out edgeEIDs, 1, ref segCosts);
if (edgeEIDs != null && edgeEIDs.Count > 0)
{
foundSource = true;
break;
}
}
if (foundSource)
{
hasSourceValveHT.Add(valve);
}
else
{
noSourceValveHT.Add(valve);
}
}
traceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;
netSolver = traceFlowSolver as INetSolver;
netSolver.SourceNetwork = network;
this.SetFlagsOrigin(ref traceFlowSolver);
////set the barrier in the network based on the saved valves
netElementBarrier = new SelectionSetBarriersClass();
foreach (IEIDInfo eidInfo in hasSourceValveHT)
{
netElementBarrier.Add(this.Valve.FeatureClassID, eidInfo.Feature.OID);
}
netSolver.SelectionSetBarriers = netElementBarrier;
////run last trace
traceFlowSolver.FindFlowElements(esriFlowMethod.esriFMConnected, this.FlowElements, out junctionEIDs, out edgeEIDs);
////deal with out put juncEIDs and edgeEIDs
JsonObject objectJson = new JsonObject();
this.SetResults(ref objectJson, edgeEIDs, junctionEIDs);
objectJson.AddArray("flagsNotFound", Helper.GetListJsonObjects(this.flagNotFound));
////valves
if (hasSourceValveHT.Count > 0)
{
JsonObject[] featureSetValves;
this.GetTrace(Helper.GetEnumNetEID(hasSourceValveHT, esriElementType.esriETJunction), out featureSetValves);
objectJson.AddJsonObject("valves", featureSetValves[0]);
}
return objectJson;
}
catch (Exception e)
{
return (new ObjectError(e.Message)).ToJsonObject();
}
}
}
}