From 178aa995ffd7cc343b536f5b42c0f0d452cc2843 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 16 Feb 2026 11:55:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E4=BB=A3=E7=A0=81=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5=E5=B9=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 115 ++++++++++++++++++ .../Collision/ClashDetectiveIntegration.cs | 5 +- src/Core/Config/ConfigManager.cs | 23 ++++ src/Core/Database/BackupManager.cs | 7 +- src/Core/FloorAttributeManager.cs | 5 +- src/Core/ModelSplitterManager.cs | 5 +- src/Core/PathDatabase.cs | 5 +- src/Core/PathPlanningModels.cs | 20 ++- src/PathPlanning/AutoPathFinder.cs | 36 +++++- src/PathPlanning/ChannelHeightDetector.cs | 9 +- src/PathPlanning/GridMap.cs | 9 +- src/PathPlanning/PathOptimizer.cs | 14 ++- src/PathPlanning/TriangleSpatialHash.cs | 4 +- src/PathPlanning/VoxelGridGenerator.cs | 3 +- .../Converters/BatchQueueStatusConverter.cs | 3 +- src/UI/WPF/Converters/BoolToBrushConverter.cs | 3 +- .../WPF/Converters/BoolToOpacityConverter.cs | 3 +- .../Converters/BoolToVisibilityConverter.cs | 2 +- .../Converters/CountToVisibilityConverter.cs | 2 +- src/UI/WPF/Converters/IndexConverter.cs | 3 +- src/UI/WPF/Converters/PathToImageConverter.cs | 3 +- src/UI/WPF/Converters/PathTypeConverter.cs | 3 +- .../ViewModels/AnimationControlViewModel.cs | 5 +- src/UI/WPF/ViewModels/PathEditingViewModel.cs | 6 +- .../ViewModels/SystemManagementViewModel.cs | 5 +- .../CoordinateSystemResultDialog.xaml.cs | 6 +- .../WPF/Views/ModelItemBoundsWindow.xaml.cs | 15 ++- src/UI/WPF/Views/PathAnalysisDialog.xaml.cs | 8 +- src/Utils/BoundingBoxGeometryUtils.cs | 6 +- src/Utils/ComApiBase.cs | 18 +-- src/Utils/CoordinateConverter.cs | 5 +- src/Utils/GeometryHelper.cs | 16 ++- src/Utils/ViewpointHelper.cs | 7 +- 33 files changed, 310 insertions(+), 69 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cd7b7ae..742eff1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -217,6 +217,121 @@ using NavisworksTransport.Utils; | 常量 | PascalCase | `MaxHeightDiff` | | 枚举 | PascalCase | `GridGenerationMode` | +### 代码开发原则 + +#### 1. 禁止硬编码默认值 + +函数的参数和初始化时不要使用硬编码的默认值,应从配置读取或使用命名常量: + +```csharp +// ❌ 错误:硬编码默认值 +public GridMap Generate(double cellSize = 0.5) { } + +// ❌ 错误:构造函数中硬编码 +public PathPlanner() { + _cellSize = 0.5; + _maxSlope = 15.0; +} + +// ✅ 正确:从配置读取 +public GridMap Generate(double cellSize) { + cellSize = cellSize > 0 ? cellSize : ConfigManager.Instance.Current.PathEditing.CellSizeMeters; + // ... +} + +// ✅ 正确:使用命名常量 +private const double DEFAULT_CELL_SIZE_METERS = 0.5; +public PathPlanner(double cellSize = DEFAULT_CELL_SIZE_METERS) { } +``` + +#### 2. 不向后兼容 + +本项目专门针对 Navisworks 2026 开发,**程序中不要写向后兼容代码**: + +```csharp +// ❌ 错误:向后兼容代码 +#if NAVISWORKS_2025 + // 2025 specific code +#elif NAVISWORKS_2026 + // 2026 specific code +#endif + +// ❌ 错误:运行时版本检查 +if (NavisworksVersion.Major < 2026) { + // 兼容旧版本的代码 +} + +// ✅ 正确:直接针对2026编写 +var clashResult = Autodesk.Navisworks.Api.Clash.ClashResult.GetAllResults(); +``` + +#### 3. 不随意加回退逻辑 + +程序中不要随意加回退逻辑,避免过度防御性编程导致隐藏问题: + +```csharp +// ❌ 错误:过度回退逻辑 +public double GetCellSize() { + try { + return ConfigManager.Instance.Current.PathEditing.CellSizeMeters; + } + catch { + return 0.5; // 隐藏了配置读取失败的问题! + } +} + +// ❌ 错误:静默回退 +double value = GetConfigValue("cellSize"); +if (value <= 0) value = 0.5; // 为什么<=0?配置验证应该保证这一点 + +// ✅ 正确:让问题暴露出来 +public double GetCellSize() { + return ConfigManager.Instance.Current.PathEditing.CellSizeMeters; + // 如果配置有问题,让它抛出异常,在源头解决 +} +``` + +#### 4. 代码复用优先 + +规划和编写新功能或新模块时,**尽量复用项目中的代码,尤其是工具和辅助类**: + +```csharp +// ❌ 错误:重复造轮子 +public static double MyConvertUnits(double value) { + // 自己写一套单位转换逻辑... +} + +// ✅ 正确:复用现有的 UnitsConverter +using NavisworksTransport.Utils; +double meters = UnitsConverter.ConvertToMeters(distance); + +// ❌ 错误:自己实现集合通知 +public class MyCollection : ObservableCollection { + // 重写一大堆线程安全代码... +} + +// ✅ 正确:复用 ThreadSafeObservableCollection +using NavisworksTransport.UI.WPF.Collections; +var collection = new ThreadSafeObservableCollection(); + +// ❌ 错误:自己写几何计算 +public double Distance(Point3D a, Point3D b) { + return Math.Sqrt(Math.Pow(a.X - b.X, 2) + ...); +} + +// ✅ 正确:复用 GeometryHelper +using NavisworksTransport.Utils; +double distance = GeometryHelper.Distance(pointA, pointB); +``` + +**复用检查清单:** +- 需要单位转换?→ 使用 `UnitsConverter` +- 需要几何计算?→ 使用 `GeometryHelper` +- 需要日志记录?→ 使用 `LogManager` +- 需要线程安全的集合?→ 使用 `ThreadSafeObservableCollection` +- 需要坐标转换?→ 使用 `CoordinateConverter` +- 需要路径相关工具?→ 使用 `PathHelper` + ### 单位系统 - 极其重要 **所有网格地图和路径规划计算必须使用模型单位,严禁混用米制单位。** diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index 0d92da9..da231a6 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -628,7 +628,10 @@ namespace NavisworksTransport var pathId = doc.Models.CreatePathId(precomputed.Item2); precomputedPathIds.Add((pathId.ModelIndex, pathId.PathId)); } - catch { /* 忽略获取PathId失败的记录 */ } + catch (Exception ex) + { + LogManager.Warning($"[PathId匹配] 获取PathId失败: {ex.Message}"); + } } } diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs index 9043912..d5a3df5 100644 --- a/src/Core/Config/ConfigManager.cs +++ b/src/Core/Config/ConfigManager.cs @@ -898,6 +898,29 @@ namespace NavisworksTransport.Core.Config return defaultValue; } + /// + /// 获取 float 配置值(带默认值,不抛出异常) + /// + private float GetFloatValueWithDefault(TomlTable table, string key, float defaultValue, List missingItems) + { + if (!table.ContainsKey(key)) + { + missingItems.Add($"{key}"); + LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}"); + return defaultValue; + } + + var value = table[key]; + if (value is long longValue) + return (float)longValue; + if (value is double doubleValue) + return (float)doubleValue; + + missingItems.Add($"{key} (类型错误)"); + LogManager.Warning($"配置项 '{key}' 类型错误,使用默认值: {defaultValue}"); + return defaultValue; + } + /// /// 获取 int 配置值(带默认值,不抛出异常) /// diff --git a/src/Core/Database/BackupManager.cs b/src/Core/Database/BackupManager.cs index ad110a9..d63f177 100644 --- a/src/Core/Database/BackupManager.cs +++ b/src/Core/Database/BackupManager.cs @@ -200,7 +200,12 @@ namespace NavisworksTransport.Core.Database finally { // 重新打开连接 - try { _database.Connection.Open(); } catch { } + try { _database.Connection.Open(); } + catch (Exception ex) + { + LogManager.Error($"[数据库恢复] 重新打开连接失败: {ex.Message}"); + throw; + } } LogManager.Info($"数据库恢复完成: {backupFilePath}"); diff --git a/src/Core/FloorAttributeManager.cs b/src/Core/FloorAttributeManager.cs index de36249..19210a3 100644 --- a/src/Core/FloorAttributeManager.cs +++ b/src/Core/FloorAttributeManager.cs @@ -237,7 +237,10 @@ namespace NavisworksTransport.Core return true; } } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[楼层管理器] 检查类别失败: {ex.Message}"); + } return false; } diff --git a/src/Core/ModelSplitterManager.cs b/src/Core/ModelSplitterManager.cs index 9513409..deabab4 100644 --- a/src/Core/ModelSplitterManager.cs +++ b/src/Core/ModelSplitterManager.cs @@ -1216,7 +1216,10 @@ namespace NavisworksTransport fileSizeInfo = $" ({sizeMB:F1}MB)"; } } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[分层管理器] 获取文件大小失败: {ex.Message}"); + } // 更新状态:导出成功 string successProgressInfo = (currentIndex > 0 && totalCount > 0) ? $" ({currentIndex}/{totalCount})" : ""; diff --git a/src/Core/PathDatabase.cs b/src/Core/PathDatabase.cs index 37ed424..e2e8e1c 100644 --- a/src/Core/PathDatabase.cs +++ b/src/Core/PathDatabase.cs @@ -1015,7 +1015,10 @@ namespace NavisworksTransport { ExecuteNonQuery("DELETE FROM sqlite_sequence"); } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[数据库] 重置自增ID失败: {ex.Message}"); + } LogManager.Info("已清空所有数据表"); } diff --git a/src/Core/PathPlanningModels.cs b/src/Core/PathPlanningModels.cs index 4e69c0d..74c701a 100644 --- a/src/Core/PathPlanningModels.cs +++ b/src/Core/PathPlanningModels.cs @@ -1463,7 +1463,10 @@ namespace NavisworksTransport // 这里可以添加更详细的属性读取逻辑 } } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[通道列表] 获取物流属性失败: {ex.Message}"); + } // 获取尺寸信息 double length = 0, width = 0, height = 0; @@ -1477,7 +1480,10 @@ namespace NavisworksTransport height = Math.Abs(boundingBox.Max.Z - boundingBox.Min.Z); } } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[通道列表] 获取包围盒失败: {ex.Message}"); + } // 添加子项 item.SubItems.Add(channelType); @@ -1601,7 +1607,10 @@ namespace NavisworksTransport { ModelHighlightHelper.ClearCategory(ChannelPreviewHighlightCategory); } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[通道预览] 清除高亮失败: {ex.Message}"); + } } catch (Exception ex) { @@ -2456,7 +2465,10 @@ namespace NavisworksTransport if (content.StartsWith("{") && content.EndsWith("}")) return "JSON"; } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[路径格式检测] 读取文件失败: {ex.Message}"); + } return "未知"; } } diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs index cfa54a2..8dd0e4d 100644 --- a/src/PathPlanning/AutoPathFinder.cs +++ b/src/PathPlanning/AutoPathFinder.cs @@ -72,6 +72,31 @@ namespace NavisworksTransport.PathPlanning /// public class AutoPathFinder { + /// + /// 缓坡速度系数 - 当坡度在 3cm 到 25cm 之间时使用 + /// + private const float SLOPE_SPEED_FACTOR_GENTLE = 0.8f; + + /// + /// 楼梯速度系数 - 当坡度在 25cm 到 50cm 之间时使用 + /// + private const float SLOPE_SPEED_FACTOR_STAIR = 0.5f; + + /// + /// 陡坡速度系数 - 当坡度超过 50cm 时使用 + /// + private const float SLOPE_SPEED_FACTOR_STEEP = 0.1f; + + /// + /// A*高度惩罚因子 - 用于计算距离目标高度的速度扣减 + /// + private const double HEIGHT_PENALTY_FACTOR = 0.1; + + /// + /// 转弯角度阈值(弧度)- 用于检测路径转弯 + /// + private const double TURN_ANGLE_THRESHOLD_RADIANS = 0.1; + /// /// 获取水平边连接允许的最大高度差(米) /// 从配置文件读取,足以支持台阶连接(约0.15米)和地面到楼梯底部的连接(约0.3米) @@ -382,9 +407,9 @@ namespace NavisworksTransport.PathPlanning double heightRatio = heightDiff / maxHeightDiff; if (heightRatio < 0.06) return (float)baseSpeed; // 平地 (<3cm,即<0.06*0.5m) - if (heightRatio <= 0.5) return (float)(baseSpeed * 0.8); // 缓坡 (≤0.25m) - if (heightRatio <= 1.0) return (float)(baseSpeed * 0.5); // 楼梯 (≤0.5m) - return (float)(baseSpeed * 0.1); // 过陡 (>0.5m) + if (heightRatio <= 0.5) return (float)(baseSpeed * SLOPE_SPEED_FACTOR_GENTLE); // 缓坡 (≤0.25m) + if (heightRatio <= 1.0) return (float)(baseSpeed * SLOPE_SPEED_FACTOR_STAIR); // 楼梯 (≤0.5m) + return (float)(baseSpeed * SLOPE_SPEED_FACTOR_STEEP); // 过陡 (>0.5m) } /// @@ -1404,8 +1429,7 @@ namespace NavisworksTransport.PathPlanning // 距离目标高度越近,速度越快(A*成本越低) // 公式:速度 = 1 / (1 + 距离 * 惩罚系数) // 例如:距离0m → 速度1.0x, 距离3m → 速度0.77x, 距离6m → 速度0.625x - const double penaltyFactor = 0.1; - return (float)(1.0 / (1.0 + distanceToTarget * penaltyFactor)); + return (float)(1.0 / (1.0 + distanceToTarget * HEIGHT_PENALTY_FACTOR)); } /// @@ -1962,7 +1986,7 @@ namespace NavisworksTransport.PathPlanning return 0; int turns = 0; - const double angleThreshold = 0.1; // 弧度 + const double angleThreshold = TURN_ANGLE_THRESHOLD_RADIANS; // 弧度 for (int i = 1; i < path.Count - 1; i++) { diff --git a/src/PathPlanning/ChannelHeightDetector.cs b/src/PathPlanning/ChannelHeightDetector.cs index 2d2e7b8..16ff639 100644 --- a/src/PathPlanning/ChannelHeightDetector.cs +++ b/src/PathPlanning/ChannelHeightDetector.cs @@ -14,6 +14,11 @@ namespace NavisworksTransport.PathPlanning /// public class ChannelHeightDetector { + /// + /// 默认射线投射容差(米)- 与配置中的安全间隙一致 + /// + private const double DEFAULT_RAYCAST_TOLERANCE_METERS = 0.1; + /// /// 当前使用的坐标系 /// @@ -25,7 +30,7 @@ namespace NavisworksTransport.PathPlanning /// 构造函数(自动使用当前坐标系) /// /// 射线投射容差(米) - public ChannelHeightDetector(double raycastTolerance = 0.1) + public ChannelHeightDetector(double raycastTolerance = DEFAULT_RAYCAST_TOLERANCE_METERS) : this(CoordinateSystemManager.Instance.Current, raycastTolerance) { } @@ -35,7 +40,7 @@ namespace NavisworksTransport.PathPlanning /// /// 坐标系 /// 射线投射容差(米) - public ChannelHeightDetector(ICoordinateSystem coordinateSystem, double raycastTolerance = 0.1) + public ChannelHeightDetector(ICoordinateSystem coordinateSystem, double raycastTolerance = DEFAULT_RAYCAST_TOLERANCE_METERS) { _coordinateSystem = coordinateSystem ?? throw new ArgumentNullException(nameof(coordinateSystem)); _heightCache = new Dictionary(); diff --git a/src/PathPlanning/GridMap.cs b/src/PathPlanning/GridMap.cs index c1e6964..ad2f315 100644 --- a/src/PathPlanning/GridMap.cs +++ b/src/PathPlanning/GridMap.cs @@ -13,6 +13,11 @@ namespace NavisworksTransport.PathPlanning /// public class GridMap { + /// + /// 默认高度层查找容差(米)- 与配置中的安全间隙一致 + /// + private const double DEFAULT_LAYER_TOLERANCE_METERS = 0.1; + /// /// 当前使用的坐标系 /// @@ -339,7 +344,7 @@ namespace NavisworksTransport.PathPlanning /// Z坐标(米) /// 容差(米),默认0.1m /// 符合条件的高度层,如果没有则返回null - public HeightLayer? FindLayerContainingZ(GridPoint2D gridPosition, double z, double tolerance = 0.1) + public HeightLayer? FindLayerContainingZ(GridPoint2D gridPosition, double z, double tolerance = DEFAULT_LAYER_TOLERANCE_METERS) { if (!IsValidGridPosition(gridPosition)) return null; @@ -436,7 +441,7 @@ namespace NavisworksTransport.PathPlanning /// Z坐标(模型单位) /// Z坐标容差(模型单位),默认0.1 /// 是否可通行 - public bool IsPassableAt3DPoint(GridPoint2D gridPosition, double zCoord, double tolerance = 0.1) + public bool IsPassableAt3DPoint(GridPoint2D gridPosition, double zCoord, double tolerance = DEFAULT_LAYER_TOLERANCE_METERS) { if (!IsValidGridPosition(gridPosition)) return false; diff --git a/src/PathPlanning/PathOptimizer.cs b/src/PathPlanning/PathOptimizer.cs index 72d9d39..5ecadb3 100644 --- a/src/PathPlanning/PathOptimizer.cs +++ b/src/PathPlanning/PathOptimizer.cs @@ -11,6 +11,16 @@ namespace NavisworksTransport.PathPlanning /// public class PathOptimizer { + /// + /// 共线检测容差(米) + /// + private const double COLLINEAR_TOLERANCE_METERS = 0.1; + + /// + /// 重复点检测容差(米)- 用于检测坐标完全相同的点 + /// + private const double DUPLICATE_POINT_TOLERANCE_METERS = 0.001; + /// /// 路径优化配置参数 /// @@ -387,7 +397,7 @@ namespace NavisworksTransport.PathPlanning /// 如果三点在同一直线上且方向一致返回true private bool IsCollinear(Point3D p1, Point3D p2, Point3D p3) { - const double tolerance = 0.1; // 容差值,单位:模型单位 + const double tolerance = COLLINEAR_TOLERANCE_METERS; // 容差值,单位:模型单位 // 🔥 修复:使用统一的高度检查函数 if (HasHeightChange(p1, p2, p3)) @@ -406,7 +416,7 @@ namespace NavisworksTransport.PathPlanning double dy23 = p3.Y - p2.Y; // 🔥 修复:使用更严格的容差检查真正的重复点(坐标完全相同) - const double duplicatePointTolerance = 0.001; // 用很小的值检查真正的重复点 + const double duplicatePointTolerance = DUPLICATE_POINT_TOLERANCE_METERS; // 用很小的值检查真正的重复点 bool isSegment1Zero = Math.Abs(dx12) < duplicatePointTolerance && Math.Abs(dy12) < duplicatePointTolerance; bool isSegment2Zero = Math.Abs(dx23) < duplicatePointTolerance && Math.Abs(dy23) < duplicatePointTolerance; diff --git a/src/PathPlanning/TriangleSpatialHash.cs b/src/PathPlanning/TriangleSpatialHash.cs index d232380..dc4020d 100644 --- a/src/PathPlanning/TriangleSpatialHash.cs +++ b/src/PathPlanning/TriangleSpatialHash.cs @@ -50,7 +50,9 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[空间哈希] 开始构建空间索引:{triangles.Count} 个三角形"); _totalTriangles = triangles.Count; - _cellSize = Math.Max(gridSize * 2, 0.1); // 使用稍大的单元格减少重复 + if (gridSize <= 0) + throw new ArgumentException("gridSize 必须大于0", nameof(gridSize)); + _cellSize = gridSize * 2; // 使用稍大的单元格减少重复 _spatialHash.Clear(); // 计算或使用提供的边界框 diff --git a/src/PathPlanning/VoxelGridGenerator.cs b/src/PathPlanning/VoxelGridGenerator.cs index fe7bf3b..56d4517 100644 --- a/src/PathPlanning/VoxelGridGenerator.cs +++ b/src/PathPlanning/VoxelGridGenerator.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using Autodesk.Navisworks.Api; using NavisworksTransport.Utils; +using NavisworksTransport.Core.Config; using static NavisworksTransport.CategoryAttributeManager; using g4; @@ -340,7 +341,7 @@ namespace NavisworksTransport.PathPlanning new Point3D(10 * metersToModelUnits, 10 * metersToModelUnits, 3 * metersToModelUnits) ); - double voxelSize = 0.5 * metersToModelUnits; // 0.5米体素 + double voxelSize = ConfigManager.Instance.Current.PathEditing.CellSizeMeters * metersToModelUnits; // 使用配置的网格大小作为体素大小 var grid = new VoxelGrid(bounds, voxelSize); diff --git a/src/UI/WPF/Converters/BatchQueueStatusConverter.cs b/src/UI/WPF/Converters/BatchQueueStatusConverter.cs index 1a7ce00..f71ef6a 100644 --- a/src/UI/WPF/Converters/BatchQueueStatusConverter.cs +++ b/src/UI/WPF/Converters/BatchQueueStatusConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Data; using NavisworksTransport.Core.Models; @@ -37,7 +38,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } \ No newline at end of file diff --git a/src/UI/WPF/Converters/BoolToBrushConverter.cs b/src/UI/WPF/Converters/BoolToBrushConverter.cs index c903e3c..42724db 100644 --- a/src/UI/WPF/Converters/BoolToBrushConverter.cs +++ b/src/UI/WPF/Converters/BoolToBrushConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Data; using System.Windows.Media; @@ -30,7 +31,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } diff --git a/src/UI/WPF/Converters/BoolToOpacityConverter.cs b/src/UI/WPF/Converters/BoolToOpacityConverter.cs index f49efc7..c702463 100644 --- a/src/UI/WPF/Converters/BoolToOpacityConverter.cs +++ b/src/UI/WPF/Converters/BoolToOpacityConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Data; namespace NavisworksTransport.UI.WPF.Converters @@ -22,7 +23,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } diff --git a/src/UI/WPF/Converters/BoolToVisibilityConverter.cs b/src/UI/WPF/Converters/BoolToVisibilityConverter.cs index bcbe431..09a7bb6 100644 --- a/src/UI/WPF/Converters/BoolToVisibilityConverter.cs +++ b/src/UI/WPF/Converters/BoolToVisibilityConverter.cs @@ -94,7 +94,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException("IsNotNullToBoolConverter不支持反向转换"); + return Binding.DoNothing; } } } \ No newline at end of file diff --git a/src/UI/WPF/Converters/CountToVisibilityConverter.cs b/src/UI/WPF/Converters/CountToVisibilityConverter.cs index 8ca3a42..0bb5a36 100644 --- a/src/UI/WPF/Converters/CountToVisibilityConverter.cs +++ b/src/UI/WPF/Converters/CountToVisibilityConverter.cs @@ -56,7 +56,7 @@ namespace NavisworksTransport.UI.WPF.Converters /// public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException("CountToVisibilityConverter不支持反向转换"); + return Binding.DoNothing; } } diff --git a/src/UI/WPF/Converters/IndexConverter.cs b/src/UI/WPF/Converters/IndexConverter.cs index 227a8dc..b1024c5 100644 --- a/src/UI/WPF/Converters/IndexConverter.cs +++ b/src/UI/WPF/Converters/IndexConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Controls; using System.Windows.Data; @@ -26,7 +27,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } \ No newline at end of file diff --git a/src/UI/WPF/Converters/PathToImageConverter.cs b/src/UI/WPF/Converters/PathToImageConverter.cs index 8d1fc78..98fad9f 100644 --- a/src/UI/WPF/Converters/PathToImageConverter.cs +++ b/src/UI/WPF/Converters/PathToImageConverter.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.IO; +using System.Windows; using System.Windows.Data; using System.Windows.Media.Imaging; @@ -36,7 +37,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } diff --git a/src/UI/WPF/Converters/PathTypeConverter.cs b/src/UI/WPF/Converters/PathTypeConverter.cs index 970277c..2c20dc4 100644 --- a/src/UI/WPF/Converters/PathTypeConverter.cs +++ b/src/UI/WPF/Converters/PathTypeConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Data; namespace NavisworksTransport.UI.WPF.Converters @@ -30,7 +31,7 @@ namespace NavisworksTransport.UI.WPF.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } } \ No newline at end of file diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index 0dbbbdc..88537e7 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -2820,7 +2820,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (volume > 1000) // 大于1000立方米 return "大型物体 - 包围盒很大,容易与路径相交"; } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[碰撞分析] 获取物体包围盒失败: {ex.Message}"); + } return "未知原因 - 建议手动检查"; } diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 6972e04..7d443b4 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -87,10 +87,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _showControlVisualization = true; // 默认显示控制点连线 private bool _showPathLines = true; // 默认显示路径线(地面连线) private bool _showObjectSpace = false; // 默认不显示通行空间 - // 兼容旧代码的互斥属性(已废弃,使用独立开关) - private bool _isStandardLineMode = false; - private bool _isRibbonLineMode = true; - private bool _isObjectSpaceMode = false; + // 渲染模式已改为独立开关(_showControlVisualization, _showPathLines, _showObjectSpace) + // 下面的互斥属性已废弃并删除 // 路径策略参数 private PathStrategyOption _selectedPathStrategy; diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs index 1f7ad32..132b190 100644 --- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs @@ -1746,7 +1746,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } } - catch { } + catch (Exception ex) + { + LogManager.Warning($"[坐标系探索] 设置视图状态失败: {ex.Message}"); + } resultDialog.ShowDialog(); diff --git a/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs index 47da669..0eef36b 100644 --- a/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs +++ b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs @@ -1,3 +1,4 @@ +using System; using System.Windows; namespace NavisworksTransport.UI.WPF.Views @@ -68,7 +69,10 @@ namespace NavisworksTransport.UI.WPF.Views { dialog.Owner = System.Windows.Application.Current?.MainWindow; } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[坐标系对话框] 设置Owner失败: {ex.Message}"); + } } dialog.ShowDialog(); diff --git a/src/UI/WPF/Views/ModelItemBoundsWindow.xaml.cs b/src/UI/WPF/Views/ModelItemBoundsWindow.xaml.cs index 30949db..cd83161 100644 --- a/src/UI/WPF/Views/ModelItemBoundsWindow.xaml.cs +++ b/src/UI/WPF/Views/ModelItemBoundsWindow.xaml.cs @@ -198,7 +198,10 @@ namespace NavisworksTransport.UI.WPF.Views System.Windows.Clipboard.SetText(coordinate); ShowButtonFeedback(CopyCenterButton); } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[坐标窗口] 复制到剪贴板失败: {ex.Message}"); + } } /// @@ -212,7 +215,10 @@ namespace NavisworksTransport.UI.WPF.Views System.Windows.Clipboard.SetText(coordinate); ShowButtonFeedback(CopyTopButton); } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[坐标窗口] 复制到剪贴板失败: {ex.Message}"); + } } /// @@ -226,7 +232,10 @@ namespace NavisworksTransport.UI.WPF.Views System.Windows.Clipboard.SetText(coordinate); ShowButtonFeedback(CopyBottomButton); } - catch { } + catch (Exception ex) + { + LogManager.Debug($"[坐标窗口] 复制到剪贴板失败: {ex.Message}"); + } } /// diff --git a/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs b/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs index d25a5d5..4d7a59d 100644 --- a/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs +++ b/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs @@ -490,7 +490,7 @@ namespace NavisworksTransport.UI.WPF.Views public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } @@ -512,7 +512,7 @@ namespace NavisworksTransport.UI.WPF.Views public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } @@ -542,7 +542,7 @@ namespace NavisworksTransport.UI.WPF.Views public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } @@ -562,7 +562,7 @@ namespace NavisworksTransport.UI.WPF.Views public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + return Binding.DoNothing; } } diff --git a/src/Utils/BoundingBoxGeometryUtils.cs b/src/Utils/BoundingBoxGeometryUtils.cs index ef73708..8c29671 100644 --- a/src/Utils/BoundingBoxGeometryUtils.cs +++ b/src/Utils/BoundingBoxGeometryUtils.cs @@ -56,11 +56,7 @@ namespace NavisworksTransport.Utils var center1 = GetBoundingBoxCenter(box1); var center2 = GetBoundingBoxCenter(box2); - double dx = center1.X - center2.X; - double dy = center1.Y - center2.Y; - double dz = center1.Z - center2.Z; - - return Math.Sqrt(dx * dx + dy * dy + dz * dz); + return GeometryHelper.CalculatePointDistance(center1, center2); } /// diff --git a/src/Utils/ComApiBase.cs b/src/Utils/ComApiBase.cs index 49f5ccf..8e4b094 100644 --- a/src/Utils/ComApiBase.cs +++ b/src/Utils/ComApiBase.cs @@ -142,10 +142,10 @@ namespace NavisworksTransport /// /// 返回类型 /// 要执行的操作 - /// 操作失败时的默认返回值 /// 操作名称(用于日志) /// 操作结果 - protected T SafeComOperation(Func operation, T defaultValue = default(T), string operationName = "COM操作") + /// COM操作失败时抛出 + protected T SafeComOperation(Func operation, string operationName = "COM操作") { try { @@ -157,17 +157,17 @@ namespace NavisworksTransport catch (COMException comEx) { LogManager.Error($"[COM操作] COM异常 - {operationName}: {comEx.Message} (HRESULT: 0x{comEx.ErrorCode:X8})"); - return defaultValue; + throw; } catch (InvalidComObjectException) { LogManager.Error($"[COM操作] COM对象已无效 - {operationName}"); - return defaultValue; + throw; } catch (Exception ex) { LogManager.Error($"[COM操作] 一般异常 - {operationName}: {ex.Message}"); - return defaultValue; + throw; } } @@ -176,14 +176,14 @@ namespace NavisworksTransport /// /// 要执行的操作 /// 操作名称(用于日志) - /// 操作是否成功 - protected bool SafeComOperation(Action operation, string operationName = "COM操作") + /// COM操作失败时抛出 + protected void SafeComOperation(Action operation, string operationName = "COM操作") { - return SafeComOperation(() => + SafeComOperation(() => { operation(); return true; - }, false, operationName); + }, operationName); } #endregion diff --git a/src/Utils/CoordinateConverter.cs b/src/Utils/CoordinateConverter.cs index be4fc8f..e00fb30 100644 --- a/src/Utils/CoordinateConverter.cs +++ b/src/Utils/CoordinateConverter.cs @@ -334,10 +334,7 @@ namespace NavisworksTransport if (point1 == null || point2 == null) throw new ArgumentNullException("世界坐标点不能为空"); - double dx = point2.X - point1.X; - double dy = point2.Y - point1.Y; - double dz = point2.Z - point1.Z; - return Math.Sqrt(dx * dx + dy * dy + dz * dz); + return GeometryHelper.CalculatePointDistance(point1, point2); } /// diff --git a/src/Utils/GeometryHelper.cs b/src/Utils/GeometryHelper.cs index 28e2401..d0ecae8 100644 --- a/src/Utils/GeometryHelper.cs +++ b/src/Utils/GeometryHelper.cs @@ -14,13 +14,23 @@ namespace NavisworksTransport /// public class GeometryHelper { + /// + /// 默认轮廓提取容差(米) + /// + private const double DEFAULT_OUTLINE_TOLERANCE_METERS = 0.5; + + /// + /// 1厘米容差(米)- 用于精确几何计算 + /// + private const double TOLERANCE_1CM_METERS = 0.01; + /// /// 提取模型项的顶视图轮廓 /// /// 模型项 /// 容差 /// 轮廓点集合 - public static List ExtractTopViewOutline(ModelItem modelItem, double tolerance = 0.5) + public static List ExtractTopViewOutline(ModelItem modelItem, double tolerance = DEFAULT_OUTLINE_TOLERANCE_METERS) { var points = new List(); @@ -594,7 +604,7 @@ namespace NavisworksTransport { iteration++; var nextEdgeIndex = -1; - var tolerance = 0.01; // 1cm容差,稍微放宽 + var tolerance = TOLERANCE_1CM_METERS; // 1cm容差,稍微放宽 for (int i = 0; i < remainingEdges.Count; i++) { @@ -747,7 +757,7 @@ namespace NavisworksTransport // 第1步:移除重复点 var uniquePoints = new List(); - const double tolerance = 0.01; // 1cm容差 + const double tolerance = TOLERANCE_1CM_METERS; // 1cm容差 foreach (var point in contour) { diff --git a/src/Utils/ViewpointHelper.cs b/src/Utils/ViewpointHelper.cs index 3e532b8..d0a0976 100644 --- a/src/Utils/ViewpointHelper.cs +++ b/src/Utils/ViewpointHelper.cs @@ -22,9 +22,10 @@ namespace NavisworksTransport.Utils /// private const double VIEW_BOUNDING_BOX_EXPANSION_FACTOR = 1.2; - /// 视野扩展范围(米) + /// + /// 默认视野扩展范围(米)- 用于调整视角时确保目标完全可见 /// - const double EXPANSION_METERS = 10.0; + private const double DEFAULT_VIEW_EXPANSION_METERS = 10.0; /// /// 智能调整视角:调整到路径中心,确保整个路径都在视野内 @@ -106,7 +107,7 @@ namespace NavisworksTransport.Utils // 3. 计算扩展边距 double boxWidth = viewBoundingBox.Max.X - viewBoundingBox.Min.X; - double expansionFactor = VIEW_BOUNDING_BOX_EXPANSION_FACTOR + (EXPANSION_METERS / baseDimension); + double expansionFactor = VIEW_BOUNDING_BOX_EXPANSION_FACTOR + (DEFAULT_VIEW_EXPANSION_METERS / baseDimension); double expansionMargin = boxWidth * (expansionFactor - 1) / 2; // 4. 应用视角(使用通用方法,带 ZoomBox)