using Autodesk.Revit.DB; using Autodesk.Revit.DB.IFC; using Autodesk.Revit.UI; using System; using System.Linq; using System.Windows; namespace Szmedi.RvKits.ModelManager { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class SplitComponentByLevelCmd : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var result=MessageBox.Show("确认按标高拆分墙柱构件?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result != MessageBoxResult.Yes) { return Result.Cancelled; } var uiapp = commandData.Application; var uidoc = uiapp.ActiveUIDocument; var doc = uidoc.Document; var view = doc.ActiveView; var instances = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).Cast(); List elementsToSkip = []; using (TransactionGroup tg = new(doc, "按标高拆分墙、柱")) { tg.Start(); //墙打断 using (Transaction trans = new(doc, "楼层分割打断构件")) { trans.Start(); var levels = doc.OfClass() .OfCategory(BuiltInCategory.OST_Levels) .Cast() .OrderBy(l => l.Elevation) .ToList(); var walls = doc.OfType().ToList(); var structuralColumns = doc.OfClass().OfCategory(BuiltInCategory.OST_StructuralColumns).ToList(); var columns = doc.OfClass().OfCategory(BuiltInCategory.OST_Columns).ToList(); List elemToSplitIds = []; foreach (var wall in walls) { //得到墙的包围框 var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == wall.Id) { elementsToSkip.Add(new MessageModel(wall, "主体不存在")); canModify = false; break; } } if (ExporterIFCUtils.HasElevationProfile(wall)) { canModify = false; } var needToDelete = false; if (canModify) { needToDelete = SplitWallByLevel(doc, wall, view); } if (needToDelete) { elemToSplitIds.Add(wall.Id); } } foreach (FamilyInstance column in structuralColumns) { var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == column.Id) { elementsToSkip.Add(new MessageModel(column, "主体不存在")); canModify = false; break; } } var needToDelete = false; if (canModify) { needToDelete = SplitColumnByLevel(doc, column, view); } if (needToDelete) { elemToSplitIds.Add(column.Id); } } foreach (FamilyInstance column in columns) { var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == column.Id) { elementsToSkip.Add(new MessageModel(column, "主体不存在")); canModify = false; break; } } var needToDelete = false; if (canModify) { needToDelete = SplitColumnByLevel(doc, column, view); } if (needToDelete) { elemToSplitIds.Add(column.Id); } } doc.Delete(elemToSplitIds); trans.Commit(); } tg.Assimilate(); } if (elementsToSkip.Count > 0) { //AssemblyLoaderHelpers loader = new(GlobalVariables.DirAssembly); //loader.HookAssemblyResolve(); try { MessageWin errorResolveWin = new() { DataContext = new MessageViewModel(uidoc, elementsToSkip) }; errorResolveWin.ShowDialog(); } catch (Exception e) { MessageBox.Show(e.Message); LogAssists.WriteLog(e.StackTrace); } //finally //{ // loader.UnhookAssemblyResolve(); //} } else { MessageBox.Show("处理完成", "处理结果", MessageBoxButton.OK, MessageBoxImage.Information); } return Result.Succeeded; } private static bool SplitColumnByLevel(Document doc, FamilyInstance column, View view) { var wallBox = column.get_BoundingBox(view); var minZ = wallBox.Min.Z; var maxZ = wallBox.Max.Z; var allLevels = new FilteredElementCollector(doc) .OfClass(typeof(Level)) .OfCategory(BuiltInCategory.OST_Levels) .Cast() .OrderBy(o => o.Elevation) .ToList(); var toSplit = new FilteredElementCollector(doc) .OfClass(typeof(Level)) .OfCategory(BuiltInCategory.OST_Levels) .Cast() .Where(l => l.Elevation - minZ > 0.0001 && maxZ - l.Elevation > 0.0001) .OrderBy(o => o.Elevation) .ToList(); if (toSplit.Count == 0) { return false; } var n = allLevels.FindIndex(l => l.Id == toSplit.First().Id); var minLevel = allLevels.First(); if (n > 0) { minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束 } XYZ translation = new(); var bottomEleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation); var minWall = doc.GetElement(bottomEleIds.FirstOrDefault()) as FamilyInstance; //底部约束 minWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(minLevel.Id); minWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(minZ - minLevel.Elevation); minWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(toSplit.First().Id); minWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(0); var maxLevel = toSplit.Last(); var m = allLevels.FindIndex(l => l.Id == toSplit.Last().Id); if (m < allLevels.Count - 1) { maxLevel = allLevels[m + 1]; //存在更高的标高 } var topEleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation); var maxWall = doc.GetElement(topEleIds.FirstOrDefault()) as FamilyInstance; maxWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(toSplit.Last().Id); maxWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(0); maxWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(maxLevel.Id); maxWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(maxZ - maxLevel.Elevation); for (var i = 0; i < toSplit.Count - 1; i++) { var baseLevel = toSplit[i]; var topLevel = toSplit[i + 1]; var eleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation); var wallCopy = doc.GetElement(eleIds.FirstOrDefault()) as FamilyInstance; wallCopy.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(baseLevel.Id); wallCopy.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(0); wallCopy.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(topLevel.Id); wallCopy.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(0); //if (i == levelsToSplit.Count - 2 && maxZ < maxLevel.Elevation) //{ // wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation); //} //Wall.Create(doc, curve, wall.WallType.Id, levels[i].Id, 100, 100, false, false); } return true; } /// /// 切分墙体 /// /// /// /// 三维视图 /// private static bool SplitWallByLevel(Document doc, Wall wall, View view) { var wallBox = wall.get_BoundingBox(view); var minZ = wallBox.Min.Z; var maxZ = wallBox.Max.Z; var allLevels = new FilteredElementCollector(doc) .OfClass(typeof(Level)) .OfCategory(BuiltInCategory.OST_Levels) .Cast() .OrderBy(o => o.Elevation) .ToList(); var toSplit = new FilteredElementCollector(doc) .OfClass(typeof(Level)) .OfCategory(BuiltInCategory.OST_Levels) .Cast() .Where(l => l.Elevation - minZ > 0.0001 && maxZ - l.Elevation > 0.0001) .OrderBy(o => o.Elevation) .ToList(); if (toSplit.Count == 0) { return false; } var n = allLevels.FindIndex(l => l.Id == toSplit.First().Id); var minLevel = allLevels.First(); if (n > 0) { minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束 } XYZ translation = new(); var bottomEleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation); var minWall = doc.GetElement(bottomEleIds.FirstOrDefault()) as Wall; //底部约束 minWall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(minLevel.Id); minWall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - minLevel.Elevation); minWall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(toSplit.First().Id); minWall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(0); var maxLevel = toSplit.Last(); var m = allLevels.FindIndex(l => l.Id == toSplit.Last().Id); if (m < allLevels.Count - 1) { maxLevel = allLevels[m + 1]; //存在更高的标高 } var topEleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation); var maxWall = doc.GetElement(topEleIds.FirstOrDefault()) as Wall; maxWall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(toSplit.Last().Id); maxWall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(0); maxWall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(maxLevel.Id); maxWall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation); for (var i = 0; i < toSplit.Count - 1; i++) { var baseLevel = toSplit[i]; var topLevel = toSplit[i + 1]; var eleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation); var wallCopy = doc.GetElement(eleIds.FirstOrDefault()) as Wall; wallCopy.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(baseLevel.Id); wallCopy.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(0); wallCopy.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(topLevel.Id); wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(0); //if (i == levelsToSplit.Count - 2 && maxZ < maxLevel.Elevation) //{ // wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation); //} //Wall.Create(doc, curve, wall.WallType.Id, levels[i].Id, 100, 100, false, false); } return true; } } }