GplotGraphParse.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /*-------------------------------------------------------------------------
  2. * 功能描述:GplotGraphParse
  3. * 作者:xulisong
  4. * 创建时间: 2019/2/14 17:51:58
  5. * 版本号:v1.0
  6. * -------------------------------------------------------------------------*/
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using Autodesk.Revit.DB;
  13. using SAGA.DotNetUtils.Data;
  14. using SAGA.GplotRelationComputerManage.SystemChecks;
  15. using SAGA.RevitUtils;
  16. using SAGA.RevitUtils.Data.Graph;
  17. using SAGA.RevitUtils.Extends;
  18. namespace SAGA.GplotRelationComputerManage
  19. {
  20. /// <summary>
  21. /// 拓扑图解析
  22. /// </summary>
  23. public class GplotGraphParse
  24. {
  25. public GplotGraphParse(GplotGraphSetting setting)
  26. {
  27. Setting = setting;
  28. }
  29. #region 属性相关
  30. /// <summary>
  31. /// 系统解析设置
  32. /// </summary>
  33. public GplotGraphSetting Setting { get; private set; }
  34. #endregion
  35. #region 创建拓扑图信息
  36. /// <summary>
  37. /// 创建拓扑结构图
  38. /// </summary>
  39. /// <param name="startElements"></param>
  40. /// <returns></returns>
  41. public List<SystemGraph> CreateGplotGraphs(List<Element> startElements)
  42. {
  43. List<SystemGraph> arrays = new List<SystemGraph>();
  44. var newStartElements = startElements.Distinct(new ElementEqualComparer()).ToList();
  45. while (newStartElements.Any())
  46. {
  47. var baseElement = newStartElements[0];
  48. newStartElements.Remove(baseElement);
  49. var graph = CreateGplotGraph(baseElement);
  50. var containElements = graph.GetRefElements();
  51. newStartElements = newStartElements.Except(containElements, new ElementEqualComparer()).ToList();
  52. arrays.Add(graph);
  53. }
  54. return arrays;
  55. }
  56. /// <summary>
  57. /// 创建拓扑结构图
  58. /// </summary>
  59. /// <param name="element"></param>
  60. /// <returns></returns>
  61. public SystemGraph CreateGplotGraph(Element element)
  62. {
  63. SystemGraph graph = GetOriginGraph(element);
  64. //节点处理
  65. ArrangeVertex(graph);
  66. //边处理
  67. ArrangeEdge(graph);
  68. return graph;
  69. }
  70. #endregion
  71. #region 解析原始图
  72. /// <summary>
  73. /// 创建原始的节点图,以起点元素为首个节点
  74. /// </summary>
  75. /// <param name="element"></param>
  76. /// <returns></returns>
  77. public SystemGraph GetOriginGraph(Element element)
  78. {
  79. return SystemGraphUtil.CreateGraph(element, Setting.IgnoredConnector, Setting.IgnoredElement,Setting.BreakElement);
  80. }
  81. #endregion
  82. #region 相关子方法
  83. #region 节点处理
  84. /// <summary>
  85. /// 整理点
  86. /// </summary>
  87. /// <param name="graph"></param>
  88. private void ArrangeVertex(SystemGraph graph)
  89. {
  90. #region 分析
  91. /*
  92. * 1、如果节点元素是一个管道,则将管道没有连接的那一个点创建一个“空间”设备,标记不可合并
  93. * 2、如果节点是设备或者特殊阀门,则标记不能合并,并加载物理世界相关设备信息
  94. * 3、如果一个点只有两条边,且该点可以被合并,则创建新边,关联上述两条边和点信息;删除旧的信息
  95. * 4、如果一条边的两个点,都是可合并,并过滤所有以这两个点为顶点的边,将这些信息合并成新的点;
  96. * 处理这种点融合边的情况,有两种方案:1,创建新点,将旧的点设置为新点的子节点。2、修改所有边的相依的节点Id为新Id
  97. * 方案各有利弊,第一种保留了初始状态,第二种以后遍历时方便
  98. */
  99. #endregion
  100. AttachVertexInfo(graph);
  101. CombineVertex(graph);
  102. }
  103. /// <summary>
  104. /// 附加节点信息
  105. /// </summary>
  106. /// <param name="graph"></param>
  107. private void AttachVertexInfo(SystemGraph graph)
  108. {
  109. var useVertexes = graph.GetBootVertexs();
  110. #region
  111. foreach (var systemVertex in useVertexes)
  112. {
  113. var data = systemVertex.Data;
  114. if (!data.Any())
  115. {
  116. continue;
  117. }
  118. //理论上此时场景,有且仅有一个关联元素
  119. var useElement = data[0];
  120. #region 虚拟设备处理
  121. EquipmentItem item = new EquipmentItem();
  122. if (useElement is MEPCurve)
  123. {
  124. item.IsVirtual = true;
  125. var edges = graph.GetOutEdges(systemVertex.Id);
  126. if (edges.Count == 1)
  127. {
  128. var currentEdge = edges[0];
  129. var joinItems = JoinItem.GetJoinItems(useElement);
  130. foreach (var joinItem in joinItems)
  131. {
  132. if (joinItem.RefElement != null && currentEdge.Data.All(e => e.Id != joinItem.RefElement.Id))
  133. {
  134. //处理点边关联信息
  135. currentEdge.Data.Add(useElement);
  136. systemVertex.Data.Remove(useElement);
  137. systemVertex.CanCombine = false;
  138. //找到断头点
  139. var location = joinItem.RefConnector.Origin;
  140. var space = useElement.Document.GetSpaceAtPoint(location);
  141. if (space != null)
  142. {
  143. item.Id = space.Id.ToString();
  144. item.BimId = space.GetBimId();
  145. }
  146. else
  147. {
  148. item.Name = string.Format("空间{0}", location.ToString());
  149. }
  150. item.ElementType = SystemCalcUtil.IsStart(useElement)?ElementType.VerticalPipe: ElementType.Space;
  151. if (SystemCalcUtil.IsStart(useElement))
  152. {
  153. item.Name = string.Format("【{0}】立管:{1}", (useElement as MEPCurve).GetSystemTypeName(),useElement.Id.ToString());
  154. }
  155. systemVertex.SetEquipment(item);
  156. break;
  157. }
  158. }
  159. }
  160. continue;
  161. }
  162. #endregion
  163. #region 真实设备处理
  164. item.Id = useElement.Id.ToString();
  165. item.BimId = useElement.GetBimId();
  166. item.Name = useElement.GetFamily()?.Name;
  167. if (MBIInfoUtil.IsEquipment(useElement))
  168. {
  169. systemVertex.CanCombine = false;
  170. item.ElementType = ElementType.Equipment;
  171. systemVertex.SetEquipment(item);
  172. continue;
  173. }
  174. if (SystemCalcUtil.IsStartValve(useElement))
  175. {
  176. systemVertex.CanCombine = false;
  177. item.IsVirtual = true;
  178. item.ElementType = ElementType.Equipment;
  179. systemVertex.SetEquipment(item);
  180. continue;
  181. }
  182. #endregion
  183. }
  184. #endregion
  185. }
  186. /// <summary>
  187. /// 合并节点
  188. /// </summary>
  189. /// <param name="graph"></param>
  190. public void CombineVertex(SystemGraph graph)
  191. {
  192. #region 以点为基础处理
  193. var useVertexes = graph.GetBootVertexs();
  194. foreach (var systemVertex in useVertexes)
  195. {
  196. if (!systemVertex.CanCombine)
  197. {
  198. continue;
  199. }
  200. var edges = graph.GetInEdges(systemVertex.Id);
  201. if (edges.Count != 2)
  202. {
  203. continue;
  204. }
  205. string startId = edges[0].GetAnotherVertex(systemVertex.Id);
  206. string endId = edges[1].GetAnotherVertex(systemVertex.Id);
  207. edges.ForEach(e => graph.RemoveEdge(e.Id));
  208. graph.RemoveVertex(systemVertex.Id);
  209. var newEdge = new SystemEdge(startId, endId);
  210. newEdge.Data = new SystemData(edges[0].Data);
  211. newEdge.Data.ExtendRefElements(edges[1].Data);
  212. newEdge.Data.ExtendRefElements(systemVertex.Data);
  213. graph.AddEdge(newEdge);
  214. }
  215. #endregion
  216. #region 以边为基础处理
  217. HandledMap map = new HandledMap();
  218. var useEdges = graph.GetBootEdges();
  219. for (int i = 0; i < useEdges.Count; i++)
  220. {
  221. var baseEdge = useEdges[i];
  222. if (map.GetHandled(baseEdge.Id))
  223. continue;
  224. var startVertex = graph.GetBootStartVertex(baseEdge);
  225. var endVertex = graph.GetBootEndVertex(baseEdge);
  226. if (startVertex == null || endVertex == null)
  227. {
  228. continue;
  229. }
  230. if (!startVertex.CanCombine || !endVertex.CanCombine)
  231. {
  232. continue;
  233. }
  234. // 如果两个节点之下还有一条其他的包含设备的边,则该边的两点不能合并
  235. var refEdges = graph.GetEdges(baseEdge.StartVertex, baseEdge.EndVertex);
  236. #region 创建新的点
  237. List<Element> elements = new List<Element>();
  238. elements.AddRange(startVertex.Data);
  239. elements.AddRange(endVertex.Data);
  240. foreach (var elementsEdge in refEdges)
  241. {
  242. elements.AddRange(elementsEdge.Data);
  243. graph.RemoveEdge(elementsEdge.Id);
  244. map.SetHandled(elementsEdge.Id, true);
  245. }
  246. graph.RemoveVertex(startVertex.Id);
  247. graph.RemoveVertex(endVertex.Id);
  248. elements = elements.Distinct(new ElementEqualComparer()).ToList();
  249. SystemVertex newVertex = new SystemVertex(new SystemData(elements));
  250. newVertex = graph.AddVertex(newVertex);
  251. #endregion
  252. #region 更新关联边的关联点
  253. var vertexIds = new List<string>() { startVertex.Id, endVertex.Id };
  254. foreach (var vertexId in vertexIds)
  255. {
  256. var edges = graph.GetInEdges(vertexId);
  257. foreach (var systemEdge in edges)
  258. {
  259. var flag = systemEdge.ContainVertex(vertexId);
  260. if (flag == 0)
  261. {
  262. systemEdge.UpdateStartVertex(newVertex.Id);
  263. }
  264. else if (flag == 1)
  265. {
  266. systemEdge.UpdateEndVertex(newVertex.Id);
  267. }
  268. }
  269. }
  270. #endregion
  271. }
  272. #endregion
  273. }
  274. #endregion
  275. #region 边处理
  276. /// <summary>
  277. /// 整理边
  278. /// </summary>
  279. /// <param name="graph"></param>
  280. private void ArrangeEdge(SystemGraph graph)
  281. {
  282. //有向化处理
  283. DirectedEdge(graph);
  284. //DirectedEdge2(graph);
  285. graph.IsDirection = true;
  286. //串并联处理
  287. //EdgesArrayGraphUtil.GplotAnalyse(graph);
  288. }
  289. /// <summary>
  290. /// 确定流向
  291. /// </summary>
  292. /// <param name="graph"></param>
  293. private void DirectedEdge(SystemGraph graph)
  294. {
  295. #region 加载边的系统信息
  296. var originEdges = graph.Edges.Where(e => !e.Children.Any()).ToList();
  297. foreach (var originEdge in originEdges)
  298. {
  299. var refElements = originEdge.Data;
  300. //获取边系统类型
  301. originEdge.SystemName = (refElements.FirstOrDefault(e => e is MEPCurve) as MEPCurve)?.GetSystemTypeName();
  302. //根据系统类型和特殊设备确定旁通和补水;未完,待续
  303. var systemItem = Setting.RelationTypeShell.GetFirstMatchSystem(originEdge.SystemName);
  304. if (systemItem != null)
  305. {
  306. originEdge.EdgeCategory = systemItem.ContainEdgeTypes.FirstOrDefault();
  307. originEdge.FlowType = systemItem.FlowType == FlowType.In ? 2 : 1;
  308. }
  309. }
  310. #endregion
  311. #region 描述
  312. /*
  313. * 1、查找遍历起点
  314. * 2、根据起点遍历所有的节点,并调整节点的顺序
  315. */
  316. #endregion
  317. #region 获取定义端点
  318. var vertexes = graph.GetBootVertexs().Where(v => SystemCalcUtil.IsStartValveName(v.GetEquipment()?.Name)).ToList();
  319. if (!vertexes.Any())
  320. return;
  321. foreach (var systemVertex in vertexes)
  322. {
  323. var tempEdges = graph.GetInEdges(systemVertex.Id);
  324. if (tempEdges.Any())
  325. {
  326. var item = systemVertex.GetEquipment();
  327. if (item == null)
  328. {
  329. continue;
  330. }
  331. if (tempEdges.Any(e => e.FlowType == 2))
  332. {
  333. item.Name = "出口" + item.Id;
  334. }
  335. else
  336. {
  337. item.Name = "入口" + item.Id;
  338. }
  339. }
  340. }
  341. #endregion
  342. #region 确定开始点
  343. List<string> edgeIds = new List<string>();
  344. List<string> vertexIds = new List<string>();
  345. foreach (var systemVertex in vertexes)
  346. {
  347. if (vertexIds.Contains(systemVertex.Id))
  348. {
  349. continue;
  350. }
  351. bool isStart = true;
  352. var currentVertexName = systemVertex.GetEquipment().Name;
  353. if (string.IsNullOrWhiteSpace(currentVertexName))
  354. {
  355. continue;
  356. }
  357. var useFlowType = 0;
  358. if (currentVertexName.Contains("入口"))
  359. {
  360. useFlowType = 1;
  361. isStart = true;
  362. }
  363. else if(currentVertexName.Contains("出口"))
  364. {
  365. useFlowType = 2;
  366. isStart = false;
  367. }
  368. else
  369. {
  370. continue;
  371. }
  372. Queue<SystemVertex> queueVertexes = new Queue<SystemVertex>();
  373. queueVertexes.Enqueue(systemVertex);
  374. while (queueVertexes.Any())
  375. {
  376. var currentVertex = queueVertexes.Dequeue();
  377. if (vertexIds.Contains(currentVertex.Id))
  378. {
  379. continue;
  380. }
  381. vertexIds.Add(currentVertex.Id);
  382. var edges = graph.GetInEdges(currentVertex.Id);
  383. foreach (var systemEdge in edges)
  384. {
  385. if (systemEdge.FlowType != useFlowType)
  386. {
  387. continue;
  388. }
  389. if (edgeIds.Contains(systemEdge.Id))
  390. {
  391. continue;
  392. }
  393. edgeIds.Add(systemEdge.Id);
  394. if ((isStart && systemEdge.ContainVertex(currentVertex.Id) == 1) || (!isStart && systemEdge.ContainVertex(currentVertex.Id) == 0))
  395. {
  396. systemEdge.Reverse();
  397. }
  398. var otherId = systemEdge.GetAnotherVertex(currentVertex.Id);
  399. if (!vertexIds.Contains(otherId))
  400. {
  401. var nextVertex = graph.FindVertex(otherId);
  402. if (nextVertex != null)
  403. {
  404. queueVertexes.Enqueue(nextVertex);
  405. }
  406. }
  407. }
  408. }
  409. }
  410. #endregion
  411. }
  412. /// <summary>
  413. /// 确定流向,
  414. /// </summary>
  415. /// <param name="graph"></param>
  416. private void DirectedEdge2(SystemGraph graph)
  417. {
  418. #region 加载边的系统信息
  419. var originEdges = graph.Edges.Where(e => !e.Children.Any()).ToList();
  420. foreach (var originEdge in originEdges)
  421. {
  422. var refElements = originEdge.Data;
  423. //获取边系统类型
  424. originEdge.SystemName = (refElements.FirstOrDefault(e => e is MEPCurve) as MEPCurve)?.GetSystemTypeName();
  425. //根据系统类型和特殊设备确定旁通和补水;未完,待续
  426. var systemItem = Setting.RelationTypeShell.GetFirstMatchSystem(originEdge.SystemName);
  427. if (systemItem != null)
  428. {
  429. originEdge.EdgeCategory = systemItem.ContainEdgeTypes.FirstOrDefault();
  430. originEdge.FlowType = systemItem.FlowType == FlowType.In ? 2 : 1;
  431. }
  432. }
  433. #endregion
  434. #region 描述
  435. /*
  436. * 1、查找遍历起点
  437. * 2、根据起点遍历所有的节点,并调整节点的顺序
  438. */
  439. #endregion
  440. #region 获取定义端点
  441. Document refDocument = null;
  442. foreach (var vertex in graph.Vertexes)
  443. {
  444. if (vertex.Data == null)
  445. continue;
  446. refDocument = vertex.Data.FirstOrDefault()?.Document;
  447. if (refDocument != null)
  448. break;
  449. }
  450. if (refDocument == null)
  451. return;
  452. //获取开始的category
  453. //如果没有设定开始点,则使用立管作为开始点
  454. List<SystemVertex> vertexes = new List<SystemVertex>();
  455. List<string> startCategories = GplotSystemCheckManager.GetSourceCategories(refDocument,Setting.RelationTypeShell.RelationItem.Type);
  456. if (startCategories.Any())
  457. {
  458. vertexes = graph.GetBootVertexs().Where(v => startCategories.Contains(MBIInfoUtil.GetEquipmentCategory(v.GetEquipment()?.Name) ?? string.Empty)).ToList();
  459. }
  460. else
  461. {
  462. vertexes = graph.GetBootVertexs().Where(v => v.GetEquipment()!=null&&v.GetEquipment().ElementType==ElementType.VerticalPipe).ToList();
  463. }
  464. if (!vertexes.Any())
  465. return;
  466. #endregion
  467. #region 确定开始点
  468. List<string> edgeIds = new List<string>();
  469. List<string> vertexIds = new List<string>();
  470. for (int i = 0; i < vertexes.Count; i++)
  471. {
  472. var currentVertex = vertexes[i];
  473. if (vertexIds.Contains(currentVertex.Id))
  474. {
  475. continue;
  476. }
  477. vertexIds.Add(currentVertex.Id);
  478. var edges = graph.GetInEdges(currentVertex.Id);
  479. foreach (var systemEdge in edges)
  480. {
  481. if (systemEdge.FlowType > 2)
  482. {
  483. continue;
  484. }
  485. if (edgeIds.Contains(systemEdge.Id))
  486. {
  487. continue;
  488. }
  489. edgeIds.Add(systemEdge.Id);
  490. if ((systemEdge.FlowType==2&&systemEdge.ContainVertex(currentVertex.Id) == 1)|| (systemEdge.FlowType == 1 && systemEdge.ContainVertex(currentVertex.Id) == 0))
  491. {
  492. systemEdge.Reverse();
  493. }
  494. var otherId = systemEdge.GetAnotherVertex(currentVertex.Id);
  495. if (!vertexIds.Contains(otherId))
  496. {
  497. var nextVertex = graph.FindVertex(otherId);
  498. if (nextVertex != null)
  499. {
  500. vertexes.Add(nextVertex);
  501. }
  502. }
  503. }
  504. }
  505. #endregion
  506. }
  507. #endregion
  508. #endregion
  509. }
  510. }