统一了物流属性查询用CategoryAttributeManager

This commit is contained in:
tian 2025-09-04 13:41:59 +08:00
parent d75582d664
commit e4771663b4
8 changed files with 220 additions and 348 deletions

View File

@ -52,7 +52,9 @@
"Bash(cmd:*)",
"WebFetch(domain:twentytwo.space)",
"Bash(git add:*)",
"Bash(git commit:*)"
"Bash(git commit:*)",
"Read(/C:\\Users\\Tellme\\apps\\NavisworksTransport\\src\\Utils/**)",
"Read(/C:\\Users\\Tellme\\apps\\NavisworksTransport\\src\\Core/**)"
],
"deny": [],
"additionalDirectories": [

View File

@ -108,17 +108,8 @@ namespace NavisworksTransport
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, attributeName, StringComparison.OrdinalIgnoreCase))
{
return property.Value?.ToDisplayString();
}
}
}
return null;
// 使用 CategoryAttributeManager 的通用属性获取方法,简化代码
return CategoryAttributeManager.GetGeneralPropertyValue(item, attributeName);
}
catch
{

View File

@ -1030,9 +1030,16 @@ namespace NavisworksTransport
}
else
{
// 通过类别属性筛选通道
var channelItems = FilterChannelsByCategory();
_selectedChannels.AddRange(channelItems);
// 直接使用 CategoryAttributeManager 的方法筛选通道,无需额外的包装方法
var document = Application.ActiveDocument;
if (document != null)
{
var allLogisticsItems = CategoryAttributeManager.GetAllLogisticsItems(document);
var channelItems = CategoryAttributeManager.FilterByLogisticsType(allLogisticsItems, CategoryAttributeManager.LogisticsElementType.);
_selectedChannels.AddRange(channelItems);
LogManager.Info($"[SelectChannels] 通过CategoryAttributeManager直接筛选到 {channelItems.Count} 个通道");
}
RaiseStatusChanged($"通过类别筛选到 {_selectedChannels.Count} 个通道", PathPlanningStatusType.Success);
}
@ -2037,38 +2044,6 @@ namespace NavisworksTransport
#region
private List<ModelItem> FilterChannelsByCategory()
{
// 保留原有实现
var channelItems = new List<ModelItem>();
try
{
var allItems = SearchLogisticsItemsUsingSearchAPI();
foreach (var item in allItems)
{
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
var singleItemCollection = new ModelItemCollection
{
item
};
var filteredItems = CategoryAttributeManager.FilterByLogisticsType(singleItemCollection, CategoryAttributeManager.LogisticsElementType.);
if (filteredItems.Count > 0)
{
channelItems.Add(item);
}
}
}
}
catch (Exception ex)
{
RaiseErrorOccurred($"筛选通道类别时发生错误: {ex.Message}", ex);
}
return channelItems;
}
private void CalculateCombinedBounds()
{
@ -2175,14 +2150,12 @@ namespace NavisworksTransport
LogManager.Info("[通道自动选择] 开始搜索可通行的物流模型");
// 使用Search API代替手动遍历提高效率
var allLogisticsItems = SearchLogisticsItemsUsingSearchAPI();
LogManager.Info($"[通道自动选择] Search API找到 {allLogisticsItems.Count} 个具有物流属性的模型项");
// 使用CategoryAttributeManager统一接口获取物流项目
var allLogisticsItemsCollection = CategoryAttributeManager.GetAllLogisticsItems(document);
LogManager.Info($"[通道自动选择] CategoryAttributeManager找到 {allLogisticsItemsCollection.Count} 个具有物流属性的模型项");
// 筛选出可通行的物流模型
var modelCollection = new ModelItemCollection();
modelCollection.AddRange(allLogisticsItems);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(modelCollection);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(allLogisticsItemsCollection);
LogManager.Info($"[通道自动选择] 筛选出 {traversableItems.Count} 个可通行的物流模型");
// 将可通行的物流模型添加到_selectedChannels
@ -2447,16 +2420,14 @@ namespace NavisworksTransport
var document = Application.ActiveDocument;
if (document?.Models != null)
{
// 使用Search API实时搜索
var logisticsItems = SearchLogisticsItemsUsingSearchAPI();
LogManager.WriteLog($"[搜索通道] 实时搜索找到 {logisticsItems.Count} 个物流模型");
// 使用CategoryAttributeManager统一接口获取物流项目
var logisticsItemsCollection = CategoryAttributeManager.GetAllLogisticsItems(document);
LogManager.WriteLog($"[搜索通道] CategoryAttributeManager找到 {logisticsItemsCollection.Count} 个物流模型");
if (logisticsItems.Count > 0)
if (logisticsItemsCollection.Count > 0)
{
// 筛选出可通行的物流模型
var modelCollection = new ModelItemCollection();
modelCollection.AddRange(logisticsItems);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(modelCollection);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(logisticsItemsCollection);
LogManager.WriteLog($"[搜索通道] 筛选出 {traversableItems.Count} 个可通行的物流模型");
// 临时设置为选中通道
@ -2478,63 +2449,6 @@ namespace NavisworksTransport
}
/// <summary>
/// 使用Navisworks Search API高效搜索具有物流属性的模型项
/// </summary>
private List<ModelItem> SearchLogisticsItemsUsingSearchAPI()
{
var logisticsItems = new List<ModelItem>();
try
{
var document = Application.ActiveDocument;
if (document?.Models == null)
{
LogManager.Warning("[Search API] 活动文档或模型为空");
return logisticsItems;
}
LogManager.Info("[Search API] 开始使用Search API搜索具有物流属性的模型项");
// 创建搜索对象
using (var search = new Search())
{
// 选择所有项目作为搜索范围
search.Selection.SelectAll();
// 创建搜索条件:查找具有物流属性的项
var searchConditions = search.SearchConditions;
searchConditions.Clear();
// 搜索条件:有物流类别的项目
var hasLogisticsCategoryCondition = SearchCondition.HasCategoryByDisplayName(CategoryAttributeManager.LogisticsCategories.LOGISTICS);
searchConditions.Add(hasLogisticsCategoryCondition);
// 执行搜索
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
ModelItemCollection searchResults = search.FindAll(document, false);
stopwatch.Stop();
LogManager.Info($"[Search API] 搜索完成,找到 {searchResults?.Count ?? 0} 个具有物流属性的项,耗时: {stopwatch.ElapsedMilliseconds}ms");
if (searchResults != null)
{
foreach (ModelItem item in searchResults)
{
logisticsItems.Add(item);
}
}
}
return logisticsItems;
}
catch (Exception ex)
{
LogManager.Error($"[Search API] SearchLogisticsItemsUsingSearchAPI方法发生错误: {ex.Message}");
RaiseErrorOccurred($"搜索物流模型项失败: {ex.Message}", ex);
return logisticsItems;
}
}
/// <summary>
/// 获取Navisworks文档单位并转换为米的系数
@ -2815,10 +2729,17 @@ namespace NavisworksTransport
return channelItems;
}
// 否则使用Search API搜索
LogManager.Info("[通道数据] 用户未选择通道且网格无通道数据使用Search API搜索");
var foundChannels = SearchLogisticsItemsUsingSearchAPI();
channelItems.AddRange(foundChannels);
// 否则使用CategoryAttributeManager搜索
LogManager.Info("[通道数据] 用户未选择通道且网格无通道数据使用CategoryAttributeManager搜索");
var document = Application.ActiveDocument;
if (document != null)
{
var foundChannelsCollection = CategoryAttributeManager.GetAllLogisticsItems(document);
foreach (ModelItem item in foundChannelsCollection)
{
channelItems.Add(item);
}
}
LogManager.Info($"[通道数据] 找到 {channelItems.Count} 个通道模型项");
return channelItems;

View File

@ -422,17 +422,8 @@ namespace NavisworksTransport
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, attributeName, StringComparison.OrdinalIgnoreCase))
{
return property.Value?.ToString()?.Trim();
}
}
}
return null;
// 使用 CategoryAttributeManager 的通用属性获取方法,简化代码
return CategoryAttributeManager.GetGeneralPropertyValueTrimmed(item, attributeName);
}
catch (Exception ex)
{

View File

@ -324,6 +324,43 @@ namespace NavisworksTransport
return filteredItems;
}
/// <summary>
/// 获取文档中所有具有物流属性的模型项
/// </summary>
/// <param name="document">Navisworks文档</param>
/// <returns>具有物流属性的模型项集合</returns>
public static ModelItemCollection GetAllLogisticsItems(Document document)
{
try
{
using (var search = new Search())
{
search.Selection.SelectAll();
var searchConditions = search.SearchConditions;
searchConditions.Clear();
var hasLogisticsCondition = SearchCondition.HasCategoryByDisplayName(LogisticsCategories.LOGISTICS);
searchConditions.Add(hasLogisticsCondition);
return search.FindAll(document, false);
}
}
catch (Exception ex)
{
LogManager.Error($"获取物流属性模型项失败: {ex.Message}");
return new ModelItemCollection();
}
}
/// <summary>
/// 获取文档中所有可通行的物流模型项(具有物流属性且通行性为"是"
/// </summary>
/// <param name="document">Navisworks文档</param>
/// <returns>可通行的物流模型项集合</returns>
public static ModelItemCollection GetAllTraversableLogisticsItems(Document document)
{
var allLogisticsItems = GetAllLogisticsItems(document);
return FilterTraversableItems(allLogisticsItems);
}
/// <summary>
/// 根据车辆尺寸筛选适用的通道
/// </summary>
@ -879,6 +916,127 @@ namespace NavisworksTransport
return string.Empty;
}
/// <summary>
/// 通用方法:获取模型项的指定属性值(不限于物流属性)
/// </summary>
/// <param name="item">模型项</param>
/// <param name="propertyName">属性名称</param>
/// <returns>属性值如果不存在返回null</returns>
public static string GetGeneralPropertyValue(ModelItem item, string propertyName)
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, propertyName, StringComparison.OrdinalIgnoreCase))
{
return property.Value?.ToDisplayString();
}
}
}
return null;
}
catch (Exception ex)
{
LogManager.WriteLog($"获取通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"获取通用属性值时发生错误: {ex.Message}");
return null;
}
}
/// <summary>
/// 通用方法获取模型项的指定属性值并进行字符串修剪用于AttributeGrouper等场景
/// </summary>
/// <param name="item">模型项</param>
/// <param name="propertyName">属性名称</param>
/// <returns>修剪后的属性值如果不存在返回null</returns>
public static string GetGeneralPropertyValueTrimmed(ModelItem item, string propertyName)
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, propertyName, StringComparison.OrdinalIgnoreCase))
{
return property.Value?.ToString()?.Trim();
}
}
}
return null;
}
catch (Exception ex)
{
LogManager.WriteLog($"获取修剪后的通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"获取修剪后的通用属性值时发生错误: {ex.Message}");
return null;
}
}
/// <summary>
/// 安全获取属性值的通用方法,会根据数据类型选择合适的转换方式
/// </summary>
/// <param name="property">数据属性</param>
/// <returns>安全转换后的属性值字符串</returns>
public static string GetSafePropertyValue(DataProperty property)
{
try
{
if (property?.Value == null)
return null;
// 检查是否为DisplayString类型
if (property.Value.IsDisplayString)
{
return property.Value.ToDisplayString()?.Trim();
}
else
{
// 对于非DisplayString类型使用ToString()
return property.Value.ToString()?.Trim();
}
}
catch (Exception ex)
{
LogManager.WriteLog($"安全获取属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"安全获取属性值时发生错误: {ex.Message}");
return null;
}
}
/// <summary>
/// 通用方法:使用安全方式获取模型项的指定属性值
/// </summary>
/// <param name="item">模型项</param>
/// <param name="propertyName">属性名称</param>
/// <returns>安全获取的属性值如果不存在返回null</returns>
public static string GetGeneralPropertyValueSafe(ModelItem item, string propertyName)
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, propertyName, StringComparison.OrdinalIgnoreCase))
{
return GetSafePropertyValue(property);
}
}
}
return null;
}
catch (Exception ex)
{
LogManager.WriteLog($"安全获取通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"安全获取通用属性值时发生错误: {ex.Message}");
return null;
}
}
/// <summary>
/// 获取模型项的完整物流属性信息
/// </summary>

