ElementRangeCheck.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* ==============================================================================
  2. * 功能描述:SagaCheck
  3. * 创 建 者:Garrett
  4. * 创建日期:2019/6/11 16:09:09
  5. * ==============================================================================*/
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Linq;
  10. using System.Text.RegularExpressions;
  11. using Autodesk.Revit.DB;
  12. using Autodesk.Revit.DB.Mechanical;
  13. using SAGA.DotNetUtils.Extend;
  14. using SAGA.RevitUtils.Extends;
  15. using ServiceRevitLib.Common;
  16. using ServiceRevitLib.Extend;
  17. using ServiceRevitLib.Mode;
  18. namespace ServiceRevitLib.DataCheck.Mode
  19. {
  20. /// <summary>
  21. /// SagaCheck
  22. /// </summary>
  23. class ElementRangeCheck : CheckBase
  24. {
  25. #region 序列化属性
  26. private double m_Redundant = 500;
  27. /// <summary>
  28. /// 高度冗余
  29. /// </summary>
  30. public double Redundant
  31. {
  32. get { return m_Redundant; }
  33. set { m_Redundant = value; }
  34. }
  35. private double m_baseLevel;
  36. /// <summary>
  37. /// 底部标高
  38. /// </summary>
  39. public double BaseLevel
  40. {
  41. get { return m_baseLevel; }
  42. }
  43. private List<double> m_topLevels = new List<double>();
  44. /// <summary>
  45. /// 顶部标高(夹层可能涉及多个顶)
  46. /// </summary>
  47. public string TopLevels
  48. {
  49. get { return string.Join(";", m_topLevels); }
  50. }
  51. #endregion
  52. public override void Check()
  53. {
  54. try
  55. {
  56. base.Check();
  57. #region
  58. var document = m_Doc;
  59. if (!SetFloorBaseTopRange()) return;
  60. var elements = document.GetAllElements();
  61. foreach (var element in elements)
  62. {
  63. var result = GetCheckResult(element);
  64. if (result != null)
  65. Content.Add(result);
  66. }
  67. #endregion
  68. }
  69. catch (Exception e)
  70. {
  71. Result = ResultState.Failure;
  72. ResultMsg = $"{e.Message}\r\n{e.StackTrace}";
  73. }
  74. }
  75. /// <summary>
  76. /// 设置当前楼层底部和顶部范围
  77. /// </summary>
  78. /// <param name="doc"></param>
  79. /// <param name="result"></param>
  80. private bool SetFloorBaseTopRange()
  81. {
  82. bool rt = true;
  83. var document = m_Doc;
  84. try
  85. {
  86. var sagaPlans = document.GetElements<ViewPlan>()
  87. .Where(t => t.ViewType == ViewType.FloorPlan && t.Name.Contains("-saga")).ToList();
  88. var curFloor = sagaPlans.FirstOrDefault();
  89. if (sagaPlans.Count != 1 || curFloor == null)
  90. {
  91. Result = ResultState.Failure;
  92. ResultMsg = "Saga标记不合法,请修正后再进行检查";
  93. return false;
  94. }
  95. //设置楼层底部高度
  96. m_baseLevel = curFloor.GenLevel.Elevation.FromApi().Round(2);
  97. //设置楼层顶部高度
  98. var levels = m_Doc.GetLevels();
  99. var mbiLevels = levels.Where(t => Regex.IsMatch(t.Name, $"{RegexConstPattern.IsMBILevel}") && t.Elevation.IsThan(m_baseLevel)).ToList();
  100. foreach (Level level in mbiLevels)
  101. {
  102. m_topLevels.Add(level.Elevation.FromApi().Round(2));
  103. if (!Regex.IsMatch(level.Name, $"{RegexConstPattern.IsSandwich}"))
  104. {
  105. break;
  106. }
  107. }
  108. //当前层为屋顶或屋顶夹层时,顶部限制设置为正无穷
  109. if (Regex.IsMatch(curFloor.GenLevel.Name, $"{RegexConstPattern.IsRF}|{RegexConstPattern.IsRFM}"))
  110. {
  111. m_topLevels.Add(double.MaxValue);
  112. }
  113. }
  114. catch (Exception e)
  115. {
  116. Console.WriteLine(e);
  117. rt = false;
  118. }
  119. return rt;
  120. }
  121. /// <summary>
  122. /// 获取检测结果
  123. /// </summary>
  124. /// <param name="element"></param>
  125. /// <returns></returns>
  126. private ElementRangeCheckResult GetCheckResult(Element element)
  127. {
  128. var result = new ElementRangeCheckResult();
  129. result.Id = element.Id.ToString();
  130. result.FamilyName = element.GetFamilyName();
  131. try
  132. {
  133. double zb = 0, zt = 0;
  134. bool rb = false, rt = false;
  135. //需要识别判定的构件
  136. DCElementType type = DCElementType.None;
  137. bool isBoxInst = false;
  138. if (element is Wall wall)
  139. {
  140. isBoxInst = true;
  141. zb = wall.GetBaseStaticHeight();
  142. zt = wall.GetTopStaticHeight();
  143. type = DCElementType.Wall;
  144. }
  145. else if (element.IsSpace())
  146. {
  147. var space = element as Space;
  148. isBoxInst = true;
  149. zb = space.GetBaseStaticHeight();
  150. zt = space.GetTopStaticHeight();
  151. type = DCElementType.Space;
  152. }
  153. else if (element is FamilyInstance)
  154. {
  155. if (element.IsAllColumn())
  156. {
  157. var fi = element as FamilyInstance;
  158. isBoxInst = true;
  159. zb = fi.GetBaseStaticHeight();
  160. zt = fi.GetTopStaticHeight();
  161. type = DCElementType.Column;
  162. }
  163. else if (element.IsEquipment() || element.IsEquipmentPart() || element.IsBeacon())
  164. {
  165. zb = element.GetLocationPointMBIXYZ().Z;
  166. type = GetRType(element);
  167. }
  168. }
  169. if (type==DCElementType.None) return null;
  170. //冗余,使用时,统一使用单位mm
  171. double w = Redundant;
  172. zb = zb.FromApi().Round(2);
  173. zt = zt.FromApi().Round(2);
  174. //构件类型
  175. result.Type = type.GetDescription();
  176. if (isBoxInst)
  177. {
  178. rb = zb.IsBetween(m_baseLevel - w, m_baseLevel);
  179. rt = m_topLevels.Any(t => zt.IsBetween(t - w, t));
  180. string ttip = rb ? "" : "底部";
  181. string ttop = rt ? "" : rb ? "和顶部" : "顶部";
  182. result.HeightRange = $"{zb},{zt}";
  183. result.Result = (rb && rt)?ResultState.Success:ResultState.Failure;
  184. result.ResultMsg = rb && rt ? "" : $"构件范围不满足要求;请检查构件{ttip}{ttop}";
  185. }
  186. else
  187. {
  188. rb = m_topLevels.Any(t => zb.IsBetween(m_baseLevel, t));
  189. result.HeightRange = $"{zb}";
  190. result.Result = (rb) ? ResultState.Success : ResultState.Failure;
  191. result.ResultMsg = rb? "" : $"构件范围不满足要求;请检查构件位置";
  192. }
  193. }
  194. catch (Exception e)
  195. {
  196. result.Result = ResultState.Failure;
  197. result.ResultMsg = "构件范围检查异常";
  198. }
  199. return result;
  200. }
  201. /// <summary>
  202. /// 获取构件类型
  203. /// </summary>
  204. /// <param name="fi"></param>
  205. /// <returns></returns>
  206. private DCElementType GetRType(Element fi)
  207. {
  208. DCElementType name = DCElementType.None;
  209. if (fi.IsEquipment())
  210. {
  211. name = DCElementType.Equipment;
  212. }
  213. else if (fi.IsEquipmentPart())
  214. {
  215. name = DCElementType.EuipmentPart;
  216. }
  217. else if (fi.IsBeacon())
  218. {
  219. name = DCElementType.Beacon;
  220. }
  221. return name;
  222. }
  223. /// <summary>
  224. /// DCElementType
  225. /// </summary>
  226. public enum DCElementType
  227. {
  228. [Description("未知")]
  229. None,
  230. [Description("墙")]
  231. Wall,
  232. [Description("柱")]
  233. Column,
  234. [Description("空间")]
  235. Space,
  236. [Description("设备")]
  237. Equipment,
  238. [Description("部件")]
  239. EuipmentPart,
  240. [Description("信标")]
  241. Beacon
  242. }
  243. }
  244. }