ElectricalUtils.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*-------------------------------------------------------------------------
  2. * 功能描述:ElectricalUtils
  3. * 作者:xulisong
  4. * 创建时间: 2019/8/4 10:57:29
  5. * 版本号:v1.0
  6. * -------------------------------------------------------------------------*/
  7. using Autodesk.Revit.DB;
  8. using Autodesk.Revit.DB.Electrical;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. namespace FWindSoft.Revit.Utils
  15. {
  16. /// <summary>
  17. /// 电气工具类
  18. /// </summary>
  19. public static class ElectricalUtils
  20. {
  21. /// <summary>
  22. /// 使用指定点打断管线
  23. /// </summary>
  24. /// <param name="document"></param>
  25. /// <param name="cableTrayConduitBaseId"></param>
  26. /// <param name="ptBreak"></param>
  27. /// <returns></returns>
  28. public static ElementId BreakCurve(Document document, ElementId cableTrayConduitBaseId, XYZ ptBreak)
  29. {
  30. #region 判断给定点的位置
  31. var cableTrayConduitBase = document.GetElement(cableTrayConduitBaseId) as CableTrayConduitBase;
  32. if (cableTrayConduitBase == null)
  33. {
  34. return ElementId.InvalidElementId;
  35. }
  36. var location = ((cableTrayConduitBase.Location as LocationCurve).Curve as Line).Clone() as Line;
  37. var direction = location.Direction.Normalize();
  38. var useVector = ptBreak - location.GetEndPoint(0);
  39. var dotValue = useVector.DotProduct(direction);
  40. if (dotValue <= 0 || dotValue >= location.Length)
  41. {
  42. //分割点不在迹线上
  43. return ElementId.InvalidElementId;
  44. }
  45. var realBreak = location.GetEndPoint(0) + dotValue * direction;
  46. #endregion
  47. #region 获取原始管道的连接信息
  48. List<Connector> nearStartConnectors = new List<Connector>();
  49. List<Connector> nearEndConnectors = new List<Connector>();
  50. foreach (Connector connector in cableTrayConduitBase.ConnectorManager.Connectors)
  51. {
  52. //没有连接,则不进行统计
  53. if (connector == null || !connector.IsConnected)
  54. continue;
  55. var origin = connector.Origin;
  56. var tempVector = origin - realBreak;
  57. var tempDotValue = tempVector.DotProduct(direction);
  58. if (tempDotValue <= 0)
  59. {
  60. nearStartConnectors.Add(connector);
  61. }
  62. else
  63. {
  64. //点乘值大于0,则在靠近管线结束点的位置
  65. nearEndConnectors.Add(connector);
  66. }
  67. }
  68. #endregion
  69. #region 复制管线,调整朝向
  70. var newId = ElementTransformUtils.CopyElement(document, cableTrayConduitBaseId, XYZ.Zero).FirstOrDefault();
  71. var newCableTrayConduitBase = document.GetElement(newId) as CableTrayConduitBase;
  72. if (newCableTrayConduitBase is CableTray cableTray)
  73. {
  74. //处理朝向
  75. cableTray.CurveNormal = (cableTrayConduitBase as CableTray).CurveNormal;
  76. }
  77. #endregion
  78. #region 确定保留区域,删除区域
  79. var nearStarTupleInfo = nearStartConnectors.Select(c => new Tuple<Connector, Connector>(c, GetRefConnector(c))).ToList();
  80. var nearEndTupleInfo = nearEndConnectors.Select(c => new Tuple<Connector, Connector>(c, GetRefConnector(c))).ToList();
  81. //当两个Conector相等时,必然是end连接End
  82. var nearStartWeight = nearStarTupleInfo.Sum(tuple => tuple.Item1.ConnectorType == tuple.Item2.ConnectorType ? 1 : 2);
  83. var nearEndWeight = nearEndTupleInfo.Sum(tuple => tuple.Item1.ConnectorType == tuple.Item2.ConnectorType ? 1 : 2);
  84. List<Tuple<Connector, Connector>> needResetConnectors = null;
  85. CableTrayConduitBase start = null,end=null;
  86. if (nearStartWeight> nearEndWeight)
  87. {
  88. //保留靠近Start的部分,因为这样对整个模型改动比较小
  89. needResetConnectors = nearEndTupleInfo;
  90. start = cableTrayConduitBase;
  91. end = newCableTrayConduitBase;
  92. }
  93. else
  94. {
  95. needResetConnectors = nearStarTupleInfo;
  96. start = newCableTrayConduitBase ;
  97. end = cableTrayConduitBase;
  98. }
  99. List<ConnectorJoinItem> joinItems = new List<ConnectorJoinItem>();
  100. foreach (var connectorTuple in needResetConnectors)
  101. {
  102. //断开连接后,Curve就不起作用了
  103. var baseConnector = connectorTuple.Item1;
  104. var refConnector = connectorTuple.Item2;
  105. ConnectorJoinItem joinItem = new ConnectorJoinItem(newCableTrayConduitBase, baseConnector.Origin);
  106. #region 确定连接类型
  107. if (baseConnector.ConnectorType == ConnectorType.End)
  108. {
  109. joinItem.JoinType = refConnector.ConnectorType == ConnectorType.Curve ? ConnectorJoinType.EndToCurve : ConnectorJoinType.EndToEnd;
  110. }
  111. else if (baseConnector.ConnectorType == ConnectorType.Curve)
  112. {
  113. joinItem.JoinType = ConnectorJoinType.CurveToEnd;
  114. }
  115. #endregion
  116. #region 确定RefConnector
  117. if(refConnector.ConnectorType==ConnectorType.End)
  118. {
  119. joinItem.RefConnector = refConnector;
  120. }
  121. if(refConnector.ConnectorType == ConnectorType.Curve)
  122. {
  123. joinItem.RefConnector = ConnectorJoinItem.GetFarnessEndConnector(refConnector.Owner as MEPCurve,refConnector.Origin);
  124. }
  125. #endregion
  126. joinItems.Add(joinItem);
  127. connectorTuple.Item1.DisconnectFrom(connectorTuple.Item2);
  128. }
  129. (start.Location as LocationCurve).Curve = Line.CreateBound(location.GetEndPoint(0), realBreak);
  130. (end.Location as LocationCurve).Curve = Line.CreateBound(realBreak, location.GetEndPoint(1));
  131. #endregion
  132. #region 恢复新创建管线所在位置的连接
  133. //document.Regenerate();
  134. joinItems.ForEach(c => c.Connect());
  135. #endregion
  136. return newCableTrayConduitBase?.Id;
  137. }
  138. #region 内部方法和类型
  139. /// <summary>
  140. /// 获取关联的Connector
  141. /// </summary>
  142. /// <param name="connector"></param>
  143. /// <returns></returns>
  144. private static Connector GetRefConnector(Connector connector)
  145. {
  146. if (!connector.IsConnected)
  147. {
  148. return null;
  149. }
  150. foreach (Connector refConnector in connector.AllRefs)
  151. {
  152. if (refConnector.Owner.Id != connector.Owner.Id)
  153. {
  154. return refConnector;
  155. }
  156. }
  157. return null;
  158. }
  159. /// <summary>
  160. /// Connector连接数据
  161. /// </summary>
  162. private class ConnectorJoinItem
  163. {
  164. public ConnectorJoinItem(MEPCurve baseCurve, XYZ basePoint)
  165. {
  166. BaseMepCurve = baseCurve;
  167. BasePoint = basePoint;
  168. }
  169. /// <summary>
  170. /// Connector连接类型
  171. /// </summary>
  172. public ConnectorJoinType JoinType { get; set; }
  173. /// <summary>
  174. /// 关联的Connector
  175. /// </summary>
  176. public Connector RefConnector { get; set; }
  177. /// <summary>
  178. /// 基础连接管线
  179. /// </summary>
  180. public MEPCurve BaseMepCurve { get; private set; }
  181. /// <summary>
  182. /// 基础的位置
  183. /// </summary>
  184. public XYZ BasePoint { get; private set; }
  185. /// <summary>
  186. /// 执行连接功能
  187. /// </summary>
  188. public void Connect()
  189. {
  190. if (RefConnector == null)
  191. {
  192. return;
  193. }
  194. Connector baseConnector = null;
  195. switch (JoinType)
  196. {
  197. case ConnectorJoinType.EndToEnd:
  198. baseConnector = GetNearnessEndConnector(BaseMepCurve, BasePoint);
  199. baseConnector.ConnectTo(RefConnector);
  200. break;
  201. case ConnectorJoinType.EndToCurve:
  202. baseConnector = GetNearnessEndConnector(BaseMepCurve, BasePoint);
  203. baseConnector.Owner.Document.Create.NewTeeFitting(RefConnector, RefConnector, baseConnector);
  204. break;
  205. case ConnectorJoinType.CurveToEnd:
  206. baseConnector = GetFarnessEndConnector(BaseMepCurve, BasePoint);
  207. baseConnector.Owner.Document.Create.NewTeeFitting(baseConnector, baseConnector, RefConnector);
  208. break;
  209. }
  210. }
  211. /// <summary>
  212. /// 获取mepCurve上距离指定location最远的end类型Connector
  213. /// </summary>
  214. /// <param name="mepCurve"></param>
  215. /// <param name="point"></param>
  216. /// <returns></returns>
  217. public static Connector GetFarnessEndConnector(MEPCurve mepCurve, XYZ point)
  218. {
  219. Connector useConnector = null;
  220. if (mepCurve == null)
  221. {
  222. return useConnector;
  223. }
  224. double maxDistance = -1d;
  225. foreach (Connector connector in mepCurve.ConnectorManager.Connectors)
  226. {
  227. if (connector == null || connector.ConnectorType != ConnectorType.End)
  228. continue;
  229. var origin = connector.Origin;
  230. var tempDistance = (origin - point).GetLength();
  231. if (tempDistance > maxDistance)
  232. {
  233. maxDistance = tempDistance;
  234. useConnector = connector;
  235. }
  236. }
  237. return useConnector;
  238. }
  239. /// <summary>
  240. /// 获取mepCurve上距离指定location最近的end类型Connector
  241. /// </summary>
  242. /// <param name="mepCurve"></param>
  243. /// <param name="point"></param>
  244. /// <returns></returns>
  245. public static Connector GetNearnessEndConnector(MEPCurve mepCurve, XYZ point)
  246. {
  247. Connector useConnector = null;
  248. if (mepCurve == null)
  249. {
  250. return useConnector;
  251. }
  252. double minDistance = double.MaxValue;
  253. foreach (Connector connector in mepCurve.ConnectorManager.Connectors)
  254. {
  255. if (connector == null || connector.ConnectorType != ConnectorType.End)
  256. continue;
  257. var origin = connector.Origin;
  258. var tempDistance = (origin - point).GetLength();
  259. if (tempDistance < minDistance)
  260. {
  261. minDistance = tempDistance;
  262. useConnector = connector;
  263. }
  264. }
  265. return useConnector;
  266. }
  267. }
  268. private enum ConnectorJoinType
  269. {
  270. /// <summary>
  271. /// 点对点连接
  272. /// </summary>
  273. EndToEnd,
  274. /// <summary>
  275. /// 点对线连接
  276. /// </summary>
  277. EndToCurve,
  278. /// <summary>
  279. /// 线对点连接
  280. /// </summary>
  281. CurveToEnd,
  282. }
  283. #endregion
  284. }
  285. }