View File

@ -224,25 +224,19 @@ namespace NavisworksTransport.PathPlanning
// 1.5. 使用智能收集策略收集所有通道相关节点
LogManager.Info("[包围盒2.5D模式] 步骤1.5: 智能收集通道相关节点");
var allChannelItems = SearchChannelModels(document);
LogManager.Info($"[包围盒2.5D模式] SearchChannelModels找到 {allChannelItems.Count} 个通道元素");
// 🔥 一行调用:直接获取所有可通行的物流模型项
var allChannelItems = CategoryAttributeManager.GetAllTraversableLogisticsItems(document);
LogManager.Info($"[包围盒2.5D模式] 直接获取到 {allChannelItems.Count} 个可通行物流元素");
// 智能收集通道相关节点(包括父节点、同级节点等)
var channelRelatedItems = CollectChannelRelatedItems(allChannelItems);
var channelRelatedItems = CollectChannelRelatedItems(allChannelItems.ToList());
LogManager.Info($"[包围盒2.5D模式] 智能收集到 {channelRelatedItems.Count} 个通道相关节点");
// 合并两个来源的通道元素:原始通道覆盖 + 智能收集的相关节点
var channelItemsSet = new HashSet<ModelItem>(channelCoverage.ChannelItems);
foreach (var item in channelRelatedItems)
{
channelItemsSet.Add(item);
}
LogManager.Info($"[包围盒2.5D模式] 最终合并通道元素集: {channelItemsSet.Count} 个");
// 2. 直接遍历处理障碍物(包围盒检测)
LogManager.Info("[包围盒2.5D模式] 步骤2: 包围盒遍历处理障碍物");
double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
ProcessObstaclesWithBoundingBox(document, channelCoverage.GridMap, channelItemsSet, scanHeight);
ProcessObstaclesWithBoundingBox(document, channelCoverage.GridMap, channelRelatedItems, scanHeight);
// 步骤2.5: 将剩余的通道网格设置为可通行
LogManager.Info("[包围盒2.5D模式] 步骤2.5: 设置通道网格为可通行");
@ -284,12 +278,11 @@ namespace NavisworksTransport.PathPlanning
channelCoverage.GridMap.HasPlanningPoints = true;
}
// 🔥 关键修复将通道数据设置到GridMap中供后续PathPlanningManager使用
// 使用最终合并的通道元素集,包含智能收集的相关节点
if (channelItemsSet != null && channelItemsSet.Any())
// 将通道数据设置到GridMap中供后续PathPlanningManager使用
if (channelRelatedItems != null && channelRelatedItems.Any())
{
channelCoverage.GridMap.ChannelItems = channelItemsSet.ToList();
LogManager.Info($"[包围盒2.5D模式] 已将 {channelItemsSet.Count} 个通道数据设置到GridMap中");
channelCoverage.GridMap.ChannelItems = channelRelatedItems.ToList();
LogManager.Info($"[包围盒2.5D模式] 已将 {channelRelatedItems.Count} 个通道数据设置到GridMap中");
}
else if (channelCoverage.ChannelItems != null && channelCoverage.ChannelItems.Any())
{
@ -1065,93 +1058,9 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高效膨胀] 车辆膨胀完成: 膨胀半径={inflationRadius}格, 新增障碍物={inflatedCells}个, 跳过={skippedCells}个, 总耗时={stopwatch.ElapsedMilliseconds}ms");
}
/// <summary>
/// 搜索所有物流通道模型
/// </summary>
/// <param name="document">Navisworks文档</param>
/// <returns>通道模型列表</returns>
private List<ModelItem> SearchChannelModels(Document document)
{
var channelModels = new List<ModelItem>();
try
{
LogManager.Info("[通道搜索] 开始搜索物流通道模型");
// 使用Search API查找所有有物流属性的模型项
using (var search = new Search())
{
// 🔥 关键修复:选择所有项目作为搜索范围
search.Selection.SelectAll();
LogManager.Info("[通道搜索] ✅ 已设置搜索范围为全选 (SelectAll)");
var searchConditions = search.SearchConditions;
searchConditions.Clear();
var hasLogisticsCondition = SearchCondition.HasCategoryByDisplayName(CategoryAttributeManager.LogisticsCategories.LOGISTICS);
searchConditions.Add(hasLogisticsCondition);
ModelItemCollection logisticsResults = search.FindAll(document, false);
LogManager.Info($"[通道搜索] Search API找到 {logisticsResults.Count} 个具有物流属性的模型项");
// 筛选出具有通过性的模型项(基于物流属性的通过性判断)
foreach (ModelItem item in logisticsResults)
{
try
{
var logisticsType = CategoryAttributeManager.GetLogisticsElementType(item);
LogManager.Info($"[通道搜索] 检查模型项: DisplayName='{item.DisplayName}', 物流类型={logisticsType}");
// 🔥 关键修改:基于物流属性的通过性判断,而不是只检查类型为"通道"
string traversableValue = CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TRAVERSABLE);
LogManager.Info($"[通道搜索] 通过性属性值: '{traversableValue}'");
if (traversableValue == "是")
{
channelModels.Add(item);
LogManager.Info($"[通道搜索] ✅ 找到可通过模型: '{item.DisplayName}' (类型={logisticsType}, 通过性=是)");
}
else
{
LogManager.Info($"[通道搜索] ❌ 跳过不可通过模型: '{item.DisplayName}' (类型={logisticsType}, 通过性={traversableValue})");
}
}
catch (Exception ex)
{
LogManager.Warning($"[通道搜索] 检查模型项时出错: {ex.Message}");
}
}
}
LogManager.Info($"[通道搜索] 搜索完成,共找到 {channelModels.Count} 个可通过模型");
return channelModels;
}
catch (Exception ex)
{
LogManager.Error($"[通道搜索] 搜索通道模型失败: {ex.Message}");
return channelModels;
}
}
/// <summary>
/// 递归收集节点的所有后代
/// </summary>
/// <param name="node">根节点</param>
/// <param name="result">结果列表</param>
private void CollectAllDescendants(ModelItem node, List<ModelItem> result)
{
// 添加当前节点
result.Add(node);
// 递归添加所有子节点
foreach (ModelItem child in node.Children)
{
CollectAllDescendants(child, result);
}
}
/// <summary>
/// 智能收集通道相关节点
/// 收集通道相关节点
/// 根据节点类型决定收集策略:几何体节点收集父节点和同级节点,集合节点收集子节点
/// </summary>
/// <param name="channelItems">通道节点列表</param>
@ -1164,46 +1073,18 @@ namespace NavisworksTransport.PathPlanning
{
try
{
// 添加通道本身
relatedItems.Add(channelItem);
LogManager.Info($"[通道收集] 开始处理通道节点: '{channelItem.DisplayName}'");
// 判断是几何体节点还是集合节点
bool hasChildren = channelItem.Children?.Any() == true;
bool hasGeometry = channelItem.HasGeometry;
// 使用 ModelItemAnalysisHelper 的通用方法收集相关节点
var itemRelatedNodes = ModelItemAnalysisHelper.CollectRelatedNodes(channelItem);
if (!hasChildren && hasGeometry)
// 将结果添加到 HashSet 中
foreach (var node in itemRelatedNodes)
{
// 几何体节点:需要收集父节点和同级节点
LogManager.Info($"[通道收集] '{channelItem.DisplayName}' 是几何体节点,收集父节点和同级节点");
if (channelItem.Parent != null)
{
// 添加父节点
relatedItems.Add(channelItem.Parent);
LogManager.Info($"[通道收集] 添加父节点: '{channelItem.Parent.DisplayName}'");
// 添加所有同级节点
foreach (var sibling in channelItem.Parent.Children)
{
relatedItems.Add(sibling);
LogManager.Info($"[通道收集] 添加同级节点: '{sibling.DisplayName}'");
}
}
}
else if (hasChildren)
{
// 集合节点:只收集子节点
LogManager.Info($"[通道收集] '{channelItem.DisplayName}' 是集合节点,收集所有子节点");
foreach (var child in channelItem.Children)
{
CollectAllDescendants(child, relatedItems);
}
}
else
{
LogManager.Info($"[通道收集] '{channelItem.DisplayName}' 类型不明确,只收集节点本身");
relatedItems.Add(node);
}
LogManager.Info($"[通道收集] 从 '{channelItem.DisplayName}' 收集到 {itemRelatedNodes.Count} 个相关节点");
}
catch (Exception ex)
{
@ -1217,29 +1098,6 @@ namespace NavisworksTransport.PathPlanning
return relatedItems;
}
/// <summary>
/// 递归收集所有后代节点重载版本使用HashSet
/// </summary>
/// <param name="node">根节点</param>
/// <param name="collection">目标集合</param>
private void CollectAllDescendants(ModelItem node, HashSet<ModelItem> collection)
{
try
{
collection.Add(node);
if (node.Children != null)
{
foreach (var child in node.Children)
{
CollectAllDescendants(child, collection);
}
}
}
catch (Exception ex)
{
LogManager.Warning($"[通道收集] 递归收集后代节点时出错: {ex.Message}");
}
}
/// <summary>
/// 使用包围盒遍历方式处理障碍物(优化版)

View File

@ -1044,27 +1044,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
// 查找物流属性类别
foreach (var category in item.PropertyCategories)
{
if (category.DisplayName == CategoryAttributeManager.LogisticsCategories.LOGISTICS)
{
foreach (var property in category.Properties)
{
if (property.DisplayName == CategoryAttributeManager.LogisticsProperties.TYPE)
{
return property.Value.ToDisplayString();
}
}
}
}
// 使用 CategoryAttributeManager 的专用方法获取物流属性值
return CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TYPE);
}
catch (Exception ex)
{
LogManager.Error($"获取物流类型失败: {ex.Message}");
return null;
}
return null;
}
/// <summary>

