修复分层预览功能中深度遍历逻辑不统一的问题
## 主要修复内容: ### 1. 创建统一的深度遍历核心函数 - 新增 GetItemsByDepthUnified() 方法实现精确的深度控制 - 确保所有策略使用相同的深度遍历逻辑 - 消除不同策略间深度处理的差异 ### 2. 重构分层策略架构 - 引入 IGroupingStrategy 接口统一所有分层策略 - 创建 FloorDetectionStrategy、FloorAttributeStrategy、ZoneAttributeStrategy、SubSystemAttributeStrategy - 所有策略现在接收完全相同的模型项集合 ### 3. 修复智能楼层检测策略 - 新增 FloorDetector.DetectFloorsFromGivenItems() 方法 - FloorDetectionStrategy 不再依赖 FloorDetector 内部的深度逻辑 - 确保智能楼层检测使用与属性策略相同的模型项集合 ### 4. 统一缓存和进度处理 - 更新缓存键生成使用统一的深度遍历函数 - 为所有策略添加详细的调试日志 - 标记所有分组项使用了统一深度遍历 ## 解决的问题: - 深度1级:现在所有策略基于相同的第一级节点集合 - 深度2级:现在所有策略基于相同的第一+二级节点集合 - 深度3级:现在所有策略基于相同的第一+二+三级节点集合 - 全部深度:现在所有策略基于相同的完整节点集合 ## 预期结果: 当用户在二级节点设置3个不同属性值时,所有深度设置下的分层结果将完全一致。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0de9de617f
commit
ad86c2ab76
Binary file not shown.
@ -24,8 +24,231 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public enum SplitStrategy
|
||||
{
|
||||
ByFloor, // 智能检测楼层
|
||||
ByCustomFloor // 按自定义分层
|
||||
BySmartFloorDetection, // 智能检测楼层(原ByFloor)
|
||||
ByFloorAttribute, // 按楼层属性(原ByCustomFloor)
|
||||
ByZoneAttribute, // 按区域属性
|
||||
BySubSystemAttribute // 按子系统属性
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分层分组策略接口
|
||||
/// </summary>
|
||||
private interface IGroupingStrategy
|
||||
{
|
||||
string GroupTypeName { get; }
|
||||
string UnclassifiedLabel { get; }
|
||||
Dictionary<string, GroupItem> GroupItems(ModelItemCollection items, SplitConfiguration config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分组项信息
|
||||
/// </summary>
|
||||
private class GroupItem
|
||||
{
|
||||
public string GroupName { get; set; }
|
||||
public string OriginalName { get; set; }
|
||||
public List<ModelItem> Items { get; set; } = new List<ModelItem>();
|
||||
public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 楼层检测分组策略 - 使用统一的深度遍历结果
|
||||
/// </summary>
|
||||
private class FloorDetectionStrategy : IGroupingStrategy
|
||||
{
|
||||
private readonly FloorDetector _floorDetector;
|
||||
|
||||
public string GroupTypeName => "楼层";
|
||||
public string UnclassifiedLabel => "未检测到楼层";
|
||||
|
||||
public FloorDetectionStrategy(FloorDetector floorDetector)
|
||||
{
|
||||
_floorDetector = floorDetector;
|
||||
}
|
||||
|
||||
public Dictionary<string, GroupItem> GroupItems(ModelItemCollection items, SplitConfiguration config)
|
||||
{
|
||||
var result = new Dictionary<string, GroupItem>();
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[FloorDetectionStrategy] 开始智能楼层检测,输入模型项数={items?.Count ?? 0}");
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
LogManager.Warning("[FloorDetectionStrategy] 输入模型项集合为空");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 关键修复:直接使用传入的items,不再让FloorDetector重新获取深度项
|
||||
// 调用 FloorDetector,但传入 maxDepth = 0 来强制使用传入的items
|
||||
var floors = _floorDetector.DetectFloorsFromGivenItems(items, null);
|
||||
|
||||
LogManager.Info($"[FloorDetectionStrategy] FloorDetector检测完成,发现 {floors?.Count ?? 0} 个楼层");
|
||||
|
||||
if (floors != null && floors.Count > 0)
|
||||
{
|
||||
foreach (var floor in floors)
|
||||
{
|
||||
result[floor.FloorName] = new GroupItem
|
||||
{
|
||||
GroupName = floor.FloorName,
|
||||
OriginalName = floor.FloorName,
|
||||
Items = floor.Items?.ToList() ?? new List<ModelItem>(),
|
||||
Metadata = new Dictionary<string, object>
|
||||
{
|
||||
["OriginalFloorName"] = floor.FloorName,
|
||||
["FloorName"] = floor.FloorName,
|
||||
["Elevation"] = floor.Elevation,
|
||||
["DetectionMethod"] = "Floor",
|
||||
["ItemsFromUnifiedDepth"] = true // 标记使用了统一深度遍历
|
||||
}
|
||||
};
|
||||
|
||||
LogManager.Info($"[FloorDetectionStrategy] 楼层 '{floor.FloorName}' 包含 {floor.Items?.Count ?? 0} 个模型项");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[FloorDetectionStrategy] 未检测到任何楼层信息");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[FloorDetectionStrategy] 楼层检测异常: {ex.Message}");
|
||||
}
|
||||
|
||||
LogManager.Info($"[FloorDetectionStrategy] 楼层检测完成,返回 {result.Count} 个楼层分组");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 属性分组策略基类
|
||||
/// </summary>
|
||||
private abstract class AttributeGroupingStrategy : IGroupingStrategy
|
||||
{
|
||||
protected readonly FloorAttributeManager _floorManager;
|
||||
|
||||
public abstract string GroupTypeName { get; }
|
||||
public abstract string UnclassifiedLabel { get; }
|
||||
|
||||
protected AttributeGroupingStrategy()
|
||||
{
|
||||
_floorManager = new FloorAttributeManager();
|
||||
}
|
||||
|
||||
protected abstract string GetAttributeValue(ModelItem item);
|
||||
|
||||
public Dictionary<string, GroupItem> GroupItems(ModelItemCollection items, SplitConfiguration config)
|
||||
{
|
||||
var result = new Dictionary<string, GroupItem>();
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[{GroupTypeName}AttributeStrategy] 开始属性分组,输入模型项数={items?.Count ?? 0},深度={config?.MaxDepth ?? -1}");
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
LogManager.Warning($"[{GroupTypeName}AttributeStrategy] 输入模型项集合为空");
|
||||
return result;
|
||||
}
|
||||
|
||||
int processedCount = 0;
|
||||
var attributeValueCounts = new Dictionary<string, int>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
try
|
||||
{
|
||||
processedCount++;
|
||||
string attributeValue = GetAttributeValue(item);
|
||||
string groupKey = string.IsNullOrEmpty(attributeValue) ? UnclassifiedLabel : attributeValue;
|
||||
|
||||
// 统计属性值分布
|
||||
if (!attributeValueCounts.ContainsKey(groupKey))
|
||||
attributeValueCounts[groupKey] = 0;
|
||||
attributeValueCounts[groupKey]++;
|
||||
|
||||
if (!result.ContainsKey(groupKey))
|
||||
{
|
||||
result[groupKey] = new GroupItem
|
||||
{
|
||||
GroupName = groupKey,
|
||||
OriginalName = attributeValue ?? UnclassifiedLabel,
|
||||
Metadata = new Dictionary<string, object>
|
||||
{
|
||||
["DetectionMethod"] = GroupTypeName + "Attribute",
|
||||
["ItemsFromUnifiedDepth"] = true, // 标记使用了统一深度遍历
|
||||
["MaxDepth"] = config?.MaxDepth ?? -1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
result[groupKey].Items.Add(item);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[{GroupTypeName}AttributeStrategy] 处理单个模型项时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 记录属性值分布
|
||||
LogManager.Info($"[{GroupTypeName}AttributeStrategy] 处理完成,共处理{processedCount}个模型项,发现{result.Count}个{GroupTypeName}分组");
|
||||
foreach (var kvp in attributeValueCounts.OrderByDescending(x => x.Value))
|
||||
{
|
||||
LogManager.Info($"[{GroupTypeName}AttributeStrategy] {GroupTypeName}分组 '{kvp.Key}': {kvp.Value} 个模型项");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[{GroupTypeName}AttributeStrategy] 属性分组异常: {ex.Message}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 楼层属性分组策略
|
||||
/// </summary>
|
||||
private class FloorAttributeStrategy : AttributeGroupingStrategy
|
||||
{
|
||||
public override string GroupTypeName => "楼层";
|
||||
public override string UnclassifiedLabel => "未设置楼层";
|
||||
|
||||
protected override string GetAttributeValue(ModelItem item)
|
||||
{
|
||||
return _floorManager.GetFloorLevel(item, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 区域属性分组策略
|
||||
/// </summary>
|
||||
private class ZoneAttributeStrategy : AttributeGroupingStrategy
|
||||
{
|
||||
public override string GroupTypeName => "区域";
|
||||
public override string UnclassifiedLabel => "未设置区域";
|
||||
|
||||
protected override string GetAttributeValue(ModelItem item)
|
||||
{
|
||||
return _floorManager.GetZoneAttribute(item, true); // 启用继承查询
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 子系统属性分组策略
|
||||
/// </summary>
|
||||
private class SubSystemAttributeStrategy : AttributeGroupingStrategy
|
||||
{
|
||||
public override string GroupTypeName => "子系统";
|
||||
public override string UnclassifiedLabel => "未设置子系统";
|
||||
|
||||
protected override string GetAttributeValue(ModelItem item)
|
||||
{
|
||||
return _floorManager.GetSubSystemAttribute(item, true); // 启用继承查询
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -36,7 +259,7 @@ namespace NavisworksTransport
|
||||
/// <summary>
|
||||
/// 分层策略
|
||||
/// </summary>
|
||||
public SplitStrategy Strategy { get; set; } = SplitStrategy.ByFloor;
|
||||
public SplitStrategy Strategy { get; set; } = SplitStrategy.BySmartFloorDetection;
|
||||
|
||||
/// <summary>
|
||||
/// 属性名称(用于自定义分层时使用)
|
||||
@ -261,11 +484,17 @@ namespace NavisworksTransport
|
||||
|
||||
switch (config.Strategy)
|
||||
{
|
||||
case SplitStrategy.ByFloor:
|
||||
previewResults = PreviewSplitByFloor(allItems, config);
|
||||
case SplitStrategy.BySmartFloorDetection:
|
||||
previewResults = PreviewSplitByAttribute(allItems, config, new FloorDetectionStrategy(_floorDetector));
|
||||
break;
|
||||
case SplitStrategy.ByCustomFloor:
|
||||
previewResults = PreviewSplitByCustomFloor(allItems, config);
|
||||
case SplitStrategy.ByFloorAttribute:
|
||||
previewResults = PreviewSplitByAttribute(allItems, config, new FloorAttributeStrategy());
|
||||
break;
|
||||
case SplitStrategy.ByZoneAttribute:
|
||||
previewResults = PreviewSplitByAttribute(allItems, config, new ZoneAttributeStrategy());
|
||||
break;
|
||||
case SplitStrategy.BySubSystemAttribute:
|
||||
previewResults = PreviewSplitByAttribute(allItems, config, new SubSystemAttributeStrategy());
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"不支持的分层策略: {config.Strategy}");
|
||||
@ -298,12 +527,12 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成缓存键
|
||||
/// 生成缓存键 - 使用统一的深度遍历
|
||||
/// </summary>
|
||||
private string GenerateCacheKey(SplitConfiguration config)
|
||||
{
|
||||
return $"{config.Strategy}_{config.MaxDepth}_{config.AttributeName ?? "Floor"}_" +
|
||||
$"{GetAllModelItems(config.MaxDepth).Count}";
|
||||
$"{GetItemsByDepthUnified(config.MaxDepth).Count}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -526,189 +755,172 @@ namespace NavisworksTransport
|
||||
#region 私有方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有模型元素(支持深度限制)
|
||||
/// 统一的深度遍历核心函数 - 精确控制深度逻辑
|
||||
/// </summary>
|
||||
private ModelItemCollection GetAllModelItems(int maxDepth = 1)
|
||||
/// <param name="maxDepth">最大深度,1=仅第一级,2=到第二级,3=到第三级,0=所有级别</param>
|
||||
/// <returns>按深度筛选的模型项集合</returns>
|
||||
private ModelItemCollection GetItemsByDepthUnified(int maxDepth)
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document?.Models?.Count == 0)
|
||||
{
|
||||
return new ModelItemCollection();
|
||||
}
|
||||
|
||||
ModelItemCollection allItems;
|
||||
|
||||
if (maxDepth <= 0)
|
||||
{
|
||||
// 如果maxDepth为0或负数,获取所有项
|
||||
allItems = new ModelItemCollection();
|
||||
allItems.AddRange(document.Models.RootItemDescendantsAndSelf);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 获取到 {allItems.Count} 个模型元素(所有级别)");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 直接使用FloorDetector的高效深度遍历,不需要先获取所有元素
|
||||
var floorDetector = new FloorDetector();
|
||||
allItems = floorDetector.GetItemsByDepth(null, maxDepth); // 传null,方法内部会直接从document获取
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 获取到 {allItems.Count} 个模型元素(深度限制:{maxDepth}级)");
|
||||
}
|
||||
|
||||
return allItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按楼层预览分层(带进度报告)
|
||||
/// </summary>
|
||||
private List<SplitPreviewResult> PreviewSplitByFloor(ModelItemCollection items, SplitConfiguration config)
|
||||
{
|
||||
var results = new List<SplitPreviewResult>();
|
||||
|
||||
try
|
||||
{
|
||||
// 楼层检测阶段 (35-70%)
|
||||
OnProgressChanged(new ProgressChangedEventArgs(40, $"正在检测 {items.Count} 个模型元素的楼层信息"));
|
||||
LogManager.Info($"[SimplifiedModelSplitter] ===== GetItemsByDepthUnified开始 ===== maxDepth={maxDepth}");
|
||||
|
||||
var floors = _floorDetector.DetectFloors(items, null, config.MaxDepth);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 按楼层检测完成,使用深度: {config.MaxDepth},发现 {floors?.Count ?? 0} 个楼层");
|
||||
|
||||
OnProgressChanged(new ProgressChangedEventArgs(70, $"楼层检测完成,发现 {floors?.Count ?? 0} 个楼层"));
|
||||
|
||||
if (floors != null && floors.Count > 0)
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document?.Models?.Count == 0)
|
||||
{
|
||||
// 生成预览结果阶段 (70-85%)
|
||||
OnProgressChanged(new ProgressChangedEventArgs(75, "正在生成楼层预览结果"));
|
||||
|
||||
int processedFloors = 0;
|
||||
foreach (var floor in floors)
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 当前文档没有模型");
|
||||
return new ModelItemCollection();
|
||||
}
|
||||
|
||||
var result = new ModelItemCollection();
|
||||
|
||||
if (maxDepth <= 0)
|
||||
{
|
||||
// 深度为0表示包含所有级别
|
||||
result.AddRange(document.Models.RootItemDescendantsAndSelf);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] maxDepth=0,返回所有级别的项,共{result.Count}个");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 从文档的根模型开始精确的深度遍历
|
||||
foreach (Model model in document.Models)
|
||||
{
|
||||
if (model.RootItem != null)
|
||||
{
|
||||
var previewResult = new SplitPreviewResult
|
||||
// 添加第一级节点(模型根的直接子节点)
|
||||
if (maxDepth >= 1)
|
||||
{
|
||||
LayerName = SanitizeLayerName(floor.FloorName),
|
||||
ItemCount = floor.ItemCount,
|
||||
EstimatedFileSize = EstimateFileSize(floor.ItemCount),
|
||||
Status = "就绪",
|
||||
Items = new ModelItemCollection()
|
||||
};
|
||||
|
||||
// 复制ModelItem集合
|
||||
if (floor.Items != null && floor.Items.Count > 0)
|
||||
{
|
||||
previewResult.Items.AddRange(floor.Items);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 楼层预览结果已缓存模型项: 楼层='{previewResult.LayerName}', 原始名称='{floor.FloorName}', 模型项数量={previewResult.Items.Count}");
|
||||
foreach (ModelItem firstLevelItem in model.RootItem.Children)
|
||||
{
|
||||
result.Add(firstLevelItem);
|
||||
|
||||
// 递归添加更深层次的节点
|
||||
AddChildrenToDepth(firstLevelItem, result, 2, maxDepth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"[SimplifiedModelSplitter] 楼层预览结果没有模型项: 楼层='{previewResult.LayerName}', 原始名称='{floor.FloorName}'");
|
||||
}
|
||||
|
||||
// 添加元数据 - 保存原始名称用于后续匹配
|
||||
previewResult.Metadata["OriginalFloorName"] = floor.FloorName; // 保存原始楼层名称
|
||||
previewResult.Metadata["FloorName"] = floor.FloorName;
|
||||
previewResult.Metadata["Elevation"] = floor.Elevation;
|
||||
previewResult.Metadata["DetectionMethod"] = "Floor";
|
||||
previewResult.Metadata["MaxDepth"] = config.MaxDepth;
|
||||
|
||||
results.Add(previewResult);
|
||||
|
||||
// 更新进度
|
||||
processedFloors++;
|
||||
int progressPercent = 75 + (processedFloors * 10 / floors.Count);
|
||||
OnProgressChanged(new ProgressChangedEventArgs(progressPercent,
|
||||
$"已处理 {processedFloors}/{floors.Count} 个楼层"));
|
||||
}
|
||||
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, $"楼层预览结果生成完成,共 {results.Count} 个分层"));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, "未检测到楼层信息"));
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 未检测到任何楼层信息");
|
||||
}
|
||||
|
||||
LogManager.Info($"[SimplifiedModelSplitter] ===== GetItemsByDepthUnified完成 ===== 返回{result.Count}个模型项(深度:{maxDepth}级)");
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[SimplifiedModelSplitter] 按楼层预览失败: {ex.Message}");
|
||||
OnProgressChanged(new ProgressChangedEventArgs(35, $"楼层分析失败: {ex.Message}"));
|
||||
throw;
|
||||
LogManager.Error($"[SimplifiedModelSplitter] GetItemsByDepthUnified异常: {ex.Message}");
|
||||
return new ModelItemCollection();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按自定义楼层预览分层(基于FloorAttributeManager)
|
||||
/// 递归添加子节点到指定深度
|
||||
/// </summary>
|
||||
private List<SplitPreviewResult> PreviewSplitByCustomFloor(ModelItemCollection items, SplitConfiguration config)
|
||||
/// <param name="parentItem">父节点</param>
|
||||
/// <param name="result">结果集合</param>
|
||||
/// <param name="currentDepth">当前深度</param>
|
||||
/// <param name="maxDepth">最大深度</param>
|
||||
private void AddChildrenToDepth(ModelItem parentItem, ModelItemCollection result, int currentDepth, int maxDepth)
|
||||
{
|
||||
if (currentDepth > maxDepth || parentItem?.Children == null)
|
||||
return;
|
||||
|
||||
foreach (ModelItem child in parentItem.Children)
|
||||
{
|
||||
result.Add(child);
|
||||
|
||||
// 如果还没有达到最大深度,继续遍历子项
|
||||
if (currentDepth < maxDepth)
|
||||
{
|
||||
AddChildrenToDepth(child, result, currentDepth + 1, maxDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有模型元素(支持深度限制)- 使用统一的深度遍历函数
|
||||
/// </summary>
|
||||
private ModelItemCollection GetAllModelItems(int maxDepth = 1)
|
||||
{
|
||||
return GetItemsByDepthUnified(maxDepth);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通用属性预览分层方法(基于分组策略模式)
|
||||
/// </summary>
|
||||
private List<SplitPreviewResult> PreviewSplitByAttribute(ModelItemCollection items, SplitConfiguration config, IGroupingStrategy strategy)
|
||||
{
|
||||
var results = new List<SplitPreviewResult>();
|
||||
|
||||
try
|
||||
{
|
||||
// 初始化FloorAttributeManager
|
||||
OnProgressChanged(new ProgressChangedEventArgs(40, $"正在分析 {items.Count} 个模型元素的自定义楼层信息"));
|
||||
// 属性分组阶段 (35-70%)
|
||||
OnProgressChanged(new ProgressChangedEventArgs(40, $"正在分析 {items.Count} 个模型元素的{strategy.GroupTypeName}信息"));
|
||||
|
||||
var floorManager = new FloorAttributeManager();
|
||||
var floorGroups = floorManager.GetFloorGroups();
|
||||
var groups = strategy.GroupItems(items, config);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] {strategy.GroupTypeName}属性检测完成,发现 {groups?.Count ?? 0} 个{strategy.GroupTypeName}分组");
|
||||
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 自定义楼层检测完成,发现 {floorGroups?.Count ?? 0} 个楼层分组");
|
||||
OnProgressChanged(new ProgressChangedEventArgs(70, $"{strategy.GroupTypeName}分组完成,发现 {groups?.Count ?? 0} 个{strategy.GroupTypeName}"));
|
||||
|
||||
OnProgressChanged(new ProgressChangedEventArgs(70, $"楼层分组完成,发现 {floorGroups?.Count ?? 0} 个楼层"));
|
||||
|
||||
if (floorGroups != null && floorGroups.Count > 0)
|
||||
if (groups != null && groups.Count > 0)
|
||||
{
|
||||
// 生成预览结果阶段 (70-85%)
|
||||
OnProgressChanged(new ProgressChangedEventArgs(75, "正在生成自定义楼层预览结果"));
|
||||
OnProgressChanged(new ProgressChangedEventArgs(75, $"正在生成{strategy.GroupTypeName}预览结果"));
|
||||
|
||||
int processedGroups = 0;
|
||||
foreach (var floorGroup in floorGroups)
|
||||
foreach (var group in groups.Values)
|
||||
{
|
||||
var previewResult = new SplitPreviewResult
|
||||
{
|
||||
LayerName = SanitizeLayerName(floorGroup.Key),
|
||||
ItemCount = floorGroup.Value.Count,
|
||||
EstimatedFileSize = EstimateFileSize(floorGroup.Value.Count),
|
||||
LayerName = SanitizeLayerName(group.GroupName),
|
||||
ItemCount = group.Items.Count,
|
||||
EstimatedFileSize = EstimateFileSize(group.Items.Count),
|
||||
Status = "就绪",
|
||||
Items = new ModelItemCollection()
|
||||
};
|
||||
|
||||
// 添加模型项到集合中
|
||||
if (floorGroup.Value != null && floorGroup.Value.Count > 0)
|
||||
if (group.Items != null && group.Items.Count > 0)
|
||||
{
|
||||
previewResult.Items.AddRange(floorGroup.Value);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] 自定义楼层预览结果已缓存模型项: 楼层='{previewResult.LayerName}', 模型项数量={previewResult.Items.Count}");
|
||||
previewResult.Items.AddRange(group.Items);
|
||||
LogManager.Info($"[SimplifiedModelSplitter] {strategy.GroupTypeName}预览结果已缓存模型项: {strategy.GroupTypeName}='{previewResult.LayerName}', 模型项数量={previewResult.Items.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"[SimplifiedModelSplitter] 自定义楼层预览结果没有模型项: 楼层='{previewResult.LayerName}'");
|
||||
LogManager.Warning($"[SimplifiedModelSplitter] {strategy.GroupTypeName}预览结果没有模型项: {strategy.GroupTypeName}='{previewResult.LayerName}'");
|
||||
}
|
||||
|
||||
// 添加元数据
|
||||
previewResult.Metadata["OriginalFloorName"] = floorGroup.Key;
|
||||
previewResult.Metadata["FloorName"] = floorGroup.Key;
|
||||
previewResult.Metadata["DetectionMethod"] = "CustomFloor";
|
||||
previewResult.Metadata["Original" + strategy.GroupTypeName + "Name"] = group.OriginalName;
|
||||
previewResult.Metadata[strategy.GroupTypeName + "Name"] = group.GroupName;
|
||||
previewResult.Metadata["MaxDepth"] = config.MaxDepth;
|
||||
|
||||
// 复制分组的自定义元数据
|
||||
foreach (var meta in group.Metadata)
|
||||
{
|
||||
previewResult.Metadata[meta.Key] = meta.Value;
|
||||
}
|
||||
|
||||
results.Add(previewResult);
|
||||
|
||||
// 更新进度
|
||||
processedGroups++;
|
||||
int progressPercent = 75 + (processedGroups * 10 / floorGroups.Count);
|
||||
int progressPercent = 75 + (processedGroups * 10 / groups.Count);
|
||||
OnProgressChanged(new ProgressChangedEventArgs(progressPercent,
|
||||
$"已处理 {processedGroups}/{floorGroups.Count} 个楼层分组"));
|
||||
$"已处理 {processedGroups}/{groups.Count} 个{strategy.GroupTypeName}分组"));
|
||||
}
|
||||
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, $"自定义楼层预览结果生成完成,共 {results.Count} 个分层"));
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, $"{strategy.GroupTypeName}预览结果生成完成,共 {results.Count} 个分层"));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, "未检测到自定义楼层信息"));
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 未检测到任何自定义楼层信息");
|
||||
OnProgressChanged(new ProgressChangedEventArgs(85, $"未检测到{strategy.GroupTypeName}信息"));
|
||||
LogManager.Warning($"[SimplifiedModelSplitter] 未检测到任何{strategy.GroupTypeName}信息");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[SimplifiedModelSplitter] 按自定义楼层预览失败: {ex.Message}", ex);
|
||||
OnProgressChanged(new ProgressChangedEventArgs(35, $"自定义楼层分析失败: {ex.Message}"));
|
||||
LogManager.Error($"[SimplifiedModelSplitter] 按{strategy.GroupTypeName}属性预览失败: {ex.Message}", ex);
|
||||
OnProgressChanged(new ProgressChangedEventArgs(35, $"{strategy.GroupTypeName}分析失败: {ex.Message}"));
|
||||
throw;
|
||||
}
|
||||
|
||||
@ -716,6 +928,9 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 处理单个分层(异步版本)
|
||||
/// </summary>
|
||||
@ -1873,7 +2088,7 @@ namespace NavisworksTransport
|
||||
// 创建测试配置
|
||||
var testConfig = new SplitConfiguration
|
||||
{
|
||||
Strategy = SplitStrategy.ByFloor,
|
||||
Strategy = SplitStrategy.BySmartFloorDetection,
|
||||
OutputDirectory = directory,
|
||||
ExportOptions = new NwdExportUserOptions() // 使用默认选项
|
||||
};
|
||||
@ -1912,10 +2127,14 @@ namespace NavisworksTransport
|
||||
{
|
||||
switch (strategy)
|
||||
{
|
||||
case SplitStrategy.ByFloor:
|
||||
case SplitStrategy.BySmartFloorDetection:
|
||||
return "智能楼层检测分析";
|
||||
case SplitStrategy.ByCustomFloor:
|
||||
return "自定义分层分析";
|
||||
case SplitStrategy.ByFloorAttribute:
|
||||
return "按楼层属性分析";
|
||||
case SplitStrategy.ByZoneAttribute:
|
||||
return "按区域属性分析";
|
||||
case SplitStrategy.BySubSystemAttribute:
|
||||
return "按子系统属性分析";
|
||||
default:
|
||||
return "分层分析";
|
||||
}
|
||||
|
||||
@ -200,6 +200,75 @@ namespace NavisworksTransport
|
||||
Math.Abs(f.Elevation - elevation) <= DEFAULT_ELEVATION_TOLERANCE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从给定的模型项集合中检测楼层信息 - 不进行深度遍历
|
||||
/// </summary>
|
||||
/// <param name="items">预先过滤的模型项集合</param>
|
||||
/// <param name="attributeName">指定的楼层属性名称,为空时自动检测</param>
|
||||
/// <returns>检测到的楼层信息列表</returns>
|
||||
public List<ModelSplitterManager.FloorInfo> DetectFloorsFromGivenItems(ModelItemCollection items, string attributeName = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[FloorDetector] ===== DetectFloorsFromGivenItems开始 =====");
|
||||
LogManager.Info($"[FloorDetector] 输入参数: items.Count={items?.Count ?? -1}, attributeName='{attributeName ?? "null"}'");
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
LogManager.Warning("[FloorDetector] 输入的模型元素集合为空");
|
||||
return new List<ModelSplitterManager.FloorInfo>();
|
||||
}
|
||||
|
||||
LogManager.Info($"[FloorDetector] 直接使用传入的模型项集合进行楼层检测,元素数量: {items.Count}");
|
||||
|
||||
List<ModelSplitterManager.FloorInfo> floors;
|
||||
|
||||
if (!string.IsNullOrEmpty(attributeName))
|
||||
{
|
||||
LogManager.Info($"[FloorDetector] 使用指定属性检测楼层: {attributeName}");
|
||||
// 使用指定属性检测楼层
|
||||
floors = DetectFloorsByAttribute(items, attributeName);
|
||||
LogManager.Info($"[FloorDetector] 使用属性 '{attributeName}' 检测到 {floors.Count} 个楼层");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info($"[FloorDetector] 开始自动检测最佳楼层属性");
|
||||
// 自动检测最佳楼层属性
|
||||
string bestAttribute = FindBestFloorAttribute(items);
|
||||
LogManager.Info($"[FloorDetector] FindBestFloorAttribute返回: '{bestAttribute ?? "null"}'");
|
||||
|
||||
if (!string.IsNullOrEmpty(bestAttribute))
|
||||
{
|
||||
LogManager.Info($"[FloorDetector] 使用自动选择的属性: {bestAttribute}");
|
||||
floors = DetectFloorsByAttribute(items, bestAttribute);
|
||||
LogManager.Info($"[FloorDetector] 自动选择属性 '{bestAttribute}' 检测到 {floors.Count} 个楼层");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info($"[FloorDetector] 未找到合适属性,使用高程检测");
|
||||
// 使用高程检测
|
||||
floors = DetectFloorsByElevation(items);
|
||||
LogManager.Info($"[FloorDetector] 使用高程检测到 {floors.Count} 个楼层");
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"[FloorDetector] 开始验证和优化楼层结果");
|
||||
// 验证和优化检测结果
|
||||
floors = ValidateAndOptimizeFloors(floors);
|
||||
LogManager.Info($"[FloorDetector] 验证优化完成,最终楼层数: {floors?.Count ?? -1}");
|
||||
|
||||
LogManager.Info($"[FloorDetector] ===== DetectFloorsFromGivenItems完成 ===== 最终识别 {floors.Count} 个楼层");
|
||||
return floors;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[FloorDetector] ===== DetectFloorsFromGivenItems异常 =====");
|
||||
LogManager.Error($"[FloorDetector] 楼层检测失败: {ex.Message}");
|
||||
LogManager.Error($"[FloorDetector] 异常堆栈: {ex.StackTrace}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有方法 - 深度控制和基于属性的检测
|
||||
|
||||
Loading…
Reference in New Issue
Block a user