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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +