SystemParse.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. 
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using SAGA.RevitUtils;
  8. using SAGA.RevitUtils.Extends;
  9. using Autodesk.Revit.DB;
  10. namespace SAGA.GplotRelationComputerManage
  11. {
  12. public class SystemParse
  13. {
  14. public SystemParse(SystemParseSetting setting)
  15. {
  16. Setting = setting;
  17. }
  18. #region 属性相关
  19. /// <summary>
  20. /// 系统解析设置
  21. /// </summary>
  22. public SystemParseSetting Setting { get; private set; }
  23. #endregion
  24. public List<ElementEdgesArray> Execute(List<Element> startElements)
  25. {
  26. List<ElementEdgesArray> arrays = new List<ElementEdgesArray>();
  27. var newStartElements = startElements.Distinct(new ElementEqualComparer()).ToList();
  28. while (newStartElements.Any())
  29. {
  30. var baseElement = newStartElements[0];
  31. var array = Execute(baseElement);
  32. var containElements = array.GetRefElements();
  33. newStartElements = newStartElements.Except(containElements, new ElementEqualComparer()).ToList();
  34. arrays.Add(array);
  35. }
  36. return arrays;
  37. }
  38. /// <summary>
  39. /// 解析单个元素连接的系统
  40. /// </summary>
  41. /// <param name="element"></param>
  42. /// <returns></returns>
  43. public ElementEdgesArray Execute(Element element)
  44. {
  45. ElementEdgesArray edges =GetOriginEdges(element);
  46. SetDisableCombineVertexes(edges);
  47. edges = RemoveVertexes(edges);
  48. #region 补充实例节点
  49. //edges = SplitEdges(edges);
  50. #endregion
  51. #region 合并没有意义的节点
  52. edges = CombineVertexes(edges);
  53. #endregion
  54. #region 业务相关点
  55. //确定点的数据信息
  56. LoadEquipmentItem(edges);
  57. //确定边类型
  58. LoadEdgeSystem(edges);
  59. #endregion
  60. #region 重复迭代进行串并联操作
  61. edges = ElementEdgesArray.ArrangeHandle(edges);
  62. edges.ArrangeVertex();//整理节点拓扑关系
  63. #endregion
  64. return edges;
  65. }
  66. /// <summary>
  67. /// 获取原始的边集列表
  68. /// </summary>
  69. /// <param name="element"></param>
  70. /// <returns></returns>
  71. public ElementEdgesArray GetOriginEdges(Element element)
  72. {
  73. Element startElement = element;
  74. ElementEdgesArray edges = new ElementEdgesArray();
  75. #region 构建初始边集合
  76. Queue<ParseQueueItem> queueItems = new Queue<ParseQueueItem>();
  77. queueItems.Enqueue(new ParseQueueItem(Setting.GetJoinItems(startElement, new List<int>())));
  78. List<int> usedNodeIds = new List<int>();
  79. while (queueItems.Any())
  80. {
  81. var currentQueueItems = queueItems.Peek();
  82. if (currentQueueItems.BaseElement == null)
  83. {
  84. queueItems.Dequeue();
  85. continue;
  86. }
  87. var joinItem = currentQueueItems.MoveNext();
  88. if (joinItem == null)
  89. {
  90. //移除并循环
  91. usedNodeIds.Add(currentQueueItems.BaseElement.Id.IntegerValue);
  92. queueItems.Dequeue();
  93. continue;
  94. }
  95. //获取基础节点信息
  96. var baseVertex = new ElementsVertex(joinItem.BaseElement);
  97. #region 关联元素为null时处理
  98. if (joinItem.RefElement == null)
  99. {
  100. var newVertex = ElementsVertex.CreateEmptyVertex();
  101. ElementsEdge edge = ElementsEdge.CreateEdge(baseVertex, newVertex, new List<Element>());
  102. newVertex.EquipLocation = joinItem.BaseConnector.Origin;
  103. edges.AddEdge(edge);
  104. continue;
  105. }
  106. #endregion
  107. List<Element> elements = new List<Element>() { joinItem.RefElement };
  108. List<int> usedIds = new List<int>() { joinItem.BaseElement.Id.IntegerValue };
  109. for (int i = 0; i < elements.Count; i++)
  110. {
  111. var current = elements[i];
  112. if (current == null)
  113. continue;
  114. if (i > 0)
  115. {
  116. usedIds = new List<int>() { elements[i - 1].Id.IntegerValue };
  117. }
  118. #region 遍历数组检验
  119. var queueItem = queueItems.FirstOrDefault(q => q.BaseElement != null && q.BaseElement.IsEqual(current));
  120. if (queueItem != null)
  121. {
  122. queueItem.UsedJoinItems.AddRange(usedIds);
  123. var newVertex = new ElementsVertex(current);
  124. //Math.Max(i, 1)
  125. var paths = elements.GetRange(0, i).ToList();
  126. ElementsEdge edge = ElementsEdge.CreateEdge(baseVertex, newVertex, paths);
  127. edges.AddEdge(edge);
  128. break;
  129. }
  130. #endregion
  131. #region 如果是节点
  132. var existVertex = edges.GetAvailableVertexes(v => v.IsMatch(current)).Any();
  133. if (existVertex || Setting.IsForkNode(current)|| MBIInfoUtil.IsEquipment(current))
  134. {
  135. var newVertex = new ElementsVertex(current);
  136. var paths = elements.GetRange(0, i).ToList();
  137. ElementsEdge edge = ElementsEdge.CreateEdge(baseVertex, newVertex, paths);
  138. edges.AddEdge(edge);
  139. //将分叉节点加入遍历序列
  140. var handled = usedNodeIds.Any(id => id == current.Id.IntegerValue);
  141. UpdateQueueItem(queueItems, current, usedIds, handled);
  142. break;
  143. }
  144. #endregion
  145. var joinItems = Setting.GetJoinItems(current, usedIds);
  146. if (joinItems.Count == 0)
  147. {
  148. //断头连接,增加节点
  149. var newVertex = new ElementsVertex(current);
  150. var paths = elements.GetRange(0, i).ToList();
  151. ElementsEdge edge = ElementsEdge.CreateEdge(baseVertex, newVertex, paths);
  152. edges.AddEdge(edge);
  153. break;
  154. }
  155. else if (joinItems.Count == 1)
  156. {
  157. var refElement = joinItems[0].RefElement;
  158. #region 检测为null处理
  159. if (refElement == null)
  160. {
  161. var newVertex = ElementsVertex.CreateEmptyVertex();
  162. //断头点放在path里
  163. var paths = elements.GetRange(0, Math.Max((i + 1), 1)).ToList();
  164. ElementsEdge edge = ElementsEdge.CreateEdge(baseVertex, newVertex, paths);
  165. newVertex.EquipLocation = joinItems[0].BaseConnector.Origin;
  166. edges.AddEdge(edge);
  167. break;
  168. }
  169. #endregion
  170. elements.Add(joinItems[0].RefElement);
  171. }
  172. else
  173. {
  174. //todo 这个逻辑还未遇到
  175. }
  176. }
  177. }
  178. #endregion
  179. return edges;
  180. }
  181. #region 辅助私有方法
  182. /// <summary>
  183. /// 更新遍历队列信息
  184. /// </summary>
  185. /// <param name="queueItems"></param>
  186. /// <param name="current"></param>
  187. /// <param name="usedIds"></param>
  188. /// <param name="handled"></param>
  189. private void UpdateQueueItem(Queue<ParseQueueItem> queueItems, Element current, List<int> usedIds, bool handled)
  190. {
  191. var queItem = queueItems.FirstOrDefault(q => q.IsMatched(current.Id.IntegerValue));
  192. //如果该节点处理过,并且在现有队列中没有找到,则直接返回
  193. if (handled && queItem == null)
  194. return;
  195. if (queItem == null)
  196. {
  197. queueItems.Enqueue(new ParseQueueItem(Setting.GetJoinItems(current, usedIds)));
  198. }
  199. else
  200. {
  201. queItem.UsedJoinItems.AddRange(usedIds);
  202. }
  203. }
  204. /// <summary>
  205. /// 合并中间没有连接有意设备的点【两个节点之间只有管道和管件】
  206. /// </summary>
  207. /// <param name="edgeArray"></param>
  208. private ElementEdgesArray CombineVertexes(ElementEdgesArray edgeArray)
  209. {
  210. //1、将无用边去除,将所有边涉及到的元素组织成新点。
  211. //2、旧的点成为新点的子节点
  212. //寻找去除的管道,需要再加大判定力度
  213. var originEdges = edgeArray.GetAvailableEdges(null);
  214. HandledMap map = new HandledMap();
  215. for (int i = 0; i < originEdges.Count; i++)
  216. {
  217. var baseEdge = originEdges[i];
  218. if (map.GetHandled(baseEdge))
  219. continue;
  220. if (!Setting.UselessEdge(baseEdge))
  221. {
  222. continue;
  223. }
  224. //todo 如果两个节点之下还有一条其他的包含设备的边,则该边的两点不能合并
  225. var refEdges = edgeArray.GetEdges(baseEdge.RealStart.Id, baseEdge.RealEnd.Id);
  226. if (refEdges.Count > 1 && refEdges.Any(e => !Setting.UselessEdge(baseEdge)))
  227. {
  228. continue;
  229. }
  230. List<Element> elements = new List<Element>();
  231. foreach (var elementsEdge in refEdges)
  232. {
  233. elements.AddRange(elementsEdge.RealStart.RefData);
  234. elements.AddRange(elementsEdge.RealEnd.RefData);
  235. elements.AddRange(elementsEdge.RefData);
  236. edgeArray.RemoveEdge(baseEdge);
  237. map.SetHandled(elementsEdge.Id, true);
  238. }
  239. elements = elements.Distinct(new ElementEqualComparer()).ToList();
  240. ElementsVertex newElements = new ElementsVertex(elements);
  241. edgeArray.AddVertex(newElements);
  242. }
  243. return edgeArray;
  244. }
  245. /// <summary>
  246. /// 通过边中的设备对象分割边
  247. /// </summary>
  248. /// <param name="edgeArray"></param>
  249. private ElementEdgesArray SplitEdges(ElementEdgesArray edgeArray)
  250. {
  251. var originEdges = edgeArray.Edges.ToList();
  252. for (int i = 0; i < originEdges.Count; i++)
  253. {
  254. var baseEdge = originEdges[i];
  255. var elements = baseEdge.RefData.ToList();
  256. //elelments从开始点到结束点排列
  257. var start = baseEdge.RealStart;
  258. for (int j = 0; j < elements.Count; j++)
  259. {
  260. var currentElement = elements[j];
  261. if (MBIInfoUtil.IsEquipment(currentElement))
  262. {
  263. var tempEnd = edgeArray.AddVertex(new ElementsVertex(currentElement));
  264. var tempEdge = ElementsEdge.CreateEdge(start, tempEnd, elements.GetRange(0, j));
  265. edgeArray.AddEdge(tempEdge);
  266. #region 复位处理
  267. elements.RemoveRange(0, j);
  268. j = 0;
  269. start = tempEnd;
  270. #endregion
  271. }
  272. }
  273. if (baseEdge.RealStart.Id == start.Id)
  274. {
  275. //没有变化
  276. continue;
  277. }
  278. //有变化
  279. var tailEdge = ElementsEdge.CreateEdge(start, baseEdge.RealEnd, elements);
  280. edgeArray.AddEdge(tailEdge);
  281. edgeArray.RemoveEdge(baseEdge);
  282. }
  283. return edgeArray;
  284. }
  285. /// <summary>
  286. /// 移除空白点
  287. /// </summary>
  288. /// <param name="edgeArray"></param>
  289. /// <returns></returns>
  290. private ElementEdgesArray RemoveVertexes(ElementEdgesArray edgeArray)
  291. {
  292. var originVertexes = edgeArray.GetAvailableVertexes(null);
  293. foreach (var vertex in originVertexes)
  294. {
  295. var edges = edgeArray.GetEdges(vertex.Id);
  296. if (edges.Count == 2 && vertex.RefData.All(e=> !MBIInfoUtil.IsEquipment(e)))
  297. {
  298. edgeArray.DeleteVertex(vertex.Id, null);
  299. }
  300. }
  301. return edgeArray;
  302. }
  303. /// <summary>
  304. /// 设置不能合并的节点信息
  305. /// </summary>
  306. /// <param name="edgeArray"></param>
  307. private void SetDisableCombineVertexes(ElementEdgesArray edgeArray)
  308. {
  309. var vertexes = edgeArray.GetAvailableVertexes(null);
  310. for (int i = 0; i < vertexes.Count; i++)
  311. {
  312. var current = vertexes[i];
  313. if (current.RefData == null && current.RefData.Any(SystemCalcUtil.IsStartValve))
  314. {
  315. current.SetDisableCombine(true);
  316. }
  317. }
  318. }
  319. #endregion
  320. public void LoadEquipmentItem(ElementEdgesArray edgesArray)
  321. {
  322. var setting = this.Setting;
  323. var vertexes = edgesArray.GetAvailableVertexes(null);
  324. for (int i = 0; i < vertexes.Count; i++)
  325. {
  326. var vertex = vertexes[i];
  327. var elements = vertex.RefData?.ToList() ?? new List<Element>();
  328. if (elements.Count == 0)
  329. {
  330. vertex.SetEquipment(new EquipmentItem() { IsVirtual = true, Name = "空间" + vertex.EquipLocation.ToString(), Id = "空间" + vertex.EquipLocation.ToString() });
  331. }
  332. else
  333. {
  334. var equipment = elements.FirstOrDefault(e => MBIInfoUtil.IsEquipment(e));
  335. if (equipment != null)
  336. {
  337. string name = MBIInfoUtil.GetShowName(equipment);
  338. vertex.SetEquipment(new EquipmentItem() { Name = name, Id= equipment.Id.ToString() });
  339. continue;
  340. }
  341. var valve = elements.FirstOrDefault(e => SystemCalcUtil.IsStartValve(e));
  342. if (valve != null)
  343. {
  344. vertex.SetEquipment(new EquipmentItem() {IsVirtual=true, Name = valve.GetFamily().Name, Id = valve.Id.ToString() });
  345. continue;
  346. }
  347. }
  348. }
  349. }
  350. /// <summary>
  351. /// 初始化边的系统类型
  352. /// </summary>
  353. /// <param name="edgesArray"></param>
  354. public void LoadEdgeSystem(ElementEdgesArray edgesArray)
  355. {
  356. #region 系统处理
  357. /*
  358. * 每条原始边,只有一个系统类型
  359. */
  360. var originEdges = edgesArray.Edges.Where(e => !e.Children.Any()).ToList();
  361. foreach (var originEdge in originEdges)
  362. {
  363. var refElements = originEdge.RefData.ToList();
  364. //获取边系统类型
  365. originEdge.SystemName = (refElements.FirstOrDefault(e => e is MEPCurve) as MEPCurve)?.GetSystemTypeName();
  366. //根据系统类型和特殊设备确定旁通和补水;未完,待续
  367. var systemItem = Setting.RelationTypeShell.GetFirstMatchSystem(originEdge.SystemName);
  368. if (systemItem != null)
  369. {
  370. originEdge.EdgeCategory = systemItem.ContainEdgeTypes.FirstOrDefault();// Setting.GplotOptions.GetCategory(originEdge.SystemName);
  371. originEdge.FlowType = systemItem.FlowType == FlowType.In ? 2 : 1;
  372. }
  373. }
  374. #endregion
  375. #region 方向处理
  376. var vertexes = edgesArray.GetAvailableVertexes(null)
  377. .Where(v => SystemCalcUtil.IsStartValveName(v.GetEquipment()?.Name));
  378. if (!vertexes.Any())
  379. return;
  380. //优先找-1边的类型,外挂顺其自然;
  381. #region 初始化数据源
  382. List<Tuple<ElementsVertex, List<ElementsEdge>>> refEdges =
  383. new List<Tuple<ElementsVertex, List<ElementsEdge>>>();
  384. foreach (var elementsVertex in vertexes)
  385. {
  386. var tempEdges = edgesArray.GetEdges(elementsVertex.Id);
  387. if (tempEdges.Any())
  388. {
  389. refEdges.Add(new Tuple<ElementsVertex, List<ElementsEdge>>(elementsVertex, tempEdges));
  390. var item = elementsVertex.GetEquipment();
  391. if (item == null)
  392. {
  393. continue;
  394. }
  395. if (tempEdges.Any(e => e.FlowType == 2))
  396. {
  397. item.Name = "出口"+item.Id;
  398. }
  399. else
  400. {
  401. item.Name = "入口"+item.Id;
  402. }
  403. }
  404. }
  405. #endregion
  406. #region 找到起始点
  407. int flag = 2;
  408. var useVertex = refEdges.FirstOrDefault(c =>
  409. c.Item2.Any(e =>e.FlowType == flag));
  410. if (useVertex == null)
  411. {
  412. flag = 1;
  413. useVertex = refEdges.FirstOrDefault(c =>
  414. c.Item2.Any(e => e.FlowType == flag));
  415. }
  416. if (useVertex == null)
  417. {
  418. useVertex = refEdges.FirstOrDefault();
  419. flag =1;
  420. }
  421. #endregion
  422. #region 查找所有路径信息
  423. List<string> handledIds = new List<string>();
  424. var elementVertexList = edgesArray.GetRouted(useVertex.Item1);
  425. foreach (var vertexList in elementVertexList)
  426. {
  427. //此时操作原始图,可以使用下述方法
  428. for (int i = 1; i < vertexList.Count; i++)
  429. {
  430. var startId = vertexList[i - 1].Id;
  431. var endId = vertexList[i ].Id;
  432. var edges = edgesArray.GetEdges(startId, endId);
  433. //理论上只有一个
  434. foreach (var elementsEdge in edges)
  435. {
  436. if (handledIds.Any(id => id == elementsEdge.Id))
  437. {
  438. continue;
  439. }
  440. handledIds.Add(elementsEdge.Id);
  441. if (flag == 1)
  442. {
  443. if (elementsEdge.RealStart.Id== startId)
  444. {
  445. elementsEdge.Reverse();
  446. }
  447. }
  448. else
  449. {
  450. //如果是回水端,开始点不一致则掉转
  451. if (elementsEdge.RealStart.Id != startId)
  452. {
  453. elementsEdge.Reverse();
  454. }
  455. }
  456. }
  457. }
  458. }
  459. #endregion
  460. #endregion
  461. }
  462. }
  463. }