using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Nice3point.Revit.Toolkit.External.Handlers; using RandomColorGenerator; namespace Sai.RvKits.RvMEP; public partial class HeadroomCheckViewModel : ObservableObject { private readonly UIApplication uiapp; public HeadroomCheckViewModel(UIApplication uiapp) { this.uiapp = uiapp; document = uiapp.ActiveUIDocument.Document; Rooms = GetRoomItems(); checkHeadroom = new ActionEventHandler(); generateRoom3d = new ActionEventHandler(); } private readonly ActionEventHandler checkHeadroom; private readonly ActionEventHandler generateRoom3d; private readonly Document document; [ObservableProperty] private List rooms; private List GetRoomItems() { var roomItems = new List(); var allRooms = uiapp.ActiveUIDocument.Document.OfClass().OfType(); var groups = allRooms.GroupBy(r => r.Name); IEnumerable> enumerable = groups as IGrouping[] ?? groups.ToArray(); var colors = GetRandomColors(enumerable.Count()); for (int i = 0; i < enumerable.Count(); i++) { var group = enumerable.ElementAt(i); var color = colors.ElementAt(i); foreach (var room in group) { var r = new RoomCheckItem() { Room = room, Name = room.Name, Color = color, }; roomItems.Add(r); } } return roomItems; } private static IEnumerable GetRandomColors(int count) { var colors = RandomColor.GetColors(ColorScheme.Random, Luminosity.Light, count); return colors.Select(color => new Color(color.R, color.G, color.B)); } private bool CanClick() { return Rooms.Any(); } [RelayCommand(CanExecute = nameof(CanClick))] private void AnalysisHeadroom() { checkHeadroom.Raise(_ => { var view = document.ActiveView; //var elev = view.GenLevel.Bottom; document.Invoke(_ => { ElementClassFilter filter = new(typeof(Floor)); foreach (var item in Rooms) { var room = item.Room; Level baseLevel = room.Level; var levels = document.OfClass().Cast(); Level aboveLevel = null; double tempElev = double.MaxValue; foreach (var level in levels) { if (level.Elevation > baseLevel.Elevation && (level.Elevation - baseLevel.Elevation) < tempElev) { aboveLevel = level; tempElev = level.Elevation; } } Element hitBottomElement = null; Element hitTopElement = null; document.XRayFindNearest(filter, FindReferenceTarget.Element, room.GetLocXYZ(), -XYZ.BasisZ, ref hitBottomElement); document.XRayFindNearest(filter, FindReferenceTarget.Element, room.GetLocXYZ(), XYZ.BasisZ, ref hitTopElement); if (hitBottomElement is Floor bottomFloor && bottomFloor.LevelId == baseLevel.Id)//击中的楼板是上层的楼板 { //绝对标高 var baseOffset = bottomFloor.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_BOTTOM).AsDouble(); //底部偏移 room.BaseOffset = baseOffset - baseLevel.Elevation; } else//找不到楼板则为0 { room.BaseOffset = 0; } if (hitTopElement is Floor topFloor && topFloor.LevelId == aboveLevel?.Id)//击中的楼板是当前的楼板 { //绝对标高 var limitOffset = topFloor.get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_TOP).AsDouble(); //高度偏移 room.LimitOffset = limitOffset - room.UpperLimit.Elevation; //全部高度 //view.GetViewRange().GetLevelId(PlanViewPlane.TopClipPlane) //item.Room } else//找不到楼板则为上部标高 { room.LimitOffset = aboveLevel.Elevation - room.UpperLimit.Elevation; } document.Regenerate(); var elements = room.GetIntersectElements().Where(e => e is MEPCurve || e.Category.Id == new ElementId(BuiltInCategory.OST_StructuralFraming)); foreach (var elem in elements) { var boundingBox = elem.get_BoundingBox(view); //最低绝对标高 var roomTopOffset = boundingBox.Min.Z; room.LimitOffset = roomTopOffset - room.UpperLimit.Elevation; } } }); }); } [RelayCommand(CanExecute = nameof(CanClick))] private void GenerateRoom3D() { document.Invoke(_ => { var list = new List(); DirectShape ds = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel)); FillPatternElement solidFillPattern = document .OfClass() .Cast() .FirstOrDefault(a => a.GetFillPattern().IsSolidFill); foreach (var item in Rooms) { list.Add(item.Room.GetSolid()); Color color = item.Color; //TextNote.Create(document, viewId, position, text, options) OverrideGraphicSettings ogs = new(); ogs.SetProjectionLineColor(color); #if REVIT2018 ogs.SetSurfaceTransparency(50); ogs.SetProjectionFillColor(color); ogs.SetProjectionFillPatternId(solidFillPattern.Id); ogs.SetCutFillColor(color); ogs.SetCutFillPatternId(solidFillPattern.Id); document.ActiveView.SetElementOverrides(ds.Id, ogs); #else ogs.SetSurfaceBackgroundPatternColor(color); ogs.SetSurfaceForegroundPatternId(solidFillPattern.Id); ogs.SetSurfaceForegroundPatternColor(color); ogs.SetCutBackgroundPatternColor(color); ogs.SetCutForegroundPatternColor(color); ogs.SetCutForegroundPatternId(solidFillPattern.Id); ogs.SetSurfaceTransparency(50); document.ActiveView.SetElementOverrides(ds.Id, ogs); #endif } ds.AppendShape(list); }, "创建三维房间实体"); } }