SpaceManager.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*-------------------------------------------------------------------------
  2. * 功能描述:SpaceManager
  3. * 作者:xulisong
  4. * 创建时间: 2018/12/14 10:11:22
  5. * 版本号:v1.0
  6. * -------------------------------------------------------------------------*/
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. using System.Threading.Tasks;
  13. using Autodesk.Revit.DB;
  14. using Autodesk.Revit.DB.Architecture;
  15. using SAGA.DotNetUtils;
  16. using SAGA.MBI.Common;
  17. using SAGA.MBI.Model;
  18. using SAGA.MBI.WinView.Space;
  19. using SAGA.RevitUtils;
  20. using SAGA.RevitUtils.Extends;
  21. using RSpace=Autodesk.Revit.DB.Mechanical.Space;
  22. namespace SAGA.MBI.WinView
  23. {
  24. /// <summary>
  25. /// 元空间管理相关模操作
  26. /// </summary>
  27. public class SpaceManager
  28. {
  29. public const string NewCreateSpaceFlag = "不保留已有空间,创建新空间";
  30. public static bool IsNewSpaceFlag(ServerSpace space)
  31. {
  32. return space?.Name == NewCreateSpaceFlag;
  33. }
  34. /// <summary>
  35. /// 获取元素Id
  36. /// </summary>
  37. /// <param name="space"></param>
  38. /// <returns></returns>
  39. public static string GetElementId(MISpace space)
  40. {
  41. return space.BimID.Split(':')[1];
  42. }
  43. /// <summary>
  44. /// 更新项目中的空间分割
  45. /// </summary>
  46. /// <param name="doc"></param>
  47. /// <param name="separations"></param>
  48. /// <param name="deletedIds"></param>
  49. public static void UpdateSpaceSequaration(Document doc,List<SpaceSeparation> separations,List<int> deletedIds)
  50. {
  51. using (Transaction trans = new Transaction(doc, "更新空间分隔符"))
  52. {
  53. trans.Start();
  54. try
  55. {
  56. FailureHandlingOptions fho = trans.GetFailureHandlingOptions();
  57. //警告不提示,但不捕获冲突空间
  58. fho.SetFailuresPreprocessor(new SpaceFailuresPreprocessor());
  59. trans.SetFailureHandlingOptions(fho);
  60. //读取空间所在视图
  61. var view = doc.GetUseView();
  62. if (view == null)
  63. {
  64. MessageShow.Infomation("无法找到-saga标志的视图");
  65. return;
  66. }
  67. //创建空间分隔符
  68. CreateSpaceSeparation(view, separations);
  69. doc.Delete(deletedIds.Select(id => new ElementId(id)).ToList());
  70. trans.Commit();
  71. }
  72. catch (Exception e)
  73. {
  74. trans.RollBack();
  75. }
  76. }
  77. }
  78. /// <summary>
  79. /// 创建空间分隔符
  80. /// </summary>
  81. /// <param name="view"></param>
  82. /// <param name="separations"></param>
  83. public static void CreateSpaceSeparation(ViewPlan view, List<SpaceSeparation> separations)
  84. {
  85. if (view == null)
  86. return;
  87. double z = view.GenLevel.Elevation;
  88. Document doc = view.Document;
  89. Plane p =Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
  90. var sp = SketchPlane.Create(doc, p);
  91. foreach (var pair in separations)
  92. {
  93. XYZ start = pair.Start.NewZ(z);
  94. XYZ end = pair.End.NewZ(z);
  95. Line line = null;
  96. try
  97. {
  98. line = start.NewLine(end);
  99. }
  100. catch (Exception e)
  101. {
  102. Console.WriteLine(e.StackTrace);
  103. }
  104. if (line != null)
  105. {
  106. var curveArray = new CurveArray();
  107. curveArray.Append(line);
  108. var newLIneId = doc.Create.NewSpaceBoundaryLines(sp, curveArray, view).get_Item(0).Id;
  109. pair.Id = newLIneId.IntegerValue;
  110. }
  111. }
  112. }
  113. /// <summary>
  114. /// 手动创建空间
  115. /// </summary>
  116. /// <param name="doc"></param>
  117. public static void CreateSpace(Document doc)
  118. {
  119. doc.LoadFamilySymbolExt(MBIConst.SpaceTagFamilyFilePath);
  120. var view = doc.GetUseView();
  121. if (view != null)
  122. {
  123. var level = view.GenLevel;
  124. var phase = view.GetUsePhase();
  125. PhaseUtil.ValidateUsePhase(phase);
  126. #region 创建新的节点
  127. List<XYZ> points = new List<XYZ>();
  128. using (SubTransaction sub = new SubTransaction(doc))
  129. {
  130. //把所有的空间分割转换成房间分割,然后获取封闭区域
  131. try
  132. {
  133. sub.Start();
  134. var virWalls = doc.FilterElements<CurveElement>((line) =>
  135. {
  136. var categoryId = line.Category.Id.IntegerValue;
  137. return categoryId == (int) BuiltInCategory.OST_MEPSpaceSeparationLines && line is ModelLine;
  138. }).OfType<ModelLine>();
  139. CurveArray curveArray = new CurveArray();
  140. foreach (var modelLine in virWalls)
  141. {
  142. curveArray.Append(modelLine.GeometryCurve);
  143. }
  144. #region 创建房间分割
  145. Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
  146. var sp = SketchPlane.Create(doc, p);
  147. doc.Create.NewRoomBoundaryLines(sp, curveArray, view);
  148. #endregion
  149. #region 获取封闭区域
  150. var topology = doc.get_PlanTopology(level, phase);
  151. foreach (PlanCircuit topologyCircuit in topology.Circuits)
  152. {
  153. var point = topologyCircuit.GetPointInside();
  154. var xyz = new XYZ(point.U, point.V, level.ProjectElevation+1); //适当升高一些
  155. points.Add(xyz);
  156. }
  157. #endregion
  158. }
  159. catch (Exception e)
  160. {
  161. }
  162. finally
  163. {
  164. sub.RollBack();
  165. }
  166. }
  167. #endregion
  168. #region 创建空间
  169. foreach (var point in points)
  170. {
  171. var oldSpace = doc.GetSpaceAtPoint(point, phase);
  172. if (oldSpace == null)
  173. {
  174. doc.Create.NewSpace(level, phase, new UV(point.X, point.Y));
  175. }
  176. }
  177. // var newSpaces = doc.Create.NewSpaces2(level, phase, view);
  178. #endregion
  179. }
  180. }
  181. /// <summary>
  182. /// 处理冲突信息
  183. /// </summary>
  184. /// <param name="doc"></param>
  185. /// <param name="failItems"></param>
  186. /// <param name="context">楼层上下文</param>
  187. /// <returns>ture表示处理完成,false表示存在没处理的空间【冲突空间可能未处理】</returns>
  188. public static bool DealSpaceFailuresPreprocessor(Document doc, List<FailItem> failItems,FloorSpaceContext context)
  189. {
  190. bool flag = true;
  191. #region 处理逻辑
  192. /*
  193. * 1、根据条件过滤,满足自动处理的自动处理。
  194. * 2、不满足自动处理的,手动选择保留项
  195. */
  196. #endregion
  197. List<ServerSpace> serverSpaces = new List<ServerSpace>();
  198. Regex regex = new Regex(@"^\d+$");
  199. var index = 1;
  200. foreach (var failItem in failItems)
  201. {
  202. var spacesServerInfo =context.GetPhysicalSpaces(failItem.Select(id=>id.IntegerValue.ToString()).ToList());
  203. if (spacesServerInfo == null || spacesServerInfo.Count == 0)
  204. {
  205. #region 冲突对象不包含物理世界空间
  206. var firstElement = doc.GetElement(failItem.FirstOrDefault());
  207. if (firstElement is RSpace first)
  208. {
  209. for (int i = 1; i < failItem.Count; i++)
  210. {
  211. var currentId = failItem[i];
  212. if (first.Id.IsEqual(currentId))
  213. continue;
  214. var curr = doc.GetElement(currentId) as RSpace;
  215. if (!regex.IsMatch(curr.Number))
  216. {
  217. doc.Delete(new List<ElementId>() { currentId });
  218. continue;
  219. }
  220. if (!regex.IsMatch(first.Number))
  221. {
  222. doc.Delete(new List<ElementId>() { first.Id });
  223. first = curr;
  224. continue;
  225. }
  226. if (int.Parse(first.Number) > int.Parse(curr.Number))
  227. {
  228. doc.Delete(new List<ElementId>() { first.Id });
  229. first = curr;
  230. }
  231. else
  232. {
  233. doc.Delete(new List<ElementId>() { currentId });
  234. }
  235. }
  236. }
  237. #endregion
  238. }
  239. else if (spacesServerInfo.Count == 1)
  240. {
  241. #region 冲突对象包好一个物理世界对象
  242. var serverSpaceId = spacesServerInfo[0].BimID.Split(':')[1];
  243. doc.Delete(failItem.Where(t => t.ToString() != serverSpaceId).ToList());
  244. #endregion
  245. }
  246. else
  247. {
  248. #region 冲突对象包含多个物理世界对象,保留物理世界对象手动选择【一般删掉空间分割产生这种情况】
  249. doc.Delete(failItem.Where(t => !spacesServerInfo.Exists(sp => sp.BimID.Split(':')[1] == t.ToString())).ToList());
  250. var groupName = $"待合并元空间组{index}";
  251. foreach (var mRevitEquipBase in spacesServerInfo)
  252. {
  253. if (mRevitEquipBase is MISpace space)
  254. {
  255. serverSpaces.Add(new ServerSpace()
  256. {
  257. Space = space,
  258. GroupName = groupName
  259. });
  260. }
  261. }
  262. serverSpaces.Add(new ServerSpace()
  263. {
  264. Name = NewCreateSpaceFlag,
  265. GroupName = groupName
  266. });
  267. index++;
  268. #endregion
  269. }
  270. }
  271. if (serverSpaces.Count > 0)
  272. {
  273. var winDeal = new WinSelectSpace(serverSpaces);
  274. var result = winDeal.ShowDialog();
  275. if (result == true)
  276. {
  277. //在指定位置创建空间,保留任意存在空间的定位点,根据定位点创建空间。
  278. var groups = serverSpaces.GroupBy(t => t.GroupName);
  279. List<string> deletedIds = new List<string>();
  280. List<UV> newSpaceLocations = new List<UV>();
  281. foreach (var groupSpaces in groups)
  282. {
  283. var spaces = groupSpaces.ToList();
  284. foreach (var serverSpace in spaces)
  285. {
  286. if (serverSpace.IsChecked)
  287. {
  288. if (IsNewSpaceFlag(serverSpace))
  289. {
  290. //新建标志的,利用原始空间坐标创建新空间
  291. var tempSpace = spaces.FirstOrDefault(c => !IsNewSpaceFlag(c));
  292. var elementId = GetElementId(tempSpace.Space);
  293. var useSpace = doc.GetElement(new ElementId(elementId.ToInt())) as RSpace;
  294. newSpaceLocations.Add(useSpace.GetLocationPoint().ToUv());
  295. }
  296. }
  297. else
  298. {
  299. //没选中删除
  300. if (!IsNewSpaceFlag(serverSpace))
  301. {
  302. deletedIds.Add(GetElementId(serverSpace.Space));
  303. }
  304. }
  305. }
  306. }
  307. #region revit 模型处理
  308. //删除
  309. if (deletedIds.Any())
  310. {
  311. doc.Delete(deletedIds.Select(c=>new ElementId(c.ToInt())).ToList());
  312. }
  313. //创建新的空间
  314. var view = doc.GetUseView();
  315. Phase phase = view.GetUsePhase();
  316. PhaseUtil.ValidateUsePhase(phase);
  317. foreach (var newSpaceLocation in newSpaceLocations)
  318. {
  319. var space = ExternalDataWrapper.Current.DocCreater.NewSpace(view.GenLevel, phase,newSpaceLocation);
  320. ExternalDataWrapper.Current.DocCreater.NewSpaceTag(space, newSpaceLocation, view);
  321. }
  322. #endregion
  323. }
  324. else
  325. {
  326. //没处理会有什么操作
  327. flag = false;
  328. }
  329. }
  330. return flag;
  331. }
  332. /// <summary>
  333. /// 上传模型
  334. /// </summary>
  335. /// <param name="doc"></param>
  336. public static void UploadModel(Document doc)
  337. {
  338. //doc.Save();
  339. string str = "";
  340. UploadModeCommand command = new UploadModeCommand();
  341. command.Execute(null, ref str, null);
  342. }
  343. }
  344. /// <summary>
  345. /// 空间分割信息
  346. /// </summary>
  347. public class SpaceSeparation
  348. {
  349. public SpaceSeparation(XYZ start, XYZ end)
  350. {
  351. this.Start = start;
  352. this.End = end;
  353. }
  354. public XYZ Start { get; private set; }
  355. public XYZ End { get; private set; }
  356. /// <summary>
  357. /// 关联Id
  358. /// </summary>
  359. public int Id { get; set; }
  360. }
  361. }