增加了配置管理功能,配置文件保存为toml格式,可在配置窗口编辑;实现了日志级别管理功能
This commit is contained in:
parent
a46568f43e
commit
7343133f12
@ -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"`
|
||||
|
||||
## 架构
|
||||
|
||||
|
||||
@ -98,6 +98,12 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
|
||||
<!-- Tomlyn TOML Parser -->
|
||||
<Reference Include="Tomlyn">
|
||||
<HintPath>packages\Tomlyn.0.19.0\lib\netstandard2.0\Tomlyn.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -128,7 +134,11 @@
|
||||
|
||||
<!-- Core - Document State Management -->
|
||||
<Compile Include="src\Core\DocumentStateManager.cs" />
|
||||
|
||||
|
||||
<!-- Core - Configuration Management -->
|
||||
<Compile Include="src\Core\Config\SystemConfig.cs" />
|
||||
<Compile Include="src\Core\Config\ConfigManager.cs" />
|
||||
|
||||
<!-- Commands - Command Pattern Framework (for testing) -->
|
||||
<Compile Include="src\Commands\IPathPlanningCommand.cs" />
|
||||
<Compile Include="src\Commands\CommandBase.cs" />
|
||||
@ -204,6 +214,9 @@
|
||||
<Compile Include="src\UI\WPF\Views\LogViewerDialog.xaml.cs">
|
||||
<DependentUpon>LogViewerDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="src\UI\WPF\Views\ConfigEditorDialog.xaml.cs">
|
||||
<DependentUpon>ConfigEditorDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="src\UI\WPF\Views\CollisionReportDialog.xaml.cs">
|
||||
<DependentUpon>CollisionReportDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -308,6 +321,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="src\UI\WPF\Views\ConfigEditorDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="src\UI\WPF\Views\CollisionReportDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
56
TestConfigManager.cs
Normal file
56
TestConfigManager.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using NavisworksTransport.Core.Config;
|
||||
|
||||
namespace NavisworksTransport.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置管理器测试程序
|
||||
/// 使用方法:在 MainPlugin 的 Execute 方法中临时调用 TestConfigManager.RunTests()
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
76
config.toml.example
Normal file
76
config.toml.example
Normal file
@ -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
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
## 功能点
|
||||
|
||||
### [2025/10/11]
|
||||
|
||||
1. [x] (功能)实现系统配置管理,采用toml格式保存配置文件
|
||||
|
||||
### [2025/10/09]
|
||||
|
||||
1. [x] (优化)支持楼梯场景的3D路径规划
|
||||
|
||||
374
src/Core/Config/ConfigManager.cs
Normal file
374
src/Core/Config/ConfigManager.cs
Normal file
@ -0,0 +1,374 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Tomlyn;
|
||||
using Tomlyn.Model;
|
||||
using NavisworksTransport.Utils;
|
||||
|
||||
namespace NavisworksTransport.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统配置管理器
|
||||
/// 负责 TOML 配置文件的读取、保存和管理
|
||||
/// </summary>
|
||||
public class ConfigManager
|
||||
{
|
||||
private static ConfigManager _instance;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 单例实例
|
||||
/// </summary>
|
||||
public static ConfigManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new ConfigManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置文件路径
|
||||
/// </summary>
|
||||
public static string ConfigFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
|
||||
"Autodesk",
|
||||
"Navisworks Manage 2026",
|
||||
"plugins",
|
||||
"NavisworksTransportPlugin",
|
||||
"config.toml"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置目录
|
||||
/// </summary>
|
||||
public static string ConfigDirectory
|
||||
{
|
||||
get { return Path.GetDirectoryName(ConfigFilePath); }
|
||||
}
|
||||
|
||||
private SystemConfig _currentConfig;
|
||||
|
||||
private ConfigManager()
|
||||
{
|
||||
_currentConfig = LoadOrCreateDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前配置
|
||||
/// </summary>
|
||||
public SystemConfig Current
|
||||
{
|
||||
get { return _currentConfig; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置文件,如果不存在则创建默认配置
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 TOML 字符串加载配置
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存配置到文件
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将配置转换为 TOML 字符串
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新加载配置
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
_currentConfig = LoadOrCreateDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置为默认配置
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
207
src/Core/Config/SystemConfig.cs
Normal file
207
src/Core/Config/SystemConfig.cs
Normal file
@ -0,0 +1,207 @@
|
||||
using System;
|
||||
|
||||
namespace NavisworksTransport.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统配置根类
|
||||
/// </summary>
|
||||
public class SystemConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 网格生成配置
|
||||
/// </summary>
|
||||
public GridGenerationConfig GridGeneration { get; set; } = new GridGenerationConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 路径规划配置
|
||||
/// </summary>
|
||||
public PathPlanningConfig PathPlanning { get; set; } = new PathPlanningConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 可视化配置
|
||||
/// </summary>
|
||||
public VisualizationConfig Visualization { get; set; } = new VisualizationConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 动画配置
|
||||
/// </summary>
|
||||
public AnimationConfig Animation { get; set; } = new AnimationConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 碰撞检测配置
|
||||
/// </summary>
|
||||
public CollisionConfig Collision { get; set; } = new CollisionConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网格生成配置
|
||||
/// </summary>
|
||||
public class GridGenerationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 网格单元大小(米)
|
||||
/// 推荐值:0.3-0.8
|
||||
/// </summary>
|
||||
public double CellSizeMeters { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆半径(米)
|
||||
/// 用于障碍物膨胀计算
|
||||
/// </summary>
|
||||
public double VehicleRadiusMeters { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 安全间隙(米)
|
||||
/// 额外的安全距离
|
||||
/// </summary>
|
||||
public double SafetyMarginMeters { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 膨胀半径(网格单元数)
|
||||
/// 障碍物膨胀的单元格数量
|
||||
/// </summary>
|
||||
public int InflationRadiusCells { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描高度(米)
|
||||
/// 障碍物扫描的垂直步进高度
|
||||
/// </summary>
|
||||
public double ScanHeightMeters { get; set; } = 0.1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路径规划配置
|
||||
/// </summary>
|
||||
public class PathPlanningConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大高度差(米)
|
||||
/// 楼梯、坡道可接受的高度阈值
|
||||
/// </summary>
|
||||
public double MaxHeightDiffMeters { get; set; } = 0.35;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆高度(米)
|
||||
/// 用于通行性判断
|
||||
/// </summary>
|
||||
public double VehicleHeightMeters { get; set; } = 2.0;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆长度(米)
|
||||
/// 用于转弯半径计算
|
||||
/// </summary>
|
||||
public double VehicleLengthMeters { get; set; } = 2.5;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆宽度(米)
|
||||
/// 用于通道宽度判断
|
||||
/// </summary>
|
||||
public double VehicleWidthMeters { get; set; } = 1.8;
|
||||
|
||||
/// <summary>
|
||||
/// 默认路径策略
|
||||
/// "Shortest" - 最短路径优先
|
||||
/// "Straightest" - 直线优先
|
||||
/// "SafetyFirst" - 安全优先
|
||||
/// </summary>
|
||||
public string DefaultPathStrategy { get; set; } = "Straightest";
|
||||
|
||||
/// <summary>
|
||||
/// 路径优化启用
|
||||
/// 是否启用路径点优化(减少转弯点)
|
||||
/// </summary>
|
||||
public bool EnablePathOptimization { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可视化配置
|
||||
/// </summary>
|
||||
public class VisualizationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 网格点大小(像素)
|
||||
/// </summary>
|
||||
public double GridPointSize { get; set; } = 5.0;
|
||||
|
||||
/// <summary>
|
||||
/// 路径线宽(像素)
|
||||
/// </summary>
|
||||
public double PathLineWidth { get; set; } = 2.0;
|
||||
|
||||
/// <summary>
|
||||
/// 路径点大小(模型单位)
|
||||
/// </summary>
|
||||
public double PathPointSize { get; set; } = 50.0;
|
||||
|
||||
/// <summary>
|
||||
/// 启用网格可视化
|
||||
/// 是否默认显示网格地图
|
||||
/// </summary>
|
||||
public bool EnableGridVisualization { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 启用多层网格可视化
|
||||
/// 是否显示多个高度层的网格
|
||||
/// </summary>
|
||||
public bool EnableMultiLayerVisualization { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画配置
|
||||
/// </summary>
|
||||
public class AnimationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 动画速度(米/秒)
|
||||
/// 默认车辆移动速度
|
||||
/// </summary>
|
||||
public double DefaultSpeedMetersPerSecond { get; set; } = 1.5;
|
||||
|
||||
/// <summary>
|
||||
/// 动画帧率(帧/秒)
|
||||
/// </summary>
|
||||
public int FrameRate { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// 步进间隔(毫秒)
|
||||
/// 步进模式下每步的时间间隔
|
||||
/// </summary>
|
||||
public int StepIntervalMs { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 启用平滑插值
|
||||
/// 是否在路径点之间使用平滑插值
|
||||
/// </summary>
|
||||
public bool EnableSmoothInterpolation { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 碰撞检测配置
|
||||
/// </summary>
|
||||
public class CollisionConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 碰撞检测步长(米)
|
||||
/// 动画过程中每次检测的移动距离
|
||||
/// </summary>
|
||||
public double DetectionStepMeters { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 碰撞容差(米)
|
||||
/// 判定为碰撞的最小距离
|
||||
/// </summary>
|
||||
public double CollisionToleranceMeters { get; set; } = 0.01;
|
||||
|
||||
/// <summary>
|
||||
/// 启用实时碰撞检测
|
||||
/// 动画播放时是否实时检测碰撞
|
||||
/// </summary>
|
||||
public bool EnableRealtimeDetection { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 自动生成碰撞报告
|
||||
/// 动画结束后是否自动生成报告
|
||||
/// </summary>
|
||||
public bool AutoGenerateReport { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public PathClickToolPlugin()
|
||||
{
|
||||
LogManager.WriteLog("[ToolPlugin] PathClickToolPlugin实例已创建");
|
||||
LogManager.Debug("[ToolPlugin] PathClickToolPlugin实例已创建");
|
||||
}
|
||||
/// <summary>
|
||||
/// 点击事件,传递精确的点击坐标和对象
|
||||
@ -50,40 +50,40 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<ModelItem>();
|
||||
@ -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;
|
||||
|
||||
@ -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} 个点标记,无连线");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<string>(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}米");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<HeightLayer>(),
|
||||
@ -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<HeightLayer>(),
|
||||
@ -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<HeightLayer>(), // 空列表,HasAnyWalkableLayer()返回false
|
||||
@ -805,25 +781,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
return cell;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建开放空间单元格
|
||||
/// </summary>
|
||||
/// <returns>开放空间单元格</returns>
|
||||
public static GridCell CreateOpenSpace()
|
||||
{
|
||||
var cell = new GridCell
|
||||
{
|
||||
// IsWalkable字段已删除,通行性由HeightLayers决定
|
||||
CellType = CategoryAttributeManager.LogisticsElementType.楼板,
|
||||
IsInChannel = false,
|
||||
HeightLayers = new List<HeightLayer>(),
|
||||
ChannelType = ChannelType.Other,
|
||||
SpeedLimit = 0
|
||||
};
|
||||
cell.Cost = cell.GetCost();
|
||||
return cell;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建门单元格
|
||||
/// </summary>
|
||||
@ -833,7 +790,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
var cell = new GridCell
|
||||
{
|
||||
// IsWalkable字段已删除,通行性由HeightLayers决定
|
||||
CellType = CategoryAttributeManager.LogisticsElementType.门,
|
||||
IsInChannel = isOpen,
|
||||
HeightLayers = new List<HeightLayer>(),
|
||||
@ -853,7 +809,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
var cell = new GridCell
|
||||
{
|
||||
// IsWalkable字段已删除,通行性由HeightLayers决定
|
||||
CellType = CategoryAttributeManager.LogisticsElementType.通道,
|
||||
IsInChannel = true,
|
||||
HeightLayers = new List<HeightLayer>(),
|
||||
|
||||
@ -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<ModelItem>(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
|
||||
/// 多层膨胀算法 - 分两次处理:障碍物膨胀 + 边界膨胀
|
||||
/// 核心原则:障碍物从外围膨胀(不含本身),边界从边界本身膨胀(包含边界)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 旧的2D膨胀算法(已废弃,保留用于参考)
|
||||
/// </summary>
|
||||
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");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在距离变换膨胀完成后,额外处理包围盒边界膨胀
|
||||
/// 从包围盒边界向内膨胀指定层数,确保车辆与边界保持安全距离
|
||||
/// </summary>
|
||||
/// <param name="gridMap">网格地图</param>
|
||||
/// <param name="inflationRadius">膨胀半径(网格层数)</param>
|
||||
/// <returns>被膨胀的边界网格数量</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集物流项目的相关节点
|
||||
/// 根据节点类型决定收集策略:几何体节点收集父节点和同级节点,集合节点收集子节点
|
||||
@ -1590,8 +1290,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
private Dictionary<ModelItem, ItemProperties> PostProcessGeometryItems(
|
||||
List<ModelItem> geometryItems,
|
||||
HashSet<ModelItem> traversableItemsSet,
|
||||
GridMap gridMap,
|
||||
double scanHeightInModelUnits,
|
||||
HashSet<ModelItem> 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));
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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<string> _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 公共属性
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用自动保存
|
||||
/// </summary>
|
||||
public bool IsAutoSaveEnabled
|
||||
{
|
||||
get => _isAutoSaveEnabled;
|
||||
set => SetProperty(ref _isAutoSaveEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用调试模式
|
||||
/// </summary>
|
||||
public bool IsDebugModeEnabled
|
||||
{
|
||||
get => _isDebugModeEnabled;
|
||||
set => SetProperty(ref _isDebugModeEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示可通行网格点
|
||||
/// </summary>
|
||||
@ -165,8 +146,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 日志级别集合
|
||||
/// </summary>
|
||||
@ -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<LogLevel>(value, out var level))
|
||||
{
|
||||
LogManager.SetLogLevel(level);
|
||||
LogManager.Info($"日志级别已更改为: {value}");
|
||||
UpdateMainStatus($"日志级别已设置为: {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 插件版本
|
||||
/// </summary>
|
||||
@ -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<string>();
|
||||
|
||||
// 初始化命令
|
||||
@ -300,8 +285,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
LogManager.Error("UIStateManager初始化失败");
|
||||
throw new InvalidOperationException("UIStateManager初始化失败");
|
||||
}
|
||||
|
||||
// 初始化线程安全的集合
|
||||
|
||||
// 初始化日志级别集合
|
||||
LogLevels = new ThreadSafeObservableCollection<string>();
|
||||
|
||||
// 初始化命令
|
||||
@ -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
|
||||
}, "查看日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空日志
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}, "清空日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出日志
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}, "导出日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开设置
|
||||
/// </summary>
|
||||
@ -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);
|
||||
}
|
||||
}, "打开设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置设置
|
||||
/// </summary>
|
||||
private void ExecuteResetSettings()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现设置重置功能
|
||||
UpdateMainStatus("设置已重置为默认值");
|
||||
IsAutoSaveEnabled = true;
|
||||
IsDebugModeEnabled = false;
|
||||
LogManager.Info("重置设置");
|
||||
}, "重置设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入配置
|
||||
/// </summary>
|
||||
private void ExecuteImportConfig()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现配置导入功能
|
||||
UpdateMainStatus("配置导入完成");
|
||||
LogManager.Info("导入配置");
|
||||
}, "导入配置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查更新 (已优化为Idle事件监听)
|
||||
/// </summary>
|
||||
@ -1000,8 +882,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// </summary>
|
||||
public bool IsValidState()
|
||||
{
|
||||
return _uiStateManager != null &&
|
||||
LogLevels != null;
|
||||
return _uiStateManager != null && LogLevels != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
214
src/UI/WPF/Views/ConfigEditorDialog.xaml
Normal file
214
src/UI/WPF/Views/ConfigEditorDialog.xaml
Normal file
@ -0,0 +1,214 @@
|
||||
<!--
|
||||
NavisworksTransport 配置编辑器对话框 - 采用与主界面一致的Navisworks 2026风格
|
||||
|
||||
功能说明:
|
||||
1. 加载和显示 TOML 配置文件
|
||||
2. 支持直接编辑配置文件内容
|
||||
3. 提供保存、重载和恢复默认功能
|
||||
4. 语法高亮和错误提示
|
||||
5. 与主界面保持一致的视觉风格
|
||||
|
||||
设计原则:使用统一的蓝色主题和样式规范,针对配置文件编辑优化
|
||||
-->
|
||||
<Window x:Class="NavisworksTransport.UI.WPF.Views.ConfigEditorDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
Title="系统参数配置"
|
||||
Height="700"
|
||||
Width="900"
|
||||
ResizeMode="CanResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
MinHeight="500"
|
||||
MinWidth="700">
|
||||
|
||||
<Window.Resources>
|
||||
<!-- 引用共享的Navisworks 2026样式资源 -->
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/NavisworksTransportPlugin;component/src/UI/WPF/Resources/NavisworksStyles.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!-- 配置编辑器特有的样式 -->
|
||||
<Style x:Key="ConfigTextBoxStyle" TargetType="TextBox">
|
||||
<Setter Property="FontFamily" Value="Consolas, Courier New"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Background" Value="#FFFEFEFE"/>
|
||||
<Setter Property="Foreground" Value="#FF333333"/>
|
||||
<Setter Property="BorderBrush" Value="#FFD4E7FF"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="IsReadOnly" Value="False"/>
|
||||
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||
<Setter Property="AcceptsReturn" Value="True"/>
|
||||
<Setter Property="AcceptsTab" Value="True"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="InfoPanelStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFFFF8DC"/>
|
||||
<Setter Property="BorderBrush" Value="#FFFFC107"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="3"/>
|
||||
<Setter Property="Padding" Value="12,8"/>
|
||||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 工具栏区域 -->
|
||||
<Border Grid.Row="0"
|
||||
BorderBrush="#FFD4E7FF"
|
||||
BorderThickness="0,0,0,1"
|
||||
Background="#FFF8FBFF"
|
||||
Padding="15,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左侧工具按钮 -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Button Content="保存"
|
||||
Click="SaveButton_Click"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Margin="0,0,10,0"
|
||||
ToolTip="保存配置文件"/>
|
||||
<Button Content="重新加载"
|
||||
Click="ReloadButton_Click"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Margin="0,0,10,0"
|
||||
ToolTip="放弃当前修改,重新加载配置文件"/>
|
||||
<Button Content="恢复默认"
|
||||
Click="ResetToDefaultButton_Click"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Margin="0,0,10,0"
|
||||
ToolTip="恢复为默认配置"/>
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<Border Width="1"
|
||||
Background="#FFD4E7FF"
|
||||
Margin="5,2"/>
|
||||
|
||||
<Button Content="打开配置文件夹"
|
||||
Click="OpenConfigFolderButton_Click"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Margin="10,0,0,0"
|
||||
ToolTip="在资源管理器中打开配置文件所在目录"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 右侧文件信息 -->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Label Content="配置文件:"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ParameterLabelStyle}"/>
|
||||
<Label Name="ConfigFilePathLabel"
|
||||
Content="config.toml"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Foreground="#FF0066CC"
|
||||
Margin="5,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 帮助信息面板 -->
|
||||
<Border Grid.Row="1"
|
||||
Style="{StaticResource InfoPanelStyle}"
|
||||
Margin="15,15,15,0">
|
||||
<StackPanel>
|
||||
<TextBlock FontWeight="SemiBold"
|
||||
Foreground="#FF856404"
|
||||
Margin="0,0,0,5">
|
||||
<Run Text="💡 "/>
|
||||
<Run Text="配置说明"/>
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
FontSize="10"
|
||||
Foreground="#FF856404"
|
||||
LineHeight="18">
|
||||
• TOML 格式配置文件,支持注释(#开头)和分组([section])<LineBreak/>
|
||||
• 所有长度单位为米(m),时间单位为秒(s)<LineBreak/>
|
||||
• 修改后点击"保存"按钮生效,建议先备份原配置<LineBreak/>
|
||||
• 语法错误会在保存时提示,请确保格式正确
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 配置内容编辑区域 -->
|
||||
<Border Grid.Row="2"
|
||||
BorderBrush="#FFD4E7FF"
|
||||
BorderThickness="1"
|
||||
Background="White"
|
||||
Margin="15,10">
|
||||
<TextBox Name="ConfigContentTextBox"
|
||||
Style="{StaticResource ConfigTextBoxStyle}"
|
||||
TextChanged="ConfigContentTextBox_TextChanged"/>
|
||||
</Border>
|
||||
|
||||
<!-- 底部状态栏和按钮 -->
|
||||
<Border Grid.Row="3"
|
||||
BorderBrush="#FFD4E7FF"
|
||||
BorderThickness="0,1,0,0"
|
||||
Background="#FFF8FBFF"
|
||||
Padding="15,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 状态信息 -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Label Name="StatusLabel"
|
||||
Content="配置已加载"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Foreground="#FF2B8A2B"/>
|
||||
<Label Name="FileSizeLabel"
|
||||
Content="大小: 0 KB"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Margin="20,0,0,0"/>
|
||||
<Label Name="LineCountLabel"
|
||||
Content="行数: 0"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Margin="20,0,0,0"/>
|
||||
<Label Name="ModifiedLabel"
|
||||
Content=""
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Foreground="#FFFF6B00"
|
||||
Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 右侧按钮 -->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Button Content="应用"
|
||||
Click="ApplyButton_Click"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Margin="0,0,10,0"
|
||||
ToolTip="应用配置并保持窗口打开"/>
|
||||
<Button Content="确定"
|
||||
Click="OkButton_Click"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Margin="0,0,10,0"
|
||||
ToolTip="保存配置并关闭窗口"/>
|
||||
<Button Content="取消"
|
||||
Click="CancelButton_Click"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
ToolTip="放弃修改并关闭窗口"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
271
src/UI/WPF/Views/ConfigEditorDialog.xaml.cs
Normal file
271
src/UI/WPF/Views/ConfigEditorDialog.xaml.cs
Normal file
@ -0,0 +1,271 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Diagnostics;
|
||||
using NavisworksTransport.Core.Config;
|
||||
using NavisworksTransport.Utils;
|
||||
|
||||
namespace NavisworksTransport.UI.WPF.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置编辑器对话框
|
||||
/// </summary>
|
||||
public partial class ConfigEditorDialog : Window
|
||||
{
|
||||
private string _originalContent;
|
||||
private bool _isModified;
|
||||
|
||||
public ConfigEditorDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadConfigContent();
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置文件内容
|
||||
/// </summary>
|
||||
private void LoadConfigContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
string configPath = ConfigManager.ConfigFilePath;
|
||||
|
||||
// 如果配置文件不存在,创建默认配置
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
ConfigManager.Instance.Current.GetType(); // 触发单例初始化
|
||||
}
|
||||
|
||||
// 读取配置文件
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
_originalContent = File.ReadAllText(configPath, System.Text.Encoding.UTF8);
|
||||
ConfigContentTextBox.Text = _originalContent;
|
||||
ConfigFilePathLabel.Content = Path.GetFileName(configPath);
|
||||
StatusLabel.Content = "配置已加载";
|
||||
StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Content = "配置文件不存在";
|
||||
StatusLabel.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
|
||||
_isModified = false;
|
||||
ModifiedLabel.Content = "";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"加载配置文件失败: {ex.Message}");
|
||||
MessageBox.Show($"加载配置文件失败:\n{ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新状态信息
|
||||
/// </summary>
|
||||
private void UpdateStatus()
|
||||
{
|
||||
try
|
||||
{
|
||||
string configPath = ConfigManager.ConfigFilePath;
|
||||
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
var fileInfo = new FileInfo(configPath);
|
||||
FileSizeLabel.Content = $"大小: {fileInfo.Length / 1024.0:F2} KB";
|
||||
}
|
||||
|
||||
int lineCount = ConfigContentTextBox.LineCount;
|
||||
LineCountLabel.Content = $"行数: {lineCount}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新状态信息失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存配置
|
||||
/// </summary>
|
||||
private bool SaveConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
string configPath = ConfigManager.ConfigFilePath;
|
||||
string content = ConfigContentTextBox.Text;
|
||||
|
||||
// 验证 TOML 格式
|
||||
try
|
||||
{
|
||||
Tomlyn.Toml.ToModel(content);
|
||||
}
|
||||
catch (Exception tomlEx)
|
||||
{
|
||||
MessageBox.Show($"TOML 格式错误:\n{tomlEx.Message}\n\n请检查配置文件语法。",
|
||||
"格式错误", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确保目录存在
|
||||
Directory.CreateDirectory(ConfigManager.ConfigDirectory);
|
||||
|
||||
// 保存文件
|
||||
File.WriteAllText(configPath, content, System.Text.Encoding.UTF8);
|
||||
|
||||
// 重新加载配置
|
||||
ConfigManager.Instance.Reload();
|
||||
|
||||
_originalContent = content;
|
||||
_isModified = false;
|
||||
ModifiedLabel.Content = "";
|
||||
|
||||
StatusLabel.Content = "配置已保存";
|
||||
StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
|
||||
|
||||
UpdateStatus();
|
||||
|
||||
LogManager.Info("配置文件已保存");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"保存配置失败: {ex.Message}");
|
||||
MessageBox.Show($"保存配置失败:\n{ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 事件处理器
|
||||
|
||||
private void SaveButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
private void ReloadButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_isModified)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"当前有未保存的修改,重新加载将丢失这些修改。\n\n确定要继续吗?",
|
||||
"确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
LoadConfigContent();
|
||||
StatusLabel.Content = "配置已重新加载";
|
||||
StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
|
||||
private void ResetToDefaultButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"确定要恢复为默认配置吗?\n\n当前配置将被覆盖,此操作无法撤销。",
|
||||
"确认", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
try
|
||||
{
|
||||
ConfigManager.Instance.ResetToDefault();
|
||||
LoadConfigContent();
|
||||
StatusLabel.Content = "已恢复默认配置";
|
||||
StatusLabel.Foreground = System.Windows.Media.Brushes.Green;
|
||||
LogManager.Info("配置已恢复为默认值");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"恢复默认配置失败: {ex.Message}");
|
||||
MessageBox.Show($"恢复默认配置失败:\n{ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenConfigFolderButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
string configDir = ConfigManager.ConfigDirectory;
|
||||
|
||||
if (!Directory.Exists(configDir))
|
||||
{
|
||||
Directory.CreateDirectory(configDir);
|
||||
}
|
||||
|
||||
Process.Start("explorer.exe", configDir);
|
||||
LogManager.Info($"打开配置文件夹: {configDir}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"打开配置文件夹失败: {ex.Message}");
|
||||
MessageBox.Show($"打开配置文件夹失败:\n{ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_isModified)
|
||||
{
|
||||
if (SaveConfig())
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_isModified)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"有未保存的修改,确定要关闭吗?",
|
||||
"确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ConfigContentTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (_originalContent != null)
|
||||
{
|
||||
_isModified = ConfigContentTextBox.Text != _originalContent;
|
||||
|
||||
if (_isModified)
|
||||
{
|
||||
ModifiedLabel.Content = "● 已修改";
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiedLabel.Content = "";
|
||||
}
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,20 +46,14 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="日志管理" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
|
||||
<!-- 日志操作按钮 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
|
||||
<Button Content="查看日志"
|
||||
Command="{Binding ViewLogCommand}"
|
||||
<Button Content="查看日志"
|
||||
Command="{Binding ViewLogCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
<Button Content="清空日志"
|
||||
Command="{Binding ClearLogCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="导出日志"
|
||||
Command="{Binding ExportLogCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<!-- 日志级别设置 -->
|
||||
<Grid Margin="0,5,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -67,15 +61,15 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<Label Grid.Column="0" Content="日志级别:" Style="{StaticResource ParameterLabelStyle}" Width="80"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding LogLevels}"
|
||||
SelectedItem="{Binding SelectedLogLevel}"
|
||||
Width="100"
|
||||
Margin="5,0,0,0"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding LogLevels}"
|
||||
SelectedItem="{Binding SelectedLogLevel}"
|
||||
Width="100"
|
||||
Margin="5,0,0,0"
|
||||
ToolTip="选择要记录的最低日志级别"/>
|
||||
</Grid>
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@ -86,26 +80,9 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
|
||||
<!-- 设置操作按钮 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
|
||||
<Button Content="设置选项"
|
||||
Command="{Binding OpenSettingsCommand}"
|
||||
<Button Content="参数设置"
|
||||
Command="{Binding OpenSettingsCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
<Button Content="重置设置"
|
||||
Command="{Binding ResetSettingsCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="导入配置"
|
||||
Command="{Binding ImportConfigCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 选项设置 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
|
||||
<CheckBox Content="启用自动保存"
|
||||
IsChecked="{Binding IsAutoSaveEnabled}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"/>
|
||||
<CheckBox Content="启用调试模式"
|
||||
IsChecked="{Binding IsDebugModeEnabled}"
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 网格可视化开关 -->
|
||||
|
||||
@ -26,25 +26,25 @@ namespace NavisworksTransport
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.WriteLog($"开始提取模型 {modelItem.DisplayName} 的几何数据");
|
||||
LogManager.WriteLog($"模型项类型: {modelItem.GetType().Name}");
|
||||
LogManager.WriteLog($"模型项GUID: {modelItem.InstanceGuid}");
|
||||
LogManager.Debug($"开始提取模型 {modelItem.DisplayName} 的几何数据");
|
||||
LogManager.Debug($"模型项类型: {modelItem.GetType().Name}");
|
||||
LogManager.Debug($"模型项GUID: {modelItem.InstanceGuid}");
|
||||
|
||||
// 详细检查模型是否有几何数据
|
||||
bool hasGeometry = modelItem.HasGeometry;
|
||||
LogManager.WriteLog($"[关键检查] ModelItem.HasGeometry = {hasGeometry}");
|
||||
LogManager.Debug($"[关键检查] ModelItem.HasGeometry = {hasGeometry}");
|
||||
|
||||
if (!hasGeometry)
|
||||
{
|
||||
LogManager.WriteLog("[关键发现] 模型项没有几何数据 - HasGeometry 返回 false");
|
||||
LogManager.WriteLog($"模型项详细信息:");
|
||||
LogManager.WriteLog($" - 显示名称: {modelItem.DisplayName}");
|
||||
LogManager.WriteLog($" - 实例GUID: {modelItem.InstanceGuid}");
|
||||
LogManager.Debug("[关键发现] 模型项没有几何数据 - HasGeometry 返回 false");
|
||||
LogManager.Debug($"模型项详细信息:");
|
||||
LogManager.Debug($" - 显示名称: {modelItem.DisplayName}");
|
||||
LogManager.Debug($" - 实例GUID: {modelItem.InstanceGuid}");
|
||||
|
||||
// 检查子项数量来判断是否为叶节点
|
||||
int childrenCount = modelItem.Children.Count();
|
||||
LogManager.WriteLog($" - 子项数量: {childrenCount}");
|
||||
LogManager.WriteLog($" - 是否为叶节点: {childrenCount == 0}");
|
||||
LogManager.Debug($" - 子项数量: {childrenCount}");
|
||||
LogManager.Debug($" - 是否为叶节点: {childrenCount == 0}");
|
||||
|
||||
// 尝试检查包围盒
|
||||
try
|
||||
@ -52,72 +52,72 @@ namespace NavisworksTransport
|
||||
var bbox = modelItem.BoundingBox();
|
||||
if (bbox != null)
|
||||
{
|
||||
LogManager.WriteLog($" - 包围盒存在: {bbox.Min} - {bbox.Max}");
|
||||
LogManager.Debug($" - 包围盒存在: {bbox.Min} - {bbox.Max}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog($" - 包围盒不存在");
|
||||
LogManager.Debug($" - 包围盒不存在");
|
||||
}
|
||||
}
|
||||
catch (Exception bboxEx)
|
||||
{
|
||||
LogManager.WriteLog($" - 获取包围盒失败: {bboxEx.Message}");
|
||||
LogManager.Warning($" - 获取包围盒失败: {bboxEx.Message}");
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
LogManager.WriteLog("[几何检查通过] 模型项有几何数据,继续处理");
|
||||
LogManager.Debug("[几何检查通过] 模型项有几何数据,继续处理");
|
||||
|
||||
// 处理多实例问题 - 确保只获取当前实例的几何
|
||||
var targetItem = modelItem;
|
||||
int instanceCount = targetItem.Instances.Count();
|
||||
LogManager.WriteLog($"原始模型实例数: {instanceCount}");
|
||||
LogManager.Debug($"原始模型实例数: {instanceCount}");
|
||||
|
||||
while (targetItem.Instances.Count() > 1)
|
||||
{
|
||||
targetItem = targetItem.Parent;
|
||||
if (targetItem == null) break;
|
||||
LogManager.WriteLog($"向上查找父项: {targetItem?.DisplayName}, 实例数: {targetItem?.Instances.Count()}");
|
||||
LogManager.Debug($"向上查找父项: {targetItem?.DisplayName}, 实例数: {targetItem?.Instances.Count()}");
|
||||
}
|
||||
|
||||
if (targetItem == null)
|
||||
{
|
||||
LogManager.WriteLog("无法找到合适的几何节点");
|
||||
LogManager.Warning("无法找到合适的几何节点");
|
||||
return points;
|
||||
}
|
||||
|
||||
// 再次检查目标项的几何状态
|
||||
bool targetHasGeometry = targetItem.HasGeometry;
|
||||
LogManager.WriteLog($"[目标项检查] 使用几何节点: {targetItem.DisplayName}");
|
||||
LogManager.WriteLog($"[目标项检查] 实例数: {targetItem.Instances.Count()}");
|
||||
LogManager.WriteLog($"[目标项检查] HasGeometry = {targetHasGeometry}");
|
||||
LogManager.Debug($"[目标项检查] 使用几何节点: {targetItem.DisplayName}");
|
||||
LogManager.Debug($"[目标项检查] 实例数: {targetItem.Instances.Count()}");
|
||||
LogManager.Debug($"[目标项检查] HasGeometry = {targetHasGeometry}");
|
||||
|
||||
if (!targetHasGeometry)
|
||||
{
|
||||
LogManager.WriteLog("[目标项问题] 目标节点也没有几何数据");
|
||||
LogManager.Warning("[目标项问题] 目标节点也没有几何数据");
|
||||
return points;
|
||||
}
|
||||
|
||||
// 使用优化的几何提取方法
|
||||
var triangles = ExtractTriangles(targetItem);
|
||||
LogManager.WriteLog($"提取到 {triangles.Count} 个三角形");
|
||||
LogManager.Debug($"提取到 {triangles.Count} 个三角形");
|
||||
|
||||
if (triangles.Count > 0)
|
||||
{
|
||||
// 生成轮廓
|
||||
points = GenerateOutlineFromTriangles(triangles, tolerance);
|
||||
LogManager.WriteLog($"生成轮廓包含 {points.Count} 个点");
|
||||
LogManager.Info($"生成轮廓包含 {points.Count} 个点");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog("未提取到三角形数据");
|
||||
LogManager.Warning("未提取到三角形数据");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"提取几何数据失败: {ex.Message}");
|
||||
LogManager.WriteLog($"堆栈跟踪: {ex.StackTrace}");
|
||||
LogManager.Error($"提取几何数据失败: {ex.Message}");
|
||||
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
|
||||
}
|
||||
|
||||
return points;
|
||||
@ -144,11 +144,11 @@ namespace NavisworksTransport
|
||||
var comState = ComStateManager.GetState();
|
||||
comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
|
||||
|
||||
LogManager.WriteLog($"COM 选择创建成功,路径数: {comSelection.Paths().Count}");
|
||||
LogManager.Debug($"COM 选择创建成功,路径数: {comSelection.Paths().Count}");
|
||||
|
||||
// 获取所有片段(已移除错误的去重逻辑)
|
||||
var allFragments = GetAllFragments(comSelection);
|
||||
LogManager.WriteLog($"获取到 {allFragments.Count} 个片段");
|
||||
LogManager.Debug($"获取到 {allFragments.Count} 个片段");
|
||||
|
||||
try
|
||||
{
|
||||
@ -164,11 +164,11 @@ namespace NavisworksTransport
|
||||
var fragmentTriangles = callback.GetTriangles();
|
||||
triangles.AddRange(fragmentTriangles);
|
||||
|
||||
LogManager.WriteLog($"片段生成了 {fragmentTriangles.Count} 个三角形");
|
||||
LogManager.Debug($"片段生成了 {fragmentTriangles.Count} 个三角形");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"处理片段失败: {ex.Message}");
|
||||
LogManager.Error($"处理片段失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,14 +186,14 @@ namespace NavisworksTransport
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"释放片段COM对象失败: {ex.Message}");
|
||||
LogManager.Warning($"释放片段COM对象失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"提取三角形失败: {ex.Message}");
|
||||
LogManager.Error($"提取三角形失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -407,7 +407,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"边计数完成,唯一边数: {edgeCount.Count}");
|
||||
LogManager.Debug($"边计数完成,唯一边数: {edgeCount.Count}");
|
||||
|
||||
// 找出只出现一次的边(边界边)
|
||||
int boundaryCount = 0;
|
||||
@ -426,22 +426,22 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"边界边分析完成:");
|
||||
LogManager.WriteLog($" 边界边数量: {boundaryCount}");
|
||||
LogManager.WriteLog($" 共享边数量: {sharedCount}");
|
||||
LogManager.WriteLog($" 边界/总边比例: {(double)boundaryCount / edges.Count:P1}");
|
||||
LogManager.Debug($"边界边分析完成:");
|
||||
LogManager.Debug($" 边界边数量: {boundaryCount}");
|
||||
LogManager.Debug($" 共享边数量: {sharedCount}");
|
||||
LogManager.Debug($" 边界/总边比例: {(double)boundaryCount / edges.Count:P1}");
|
||||
|
||||
// 验证边界边的连通性
|
||||
if (boundaryEdges.Count > 0)
|
||||
{
|
||||
var connectivity = AnalyzeBoundaryConnectivity(boundaryEdges);
|
||||
LogManager.WriteLog($"边界边连通性分析: {connectivity}");
|
||||
LogManager.Debug($"边界边连通性分析: {connectivity}");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"查找边界边失败: {ex.Message}");
|
||||
LogManager.Error($"查找边界边失败: {ex.Message}");
|
||||
}
|
||||
|
||||
return boundaryEdges;
|
||||
@ -501,18 +501,18 @@ namespace NavisworksTransport
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.WriteLog($"开始构建轮廓,总边数: {edges.Count}");
|
||||
LogManager.Debug($"开始构建轮廓,总边数: {edges.Count}");
|
||||
|
||||
while (remainingEdges.Count > 0 && contourCount < 10) // 最多处理10个轮廓
|
||||
{
|
||||
contourCount++;
|
||||
LogManager.WriteLog($"=== 开始构建第 {contourCount} 个轮廓 ===");
|
||||
LogManager.Debug($"=== 开始构建第 {contourCount} 个轮廓 ===");
|
||||
|
||||
var currentContour = BuildSingleContour(remainingEdges);
|
||||
|
||||
if (currentContour.Count >= 3) // 至少3个点才能形成有效轮廓
|
||||
{
|
||||
LogManager.WriteLog($"第 {contourCount} 个轮廓包含 {currentContour.Count} 个点");
|
||||
LogManager.Debug($"第 {contourCount} 个轮廓包含 {currentContour.Count} 个点");
|
||||
allOutlinePoints.AddRange(currentContour);
|
||||
|
||||
// 添加轮廓分隔符(使用特殊坐标标记)
|
||||
@ -523,23 +523,23 @@ namespace NavisworksTransport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog($"第 {contourCount} 个轮廓点数不足({currentContour.Count}),跳过");
|
||||
LogManager.Debug($"第 {contourCount} 个轮廓点数不足({currentContour.Count}),跳过");
|
||||
break; // 如果轮廓太小,可能是噪声,停止处理
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"轮廓构建完成,共 {contourCount} 个轮廓,总点数: {allOutlinePoints.Count}");
|
||||
LogManager.Info($"轮廓构建完成,共 {contourCount} 个轮廓,总点数: {allOutlinePoints.Count}");
|
||||
|
||||
// 如果有多个轮廓,返回最大的外部轮廓
|
||||
if (contourCount > 1)
|
||||
{
|
||||
LogManager.WriteLog("检测到多个轮廓,返回最大轮廓作为外部边界");
|
||||
LogManager.Debug("检测到多个轮廓,返回最大轮廓作为外部边界");
|
||||
return GetLargestContour(allOutlinePoints);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"构建轮廓失败: {ex.Message}");
|
||||
LogManager.Error($"构建轮廓失败: {ex.Message}");
|
||||
}
|
||||
|
||||
return allOutlinePoints;
|
||||
@ -566,7 +566,7 @@ namespace NavisworksTransport
|
||||
var currentPoint = currentEdge.End;
|
||||
var startPoint = currentEdge.Start;
|
||||
|
||||
LogManager.WriteLog($"轮廓起点: ({startPoint.X:F2}, {startPoint.Y:F2})");
|
||||
LogManager.Debug($"轮廓起点: ({startPoint.X:F2}, {startPoint.Y:F2})");
|
||||
|
||||
// 连接后续的边
|
||||
int maxIterations = remainingEdges.Count + 10; // 防止无限循环
|
||||
@ -609,25 +609,25 @@ namespace NavisworksTransport
|
||||
if (Math.Abs(currentPoint.X - startPoint.X) < tolerance &&
|
||||
Math.Abs(currentPoint.Y - startPoint.Y) < tolerance)
|
||||
{
|
||||
LogManager.WriteLog($"轮廓已闭合,点数: {contour.Count}");
|
||||
LogManager.Debug($"轮廓已闭合,点数: {contour.Count}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog($"无法找到连接边,轮廓中断,点数: {contour.Count}");
|
||||
LogManager.Warning($"无法找到连接边,轮廓中断,点数: {contour.Count}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iteration >= maxIterations)
|
||||
{
|
||||
LogManager.WriteLog($"轮廓构建达到最大迭代次数,强制停止");
|
||||
LogManager.Warning($"轮廓构建达到最大迭代次数,强制停止");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"构建单个轮廓失败: {ex.Message}");
|
||||
LogManager.Error($"构建单个轮廓失败: {ex.Message}");
|
||||
}
|
||||
|
||||
return contour;
|
||||
@ -671,7 +671,7 @@ namespace NavisworksTransport
|
||||
|
||||
if (contours.Count == 0)
|
||||
{
|
||||
LogManager.WriteLog("未找到有效轮廓");
|
||||
LogManager.Warning("未找到有效轮廓");
|
||||
return allPoints;
|
||||
}
|
||||
|
||||
@ -685,7 +685,7 @@ namespace NavisworksTransport
|
||||
if (contour.Count >= 3)
|
||||
{
|
||||
var area = CalculateContourArea(contour);
|
||||
LogManager.WriteLog($"轮廓 {i + 1} 面积: {area:F2}, 点数: {contour.Count}");
|
||||
LogManager.Debug($"轮廓 {i + 1} 面积: {area:F2}, 点数: {contour.Count}");
|
||||
|
||||
if (area > maxArea)
|
||||
{
|
||||
@ -695,17 +695,17 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"选择最大轮廓,面积: {maxArea:F2}, 原始点数: {largestContour.Count}");
|
||||
LogManager.Debug($"选择最大轮廓,面积: {maxArea:F2}, 原始点数: {largestContour.Count}");
|
||||
|
||||
// 清理和排序最大轮廓
|
||||
var cleanedContour = CleanAndSortContour(largestContour);
|
||||
LogManager.WriteLog($"清理后轮廓点数: {cleanedContour.Count}");
|
||||
LogManager.Debug($"清理后轮廓点数: {cleanedContour.Count}");
|
||||
|
||||
return cleanedContour;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"获取最大轮廓失败: {ex.Message}");
|
||||
LogManager.Error($"获取最大轮廓失败: {ex.Message}");
|
||||
return allPoints; // 返回原始点集合
|
||||
}
|
||||
}
|
||||
@ -723,7 +723,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
if (contour.Count < 3)
|
||||
{
|
||||
LogManager.WriteLog($"轮廓点数不足: {contour.Count}");
|
||||
LogManager.Warning($"轮廓点数不足: {contour.Count}");
|
||||
return contour;
|
||||
}
|
||||
|
||||
@ -750,26 +750,26 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"去重后点数: {uniquePoints.Count}");
|
||||
LogManager.Debug($"去重后点数: {uniquePoints.Count}");
|
||||
|
||||
if (uniquePoints.Count < 3)
|
||||
{
|
||||
LogManager.WriteLog("去重后点数不足,返回原始轮廓");
|
||||
LogManager.Warning("去重后点数不足,返回原始轮廓");
|
||||
return contour;
|
||||
}
|
||||
|
||||
// 第2步:排序点以形成正确的轮廓
|
||||
result = SortPointsIntoContour(uniquePoints);
|
||||
|
||||
LogManager.WriteLog($"排序后轮廓点数: {result.Count}");
|
||||
LogManager.Debug($"排序后轮廓点数: {result.Count}");
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
LogManager.WriteLog($" 排序点 {i}: ({result[i].X:F2}, {result[i].Y:F2})");
|
||||
LogManager.Debug($" 排序点 {i}: ({result[i].X:F2}, {result[i].Y:F2})");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"清理轮廓失败: {ex.Message}");
|
||||
LogManager.Error($"清理轮廓失败: {ex.Message}");
|
||||
return contour;
|
||||
}
|
||||
|
||||
@ -796,7 +796,7 @@ namespace NavisworksTransport
|
||||
var remainingPoints = new List<Point2D>(points);
|
||||
remainingPoints.Remove(startPoint);
|
||||
|
||||
LogManager.WriteLog($"轮廓起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");
|
||||
LogManager.Debug($"轮廓起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");
|
||||
|
||||
// 使用最近邻算法按顺序连接点
|
||||
var currentPoint = startPoint;
|
||||
@ -825,11 +825,11 @@ namespace NavisworksTransport
|
||||
remainingPoints.Remove(nearestPoint.Value);
|
||||
currentPoint = nearestPoint.Value;
|
||||
|
||||
LogManager.WriteLog($"下一个点: ({nearestPoint.Value.X:F2}, {nearestPoint.Value.Y:F2}), 距离: {minDistance:F2}");
|
||||
LogManager.Debug($"下一个点: ({nearestPoint.Value.X:F2}, {nearestPoint.Value.Y:F2}), 距离: {minDistance:F2}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog("无法找到下一个最近点");
|
||||
LogManager.Warning("无法找到下一个最近点");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -844,12 +844,12 @@ namespace NavisworksTransport
|
||||
Math.Pow(lastPoint.Y - firstPoint.Y, 2)
|
||||
);
|
||||
|
||||
LogManager.WriteLog($"轮廓闭合距离: {closingDistance:F2}");
|
||||
LogManager.Debug($"轮廓闭合距离: {closingDistance:F2}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"排序轮廓点失败: {ex.Message}");
|
||||
LogManager.Error($"排序轮廓点失败: {ex.Message}");
|
||||
return points;
|
||||
}
|
||||
|
||||
@ -940,7 +940,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"射线-三角形相交计算出错: {ex.Message}");
|
||||
LogManager.Error($"射线-三角形相交计算出错: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1041,11 +1041,11 @@ namespace NavisworksTransport
|
||||
|
||||
if (_transformMatrix != null)
|
||||
{
|
||||
LogManager.WriteLog($"几何回调处理器使用预处理矩阵,元素数量: {_transformMatrix.Length}");
|
||||
LogManager.Debug($"几何回调处理器使用预处理矩阵,元素数量: {_transformMatrix.Length}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog("几何回调处理器使用单位矩阵(无变换)");
|
||||
LogManager.Debug("几何回调处理器使用单位矩阵(无变换)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1089,7 +1089,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"处理三角形失败: {ex.Message}");
|
||||
LogManager.Error($"处理三角形失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1130,7 +1130,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"坐标变换失败: {ex.Message}");
|
||||
LogManager.Error($"坐标变换失败: {ex.Message}");
|
||||
return localPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,17 @@ using System.IO;
|
||||
|
||||
namespace NavisworksTransport
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志级别枚举
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统一日志管理器
|
||||
/// 提供全局日志记录功能
|
||||
@ -10,11 +21,16 @@ namespace NavisworksTransport
|
||||
public static class LogManager
|
||||
{
|
||||
private static readonly string _logFilePath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
|
||||
"Autodesk", "Navisworks Manage 2026", "NavisworksTransport", "logs", "debug.log");
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
|
||||
"Autodesk", "Navisworks Manage 2026", "plugins", "NavisworksTransportPlugin", "logs", "debug.log");
|
||||
|
||||
private static readonly object _lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 当前日志级别,默认为 Info
|
||||
/// </summary>
|
||||
private static LogLevel _currentLevel = LogLevel.Info;
|
||||
|
||||
/// <summary>
|
||||
/// 静态构造函数,确保日志目录存在并清空旧日志
|
||||
/// </summary>
|
||||
@ -43,6 +59,31 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public static string LogFilePath => _logFilePath;
|
||||
|
||||
/// <summary>
|
||||
/// 设置日志级别
|
||||
/// </summary>
|
||||
public static void SetLogLevel(LogLevel level)
|
||||
{
|
||||
_currentLevel = level;
|
||||
Info($"日志级别已设置为: {level}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前日志级别
|
||||
/// </summary>
|
||||
public static LogLevel GetLogLevel()
|
||||
{
|
||||
return _currentLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否应该记录指定级别的日志
|
||||
/// </summary>
|
||||
private static bool ShouldLog(LogLevel level)
|
||||
{
|
||||
return level >= _currentLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空调试日志
|
||||
/// </summary>
|
||||
@ -81,10 +122,10 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入调试日志(同时输出到Debug和文件)
|
||||
/// 写入调试日志(同时输出到Debug和文件)- 私有方法,强制使用带级别的方法
|
||||
/// </summary>
|
||||
/// <param name="message">日志消息</param>
|
||||
public static void WriteLog(string message)
|
||||
private static void WriteLog(string message)
|
||||
{
|
||||
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}";
|
||||
System.Diagnostics.Debug.WriteLine(logMessage);
|
||||
@ -108,7 +149,10 @@ namespace NavisworksTransport
|
||||
/// <param name="message">日志消息</param>
|
||||
public static void Info(string message)
|
||||
{
|
||||
WriteLog($"[INFO] {message}");
|
||||
if (ShouldLog(LogLevel.Info))
|
||||
{
|
||||
WriteLog($"[INFO] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -117,7 +161,10 @@ namespace NavisworksTransport
|
||||
/// <param name="message">日志消息</param>
|
||||
public static void Warning(string message)
|
||||
{
|
||||
WriteLog($"[WARN] {message}");
|
||||
if (ShouldLog(LogLevel.Warning))
|
||||
{
|
||||
WriteLog($"[WARN] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -126,7 +173,10 @@ namespace NavisworksTransport
|
||||
/// <param name="message">日志消息</param>
|
||||
public static void Error(string message)
|
||||
{
|
||||
WriteLog($"[ERROR] {message}");
|
||||
if (ShouldLog(LogLevel.Error))
|
||||
{
|
||||
WriteLog($"[ERROR] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -136,8 +186,11 @@ namespace NavisworksTransport
|
||||
/// <param name="exception">异常对象</param>
|
||||
public static void Error(string message, Exception exception)
|
||||
{
|
||||
WriteLog($"[ERROR] {message}: {exception.Message}");
|
||||
WriteLog($"[ERROR] 堆栈跟踪: {exception.StackTrace}");
|
||||
if (ShouldLog(LogLevel.Error))
|
||||
{
|
||||
WriteLog($"[ERROR] {message}: {exception.Message}");
|
||||
WriteLog($"[ERROR] 堆栈跟踪: {exception.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -146,7 +199,10 @@ namespace NavisworksTransport
|
||||
/// <param name="message">日志消息</param>
|
||||
public static void Debug(string message)
|
||||
{
|
||||
WriteLog($"[DEBUG] {message}");
|
||||
if (ShouldLog(LogLevel.Debug))
|
||||
{
|
||||
WriteLog($"[DEBUG] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -26,12 +26,12 @@ namespace NavisworksTransport.Utils
|
||||
// 方法: 空集合的SetHidden操作(几乎零开销的伪操作)
|
||||
var emptyCollection = new ModelItemCollection();
|
||||
document.Models.SetHidden(emptyCollection, false);
|
||||
LogManager.WriteLog($"[{logPrefix}] ✅ 已执行轻量级缓存刷新");
|
||||
LogManager.Debug($"[{logPrefix}] ✅ 已执行轻量级缓存刷新");
|
||||
}
|
||||
}
|
||||
catch (Exception refreshEx)
|
||||
{
|
||||
LogManager.WriteLog($"[{logPrefix}] ⚠️ 缓存刷新失败,但不影响主要操作: {refreshEx.Message}");
|
||||
LogManager.Warning($"[{logPrefix}] ⚠️ 缓存刷新失败,但不影响主要操作: {refreshEx.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user