添加空间索引格子大小配置,优化动画碰撞检测性能,修复属性设置的线程安全问题

This commit is contained in:
tian 2026-01-14 11:41:09 +08:00
parent c4cf718502
commit fcc87b2cb0
7 changed files with 34 additions and 25 deletions

View File

@ -40,6 +40,9 @@ duration_seconds = 10.0
# 检测间隙(米)
detection_gap_meters = 0.05
# 空间索引格子大小(米)- 用于动画碰撞检测的空间索引,推荐值:车辆宽度
spatial_index_cell_size = 1.0
[logistics]
# 可通行性默认值true
traversable = true

View File

@ -4,8 +4,8 @@
### [2026/1/13]
1. [ ] 优化检查API调用的线程安全问题提高插件的稳定性
2. [ ] 优化减少ClashDetective检测部分的耗时
1. [x] 优化检查API调用的线程安全问题提高插件的稳定性
2. [x] 优化减少ClashDetective检测部分的耗时
### [2026/1/6]

View File

@ -539,11 +539,10 @@ namespace NavisworksTransport.Core.Animation
LogManager.Info("=== 构建全局空间索引 ===");
spatialIndexManager = SpatialIndexManager.Instance;
// 使用传入的车辆宽度参数而不是从ConfigManager读取
double vehicleWidthMeters = _virtualVehicleWidth;
double cellSizeInModelUnits = UnitsConverter.ConvertFromMeters(vehicleWidthMeters);
// 使用动画专用的空间索引格子大小配置
double cellSizeInModelUnits = UnitsConverter.ConvertFromMeters(ConfigManager.Instance.Current.Animation.SpatialIndexCellSize);
LogManager.Info($"[空间索引] 车辆宽度: {vehicleWidthMeters:F2}米 → 格子大小: {cellSizeInModelUnits:F2}模型单位");
LogManager.Info($"[空间索引] 格子大小: {cellSizeInModelUnits:F2}模型单位 (动画配置)");
// 检查空间索引是否需要重新构建(格子大小变化或未初始化)
bool needRebuild = !spatialIndexManager.IsInitialized ||

View File

@ -198,6 +198,7 @@ namespace NavisworksTransport.Core.Config
config.Animation.FrameRate = GetRequiredIntValue(anim, "frame_rate");
config.Animation.DurationSeconds = GetRequiredDoubleValue(anim, "duration_seconds");
config.Animation.DetectionGapMeters = GetRequiredDoubleValue(anim, "detection_gap_meters");
config.Animation.SpatialIndexCellSize = GetRequiredDoubleValue(anim, "spatial_index_cell_size");
// 加载物流属性配置
if (!model.ContainsKey("logistics"))
@ -344,6 +345,7 @@ namespace NavisworksTransport.Core.Config
anim["frame_rate"] = config.Animation.FrameRate;
anim["duration_seconds"] = config.Animation.DurationSeconds;
anim["detection_gap_meters"] = config.Animation.DetectionGapMeters;
anim["spatial_index_cell_size"] = config.Animation.SpatialIndexCellSize;
}
}

View File

@ -127,6 +127,11 @@ namespace NavisworksTransport.Core.Config
/// 检测间隙(米)
/// </summary>
public double DetectionGapMeters { get; set; }
/// <summary>
/// 空间索引格子大小(米)- 用于动画碰撞检测的空间索引
/// </summary>
public double SpatialIndexCellSize { get; set; }
}
/// <summary>

View File

@ -422,7 +422,7 @@ namespace NavisworksTransport.PathPlanning
if (railItems == null || railItems.Count == 0)
{
LogManager.Warning("[空轨] 没有找到设置为空轨属性的模型");
LogManager.Info("[空轨] 没有找到设置为空轨属性的模型");
return 0;
}

View File

@ -586,12 +586,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (result.Success)
{
await RefreshLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
// 重要ApplyVisibilityMode包含Navisworks API调用必须在主线程中执行
ApplyVisibilityMode();
await _uiStateManager.ExecuteUIUpdateAsync(() => ApplyVisibilityMode());
}
}
}
@ -631,8 +631,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var result = await Task.Run(() =>
// 2. 业务逻辑执行(必须在主线程上执行,因为包含 Navisworks COM API 调用
var result = await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
try
{
@ -645,12 +645,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 使用CategoryAttributeManager的RemoveLogisticsAttributes方法
int successCount = CategoryAttributeManager.RemoveLogisticsAttributes(selectedItems);
return new {
Success = successCount > 0,
Count = successCount,
Message = successCount > 0 ?
$"已清除 {successCount} 个元素的物流属性" :
"没有找到可清除的物流属性"
return new {
Success = successCount > 0,
Count = successCount,
Message = successCount > 0 ?
$"已清除 {successCount} 个元素的物流属性" :
"没有找到可清除的物流属性"
};
}
catch (Exception ex)
@ -678,12 +678,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (result.Success)
{
await RefreshLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
// 重要ApplyVisibilityMode包含Navisworks API调用必须在主线程中执行
ApplyVisibilityMode();
await _uiStateManager.ExecuteUIUpdateAsync(() => ApplyVisibilityMode());
}
}
}
@ -721,8 +721,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var result = await Task.Run(() =>
// 2. 业务逻辑执行(必须在主线程上执行,因为包含 Navisworks COM API 调用
var result = await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
try
{
@ -730,12 +730,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var document = NavisApplication.ActiveDocument;
var logisticsItems = CategoryAttributeManager.GetAllLogisticsItems();
var models = new List<LogisticsModel>();
foreach (var item in logisticsItems)
{
// 直接使用 CategoryAttributeManager 的 API
var info = CategoryAttributeManager.GetLogisticsAttributeInfo(item);
var model = new LogisticsModel
{
Name = item.DisplayName ?? "未命名模型",
@ -746,7 +746,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
};
models.Add(model);
}
return new { Success = true, Models = models, Count = models.Count };
}
catch (Exception ex)
@ -1163,7 +1163,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
ShowAllInternal();
}
}, "应用可见性模式");
}, "应用可见性模式", runOnUIThread: true);
}
/// <summary>