using System.Windows; using Autodesk.Revit.DB; using Autodesk.Revit.DB.IFC; using Nice3point.Revit.Toolkit.External; using ShrlAlgoToolkit.RevitAddins.Assists; using ShrlAlgoToolkit.RevitAddins.Windows; namespace ShrlAlgoToolkit.RevitAddins.RvCivil; [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class SplitComsByLevelCmd : ExternalCommand { public override void Execute() { var instances = Document.OfCollector().OfClass(typeof(FamilyInstance)).Cast().ToList(); var errors = new List(); using (TransactionGroup tg = new(Document, "按标高拆分墙、柱")) { tg.Start(); //墙打断 using (Transaction trans = new(Document, "楼层分割打断构件")) { trans.Start(); var walls = Document.OfCollector().OfClass(typeof(Wall)).Cast().ToList(); var structuralColumns = Document.OfCollector() .OfClass(typeof(FamilyInstance)) .OfCategory(BuiltInCategory.OST_StructuralColumns) .Cast() .ToList(); var columns = Document.OfCollector() .OfClass(typeof(FamilyInstance)) .OfCategory(BuiltInCategory.OST_Columns) .Cast() .ToList(); var elemToSplitIds = new List(); foreach (var wall in walls) { //得到墙的包围框 var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == wall.Id) { errors.Add(new MessageModel(wall, "有族基于当前墙无法拆分")); canModify = false; break; } } if (ExporterIFCUtils.HasElevationProfile(wall)) { canModify = false; errors.Add(new MessageModel(wall, "轮廓被修改无法拆分")); } var needToDelete = false; if (canModify) { needToDelete = SplitWallByLevel(Document, wall, ActiveView); } if (needToDelete) { elemToSplitIds.Add(wall.Id); } } foreach (var column in structuralColumns) { var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == column.Id) { errors.Add(new MessageModel(column, "有族基于当前结构柱,无法拆分")); canModify = false; break; } } var needToDelete = false; if (canModify) { needToDelete = SplitColumnByLevel(Document, column, ActiveView); } if (needToDelete) { elemToSplitIds.Add(column.Id); } } foreach (var column in columns) { var canModify = true; foreach (var instance in instances) { if (instance.Host != null && instance.Host.Id == column.Id) { errors.Add(new MessageModel(column, "有族基于当前柱,无法拆分")); canModify = false; break; } } var needToDelete = false; if (canModify) { needToDelete = SplitColumnByLevel(Document, column, ActiveView); } if (needToDelete) { elemToSplitIds.Add(column.Id); } } Document.Delete(elemToSplitIds); trans.Commit(); } tg.Assimilate(); } if (errors.Any()) { WinDialogHelper.ShowModeless(new MessageViewModel(UiDocument, errors, "未解决错误")); } else { MessageBox.Show("处理完成", "提示", MessageBoxButton.OK, MessageBoxImage.Information); } } private static bool SplitColumnByLevel(Document document, FamilyInstance column, View view) { var wallBox = column.get_BoundingBox(view); var minZ = wallBox.Min.Z; var maxZ = wallBox.Max.Z; var allLevels = document .OfClass() .OfCategory(BuiltInCategory.OST_Levels) .Cast() .OrderBy(o => o.Elevation) .ToList(); var toSplit = document .OfClass() .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[0].Id); var minLevel = allLevels[0]; if (n > 0) { minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束 } var translation = XYZ.BasisZ; var bottomEleIds = ElementTransformUtils.CopyElement(document, column.Id, translation); var minWall = document.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[0].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(document, column.Id, translation); var maxWall = document.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(document, column.Id, translation); var wallCopy = document.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.Bottom) //{ // wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Bottom); //} //Wall.Create(document, curve, wall.WallType.ViewId, levels[i].ViewId, 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[0].Id); var minLevel = allLevels[0]; if (n > 0) { minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束 } var translation = XYZ.BasisZ; 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[0].Id); minWall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(0); //Wall.Create(doc, (wall.Location as LocationCurve).Curve, wall.WallType.Id, minLevel.Id, minLevel.Bottom - minZ, minZ - minLevel.Bottom, wall.Flipped, Convert.ToBoolean(wall.get_Parameter(BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT).AsInteger())); 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); doc.Regenerate(); 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); doc.Regenerate(); 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.Bottom) //{ // wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Bottom); //} //Wall.Create(document, curve, wall.WallType.ViewId, levels[i].ViewId, 100, 100, false, false); } return true; } }