375 lines
15 KiB
C#
375 lines
15 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|