769 lines
31 KiB
C#
769 lines
31 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using Autodesk.Revit.DB;
|
||
using Autodesk.Revit.UI;
|
||
using RevitHttpControl.Models;
|
||
|
||
namespace RevitHttpControl.Services
|
||
{
|
||
/// <summary>
|
||
/// Revit API 操作服务
|
||
/// </summary>
|
||
public static class RevitService
|
||
{
|
||
/// <summary>
|
||
/// 获取当前文档信息
|
||
/// </summary>
|
||
/// <returns>当前文档信息</returns>
|
||
public static CurrentDocumentInfo GetCurrentDocumentInfo()
|
||
{
|
||
var documentInfo = new CurrentDocumentInfo
|
||
{
|
||
IsOpen = false,
|
||
FileName = null,
|
||
FilePath = null
|
||
};
|
||
|
||
try
|
||
{
|
||
// 尝试获取当前活动文档信息
|
||
if (App.Instance != null)
|
||
{
|
||
// 通过队列执行获取文档信息的操作
|
||
var docInfoResult = new CurrentDocumentInfo
|
||
{
|
||
IsOpen = false,
|
||
FileName = null,
|
||
FilePath = null
|
||
};
|
||
var completed = false;
|
||
Exception executionException = null;
|
||
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
System.Diagnostics.Debug.WriteLine("RevitService: Getting document info...");
|
||
|
||
var activeDoc = uiApp.ActiveUIDocument?.Document;
|
||
if (activeDoc != null)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Found active document: {activeDoc.Title}");
|
||
|
||
docInfoResult.IsOpen = true;
|
||
|
||
// 处理文档路径
|
||
var pathName = activeDoc.PathName;
|
||
if (!string.IsNullOrEmpty(pathName))
|
||
{
|
||
docInfoResult.FileName = Path.GetFileName(pathName);
|
||
docInfoResult.FilePath = pathName;
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Document path: {pathName}");
|
||
}
|
||
else
|
||
{
|
||
// 对于未保存的文档,使用Title
|
||
docInfoResult.FileName = activeDoc.Title;
|
||
docInfoResult.FilePath = null;
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Unsaved document: {activeDoc.Title}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
System.Diagnostics.Debug.WriteLine("RevitService: No active document found");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Exception getting document info: {ex.Message}");
|
||
executionException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待3秒)
|
||
var timeout = DateTime.Now.AddSeconds(3);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(50);
|
||
}
|
||
|
||
if (!completed)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine("RevitService: Timeout waiting for document info");
|
||
return documentInfo; // 返回默认值
|
||
}
|
||
|
||
if (executionException != null)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Execution failed: {executionException.Message}");
|
||
return documentInfo; // 返回默认值
|
||
}
|
||
|
||
return docInfoResult;
|
||
}
|
||
else
|
||
{
|
||
System.Diagnostics.Debug.WriteLine("RevitService: App.Instance is null");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"RevitService: Outer exception: {ex.Message}");
|
||
}
|
||
|
||
return documentInfo;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元素统计数量
|
||
/// </summary>
|
||
/// <param name="type">统计类型</param>
|
||
/// <returns>元素数量</returns>
|
||
public static int GetElementCount(StatsType type)
|
||
{
|
||
try
|
||
{
|
||
var count = 0;
|
||
var completed = false;
|
||
Exception capturedException = null;
|
||
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc != null)
|
||
{
|
||
var collector = new FilteredElementCollector(doc);
|
||
var category = GetBuiltInCategory(type);
|
||
count = collector.OfCategory(category).Count();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
capturedException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待5秒)
|
||
var timeout = DateTime.Now.AddSeconds(5);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(50);
|
||
}
|
||
|
||
if (capturedException != null)
|
||
throw capturedException;
|
||
|
||
return count;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"获取 {type} 统计数据失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 异步获取元素统计数量
|
||
/// </summary>
|
||
/// <param name="type">统计类型</param>
|
||
/// <param name="taskId">任务ID</param>
|
||
/// <param name="taskManager">任务管理器</param>
|
||
public static void GetElementCountAsync(StatsType type, Guid taskId, TaskManager taskManager)
|
||
{
|
||
try
|
||
{
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc != null)
|
||
{
|
||
var collector = new FilteredElementCollector(doc);
|
||
var category = GetBuiltInCategory(type);
|
||
var count = collector.OfCategory(category).Count();
|
||
|
||
// 构建完整的统计响应
|
||
var statsResponse = new SyncStatsResponse
|
||
{
|
||
ElementType = type.ToString(),
|
||
Count = count,
|
||
Details = new StatsDetails
|
||
{
|
||
TypeName = GetStatsTypeDisplayName(type),
|
||
TypeId = (int)category
|
||
}
|
||
};
|
||
|
||
// 将完整结果存储到任务管理器
|
||
taskManager.CompleteTask(taskId, statsResponse);
|
||
}
|
||
else
|
||
{
|
||
taskManager.FailTask(taskId, "没有打开的文档");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
taskManager.FailTask(taskId, ex.Message);
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
taskManager.FailTask(taskId, ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 统计类型到 BuiltInCategory 的映射
|
||
/// </summary>
|
||
/// <param name="type">统计类型</param>
|
||
/// <returns>对应的 BuiltInCategory</returns>
|
||
public static BuiltInCategory GetBuiltInCategory(StatsType type)
|
||
{
|
||
switch (type)
|
||
{
|
||
case StatsType.Wall:
|
||
return BuiltInCategory.OST_Walls;
|
||
case StatsType.Door:
|
||
return BuiltInCategory.OST_Doors;
|
||
case StatsType.Window:
|
||
return BuiltInCategory.OST_Windows;
|
||
case StatsType.Floor:
|
||
return BuiltInCategory.OST_Floors;
|
||
case StatsType.Ceiling:
|
||
return BuiltInCategory.OST_Ceilings;
|
||
case StatsType.Roof:
|
||
return BuiltInCategory.OST_Roofs;
|
||
case StatsType.Column:
|
||
return BuiltInCategory.OST_Columns;
|
||
case StatsType.Beam:
|
||
return BuiltInCategory.OST_StructuralFraming;
|
||
case StatsType.Furniture:
|
||
return BuiltInCategory.OST_Furniture;
|
||
case StatsType.Room:
|
||
return BuiltInCategory.OST_Rooms;
|
||
default:
|
||
throw new ArgumentException($"不支持的统计类型: {type}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元素统计详细信息
|
||
/// </summary>
|
||
/// <param name="type">统计类型</param>
|
||
/// <returns>详细统计信息</returns>
|
||
public static SyncStatsResponse GetElementStatsDetail(StatsType type)
|
||
{
|
||
try
|
||
{
|
||
var count = 0;
|
||
var completed = false;
|
||
Exception capturedException = null;
|
||
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc != null)
|
||
{
|
||
var collector = new FilteredElementCollector(doc);
|
||
var category = GetBuiltInCategory(type);
|
||
count = collector.OfCategory(category).Count();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
capturedException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待5秒)
|
||
var timeout = DateTime.Now.AddSeconds(5);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(50);
|
||
}
|
||
|
||
if (capturedException != null)
|
||
throw capturedException;
|
||
|
||
// 构建完整的响应
|
||
return new SyncStatsResponse
|
||
{
|
||
ElementType = type.ToString(),
|
||
Count = count,
|
||
Details = new StatsDetails
|
||
{
|
||
TypeName = GetStatsTypeDisplayName(type),
|
||
TypeId = (int)GetBuiltInCategory(type)
|
||
}
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"获取 {type} 统计数据失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取统计类型的中文显示名称
|
||
/// </summary>
|
||
/// <param name="type">统计类型</param>
|
||
/// <returns>中文名称</returns>
|
||
public static string GetStatsTypeDisplayName(StatsType type)
|
||
{
|
||
switch (type)
|
||
{
|
||
case StatsType.Wall:
|
||
return "墙体";
|
||
case StatsType.Door:
|
||
return "门";
|
||
case StatsType.Window:
|
||
return "窗";
|
||
case StatsType.Floor:
|
||
return "楼板";
|
||
case StatsType.Ceiling:
|
||
return "天花板";
|
||
case StatsType.Roof:
|
||
return "屋顶";
|
||
case StatsType.Column:
|
||
return "柱";
|
||
case StatsType.Beam:
|
||
return "梁";
|
||
case StatsType.Furniture:
|
||
return "家具";
|
||
case StatsType.Room:
|
||
return "房间";
|
||
default:
|
||
return type.ToString();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 快速获取模型总览信息
|
||
/// </summary>
|
||
/// <returns>模型总览信息</returns>
|
||
public static ModelOverviewResponse GetModelOverview()
|
||
{
|
||
try
|
||
{
|
||
ModelOverviewResponse overview = null;
|
||
var completed = false;
|
||
Exception capturedException = null;
|
||
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc == null)
|
||
{
|
||
throw new InvalidOperationException("没有打开的文档");
|
||
}
|
||
|
||
// 1. 项目基本信息
|
||
var filePath = doc.IsWorkshared ?
|
||
(doc.GetWorksharingCentralModelPath()?.ToString() ?? "中心文件路径未知") :
|
||
(!string.IsNullOrEmpty(doc.PathName) ? doc.PathName : "未保存");
|
||
|
||
// 获取文件大小
|
||
long fileSizeBytes = 0;
|
||
string fileSizeDisplay = "未知";
|
||
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(doc.PathName) && System.IO.File.Exists(doc.PathName))
|
||
{
|
||
var fileInfo = new System.IO.FileInfo(doc.PathName);
|
||
fileSizeBytes = fileInfo.Length;
|
||
fileSizeDisplay = FormatFileSize(fileSizeBytes);
|
||
}
|
||
else if (doc.IsWorkshared)
|
||
{
|
||
var centralPath = doc.GetWorksharingCentralModelPath();
|
||
if (centralPath != null)
|
||
{
|
||
var centralPathString = centralPath.ToString();
|
||
if (!string.IsNullOrEmpty(centralPathString) && System.IO.File.Exists(centralPathString))
|
||
{
|
||
var fileInfo = new System.IO.FileInfo(centralPathString);
|
||
fileSizeBytes = fileInfo.Length;
|
||
fileSizeDisplay = FormatFileSize(fileSizeBytes);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
fileSizeDisplay = "未保存";
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
fileSizeDisplay = "无法获取";
|
||
}
|
||
|
||
var projectInfo = new Models.ProjectInfo
|
||
{
|
||
Name = string.IsNullOrEmpty(doc.Title) ? "未命名项目" : doc.Title,
|
||
FilePath = filePath,
|
||
RevitVersion = uiApp.Application.VersionName,
|
||
IsCentralFile = doc.IsWorkshared,
|
||
Status = doc.IsModified ? "已修改" : "已保存",
|
||
FileSizeBytes = fileSizeBytes,
|
||
FileSizeDisplay = fileSizeDisplay
|
||
};
|
||
|
||
// 2. 快速统计主要构件(批量获取避免多次调用)
|
||
var elementCounts = new ElementCounts
|
||
{
|
||
Walls = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).Count(),
|
||
Doors = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Doors).Count(),
|
||
Windows = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Windows).Count(),
|
||
Floors = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors).Count(),
|
||
Ceilings = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Ceilings).Count(),
|
||
Columns = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Columns).Count(),
|
||
Beams = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).Count(),
|
||
Rooms = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).Count()
|
||
};
|
||
|
||
// 3. 模型组织结构信息
|
||
var structure = new ModelStructure
|
||
{
|
||
Levels = new FilteredElementCollector(doc).OfClass(typeof(Level)).Count(),
|
||
FloorPlans = new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).Count(),
|
||
Views3D = new FilteredElementCollector(doc).OfClass(typeof(View3D)).Count(),
|
||
Elevations = new FilteredElementCollector(doc).OfClass(typeof(View))
|
||
.Cast<View>().Count(v => v.ViewType == ViewType.Elevation),
|
||
Sections = new FilteredElementCollector(doc).OfClass(typeof(ViewSection)).Count(),
|
||
Sheets = new FilteredElementCollector(doc).OfClass(typeof(ViewSheet)).Count()
|
||
};
|
||
|
||
// 4. 模型层级信息
|
||
var hierarchy = new ModelHierarchy
|
||
{
|
||
Levels = new List<LevelInfo>(),
|
||
Groups = new FilteredElementCollector(doc).OfClass(typeof(Group)).Count(),
|
||
Worksets = doc.IsWorkshared ? new FilteredWorksetCollector(doc).Count() : 0,
|
||
Phases = new FilteredElementCollector(doc).OfClass(typeof(Phase)).Count(),
|
||
DesignOptions = new FilteredElementCollector(doc).OfClass(typeof(DesignOption)).Count()
|
||
};
|
||
|
||
// 获取楼层详细信息
|
||
var levels = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(Level))
|
||
.Cast<Level>()
|
||
.OrderBy(l => l.Elevation)
|
||
.ToList();
|
||
|
||
foreach (var level in levels)
|
||
{
|
||
hierarchy.Levels.Add(new LevelInfo
|
||
{
|
||
Name = level.Name,
|
||
Elevation = level.Elevation * 304.8 // 转换为毫米
|
||
});
|
||
}
|
||
|
||
// 5. 链接文件统计
|
||
var links = new LinkFiles
|
||
{
|
||
RevitLinks = new LinkCategory(),
|
||
CadLinks = new LinkCategory(),
|
||
PointClouds = 0,
|
||
Images = 0
|
||
};
|
||
|
||
// Revit链接统计
|
||
// 使用OfClass确保只获取RevitLinkInstance类型的元素
|
||
var revitLinkInstances = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(RevitLinkInstance))
|
||
.Cast<RevitLinkInstance>();
|
||
|
||
links.RevitLinks.Total = revitLinkInstances.Count();
|
||
links.RevitLinks.Loaded = revitLinkInstances.Count(link => link.GetLinkDocument() != null);
|
||
links.RevitLinks.Unloaded = links.RevitLinks.Total - links.RevitLinks.Loaded;
|
||
|
||
// CAD链接统计
|
||
var cadLinkTypes = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(CADLinkType))
|
||
.Cast<CADLinkType>();
|
||
|
||
links.CadLinks.Total = cadLinkTypes.Count();
|
||
|
||
// CAD链接状态检查(通过实例检查)
|
||
var cadInstances = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(ImportInstance))
|
||
.Cast<ImportInstance>();
|
||
|
||
var loadedCadCount = 0;
|
||
foreach (var cadType in cadLinkTypes)
|
||
{
|
||
var hasInstance = cadInstances.Any(inst => inst.GetTypeId() == cadType.Id);
|
||
if (hasInstance) loadedCadCount++;
|
||
}
|
||
|
||
links.CadLinks.Loaded = loadedCadCount;
|
||
links.CadLinks.Unloaded = links.CadLinks.Total - links.CadLinks.Loaded;
|
||
|
||
// 点云链接
|
||
links.PointClouds = new FilteredElementCollector(doc)
|
||
.OfCategory(BuiltInCategory.OST_PointClouds).Count();
|
||
|
||
// 图像链接
|
||
links.Images = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(ImageType)).Count();
|
||
|
||
// 生成链接文件总结
|
||
var totalLinks = links.RevitLinks.Total + links.CadLinks.Total + links.PointClouds + links.Images;
|
||
var loadedLinks = links.RevitLinks.Loaded + links.CadLinks.Loaded + links.PointClouds + links.Images;
|
||
links.Summary = totalLinks > 0 ?
|
||
$"{totalLinks}个链接文件,{loadedLinks}个已加载" :
|
||
"无链接文件";
|
||
|
||
// 组装总览响应
|
||
overview = new ModelOverviewResponse
|
||
{
|
||
Project = projectInfo,
|
||
Elements = elementCounts,
|
||
Structure = structure,
|
||
Hierarchy = hierarchy,
|
||
Links = links,
|
||
GeneratedAt = DateTime.Now
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
capturedException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待10秒,因为信息较多)
|
||
var timeout = DateTime.Now.AddSeconds(10);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(50);
|
||
}
|
||
|
||
if (capturedException != null)
|
||
throw capturedException;
|
||
|
||
if (!completed)
|
||
throw new TimeoutException("获取模型总览信息超时");
|
||
|
||
return overview;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"获取模型总览失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 格式化文件大小显示
|
||
/// </summary>
|
||
/// <param name="bytes">文件大小(字节)</param>
|
||
/// <returns>格式化的文件大小字符串</returns>
|
||
private static string FormatFileSize(long bytes)
|
||
{
|
||
const long KB = 1024;
|
||
const long MB = KB * 1024;
|
||
const long GB = MB * 1024;
|
||
|
||
if (bytes >= GB)
|
||
{
|
||
return $"{bytes / (double)GB:F1} GB";
|
||
}
|
||
else if (bytes >= MB)
|
||
{
|
||
return $"{bytes / (double)MB:F1} MB";
|
||
}
|
||
else if (bytes >= KB)
|
||
{
|
||
return $"{bytes / (double)KB:F1} KB";
|
||
}
|
||
else
|
||
{
|
||
return $"{bytes} 字节";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分析薄壳优化方案
|
||
/// </summary>
|
||
/// <param name="mode">优化模式</param>
|
||
/// <returns>分析结果</returns>
|
||
public static ShellAnalyzeResponse AnalyzeShellOptimization(ShellOptimizeMode mode)
|
||
{
|
||
ShellAnalyzeResponse result = null;
|
||
Exception capturedException = null;
|
||
bool completed = false;
|
||
|
||
try
|
||
{
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc == null)
|
||
throw new InvalidOperationException("没有打开的Revit文档");
|
||
|
||
var analyzer = new ShellAnalyzer();
|
||
result = analyzer.AnalyzeModel(doc, mode);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
capturedException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待30秒,分析可能需要较长时间)
|
||
var timeout = DateTime.Now.AddSeconds(30);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(100);
|
||
}
|
||
|
||
if (capturedException != null)
|
||
throw capturedException;
|
||
|
||
if (!completed)
|
||
throw new TimeoutException("薄壳分析超时");
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"薄壳分析失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行薄壳优化(同步)
|
||
/// </summary>
|
||
/// <param name="mode">优化模式</param>
|
||
/// <param name="backupOriginal">是否备份原文件</param>
|
||
/// <returns>执行结果</returns>
|
||
public static ShellOptimizeResult ExecuteShellOptimization(ShellOptimizeMode mode, bool backupOriginal = true)
|
||
{
|
||
ShellOptimizeResult result = null;
|
||
Exception capturedException = null;
|
||
bool completed = false;
|
||
|
||
try
|
||
{
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc == null)
|
||
throw new InvalidOperationException("没有打开的Revit文档");
|
||
|
||
var optimizer = new ShellOptimizer();
|
||
result = optimizer.ExecuteOptimization(doc, mode, backupOriginal);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
capturedException = ex;
|
||
}
|
||
finally
|
||
{
|
||
completed = true;
|
||
}
|
||
});
|
||
|
||
// 等待命令执行完成(最多等待5分钟,删除操作可能需要较长时间)
|
||
var timeout = DateTime.Now.AddMinutes(5);
|
||
while (!completed && DateTime.Now < timeout)
|
||
{
|
||
System.Threading.Thread.Sleep(200);
|
||
}
|
||
|
||
if (capturedException != null)
|
||
throw capturedException;
|
||
|
||
if (!completed)
|
||
throw new TimeoutException("薄壳优化执行超时");
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"薄壳优化执行失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行薄壳优化(异步)
|
||
/// </summary>
|
||
/// <param name="mode">优化模式</param>
|
||
/// <param name="backupOriginal">是否备份原文件</param>
|
||
/// <param name="taskId">任务ID</param>
|
||
/// <param name="taskManager">任务管理器</param>
|
||
public static void ExecuteShellOptimizationAsync(ShellOptimizeMode mode, bool backupOriginal, Guid taskId, TaskManager taskManager)
|
||
{
|
||
try
|
||
{
|
||
App.Instance.EnqueueCommand(uiApp =>
|
||
{
|
||
try
|
||
{
|
||
var doc = uiApp.ActiveUIDocument?.Document;
|
||
if (doc == null)
|
||
{
|
||
taskManager.FailTask(taskId, "没有打开的Revit文档");
|
||
return;
|
||
}
|
||
|
||
var optimizer = new ShellOptimizer();
|
||
|
||
// 更新任务状态为进行中
|
||
taskManager.SetTaskRunning(taskId);
|
||
|
||
// 执行优化
|
||
var result = optimizer.ExecuteOptimization(doc, mode, backupOriginal);
|
||
|
||
// 设置任务完成
|
||
taskManager.CompleteTask(taskId, result);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
taskManager.FailTask(taskId, $"薄壳优化执行失败: {ex.Message}");
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
taskManager.FailTask(taskId, $"启动薄壳优化任务失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|