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;
}
}
}