using System; using System.Collections.Generic; using System.Linq; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using RevitHttpControl.Models; namespace RevitHttpControl.Services { /// /// 薄壳分析服务 /// public class ShellAnalyzer { public ElementAction GetElementAction(Element element, ShellOptimizeMode mode) { if (element?.Category == null) return ElementAction.Keep; return DetermineElementAction(element, mode); } /// /// 分析模型构件,确定保留和删除的元素 /// public ShellAnalyzeResponse AnalyzeModel(Document doc, ShellOptimizeMode mode) { if (doc == null) throw new ArgumentNullException(nameof(doc)); // 获取所有构件 var allElements = GetAnalyzableElements(doc); // 分析每个构件 var analysisResults = new List(); foreach (var element in allElements) { var result = AnalyzeElement(element, mode); analysisResults.Add(result); } // 统计结果 var summary = CreateAnalysisSummary(analysisResults); var categories = CreateCategoryStatistics(analysisResults); return new ShellAnalyzeResponse { Analysis = summary, Categories = categories }; } /// /// 获取可分析的构件(排除视图、注释等) /// private List GetAnalyzableElements(Document doc) { var collector = new FilteredElementCollector(doc) .WhereElementIsNotElementType() .WhereElementIsViewIndependent(); var elements = new List(); foreach (Element element in collector) { // 只分析实体构件,排除视图、注释、标注等 if (IsAnalyzableElement(element)) { elements.Add(element); } } return elements; } /// /// 判断构件是否可分析 /// private bool IsAnalyzableElement(Element element) { // 排除不需要分析的元素类型 if (element is View || element is ViewSheet || element is Viewport) return false; if (element.Category == null) return false; var category = element.Category.Id.IntegerValue; // 包含的主要构件类别 var includedCategories = new[] { (int)BuiltInCategory.OST_Walls, // 墙 (int)BuiltInCategory.OST_Doors, // 门 (int)BuiltInCategory.OST_Windows, // 窗 (int)BuiltInCategory.OST_Furniture, // 家具 (int)BuiltInCategory.OST_FurnitureSystems, // 家具系统 (int)BuiltInCategory.OST_Casework, // 橱柜 (int)BuiltInCategory.OST_Columns, // 柱 (int)BuiltInCategory.OST_StructuralColumns, // 结构柱 (int)BuiltInCategory.OST_StructuralFraming, // 结构框架 (int)BuiltInCategory.OST_Floors, // 楼板 (int)BuiltInCategory.OST_Roofs, // 屋顶 (int)BuiltInCategory.OST_Ceilings, // 天花板 (int)BuiltInCategory.OST_Stairs, // 楼梯 (int)BuiltInCategory.OST_Railings, // 栏杆 (int)BuiltInCategory.OST_GenericModel, // 常规模型 (int)BuiltInCategory.OST_Entourage, // 配景 (int)BuiltInCategory.OST_LightingFixtures, // 灯具 (int)BuiltInCategory.OST_PlumbingFixtures, // 卫浴装置 (int)BuiltInCategory.OST_ElectricalFixtures, // 电气装置 (int)BuiltInCategory.OST_MechanicalEquipment, // 机械设备 (int)BuiltInCategory.OST_ElectricalEquipment, // 电气设备 (int)BuiltInCategory.OST_SpecialityEquipment, // 专用设备 }; return includedCategories.Contains(category); } /// /// 分析单个构件 /// private ElementAnalysisResult AnalyzeElement(Element element, ShellOptimizeMode mode) { var categoryId = element.Category?.Id?.IntegerValue ?? 0; var categoryName = element.Category?.Name ?? "未知类别"; var action = DetermineElementAction(element, mode); var reason = GetActionReason(element, action, mode); return new ElementAnalysisResult { ElementId = element.Id.IntegerValue, CategoryId = categoryId, CategoryName = categoryName, Action = action, Reason = reason }; } /// /// 确定构件的处理动作(保留或删除) /// private ElementAction DetermineElementAction(Element element, ShellOptimizeMode mode) { var category = element.Category.Id.IntegerValue; if (mode == ShellOptimizeMode.EnvelopeOnly) { if (IsSiteElement(category)) return ElementAction.Keep; if (element is RevitLinkInstance) return ElementAction.Remove; return IsEnvelopeElement(element) ? ElementAction.Keep : ElementAction.Remove; } // 1. 始终保留的结构元素 if (IsStructuralElement(category)) return ElementAction.Keep; // 2. 始终保留的外围元素 if (IsExteriorElement(element)) return ElementAction.Keep; // 3. 根据模式判断其他元素 switch (mode) { case ShellOptimizeMode.Conservative: return DetermineConservativeAction(category); case ShellOptimizeMode.Standard: return DetermineStandardAction(category); case ShellOptimizeMode.Aggressive: return DetermineAggressiveAction(category); default: return ElementAction.Keep; } } private bool IsSiteElement(int categoryId) { var siteCategories = new[] { (int)BuiltInCategory.OST_Topography, (int)BuiltInCategory.OST_Site, (int)BuiltInCategory.OST_Parking, (int)BuiltInCategory.OST_Planting, }; return siteCategories.Contains(categoryId); } private bool IsEnvelopeElement(Element element) { if (element?.Category == null) return false; var categoryId = element.Category.Id.IntegerValue; // Curtain系统构件 if (categoryId == (int)BuiltInCategory.OST_CurtainWallPanels || categoryId == (int)BuiltInCategory.OST_CurtainWallMullions) return true; // 外墙 if (element is Wall wall) return IsExteriorWall(wall); // 屋顶 if (element is RoofBase) return true; // 外门窗:Host 为外墙 if (element is FamilyInstance fi) { if (categoryId == (int)BuiltInCategory.OST_Doors || categoryId == (int)BuiltInCategory.OST_Windows) { try { return fi.Host is Wall hostWall && IsExteriorWall(hostWall); } catch { return false; } } } return false; } private bool IsExteriorWall(Wall wall) { try { var wallType = wall.WallType; if (wallType != null) { if (wallType.Function == WallFunction.Exterior) return true; // 少量模型不设置Function时的兜底:幕墙通常属于围护 var typeName = wallType.Name?.ToLower() ?? ""; if (typeName.Contains("curtain") || typeName.Contains("幕墙")) return true; } } catch { return false; } return false; } /// /// 判断是否为结构元素(始终保留) /// private bool IsStructuralElement(int categoryId) { var structuralCategories = new[] { (int)BuiltInCategory.OST_Columns, (int)BuiltInCategory.OST_StructuralColumns, (int)BuiltInCategory.OST_StructuralFraming, (int)BuiltInCategory.OST_Floors, (int)BuiltInCategory.OST_Roofs, (int)BuiltInCategory.OST_Stairs, (int)BuiltInCategory.OST_Railings }; return structuralCategories.Contains(categoryId); } /// /// 判断是否为外围元素(外墙、外门窗等) /// private bool IsExteriorElement(Element element) { // 简化判断:假定外墙、外门窗通过命名或参数识别 // 实际项目中可能需要更复杂的空间分析 if (element is Wall wall) { // 检查墙是否为外墙(简化判断) try { var wallType = wall.WallType; var typeName = wallType?.Name?.ToLower() ?? ""; return typeName.Contains("外") || typeName.Contains("exterior") || typeName.Contains("外墙") || typeName.Contains("curtain"); } catch { return false; } } if (element is FamilyInstance familyInstance) { // 检查门窗是否在外墙上 try { var host = familyInstance.Host; if (host is Wall hostWall) { return IsExteriorElement(hostWall); } } catch { return false; } } return false; } /// /// 保守模式的判断逻辑(只删除装饰元素) /// private ElementAction DetermineConservativeAction(int categoryId) { var decorativeCategories = new[] { (int)BuiltInCategory.OST_Entourage, // 配景 }; return decorativeCategories.Contains(categoryId) ? ElementAction.Remove : ElementAction.Keep; } /// /// 标准模式的判断逻辑(删除家具和部分内墙) /// private ElementAction DetermineStandardAction(int categoryId) { var removeCategories = new[] { (int)BuiltInCategory.OST_Furniture, // 家具 (int)BuiltInCategory.OST_FurnitureSystems, // 家具系统 (int)BuiltInCategory.OST_Casework, // 橱柜 (int)BuiltInCategory.OST_Entourage, // 配景 (int)BuiltInCategory.OST_LightingFixtures, // 灯具(部分) }; return removeCategories.Contains(categoryId) ? ElementAction.Remove : ElementAction.Keep; } /// /// 激进模式的判断逻辑(删除所有内部元素) /// private ElementAction DetermineAggressiveAction(int categoryId) { var removeCategories = new[] { (int)BuiltInCategory.OST_Furniture, // 家具 (int)BuiltInCategory.OST_FurnitureSystems, // 家具系统 (int)BuiltInCategory.OST_Casework, // 橱柜 (int)BuiltInCategory.OST_Entourage, // 配景 (int)BuiltInCategory.OST_LightingFixtures, // 灯具 (int)BuiltInCategory.OST_ElectricalFixtures, // 电气装置 (int)BuiltInCategory.OST_PlumbingFixtures, // 卫浴装置 (int)BuiltInCategory.OST_MechanicalEquipment, // 机械设备 (int)BuiltInCategory.OST_ElectricalEquipment, // 电气设备 (int)BuiltInCategory.OST_SpecialityEquipment, // 专用设备 (int)BuiltInCategory.OST_Ceilings, // 天花板 (int)BuiltInCategory.OST_GenericModel, // 常规模型(部分) }; return removeCategories.Contains(categoryId) ? ElementAction.Remove : ElementAction.Keep; } /// /// 获取动作的原因说明 /// private string GetActionReason(Element element, ElementAction action, ShellOptimizeMode mode) { var category = element.Category.Id.IntegerValue; if (action == ElementAction.Keep) { if (mode == ShellOptimizeMode.EnvelopeOnly) { if (IsSiteElement(category)) return "场地/地形构件,必须保留"; return "围护构件,必须保留"; } if (IsStructuralElement(category)) return "结构元素,必须保留"; if (IsExteriorElement(element)) return "外围元素,必须保留"; return $"{mode}模式下保留"; } else { if (mode == ShellOptimizeMode.EnvelopeOnly) { if (element is RevitLinkInstance) return "链接模型,必须删除"; return "室内/非围护构件,删除"; } switch (mode) { case ShellOptimizeMode.Conservative: return "装饰元素,保守模式下删除"; case ShellOptimizeMode.Standard: return "内部元素,标准模式下删除"; case ShellOptimizeMode.Aggressive: return "非结构元素,激进模式下删除"; default: return "删除"; } } } /// /// 创建分析摘要 /// private ShellAnalysisSummary CreateAnalysisSummary(List results) { var total = results.Count; var keep = results.Count(r => r.Action == ElementAction.Keep); var remove = results.Count(r => r.Action == ElementAction.Remove); var estimatedReduction = total > 0 ? $"{(remove * 100.0 / total):F1}%" : "0%"; return new ShellAnalysisSummary { TotalElements = total, KeepElements = keep, RemoveElements = remove, EstimatedReduction = estimatedReduction, OriginalSize = "未知", EstimatedOptimizedSize = "未知" }; } /// /// 创建分类统计 /// private List CreateCategoryStatistics(List results) { var categoryGroups = results.GroupBy(r => new { r.CategoryId, r.CategoryName }); var statistics = new List(); foreach (var group in categoryGroups.OrderBy(g => g.Key.CategoryName)) { var total = group.Count(); var keep = group.Count(r => r.Action == ElementAction.Keep); var remove = group.Count(r => r.Action == ElementAction.Remove); statistics.Add(new CategoryStatistics { CategoryId = group.Key.CategoryId, Name = group.Key.CategoryName, Total = total, Keep = keep, Remove = remove }); } return statistics; } } }