using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Mechanical; using FWindSoft.Revit; using FWindSoft.Revit.Extension; using FWindSoft.SystemExtensions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LRH.Tool { public static class RoomToSpaceUtils { /// /// 获取指定的元素信息 /// /// /// /// public static List GetElements(View view, ElementFilter filter) { //删除当前视图下的所有空间和空间分割 var doc = view.Document; var elements = doc.GetElements(filter); return elements.Where(e => e.LevelId == view.GenLevel.Id).ToList(); } /// /// 房间转换成空间 /// /// /// /// public static List RoomToSpace(View view, RoomToSpaceTransOption option,Transaction tran) { //删除当前视图下的所有空间和空间分割 var doc = view.Document; var spaces = GetElements(view, new SpaceFilter()); if (option.DeleteOriginalSpace) { try { tran.Start(); doc.Delete(spaces.Select(e => e.Id).ToList()); tran.Commit(); } catch (Exception) { tran.RollBack(); } } var spaceSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaceSeparationLines)).OfType().ToList(); if (option.DeleteOriginalSpaceSq) { try { tran.Start(); doc.Delete(spaceSeps.Select(e => e.Id).ToList()); tran.Commit(); } catch (Exception) { tran.RollBack(); } } CreateSpaces(view, tran); List relationItems = new List(); try { tran.Start(); #region 根据房间分割创建空间分割 if (option.RoomSqToSpaceSq) { var roomSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_RoomSeparationLines)) .OfType().ToList(); CurveArray curveArray = new CurveArray(); foreach (var roomSep in roomSeps) { curveArray.Append(roomSep.GeometryCurve); } if (!curveArray.IsEmpty) { Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin); var sp = SketchPlane.Create(doc, p); doc.Create.NewSpaceBoundaryLines(sp, curveArray, view); } } #endregion relationItems = RoomDataToSpace(view); tran.Commit(); } catch (Exception) { tran.RollBack(); } return relationItems; } /// /// 房间数据转移到空间数据 /// /// /// public static List RoomDataToSpace(View view) { var doc = view.Document; var rooms = GetElements(view, new RoomFilter()).OfType(); var offset = XYZ.BasisZ * 0.1; HashSet handledSpaces = new HashSet(); List relations = new List(); foreach (Room room in rooms) { var relationItem = new RoomRelationItem() { RoomId = room.Id.ToString() }; relations.Add(relationItem); using (SubTransaction subTran = new SubTransaction(doc)) { Space useSpcae = null; try { subTran.Start(); var location = room.Location.ConvertToPoint(); if (location == null ) { //|| room.Area.IsEqual(0) relationItem.Messages.Add("房间信息无效"); continue; } useSpcae = doc.GetSpaceAtPoint(location.Add(offset)); if (useSpcae == null) { relationItem.Messages.Add("未找到对应空间"); continue; } InfoTrans(room, useSpcae, handledSpaces.Contains(useSpcae.Id.IntegerValue)); subTran.Commit(); //成功 handledSpaces.Add(useSpcae.Id.IntegerValue); relationItem.SpaceId = useSpcae.Id.ToString(); relationItem.IsSuccess = true; } catch (Exception ex) { relationItem.Messages.Add("赋值异常"+ex.Message); subTran.RollBack(); } } } return relations; } public static List CreateSpaces(View view) { List spaces = new List(); Document doc = view.Document; var level = view.GenLevel; Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE); ElementId phaseId = para.AsElementId(); var phase = doc.GetElement(phaseId) as Phase; var points = GetSpacesPoints(view); foreach (var point in points) { var oldSpace = doc.GetSpaceAtPoint(point, phase); if (oldSpace == null) { var tempSapce = doc.Create.NewSpace(level, phase, new UV(point.X, point.Y)); spaces.Add(tempSapce); } } return spaces; } public static void CreateSpaces(View view,Transaction tran) { Document doc = view.Document; FailuresPreprocessor preprocessor = new FailuresPreprocessor(true); { try { FailureHandlingOptions fho = tran.GetFailureHandlingOptions(); fho.SetFailuresPreprocessor(preprocessor); tran.SetFailureHandlingOptions(fho); #region 创建空间 tran.Start(); var spaces=CreateSpaces(view); tran.Commit(); //提交获取冲突代码 #endregion #region 冲突处理代码 FailureHandlingOptions failureOptions = tran.GetFailureHandlingOptions(); failureOptions.SetFailuresPreprocessor(new FailuresPreprocessor(false)); tran.SetFailureHandlingOptions(failureOptions); tran.Start(); //返回值临时使用 var failItems = preprocessor.Items; foreach (var failuresItem in failItems) { var firstId = failuresItem.Items.FirstOrDefault(); if (firstId == null) { continue; } for (int i = 1; i < failuresItem.Items.Count; i++) { var currentId = failuresItem.Items[i]; if (firstId.IntegerValue > currentId.IntegerValue) { doc.Delete(new List() { firstId }); firstId = currentId; } } // doc.GetElement(failuresItem.Items.FirstOrDefault()); } tran.Commit(); #endregion } catch (Exception ex) { tran.RollBack(); } } } /// /// 获取视图中创建空间的点的信息 /// /// /// public static List GetSpacesPoints(View view) { Document doc = view.Document; var level = view.GenLevel; Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE); ElementId phaseId = para.AsElementId(); var phase = doc.GetElement(phaseId) as Phase; #region 创建新的节点 List points = new List(); using (SubTransaction sub = new SubTransaction(doc)) { try { sub.Start(); var spaceSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaceSeparationLines)).OfType().ToList(); CurveArray curveArray = new CurveArray(); foreach (var modelLine in spaceSeps) { curveArray.Append(modelLine.GeometryCurve); } #region 创建房间分割 Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin); var sp = SketchPlane.Create(doc, p); if (!curveArray.IsEmpty) { doc.Create.NewRoomBoundaryLines(sp, curveArray, view); } #endregion #region 获取封闭区域 var topology = doc.get_PlanTopology(level, phase); foreach (PlanCircuit topologyCircuit in topology.Circuits) { var point = topologyCircuit.GetPointInside(); var xyz = new XYZ(point.U, point.V, level.ProjectElevation + 1); //适当升高一些 points.Add(xyz); } #endregion } catch (Exception e) { } finally { sub.RollBack(); } } #endregion return points; } public static void InfoTrans(Room room,Space space,bool isAppend) { var name = room.GetParameterString(BuiltInParameter.ROOM_NAME) ?? string.Empty; if (isAppend) { var oldName = space.GetParameterString(BuiltInParameter.ROOM_NAME)??string.Empty; if (!string.IsNullOrWhiteSpace(name)&& !oldName.Contains(name)) { name = oldName + "," + name; } } space.SetParameter(BuiltInParameter.ROOM_NAME, name); } public static StringBuilder CreateResult(List items) { StringBuilder builder = new StringBuilder(); int errorCount = 0; foreach (var item in items) { if (item.IsSuccess) { continue; } builder.AppendLine(item.ToString()); errorCount++; } builder.AppendLine($"总共{items.Count}房间,转换过程出现问题{errorCount}个"); return builder; } } #region 扩展选项类 public class RoomRelationItem { public string RoomId { get; set; } public string SpaceId { get; set; } /// /// 是否成功 /// public bool IsSuccess { get; set; } /// /// 错误消息 /// public List Messages { get; private set; } = new List(); public override string ToString() { var message = string.Join(";", Messages); return $"RoomId:{RoomId} SpaceId:{SpaceId} Result:{message}"; } } /// /// 导出控制选项 /// public class RoomToSpaceTransOption { /// /// 是否删除原始空间 /// public bool DeleteOriginalSpace { get; set; } = true; /// /// 是否删除原始空间分割 /// public bool DeleteOriginalSpaceSq { get; set; } /// /// 是否将房间分割转换成空间分割 /// public bool RoomSqToSpaceSq { get; set; } } public class FailuresItem { public FailuresItem() { } public FailuresItem(IEnumerable ids) { Items.AddRange(ids); } public List Items { get; private set; } = new List(); } /// /// 空间错误机制 /// public class FailuresPreprocessor : IFailuresPreprocessor { /* * 创建警告时,如果一个区域已经存在多个空间,创建警告时会把所有警告空间进行捕获 */ #region 构造函数 public FailuresPreprocessor() { Items = new List(); } public FailuresPreprocessor(bool append) : this() { Append = append; } #endregion #region 相关操纵选项 /// /// 是否追加捕获信息 /// private bool Append { get; set; } public void SetOperate(bool continueAdd) { Append = continueAdd; } public List Items { get; private set; } #endregion public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor) { IList messages = failuresAccessor.GetFailureMessages(); if (messages.Count == 0) return FailureProcessingResult.Continue; foreach (FailureMessageAccessor message in messages) { var currentSeverity = message.GetSeverity(); switch (currentSeverity) { case FailureSeverity.Error: { if (message.HasResolutions()) failuresAccessor.ResolveFailure(message); break; } case FailureSeverity.Warning: { if (Append) { var elementIds = message.GetFailingElementIds(); if (elementIds.Any()) { Items.Add(new FailuresItem(elementIds.ToList())); } } failuresAccessor.DeleteWarning(message); break; } } } return FailureProcessingResult.ProceedWithCommit; } } #endregion }