using Autodesk.Revit.DB; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using ShrlAlgo.RvKits.Windows; namespace ShrlAlgo.RvKits.ModelManager; public class CorrectReferLevelExecutes { public CorrectReferLevelExecutes(UIApplication uiapp) { var uidoc = uiapp.ActiveUIDocument; doc = uidoc.Document; view = uidoc.ActiveView; levels =doc.OfClass() .OfCategory(BuiltInCategory.OST_Levels) .Cast() .OrderBy(l => l.Elevation) .ToList(); levelOutlines = GetRegions(levels); } private readonly Document doc; private readonly Dictionary levelOutlines; private readonly List levels; //private uiApplication uiApplication; private readonly View view; /// /// 设置族实例 /// /// public List SetInstances() { List errors = []; doc.Invoke(ts => { //对比标高,得到实际分层位置 foreach (var keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); var level = keyPair.Key; var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem is FamilyInstance && (elem.LevelId != level.Id || elem.get_BoundingBox(view) != null)).ToList(); foreach (var elem in insideCollector) { try { //获取构件定位方式,基于标高,基于主体(基于面,基于线,基于主体构件:墙板等),基于点 if (elem is not FamilyInstance familyInstance) { continue; } var placementType = familyInstance.Symbol.Family.FamilyPlacementType; switch (placementType) { case FamilyPlacementType.OneLevelBased: ModifyOneLevelBasedFamily(doc, level, familyInstance); break; case FamilyPlacementType.OneLevelBasedHosted: break; case FamilyPlacementType.TwoLevelsBased: ModifyTwoLevelBasedFamily(doc, levels, level, familyInstance); break; case FamilyPlacementType.ViewBased: break; case FamilyPlacementType.WorkPlaneBased: ModifyWorkPlaneBasedFamily(doc, level, familyInstance); break; case FamilyPlacementType.CurveBased: ModifyCurveBasedFamily(doc, level, familyInstance); break; case FamilyPlacementType.CurveBasedDetail: break; case FamilyPlacementType.CurveDrivenStructural: break; case FamilyPlacementType.Adaptive: break; case FamilyPlacementType.Invalid: break; } } catch (Exception ex) { errors.Add(new MessageModel(elem, ex.Message)); } } } }, "校正族实例标高"); return errors; //if (errors.Any()) //{ // var processorViewModel = new ErrorResolveViewModel(UiDocument, errors); // var errorResolveWin = new ErrorResolveWin(processorViewModel); // WinDialogHelper.ShowAhead(errorResolveWin); //} } /// /// 设置管线 /// /// public List SetMEPCurves() { List errors = []; doc.Invoke(ts => { //对比标高,得到实际分层位置 foreach (var keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); var level = keyPair.Key; var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(view) != null).ToList(); foreach (var elem in insideCollector) { try { if (elem is Pipe or Duct or CableTray or Conduit) { elem.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(level.Id); } } catch (Exception ex) { errors.Add(new MessageModel(elem, ex.Message)); } } } }, "校正管线标高"); return errors; } /// /// 设置墙 /// /// public List SetWalls() { List errors = []; doc.Invoke(_ => { //对比标高,得到实际分层位置 foreach (var keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); var level = keyPair.Key; var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(view) != null).ToList(); foreach (var elem in insideCollector) { try { if (elem is Wall) { ModifyWall(view, levels, level, elem); } } catch (Exception ex) { errors.Add(new MessageModel(elem, ex.Message)); } } } }, "校正墙体标高"); return errors; //if (errors.Any()) //{ // var processorViewModel = new ErrorResolveViewModel(UiDocument, errors); // var errorResolveWin = new ErrorResolveWin(processorViewModel); // WinDialogHelper.ShowAhead(errorResolveWin); //} } /// /// 获取基于标高的边界 /// /// /// public static Dictionary GetRegions(IEnumerable levels) { Dictionary levelOutlines = []; ////获取标高范围 for (var i = 0; i < levels.Count() - 1; i++) { var baseLevel = levels.ElementAt(i); var topLevel = levels.ElementAt(i + 1); XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation); XYZ max = new(double.MaxValue, double.MaxValue, topLevel.Elevation); Outline outline = new(min, max); levelOutlines.Add(baseLevel, outline); } return levelOutlines; } /// /// 修改基于线的族 /// /// /// /// private static void ModifyCurveBasedFamily(Document doc, Level level, FamilyInstance familyInstance) { var originOffset = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble(); if (familyInstance.Host is not Level) { return; } if (!familyInstance.Symbol.IsActive) { familyInstance.Symbol.Activate(); } var hostLevel = familyInstance.Host as Level; var offset = hostLevel.Elevation + originOffset - level.Elevation; var loc = familyInstance.Location as LocationCurve; var p1 = loc.Curve.GetEndPoint(0); var p2 = loc.Curve.GetEndPoint(1); var line = Line.CreateBound(p1.Add(XYZ.BasisZ * level.Elevation), p2.Add(XYZ.BasisZ * level.Elevation)); var newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), line, familyInstance.Symbol); var offsetParam = newFamilyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); offsetParam.Set(offset); foreach (Parameter param in familyInstance.Parameters) { if (param.IsReadOnly || param.Definition.Name == offsetParam.Definition.Name) { continue; } switch (param.StorageType) { case StorageType.None: break; case StorageType.Integer: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsInteger()); break; case StorageType.Double: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsDouble()); break; case StorageType.String: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsString()); break; case StorageType.ElementId: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsElementId()); break; } } doc.Delete(familyInstance.Id); } /// /// 修改基于标高的族 /// /// /// /// private static void ModifyOneLevelBasedFamily(Document doc, Level level, FamilyInstance familyInstance) { var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM); var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level; baseLevelParam.Set(level.Id); var param = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); if (param == null || param.IsReadOnly) { return; } var value = param.AsDouble(); param.Set(originLevel.Elevation + value - level.Elevation); } /// /// 修改基于两个标高的族 /// /// /// /// /// private static void ModifyTwoLevelBasedFamily(Document doc, List levels, Level level, FamilyInstance familyInstance) { var n = levels.FindIndex(l => l.Id == level.Id); var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM); var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level; baseLevelParam.Set(level.Id); var baseOffsetParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM); var baseOffsetValue = baseOffsetParam.AsDouble(); baseOffsetParam.Set(baseOffsetValue + originLevel.Elevation - level.Elevation); var topLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM); originLevel = doc.GetElement(topLevelParam.AsElementId()) as Level; topLevelParam.Set(levels[n + 1].Id); var topOffsetParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM); var topOffsetValue = topOffsetParam.AsDouble(); familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(originLevel.Elevation + topOffsetValue - levels[n + 1].Elevation); } /// /// 修改基于墙 /// /// /// /// /// private static void ModifyWall(View view, List levels, Level level, Element elem) { var wall = (Wall)elem; var doc = elem.Document; var isExist = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).Cast().Any(fi => fi.Host?.Id == wall.Id); if (isExist) { return; } var n = levels.FindIndex(l => l.Id == level.Id); var wallBox = wall.get_BoundingBox(view); var minZ = wallBox.Min.Z; var maxZ = wallBox.Max.Z; wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(level.Id); wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - level.Elevation); wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(levels[n + 1].Id); wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - levels[n + 1].Elevation); } /// /// 修改基于工作平面的族 /// /// /// /// /// private static void ModifyWorkPlaneBasedFamily(Document doc, Level level, FamilyInstance familyInstance) { var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM); //var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level; //var hostParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_PARAM); //var hostParamValue = doc.GetElement(hostParam.AsElementId()); if (familyInstance.Host is Level) { if (!familyInstance.Symbol.IsActive) { familyInstance.Symbol.Activate(); } var lop = familyInstance.Location as LocationPoint; var newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), lop?.Point, familyInstance.HandOrientation, familyInstance.Symbol); var p = newFamilyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Definition; foreach (Parameter param in familyInstance.Parameters) { if (param.IsReadOnly || param.Definition.Name == p.Name) { continue; } switch (param.StorageType) { case StorageType.None: break; case StorageType.Integer: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsInteger()); break; case StorageType.Double: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsDouble()); break; case StorageType.String: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsString()); break; case StorageType.ElementId: newFamilyInstance.get_Parameter(param.Definition).Set(param.AsElementId()); break; default: break; } } doc.Delete(familyInstance.Id); } else { if (baseLevelParam.IsReadOnly == false) { baseLevelParam.Set(level.Id); } } } }