using Autodesk.Revit.DB; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.IFC; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Plumbing; using System; using System.Linq; namespace Szmedi.RvKits.ModelManager { /// /// 基于标高的 /// public static class BaseLevelHelpers { /// /// 获取基于标高的边界 /// /// /// public static Dictionary GetRegions(List levelList) { Dictionary outlines = new(); ////获取标高范围 for (int i = 0; i < levelList.Count() - 1; i++) { Level baseLevel = levelList.ElementAt(i); Level topLevel = levelList.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); outlines.Add(baseLevel, outline); } return outlines; } /// /// 修改基于线的族 /// /// /// /// public static void ModifyCurveBasedFamily(Level level, FamilyInstance familyInstance) { var originOffset = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble(); var doc = level.Document; 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; default: throw new ArgumentOutOfRangeException(); } } doc.Delete(familyInstance.Id); } /// /// 修改基于标高的族 /// /// /// /// public static void ModifyOneLevelBasedFamily(Level level, FamilyInstance familyInstance) { var doc = level.Document; var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM); var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level; if (!baseLevelParam.IsReadOnly && baseLevelParam.UserModifiable) { baseLevelParam.Set(level.Id); var param = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); if (param != null && param.IsReadOnly == false) { var value = param.AsDouble(); param.Set(originLevel.Elevation + value - level.Elevation); } } } /// /// 修改基于两个标高的族 /// /// /// /// public static void ModifyTwoLevelBasedFamily(List levels, Level level, FamilyInstance familyInstance) { var levelOrdered = levels.OrderBy(l => l.Elevation).ToList(); var n = levelOrdered.FindIndex(l => l.Id == level.Id); var doc = level.Document; var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM); var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level; if (!baseLevelParam.IsReadOnly && baseLevelParam.UserModifiable) { baseLevelParam.Set(level.Id); var baseOffestParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM); var baseOffestValue = baseOffestParam.AsDouble(); baseOffestParam.Set(baseOffestValue + originLevel.Elevation - level.Elevation); if (n + 1 < levelOrdered.Count) { var topLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM); originLevel = doc.GetElement(topLevelParam.AsElementId()) as Level; topLevelParam.Set(levelOrdered[n + 1].Id); var topOffestparam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM); var topffestValue = topOffestparam.AsDouble(); familyInstance .get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM) .Set(originLevel.Elevation + topffestValue - levelOrdered[n + 1].Elevation); } } } /// /// 修改墙标高 /// /// /// 项目中的所有标高 /// /// public static void ModifyWall(View view, List levels, Level level, Wall wall) { var doc = wall.Document; var isExist = new FilteredElementCollector(doc) .OfClass(typeof(FamilyInstance)) .Cast() .Any(fi => fi.Host?.Id == wall.Id); var instances = doc.OfType().Where(ins => ins.Host != null && ins.Host.Id == wall.Id); //存在主体依赖 if (isExist) { return; } var levelOrdered = levels.OrderBy(l => l.Elevation).ToList(); var n = levelOrdered.FindIndex(l => l.Id == level.Id); var wallBox = wall.get_BoundingBox(view); var minZ = wallBox.Min.Z; var maxZ = wallBox.Max.Z; if (ExporterIFCUtils.HasElevationProfile(wall) || instances.Any()) { return; } wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(level.Id); var originBaseOffest = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - level.Elevation); if (n + 1 < levelOrdered.Count) { wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(levelOrdered[n + 1].Id); var originTopOffest = wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - levelOrdered[n + 1].Elevation); } } /// /// 修改基于工作平面的族 /// /// /// /// /// public static void ModifyWorkPlaneBasedFamily(Level level, FamilyInstance familyInstance) { Parameter baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM); var doc = level.Document; //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(); } LocationPoint lop = familyInstance.Location as LocationPoint; FamilyInstance newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), lop?.Point, familyInstance.HandOrientation, familyInstance.Symbol); Definition 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: throw new ArgumentOutOfRangeException(); } } doc.Delete(familyInstance.Id); } else { if (baseLevelParam.IsReadOnly == false) { baseLevelParam.Set(level.Id); } } } /// /// 设置族实例 /// /// 标高范围,通过GetRegion方法获得 /// public static List SetInstances(List levels) { var levelOutlines = GetRegions(levels); List errors = new(); var doc = levels.FirstOrDefault().Document; doc.Invoke(ts => { //对比标高,得到实际分层位置 foreach (KeyValuePair keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); Level level = keyPair.Key; List insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem is FamilyInstance && (elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null)).ToList(); foreach (Element elem in insideCollector) { try { //获取构件定位方式,基于标高,基于主体(基于面,基于线,基于主体构件:墙板等),基于点 if (elem is not FamilyInstance familyInstance) { continue; } FamilyPlacementType placementType = familyInstance.Symbol.Family.FamilyPlacementType; switch (placementType) { case FamilyPlacementType.OneLevelBased: ModifyOneLevelBasedFamily(level, familyInstance); break; case FamilyPlacementType.OneLevelBasedHosted: break; case FamilyPlacementType.TwoLevelsBased: ModifyTwoLevelBasedFamily(levels, level, familyInstance); break; case FamilyPlacementType.ViewBased: break; case FamilyPlacementType.WorkPlaneBased: ModifyWorkPlaneBasedFamily(level, familyInstance); break; case FamilyPlacementType.CurveBased: ModifyCurveBasedFamily(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(uidoc, errors); // var errorResolveWin = new ErrorResolveWin(processorViewModel); // WinDialogAssists.ShowAhead(errorResolveWin); //} } /// /// 设置管线 /// /// public static List SetMEPCurves(List levels) { List errors = new(); var doc = levels.FirstOrDefault().Document; var levelOutlines = GetRegions(levels); doc.Invoke(ts => { //对比标高,得到实际分层位置 foreach (KeyValuePair keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); Level level = keyPair.Key; List insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null).ToList(); foreach (Element 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 static List SetWalls(List levels) { List errors = new(); var doc = levels.FirstOrDefault().Document; var levelOutlines = GetRegions(levels); doc.Invoke(_ => { //对比标高,得到实际分层位置 foreach (KeyValuePair keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); Level level = keyPair.Key; List insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null).ToList(); foreach (Element elem in insideCollector) { try { if (elem is Wall wall) { ModifyWall(doc.ActiveView, levels, level, wall); } } catch (Exception ex) { errors.Add(new MessageModel(elem, ex.Message)); } } } }, "校正墙体标高"); return errors; //if (errors.Any()) //{ // var processorViewModel = new ErrorResolveViewModel(uidoc, errors); // var errorResolveWin = new ErrorResolveWin(processorViewModel); // WinDialogAssists.ShowAhead(errorResolveWin); //} } } }