JoinConduits.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. using Autodesk.Revit.DB;
  2. using Autodesk.Revit.DB.Electrical;
  3. using FWindSoft.SystemExtensions;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace FWindSoft.Revit.Mep
  10. {
  11. /*
  12. * 连接相关的相代码
  13. */
  14. /// <summary>
  15. /// 连接管道基础类
  16. /// </summary>
  17. public abstract class BaseJoinConduit : IJoinCurve
  18. {
  19. /// <summary>
  20. /// 连接管线
  21. /// </summary>
  22. /// <param name="elements"></param>
  23. /// <param name="context"></param>
  24. /// <returns></returns>
  25. protected abstract bool JoinImpl(List<JoinElementWraper> elements, JoinContext context);
  26. /// <summary>
  27. /// 连接管线
  28. /// </summary>
  29. /// <param name="elements"></param>
  30. /// <param name="context"></param>
  31. public bool Join(List<JoinElementWraper> elements, JoinContext context)
  32. {
  33. if (elements.Any(ew => !(ew.AssociateElement is Conduit)))
  34. {
  35. return false;
  36. }
  37. return JoinImpl(elements, context);
  38. }
  39. }
  40. #region 两个管道进行连接
  41. public class Join2Conduit : BaseJoinConduit
  42. {
  43. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  44. {
  45. if (elements == null || elements.Count < 2)
  46. {
  47. return false;
  48. }
  49. var conduit1 = elements[0].AssociateElement as Conduit;
  50. var conduit2 = elements[1].AssociateElement as Conduit;
  51. var line1 = conduit1.GetLocationLine();
  52. var line2 = conduit2.GetLocationLine();
  53. BaseJoinConduit joinConduit;
  54. if (line1.IsCollinear(line2))
  55. {
  56. if (conduit1.Diameter.IsEqual(conduit2.Diameter))
  57. {
  58. joinConduit = new Join2ConduitByUnion();
  59. }
  60. else
  61. {
  62. joinConduit = new Join2ConduitByTransition();
  63. }
  64. }
  65. else
  66. {
  67. joinConduit = new Join2ConduitByElbow();
  68. }
  69. if (joinConduit != null)
  70. {
  71. return joinConduit.Join(elements, context);
  72. }
  73. return false;
  74. }
  75. }
  76. /// <summary>
  77. /// 使用活接头连接
  78. /// </summary>
  79. public class Join2ConduitByUnion : BaseJoinConduit
  80. {
  81. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  82. {
  83. if (elements == null || elements.Count < 2)
  84. {
  85. return false;
  86. }
  87. var conduit1 = elements[0].AssociateElement as Conduit;
  88. var conduit2 = elements[1].AssociateElement as Conduit;
  89. var line1 = conduit1.GetLocationLine();
  90. var line2 = conduit2.GetLocationLine();
  91. if (!conduit1.Diameter.IsEqual(conduit2.Diameter) || !line1.IsCollinear(line2))
  92. {
  93. return false;
  94. }
  95. //找到connector方向相反,且距离较近的一对点,创建连接
  96. var connectors = conduit1.GetAllConnectors();
  97. Connector useConnector1 = null, useConnector2 = null;
  98. double distance = double.MaxValue;
  99. foreach (Connector connector in connectors)
  100. {
  101. var refConnector = conduit2.GetConnectorByDirection(-connector.CoordinateSystem.BasisZ);
  102. if (refConnector != null)
  103. {
  104. var tempLength = connector.Origin.DistanceTo(refConnector.Origin);
  105. if (tempLength.Less(distance))
  106. {
  107. useConnector1 = connector;
  108. useConnector2 = refConnector;
  109. distance = tempLength;
  110. }
  111. }
  112. }
  113. FamilyInstance fi = null;
  114. if (useConnector1 != null && useConnector1 != null)
  115. {
  116. var line2Other = line2.GetFarnessPoint(useConnector2.Origin);
  117. if (line2Other.Subtract(useConnector1.Origin).GetLength().More(JoinConduitUtils.FaultTolerantLength))
  118. {
  119. fi = ConduitFittingCreator.NewUnionFitting(useConnector1, useConnector2, context);
  120. }
  121. }
  122. return fi != null;
  123. }
  124. }
  125. /// <summary>
  126. /// 使用变径连接
  127. /// </summary>
  128. public class Join2ConduitByTransition : BaseJoinConduit
  129. {
  130. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  131. {
  132. if (elements == null || elements.Count < 2)
  133. {
  134. return false;
  135. }
  136. var conduit1 = elements[0].AssociateElement as Conduit;
  137. var conduit2 = elements[1].AssociateElement as Conduit;
  138. var line1 = conduit1.GetLocationLine();
  139. var line2 = conduit2.GetLocationLine();
  140. if (conduit1.Diameter.IsEqual(conduit2.Diameter) || !line1.IsCollinear(line2))
  141. {
  142. return false;
  143. }
  144. //找到connector方向相反,且距离较近的一对点,创建连接
  145. var connectors = conduit1.GetAllConnectors();
  146. Connector useConnector1 = null, useConnector2 = null;
  147. double distance = double.MaxValue;
  148. foreach (Connector connector in connectors)
  149. {
  150. var refConnector = conduit2.GetConnectorByDirection(-connector.CoordinateSystem.BasisZ);
  151. if (refConnector != null)
  152. {
  153. var tempLength = connector.Origin.DistanceTo(refConnector.Origin);
  154. if (tempLength.Less(distance))
  155. {
  156. useConnector1 = connector;
  157. useConnector2 = refConnector;
  158. distance = tempLength;
  159. }
  160. }
  161. }
  162. FamilyInstance fi = null;
  163. if (useConnector1 != null && useConnector1 != null)
  164. {
  165. var line2Other = line2.GetFarnessPoint(useConnector2.Origin);
  166. if (line2Other.Subtract(useConnector1.Origin).GetLength().More(JoinConduitUtils.FaultTolerantLength))
  167. {
  168. fi = ConduitFittingCreator.NewTransitionFitting(useConnector1, useConnector2, context);
  169. }
  170. }
  171. return fi != null;
  172. }
  173. }
  174. /// <summary>
  175. /// 使用弯头连接
  176. /// </summary>
  177. public class Join2ConduitByElbow : BaseJoinConduit
  178. {
  179. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  180. {
  181. if (elements == null || elements.Count < 2)
  182. {
  183. return false;
  184. }
  185. var conduit1 = elements[0].AssociateElement as Conduit;
  186. var conduit2 = elements[1].AssociateElement as Conduit;
  187. var line1 = conduit1.GetLocationLine();
  188. var line2 = conduit2.GetLocationLine();
  189. var lineUnbound1 = line1.CloneUnbound();
  190. var lineUnbound2 = line2.CloneUnbound();
  191. var intersectPoint = lineUnbound1.GetSpatialIntersection(lineUnbound2);
  192. if (null == intersectPoint)
  193. {
  194. return false;
  195. }
  196. Connector connector1 = conduit1.GetConnectorByOrigin(line1.GetNearnessPoint(intersectPoint));
  197. Connector connector2 = conduit2.GetConnectorByOrigin(line2.GetNearnessPoint(intersectPoint));
  198. FamilyInstance fi = ConduitFittingCreator.NewElbowFitting(connector1, connector2, context);
  199. return fi != null;
  200. }
  201. }
  202. #endregion
  203. #region 三个管道进行连接
  204. /// <summary>
  205. /// 连接三个管道
  206. /// </summary>
  207. public class Join3Conduit : BaseJoinConduit
  208. {
  209. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  210. {
  211. if (elements == null || elements.Count < 3)
  212. {
  213. return false;
  214. }
  215. var conduit1 = elements[0].AssociateElement as Conduit;
  216. var conduit2 = elements[1].AssociateElement as Conduit;
  217. var conduit3 = elements[2].AssociateElement as Conduit;
  218. var line1 = conduit1.GetLocationLine();
  219. var line2 = conduit2.GetLocationLine();
  220. var line3 = conduit3.GetLocationLine();
  221. #region 算法流程
  222. /*
  223. * 取到conduit使用的三通。
  224. * 在交点位置放置三通,顶面Connector朝下。
  225. * 旋转到相应的位置,将匹配的Connector进行连接
  226. * 匹配Connector未能按默认连接,进行特殊处理?
  227. *
  228. * 尽量保证线盒横放。如果位置关系不允许横放,再考虑其他摆放
  229. * 分类:两两垂直;一个与其中一个平行,与另一个垂直
  230. */
  231. #endregion
  232. //正常情况下,一条线,必然和其余两条线存在不平行的情况
  233. XYZ ins = null;
  234. if (!line1.IsParallel(line2))
  235. {
  236. ins = line1.GetSpatialIntersection(line2);
  237. }
  238. else if (!line1.IsParallel(line3))
  239. {
  240. ins = line1.GetSpatialIntersection(line3);
  241. }
  242. if (ins != null)
  243. {
  244. var fi = ConduitFittingCreator.NewTeeFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), context);
  245. return fi != null;
  246. }
  247. return false;
  248. }
  249. }
  250. #endregion
  251. #region 四个管道进行连接
  252. /// <summary>
  253. /// 连接四个管道
  254. /// </summary>
  255. public class Join4Conduit : BaseJoinConduit
  256. {
  257. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  258. {
  259. if (elements == null || elements.Count < 3)
  260. {
  261. return false;
  262. }
  263. var conduit1 = elements[0].AssociateElement as Conduit;
  264. var conduit2 = elements[1].AssociateElement as Conduit;
  265. var conduit3 = elements[2].AssociateElement as Conduit;
  266. var conduit4 = elements[3].AssociateElement as Conduit;
  267. var line1 = conduit1.GetLocationLine();
  268. var line2 = conduit2.GetLocationLine();
  269. var line3 = conduit3.GetLocationLine();
  270. var line4 = conduit4.GetLocationLine();
  271. //正常情况下,一条线,必然和其余两条线存在不平行的情况
  272. XYZ ins = null;
  273. if (!line1.IsParallel(line2))
  274. {
  275. ins = line1.GetSpatialIntersection(line2);
  276. }
  277. else if (!line1.IsParallel(line3))
  278. {
  279. ins = line1.GetSpatialIntersection(line3);
  280. }
  281. if (ins != null)
  282. {
  283. var fi = ConduitFittingCreator.NewCrossFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), conduit4.GetNearnessConnector(ins), context);
  284. return fi != null;
  285. }
  286. return false;
  287. }
  288. }
  289. #endregion
  290. #region 五个个管道进行连接
  291. /// <summary>
  292. /// 连接五个管道
  293. /// </summary>
  294. public class Join5Conduit : BaseJoinConduit
  295. {
  296. protected override bool JoinImpl(List<JoinElementWraper> elements, JoinContext context)
  297. {
  298. if (elements == null || elements.Count < 3)
  299. {
  300. return false;
  301. }
  302. var conduit1 = elements[0].AssociateElement as Conduit;
  303. var conduit2 = elements[1].AssociateElement as Conduit;
  304. var conduit3 = elements[2].AssociateElement as Conduit;
  305. var conduit4 = elements[3].AssociateElement as Conduit;
  306. var conduit5 = elements[4].AssociateElement as Conduit;
  307. var line1 = conduit1.GetLocationLine();
  308. var line2 = conduit2.GetLocationLine();
  309. var line3 = conduit3.GetLocationLine();
  310. var line4 = conduit4.GetLocationLine();
  311. var line5 = conduit5.GetLocationLine();
  312. //正常情况下,一条线,必然和其余两条线存在不平行的情况
  313. XYZ ins = null;
  314. if (!line1.IsParallel(line2))
  315. {
  316. ins = line1.GetSpatialIntersection(line2);
  317. }
  318. else if (!line1.IsParallel(line3))
  319. {
  320. ins = line1.GetSpatialIntersection(line3);
  321. }
  322. if (ins != null)
  323. {
  324. var fi = ConduitFittingCreator.NewFiveLinksFitting(conduit1.GetNearnessConnector(ins), conduit2.GetNearnessConnector(ins), conduit3.GetNearnessConnector(ins), conduit4.GetNearnessConnector(ins), conduit5.GetNearnessConnector(ins), context);
  325. return fi != null;
  326. }
  327. return false;
  328. }
  329. }
  330. #endregion
  331. }