diff --git a/CLAUDE.md b/CLAUDE.md
index 7800fa9..c6ab754 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -16,7 +16,7 @@ powershell -Command "& 'C:\...\MSBuild.exe' AStarTestRunner.csproj /p:Configurat
bin\Debug\AStarTestRunner.exe
```
-**调试**: 日志在 `C:\ProgramData\Autodesk\Navisworks Manage 2026\NavisworksTransport\logs\debug.log`
+**调试**: 日志在 `"C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\logs\debug.log"`
## 架构
diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index a60de34..2dbc9e5 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -98,6 +98,12 @@
True
+
+
+ packages\Tomlyn.0.19.0\lib\netstandard2.0\Tomlyn.dll
+ True
+
+
@@ -128,7 +134,11 @@
-
+
+
+
+
+
@@ -204,6 +214,9 @@
LogViewerDialog.xaml
+
+ ConfigEditorDialog.xaml
+
CollisionReportDialog.xaml
@@ -308,6 +321,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/TestConfigManager.cs b/TestConfigManager.cs
new file mode 100644
index 0000000..ea7645a
--- /dev/null
+++ b/TestConfigManager.cs
@@ -0,0 +1,56 @@
+using System;
+using NavisworksTransport.Core.Config;
+
+namespace NavisworksTransport.Tests
+{
+ ///
+ /// 配置管理器测试程序
+ /// 使用方法:在 MainPlugin 的 Execute 方法中临时调用 TestConfigManager.RunTests()
+ ///
+ public class TestConfigManager
+ {
+ public static void RunTests()
+ {
+ Console.WriteLine("=== 开始测试配置管理器 ===");
+ Console.WriteLine();
+
+ // 测试 1:加载或创建默认配置
+ Console.WriteLine("测试 1: 加载或创建默认配置");
+ var config = ConfigManager.Instance.Current;
+ Console.WriteLine($"配置文件路径: {ConfigManager.ConfigFilePath}");
+ Console.WriteLine($"网格尺寸: {config.GridGeneration.CellSizeMeters} 米");
+ Console.WriteLine($"车辆半径: {config.GridGeneration.VehicleRadiusMeters} 米");
+ Console.WriteLine($"路径策略: {config.PathPlanning.DefaultPathStrategy}");
+ Console.WriteLine();
+
+ // 测试 2:修改配置并保存
+ Console.WriteLine("测试 2: 修改配置并保存");
+ config.GridGeneration.CellSizeMeters = 0.6;
+ config.PathPlanning.DefaultPathStrategy = "SafetyFirst";
+ config.Visualization.EnableGridVisualization = true;
+ ConfigManager.Instance.SaveConfig(config);
+ Console.WriteLine("配置已保存");
+ Console.WriteLine();
+
+ // 测试 3:重新加载配置
+ Console.WriteLine("测试 3: 重新加载配置");
+ ConfigManager.Instance.Reload();
+ var reloadedConfig = ConfigManager.Instance.Current;
+ Console.WriteLine($"重载后网格尺寸: {reloadedConfig.GridGeneration.CellSizeMeters} 米");
+ Console.WriteLine($"重载后路径策略: {reloadedConfig.PathPlanning.DefaultPathStrategy}");
+ Console.WriteLine($"重载后网格可视化: {reloadedConfig.Visualization.EnableGridVisualization}");
+ Console.WriteLine();
+
+ // 测试 4:重置为默认配置
+ Console.WriteLine("测试 4: 重置为默认配置");
+ ConfigManager.Instance.ResetToDefault();
+ var defaultConfig = ConfigManager.Instance.Current;
+ Console.WriteLine($"重置后网格尺寸: {defaultConfig.GridGeneration.CellSizeMeters} 米");
+ Console.WriteLine($"重置后路径策略: {defaultConfig.PathPlanning.DefaultPathStrategy}");
+ Console.WriteLine();
+
+ Console.WriteLine("=== 测试完成 ===");
+ Console.WriteLine($"请检查配置文件: {ConfigManager.ConfigFilePath}");
+ }
+ }
+}
diff --git a/config.toml.example b/config.toml.example
new file mode 100644
index 0000000..f5d7f77
--- /dev/null
+++ b/config.toml.example
@@ -0,0 +1,76 @@
+# NavisworksTransport 系统配置文件
+# 单位说明:长度单位均为米(m),时间单位为秒(s)
+# 自动生成时间: 2025-10-11 10:50:00
+
+[grid_generation]
+# 网格单元大小(米)- 推荐值:0.3-0.8
+cell_size_meters = 0.5
+
+# 车辆半径(米)- 用于障碍物膨胀计算
+vehicle_radius_meters = 0.3
+
+# 安全间隙(米)- 额外的安全距离
+safety_margin_meters = 0.2
+
+# 膨胀半径(网格单元数)
+inflation_radius_cells = 2
+
+# 扫描高度(米)
+scan_height_meters = 0.1
+
+[path_planning]
+# 最大高度差(米)- 楼梯、坡道可接受的高度阈值
+max_height_diff_meters = 0.35
+
+# 车辆尺寸(米)
+vehicle_height_meters = 2.0
+vehicle_length_meters = 2.5
+vehicle_width_meters = 1.8
+
+# 默认路径策略:"Shortest" | "Straightest" | "SafetyFirst"
+default_path_strategy = "Straightest"
+
+# 启用路径优化(减少转弯点)
+enable_path_optimization = true
+
+[visualization]
+# 网格点大小(像素)
+grid_point_size = 5.0
+
+# 路径线宽(像素)
+path_line_width = 2.0
+
+# 路径点大小(模型单位)
+path_point_size = 50.0
+
+# 启用网格可视化
+enable_grid_visualization = false
+
+# 启用多层网格可视化
+enable_multi_layer_visualization = true
+
+[animation]
+# 默认动画速度(米/秒)
+default_speed_meters_per_second = 1.5
+
+# 动画帧率(帧/秒)
+frame_rate = 30
+
+# 步进间隔(毫秒)
+step_interval_ms = 100
+
+# 启用平滑插值
+enable_smooth_interpolation = true
+
+[collision]
+# 碰撞检测步长(米)
+detection_step_meters = 0.1
+
+# 碰撞容差(米)
+collision_tolerance_meters = 0.01
+
+# 启用实时碰撞检测
+enable_realtime_detection = true
+
+# 自动生成碰撞报告
+auto_generate_report = true
diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md
index 1c5bd81..081d75c 100644
--- a/doc/requirement/todo_features.md
+++ b/doc/requirement/todo_features.md
@@ -2,6 +2,10 @@
## 功能点
+### [2025/10/11]
+
+1. [x] (功能)实现系统配置管理,采用toml格式保存配置文件
+
### [2025/10/09]
1. [x] (优化)支持楼梯场景的3D路径规划
diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs
new file mode 100644
index 0000000..ab82acb
--- /dev/null
+++ b/src/Core/Config/ConfigManager.cs
@@ -0,0 +1,374 @@
+using System;
+using System.IO;
+using System.Text;
+using Tomlyn;
+using Tomlyn.Model;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport.Core.Config
+{
+ ///
+ /// 系统配置管理器
+ /// 负责 TOML 配置文件的读取、保存和管理
+ ///
+ public class ConfigManager
+ {
+ private static ConfigManager _instance;
+ private static readonly object _lock = new object();
+
+ ///
+ /// 单例实例
+ ///
+ public static ConfigManager Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ lock (_lock)
+ {
+ if (_instance == null)
+ {
+ _instance = new ConfigManager();
+ }
+ }
+ }
+ return _instance;
+ }
+ }
+
+ ///
+ /// 配置文件路径
+ ///
+ public static string ConfigFilePath
+ {
+ get
+ {
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
+ "Autodesk",
+ "Navisworks Manage 2026",
+ "plugins",
+ "NavisworksTransportPlugin",
+ "config.toml"
+ );
+ }
+ }
+
+ ///
+ /// 配置目录
+ ///
+ public static string ConfigDirectory
+ {
+ get { return Path.GetDirectoryName(ConfigFilePath); }
+ }
+
+ private SystemConfig _currentConfig;
+
+ private ConfigManager()
+ {
+ _currentConfig = LoadOrCreateDefault();
+ }
+
+ ///
+ /// 获取当前配置
+ ///
+ public SystemConfig Current
+ {
+ get { return _currentConfig; }
+ }
+
+ ///
+ /// 加载配置文件,如果不存在则创建默认配置
+ ///
+ public SystemConfig LoadOrCreateDefault()
+ {
+ try
+ {
+ if (!File.Exists(ConfigFilePath))
+ {
+ LogManager.Info($"配置文件不存在,创建默认配置: {ConfigFilePath}");
+ var defaultConfig = new SystemConfig();
+ SaveConfig(defaultConfig);
+ return defaultConfig;
+ }
+
+ LogManager.Info($"加载配置文件: {ConfigFilePath}");
+ var tomlContent = File.ReadAllText(ConfigFilePath, Encoding.UTF8);
+ var config = LoadFromToml(tomlContent);
+
+ LogManager.Info("配置文件加载成功");
+ return config;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"加载配置文件失败: {ex.Message}");
+ LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
+
+ // 加载失败时返回默认配置
+ LogManager.Info("使用默认配置");
+ return new SystemConfig();
+ }
+ }
+
+ ///
+ /// 从 TOML 字符串加载配置
+ ///
+ private SystemConfig LoadFromToml(string tomlContent)
+ {
+ var model = Toml.ToModel(tomlContent);
+ var config = new SystemConfig();
+
+ // 加载网格生成配置
+ if (model.ContainsKey("grid_generation"))
+ {
+ var gridGen = model["grid_generation"] as TomlTable;
+ if (gridGen != null)
+ {
+ config.GridGeneration.CellSizeMeters = GetDouble(gridGen, "cell_size_meters", 0.5);
+ config.GridGeneration.VehicleRadiusMeters = GetDouble(gridGen, "vehicle_radius_meters", 0.3);
+ config.GridGeneration.SafetyMarginMeters = GetDouble(gridGen, "safety_margin_meters", 0.2);
+ config.GridGeneration.InflationRadiusCells = GetInt(gridGen, "inflation_radius_cells", 2);
+ config.GridGeneration.ScanHeightMeters = GetDouble(gridGen, "scan_height_meters", 0.1);
+ }
+ }
+
+ // 加载路径规划配置
+ if (model.ContainsKey("path_planning"))
+ {
+ var pathPlan = model["path_planning"] as TomlTable;
+ if (pathPlan != null)
+ {
+ config.PathPlanning.MaxHeightDiffMeters = GetDouble(pathPlan, "max_height_diff_meters", 0.35);
+ config.PathPlanning.VehicleHeightMeters = GetDouble(pathPlan, "vehicle_height_meters", 2.0);
+ config.PathPlanning.VehicleLengthMeters = GetDouble(pathPlan, "vehicle_length_meters", 2.5);
+ config.PathPlanning.VehicleWidthMeters = GetDouble(pathPlan, "vehicle_width_meters", 1.8);
+ config.PathPlanning.DefaultPathStrategy = GetString(pathPlan, "default_path_strategy", "Straightest");
+ config.PathPlanning.EnablePathOptimization = GetBool(pathPlan, "enable_path_optimization", true);
+ }
+ }
+
+ // 加载可视化配置
+ if (model.ContainsKey("visualization"))
+ {
+ var visual = model["visualization"] as TomlTable;
+ if (visual != null)
+ {
+ config.Visualization.GridPointSize = GetDouble(visual, "grid_point_size", 5.0);
+ config.Visualization.PathLineWidth = GetDouble(visual, "path_line_width", 2.0);
+ config.Visualization.PathPointSize = GetDouble(visual, "path_point_size", 50.0);
+ config.Visualization.EnableGridVisualization = GetBool(visual, "enable_grid_visualization", false);
+ config.Visualization.EnableMultiLayerVisualization = GetBool(visual, "enable_multi_layer_visualization", true);
+ }
+ }
+
+ // 加载动画配置
+ if (model.ContainsKey("animation"))
+ {
+ var anim = model["animation"] as TomlTable;
+ if (anim != null)
+ {
+ config.Animation.DefaultSpeedMetersPerSecond = GetDouble(anim, "default_speed_meters_per_second", 1.5);
+ config.Animation.FrameRate = GetInt(anim, "frame_rate", 30);
+ config.Animation.StepIntervalMs = GetInt(anim, "step_interval_ms", 100);
+ config.Animation.EnableSmoothInterpolation = GetBool(anim, "enable_smooth_interpolation", true);
+ }
+ }
+
+ // 加载碰撞检测配置
+ if (model.ContainsKey("collision"))
+ {
+ var collision = model["collision"] as TomlTable;
+ if (collision != null)
+ {
+ config.Collision.DetectionStepMeters = GetDouble(collision, "detection_step_meters", 0.1);
+ config.Collision.CollisionToleranceMeters = GetDouble(collision, "collision_tolerance_meters", 0.01);
+ config.Collision.EnableRealtimeDetection = GetBool(collision, "enable_realtime_detection", true);
+ config.Collision.AutoGenerateReport = GetBool(collision, "auto_generate_report", true);
+ }
+ }
+
+ return config;
+ }
+
+ ///
+ /// 保存配置到文件
+ ///
+ public void SaveConfig(SystemConfig config)
+ {
+ try
+ {
+ // 确保目录存在
+ Directory.CreateDirectory(ConfigDirectory);
+
+ var tomlContent = ConvertToToml(config);
+ File.WriteAllText(ConfigFilePath, tomlContent, Encoding.UTF8);
+
+ _currentConfig = config;
+ LogManager.Info($"配置文件已保存: {ConfigFilePath}");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"保存配置文件失败: {ex.Message}");
+ LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
+ throw;
+ }
+ }
+
+ ///
+ /// 将配置转换为 TOML 字符串
+ ///
+ private string ConvertToToml(SystemConfig config)
+ {
+ var sb = new StringBuilder();
+
+ // 添加文件头注释
+ sb.AppendLine("# NavisworksTransport 系统配置文件");
+ sb.AppendLine("# 单位说明:长度单位均为米(m),时间单位为秒(s)");
+ sb.AppendLine("# 自动生成时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
+ sb.AppendLine();
+
+ // 网格生成配置
+ sb.AppendLine("[grid_generation]");
+ sb.AppendLine("# 网格单元大小(米)- 推荐值:0.3-0.8");
+ sb.AppendLine($"cell_size_meters = {config.GridGeneration.CellSizeMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 车辆半径(米)- 用于障碍物膨胀计算");
+ sb.AppendLine($"vehicle_radius_meters = {config.GridGeneration.VehicleRadiusMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 安全间隙(米)- 额外的安全距离");
+ sb.AppendLine($"safety_margin_meters = {config.GridGeneration.SafetyMarginMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 膨胀半径(网格单元数)");
+ sb.AppendLine($"inflation_radius_cells = {config.GridGeneration.InflationRadiusCells}");
+ sb.AppendLine();
+ sb.AppendLine("# 扫描高度(米)");
+ sb.AppendLine($"scan_height_meters = {config.GridGeneration.ScanHeightMeters}");
+ sb.AppendLine();
+
+ // 路径规划配置
+ sb.AppendLine("[path_planning]");
+ sb.AppendLine("# 最大高度差(米)- 楼梯、坡道可接受的高度阈值");
+ sb.AppendLine($"max_height_diff_meters = {config.PathPlanning.MaxHeightDiffMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 车辆尺寸(米)");
+ sb.AppendLine($"vehicle_height_meters = {config.PathPlanning.VehicleHeightMeters}");
+ sb.AppendLine($"vehicle_length_meters = {config.PathPlanning.VehicleLengthMeters}");
+ sb.AppendLine($"vehicle_width_meters = {config.PathPlanning.VehicleWidthMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 默认路径策略:\"Shortest\" | \"Straightest\" | \"SafetyFirst\"");
+ sb.AppendLine($"default_path_strategy = \"{config.PathPlanning.DefaultPathStrategy}\"");
+ sb.AppendLine();
+ sb.AppendLine("# 启用路径优化(减少转弯点)");
+ sb.AppendLine($"enable_path_optimization = {config.PathPlanning.EnablePathOptimization.ToString().ToLower()}");
+ sb.AppendLine();
+
+ // 可视化配置
+ sb.AppendLine("[visualization]");
+ sb.AppendLine("# 网格点大小(像素)");
+ sb.AppendLine($"grid_point_size = {config.Visualization.GridPointSize}");
+ sb.AppendLine();
+ sb.AppendLine("# 路径线宽(像素)");
+ sb.AppendLine($"path_line_width = {config.Visualization.PathLineWidth}");
+ sb.AppendLine();
+ sb.AppendLine("# 路径点大小(模型单位)");
+ sb.AppendLine($"path_point_size = {config.Visualization.PathPointSize}");
+ sb.AppendLine();
+ sb.AppendLine("# 启用网格可视化");
+ sb.AppendLine($"enable_grid_visualization = {config.Visualization.EnableGridVisualization.ToString().ToLower()}");
+ sb.AppendLine();
+ sb.AppendLine("# 启用多层网格可视化");
+ sb.AppendLine($"enable_multi_layer_visualization = {config.Visualization.EnableMultiLayerVisualization.ToString().ToLower()}");
+ sb.AppendLine();
+
+ // 动画配置
+ sb.AppendLine("[animation]");
+ sb.AppendLine("# 默认动画速度(米/秒)");
+ sb.AppendLine($"default_speed_meters_per_second = {config.Animation.DefaultSpeedMetersPerSecond}");
+ sb.AppendLine();
+ sb.AppendLine("# 动画帧率(帧/秒)");
+ sb.AppendLine($"frame_rate = {config.Animation.FrameRate}");
+ sb.AppendLine();
+ sb.AppendLine("# 步进间隔(毫秒)");
+ sb.AppendLine($"step_interval_ms = {config.Animation.StepIntervalMs}");
+ sb.AppendLine();
+ sb.AppendLine("# 启用平滑插值");
+ sb.AppendLine($"enable_smooth_interpolation = {config.Animation.EnableSmoothInterpolation.ToString().ToLower()}");
+ sb.AppendLine();
+
+ // 碰撞检测配置
+ sb.AppendLine("[collision]");
+ sb.AppendLine("# 碰撞检测步长(米)");
+ sb.AppendLine($"detection_step_meters = {config.Collision.DetectionStepMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 碰撞容差(米)");
+ sb.AppendLine($"collision_tolerance_meters = {config.Collision.CollisionToleranceMeters}");
+ sb.AppendLine();
+ sb.AppendLine("# 启用实时碰撞检测");
+ sb.AppendLine($"enable_realtime_detection = {config.Collision.EnableRealtimeDetection.ToString().ToLower()}");
+ sb.AppendLine();
+ sb.AppendLine("# 自动生成碰撞报告");
+ sb.AppendLine($"auto_generate_report = {config.Collision.AutoGenerateReport.ToString().ToLower()}");
+
+ return sb.ToString();
+ }
+
+ ///
+ /// 重新加载配置
+ ///
+ public void Reload()
+ {
+ _currentConfig = LoadOrCreateDefault();
+ }
+
+ ///
+ /// 重置为默认配置
+ ///
+ public void ResetToDefault()
+ {
+ var defaultConfig = new SystemConfig();
+ SaveConfig(defaultConfig);
+ }
+
+ // 辅助方法:从 TomlTable 获取值
+ private double GetDouble(TomlTable table, string key, double defaultValue)
+ {
+ if (table.ContainsKey(key))
+ {
+ var value = table[key];
+ if (value is long longValue)
+ return (double)longValue;
+ if (value is double doubleValue)
+ return doubleValue;
+ }
+ return defaultValue;
+ }
+
+ private int GetInt(TomlTable table, string key, int defaultValue)
+ {
+ if (table.ContainsKey(key) && table[key] is long longValue)
+ {
+ return (int)longValue;
+ }
+ return defaultValue;
+ }
+
+ private bool GetBool(TomlTable table, string key, bool defaultValue)
+ {
+ if (table.ContainsKey(key) && table[key] is bool boolValue)
+ {
+ return boolValue;
+ }
+ return defaultValue;
+ }
+
+ private string GetString(TomlTable table, string key, string defaultValue)
+ {
+ if (table.ContainsKey(key) && table[key] is string stringValue)
+ {
+ return stringValue;
+ }
+ return defaultValue;
+ }
+ }
+}
diff --git a/src/Core/Config/SystemConfig.cs b/src/Core/Config/SystemConfig.cs
new file mode 100644
index 0000000..62f6d78
--- /dev/null
+++ b/src/Core/Config/SystemConfig.cs
@@ -0,0 +1,207 @@
+using System;
+
+namespace NavisworksTransport.Core.Config
+{
+ ///
+ /// 系统配置根类
+ ///
+ public class SystemConfig
+ {
+ ///
+ /// 网格生成配置
+ ///
+ public GridGenerationConfig GridGeneration { get; set; } = new GridGenerationConfig();
+
+ ///
+ /// 路径规划配置
+ ///
+ public PathPlanningConfig PathPlanning { get; set; } = new PathPlanningConfig();
+
+ ///
+ /// 可视化配置
+ ///
+ public VisualizationConfig Visualization { get; set; } = new VisualizationConfig();
+
+ ///
+ /// 动画配置
+ ///
+ public AnimationConfig Animation { get; set; } = new AnimationConfig();
+
+ ///
+ /// 碰撞检测配置
+ ///
+ public CollisionConfig Collision { get; set; } = new CollisionConfig();
+ }
+
+ ///
+ /// 网格生成配置
+ ///
+ public class GridGenerationConfig
+ {
+ ///
+ /// 网格单元大小(米)
+ /// 推荐值:0.3-0.8
+ ///
+ public double CellSizeMeters { get; set; } = 0.5;
+
+ ///
+ /// 车辆半径(米)
+ /// 用于障碍物膨胀计算
+ ///
+ public double VehicleRadiusMeters { get; set; } = 0.3;
+
+ ///
+ /// 安全间隙(米)
+ /// 额外的安全距离
+ ///
+ public double SafetyMarginMeters { get; set; } = 0.2;
+
+ ///
+ /// 膨胀半径(网格单元数)
+ /// 障碍物膨胀的单元格数量
+ ///
+ public int InflationRadiusCells { get; set; } = 2;
+
+ ///
+ /// 扫描高度(米)
+ /// 障碍物扫描的垂直步进高度
+ ///
+ public double ScanHeightMeters { get; set; } = 0.1;
+ }
+
+ ///
+ /// 路径规划配置
+ ///
+ public class PathPlanningConfig
+ {
+ ///
+ /// 最大高度差(米)
+ /// 楼梯、坡道可接受的高度阈值
+ ///
+ public double MaxHeightDiffMeters { get; set; } = 0.35;
+
+ ///
+ /// 车辆高度(米)
+ /// 用于通行性判断
+ ///
+ public double VehicleHeightMeters { get; set; } = 2.0;
+
+ ///
+ /// 车辆长度(米)
+ /// 用于转弯半径计算
+ ///
+ public double VehicleLengthMeters { get; set; } = 2.5;
+
+ ///
+ /// 车辆宽度(米)
+ /// 用于通道宽度判断
+ ///
+ public double VehicleWidthMeters { get; set; } = 1.8;
+
+ ///
+ /// 默认路径策略
+ /// "Shortest" - 最短路径优先
+ /// "Straightest" - 直线优先
+ /// "SafetyFirst" - 安全优先
+ ///
+ public string DefaultPathStrategy { get; set; } = "Straightest";
+
+ ///
+ /// 路径优化启用
+ /// 是否启用路径点优化(减少转弯点)
+ ///
+ public bool EnablePathOptimization { get; set; } = true;
+ }
+
+ ///
+ /// 可视化配置
+ ///
+ public class VisualizationConfig
+ {
+ ///
+ /// 网格点大小(像素)
+ ///
+ public double GridPointSize { get; set; } = 5.0;
+
+ ///
+ /// 路径线宽(像素)
+ ///
+ public double PathLineWidth { get; set; } = 2.0;
+
+ ///
+ /// 路径点大小(模型单位)
+ ///
+ public double PathPointSize { get; set; } = 50.0;
+
+ ///
+ /// 启用网格可视化
+ /// 是否默认显示网格地图
+ ///
+ public bool EnableGridVisualization { get; set; } = false;
+
+ ///
+ /// 启用多层网格可视化
+ /// 是否显示多个高度层的网格
+ ///
+ public bool EnableMultiLayerVisualization { get; set; } = true;
+ }
+
+ ///
+ /// 动画配置
+ ///
+ public class AnimationConfig
+ {
+ ///
+ /// 动画速度(米/秒)
+ /// 默认车辆移动速度
+ ///
+ public double DefaultSpeedMetersPerSecond { get; set; } = 1.5;
+
+ ///
+ /// 动画帧率(帧/秒)
+ ///
+ public int FrameRate { get; set; } = 30;
+
+ ///
+ /// 步进间隔(毫秒)
+ /// 步进模式下每步的时间间隔
+ ///
+ public int StepIntervalMs { get; set; } = 100;
+
+ ///
+ /// 启用平滑插值
+ /// 是否在路径点之间使用平滑插值
+ ///
+ public bool EnableSmoothInterpolation { get; set; } = true;
+ }
+
+ ///
+ /// 碰撞检测配置
+ ///
+ public class CollisionConfig
+ {
+ ///
+ /// 碰撞检测步长(米)
+ /// 动画过程中每次检测的移动距离
+ ///
+ public double DetectionStepMeters { get; set; } = 0.1;
+
+ ///
+ /// 碰撞容差(米)
+ /// 判定为碰撞的最小距离
+ ///
+ public double CollisionToleranceMeters { get; set; } = 0.01;
+
+ ///
+ /// 启用实时碰撞检测
+ /// 动画播放时是否实时检测碰撞
+ ///
+ public bool EnableRealtimeDetection { get; set; } = true;
+
+ ///
+ /// 自动生成碰撞报告
+ /// 动画结束后是否自动生成报告
+ ///
+ public bool AutoGenerateReport { get; set; } = true;
+ }
+}
diff --git a/src/Core/PathClickToolPlugin.cs b/src/Core/PathClickToolPlugin.cs
index f72dd2e..f663ba4 100644
--- a/src/Core/PathClickToolPlugin.cs
+++ b/src/Core/PathClickToolPlugin.cs
@@ -15,7 +15,7 @@ namespace NavisworksTransport
///
public PathClickToolPlugin()
{
- LogManager.WriteLog("[ToolPlugin] PathClickToolPlugin实例已创建");
+ LogManager.Debug("[ToolPlugin] PathClickToolPlugin实例已创建");
}
///
/// 点击事件,传递精确的点击坐标和对象
@@ -50,40 +50,40 @@ namespace NavisworksTransport
///
public override bool MouseDown(View view, KeyModifiers modifiers, ushort button, int x, int y, double timeOffset)
{
- LogManager.WriteLog("[ToolPlugin] ★★★ MouseDown方法被调用 ★★★");
+ LogManager.Debug("[ToolPlugin] ★★★ MouseDown方法被调用 ★★★");
try
{
- LogManager.WriteLog("[ToolPlugin] ===== 鼠标点击事件 =====");
- LogManager.WriteLog($"[ToolPlugin] 屏幕坐标: ({x}, {y})");
- LogManager.WriteLog($"[ToolPlugin] 按键: {button}, 修饰键: {modifiers}");
+ LogManager.Debug("[ToolPlugin] ===== 鼠标点击事件 =====");
+ LogManager.Debug($"[ToolPlugin] 屏幕坐标: ({x}, {y})");
+ LogManager.Debug($"[ToolPlugin] 按键: {button}, 修饰键: {modifiers}");
// 只处理左键点击
if (button == 1) // 左键
{
- LogManager.WriteLog("[ToolPlugin] 检测到左键点击,开始处理");
+ LogManager.Debug("[ToolPlugin] 检测到左键点击,开始处理");
// 使用PickItemFromPoint获取精确的3D坐标
PickItemResult itemResult = view.PickItemFromPoint(x, y);
if (itemResult != null)
{
- LogManager.WriteLog("[ToolPlugin] ✓ PickItemFromPoint成功");
- LogManager.WriteLog($"[ToolPlugin] 精确3D坐标: ({itemResult.Point.X:F3}, {itemResult.Point.Y:F3}, {itemResult.Point.Z:F3})");
- LogManager.WriteLog($"[ToolPlugin] 选中对象: {itemResult.ModelItem?.DisplayName ?? "NULL"}");
+ LogManager.Debug("[ToolPlugin] ✓ PickItemFromPoint成功");
+ LogManager.Debug($"[ToolPlugin] 精确3D坐标: ({itemResult.Point.X:F3}, {itemResult.Point.Y:F3}, {itemResult.Point.Z:F3})");
+ LogManager.Debug($"[ToolPlugin] 选中对象: {itemResult.ModelItem?.DisplayName ?? "NULL"}");
// 触发事件,将精确坐标传递给PathPlanningManager
MouseClicked?.Invoke(this, itemResult);
-
- LogManager.WriteLog("[ToolPlugin] 事件已触发");
+
+ LogManager.Debug("[ToolPlugin] 事件已触发");
}
else
{
- LogManager.WriteLog("[ToolPlugin] ✗ PickItemFromPoint返回null(未点击到对象)");
+ LogManager.Debug("[ToolPlugin] ✗ PickItemFromPoint返回null(未点击到对象)");
}
}
else
{
- LogManager.WriteLog($"[ToolPlugin] 忽略非左键点击: {button}");
+ LogManager.Debug($"[ToolPlugin] 忽略非左键点击: {button}");
}
// 返回false表示继续传递事件给其他处理程序
@@ -91,8 +91,8 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[ToolPlugin] 异常: {ex.Message}");
- LogManager.WriteLog($"[ToolPlugin] 堆栈: {ex.StackTrace}");
+ LogManager.Error($"[ToolPlugin] 异常: {ex.Message}");
+ LogManager.Error($"[ToolPlugin] 堆栈: {ex.StackTrace}");
return false;
}
}
diff --git a/src/Core/PathInputMonitor.cs b/src/Core/PathInputMonitor.cs
index 6a53120..406f330 100644
--- a/src/Core/PathInputMonitor.cs
+++ b/src/Core/PathInputMonitor.cs
@@ -52,7 +52,7 @@ namespace NavisworksTransport
var currentTool = Application.MainDocument.Tool.Value;
if (currentTool != Tool.CustomToolPlugin)
{
- LogManager.WriteLog($"[InputMonitor] 用户按空格键,当前工具为{currentTool},重新激活工具");
+ LogManager.Info($"[InputMonitor] 用户按空格键,当前工具为{currentTool},重新激活工具");
pathManager.ReactivateToolPlugin();
return true;
}
@@ -63,7 +63,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[InputMonitor] 处理键盘事件异常: {ex.Message}");
+ LogManager.Error($"[InputMonitor] 处理键盘事件异常: {ex.Message}");
return false;
}
}
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index 411dce4..0ab45d2 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -114,7 +114,7 @@ namespace NavisworksTransport
{
// 设置静态引用,确保所有地方都使用同一个实例
_activePathManager = this;
- LogManager.WriteLog($"[路径管理] 设置_activePathManager静态引用, ManagerId: {_managerId}");
+ LogManager.Debug($"[路径管理] 设置_activePathManager静态引用, ManagerId: {_managerId}");
// 尝试初始化路径分析数据库
EnsureDatabaseInitialized();
@@ -156,21 +156,21 @@ namespace NavisworksTransport
_renderPlugin = PathPointRenderPlugin.Instance;
if (_renderPlugin != null)
{
- LogManager.WriteLog("[路径管理] ✅ PathPointRenderPlugin实例获取成功");
- LogManager.WriteLog($"[路径管理] 渲染插件状态 - 启用: {_renderPlugin.IsEnabled}, 标记数量: {_renderPlugin.MarkerCount}");
+ LogManager.Info("[路径管理] ✅ PathPointRenderPlugin实例获取成功");
+ LogManager.Debug($"[路径管理] 渲染插件状态 - 启用: {_renderPlugin.IsEnabled}, 标记数量: {_renderPlugin.MarkerCount}");
// 推送默认的网格大小和车辆参数,确保渲染插件有合理的初始值
InitializeRenderPluginDefaults();
}
else
{
- LogManager.WriteLog("[路径管理] ❌ PathPointRenderPlugin实例尚未就绪,将在后续尝试获取");
+ LogManager.Warning("[路径管理] ❌ PathPointRenderPlugin实例尚未就绪,将在后续尝试获取");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[路径管理] PathPointRenderPlugin实例获取失败: {ex.Message}");
- LogManager.WriteLog($"[路径管理] 异常堆栈: {ex.StackTrace}");
+ LogManager.Error($"[路径管理] PathPointRenderPlugin实例获取失败: {ex.Message}");
+ LogManager.Error($"[路径管理] 异常堆栈: {ex.StackTrace}");
_renderPlugin = null;
}
@@ -797,26 +797,26 @@ namespace NavisworksTransport
{
try
{
- LogManager.WriteLog("[事件清理] ===== 开始执行StopClickTool - 完整事件订阅清理 =====");
+ LogManager.Debug("[事件清理] ===== 开始执行StopClickTool - 完整事件订阅清理 =====");
// 1. 停用ToolPlugin并清理事件订阅
DeactivateToolPlugin();
// 2. 简化的事件订阅清理 - 移除危险的反射操作
- LogManager.WriteLog("[事件清理] 执行安全的事件订阅清理");
+ LogManager.Debug("[事件清理] 执行安全的事件订阅清理");
try
{
// 安全地移除事件订阅,多次取消订阅同一处理程序是安全的
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
- LogManager.WriteLog("[事件清理] 已安全移除PathPlanningManager.OnToolPluginMouseClicked订阅");
+ LogManager.Debug("[事件清理] 已安全移除PathPlanningManager.OnToolPluginMouseClicked订阅");
}
catch (Exception cleanupEx)
{
- LogManager.WriteLog($"[事件清理] 事件清理过程异常: {cleanupEx.Message}");
+ LogManager.Error($"[事件清理] 事件清理过程异常: {cleanupEx.Message}");
}
// 注意:移除了PathEditState设置,StopClickTool只管理工具插件状态,不修改业务逻辑状态
- LogManager.WriteLog("[事件清理] ===== StopClickTool执行完成,所有事件订阅已清理 =====");
+ LogManager.Debug("[事件清理] ===== StopClickTool执行完成,所有事件订阅已清理 =====");
}
catch (Exception ex)
{
@@ -2402,80 +2402,80 @@ namespace NavisworksTransport
// 如果已经激活,检查是否需要订阅事件
if (_isToolPluginActive)
{
- LogManager.WriteLog("[ToolPlugin] ToolPlugin已激活,检查事件订阅状态");
+ LogManager.Debug("[ToolPlugin] ToolPlugin已激活,检查事件订阅状态");
if (subscribeToEvents)
{
// 确保事件订阅(避免重复订阅)
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
- LogManager.WriteLog("[ToolPlugin] 已确保PathPlanningManager事件订阅");
+ LogManager.Debug("[ToolPlugin] 已确保PathPlanningManager事件订阅");
}
return true;
}
try
{
- LogManager.WriteLog("[ToolPlugin] ===== 开始激活ToolPlugin =====");
- LogManager.WriteLog($"[ToolPlugin] 订阅事件: {subscribeToEvents}");
- LogManager.WriteLog($"[ToolPlugin] 当前应用程序状态: {Application.IsAutomated}");
- LogManager.WriteLog($"[ToolPlugin] 当前文档状态: {Application.ActiveDocument?.Title ?? "NULL"}");
+ LogManager.Debug("[ToolPlugin] ===== 开始激活ToolPlugin =====");
+ LogManager.Debug($"[ToolPlugin] 订阅事件: {subscribeToEvents}");
+ LogManager.Debug($"[ToolPlugin] 当前应用程序状态: {Application.IsAutomated}");
+ LogManager.Debug($"[ToolPlugin] 当前文档状态: {Application.ActiveDocument?.Title ?? "NULL"}");
// 1. 加载插件程序集
- LogManager.WriteLog("[ToolPlugin] 步骤1: 加载插件程序集");
+ LogManager.Debug("[ToolPlugin] 步骤1: 加载插件程序集");
var assemblyPath = PathClickToolPlugin.AssemblyPath;
- LogManager.WriteLog($"[ToolPlugin] 程序集路径: {assemblyPath}");
- LogManager.WriteLog($"[ToolPlugin] 程序集文件是否存在: {System.IO.File.Exists(assemblyPath)}");
+ LogManager.Debug($"[ToolPlugin] 程序集路径: {assemblyPath}");
+ LogManager.Debug($"[ToolPlugin] 程序集文件是否存在: {System.IO.File.Exists(assemblyPath)}");
Application.Plugins.AddPluginAssembly(assemblyPath);
- LogManager.WriteLog("[ToolPlugin] ✓ 程序集加载完成");
+ LogManager.Debug("[ToolPlugin] ✓ 程序集加载完成");
// 2. 查找插件
- LogManager.WriteLog("[ToolPlugin] 步骤2: 查找插件");
+ LogManager.Debug("[ToolPlugin] 步骤2: 查找插件");
ToolPluginRecord toolPluginRecord = (ToolPluginRecord)Application.Plugins.FindPlugin("PathClickTool.NavisworksTransport");
if (toolPluginRecord == null)
{
- LogManager.WriteLog("[ToolPlugin] ✗ 错误: 无法找到PathClickTool插件");
+ LogManager.Error("[ToolPlugin] ✗ 错误: 无法找到PathClickTool插件");
return false;
}
- LogManager.WriteLog("[ToolPlugin] ✓ 插件查找成功");
+ LogManager.Debug("[ToolPlugin] ✓ 插件查找成功");
// 3. 加载插件
- LogManager.WriteLog("[ToolPlugin] 步骤3: 加载插件");
+ LogManager.Debug("[ToolPlugin] 步骤3: 加载插件");
var loadedPlugin = toolPluginRecord.LoadPlugin();
if (loadedPlugin == null)
{
- LogManager.WriteLog("[ToolPlugin] ✗ 错误: 插件加载失败");
+ LogManager.Error("[ToolPlugin] ✗ 错误: 插件加载失败");
return false;
}
- LogManager.WriteLog("[ToolPlugin] ✓ 插件加载成功");
+ LogManager.Debug("[ToolPlugin] ✓ 插件加载成功");
// 4. 设置为活动工具
- LogManager.WriteLog("[ToolPlugin] 步骤4: 设置为活动工具");
+ LogManager.Debug("[ToolPlugin] 步骤4: 设置为活动工具");
// 先重置工具状态,清除可能的导航工具
// 这一步很重要,确保从导航工具(如Pan、Orbit)切换回自定义工具
Application.MainDocument.Tool.Value = Tool.None;
- LogManager.WriteLog("[ToolPlugin] 已重置工具状态为None");
+ LogManager.Debug("[ToolPlugin] 已重置工具状态为None");
// 然后设置自定义工具插件
Application.MainDocument.Tool.SetCustomToolPlugin(loadedPlugin);
- LogManager.WriteLog("[ToolPlugin] ✓ 工具设置成功");
+ LogManager.Debug("[ToolPlugin] ✓ 工具设置成功");
// 5. 根据参数决定是否订阅点击事件
if (subscribeToEvents)
{
- LogManager.WriteLog("[ToolPlugin] 步骤5: 订阅点击事件");
+ LogManager.Debug("[ToolPlugin] 步骤5: 订阅点击事件");
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
- LogManager.WriteLog("[ToolPlugin] ✓ PathPlanningManager事件订阅成功");
+ LogManager.Debug("[ToolPlugin] ✓ PathPlanningManager事件订阅成功");
}
else
{
- LogManager.WriteLog("[ToolPlugin] 步骤5: 跳过事件订阅(由外部组件管理)");
+ LogManager.Debug("[ToolPlugin] 步骤5: 跳过事件订阅(由外部组件管理)");
}
_isToolPluginActive = true;
- LogManager.WriteLog("[ToolPlugin] ===== ToolPlugin激活完成 =====");
+ LogManager.Info("[ToolPlugin] ===== ToolPlugin激活完成 =====");
return true;
}
catch (Exception ex)
@@ -2503,7 +2503,7 @@ namespace NavisworksTransport
var currentTool = Application.MainDocument.Tool.Value;
if (currentTool != Tool.CustomToolPlugin)
{
- LogManager.WriteLog($"[ReactivateToolPlugin] 当前工具为{currentTool},开始重新激活ToolPlugin");
+ LogManager.Debug($"[ReactivateToolPlugin] 当前工具为{currentTool},开始重新激活ToolPlugin");
// 重要:先将激活标志设置为false,强制执行完整的激活流程
_isToolPluginActive = false;
@@ -2511,23 +2511,23 @@ namespace NavisworksTransport
// 调用现有的激活方法,但不重复订阅事件
if (ActivateToolPlugin(false))
{
- LogManager.WriteLog("[ReactivateToolPlugin] ToolPlugin重新激活成功");
+ LogManager.Info("[ReactivateToolPlugin] ToolPlugin重新激活成功");
RaiseStatusChanged("工具已重新激活", PathPlanningStatusType.Info);
}
else
{
- LogManager.WriteLog("[ReactivateToolPlugin] ToolPlugin重新激活失败");
+ LogManager.Warning("[ReactivateToolPlugin] ToolPlugin重新激活失败");
RaiseErrorOccurred("无法重新激活编辑工具");
}
}
else
{
- LogManager.WriteLog("[ReactivateToolPlugin] 当前已是CustomToolPlugin,无需重新激活");
+ LogManager.Debug("[ReactivateToolPlugin] 当前已是CustomToolPlugin,无需重新激活");
}
}
else
{
- LogManager.WriteLog($"[ReactivateToolPlugin] 跳过重新激活 - PathEditState: {PathEditState}");
+ LogManager.Debug($"[ReactivateToolPlugin] 跳过重新激活 - PathEditState: {PathEditState}");
}
}
catch (Exception ex)
@@ -2547,7 +2547,7 @@ namespace NavisworksTransport
// 如果在自动路径规划模式,则跳过处理(应该由PathEditingViewModel处理)
if (IsInAutoPathMode)
{
- LogManager.WriteLog("[ToolPlugin事件] 当前在自动路径规划模式,跳过PathPlanningManager处理");
+ LogManager.Debug("[ToolPlugin事件] 当前在自动路径规划模式,跳过PathPlanningManager处理");
return;
}
@@ -2567,12 +2567,12 @@ namespace NavisworksTransport
private void ProcessManualPathEditing(PickItemResult pickResult)
{
// 检查当前选中的通道状态
- LogManager.WriteLog($"[手动编辑] 当前_selectedChannels状态: {(_walkableAreas == null ? "NULL" : $"包含{_walkableAreas.Count}个项目")}");
+ LogManager.Debug($"[手动编辑] 当前_selectedChannels状态: {(_walkableAreas == null ? "NULL" : $"包含{_walkableAreas.Count}个项目")}");
// 如果没有选中的通道,尝试实时搜索
if (_walkableAreas == null || _walkableAreas.Count == 0)
{
- LogManager.WriteLog("[手动编辑] 没有预选通道,开始实时搜索可通行的物流模型");
+ LogManager.Debug("[手动编辑] 没有预选通道,开始实时搜索可通行的物流模型");
SearchAndSetTraversableChannels();
}
@@ -2582,7 +2582,7 @@ namespace NavisworksTransport
bool isInTraversableLogisticsModel = IsItemInSelectedChannels(pickResult.ModelItem) ||
IsItemChildOfSelectedChannels(pickResult.ModelItem);
- LogManager.WriteLog($"[手动编辑] 在可通行的物流模型内: {isInTraversableLogisticsModel}");
+ LogManager.Debug($"[手动编辑] 在可通行的物流模型内: {isInTraversableLogisticsModel}");
if (isInTraversableLogisticsModel)
{
@@ -2590,50 +2590,50 @@ namespace NavisworksTransport
if (PathEditState == PathEditState.AddingPoints)
{
// 添加路径点模式 - 使用预览点
- LogManager.WriteLog("[手动编辑] 设置预览点位置");
+ LogManager.Debug("[手动编辑] 设置预览点位置");
var previewPoint = SetPreviewPoint(pickResult.Point);
if (previewPoint != null)
{
- LogManager.WriteLog($"[手动编辑] ✓ 预览点已设置: {previewPoint.Name}");
+ LogManager.Debug($"[手动编辑] ✓ 预览点已设置: {previewPoint.Name}");
}
else
{
- LogManager.WriteLog("[手动编辑] ✗ 预览点设置失败");
+ LogManager.Warning("[手动编辑] ✗ 预览点设置失败");
}
}
else if (PathEditState == PathEditState.EditingPoint)
{
// 修改路径点模式 - 设置预览位置
- LogManager.WriteLog("[手动编辑] 设置修改路径点预览位置");
+ LogManager.Debug("[手动编辑] 设置修改路径点预览位置");
SetEditingPreviewPoint(pickResult.Point);
- LogManager.WriteLog($"[手动编辑] ✓ 修改路径点预览位置已设置: ({pickResult.Point.X:F3}, {pickResult.Point.Y:F3}, {pickResult.Point.Z:F3})");
+ LogManager.Debug($"[手动编辑] ✓ 修改路径点预览位置已设置: ({pickResult.Point.X:F3}, {pickResult.Point.Y:F3}, {pickResult.Point.Z:F3})");
}
else
{
// 其他编辑模式 - 保持原有逻辑
- LogManager.WriteLog("[手动编辑] 调用AddPathPointIn3D添加路径点");
+ LogManager.Debug("[手动编辑] 调用AddPathPointIn3D添加路径点");
var pathPoint = AddPathPointIn3D(pickResult.Point);
if (pathPoint != null)
{
- LogManager.WriteLog($"[手动编辑] ✓ 路径点添加成功: {pathPoint.Name}");
+ LogManager.Debug($"[手动编辑] ✓ 路径点添加成功: {pathPoint.Name}");
}
else
{
- LogManager.WriteLog("[手动编辑] ✗ 路径点添加失败");
+ LogManager.Warning("[手动编辑] ✗ 路径点添加失败");
}
}
}
else
{
- LogManager.WriteLog("[手动编辑] ✗ 点击位置不在可通行的物流模型内");
+ LogManager.Debug("[手动编辑] ✗ 点击位置不在可通行的物流模型内");
RaiseErrorOccurred("点击位置不在物流通道内,请选择有效的物流路径位置");
}
}
else
{
- LogManager.WriteLog("[手动编辑] ✗ 未找到可通行的物流模型");
+ LogManager.Warning("[手动编辑] ✗ 未找到可通行的物流模型");
RaiseErrorOccurred("未找到可通行的物流通道,请先选择或配置物流通道");
}
}
@@ -2650,13 +2650,13 @@ namespace NavisworksTransport
{
// 使用CategoryAttributeManager统一接口获取物流项目
var logisticsItemsCollection = CategoryAttributeManager.GetAllLogisticsItems();
- LogManager.WriteLog($"[搜索通道] CategoryAttributeManager找到 {logisticsItemsCollection.Count} 个物流模型");
+ LogManager.Debug($"[搜索通道] CategoryAttributeManager找到 {logisticsItemsCollection.Count} 个物流模型");
if (logisticsItemsCollection.Count > 0)
{
// 筛选出可通行的物流模型
var traversableItems = CategoryAttributeManager.FilterTraversableItems(logisticsItemsCollection);
- LogManager.WriteLog($"[搜索通道] 筛选出 {traversableItems.Count} 个可通行的物流模型");
+ LogManager.Debug($"[搜索通道] 筛选出 {traversableItems.Count} 个可通行的物流模型");
// 临时设置为选中通道
if (_walkableAreas == null) _walkableAreas = new List();
@@ -2665,14 +2665,14 @@ namespace NavisworksTransport
foreach (ModelItem item in traversableItems)
{
_walkableAreas.Add(item);
- LogManager.WriteLog($"[搜索通道] 添加可通行模型: '{item.DisplayName}'");
+ LogManager.Debug($"[搜索通道] 添加可通行模型: '{item.DisplayName}'");
}
}
}
}
catch (Exception searchEx)
{
- LogManager.WriteLog($"[搜索通道] 实时搜索失败: {searchEx.Message}");
+ LogManager.Error($"[搜索通道] 实时搜索失败: {searchEx.Message}");
}
}
@@ -2768,7 +2768,7 @@ namespace NavisworksTransport
{
if (!_isToolPluginActive)
{
- LogManager.WriteLog("[ToolPlugin] ToolPlugin未激活,无需停用");
+ LogManager.Debug("[ToolPlugin] ToolPlugin未激活,无需停用");
return true;
}
@@ -2785,11 +2785,11 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[ToolPlugin] 重置工具状态失败: {ex.Message}");
+ LogManager.Warning($"[ToolPlugin] 重置工具状态失败: {ex.Message}");
}
_isToolPluginActive = false;
- LogManager.WriteLog("[ToolPlugin] ===== ToolPlugin停用完成 =====");
+ LogManager.Debug("[ToolPlugin] ===== ToolPlugin停用完成 =====");
return true;
}
catch (Exception ex)
@@ -2809,27 +2809,27 @@ namespace NavisworksTransport
{
try
{
- LogManager.WriteLog($"[工具插件重初始化] 开始强制重新初始化ToolPlugin,订阅事件: {subscribeToEvents}");
+ LogManager.Debug($"[工具插件重初始化] 开始强制重新初始化ToolPlugin,订阅事件: {subscribeToEvents}");
// 1. 停用当前ToolPlugin
bool deactivated = DeactivateToolPlugin();
- LogManager.WriteLog($"[工具插件重初始化] 停用结果: {deactivated}");
+ LogManager.Debug($"[工具插件重初始化] 停用结果: {deactivated}");
// 2. 强制重置激活状态
_isToolPluginActive = false;
- LogManager.WriteLog("[工具插件重初始化] 已重置激活状态标志");
+ LogManager.Debug("[工具插件重初始化] 已重置激活状态标志");
// 3. 重新激活ToolPlugin
bool activated = ActivateToolPlugin(subscribeToEvents);
- LogManager.WriteLog($"[工具插件重初始化] 激活结果(事件订阅: {subscribeToEvents}): {activated}");
+ LogManager.Debug($"[工具插件重初始化] 激活结果(事件订阅: {subscribeToEvents}): {activated}");
if (activated)
{
- LogManager.WriteLog("[工具插件重初始化] ToolPlugin重新初始化成功,已获得鼠标焦点");
+ LogManager.Info("[工具插件重初始化] ToolPlugin重新初始化成功,已获得鼠标焦点");
}
else
{
- LogManager.WriteLog("[工具插件重初始化] ToolPlugin激活失败");
+ LogManager.Error("[工具插件重初始化] ToolPlugin激活失败");
}
return activated;
diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs
index 35c4e66..a802623 100644
--- a/src/Core/PathPointRenderPlugin.cs
+++ b/src/Core/PathPointRenderPlugin.cs
@@ -447,7 +447,7 @@ namespace NavisworksTransport
catch (Exception ex)
{
// 渲染异常应该静默处理,避免影响Navisworks主程序
- LogManager.WriteLog($"[渲染异常] {ex.Message}");
+ LogManager.Error($"[渲染异常] {ex.Message}", ex);
// 不输出堆栈信息,避免日志过量
}
}
@@ -462,7 +462,6 @@ namespace NavisworksTransport
{
if (pathRoute == null)
{
- LogManager.WriteLog("[路径渲染] 路径数据为空");
return;
}
@@ -481,12 +480,11 @@ namespace NavisworksTransport
_pathVisualizations[pathRoute.Id] = visualization;
}
- LogManager.WriteLog($"[路径渲染] 渲染路径: {pathRoute.Name}, 点数: {pathRoute.Points.Count}");
RequestViewRefresh();
}
catch (Exception ex)
{
- LogManager.WriteLog($"[路径渲染] 渲染路径失败: {ex.Message}");
+ LogManager.Error($"[路径渲染] 渲染路径失败: {ex.Message}", ex);
}
}
@@ -497,7 +495,6 @@ namespace NavisworksTransport
{
if (pathRoute == null)
{
- LogManager.WriteLog("[点标记渲染] 路径数据为空");
return;
}
@@ -523,22 +520,12 @@ namespace NavisworksTransport
{
_pathVisualizations[pathRoute.Id] = visualization;
}
-
- // 网格可视化只打印统计日志,不打印详细日志
- if (!isGridVisualization)
- {
- LogManager.WriteLog($"[点标记渲染] 渲染点标记: {pathRoute.Name}, 点数: {pathRoute.Points.Count}");
- }
- else
- {
- LogManager.WriteLog($"[网格可视化] 渲染网格点: {pathRoute.Points.Count} 个可通行单元");
- }
RequestViewRefresh();
}
catch (Exception ex)
{
- LogManager.WriteLog($"[点标记渲染] 渲染点标记失败: {ex.Message}");
+ LogManager.Error($"[点标记渲染] 渲染点标记失败: {ex.Message}", ex);
}
}
@@ -572,12 +559,6 @@ namespace NavisworksTransport
}
visualization.LastUpdated = DateTime.Now;
-
- // 网格可视化不打印详细构建日志,避免日志泛滥
- if (!isGridVisualization)
- {
- LogManager.WriteLog($"[点标记构建] 已构建 {visualization.PointMarkers.Count} 个点标记,无连线");
- }
}
///
@@ -591,7 +572,6 @@ namespace NavisworksTransport
if (_pathVisualizations.TryGetValue(pathId, out var visualization))
{
BuildVisualization(visualization);
- LogManager.WriteLog($"[路径刷新] 刷新路径: {pathId}");
RequestViewRefresh();
}
}
@@ -628,7 +608,6 @@ namespace NavisworksTransport
if (normalPathIds.Count > 0)
{
- LogManager.WriteLog($"[路径刷新] 刷新普通路径: {normalPathIds.Count}个, 模式: {_visualizationMode}");
RequestViewRefresh();
}
}
@@ -644,7 +623,6 @@ namespace NavisworksTransport
{
if (_pathVisualizations.Remove(pathId))
{
- LogManager.WriteLog($"[路径移除] 移除路径: {pathId}");
RequestViewRefresh();
}
}
@@ -659,7 +637,6 @@ namespace NavisworksTransport
{
var count = _pathVisualizations.Count;
_pathVisualizations.Clear();
- LogManager.WriteLog($"[路径清空] 清空所有路径,共{count}个");
RequestViewRefresh();
}
}
@@ -682,23 +659,10 @@ namespace NavisworksTransport
var excludedSet = new HashSet(excludedPathIds.Where(id => !string.IsNullOrEmpty(id)));
var toRemove = _pathVisualizations.Keys.Where(id => !excludedSet.Contains(id)).ToList();
-
- // 记录当前状态
- LogManager.WriteLog($"[选择性清空] 当前路径数: {_pathVisualizations.Count}, 排除路径数: {excludedSet.Count}, 待清理路径数: {toRemove.Count}");
-
+
// 检查排除的路径是否实际存在
var existingExcluded = excludedSet.Where(id => _pathVisualizations.ContainsKey(id)).ToList();
var nonExistingExcluded = excludedSet.Where(id => !_pathVisualizations.ContainsKey(id)).ToList();
-
- if (nonExistingExcluded.Any())
- {
- LogManager.WriteLog($"[选择性清空] 注意:尝试保留的路径不存在: {string.Join(", ", nonExistingExcluded)}");
- }
-
- if (existingExcluded.Any())
- {
- LogManager.WriteLog($"[选择性清空] 将保留的现有路径: {string.Join(", ", existingExcluded)}");
- }
int removedCount = 0;
foreach (var pathId in toRemove)
@@ -709,7 +673,6 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"[选择性清空] 成功清空{removedCount}个路径,保留{_pathVisualizations.Count}个路径");
if (removedCount > 0)
{
RequestViewRefresh();
@@ -799,8 +762,6 @@ namespace NavisworksTransport
CreatedTime = DateTime.Now
};
visualization.PointMarkers.Add(grayEndMarker);
-
- LogManager.WriteLog($"[路径可视化] 添加未到达终点: ({originalEndPoint.X:F2}, {originalEndPoint.Y:F2}, {originalEndPoint.Z:F2}), 完成度: {visualization.PathRoute.CompletionPercentage:F1}%");
}
visualization.LastUpdated = DateTime.Now;
@@ -918,7 +879,6 @@ namespace NavisworksTransport
public void SetGridSize(double gridSizeInMeters)
{
_currentGridSizeInMeters = gridSizeInMeters;
- LogManager.WriteLog($"[网格点大小] 设置网格大小: {gridSizeInMeters:F2}米");
}
///
@@ -935,8 +895,6 @@ namespace NavisworksTransport
_vehicleHeight = vehicleHeight;
_safetyMargin = safetyMargin;
- LogManager.WriteLog($"[车辆参数] 更新车辆参数: 长={vehicleLength:F2}m, 宽={vehicleWidth:F2}m, 高={vehicleHeight:F2}m, 安全间隙={safetyMargin:F2}m");
-
// 车辆参数改变时刷新车辆空间模式下的所有普通路径
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
@@ -1032,7 +990,6 @@ namespace NavisworksTransport
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
- LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
@@ -1056,12 +1013,11 @@ namespace NavisworksTransport
// 重建可视化
BuildVisualization(visualization);
- LogManager.WriteLog($"[路径编辑] 添加路径点: {newPoint.Name} 到路径 {pathId}");
RequestViewRefresh();
}
catch (Exception ex)
{
- LogManager.WriteLog($"[路径编辑] 添加路径点失败: {ex.Message}");
+ LogManager.Error($"[路径编辑] 添加路径点失败: {ex.Message}", ex);
}
}
@@ -1075,7 +1031,6 @@ namespace NavisworksTransport
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
- LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
@@ -1092,17 +1047,16 @@ namespace NavisworksTransport
// 重建可视化
BuildVisualization(visualization);
- LogManager.WriteLog($"[路径编辑] 移除路径点: 索引 {pointIndex} 从路径 {pathId}");
RequestViewRefresh();
}
else
{
- LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
+ LogManager.Warning($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[路径编辑] 移除路径点失败: {ex.Message}");
+ LogManager.Error($"[路径编辑] 移除路径点失败: {ex.Message}", ex);
}
}
@@ -1117,7 +1071,6 @@ namespace NavisworksTransport
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
- LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
@@ -1137,17 +1090,16 @@ namespace NavisworksTransport
// 重建可视化
BuildVisualization(visualization);
- LogManager.WriteLog($"[路径编辑] 更新路径点: 索引 {pointIndex} 在路径 {pathId}");
RequestViewRefresh();
}
else
{
- LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
+ LogManager.Warning($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[路径编辑] 更新路径点失败: {ex.Message}");
+ LogManager.Error($"[路径编辑] 更新路径点失败: {ex.Message}", ex);
}
}
@@ -1190,14 +1142,11 @@ namespace NavisworksTransport
{
if (previewPoint == null)
{
- LogManager.WriteLog("[预览点渲染] 预览点为null,跳过渲染");
return;
}
lock (_lockObject)
{
- LogManager.WriteLog($"[预览点渲染] 开始渲染预览点: {previewPoint.Name}");
-
// 获取适当的半径
double radius = GetRadiusForPointType(previewPoint.Type);
@@ -1214,8 +1163,6 @@ namespace NavisworksTransport
IsVisible = true,
PathPoint = previewPoint
};
-
- LogManager.WriteLog($"[预览点渲染] 预览点标记已创建: 位置({previewPoint.Position.X:F2}, {previewPoint.Position.Y:F2}, {previewPoint.Position.Z:F2}), 半径: {radius:F2}, 颜色: 灰色");
// 请求刷新视图
RequestViewRefresh();
@@ -1223,8 +1170,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[预览点渲染] 渲染预览点失败: {ex.Message}");
- LogManager.WriteLog($"[预览点渲染] 堆栈跟踪: {ex.StackTrace}");
+ LogManager.Error($"[预览点渲染] 渲染预览点失败: {ex.Message}", ex);
}
}
@@ -1239,22 +1185,17 @@ namespace NavisworksTransport
{
if (_previewMarker != null || _previewLines.Count > 0)
{
- LogManager.WriteLog($"[预览点渲染] 清除预览点和连线: {_previewMarker?.PathPoint?.Name ?? "未知"}");
_previewMarker = null;
_previewLines.Clear();
// 请求刷新视图
RequestViewRefresh();
}
- else
- {
- LogManager.WriteLog("[预览点渲染] 没有预览点或连线需要清除");
- }
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[预览点渲染] 清除预览点失败: {ex.Message}");
+ LogManager.Error($"[预览点渲染] 清除预览点失败: {ex.Message}", ex);
}
}
@@ -1269,7 +1210,6 @@ namespace NavisworksTransport
{
if (previewPoint == null || pathPoints == null || pathPoints.Count == 0)
{
- LogManager.WriteLog("[预览连线渲染] 参数无效,跳过预览连线渲染");
return;
}
@@ -1306,11 +1246,10 @@ namespace NavisworksTransport
};
_previewLines.Add(line2);
- LogManager.WriteLog($"[预览连线渲染] 已创建预览连线: {prevPoint.Name} -> {previewPoint.Name} -> {nextPoint.Name}");
}
else
{
- LogManager.WriteLog("[预览连线渲染] 未找到合适的线段插入预览点");
+ LogManager.Warning("[预览连线渲染] 未找到合适的线段插入预览点");
}
// 请求刷新视图
@@ -1319,7 +1258,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[预览连线渲染] 渲染预览连线失败: {ex.Message}");
+ LogManager.Error($"[预览连线渲染] 渲染预览连线失败: {ex.Message}", ex);
}
}
@@ -1334,7 +1273,6 @@ namespace NavisworksTransport
{
if (_previewLines.Count > 0)
{
- LogManager.WriteLog($"[预览连线渲染] 清除 {_previewLines.Count} 条预览连线");
_previewLines.Clear();
// 请求刷新视图
@@ -1344,7 +1282,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[预览连线渲染] 清除预览连线失败: {ex.Message}");
+ LogManager.Error($"[预览连线渲染] 清除预览连线失败: {ex.Message}", ex);
}
}
@@ -1358,14 +1296,11 @@ namespace NavisworksTransport
{
if (previewRoute == null || previewRoute.Points.Count == 0)
{
- LogManager.WriteLog("[预览路径渲染] 预览路径为null或没有路径点,跳过渲染");
return;
}
lock (_lockObject)
{
- LogManager.WriteLog($"[预览路径渲染] 开始渲染预览路径: {previewRoute.Name}, 点数: {previewRoute.Points.Count}");
-
// 只清理预览元素,不影响原有路径
ClearPreviewPoint();
ClearPreviewLines();
@@ -1416,23 +1351,19 @@ namespace NavisworksTransport
Radius = GetLineRadius()
};
_previewLines.Add(line2);
- }
-
- LogManager.WriteLog($"[预览路径渲染] 已渲染编辑预览: 预览点 + {_previewLines.Count} 条连线");
+ }
}
else
{
- LogManager.WriteLog("[预览路径渲染] 未找到预览点,跳过渲染");
+ LogManager.Warning("[预览路径渲染] 未找到预览点,跳过渲染");
}
RequestViewRefresh();
- LogManager.WriteLog("[预览路径渲染] 预览路径渲染完成");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[预览路径渲染] 渲染预览路径失败: {ex.Message}");
- LogManager.WriteLog($"[预览路径渲染] 堆栈跟踪: {ex.StackTrace}");
+ LogManager.Error($"[预览路径渲染] 渲染预览路径失败: {ex.Message}", ex);
}
}
@@ -1445,8 +1376,6 @@ namespace NavisworksTransport
{
lock (_lockObject)
{
- LogManager.WriteLog("[清理预览] 开始清理所有预览渲染");
-
// 清理预览点
ClearPreviewPoint();
@@ -1454,12 +1383,11 @@ namespace NavisworksTransport
ClearPreviewLines();
RequestViewRefresh();
- LogManager.WriteLog("[清理预览] 预览清理完成");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[清理预览] 清理预览失败: {ex.Message}");
+ LogManager.Error($"[清理预览] 清理预览失败: {ex.Message}", ex);
}
}
@@ -1502,9 +1430,7 @@ namespace NavisworksTransport
// 转换为模型单位
double radiusInModelUnits = baseRadiusInMeters * metersToModelUnits;
-
- //LogManager.WriteLog($"[半径计算] 类型={pointType}, 网格大小={_currentGridSizeInMeters:F2}m, 标准尺寸={standardRadiusInMeters:F2}m, 基础半径={baseRadiusInMeters:F2}m, 最终半径={radiusInModelUnits:F2}");
-
+
return radiusInModelUnits;
}
@@ -1517,52 +1443,38 @@ namespace NavisworksTransport
try
{
var units = Application.ActiveDocument.Units;
- //LogManager.WriteLog($"[单位检测] API返回的文档单位: {units}");
switch (units)
{
case Units.Millimeters:
- //LogManager.WriteLog("[单位检测] 确认为毫米单位,转换系数=1000");
return 1000.0; // 1米 = 1000毫米
case Units.Centimeters:
- //LogManager.WriteLog("[单位检测] 确认为厘米单位,转换系数=100");
return 100.0; // 1米 = 100厘米
case Units.Meters:
- //LogManager.WriteLog("[单位检测] 确认为米单位,转换系数=1");
return 1.0; // 1米 = 1米
case Units.Inches:
- //LogManager.WriteLog("[单位检测] 确认为英寸单位,转换系数=39.37");
return 39.37; // 1米 = 39.37英寸
case Units.Feet:
- //LogManager.WriteLog("[单位检测] 确认为英尺单位,转换系数=3.281");
return 3.281; // 1米 = 3.281英尺
case Units.Kilometers:
- //LogManager.WriteLog("[单位检测] 确认为公里单位,转换系数=0.001");
return 0.001; // 1米 = 0.001公里
case Units.Micrometers:
- //LogManager.WriteLog("[单位检测] 确认为微米单位,转换系数=1000000");
return 1000000.0; // 1米 = 1000000微米
case Units.Microinches:
- //LogManager.WriteLog("[单位检测] 确认为微英寸单位,转换系数=39370078.74");
return 39370078.74; // 1米 = 39370078.74微英寸
case Units.Mils:
- //LogManager.WriteLog("[单位检测] 确认为密尔单位,转换系数=39370.08");
return 39370.08; // 1米 = 39370.08密尔
case Units.Yards:
- //LogManager.WriteLog("[单位检测] 确认为码单位,转换系数=1.094");
return 1.094; // 1米 = 1.094码
case Units.Miles:
- //LogManager.WriteLog("[单位检测] 确认为英里单位,转换系数=0.000621");
- return 0.000621; // 1米 = 0.000621英里
+ return 0.000621; // 1米 = 0.000621英里
default:
- //LogManager.WriteLog($"[单位检测] 未知单位类型: {units},使用默认米单位,转换系数=1");
return 1.0;
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"[单位检测] API调用失败: {ex.Message}");
- LogManager.WriteLog("[单位检测] 使用默认米单位,转换系数=1");
+ LogManager.Error($"[单位检测] API调用失败: {ex.Message}");
return 1.0;
}
}
@@ -1659,7 +1571,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[车辆空间渲染] 渲染车辆通行空间失败: {ex.Message}");
+ LogManager.Error($"[车辆空间渲染] 渲染车辆通行空间失败: {ex.Message}", ex);
}
}
@@ -1686,7 +1598,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[视图刷新] 失败: {ex.Message}");
+ LogManager.Error($"[视图刷新] 失败: {ex.Message}", ex);
}
}
diff --git a/src/Core/Properties/CategoryAttributeManager.cs b/src/Core/Properties/CategoryAttributeManager.cs
index 2e94c11..04e3577 100644
--- a/src/Core/Properties/CategoryAttributeManager.cs
+++ b/src/Core/Properties/CategoryAttributeManager.cs
@@ -148,7 +148,7 @@ namespace NavisworksTransport
properties,
propertyInternalNames);
- LogManager.WriteLog($"[属性添加] 添加操作完成,成功添加 {successCount} 个模型的属性");
+ LogManager.Info($"[属性添加] 添加操作完成,成功添加 {successCount} 个模型的属性");
return successCount;
}
@@ -584,7 +584,7 @@ namespace NavisworksTransport
propertyInternalNames,
overwriteExisting: true);
- LogManager.WriteLog($"[属性更新] 更新操作完成,成功更新 {successCount} 个模型的属性");
+ LogManager.Info($"[属性更新] 更新操作完成,成功更新 {successCount} 个模型的属性");
return successCount;
}
@@ -653,7 +653,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"获取通用属性值时发生错误: {ex.Message}");
+ LogManager.Error($"获取通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"获取通用属性值时发生错误: {ex.Message}");
return null;
}
@@ -683,7 +683,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"获取修剪后的通用属性值时发生错误: {ex.Message}");
+ LogManager.Error($"获取修剪后的通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"获取修剪后的通用属性值时发生错误: {ex.Message}");
return null;
}
@@ -714,7 +714,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"安全获取属性值时发生错误: {ex.Message}");
+ LogManager.Error($"安全获取属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"安全获取属性值时发生错误: {ex.Message}");
return null;
}
@@ -744,7 +744,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"安全获取通用属性值时发生错误: {ex.Message}");
+ LogManager.Error($"安全获取通用属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"安全获取通用属性值时发生错误: {ex.Message}");
return null;
}
diff --git a/src/Core/Properties/NavisworksComPropertyManager.cs b/src/Core/Properties/NavisworksComPropertyManager.cs
index 294021d..bfa9c28 100644
--- a/src/Core/Properties/NavisworksComPropertyManager.cs
+++ b/src/Core/Properties/NavisworksComPropertyManager.cs
@@ -79,36 +79,36 @@ namespace NavisworksTransport
// 🎯 存在属性时:使用正确的索引进行更新
// 注意:SetUserDefined的索引是从1开始的
int updateIndex = existingIndex + 1;
- LogManager.WriteLog($"[COM属性管理] 发现现有属性类别在索引 {existingIndex},将使用索引 {updateIndex} 进行更新");
+ LogManager.Debug($"[COM属性管理] 发现现有属性类别在索引 {existingIndex},将使用索引 {updateIndex} 进行更新");
try
{
// 使用正确的索引覆盖现有PropertyCategory
propertyNode.SetUserDefined(updateIndex, categoryDisplayName,
categoryInternalName, propertyCategory);
- LogManager.WriteLog($"[COM属性管理] ✅ 成功覆盖现有属性类别 (index={updateIndex})");
+ LogManager.Info($"[COM属性管理] ✅ 成功覆盖现有属性类别 (index={updateIndex})");
}
catch (Exception setEx)
{
- LogManager.WriteLog($"[COM属性管理] ❌ 覆盖属性失败,错误: {setEx.Message}");
+ LogManager.Error($"[COM属性管理] ❌ 覆盖属性失败,错误: {setEx.Message}");
throw;
}
}
else
{
// 🆕 不存在属性时:使用索引0创建新属性
- LogManager.WriteLog("[COM属性管理] 未发现现有属性类别,将创建新的属性类别");
+ LogManager.Debug("[COM属性管理] 未发现现有属性类别,将创建新的属性类别");
try
{
// 使用参数0表示创建新的PropertyCategory
propertyNode.SetUserDefined(0, categoryDisplayName,
categoryInternalName, propertyCategory);
- LogManager.WriteLog("[COM属性管理] ✅ 成功创建新的属性类别 (index=0)");
+ LogManager.Info("[COM属性管理] ✅ 成功创建新的属性类别 (index=0)");
}
catch (Exception setEx)
{
- LogManager.WriteLog($"[COM属性管理] ❌ 创建属性失败,错误: {setEx.Message}");
+ LogManager.Error($"[COM属性管理] ❌ 创建属性失败,错误: {setEx.Message}");
throw;
}
}
@@ -117,7 +117,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM属性管理] 处理单个模型项时发生错误: {ex.Message}");
+ LogManager.Error($"[COM属性管理] 处理单个模型项时发生错误: {ex.Message}");
}
finally
{
@@ -141,7 +141,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM属性管理] 设置属性时发生错误: {ex.Message}");
+ LogManager.Error($"[COM属性管理] 设置属性时发生错误: {ex.Message}");
}
finally
{
@@ -152,7 +152,7 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"[COM属性管理] 操作完成,成功处理 {successCount} 个模型的属性");
+ LogManager.Info($"[COM属性管理] 操作完成,成功处理 {successCount} 个模型的属性");
return successCount;
}
@@ -174,7 +174,7 @@ namespace NavisworksTransport
int successCount = 0;
ComApi.InwOpSelection comSelection = null;
- LogManager.WriteLog($"[COM属性管理] 开始删除 {items.Count} 个模型的属性类别: {categoryDisplayName}");
+ LogManager.Info($"[COM属性管理] 开始删除 {items.Count} 个模型的属性类别: {categoryDisplayName}");
try
{
@@ -196,7 +196,7 @@ namespace NavisworksTransport
if (relativeIndex < 0)
{
- LogManager.WriteLog($"[COM属性管理] 该模型没有属性类别 '{categoryDisplayName}',跳过");
+ LogManager.Debug($"[COM属性管理] 该模型没有属性类别 '{categoryDisplayName}',跳过");
continue;
}
@@ -206,11 +206,11 @@ namespace NavisworksTransport
propertyNode.RemoveUserDefined(userDefinedIndex);
successCount++;
- LogManager.WriteLog($"[COM属性管理] ✅ 成功删除属性类别 (索引={userDefinedIndex})");
+ LogManager.Info($"[COM属性管理] ✅ 成功删除属性类别 (索引={userDefinedIndex})");
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM属性管理] ❌ 删除单个模型项属性时发生错误: {ex.Message}");
+ LogManager.Error($"[COM属性管理] ❌ 删除单个模型项属性时发生错误: {ex.Message}");
}
finally
{
@@ -229,7 +229,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM属性管理] ❌ 删除属性时发生错误: {ex.Message}");
+ LogManager.Error($"[COM属性管理] ❌ 删除属性时发生错误: {ex.Message}");
}
finally
{
@@ -240,7 +240,7 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"[COM属性管理] 删除操作完成,成功删除 {successCount} 个模型的属性");
+ LogManager.Info($"[COM属性管理] 删除操作完成,成功删除 {successCount} 个模型的属性");
return successCount;
}
@@ -317,11 +317,11 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"[COM API读取] 模型: {item.DisplayName}, 属性: {propertyName} - 未找到");
+ LogManager.Debug($"[COM API读取] 模型: {item.DisplayName}, 属性: {propertyName} - 未找到");
}
catch (Exception ex)
{
- LogManager.WriteLog($"通过COM API获取属性值时发生错误: {ex.Message}");
+ LogManager.Error($"通过COM API获取属性值时发生错误: {ex.Message}");
}
finally
{
@@ -360,7 +360,7 @@ namespace NavisworksTransport
try
{
- LogManager.WriteLog($"[COM属性管理] 开始更新模型 {item.DisplayName} 的属性 {propertyName} = {propertyValue}");
+ LogManager.Debug($"[COM属性管理] 开始更新模型 {item.DisplayName} 的属性 {propertyName} = {propertyValue}");
// 转换ModelItem为COM路径
comPath = ComApiBridge.ToInwOaPath(item);
@@ -373,7 +373,7 @@ namespace NavisworksTransport
if (existingIndex < 0)
{
- LogManager.WriteLog($"[COM属性管理] 模型没有属性类别 '{categoryDisplayName}',无法更新属性");
+ LogManager.Warning($"[COM属性管理] 模型没有属性类别 '{categoryDisplayName}',无法更新属性");
return false;
}
@@ -405,7 +405,7 @@ namespace NavisworksTransport
if (existingAttribute == null)
{
- LogManager.WriteLog($"[COM属性管理] 无法获取现有的属性类别 '{categoryDisplayName}'");
+ LogManager.Warning($"[COM属性管理] 无法获取现有的属性类别 '{categoryDisplayName}'");
return false;
}
@@ -449,7 +449,7 @@ namespace NavisworksTransport
propertyNode.SetUserDefined(updateIndex, categoryDisplayName,
categoryInternalName, newPropertyCategory);
- LogManager.WriteLog($"[COM属性管理] ✅ 成功更新属性 {propertyName} = {propertyValue} (index={updateIndex})");
+ LogManager.Info($"[COM属性管理] ✅ 成功更新属性 {propertyName} = {propertyValue} (index={updateIndex})");
return true;
}
finally
@@ -466,7 +466,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM属性管理] ❌ 更新属性失败,错误: {ex.Message}");
+ LogManager.Error($"[COM属性管理] ❌ 更新属性失败,错误: {ex.Message}");
return false;
}
finally
@@ -527,13 +527,13 @@ namespace NavisworksTransport
try
{
int userDefinedIndex = 0; // 用户定义属性的索引计数器
- LogManager.WriteLog($"[相对索引查找] 开始查找属性分类 '{categoryDisplayName}' 的相对索引");
-
+ LogManager.Debug($"[相对索引查找] 开始查找属性分类 '{categoryDisplayName}' 的相对索引");
+
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
try
{
- LogManager.WriteLog($"[相对索引查找] 检查属性: UserDefined={attribute.UserDefined}, ClassUserName='{attribute.ClassUserName ?? "无名称"}'");
+ LogManager.Debug($"[相对索引查找] 检查属性: UserDefined={attribute.UserDefined}, ClassUserName='{attribute.ClassUserName ?? "无名称"}'");
if (attribute.UserDefined)
{
@@ -541,12 +541,12 @@ namespace NavisworksTransport
// ClassName是系统生成的(如"LcOaPropOverrideCat"),我们无法控制
if (attribute.ClassUserName == categoryDisplayName)
{
- LogManager.WriteLog($"[相对索引查找] ✅ 找到属性分类,相对索引为: {userDefinedIndex}, ClassUserName='{attribute.ClassUserName}'");
+ LogManager.Debug($"[相对索引查找] ✅ 找到属性分类,相对索引为: {userDefinedIndex}, ClassUserName='{attribute.ClassUserName}'");
return userDefinedIndex; // 返回在用户定义属性中的索引位置
}
// 只有用户定义的属性才计入索引
userDefinedIndex++;
- LogManager.WriteLog($"[相对索引查找] 发现其他用户定义属性 '{attribute.ClassUserName}',当前索引计数: {userDefinedIndex}");
+ LogManager.Debug($"[相对索引查找] 发现其他用户定义属性 '{attribute.ClassUserName}',当前索引计数: {userDefinedIndex}");
}
}
finally
@@ -558,12 +558,12 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"[相对索引查找] ❌ 未找到属性分类 '{categoryDisplayName}',总共检查了 {userDefinedIndex} 个用户定义属性");
+ LogManager.Debug($"[相对索引查找] ❌ 未找到属性分类 '{categoryDisplayName}',总共检查了 {userDefinedIndex} 个用户定义属性");
return -1; // 未找到返回-1
}
catch (Exception ex)
{
- LogManager.WriteLog($"[相对索引查找] 查找属性相对索引时发生错误: {ex.Message}");
+ LogManager.Error($"[相对索引查找] 查找属性相对索引时发生错误: {ex.Message}");
return -1;
}
}
@@ -599,7 +599,7 @@ namespace NavisworksTransport
try
{
- LogManager.WriteLog($"[COM楼层管理] 开始设置模型 {item.DisplayName} 的楼层属性");
+ LogManager.Debug($"[COM楼层管理] 开始设置模型 {item.DisplayName} 的楼层属性");
// 转换ModelItem为COM路径
comPath = ComApiBridge.ToInwOaPath(item);
@@ -640,39 +640,39 @@ namespace NavisworksTransport
{
// 🎯 存在属性时:使用正确的索引进行更新
int updateIndex = existingIndex + 1;
- LogManager.WriteLog($"[COM楼层管理] 发现现有楼层属性在索引 {existingIndex},将使用索引 {updateIndex} 进行更新");
+ LogManager.Debug($"[COM楼层管理] 发现现有楼层属性在索引 {existingIndex},将使用索引 {updateIndex} 进行更新");
try
{
propertyNode.SetUserDefined(updateIndex, categoryDisplayName,
categoryInternalName, propertyCategory);
- LogManager.WriteLog($"[COM楼层管理] ✅ 成功覆盖现有楼层属性类别 (index={updateIndex})");
+ LogManager.Info($"[COM楼层管理] ✅ 成功覆盖现有楼层属性类别 (index={updateIndex})");
}
catch (Exception setEx)
{
- LogManager.WriteLog($"[COM楼层管理] ❌ 覆盖楼层属性失败,错误: {setEx.Message}");
+ LogManager.Error($"[COM楼层管理] ❌ 覆盖楼层属性失败,错误: {setEx.Message}");
throw;
}
}
else
{
// 🆕 不存在属性时:使用索引0创建新属性
- LogManager.WriteLog("[COM楼层管理] 未发现现有楼层属性,将创建新的属性类别");
+ LogManager.Debug("[COM楼层管理] 未发现现有楼层属性,将创建新的属性类别");
try
{
propertyNode.SetUserDefined(0, categoryDisplayName,
categoryInternalName, propertyCategory);
- LogManager.WriteLog("[COM楼层管理] ✅ 成功创建新的楼层属性类别 (index=0)");
+ LogManager.Info("[COM楼层管理] ✅ 成功创建新的楼层属性类别 (index=0)");
}
catch (Exception setEx)
{
- LogManager.WriteLog($"[COM楼层管理] ❌ 创建楼层属性失败,错误: {setEx.Message}");
+ LogManager.Error($"[COM楼层管理] ❌ 创建楼层属性失败,错误: {setEx.Message}");
throw;
}
}
- LogManager.WriteLog($"[COM楼层管理] ✅ 成功设置楼层属性");
+ LogManager.Info($"[COM楼层管理] ✅ 成功设置楼层属性");
return true;
}
finally
@@ -685,7 +685,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"[COM楼层管理] ❌ 设置楼层属性失败,错误: {ex.Message}");
+ LogManager.Error($"[COM楼层管理] ❌ 设置楼层属性失败,错误: {ex.Message}");
return false;
}
finally
@@ -752,7 +752,7 @@ namespace NavisworksTransport
if (property.name == propertyInternalName)
{
string value = property.value?.ToString();
- LogManager.WriteLog($"[COM楼层读取] 模型: {item.DisplayName}, 属性: {propertyInternalName}, 值: {value}");
+ LogManager.Debug($"[COM楼层读取] 模型: {item.DisplayName}, 属性: {propertyInternalName}, 值: {value}");
return value;
}
}
@@ -787,7 +787,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"通过COM API获取楼层属性值时发生错误: {ex.Message}");
+ LogManager.Error($"通过COM API获取楼层属性值时发生错误: {ex.Message}");
return null;
}
finally
diff --git a/src/PathPlanning/GridMap.cs b/src/PathPlanning/GridMap.cs
index a2d4b64..0e88fc5 100644
--- a/src/PathPlanning/GridMap.cs
+++ b/src/PathPlanning/GridMap.cs
@@ -100,21 +100,6 @@ namespace NavisworksTransport.PathPlanning
Width = (int)Math.Ceiling(worldWidth / cellSize);
Height = (int)Math.Ceiling(worldHeight / cellSize);
- // 检查网格大小是否超出限制
- const int MAX_GRID_SIZE = 10000; // 最大10000x10000网格
- const long MAX_TOTAL_CELLS = 50000000; // 最大5000万个单元格
-
- if (Width > MAX_GRID_SIZE || Height > MAX_GRID_SIZE)
- {
- throw new ArgumentException($"网格尺寸过大: {Width}x{Height},最大允许{MAX_GRID_SIZE}x{MAX_GRID_SIZE}。请增加网格单元格大小或减小搜索区域。");
- }
-
- long totalCells = (long)Width * Height;
- if (totalCells > MAX_TOTAL_CELLS)
- {
- throw new ArgumentException($"网格单元格总数过多: {totalCells:N0},最大允许{MAX_TOTAL_CELLS:N0}。请增加网格单元格大小或减小搜索区域。");
- }
-
// 设置原点为边界框的最小点
Origin = bounds.Min;
@@ -153,14 +138,8 @@ namespace NavisworksTransport.PathPlanning
{
for (int y = 0; y < Height; y++)
{
- // 计算2D世界坐标,并设置合理的初始Z坐标(使用地面高度而不是0)
- var worldPos2D = GridToWorld2D(new GridPoint2D(x, y));
- // 使用边界框最小Z值(地面高度)作为Unknown网格的初始高度
- var worldPos = new Point3D(worldPos2D.X, worldPos2D.Y, Bounds.Min.Z);
-
var cell = new GridCell
{
-// IsWalkable字段已删除,通行性由HeightLayers决定
CellType = CategoryAttributeManager.LogisticsElementType.Unknown, // 修改:默认为未知/空洞类型
IsInChannel = false,
HeightLayers = new List(),
@@ -260,7 +239,6 @@ namespace NavisworksTransport.PathPlanning
var worldPos = GridToWorld3D(gridPosition);
var cell = new GridCell
{
-// IsWalkable字段已删除,通行性由HeightLayers决定
CellType = cellType,
IsInChannel = cellType == CategoryAttributeManager.LogisticsElementType.通道,
HeightLayers = new List(),
@@ -385,7 +363,6 @@ namespace NavisworksTransport.PathPlanning
if (cell.CellType == CategoryAttributeManager.LogisticsElementType.Unknown ||
cell.CellType == CategoryAttributeManager.LogisticsElementType.障碍物)
{
- // IsWalkable由层决定,不再在网格级别设置
// Unknown和障碍物没有可通行层,HasAnyWalkableLayer()自动返回false
cell.Cost = double.MaxValue;
}
@@ -794,7 +771,6 @@ namespace NavisworksTransport.PathPlanning
{
var cell = new GridCell
{
- // IsWalkable由层决定,障碍物没有层或所有层IsWalkable=false
CellType = CategoryAttributeManager.LogisticsElementType.障碍物,
IsInChannel = false,
HeightLayers = new List(), // 空列表,HasAnyWalkableLayer()返回false
@@ -805,25 +781,6 @@ namespace NavisworksTransport.PathPlanning
return cell;
}
- ///
- /// 创建开放空间单元格
- ///
- /// 开放空间单元格
- public static GridCell CreateOpenSpace()
- {
- var cell = new GridCell
- {
-// IsWalkable字段已删除,通行性由HeightLayers决定
- CellType = CategoryAttributeManager.LogisticsElementType.楼板,
- IsInChannel = false,
- HeightLayers = new List(),
- ChannelType = ChannelType.Other,
- SpeedLimit = 0
- };
- cell.Cost = cell.GetCost();
- return cell;
- }
-
///
/// 创建门单元格
///
@@ -833,7 +790,6 @@ namespace NavisworksTransport.PathPlanning
{
var cell = new GridCell
{
-// IsWalkable字段已删除,通行性由HeightLayers决定
CellType = CategoryAttributeManager.LogisticsElementType.门,
IsInChannel = isOpen,
HeightLayers = new List(),
@@ -853,7 +809,6 @@ namespace NavisworksTransport.PathPlanning
{
var cell = new GridCell
{
-// IsWalkable字段已删除,通行性由HeightLayers决定
CellType = CategoryAttributeManager.LogisticsElementType.通道,
IsInChannel = true,
HeightLayers = new List(),
diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs
index 5f09463..bd1cb54 100644
--- a/src/PathPlanning/GridMapGenerator.cs
+++ b/src/PathPlanning/GridMapGenerator.cs
@@ -134,7 +134,6 @@ namespace NavisworksTransport.PathPlanning
// 智能收集无关项相关节点(包括子节点等)
var irrelevantRelatedItems = CollectRelatedItems(irrelevantItems);
LogManager.Info($"【生成网格地图】智能收集到 {irrelevantRelatedItems.Count} 个无关项相关节点(将被排除)");
- var irrelevantItemsSet = irrelevantRelatedItems; // 使用收集后的完整集合
// 2. 先设置PassableHeights,确保障碍物高度检查时有正确的高度范围
LogManager.Info("【生成网格地图】步骤2: 为可通行网格设置高度约束");
@@ -143,7 +142,7 @@ namespace NavisworksTransport.PathPlanning
// 2.5. 处理障碍物(包围盒检测) - 使用高性能优化版本
LogManager.Info("【生成网格地图】步骤2.5: 高性能包围盒遍历处理障碍物");
- ProcessObstaclesWithBoundingBox(channelCoverage.GridMap, traversableRelatedItems, scanHeightInModelUnits, channelCoverage, irrelevantItemsSet);
+ ProcessObstaclesWithBoundingBox(channelCoverage.GridMap, traversableRelatedItems, scanHeightInModelUnits, channelCoverage, irrelevantRelatedItems);
LogManager.Info($"【阶段2.5完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
@@ -159,7 +158,7 @@ namespace NavisworksTransport.PathPlanning
MarkBoundaryLayers(channelCoverage.GridMap, maxHeightDiffInModelUnits);
LogManager.Info($"【阶段2.7完成】边界层标记后网格统计: {channelCoverage.GridMap.GetStatistics()}");
- // 3. 应用车辆尺寸膨胀(如果需要)
+ // 3. 应用车辆尺寸膨胀
if (vehicleRadius > 0 || safetyMargin > 0)
{
LogManager.Info("【生成网格地图】步骤3: 应用车辆膨胀");
@@ -168,28 +167,22 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"【阶段3完成】车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}");
}
- // 注意:边界膨胀已集成到车辆膨胀中,无需单独处理
-
// 4. 设置规划起点和终点信息
if (planningStartPoint != default(Point3D) && planningEndPoint != default(Point3D))
{
channelCoverage.GridMap.PlanningStartPoint = planningStartPoint;
channelCoverage.GridMap.PlanningEndPoint = planningEndPoint;
channelCoverage.GridMap.HasPlanningPoints = true;
-
- // 注意:网格的Z坐标已在通道生成时设置为实际通道高度,无需重新计算
}
- // 将通道数据设置到GridMap中,供后续PathPlanningManager使用
+ // 将通道数据设置到GridMap中
if (traversableRelatedItems != null && traversableRelatedItems.Any())
{
channelCoverage.GridMap.ChannelItems = traversableRelatedItems.ToList();
- LogManager.Info($"【生成网格地图】已将 {traversableRelatedItems.Count} 个通道数据设置到GridMap中");
}
else if (channelCoverage.ChannelItems != null && channelCoverage.ChannelItems.Any())
{
channelCoverage.GridMap.ChannelItems = new List(channelCoverage.ChannelItems);
- LogManager.Info($"【生成网格地图】已将 {channelCoverage.ChannelItems.Count} 个通道数据设置到GridMap中");
}
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
@@ -835,7 +828,7 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高效膨胀] 膨胀半径: {inflationRadius}个网格单元");
// 使用高效的距离变换算法
- ApplyVehicleInflationOptimized(gridMap, inflationRadius);
+ ApplyVehicleInflation(gridMap, inflationRadius);
}
catch (Exception ex)
{
@@ -848,7 +841,7 @@ namespace NavisworksTransport.PathPlanning
/// 多层膨胀算法 - 分两次处理:障碍物膨胀 + 边界膨胀
/// 核心原则:障碍物从外围膨胀(不含本身),边界从边界本身膨胀(包含边界)
///
- private void ApplyVehicleInflationOptimized(GridMap gridMap, int inflationRadius)
+ private void ApplyVehicleInflation(GridMap gridMap, int inflationRadius)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
@@ -1127,299 +1120,6 @@ namespace NavisworksTransport.PathPlanning
return (boundaryCount, inflatedCount);
}
- ///
- /// 旧的2D膨胀算法(已废弃,保留用于参考)
- ///
- private void ApplyVehicleInflationOptimized_Old2D(GridMap gridMap, int inflationRadius)
- {
- var stopwatch = System.Diagnostics.Stopwatch.StartNew();
-
- LogManager.Info($"【8连通膨胀】使用正确的8连通距离变换算法,网格大小: {gridMap.Width}x{gridMap.Height}");
-
- // 使用浮点数距离矩阵支持√2对角线距离
- var distanceMap = new double[gridMap.Width, gridMap.Height];
- const double SQRT2 = 1.414213562373095; // √2
-
- // 初始化距离矩阵
- int obstacleCount = 0;
- int unknownCount = 0;
- int boundaryCount = 0;
-
- for (int x = 0; x < gridMap.Width; x++)
- {
- for (int y = 0; y < gridMap.Height; y++)
- {
- var cell = gridMap.Cells[x, y];
-
- // 膨胀源点:1.障碍物 2.Unknown网格 3.边界层网格
- if (!cell.HasAnyWalkableLayer())
- {
- distanceMap[x, y] = 0.0;
- obstacleCount++;
- }
- else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.Unknown)
- {
- distanceMap[x, y] = 0.0;
- unknownCount++;
- }
- else if (cell.HeightLayers != null && cell.HeightLayers.Any(layer => layer.IsBoundary))
- {
- // 包含边界层的网格作为膨胀源点
- distanceMap[x, y] = 0.0;
- boundaryCount++;
- }
- else
- {
- distanceMap[x, y] = double.MaxValue;
- }
- }
- }
-
- LogManager.Info($"【8连通膨胀】膨胀源点统计 - 障碍物: {obstacleCount}, Unknown: {unknownCount}, 边界: {boundaryCount}");
-
- // 使用标准的距离变换算法 - 正向扫描
- for (int x = 0; x < gridMap.Width; x++)
- {
- for (int y = 0; y < gridMap.Height; y++)
- {
- if (distanceMap[x, y] == double.MaxValue)
- {
- double minDist = double.MaxValue;
-
- // 检查左侧和上方的邻居(4连通)
- if (x > 0)
- minDist = Math.Min(minDist, distanceMap[x - 1, y] + 1.0);
- if (y > 0)
- minDist = Math.Min(minDist, distanceMap[x, y - 1] + 1.0);
-
- // 检查对角线邻居(8连通扩展)
- if (x > 0 && y > 0)
- minDist = Math.Min(minDist, distanceMap[x - 1, y - 1] + SQRT2);
- if (x > 0 && y < gridMap.Height - 1)
- minDist = Math.Min(minDist, distanceMap[x - 1, y + 1] + SQRT2);
-
- if (minDist != double.MaxValue)
- distanceMap[x, y] = minDist;
- }
- }
- }
-
- LogManager.Info($"【8连通膨胀】正向扫描完成,耗时: {stopwatch.ElapsedMilliseconds}ms");
-
- // 反向扫描
- for (int x = gridMap.Width - 1; x >= 0; x--)
- {
- for (int y = gridMap.Height - 1; y >= 0; y--)
- {
- if (distanceMap[x, y] != 0.0)
- {
- double minDist = distanceMap[x, y];
-
- // 检查右侧和下方的邻居(4连通)
- if (x < gridMap.Width - 1)
- minDist = Math.Min(minDist, distanceMap[x + 1, y] + 1.0);
- if (y < gridMap.Height - 1)
- minDist = Math.Min(minDist, distanceMap[x, y + 1] + 1.0);
-
- // 检查对角线邻居(8连通扩展)
- if (x < gridMap.Width - 1 && y < gridMap.Height - 1)
- minDist = Math.Min(minDist, distanceMap[x + 1, y + 1] + SQRT2);
- if (x < gridMap.Width - 1 && y > 0)
- minDist = Math.Min(minDist, distanceMap[x + 1, y - 1] + SQRT2);
-
- distanceMap[x, y] = minDist;
- }
- }
- }
-
- LogManager.Info($"【8连通膨胀】反向扫描完成,耗时: {stopwatch.ElapsedMilliseconds}ms");
-
- // 应用膨胀结果
- int inflatedCells = 0;
- int processedCells = 0;
- int totalCells = gridMap.Width * gridMap.Height;
- int skippedCells = 0;
- int protectedDoorCells = 0;
-
- LogManager.Info($"【8连通膨胀】开始应用膨胀结果,总单元格数: {totalCells}");
-
- try
- {
- for (int x = 0; x < gridMap.Width; x++)
- {
- for (int y = 0; y < gridMap.Height; y++)
- {
- processedCells++;
-
- // 每处理50万个单元格输出一次进度
- if (processedCells % 500000 == 0)
- {
- double progress = (double)processedCells / totalCells * 100;
- LogManager.Info($"【8连通膨胀】应用进度: {progress:F1}% ({processedCells}/{totalCells})");
- }
-
- var gridPos = new GridPoint2D(x, y);
- var cell = gridMap.Cells[x, y];
-
- // 只有满足以下所有条件才进行膨胀:
- // 1. 当前位置原本是可通行的
- // 2. 距离值不是无穷大(有有效的距离计算)
- // 3. 距离小于等于膨胀半径(使用浮点数比较)
- // 4. 距离值大于0(不是原始障碍物)
- // 5. 不是门类型(门保护)
- if (gridMap.IsWalkable(gridPos) &&
- distanceMap[x, y] != double.MaxValue &&
- distanceMap[x, y] > 0.0 &&
- distanceMap[x, y] <= inflationRadius)
- {
- // 门元素保护:跳过门类型的网格,不将其膨胀为障碍物
- if (cell.CellType == CategoryAttributeManager.LogisticsElementType.门)
- {
- protectedDoorCells++;
- // 跳过门网格,保持其可通行状态
- continue;
- }
-
- // 膨胀处理:保留层结构,只将所有层标记为不可通行
- if (cell.HeightLayers != null && cell.HeightLayers.Count > 0)
- {
- // 有高度层:将所有层标记为不可通行
- for (int i = 0; i < cell.HeightLayers.Count; i++)
- {
- var layer = cell.HeightLayers[i];
- layer.IsWalkable = false;
- cell.HeightLayers[i] = layer;
- }
- }
-
- // 更新网格类型和属性
- cell.CellType = CategoryAttributeManager.LogisticsElementType.障碍物;
- cell.Cost = double.MaxValue;
- cell.IsInChannel = false;
- gridMap.Cells[x, y] = cell;
- inflatedCells++;
- }
- else if (distanceMap[x, y] == double.MaxValue || distanceMap[x, y] > inflationRadius)
- {
- skippedCells++;
- }
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"【8连通膨胀】应用膨胀结果时发生错误: {ex.Message},已处理{processedCells}/{totalCells}个单元格");
- throw;
- }
-
- // 单独处理包围盒边界膨胀
- int boundaryInflatedCells = ApplyBoundaryInflationPost(gridMap, inflationRadius);
-
- stopwatch.Stop();
- LogManager.Info($"【8连通膨胀】车辆膨胀完成: 膨胀半径={inflationRadius}格, 新增障碍物={inflatedCells}个, 边界膨胀={boundaryInflatedCells}个, 跳过={skippedCells}个, 保护门网格={protectedDoorCells}个, 总耗时={stopwatch.ElapsedMilliseconds}ms");
- }
-
- ///
- /// 在距离变换膨胀完成后,额外处理包围盒边界膨胀
- /// 从包围盒边界向内膨胀指定层数,确保车辆与边界保持安全距离
- ///
- /// 网格地图
- /// 膨胀半径(网格层数)
- /// 被膨胀的边界网格数量
- private int ApplyBoundaryInflationPost(GridMap gridMap, int inflationRadius)
- {
- int boundaryInflatedCount = 0;
-
- LogManager.Info($"[边界后处理] 开始处理包围盒边界膨胀,膨胀半径: {inflationRadius}层");
-
- // 逐层向内膨胀
- for (int layer = 0; layer < inflationRadius; layer++)
- {
- int layerInflatedCount = 0;
-
- // 处理下边界 (y = layer)
- if (layer < gridMap.Height)
- {
- for (int x = 0; x < gridMap.Width; x++)
- {
- var gridPos = new GridPoint2D(x, layer);
- if (gridMap.IsWalkable(gridPos))
- {
- // 创建障碍物GridCell
- var worldPos = gridMap.GridToWorld3D(gridPos);
- var obstacleCell = GridCellBuilder.Obstacle(worldPos, null);
- gridMap.PlaceCell(gridPos, obstacleCell);
- layerInflatedCount++;
- }
- }
- }
-
- // 处理上边界 (y = maxY - layer)
- if (gridMap.Height - 1 - layer >= 0 && gridMap.Height - 1 - layer != layer) // 避免重复处理
- {
- for (int x = 0; x < gridMap.Width; x++)
- {
- var gridPos = new GridPoint2D(x, gridMap.Height - 1 - layer);
- if (gridMap.IsWalkable(gridPos))
- {
- // 创建障碍物GridCell
- var worldPos = gridMap.GridToWorld3D(gridPos);
- var obstacleCell = GridCellBuilder.Obstacle(worldPos, null);
- gridMap.PlaceCell(gridPos, obstacleCell);
- layerInflatedCount++;
- }
- }
- }
-
- // 处理左边界 (x = layer)
- if (layer < gridMap.Width)
- {
- for (int y = layer + 1; y < gridMap.Height - layer - 1; y++) // 避免角点重复
- {
- var gridPos = new GridPoint2D(layer, y);
- if (gridMap.IsWalkable(gridPos))
- {
- // 创建障碍物GridCell
- var worldPos = gridMap.GridToWorld3D(gridPos);
- var obstacleCell = GridCellBuilder.Obstacle(worldPos, null);
- gridMap.PlaceCell(gridPos, obstacleCell);
- layerInflatedCount++;
- }
- }
- }
-
- // 处理右边界 (x = maxX - layer)
- if (gridMap.Width - 1 - layer >= 0 && gridMap.Width - 1 - layer != layer) // 避免重复处理
- {
- for (int y = layer + 1; y < gridMap.Height - layer - 1; y++) // 避免角点重复
- {
- var gridPos = new GridPoint2D(gridMap.Width - 1 - layer, y);
- if (gridMap.IsWalkable(gridPos))
- {
- // 创建障碍物GridCell
- var worldPos = gridMap.GridToWorld3D(gridPos);
- var obstacleCell = GridCellBuilder.Obstacle(worldPos, null);
- gridMap.PlaceCell(gridPos, obstacleCell);
- layerInflatedCount++;
- }
- }
- }
-
- boundaryInflatedCount += layerInflatedCount;
- LogManager.Info($"[边界后处理] 第{layer + 1}层膨胀完成,新增障碍物: {layerInflatedCount}个");
-
- // 如果这一层没有可膨胀的网格,提前结束
- if (layerInflatedCount == 0)
- {
- LogManager.Info($"[边界后处理] 第{layer + 1}层无可膨胀网格,膨胀结束");
- break;
- }
- }
-
- LogManager.Info($"[边界后处理] 边界膨胀完成,新增障碍物: {boundaryInflatedCount}个");
- return boundaryInflatedCount;
- }
-
///
/// 收集物流项目的相关节点
/// 根据节点类型决定收集策略:几何体节点收集父节点和同级节点,集合节点收集子节点
@@ -1590,8 +1290,6 @@ namespace NavisworksTransport.PathPlanning
private Dictionary PostProcessGeometryItems(
List geometryItems,
HashSet traversableItemsSet,
- GridMap gridMap,
- double scanHeightInModelUnits,
HashSet irrelevantItemsSet)
{
LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果");
@@ -1665,7 +1363,6 @@ namespace NavisworksTransport.PathPlanning
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
LogManager.Info($"[轻量级后处理] 完成,输入 {totalItems} 项,有效结果 {itemCache.Count} 项,API调用 {apiCalls} 次,耗时: {elapsed:F1}ms");
LogManager.Info($"[轻量级后处理] 筛除统计 - 通道相关: {skippedByChannel}, 无关项: {skippedByIrrelevant}, 无边界框: {skippedByBoundingBox}");
- LogManager.Info("[轻量级后处理] 已移除全局高度预过滤,将在障碍物遍历阶段进行精确高度检查");
return itemCache;
}
@@ -1694,7 +1391,7 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {traversableItemsSet.Count}");
// 阶段2:轻量级后处理(只对预筛选结果进行必要的API调用)
- var itemCache = PostProcessGeometryItems(geometryItems, traversableItemsSet, gridMap, scanHeightInModelUnits, irrelevantItemsSet);
+ var itemCache = PostProcessGeometryItems(geometryItems, traversableItemsSet, irrelevantItemsSet);
// 阶段3:条件过滤(并行数值计算)- 使用50%CPU核心优化
LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤");
@@ -1864,7 +1561,7 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高性能障碍物处理] 性能分解 - Search API预筛选+后处理: {searchTime:F1}ms, 过滤: {filterElapsed:F1}ms, 计算: {gridCalcElapsed:F1}ms, 更新: {updateElapsed:F1}ms");
// 性能对比统计
- LogManager.Info($"[性能优化统计] 处理几何体项目: {geometryItems.Count}, 最终有效项目: {validItems.Count}, 优化比率: {(1.0 - (double)validItems.Count / geometryItems.Count):P1}");
+ LogManager.Info($"[性能优化统计] 处理几何体项目: {geometryItems.Count}, 最终有效项目: {validItems.Count}, 优化比率: {1.0 - (double)validItems.Count / geometryItems.Count:P1}");
LogManager.Info($"[精确高度过滤统计] 高度检查项目: {totalCheckedItems}, 高度过滤项目: {filteredItems}, 精确过滤率: {(double)filteredItems / Math.Max(1, totalCheckedItems):P1}");
LogManager.Info($"[并行优化统计] 使用 {optimalParallelism}/{Environment.ProcessorCount} CPU核心,每核心处理 {Math.Ceiling((double)validItems.Count / optimalParallelism)} 个项目");
}
@@ -1889,10 +1586,6 @@ namespace NavisworksTransport.PathPlanning
try
{
- // 网格坐标(x,y)代表左下角,覆盖世界坐标范围:
- // X: [Origin.X + x*CellSize, Origin.X + (x+1)*CellSize)
- // Y: [Origin.Y + y*CellSize, Origin.Y + (y+1)*CellSize)
-
// 直接使用WorldToGrid进行坐标转换
var minGridPos = gridMap.WorldToGrid(new Point3D(bbox.Min.X, bbox.Min.Y, 0));
var maxGridPos = gridMap.WorldToGrid(new Point3D(bbox.Max.X, bbox.Max.Y, 0));
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index ce40470..9eebedf 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -210,7 +210,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 1. 清理现有的路径可视化,但保留网格可视化
PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
- LogManager.WriteLog("[路径可视化] 已清理现有路径显示(保留网格可视化)");
// 2. 如果有选中的路径,则显示该路径
if (_selectedPathRoute != null && _selectedPathRoute.Points.Count > 0)
@@ -230,7 +229,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
- LogManager.WriteLog("[路径可视化] 没有选中的路径,仅清理显示");
+ LogManager.Debug("[路径可视化] 没有选中的路径,仅清理显示");
}
// 3. 恢复网格可视化(如果网格可视化已启用且当前路径有关联的GridMap)
@@ -240,8 +239,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var currentRoute = _pathPlanningManager.CurrentRoute;
if (currentRoute?.AssociatedGridMap != null)
{
- LogManager.WriteLog("[路径可视化] 检测到网格可视化已启用且当前路径有GridMap,恢复网格显示");
-
// 通过PathPlanningManager的RefreshGridVisualization方法恢复网格
// 这会使用当前路径的AssociatedGridMap来重新渲染网格
var refreshMethod = typeof(PathPlanningManager).GetMethod("RefreshGridVisualization",
@@ -249,7 +246,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (refreshMethod != null)
{
refreshMethod.Invoke(_pathPlanningManager, null);
- LogManager.WriteLog("[路径可视化] 网格可视化已恢复");
}
else
{
@@ -258,7 +254,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
- LogManager.WriteLog("[路径可视化] 当前路径没有关联的GridMap,跳过网格恢复");
+ LogManager.Debug("[路径可视化] 当前路径没有关联的GridMap,跳过网格恢复");
}
}
}
@@ -800,7 +796,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (PathPointRenderPlugin.Instance != null && _autoPathStartPointRoute != null)
{
PathPointRenderPlugin.Instance.RemovePath(_autoPathStartPointRoute.Id);
- LogManager.WriteLog($"[选择起点] 已清除之前的起点标记,ID: {_autoPathStartPointRoute.Id}");
_autoPathStartPointRoute = null; // 清除引用
}
@@ -858,7 +853,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (PathPointRenderPlugin.Instance != null && _autoPathEndPointRoute != null)
{
PathPointRenderPlugin.Instance.RemovePath(_autoPathEndPointRoute.Id);
- LogManager.WriteLog($"[选择终点] 已清除之前的终点标记,ID: {_autoPathEndPointRoute.Id}");
+ LogManager.Debug($"[选择终点] 已清除之前的终点标记,ID: {_autoPathEndPointRoute.Id}");
_autoPathEndPointRoute = null; // 清除引用
}
@@ -913,7 +908,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info("=== 开始执行自动路径规划 ===");
// 确保在开始自动路径规划前清理任何残留的事件订阅
- LogManager.WriteLog("[自动路径规划] 规划前清理事件订阅状态");
CleanupAutoPathEventSubscriptions();
if (_pathPlanningManager != null)
{
@@ -921,7 +915,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
// 清理所有临时路径,确保干净的起始状态
- LogManager.WriteLog("[自动路径规划] 清理所有临时路径和历史渲染对象");
ClearTemporaryAutoPathMarkers();
if (PathPointRenderPlugin.Instance != null)
{
@@ -929,12 +922,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_pathPlanningManager?.IsAnyGridVisualizationEnabled == true)
{
PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
- LogManager.WriteLog("[自动路径规划] 已清理历史路径对象(保留网格可视化)");
}
else
{
PathPointRenderPlugin.Instance.ClearPathsExcept(); // 清理所有路径,不保留任何内容
- LogManager.WriteLog("[自动路径规划] 已清理历史路径对象(无网格可视化需保留)");
}
}
@@ -978,7 +969,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"路径规划成功,共 {pathRoute.Points.Count} 个点");
// 自动路径规划完成后,执行完整的事件订阅清理
- LogManager.WriteLog("[自动路径规划] 规划完成后清理事件订阅状态");
CleanupAutoPathEventSubscriptions();
if (_pathPlanningManager != null)
{
@@ -999,7 +989,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 这里的逻辑已经在上方处理过了
// 失败情况下也要清理事件订阅和临时标记
- LogManager.WriteLog("[自动路径规划] 规划失败后清理所有状态");
CleanupAutoPathEventSubscriptions();
if (_pathPlanningManager != null)
{
@@ -1016,12 +1005,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_pathPlanningManager?.IsAnyGridVisualizationEnabled == true)
{
PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
- LogManager.WriteLog("[自动路径规划] 规划失败后已清理渲染对象(保留网格可视化)");
}
else
{
PathPointRenderPlugin.Instance.ClearPathsExcept(); // 清理所有路径,不保留任何内容
- LogManager.WriteLog("[自动路径规划] 规划失败后已清理渲染对象(无网格可视化需保留)");
}
}
}
@@ -1888,22 +1875,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private async void OnAutoPathMouseClicked(object sender, PickItemResult pickResult)
{
try
- {
- LogManager.WriteLog("[自动路径事件] ===== OnAutoPathMouseClicked被调用 =====");
-
+ {
if (pickResult == null)
{
- LogManager.WriteLog("[自动路径事件] pickResult为null,退出处理");
return;
}
var point3D = pickResult.Point;
- LogManager.WriteLog($"[自动路径事件] 接收到点击事件: ({point3D.X:F2}, {point3D.Y:F2}, {point3D.Z:F2})");
- LogManager.WriteLog($"[自动路径事件] IsSelectingStartPoint: {IsSelectingStartPoint}, IsSelectingEndPoint: {IsSelectingEndPoint}");
if (IsSelectingStartPoint)
{
- LogManager.WriteLog("[自动路径事件] 设置起点并停止点击工具");
SetAutoPathStartPoint(point3D);
await SafeExecuteAsync(() =>
{
@@ -1916,7 +1897,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else if (IsSelectingEndPoint)
{
- LogManager.WriteLog("[自动路径事件] 设置终点并停止点击工具");
SetAutoPathEndPoint(point3D);
await SafeExecuteAsync(() =>
{
@@ -1929,7 +1909,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
- LogManager.WriteLog("[自动路径事件] 非选择状态,直接清理事件订阅");
CleanupAutoPathEventSubscriptions();
_pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
}
@@ -2076,7 +2055,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
VehicleWidth,
VehicleHeight,
SafetyMargin);
- LogManager.WriteLog($"[车辆参数同步] 已同步车辆参数到渲染插件: 长={VehicleLength:F2}m, 宽={VehicleWidth:F2}m, 高={VehicleHeight:F2}m, 安全间隙={SafetyMargin:F2}m");
}
else
{
@@ -2115,16 +2093,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private void CleanupAutoPathEventSubscriptions()
{
try
- {
- LogManager.WriteLog("[事件清理] 开始清理自动路径事件订阅");
-
+ {
// 简单安全地移除事件订阅
// 由于C#事件处理机制,多次取消订阅同一个处理程序是安全的
// 即使处理程序未订阅,取消操作也不会抛出异常
- PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
-
- LogManager.WriteLog("[事件清理] 已安全移除PathClickToolPlugin.MouseClicked事件订阅");
- LogManager.WriteLog("[事件清理] 自动路径事件订阅清理完成");
+ PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
}
catch (Exception ex)
{
@@ -2139,16 +2112,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private void ClearTemporaryAutoPathMarkers()
{
try
- {
- LogManager.WriteLog("[临时标记清理] 开始清理自动路径临时标记");
-
+ {
if (PathPointRenderPlugin.Instance != null)
{
// 清除临时的起点标记(使用正确的路径ID)
if (_autoPathStartPointRoute != null)
{
PathPointRenderPlugin.Instance.RemovePath(_autoPathStartPointRoute.Id);
- LogManager.WriteLog($"[临时标记清理] 已清除起点标记,ID: {_autoPathStartPointRoute.Id}");
_autoPathStartPointRoute = null;
}
@@ -2156,15 +2126,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_autoPathEndPointRoute != null)
{
PathPointRenderPlugin.Instance.RemovePath(_autoPathEndPointRoute.Id);
- LogManager.WriteLog($"[临时标记清理] 已清除终点标记,ID: {_autoPathEndPointRoute.Id}");
_autoPathEndPointRoute = null;
}
- LogManager.WriteLog("[临时标记清理] 自动路径临时标记清理完成");
}
else
{
- LogManager.WriteLog("[临时标记清理] PathPointRenderPlugin实例为null,无法清理标记");
+ LogManager.Warning("[临时标记清理] PathPointRenderPlugin实例为null,无法清理标记");
}
}
catch (Exception ex)
diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
index 24694f5..3519f1c 100644
--- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
+++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
@@ -18,11 +18,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region 私有字段
private readonly UIStateManager _uiStateManager;
-
- // 系统管理相关字段
- private bool _isAutoSaveEnabled = true;
- private bool _isDebugModeEnabled = false;
-
+
// 网格可视化开关字段
private bool _showWalkableGrid = false;
private bool _showObstacleGrid = false;
@@ -31,8 +27,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 路径可视化模式字段
private bool _isStandardLineMode = true;
private bool _isVehicleSpaceMode = false;
+
+ // 日志管理字段
private ObservableCollection _logLevels;
private string _selectedLogLevel = "Info";
+
private string _pluginVersion = "v1.0";
private string _navisworksVersion = "2026";
private string _memoryUsage = "0 MB";
@@ -50,24 +49,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region 公共属性
- ///
- /// 是否启用自动保存
- ///
- public bool IsAutoSaveEnabled
- {
- get => _isAutoSaveEnabled;
- set => SetProperty(ref _isAutoSaveEnabled, value);
- }
-
- ///
- /// 是否启用调试模式
- ///
- public bool IsDebugModeEnabled
- {
- get => _isDebugModeEnabled;
- set => SetProperty(ref _isDebugModeEnabled, value);
- }
-
///
/// 是否显示可通行网格点
///
@@ -165,8 +146,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
-
-
///
/// 日志级别集合
///
@@ -182,11 +161,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public string SelectedLogLevel
{
get => _selectedLogLevel;
- set => SetProperty(ref _selectedLogLevel, value);
+ set
+ {
+ if (SetProperty(ref _selectedLogLevel, value))
+ {
+ // 将字符串转换为LogLevel枚举并设置
+ if (Enum.TryParse(value, out var level))
+ {
+ LogManager.SetLogLevel(level);
+ LogManager.Info($"日志级别已更改为: {value}");
+ UpdateMainStatus($"日志级别已设置为: {value}");
+ }
+ }
+ }
}
-
-
///
/// 插件版本
///
@@ -231,12 +220,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region 命令
- public ICommand ClearLogCommand { get; private set; }
- public ICommand ExportLogCommand { get; private set; }
public ICommand ViewLogCommand { get; private set; }
public ICommand OpenSettingsCommand { get; private set; }
- public ICommand ResetSettingsCommand { get; private set; }
- public ICommand ImportConfigCommand { get; private set; }
public ICommand CheckUpdateCommand { get; private set; }
public ICommand GeneratePerformanceReportCommand { get; private set; }
public ICommand DiagnosticCommand { get; private set; }
@@ -258,8 +243,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
-
- // 初始化线程安全的集合
+
+ // 初始化日志级别集合
LogLevels = new ThreadSafeObservableCollection();
// 初始化命令
@@ -300,8 +285,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
-
- // 初始化线程安全的集合
+
+ // 初始化日志级别集合
LogLevels = new ThreadSafeObservableCollection();
// 初始化命令
@@ -335,11 +320,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
// 系统管理命令
ViewLogCommand = new RelayCommand(() => ExecuteViewLog());
- ClearLogCommand = new RelayCommand(() => ExecuteClearLog());
- ExportLogCommand = new RelayCommand(() => ExecuteExportLog());
OpenSettingsCommand = new RelayCommand(() => ExecuteOpenSettings());
- ResetSettingsCommand = new RelayCommand(() => ExecuteResetSettings());
- ImportConfigCommand = new RelayCommand(() => ExecuteImportConfig());
CheckUpdateCommand = new RelayCommand(() => ExecuteCheckUpdate());
GeneratePerformanceReportCommand = new RelayCommand(() => ExecuteGeneratePerformanceReport());
DiagnosticCommand = new RelayCommand(() => ExecuteDiagnostic());
@@ -455,22 +436,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
// 初始化日志级别
LogLevels.Clear();
- var logLevels = new[] { "Debug", "Info", "Warning", "Error" };
- foreach (var level in logLevels)
- {
- LogLevels.Add(level);
- }
- SelectedLogLevel = "Info";
-
+ LogLevels.Add("Debug");
+ LogLevels.Add("Info");
+ LogLevels.Add("Warning");
+ LogLevels.Add("Error");
+
+ // 获取当前日志级别
+ var currentLevel = LogManager.GetLogLevel();
+ SelectedLogLevel = currentLevel.ToString();
+
// 初始化系统信息
PluginVersion = "v1.0";
NavisworksVersion = "2026";
UpdateMainStatus("系统管理初始化完成");
});
-
+
// 启动性能监控
StartPerformanceMonitoring();
-
+
LogManager.Info("系统管理设置初始化完成");
}, "初始化系统管理设置");
}
@@ -608,129 +591,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}, "查看日志");
}
- ///
- /// 清空日志
- ///
- private void ExecuteClearLog()
- {
- SafeExecute(() =>
- {
- try
- {
- // 弹出确认对话框
- var result = System.Windows.MessageBox.Show(
- "确定要清空日志吗?此操作不可撤销。",
- "确认清空日志",
- System.Windows.MessageBoxButton.YesNo,
- System.Windows.MessageBoxImage.Question);
-
- if (result == System.Windows.MessageBoxResult.Yes)
- {
- // 调用LogManager清空日志
- LogManager.ClearLog();
-
- UpdateMainStatus("日志已清空");
- LogManager.Info("通过系统管理清空日志");
-
- // 显示成功消息
- System.Windows.MessageBox.Show("日志已成功清空。", "操作完成",
- System.Windows.MessageBoxButton.OK,
- System.Windows.MessageBoxImage.Information);
- }
- else
- {
- UpdateMainStatus("取消清空日志");
- LogManager.Info("用户取消清空日志操作");
- }
- }
- catch (Exception ex)
- {
- UpdateMainStatus("清空日志失败");
- LogManager.Error($"清空日志失败: {ex.Message}", ex);
-
- // 显示错误消息给用户
- System.Windows.MessageBox.Show($"清空日志失败: {ex.Message}", "错误",
- System.Windows.MessageBoxButton.OK,
- System.Windows.MessageBoxImage.Error);
- }
- }, "清空日志");
- }
-
- ///
- /// 导出日志
- ///
- private void ExecuteExportLog()
- {
- SafeExecute(() =>
- {
- try
- {
- // 创建保存文件对话框
- var saveFileDialog = new Microsoft.Win32.SaveFileDialog
- {
- Title = "导出日志文件",
- Filter = "日志文件 (*.log)|*.log|文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*",
- DefaultExt = "log",
- FileName = $"NavisworksTransport_Log_{DateTime.Now:yyyyMMdd_HHmmss}.log"
- };
-
- if (saveFileDialog.ShowDialog() == true)
- {
- var logFilePath = LogManager.LogFilePath;
-
- if (System.IO.File.Exists(logFilePath))
- {
- // 从源日志文件复制到目标位置
- System.IO.File.Copy(logFilePath, saveFileDialog.FileName, true);
-
- UpdateMainStatus($"日志已导出到: {System.IO.Path.GetFileName(saveFileDialog.FileName)}");
- LogManager.Info($"日志已导出到: {saveFileDialog.FileName}");
-
- // 显示成功消息并询问是否打开文件夹
- var result = System.Windows.MessageBox.Show(
- $"日志已成功导出到:\n{saveFileDialog.FileName}\n\n是否打开文件所在文件夹?",
- "导出完成",
- System.Windows.MessageBoxButton.YesNo,
- System.Windows.MessageBoxImage.Information);
-
- if (result == System.Windows.MessageBoxResult.Yes)
- {
- // 打开文件所在文件夹并选中文件
- System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{saveFileDialog.FileName}\"");
- }
- }
- else
- {
- // 如果日志文件不存在,创建一个空的日志文件
- System.IO.File.WriteAllText(saveFileDialog.FileName, $"NavisworksTransport 日志文件\n导出时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n\n日志文件为空或不存在。\n");
-
- UpdateMainStatus("日志文件不存在,已创建空文件");
- LogManager.Warning("日志文件不存在,已创建空的导出文件");
-
- System.Windows.MessageBox.Show("原始日志文件不存在,已创建空的导出文件。", "注意",
- System.Windows.MessageBoxButton.OK,
- System.Windows.MessageBoxImage.Warning);
- }
- }
- else
- {
- UpdateMainStatus("取消导出日志");
- LogManager.Info("用户取消导出日志操作");
- }
- }
- catch (Exception ex)
- {
- UpdateMainStatus("导出日志失败");
- LogManager.Error($"导出日志失败: {ex.Message}", ex);
-
- // 显示错误消息给用户
- System.Windows.MessageBox.Show($"导出日志失败: {ex.Message}", "错误",
- System.Windows.MessageBoxButton.OK,
- System.Windows.MessageBoxImage.Error);
- }
- }, "导出日志");
- }
-
///
/// 打开设置
///
@@ -738,40 +598,62 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
SafeExecute(() =>
{
- // TODO: 实现设置对话框
- UpdateMainStatus("打开插件设置");
- LogManager.Info("打开设置");
+ try
+ {
+ // 创建并显示配置编辑器对话框
+ var configEditorDialog = new NavisworksTransport.UI.WPF.Views.ConfigEditorDialog();
+
+ // 尝试设置窗口所有者
+ try
+ {
+ var mainWindow = System.Windows.Application.Current.MainWindow;
+ if (mainWindow != null && mainWindow.IsLoaded)
+ {
+ configEditorDialog.Owner = mainWindow;
+ }
+ else
+ {
+ foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
+ {
+ if (window.IsActive && window.IsLoaded)
+ {
+ configEditorDialog.Owner = window;
+ break;
+ }
+ }
+ }
+ }
+ catch (Exception ownerEx)
+ {
+ LogManager.Warning($"设置配置编辑器Owner失败: {ownerEx.Message}");
+ }
+
+ // 显示对话框
+ bool? result = configEditorDialog.ShowDialog();
+
+ if (result == true)
+ {
+ UpdateMainStatus("配置已更新");
+ LogManager.Info("配置编辑器:用户保存了配置");
+ }
+ else
+ {
+ UpdateMainStatus("配置编辑已取消");
+ LogManager.Info("配置编辑器:用户取消了修改");
+ }
+ }
+ catch (Exception ex)
+ {
+ UpdateMainStatus("打开配置编辑器失败");
+ LogManager.Error($"打开配置编辑器失败: {ex.Message}", ex);
+
+ System.Windows.MessageBox.Show($"打开配置编辑器失败: {ex.Message}", "错误",
+ System.Windows.MessageBoxButton.OK,
+ System.Windows.MessageBoxImage.Error);
+ }
}, "打开设置");
}
- ///
- /// 重置设置
- ///
- private void ExecuteResetSettings()
- {
- SafeExecute(() =>
- {
- // TODO: 实现设置重置功能
- UpdateMainStatus("设置已重置为默认值");
- IsAutoSaveEnabled = true;
- IsDebugModeEnabled = false;
- LogManager.Info("重置设置");
- }, "重置设置");
- }
-
- ///
- /// 导入配置
- ///
- private void ExecuteImportConfig()
- {
- SafeExecute(() =>
- {
- // TODO: 实现配置导入功能
- UpdateMainStatus("配置导入完成");
- LogManager.Info("导入配置");
- }, "导入配置");
- }
-
///
/// 检查更新 (已优化为Idle事件监听)
///
@@ -1000,8 +882,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
public bool IsValidState()
{
- return _uiStateManager != null &&
- LogLevels != null;
+ return _uiStateManager != null && LogLevels != null;
}
///
diff --git a/src/UI/WPF/Views/ConfigEditorDialog.xaml b/src/UI/WPF/Views/ConfigEditorDialog.xaml
new file mode 100644
index 0000000..a8b8b8d
--- /dev/null
+++ b/src/UI/WPF/Views/ConfigEditorDialog.xaml
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ • TOML 格式配置文件,支持注释(#开头)和分组([section])
+ • 所有长度单位为米(m),时间单位为秒(s)
+ • 修改后点击"保存"按钮生效,建议先备份原配置
+ • 语法错误会在保存时提示,请确保格式正确
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UI/WPF/Views/ConfigEditorDialog.xaml.cs b/src/UI/WPF/Views/ConfigEditorDialog.xaml.cs
new file mode 100644
index 0000000..55531ef
--- /dev/null
+++ b/src/UI/WPF/Views/ConfigEditorDialog.xaml.cs
@@ -0,0 +1,271 @@
+using System;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using System.Diagnostics;
+using NavisworksTransport.Core.Config;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport.UI.WPF.Views
+{
+ ///
+ /// 配置编辑器对话框
+ ///
+ public partial class ConfigEditorDialog : Window
+ {
+ private string _originalContent;
+ private bool _isModified;
+
+ public ConfigEditorDialog()
+ {
+ InitializeComponent();
+ LoadConfigContent();
+ UpdateStatus();
+ }
+
+ ///
+ /// 加载配置文件内容
+ ///
+ private void LoadConfigContent()
+ {
+ try
+ {
+ string configPath = ConfigManager.ConfigFilePath;
+
+ // 如果配置文件不存在,创建默认配置
+ if (!File.Exists(configPath))
+ {
+ ConfigManager.Instance.Current.GetType(); // 触发单例初始化
+ }
+
+ // 读取配置文件
+ if (File.Exists(configPath))
+ {
+ _originalContent = File.ReadAllText(configPath, System.Text.Encoding.UTF8);
+ ConfigContentTextBox.Text = _originalContent;
+ ConfigFilePathLabel.Content = Path.GetFileName(configPath);
+ StatusLabel.Content = "配置已加载";
+ StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
+ }
+ else
+ {
+ StatusLabel.Content = "配置文件不存在";
+ StatusLabel.Foreground = System.Windows.Media.Brushes.Red;
+ }
+
+ _isModified = false;
+ ModifiedLabel.Content = "";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"加载配置文件失败: {ex.Message}");
+ MessageBox.Show($"加载配置文件失败:\n{ex.Message}",
+ "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ ///
+ /// 更新状态信息
+ ///
+ private void UpdateStatus()
+ {
+ try
+ {
+ string configPath = ConfigManager.ConfigFilePath;
+
+ if (File.Exists(configPath))
+ {
+ var fileInfo = new FileInfo(configPath);
+ FileSizeLabel.Content = $"大小: {fileInfo.Length / 1024.0:F2} KB";
+ }
+
+ int lineCount = ConfigContentTextBox.LineCount;
+ LineCountLabel.Content = $"行数: {lineCount}";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"更新状态信息失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 保存配置
+ ///
+ private bool SaveConfig()
+ {
+ try
+ {
+ string configPath = ConfigManager.ConfigFilePath;
+ string content = ConfigContentTextBox.Text;
+
+ // 验证 TOML 格式
+ try
+ {
+ Tomlyn.Toml.ToModel(content);
+ }
+ catch (Exception tomlEx)
+ {
+ MessageBox.Show($"TOML 格式错误:\n{tomlEx.Message}\n\n请检查配置文件语法。",
+ "格式错误", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return false;
+ }
+
+ // 确保目录存在
+ Directory.CreateDirectory(ConfigManager.ConfigDirectory);
+
+ // 保存文件
+ File.WriteAllText(configPath, content, System.Text.Encoding.UTF8);
+
+ // 重新加载配置
+ ConfigManager.Instance.Reload();
+
+ _originalContent = content;
+ _isModified = false;
+ ModifiedLabel.Content = "";
+
+ StatusLabel.Content = "配置已保存";
+ StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
+
+ UpdateStatus();
+
+ LogManager.Info("配置文件已保存");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"保存配置失败: {ex.Message}");
+ MessageBox.Show($"保存配置失败:\n{ex.Message}",
+ "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ return false;
+ }
+ }
+
+ // 事件处理器
+
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ SaveConfig();
+ }
+
+ private void ReloadButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_isModified)
+ {
+ var result = MessageBox.Show(
+ "当前有未保存的修改,重新加载将丢失这些修改。\n\n确定要继续吗?",
+ "确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
+
+ if (result != MessageBoxResult.Yes)
+ return;
+ }
+
+ LoadConfigContent();
+ StatusLabel.Content = "配置已重新加载";
+ StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
+ }
+
+ private void ResetToDefaultButton_Click(object sender, RoutedEventArgs e)
+ {
+ var result = MessageBox.Show(
+ "确定要恢复为默认配置吗?\n\n当前配置将被覆盖,此操作无法撤销。",
+ "确认", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+
+ if (result == MessageBoxResult.Yes)
+ {
+ try
+ {
+ ConfigManager.Instance.ResetToDefault();
+ LoadConfigContent();
+ StatusLabel.Content = "已恢复默认配置";
+ StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
+ LogManager.Info("配置已恢复为默认值");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"恢复默认配置失败: {ex.Message}");
+ MessageBox.Show($"恢复默认配置失败:\n{ex.Message}",
+ "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+ }
+
+ private void OpenConfigFolderButton_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ string configDir = ConfigManager.ConfigDirectory;
+
+ if (!Directory.Exists(configDir))
+ {
+ Directory.CreateDirectory(configDir);
+ }
+
+ Process.Start("explorer.exe", configDir);
+ LogManager.Info($"打开配置文件夹: {configDir}");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"打开配置文件夹失败: {ex.Message}");
+ MessageBox.Show($"打开配置文件夹失败:\n{ex.Message}",
+ "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ private void ApplyButton_Click(object sender, RoutedEventArgs e)
+ {
+ SaveConfig();
+ }
+
+ private void OkButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_isModified)
+ {
+ if (SaveConfig())
+ {
+ DialogResult = true;
+ Close();
+ }
+ }
+ else
+ {
+ DialogResult = true;
+ Close();
+ }
+ }
+
+ private void CancelButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_isModified)
+ {
+ var result = MessageBox.Show(
+ "有未保存的修改,确定要关闭吗?",
+ "确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
+
+ if (result != MessageBoxResult.Yes)
+ return;
+ }
+
+ DialogResult = false;
+ Close();
+ }
+
+ private void ConfigContentTextBox_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ if (_originalContent != null)
+ {
+ _isModified = ConfigContentTextBox.Text != _originalContent;
+
+ if (_isModified)
+ {
+ ModifiedLabel.Content = "● 已修改";
+ }
+ else
+ {
+ ModifiedLabel.Content = "";
+ }
+
+ UpdateStatus();
+ }
+ }
+ }
+}
diff --git a/src/UI/WPF/Views/SystemManagementView.xaml b/src/UI/WPF/Views/SystemManagementView.xaml
index ca2a612..94c3f0d 100644
--- a/src/UI/WPF/Views/SystemManagementView.xaml
+++ b/src/UI/WPF/Views/SystemManagementView.xaml
@@ -46,20 +46,14 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
-
+
-
-
-
-
+
@@ -67,15 +61,15 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
-
+
-
+
-
@@ -86,26 +80,9 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
-
-
-
-
-
-
-
-
-
diff --git a/src/Utils/GeometryHelper.cs b/src/Utils/GeometryHelper.cs
index 5bea062..7d1e5e9 100644
--- a/src/Utils/GeometryHelper.cs
+++ b/src/Utils/GeometryHelper.cs
@@ -26,25 +26,25 @@ namespace NavisworksTransport
try
{
- LogManager.WriteLog($"开始提取模型 {modelItem.DisplayName} 的几何数据");
- LogManager.WriteLog($"模型项类型: {modelItem.GetType().Name}");
- LogManager.WriteLog($"模型项GUID: {modelItem.InstanceGuid}");
+ LogManager.Debug($"开始提取模型 {modelItem.DisplayName} 的几何数据");
+ LogManager.Debug($"模型项类型: {modelItem.GetType().Name}");
+ LogManager.Debug($"模型项GUID: {modelItem.InstanceGuid}");
// 详细检查模型是否有几何数据
bool hasGeometry = modelItem.HasGeometry;
- LogManager.WriteLog($"[关键检查] ModelItem.HasGeometry = {hasGeometry}");
+ LogManager.Debug($"[关键检查] ModelItem.HasGeometry = {hasGeometry}");
if (!hasGeometry)
{
- LogManager.WriteLog("[关键发现] 模型项没有几何数据 - HasGeometry 返回 false");
- LogManager.WriteLog($"模型项详细信息:");
- LogManager.WriteLog($" - 显示名称: {modelItem.DisplayName}");
- LogManager.WriteLog($" - 实例GUID: {modelItem.InstanceGuid}");
+ LogManager.Debug("[关键发现] 模型项没有几何数据 - HasGeometry 返回 false");
+ LogManager.Debug($"模型项详细信息:");
+ LogManager.Debug($" - 显示名称: {modelItem.DisplayName}");
+ LogManager.Debug($" - 实例GUID: {modelItem.InstanceGuid}");
// 检查子项数量来判断是否为叶节点
int childrenCount = modelItem.Children.Count();
- LogManager.WriteLog($" - 子项数量: {childrenCount}");
- LogManager.WriteLog($" - 是否为叶节点: {childrenCount == 0}");
+ LogManager.Debug($" - 子项数量: {childrenCount}");
+ LogManager.Debug($" - 是否为叶节点: {childrenCount == 0}");
// 尝试检查包围盒
try
@@ -52,72 +52,72 @@ namespace NavisworksTransport
var bbox = modelItem.BoundingBox();
if (bbox != null)
{
- LogManager.WriteLog($" - 包围盒存在: {bbox.Min} - {bbox.Max}");
+ LogManager.Debug($" - 包围盒存在: {bbox.Min} - {bbox.Max}");
}
else
{
- LogManager.WriteLog($" - 包围盒不存在");
+ LogManager.Debug($" - 包围盒不存在");
}
}
catch (Exception bboxEx)
{
- LogManager.WriteLog($" - 获取包围盒失败: {bboxEx.Message}");
+ LogManager.Warning($" - 获取包围盒失败: {bboxEx.Message}");
}
return points;
}
- LogManager.WriteLog("[几何检查通过] 模型项有几何数据,继续处理");
+ LogManager.Debug("[几何检查通过] 模型项有几何数据,继续处理");
// 处理多实例问题 - 确保只获取当前实例的几何
var targetItem = modelItem;
int instanceCount = targetItem.Instances.Count();
- LogManager.WriteLog($"原始模型实例数: {instanceCount}");
+ LogManager.Debug($"原始模型实例数: {instanceCount}");
while (targetItem.Instances.Count() > 1)
{
targetItem = targetItem.Parent;
if (targetItem == null) break;
- LogManager.WriteLog($"向上查找父项: {targetItem?.DisplayName}, 实例数: {targetItem?.Instances.Count()}");
+ LogManager.Debug($"向上查找父项: {targetItem?.DisplayName}, 实例数: {targetItem?.Instances.Count()}");
}
if (targetItem == null)
{
- LogManager.WriteLog("无法找到合适的几何节点");
+ LogManager.Warning("无法找到合适的几何节点");
return points;
}
// 再次检查目标项的几何状态
bool targetHasGeometry = targetItem.HasGeometry;
- LogManager.WriteLog($"[目标项检查] 使用几何节点: {targetItem.DisplayName}");
- LogManager.WriteLog($"[目标项检查] 实例数: {targetItem.Instances.Count()}");
- LogManager.WriteLog($"[目标项检查] HasGeometry = {targetHasGeometry}");
+ LogManager.Debug($"[目标项检查] 使用几何节点: {targetItem.DisplayName}");
+ LogManager.Debug($"[目标项检查] 实例数: {targetItem.Instances.Count()}");
+ LogManager.Debug($"[目标项检查] HasGeometry = {targetHasGeometry}");
if (!targetHasGeometry)
{
- LogManager.WriteLog("[目标项问题] 目标节点也没有几何数据");
+ LogManager.Warning("[目标项问题] 目标节点也没有几何数据");
return points;
}
// 使用优化的几何提取方法
var triangles = ExtractTriangles(targetItem);
- LogManager.WriteLog($"提取到 {triangles.Count} 个三角形");
+ LogManager.Debug($"提取到 {triangles.Count} 个三角形");
if (triangles.Count > 0)
{
// 生成轮廓
points = GenerateOutlineFromTriangles(triangles, tolerance);
- LogManager.WriteLog($"生成轮廓包含 {points.Count} 个点");
+ LogManager.Info($"生成轮廓包含 {points.Count} 个点");
}
else
{
- LogManager.WriteLog("未提取到三角形数据");
+ LogManager.Warning("未提取到三角形数据");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"提取几何数据失败: {ex.Message}");
- LogManager.WriteLog($"堆栈跟踪: {ex.StackTrace}");
+ LogManager.Error($"提取几何数据失败: {ex.Message}");
+ LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
}
return points;
@@ -144,11 +144,11 @@ namespace NavisworksTransport
var comState = ComStateManager.GetState();
comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
- LogManager.WriteLog($"COM 选择创建成功,路径数: {comSelection.Paths().Count}");
+ LogManager.Debug($"COM 选择创建成功,路径数: {comSelection.Paths().Count}");
// 获取所有片段(已移除错误的去重逻辑)
var allFragments = GetAllFragments(comSelection);
- LogManager.WriteLog($"获取到 {allFragments.Count} 个片段");
+ LogManager.Debug($"获取到 {allFragments.Count} 个片段");
try
{
@@ -164,11 +164,11 @@ namespace NavisworksTransport
var fragmentTriangles = callback.GetTriangles();
triangles.AddRange(fragmentTriangles);
- LogManager.WriteLog($"片段生成了 {fragmentTriangles.Count} 个三角形");
+ LogManager.Debug($"片段生成了 {fragmentTriangles.Count} 个三角形");
}
catch (Exception ex)
{
- LogManager.WriteLog($"处理片段失败: {ex.Message}");
+ LogManager.Error($"处理片段失败: {ex.Message}");
}
}
}
@@ -186,14 +186,14 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"释放片段COM对象失败: {ex.Message}");
+ LogManager.Warning($"释放片段COM对象失败: {ex.Message}");
}
}
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"提取三角形失败: {ex.Message}");
+ LogManager.Error($"提取三角形失败: {ex.Message}");
}
finally
{
@@ -407,7 +407,7 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"边计数完成,唯一边数: {edgeCount.Count}");
+ LogManager.Debug($"边计数完成,唯一边数: {edgeCount.Count}");
// 找出只出现一次的边(边界边)
int boundaryCount = 0;
@@ -426,22 +426,22 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"边界边分析完成:");
- LogManager.WriteLog($" 边界边数量: {boundaryCount}");
- LogManager.WriteLog($" 共享边数量: {sharedCount}");
- LogManager.WriteLog($" 边界/总边比例: {(double)boundaryCount / edges.Count:P1}");
+ LogManager.Debug($"边界边分析完成:");
+ LogManager.Debug($" 边界边数量: {boundaryCount}");
+ LogManager.Debug($" 共享边数量: {sharedCount}");
+ LogManager.Debug($" 边界/总边比例: {(double)boundaryCount / edges.Count:P1}");
// 验证边界边的连通性
if (boundaryEdges.Count > 0)
{
var connectivity = AnalyzeBoundaryConnectivity(boundaryEdges);
- LogManager.WriteLog($"边界边连通性分析: {connectivity}");
+ LogManager.Debug($"边界边连通性分析: {connectivity}");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"查找边界边失败: {ex.Message}");
+ LogManager.Error($"查找边界边失败: {ex.Message}");
}
return boundaryEdges;
@@ -501,18 +501,18 @@ namespace NavisworksTransport
try
{
- LogManager.WriteLog($"开始构建轮廓,总边数: {edges.Count}");
+ LogManager.Debug($"开始构建轮廓,总边数: {edges.Count}");
while (remainingEdges.Count > 0 && contourCount < 10) // 最多处理10个轮廓
{
contourCount++;
- LogManager.WriteLog($"=== 开始构建第 {contourCount} 个轮廓 ===");
+ LogManager.Debug($"=== 开始构建第 {contourCount} 个轮廓 ===");
var currentContour = BuildSingleContour(remainingEdges);
if (currentContour.Count >= 3) // 至少3个点才能形成有效轮廓
{
- LogManager.WriteLog($"第 {contourCount} 个轮廓包含 {currentContour.Count} 个点");
+ LogManager.Debug($"第 {contourCount} 个轮廓包含 {currentContour.Count} 个点");
allOutlinePoints.AddRange(currentContour);
// 添加轮廓分隔符(使用特殊坐标标记)
@@ -523,23 +523,23 @@ namespace NavisworksTransport
}
else
{
- LogManager.WriteLog($"第 {contourCount} 个轮廓点数不足({currentContour.Count}),跳过");
+ LogManager.Debug($"第 {contourCount} 个轮廓点数不足({currentContour.Count}),跳过");
break; // 如果轮廓太小,可能是噪声,停止处理
}
}
- LogManager.WriteLog($"轮廓构建完成,共 {contourCount} 个轮廓,总点数: {allOutlinePoints.Count}");
+ LogManager.Info($"轮廓构建完成,共 {contourCount} 个轮廓,总点数: {allOutlinePoints.Count}");
// 如果有多个轮廓,返回最大的外部轮廓
if (contourCount > 1)
{
- LogManager.WriteLog("检测到多个轮廓,返回最大轮廓作为外部边界");
+ LogManager.Debug("检测到多个轮廓,返回最大轮廓作为外部边界");
return GetLargestContour(allOutlinePoints);
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"构建轮廓失败: {ex.Message}");
+ LogManager.Error($"构建轮廓失败: {ex.Message}");
}
return allOutlinePoints;
@@ -566,7 +566,7 @@ namespace NavisworksTransport
var currentPoint = currentEdge.End;
var startPoint = currentEdge.Start;
- LogManager.WriteLog($"轮廓起点: ({startPoint.X:F2}, {startPoint.Y:F2})");
+ LogManager.Debug($"轮廓起点: ({startPoint.X:F2}, {startPoint.Y:F2})");
// 连接后续的边
int maxIterations = remainingEdges.Count + 10; // 防止无限循环
@@ -609,25 +609,25 @@ namespace NavisworksTransport
if (Math.Abs(currentPoint.X - startPoint.X) < tolerance &&
Math.Abs(currentPoint.Y - startPoint.Y) < tolerance)
{
- LogManager.WriteLog($"轮廓已闭合,点数: {contour.Count}");
+ LogManager.Debug($"轮廓已闭合,点数: {contour.Count}");
break;
}
}
else
{
- LogManager.WriteLog($"无法找到连接边,轮廓中断,点数: {contour.Count}");
+ LogManager.Warning($"无法找到连接边,轮廓中断,点数: {contour.Count}");
break;
}
}
if (iteration >= maxIterations)
{
- LogManager.WriteLog($"轮廓构建达到最大迭代次数,强制停止");
+ LogManager.Warning($"轮廓构建达到最大迭代次数,强制停止");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"构建单个轮廓失败: {ex.Message}");
+ LogManager.Error($"构建单个轮廓失败: {ex.Message}");
}
return contour;
@@ -671,7 +671,7 @@ namespace NavisworksTransport
if (contours.Count == 0)
{
- LogManager.WriteLog("未找到有效轮廓");
+ LogManager.Warning("未找到有效轮廓");
return allPoints;
}
@@ -685,7 +685,7 @@ namespace NavisworksTransport
if (contour.Count >= 3)
{
var area = CalculateContourArea(contour);
- LogManager.WriteLog($"轮廓 {i + 1} 面积: {area:F2}, 点数: {contour.Count}");
+ LogManager.Debug($"轮廓 {i + 1} 面积: {area:F2}, 点数: {contour.Count}");
if (area > maxArea)
{
@@ -695,17 +695,17 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"选择最大轮廓,面积: {maxArea:F2}, 原始点数: {largestContour.Count}");
+ LogManager.Debug($"选择最大轮廓,面积: {maxArea:F2}, 原始点数: {largestContour.Count}");
// 清理和排序最大轮廓
var cleanedContour = CleanAndSortContour(largestContour);
- LogManager.WriteLog($"清理后轮廓点数: {cleanedContour.Count}");
+ LogManager.Debug($"清理后轮廓点数: {cleanedContour.Count}");
return cleanedContour;
}
catch (Exception ex)
{
- LogManager.WriteLog($"获取最大轮廓失败: {ex.Message}");
+ LogManager.Error($"获取最大轮廓失败: {ex.Message}");
return allPoints; // 返回原始点集合
}
}
@@ -723,7 +723,7 @@ namespace NavisworksTransport
{
if (contour.Count < 3)
{
- LogManager.WriteLog($"轮廓点数不足: {contour.Count}");
+ LogManager.Warning($"轮廓点数不足: {contour.Count}");
return contour;
}
@@ -750,26 +750,26 @@ namespace NavisworksTransport
}
}
- LogManager.WriteLog($"去重后点数: {uniquePoints.Count}");
+ LogManager.Debug($"去重后点数: {uniquePoints.Count}");
if (uniquePoints.Count < 3)
{
- LogManager.WriteLog("去重后点数不足,返回原始轮廓");
+ LogManager.Warning("去重后点数不足,返回原始轮廓");
return contour;
}
// 第2步:排序点以形成正确的轮廓
result = SortPointsIntoContour(uniquePoints);
- LogManager.WriteLog($"排序后轮廓点数: {result.Count}");
+ LogManager.Debug($"排序后轮廓点数: {result.Count}");
for (int i = 0; i < result.Count; i++)
{
- LogManager.WriteLog($" 排序点 {i}: ({result[i].X:F2}, {result[i].Y:F2})");
+ LogManager.Debug($" 排序点 {i}: ({result[i].X:F2}, {result[i].Y:F2})");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"清理轮廓失败: {ex.Message}");
+ LogManager.Error($"清理轮廓失败: {ex.Message}");
return contour;
}
@@ -796,7 +796,7 @@ namespace NavisworksTransport
var remainingPoints = new List(points);
remainingPoints.Remove(startPoint);
- LogManager.WriteLog($"轮廓起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");
+ LogManager.Debug($"轮廓起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");
// 使用最近邻算法按顺序连接点
var currentPoint = startPoint;
@@ -825,11 +825,11 @@ namespace NavisworksTransport
remainingPoints.Remove(nearestPoint.Value);
currentPoint = nearestPoint.Value;
- LogManager.WriteLog($"下一个点: ({nearestPoint.Value.X:F2}, {nearestPoint.Value.Y:F2}), 距离: {minDistance:F2}");
+ LogManager.Debug($"下一个点: ({nearestPoint.Value.X:F2}, {nearestPoint.Value.Y:F2}), 距离: {minDistance:F2}");
}
else
{
- LogManager.WriteLog("无法找到下一个最近点");
+ LogManager.Warning("无法找到下一个最近点");
break;
}
}
@@ -844,12 +844,12 @@ namespace NavisworksTransport
Math.Pow(lastPoint.Y - firstPoint.Y, 2)
);
- LogManager.WriteLog($"轮廓闭合距离: {closingDistance:F2}");
+ LogManager.Debug($"轮廓闭合距离: {closingDistance:F2}");
}
}
catch (Exception ex)
{
- LogManager.WriteLog($"排序轮廓点失败: {ex.Message}");
+ LogManager.Error($"排序轮廓点失败: {ex.Message}");
return points;
}
@@ -940,7 +940,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"射线-三角形相交计算出错: {ex.Message}");
+ LogManager.Error($"射线-三角形相交计算出错: {ex.Message}");
return false;
}
}
@@ -1041,11 +1041,11 @@ namespace NavisworksTransport
if (_transformMatrix != null)
{
- LogManager.WriteLog($"几何回调处理器使用预处理矩阵,元素数量: {_transformMatrix.Length}");
+ LogManager.Debug($"几何回调处理器使用预处理矩阵,元素数量: {_transformMatrix.Length}");
}
else
{
- LogManager.WriteLog("几何回调处理器使用单位矩阵(无变换)");
+ LogManager.Debug("几何回调处理器使用单位矩阵(无变换)");
}
}
@@ -1089,7 +1089,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"处理三角形失败: {ex.Message}");
+ LogManager.Error($"处理三角形失败: {ex.Message}");
}
}
@@ -1130,7 +1130,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- LogManager.WriteLog($"坐标变换失败: {ex.Message}");
+ LogManager.Error($"坐标变换失败: {ex.Message}");
return localPoint;
}
}
diff --git a/src/Utils/LogManager.cs b/src/Utils/LogManager.cs
index 8748e7a..865f0ab 100644
--- a/src/Utils/LogManager.cs
+++ b/src/Utils/LogManager.cs
@@ -3,6 +3,17 @@ using System.IO;
namespace NavisworksTransport
{
+ ///
+ /// 日志级别枚举
+ ///
+ public enum LogLevel
+ {
+ Debug = 0,
+ Info = 1,
+ Warning = 2,
+ Error = 3
+ }
+
///
/// 统一日志管理器
/// 提供全局日志记录功能
@@ -10,11 +21,16 @@ namespace NavisworksTransport
public static class LogManager
{
private static readonly string _logFilePath = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
- "Autodesk", "Navisworks Manage 2026", "NavisworksTransport", "logs", "debug.log");
+ Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
+ "Autodesk", "Navisworks Manage 2026", "plugins", "NavisworksTransportPlugin", "logs", "debug.log");
private static readonly object _lockObject = new object();
+ ///
+ /// 当前日志级别,默认为 Info
+ ///
+ private static LogLevel _currentLevel = LogLevel.Info;
+
///
/// 静态构造函数,确保日志目录存在并清空旧日志
///
@@ -43,6 +59,31 @@ namespace NavisworksTransport
///
public static string LogFilePath => _logFilePath;
+ ///
+ /// 设置日志级别
+ ///
+ public static void SetLogLevel(LogLevel level)
+ {
+ _currentLevel = level;
+ Info($"日志级别已设置为: {level}");
+ }
+
+ ///
+ /// 获取当前日志级别
+ ///
+ public static LogLevel GetLogLevel()
+ {
+ return _currentLevel;
+ }
+
+ ///
+ /// 检查是否应该记录指定级别的日志
+ ///
+ private static bool ShouldLog(LogLevel level)
+ {
+ return level >= _currentLevel;
+ }
+
///
/// 清空调试日志
///
@@ -81,10 +122,10 @@ namespace NavisworksTransport
}
///
- /// 写入调试日志(同时输出到Debug和文件)
+ /// 写入调试日志(同时输出到Debug和文件)- 私有方法,强制使用带级别的方法
///
/// 日志消息
- public static void WriteLog(string message)
+ private static void WriteLog(string message)
{
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}";
System.Diagnostics.Debug.WriteLine(logMessage);
@@ -108,7 +149,10 @@ namespace NavisworksTransport
/// 日志消息
public static void Info(string message)
{
- WriteLog($"[INFO] {message}");
+ if (ShouldLog(LogLevel.Info))
+ {
+ WriteLog($"[INFO] {message}");
+ }
}
///
@@ -117,7 +161,10 @@ namespace NavisworksTransport
/// 日志消息
public static void Warning(string message)
{
- WriteLog($"[WARN] {message}");
+ if (ShouldLog(LogLevel.Warning))
+ {
+ WriteLog($"[WARN] {message}");
+ }
}
///
@@ -126,7 +173,10 @@ namespace NavisworksTransport
/// 日志消息
public static void Error(string message)
{
- WriteLog($"[ERROR] {message}");
+ if (ShouldLog(LogLevel.Error))
+ {
+ WriteLog($"[ERROR] {message}");
+ }
}
///
@@ -136,8 +186,11 @@ namespace NavisworksTransport
/// 异常对象
public static void Error(string message, Exception exception)
{
- WriteLog($"[ERROR] {message}: {exception.Message}");
- WriteLog($"[ERROR] 堆栈跟踪: {exception.StackTrace}");
+ if (ShouldLog(LogLevel.Error))
+ {
+ WriteLog($"[ERROR] {message}: {exception.Message}");
+ WriteLog($"[ERROR] 堆栈跟踪: {exception.StackTrace}");
+ }
}
///
@@ -146,7 +199,10 @@ namespace NavisworksTransport
/// 日志消息
public static void Debug(string message)
{
- WriteLog($"[DEBUG] {message}");
+ if (ShouldLog(LogLevel.Debug))
+ {
+ WriteLog($"[DEBUG] {message}");
+ }
}
///
diff --git a/src/Utils/NavisworksApiHelper.cs b/src/Utils/NavisworksApiHelper.cs
index d30be14..078fa8e 100644
--- a/src/Utils/NavisworksApiHelper.cs
+++ b/src/Utils/NavisworksApiHelper.cs
@@ -26,12 +26,12 @@ namespace NavisworksTransport.Utils
// 方法: 空集合的SetHidden操作(几乎零开销的伪操作)
var emptyCollection = new ModelItemCollection();
document.Models.SetHidden(emptyCollection, false);
- LogManager.WriteLog($"[{logPrefix}] ✅ 已执行轻量级缓存刷新");
+ LogManager.Debug($"[{logPrefix}] ✅ 已执行轻量级缓存刷新");
}
}
catch (Exception refreshEx)
{
- LogManager.WriteLog($"[{logPrefix}] ⚠️ 缓存刷新失败,但不影响主要操作: {refreshEx.Message}");
+ LogManager.Warning($"[{logPrefix}] ⚠️ 缓存刷新失败,但不影响主要操作: {refreshEx.Message}");
}
}