View File

@ -392,17 +392,8 @@ namespace NavisworksTransport
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
foreach (DataProperty property in category.Properties)
{
if (string.Equals(property.DisplayName, attributeName, StringComparison.OrdinalIgnoreCase))
{
return GetSafePropertyValue(property);
}
}
}
return null;
// 使用 CategoryAttributeManager 的安全属性获取方法,简化代码
return CategoryAttributeManager.GetGeneralPropertyValueSafe(item, attributeName);
}
catch
{
@ -410,33 +401,6 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 安全获取属性值字符串避免ToDisplayString异常
/// </summary>
private string GetSafePropertyValue(DataProperty property)
{
try
{
if (property?.Value == null)
return null;
// 检查是否为DisplayString类型
if (property.Value.IsDisplayString)
{
return property.Value.ToDisplayString()?.Trim();
}
else
{
// 对于非DisplayString类型使用ToString()
return property.Value.ToString()?.Trim();
}
}
catch (Exception ex)
{
LogManager.Warning($"[FloorDetector] 获取属性值失败: {ex.Message}");
return null;
}
}
#endregion
@ -486,7 +450,7 @@ namespace NavisworksTransport
if (IsFloorRelatedAttribute(propName))
{
//LogManager.Info($"[FloorDetector] 找到楼层相关属性: {propName}");
string value = GetSafePropertyValue(property);
string value = CategoryAttributeManager.GetSafePropertyValue(property);
//LogManager.Info($"[FloorDetector] 属性值: {value ?? "null"}");
if (!string.IsNullOrEmpty(value) && IsValidFloorValue(value))