diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 110cc46..c02678d 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -155,7 +155,9 @@
"Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" AStarTestRunner.csproj)",
"Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" NavisworksTransport.UnitTests.csproj)",
"Bash(\"bin\\Debug\\AStarTestRunner.exe\")",
- "Bash(git restore:*)"
+ "Bash(git restore:*)",
+ "Read(//c/Program Files/Autodesk/Navisworks Manage 2026/**)",
+ "Bash(where:*)"
],
"deny": [],
"additionalDirectories": [
diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index 8de5f9b..25b291c 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -91,7 +91,13 @@
packages\RoyT.AStar.3.0.2\lib\netstandard2.0\Roy-T.AStar.dll
True
-
+
+
+
+ packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.118.0\lib\net46\System.Data.SQLite.dll
+ True
+
+
@@ -106,6 +112,8 @@
+
+
diff --git a/clean_database.bat b/clean_database.bat
new file mode 100644
index 0000000..3866d43
--- /dev/null
+++ b/clean_database.bat
@@ -0,0 +1,35 @@
+@echo off
+echo ========================================
+echo NavisworksTransport 数据库清理工具
+echo ========================================
+echo.
+echo 此脚本将删除所有现有的路径数据库文件(.db文件)
+echo 下次启动插件时将自动创建新的数据库结构
+echo.
+echo 警告:此操作将删除所有历史路径数据!
+echo.
+pause
+
+REM 设置数据库文件所在目录
+set DB_DIR=C:\Users\Tellme\Documents\NavisworksTransport\分层输出
+
+echo.
+echo 正在清理数据库文件...
+echo 目录: %DB_DIR%
+echo.
+
+REM 删除所有.db文件
+if exist "%DB_DIR%\*.db" (
+ del /f /q "%DB_DIR%\*.db"
+ echo 已删除所有数据库文件
+) else (
+ echo 未找到数据库文件
+)
+
+echo.
+echo ========================================
+echo 数据库清理完成!
+echo 下次启动Navisworks插件时将自动创建新的数据库
+echo ========================================
+echo.
+pause
\ No newline at end of file
diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md
index b5e0aa1..2f7e32d 100644
--- a/doc/requirement/todo_features.md
+++ b/doc/requirement/todo_features.md
@@ -2,6 +2,10 @@
## 功能点
+### [2025/10/01]
+
+1. [x] (功能)路径分析
+
### [2025/09/29]
1. [x] (功能)导出导航地图为图片
diff --git a/packages.config b/packages.config
index 5eb4173..0d232e8 100644
--- a/packages.config
+++ b/packages.config
@@ -4,4 +4,5 @@
+
\ No newline at end of file
diff --git a/src/Core/MainPlugin.cs b/src/Core/MainPlugin.cs
index 4fa6014..2256d1e 100644
--- a/src/Core/MainPlugin.cs
+++ b/src/Core/MainPlugin.cs
@@ -471,10 +471,24 @@ namespace NavisworksTransport
LogManager.Info($"[文档管理] 文档文件名: {activeDoc?.FileName ?? "空"}");
LogManager.Info($"[文档管理] 文档标题: {activeDoc?.Title ?? "空"}");
- // 分析状态变化类型
+ // 分析状态变化类型并执行相应操作
if (!_hasModels && currentHasModels)
{
LogManager.Info($"[文档管理] *** 状态分析: 从无到有(可能是打开文档)***");
+
+ // 文档加载完成,初始化PathDatabase
+ if (!string.IsNullOrEmpty(activeDoc?.FileName))
+ {
+ GlobalExceptionHandler.SafeExecute(() =>
+ {
+ var pathManager = PathPlanningManager.GetActivePathManager();
+ if (pathManager != null)
+ {
+ pathManager.EnsureDatabaseInitialized();
+ LogManager.Info("[文档管理] 已触发PathDatabase初始化");
+ }
+ }, "初始化PathDatabase");
+ }
}
else if (_hasModels && !currentHasModels)
{
@@ -488,14 +502,11 @@ namespace NavisworksTransport
{
LogManager.Info($"[文档管理] *** 状态分析: 保持有模型状态(模型数量变化)***");
}
-
+
LogManager.Info("========================================");
-
+
// 更新状态
_hasModels = currentHasModels;
-
- // 暂时不执行任何清理或初始化操作
- LogManager.Info("[文档管理] 观察模式:不执行清理或初始化操作");
}
///
diff --git a/src/Core/PathAnalysisService.cs b/src/Core/PathAnalysisService.cs
new file mode 100644
index 0000000..1d981ff
--- /dev/null
+++ b/src/Core/PathAnalysisService.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport
+{
+ ///
+ /// 路径分析服务 - 简化版
+ /// 负责路径碰撞分析和评分计算
+ ///
+ public class PathAnalysisService
+ {
+ private readonly PathDatabase _database;
+
+ public PathAnalysisService(PathDatabase database)
+ {
+ _database = database ?? throw new ArgumentNullException(nameof(database));
+ }
+
+ ///
+ /// 分析单条路径
+ ///
+ /// 路径对象
+ /// 分析策略:安全优先/效率优先
+ /// 分析结果
+ public PathAnalysisResult AnalyzePath(PathRoute route, string strategy = "安全优先")
+ {
+ try
+ {
+ // 1. 执行碰撞检测
+ var collisions = DetectCollisions(route);
+
+ // 2. 保存碰撞结果到数据库
+ _database.SaveCollisions(route.Id, collisions);
+
+ // 3. 计算评分
+ var safetyScore = CalculateSafetyScore(collisions.Count, route.TotalLength);
+ var efficiencyScore = CalculateEfficiencyScore(route.TotalLength, route.EstimatedTime);
+
+ // 4. 保存分析结果到数据库
+ _database.SaveAnalysisScore(route.Id, collisions.Count, safetyScore, efficiencyScore, strategy);
+
+ LogManager.Info($"路径分析完成: {route.Name}, 碰撞={collisions.Count}, 安全分={safetyScore:F1}, 效率分={efficiencyScore:F1}");
+
+ return _database.GetAnalysisResult(route.Id);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"路径分析失败: {route?.Name ?? "未知路径"}, {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ ///
+ /// 对比多条路径,返回最佳路径和建议
+ ///
+ /// 路径列表
+ /// 分析策略
+ /// 对比结果
+ public PathComparisonResult CompareRoutes(List routes, string strategy = "安全优先")
+ {
+ if (routes == null || routes.Count == 0)
+ throw new ArgumentException("路径列表不能为空");
+
+ var result = new PathComparisonResult
+ {
+ Strategy = strategy,
+ Analyses = new List()
+ };
+
+ // 1. 分析每条路径
+ foreach (var route in routes)
+ {
+ var analysis = AnalyzePath(route, strategy);
+ result.Analyses.Add(analysis);
+ }
+
+ // 2. 根据策略选择最佳路径
+ PathAnalysisResult bestRoute;
+ if (strategy == "安全优先")
+ {
+ // 优先选择碰撞少、安全分高的路径
+ bestRoute = result.Analyses
+ .OrderBy(a => a.CollisionCount)
+ .ThenByDescending(a => a.SafetyScore)
+ .First();
+ }
+ else // 效率优先
+ {
+ // 优先选择效率分高、长度短的路径
+ bestRoute = result.Analyses
+ .OrderByDescending(a => a.EfficiencyScore)
+ .ThenBy(a => a.CollisionCount)
+ .First();
+ }
+
+ result.BestRouteId = bestRoute.RouteId;
+ result.BestRouteName = routes.First(r => r.Id == bestRoute.RouteId).Name;
+
+ // 3. 生成优化建议
+ result.Suggestions = GenerateSuggestions(result.Analyses, routes, strategy);
+
+ LogManager.Info($"路径对比完成: 共{routes.Count}条路径, 最佳路径={result.BestRouteName}, 策略={strategy}");
+
+ return result;
+ }
+
+ ///
+ /// 执行碰撞检测
+ /// 注意:实际的碰撞检测需要在路径动画执行时进行
+ /// 这里优先从数据库加载已有的碰撞结果
+ ///
+ private List DetectCollisions(PathRoute route)
+ {
+ try
+ {
+ // 先尝试从数据库获取已有的碰撞数据
+ var existingCount = _database.GetCollisionCount(route.Id);
+
+ if (existingCount > 0)
+ {
+ LogManager.Info($"从数据库加载碰撞数据: {route.Name}, 碰撞数={existingCount}");
+ // 返回空列表,碰撞数量已经从数据库获取
+ return new List();
+ }
+
+ // 如果数据库没有碰撞数据,返回空列表
+ // TODO: 未来可以在这里触发实际的碰撞检测
+ LogManager.Info($"路径{route.Name}暂无碰撞数据");
+ return new List();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"获取碰撞数据失败: {route.Name}, {ex.Message}", ex);
+ return new List();
+ }
+ }
+
+ ///
+ /// 计算安全评分(100分制)
+ /// 碰撞越少分数越高
+ ///
+ private double CalculateSafetyScore(int collisionCount, double pathLength)
+ {
+ // 基础分:100分
+ double baseScore = 100.0;
+
+ // 每次碰撞扣10分
+ double collisionPenalty = collisionCount * 10.0;
+
+ // 长路径额外扣分(每100米扣1分)
+ double lengthPenalty = (pathLength / 100.0) * 0.5;
+
+ double score = baseScore - collisionPenalty - lengthPenalty;
+
+ // 分数不低于0
+ return Math.Max(0, score);
+ }
+
+ ///
+ /// 计算效率评分(100分制)
+ /// 路径越短、速度越快分数越高
+ ///
+ private double CalculateEfficiencyScore(double pathLength, double estimatedTime)
+ {
+ if (estimatedTime <= 0)
+ return 0;
+
+ // 计算平均速度 (m/s)
+ double avgSpeed = pathLength / estimatedTime;
+
+ // 速度分数:速度越快分数越高
+ // 假设理想速度为1.0 m/s,速度每提升0.1则加10分
+ double speedScore = Math.Min(100, avgSpeed * 100);
+
+ // 路径长度惩罚:路径越短越好
+ // 基准长度100米,每超过10米扣1分
+ double lengthPenalty = Math.Max(0, (pathLength - 100) / 10);
+
+ double score = speedScore - lengthPenalty;
+
+ return Math.Max(0, Math.Min(100, score));
+ }
+
+ ///
+ /// 生成优化建议(基于简单规则)
+ ///
+ private List GenerateSuggestions(List analyses,
+ List routes, string strategy)
+ {
+ var suggestions = new List();
+
+ // 规则1:碰撞过多
+ var maxCollision = analyses.Max(a => a.CollisionCount);
+ if (maxCollision > 5)
+ {
+ suggestions.Add($"✅ 优先处理碰撞热点,当前最多{maxCollision}次碰撞");
+ }
+ else if (maxCollision > 0)
+ {
+ suggestions.Add($"⚠️ 存在{maxCollision}次碰撞,建议优化路径避让");
+ }
+
+ // 规则2:路径长度差异大
+ var avgLength = routes.Average(r => r.TotalLength);
+ var longRoutes = routes.Where(r => r.TotalLength > avgLength * 1.3).ToList();
+ if (longRoutes.Count > 0)
+ {
+ suggestions.Add($"✅ {longRoutes.Count}条路径偏长(超过平均值30%),建议优化路线");
+ }
+
+ // 规则3:时间效率建议
+ var avgTime = routes.Average(r => r.EstimatedTime);
+ var slowRoutes = routes.Where(r => r.EstimatedTime > avgTime * 1.2).ToList();
+ if (slowRoutes.Count > 0)
+ {
+ suggestions.Add($"⚠️ {slowRoutes.Count}条路径耗时较长,考虑提高通行速度或缩短路径");
+ }
+
+ // 规则4:零碰撞路径推荐
+ var zeroCollisionRoutes = analyses.Where(a => a.CollisionCount == 0).ToList();
+ if (zeroCollisionRoutes.Count > 0)
+ {
+ suggestions.Add($"✅ {zeroCollisionRoutes.Count}条路径无碰撞,优先推荐使用");
+ }
+
+ // 规则5:策略特定建议
+ if (strategy == "安全优先")
+ {
+ suggestions.Add("💡 当前策略:安全优先 - 建议选择碰撞最少的路径");
+ }
+ else
+ {
+ suggestions.Add("💡 当前策略:效率优先 - 建议选择最短路径,但需注意安全");
+ }
+
+ // 如果没有任何建议,添加默认建议
+ if (suggestions.Count == 0)
+ {
+ suggestions.Add("✅ 所有路径表现良好,可根据实际需求选择");
+ }
+
+ return suggestions;
+ }
+ }
+
+ ///
+ /// 路径对比结果
+ ///
+ public class PathComparisonResult
+ {
+ /// 最佳路径ID
+ public string BestRouteId { get; set; }
+
+ /// 最佳路径名称
+ public string BestRouteName { get; set; }
+
+ /// 分析策略
+ public string Strategy { get; set; }
+
+ /// 所有路径的分析结果
+ public List Analyses { get; set; }
+
+ /// 优化建议列表
+ public List Suggestions { get; set; }
+ }
+}
diff --git a/src/Core/PathDatabase.cs b/src/Core/PathDatabase.cs
new file mode 100644
index 0000000..366eda7
--- /dev/null
+++ b/src/Core/PathDatabase.cs
@@ -0,0 +1,519 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SQLite;
+using System.IO;
+using Autodesk.Navisworks.Api;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport
+{
+ ///
+ /// 路径数据库管理器 - 简化版
+ /// 负责路径和碰撞数据的持久化存储
+ ///
+ public class PathDatabase : IDisposable
+ {
+ private SQLiteConnection _connection;
+ private readonly string _dbPath;
+
+ ///
+ /// 初始化路径数据库
+ ///
+ /// Navisworks文档路径
+ public PathDatabase(string documentPath)
+ {
+ if (string.IsNullOrEmpty(documentPath))
+ throw new ArgumentException("文档路径不能为空");
+
+ // 数据库文件与nwd文件同名,扩展名为.db
+ _dbPath = Path.ChangeExtension(documentPath, ".db");
+
+ InitializeDatabase();
+ }
+
+ ///
+ /// 初始化数据库连接和表结构
+ ///
+ private void InitializeDatabase()
+ {
+ bool isNewDatabase = !File.Exists(_dbPath);
+
+ _connection = new SQLiteConnection($"Data Source={_dbPath};Version=3;");
+ _connection.Open();
+
+ // 启用WAL模式(Write-Ahead Logging,支持并发读)
+ ExecuteNonQuery("PRAGMA journal_mode=WAL");
+ ExecuteNonQuery("PRAGMA foreign_keys=ON");
+
+ if (isNewDatabase)
+ {
+ CreateTables();
+ LogManager.Info($"创建新数据库: {_dbPath}");
+ }
+ else
+ {
+ LogManager.Info($"打开现有数据库: {_dbPath}");
+ }
+ }
+
+ ///
+ /// 创建数据库表结构
+ ///
+ private void CreateTables()
+ {
+ // 1. 路径基本信息表
+ ExecuteNonQuery(@"
+ CREATE TABLE IF NOT EXISTS PathRoutes (
+ Id TEXT PRIMARY KEY,
+ Name TEXT NOT NULL,
+ TotalLength REAL,
+ EstimatedTime REAL,
+ CreatedTime DATETIME,
+ LastModified DATETIME
+ )
+ ");
+
+ // 2. 碰撞结果表
+ ExecuteNonQuery(@"
+ CREATE TABLE IF NOT EXISTS CollisionResults (
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
+ RouteId TEXT NOT NULL,
+ Item1Name TEXT,
+ Item2Name TEXT,
+ CenterX REAL,
+ CenterY REAL,
+ CenterZ REAL,
+ Distance REAL,
+ DetectedTime DATETIME,
+ FOREIGN KEY(RouteId) REFERENCES PathRoutes(Id) ON DELETE CASCADE
+ )
+ ");
+
+ // 3. 分析结果表
+ ExecuteNonQuery(@"
+ CREATE TABLE IF NOT EXISTS AnalysisResults (
+ RouteId TEXT PRIMARY KEY,
+ CollisionCount INTEGER,
+ SafetyScore REAL,
+ EfficiencyScore REAL,
+ OverallScore REAL,
+ AnalysisTime DATETIME,
+ Strategy TEXT,
+ FOREIGN KEY(RouteId) REFERENCES PathRoutes(Id) ON DELETE CASCADE
+ )
+ ");
+
+ // 4. 路径点表
+ ExecuteNonQuery(@"
+ CREATE TABLE IF NOT EXISTS PathPoints (
+ Id TEXT PRIMARY KEY,
+ RouteId TEXT NOT NULL,
+ SequenceNumber INTEGER NOT NULL,
+ Name TEXT,
+ X REAL,
+ Y REAL,
+ Z REAL,
+ Type INTEGER,
+ FOREIGN KEY(RouteId) REFERENCES PathRoutes(Id) ON DELETE CASCADE
+ )
+ ");
+
+ // 创建索引
+ ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_collisions_route ON CollisionResults(RouteId)");
+ ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_pathpoints_route ON PathPoints(RouteId)");
+ }
+
+ ///
+ /// 保存路径基本信息
+ ///
+ public void SavePathRoute(PathRoute route)
+ {
+ // 使用事务确保路径和路径点一起保存
+ using (var transaction = _connection.BeginTransaction())
+ {
+ try
+ {
+ // 保存路径基本信息
+ var sql = @"
+ INSERT OR REPLACE INTO PathRoutes
+ (Id, Name, TotalLength, EstimatedTime, CreatedTime, LastModified)
+ VALUES (@id, @name, @length, @time, @created, @modified)
+ ";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", route.Id);
+ cmd.Parameters.AddWithValue("@name", route.Name);
+ cmd.Parameters.AddWithValue("@length", route.TotalLength);
+ cmd.Parameters.AddWithValue("@time", route.EstimatedTime);
+ cmd.Parameters.AddWithValue("@created", route.CreatedTime);
+ cmd.Parameters.AddWithValue("@modified", DateTime.Now);
+ cmd.ExecuteNonQuery();
+ }
+
+ // 删除旧的路径点
+ ExecuteNonQuery("DELETE FROM PathPoints WHERE RouteId=@id", new { id = route.Id });
+
+ // 保存新的路径点
+ if (route.Points != null && route.Points.Count > 0)
+ {
+ var pointSql = @"
+ INSERT INTO PathPoints
+ (Id, RouteId, SequenceNumber, Name, X, Y, Z, Type)
+ VALUES (@id, @routeId, @seq, @name, @x, @y, @z, @type)
+ ";
+
+ for (int i = 0; i < route.Points.Count; i++)
+ {
+ var point = route.Points[i];
+ using (var cmd = new SQLiteCommand(pointSql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", point.Id);
+ cmd.Parameters.AddWithValue("@routeId", route.Id);
+ cmd.Parameters.AddWithValue("@seq", i);
+ cmd.Parameters.AddWithValue("@name", point.Name ?? "");
+ cmd.Parameters.AddWithValue("@x", point.Position.X);
+ cmd.Parameters.AddWithValue("@y", point.Position.Y);
+ cmd.Parameters.AddWithValue("@z", point.Position.Z);
+ cmd.Parameters.AddWithValue("@type", (int)point.Type);
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ LogManager.Info($"保存路径: {route.Name},包含 {route.Points.Count} 个路径点");
+ }
+
+ transaction.Commit();
+ }
+ catch (Exception ex)
+ {
+ transaction.Rollback();
+ LogManager.Error($"保存路径失败: {ex.Message}", ex);
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// 保存路径的碰撞结果
+ ///
+ public void SaveCollisions(string routeId, List collisions)
+ {
+ // 先删除旧的碰撞数据
+ ExecuteNonQuery("DELETE FROM CollisionResults WHERE RouteId=@id",
+ new { id = routeId });
+
+ if (collisions == null || collisions.Count == 0)
+ return;
+
+ // 批量插入新数据
+ using (var transaction = _connection.BeginTransaction())
+ {
+ try
+ {
+ var sql = @"
+ INSERT INTO CollisionResults
+ (RouteId, Item1Name, Item2Name, CenterX, CenterY, CenterZ, Distance, DetectedTime)
+ VALUES (@rid, @i1, @i2, @x, @y, @z, @dist, @time)
+ ";
+
+ foreach (var collision in collisions)
+ {
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@rid", routeId);
+ cmd.Parameters.AddWithValue("@i1", GetItemDisplayName(collision.Item1));
+ cmd.Parameters.AddWithValue("@i2", GetItemDisplayName(collision.Item2));
+ cmd.Parameters.AddWithValue("@x", collision.Center.X);
+ cmd.Parameters.AddWithValue("@y", collision.Center.Y);
+ cmd.Parameters.AddWithValue("@z", collision.Center.Z);
+ cmd.Parameters.AddWithValue("@dist", collision.Distance);
+ cmd.Parameters.AddWithValue("@time", DateTime.Now);
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ transaction.Commit();
+ LogManager.Info($"保存碰撞结果: RouteId={routeId}, Count={collisions.Count}");
+ }
+ catch (Exception ex)
+ {
+ transaction.Rollback();
+ LogManager.Error($"保存碰撞结果失败: {ex.Message}", ex);
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// 保存分析评分结果
+ ///
+ public void SaveAnalysisScore(string routeId, int collisionCount, double safetyScore,
+ double efficiencyScore, string strategy)
+ {
+ var overallScore = (safetyScore + efficiencyScore) / 2.0;
+
+ var sql = @"
+ INSERT OR REPLACE INTO AnalysisResults
+ (RouteId, CollisionCount, SafetyScore, EfficiencyScore, OverallScore, AnalysisTime, Strategy)
+ VALUES (@id, @count, @safety, @eff, @overall, @time, @strategy)
+ ";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", routeId);
+ cmd.Parameters.AddWithValue("@count", collisionCount);
+ cmd.Parameters.AddWithValue("@safety", safetyScore);
+ cmd.Parameters.AddWithValue("@eff", efficiencyScore);
+ cmd.Parameters.AddWithValue("@overall", overallScore);
+ cmd.Parameters.AddWithValue("@time", DateTime.Now);
+ cmd.Parameters.AddWithValue("@strategy", strategy ?? "默认");
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ ///
+ /// 获取路径的碰撞数量
+ ///
+ public int GetCollisionCount(string routeId)
+ {
+ var sql = "SELECT COUNT(*) FROM CollisionResults WHERE RouteId=@id";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", routeId);
+ var result = cmd.ExecuteScalar();
+ return Convert.ToInt32(result);
+ }
+ }
+
+ ///
+ /// 获取路径的分析结果
+ ///
+ public PathAnalysisResult GetAnalysisResult(string routeId)
+ {
+ var sql = "SELECT * FROM AnalysisResults WHERE RouteId=@id";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", routeId);
+ using (var reader = cmd.ExecuteReader())
+ {
+ if (reader.Read())
+ {
+ return new PathAnalysisResult
+ {
+ RouteId = reader["RouteId"].ToString(),
+ CollisionCount = Convert.ToInt32(reader["CollisionCount"]),
+ SafetyScore = Convert.ToDouble(reader["SafetyScore"]),
+ EfficiencyScore = Convert.ToDouble(reader["EfficiencyScore"]),
+ OverallScore = Convert.ToDouble(reader["OverallScore"]),
+ AnalysisTime = Convert.ToDateTime(reader["AnalysisTime"]),
+ Strategy = reader["Strategy"].ToString()
+ };
+ }
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// 获取所有路径的分析结果
+ ///
+ public List GetAllAnalysisResults()
+ {
+ var results = new List();
+ var sql = "SELECT * FROM AnalysisResults ORDER BY OverallScore DESC";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ using (var reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ results.Add(new PathAnalysisResult
+ {
+ RouteId = reader["RouteId"].ToString(),
+ CollisionCount = Convert.ToInt32(reader["CollisionCount"]),
+ SafetyScore = Convert.ToDouble(reader["SafetyScore"]),
+ EfficiencyScore = Convert.ToDouble(reader["EfficiencyScore"]),
+ OverallScore = Convert.ToDouble(reader["OverallScore"]),
+ AnalysisTime = Convert.ToDateTime(reader["AnalysisTime"]),
+ Strategy = reader["Strategy"].ToString()
+ });
+ }
+ }
+
+ return results;
+ }
+
+ ///
+ /// 删除路径及其相关数据
+ ///
+ /// 路径ID
+ public void DeletePathRoute(string routeId)
+ {
+ try
+ {
+ // 由于设置了外键级联删除,删除路径时会自动删除相关的碰撞结果和分析结果
+ var sql = "DELETE FROM PathRoutes WHERE Id = @id";
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@id", routeId);
+ int affected = cmd.ExecuteNonQuery();
+ LogManager.Info($"删除路径记录: ID={routeId}, 影响行数={affected}");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"删除路径失败: ID={routeId}, {ex.Message}", ex);
+ throw;
+ }
+ }
+
+ ///
+ /// 获取所有路径基本信息
+ ///
+ public List GetAllPathRoutes()
+ {
+ var routes = new List();
+ var sql = @"SELECT pr.*, ar.CollisionCount, ar.SafetyScore, ar.EfficiencyScore, ar.OverallScore
+ FROM PathRoutes pr
+ LEFT JOIN AnalysisResults ar ON pr.Id = ar.RouteId
+ ORDER BY pr.LastModified DESC";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ using (var reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var route = new PathRoute
+ {
+ Id = reader["Id"].ToString(),
+ Name = reader["Name"].ToString(),
+ TotalLength = Convert.ToDouble(reader["TotalLength"]),
+ EstimatedTime = Convert.ToDouble(reader["EstimatedTime"]),
+ CreatedTime = Convert.ToDateTime(reader["CreatedTime"]),
+ LastModified = Convert.ToDateTime(reader["LastModified"])
+ };
+
+ // 添加分析结果(如果存在)
+ if (!reader.IsDBNull(reader.GetOrdinal("CollisionCount")))
+ {
+ route.CollisionCount = Convert.ToInt32(reader["CollisionCount"]);
+ route.SafetyScore = Convert.ToDouble(reader["SafetyScore"]);
+ route.EfficiencyScore = Convert.ToDouble(reader["EfficiencyScore"]);
+ route.OverallScore = Convert.ToDouble(reader["OverallScore"]);
+ }
+
+ routes.Add(route);
+ }
+ }
+
+ // 为每个路径加载路径点
+ foreach (var route in routes)
+ {
+ LoadPathPoints(route);
+ }
+
+ LogManager.Info($"从数据库加载了 {routes.Count} 条路径记录");
+ return routes;
+ }
+
+ ///
+ /// 加载指定路径的路径点
+ ///
+ private void LoadPathPoints(PathRoute route)
+ {
+ var sql = @"SELECT * FROM PathPoints
+ WHERE RouteId=@routeId
+ ORDER BY SequenceNumber";
+
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ cmd.Parameters.AddWithValue("@routeId", route.Id);
+ using (var reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var point = new PathPoint
+ {
+ Id = reader["Id"].ToString(),
+ Name = reader["Name"].ToString(),
+ Position = new Autodesk.Navisworks.Api.Point3D(
+ Convert.ToDouble(reader["X"]),
+ Convert.ToDouble(reader["Y"]),
+ Convert.ToDouble(reader["Z"])
+ ),
+ Type = (PathPointType)Convert.ToInt32(reader["Type"])
+ };
+
+ route.Points.Add(point);
+ }
+ }
+ }
+
+ LogManager.Info($"为路径 '{route.Name}' 加载了 {route.Points.Count} 个路径点");
+ }
+
+ ///
+ /// 执行非查询SQL语句
+ ///
+ private void ExecuteNonQuery(string sql, object parameters = null)
+ {
+ using (var cmd = new SQLiteCommand(sql, _connection))
+ {
+ if (parameters != null)
+ {
+ var props = parameters.GetType().GetProperties();
+ foreach (var prop in props)
+ {
+ cmd.Parameters.AddWithValue($"@{prop.Name}", prop.GetValue(parameters));
+ }
+ }
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ ///
+ /// 获取ModelItem的显示名称
+ ///
+ private string GetItemDisplayName(ModelItem item)
+ {
+ if (item == null)
+ return "未知对象";
+
+ try
+ {
+ return item.DisplayName ?? item.ToString();
+ }
+ catch
+ {
+ return "未知对象";
+ }
+ }
+
+ ///
+ /// 释放资源
+ ///
+ public void Dispose()
+ {
+ _connection?.Close();
+ _connection?.Dispose();
+ }
+ }
+
+ ///
+ /// 路径分析结果数据模型
+ ///
+ public class PathAnalysisResult
+ {
+ public string RouteId { get; set; }
+ public int CollisionCount { get; set; }
+ public double SafetyScore { get; set; }
+ public double EfficiencyScore { get; set; }
+ public double OverallScore { get; set; }
+ public DateTime AnalysisTime { get; set; }
+ public string Strategy { get; set; }
+ }
+}
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index cca9077..b90f418 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -25,6 +25,10 @@ namespace NavisworksTransport
private CoordinateConverter _coordinateConverter;
private PathPointRenderPlugin _renderPlugin;
+
+ // 路径分析相关
+ private PathDatabase _pathDatabase;
+ private PathAnalysisService _analysisService;
private List _walkableAreas;
private List _routes;
private PathRoute _currentRoute;
@@ -111,6 +115,40 @@ namespace NavisworksTransport
_activePathManager = this;
LogManager.WriteLog($"[路径管理] 设置_activePathManager静态引用, ManagerId: {_managerId}");
+ // 尝试初始化路径分析数据库
+ EnsureDatabaseInitialized();
+ }
+
+ ///
+ /// 确保路径分析数据库已初始化(支持延迟初始化)
+ ///
+ public void EnsureDatabaseInitialized()
+ {
+ if (_pathDatabase != null && _analysisService != null)
+ {
+ LogManager.Info("路径分析数据库已初始化,跳过");
+ return;
+ }
+
+ try
+ {
+ var documentPath = Autodesk.Navisworks.Api.Application.ActiveDocument?.FileName;
+ if (!string.IsNullOrEmpty(documentPath))
+ {
+ _pathDatabase = new PathDatabase(documentPath);
+ _analysisService = new PathAnalysisService(_pathDatabase);
+ LogManager.Info($"路径分析数据库初始化成功,文档路径: {documentPath}");
+ }
+ else
+ {
+ LogManager.Warning("文档路径为空,路径分析数据库初始化将延迟到文档加载后");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"初始化路径分析数据库失败: {ex.Message}", ex);
+ }
+
// 获取已注册的圆形渲染插件实例
try
{
@@ -119,7 +157,7 @@ namespace NavisworksTransport
{
LogManager.WriteLog("[路径管理] ✅ PathPointRenderPlugin实例获取成功");
LogManager.WriteLog($"[路径管理] 渲染插件状态 - 启用: {_renderPlugin.IsEnabled}, 标记数量: {_renderPlugin.MarkerCount}");
-
+
// 推送默认的网格大小和车辆参数,确保渲染插件有合理的初始值
InitializeRenderPluginDefaults();
}
@@ -142,6 +180,9 @@ namespace NavisworksTransport
_coordinateConverter = null; // 将在需要时初始化
_pathPointMarkers = new List();
+ // 从数据库加载历史路径到内存
+ LoadHistoricalRoutesFromDatabase();
+
LogManager.Info($"PathPlanningManager初始化完成,ManagerId: {_managerId}");
}
@@ -163,14 +204,14 @@ namespace NavisworksTransport
const double defaultVehicleWidth = 1.0; // 米
const double defaultVehicleHeight = 2.0; // 米
const double defaultSafetyMargin = 0.25; // 米
-
+
_renderPlugin.SetVehicleParameters(
defaultVehicleLength,
- defaultVehicleWidth,
+ defaultVehicleWidth,
defaultVehicleHeight,
defaultSafetyMargin
);
-
+
LogManager.Info($"[渲染插件初始化] 已设置默认车辆参数: 长={defaultVehicleLength}m, 宽={defaultVehicleWidth}m, 高={defaultVehicleHeight}m, 安全间隙={defaultSafetyMargin}m");
}
catch (Exception ex)
@@ -679,10 +720,10 @@ namespace NavisworksTransport
}
///
- /// 从3D中移除路径点
+ /// 删除路径点
///
- /// 要移除的路径点
- public void RemovePathPointFrom3D(PathPoint point)
+ /// 要删除的路径点
+ public void RemovePathPoint(PathPoint point)
{
try
{
@@ -708,6 +749,12 @@ namespace NavisworksTransport
// 触发路径点移除事件
RaisePathPointOperation(PathPointOperationType.Removed, point, CurrentRoute);
+
+ // 保存到数据库
+ if (CurrentRoute != null)
+ {
+ SavePathToDatabase(CurrentRoute);
+ }
}
}
catch (Exception ex)
@@ -991,6 +1038,8 @@ namespace NavisworksTransport
if (!_routes.Contains(autoRoute))
{
_routes.Add(autoRoute);
+ // 保存自动生成的路径到数据库
+ SavePathToDatabase(autoRoute);
}
CurrentRoute = autoRoute;
@@ -1187,6 +1236,9 @@ namespace NavisworksTransport
_routes.Add(route);
RaiseStatusChanged($"已添加路径: {route.Name}", PathPlanningStatusType.Success);
+ // 保存到数据库
+ SavePathToDatabase(route);
+
// AddRoute只负责添加路径到数据集合,不自动设置当前路径
// 路径选择应该通过专门的选择逻辑处理,而不是添加操作的副作用
// if (_currentRoute == null || _currentRoute.Points.Count == 0)
@@ -1222,6 +1274,9 @@ namespace NavisworksTransport
_routes.Add(newRoute);
CurrentRoute = newRoute;
+ // 保存到数据库
+ SavePathToDatabase(newRoute);
+
RaiseStatusChanged($"已创建新路径: {routeName}", PathPlanningStatusType.Success);
return newRoute;
}
@@ -1240,6 +1295,21 @@ namespace NavisworksTransport
bool removed = _routes.Remove(route);
if (removed)
{
+ // 从数据库删除
+ if (_pathDatabase != null)
+ {
+ try
+ {
+ _pathDatabase.DeletePathRoute(route.Id);
+ LogManager.Info($"已从数据库删除路径: {route.Name}");
+ }
+ catch (Exception dbEx)
+ {
+ LogManager.Error($"从数据库删除路径失败: {dbEx.Message}", dbEx);
+ // 继续执行,不影响内存操作
+ }
+ }
+
if (_currentRoute == route)
{
var newRoute = _routes.FirstOrDefault() ?? new PathRoute("默认路径");
@@ -1379,6 +1449,9 @@ namespace NavisworksTransport
{
_routes.Add(CurrentRoute);
+ // 保存到数据库
+ SavePathToDatabase(CurrentRoute);
+
// 添加历史记录
var historyEntry = new PathHistoryEntry(
CurrentRoute.Id,
@@ -1392,6 +1465,9 @@ namespace NavisworksTransport
// 如果是编辑模式,保存编辑历史
if (_pathEditState == PathEditState.Editing && EditingRoute != null)
{
+ // 更新数据库
+ SavePathToDatabase(EditingRoute);
+
var historyEntry = new PathHistoryEntry(
EditingRoute.Id,
PathHistoryOperationType.Edited,
@@ -1498,10 +1574,10 @@ namespace NavisworksTransport
}
///
- /// 确认修改路径点
+ /// 更新路径点位置(保存修改)
///
- /// 是否成功确认修改
- public bool ConfirmEditPoint()
+ /// 是否成功更新
+ public bool UpdatePointPosition()
{
try
{
@@ -1541,6 +1617,9 @@ namespace NavisworksTransport
// 触发路径点列表更新事件
RaisePathPointsListUpdated(CurrentRoute, "路径点修改完成");
+ // 保存到数据库
+ SavePathToDatabase(CurrentRoute);
+
RaiseStatusChanged($"路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
LogManager.Info($"路径点修改完成: {pointToUpdate.Name}");
@@ -1548,7 +1627,7 @@ namespace NavisworksTransport
}
catch (Exception ex)
{
- RaiseErrorOccurred($"确认修改路径点失败: {ex.Message}", ex);
+ RaiseErrorOccurred($"确认修改路径点失败: {ex.Message}");
return false;
}
}
@@ -1852,10 +1931,10 @@ namespace NavisworksTransport
}
///
- /// 确认预览点,将其添加到当前路径中
+ /// 将预览点添加为正式路径点
///
/// 添加的路径点,如果失败返回null
- public PathPoint ConfirmPreviewPoint()
+ public PathPoint ConvertPreviewToPathPoint()
{
if (!_isPreviewMode || _previewPoint == null)
{
@@ -1913,11 +1992,14 @@ namespace NavisworksTransport
// 触发路径列表更新事件
RaisePathPointsListUpdated(CurrentRoute, "确认添加预览点");
+ // 保存到数据库
+ SavePathToDatabase(CurrentRoute);
+
return confirmPoint;
}
catch (Exception ex)
{
- RaiseErrorOccurred($"确认预览点失败: {ex.Message}", ex);
+ RaiseErrorOccurred($"确认预览点失败: {ex.Message}");
return null;
}
}
@@ -3482,6 +3564,166 @@ namespace NavisworksTransport
#endregion
+ #region 路径分析方法
+
+ ///
+ /// 获取所有路径(供分析使用)
+ ///
+ public List GetAllRoutes()
+ {
+ try
+ {
+ // 直接返回内存中的路径列表
+ // 因为所有路径操作都已同步到数据库,内存列表就是当前的完整列表
+ return _routes ?? new List();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"获取所有路径失败: {ex.Message}", ex);
+ return new List();
+ }
+ }
+
+ ///
+ /// 分析多条路径并进行对比
+ ///
+ /// 要分析的路径ID列表
+ /// 分析策略
+ /// 对比结果
+ public PathComparisonResult AnalyzePathsAndCompare(List routeIds, string strategy)
+ {
+ try
+ {
+ if (_analysisService == null)
+ {
+ LogManager.Error("路径分析服务未初始化");
+ return null;
+ }
+
+ // 获取要分析的路径
+ var routesToAnalyze = _routes?.Where(r => routeIds.Contains(r.Id)).ToList();
+ if (routesToAnalyze == null || routesToAnalyze.Count == 0)
+ {
+ LogManager.Warning("未找到要分析的路径");
+ return null;
+ }
+
+ // 执行分析和对比
+ var result = _analysisService.CompareRoutes(routesToAnalyze, strategy);
+
+ return result;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"路径分析失败: {ex.Message}", ex);
+ return null;
+ }
+ }
+
+ ///
+ /// 从数据库加载历史路径到内存
+ ///
+ private void LoadHistoricalRoutesFromDatabase()
+ {
+ try
+ {
+ if (_pathDatabase == null)
+ {
+ LogManager.Info("数据库未初始化,跳过加载历史路径");
+ return;
+ }
+
+ var historicalRoutes = _pathDatabase.GetAllPathRoutes();
+ if (historicalRoutes != null && historicalRoutes.Count > 0)
+ {
+ // 使用HashSet记录已存在的路径ID,避免重复
+ var existingIds = new HashSet(_routes.Select(r => r.Id));
+ int loadedCount = 0;
+
+ // 加载历史路径(跳过已存在的)
+ foreach (var route in historicalRoutes)
+ {
+ if (!existingIds.Contains(route.Id))
+ {
+ _routes.Add(route);
+ loadedCount++;
+ LogManager.Info($"加载历史路径: {route.Name}, ID={route.Id}, 长度={route.TotalLength:F2}米");
+ }
+ }
+
+ if (loadedCount > 0)
+ {
+ LogManager.Info($"成功从数据库加载 {loadedCount} 条历史路径(总计 {historicalRoutes.Count} 条)");
+ }
+ else
+ {
+ LogManager.Info($"数据库中的 {historicalRoutes.Count} 条路径已全部在内存中");
+ }
+
+ // 如果当前没有选中的路径,且路径列表不为空,选择第一条
+ if ((_currentRoute == null || string.IsNullOrEmpty(_currentRoute.Name) || _currentRoute.Name == "默认路径")
+ && _routes.Count > 0)
+ {
+ _currentRoute = _routes[0];
+ LogManager.Info($"设置当前路径为: {_currentRoute.Name}");
+ }
+
+ // 历史路径加载完成后,触发RouteGenerated事件通知UI刷新
+ // 使用特殊的生成方法标记这是数据库加载
+ foreach (var route in _routes)
+ {
+ RaiseRouteGenerated(route, RouteGenerationMethod.DatabaseLoad);
+ }
+ LogManager.Info($"已触发{_routes.Count}个RouteGenerated事件,通知UI刷新历史路径");
+ }
+ else
+ {
+ LogManager.Info("数据库中没有历史路径记录");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"加载历史路径失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 保存路径时同时保存到数据库
+ ///
+ private void SavePathToDatabase(PathRoute route)
+ {
+ try
+ {
+ if (_pathDatabase != null && route != null)
+ {
+ _pathDatabase.SavePathRoute(route);
+ LogManager.Info($"路径已保存到数据库: {route.Name}");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"保存路径到数据库失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 获取Instance单例(为兼容现有代码)
+ ///
+ public static PathPlanningManager Instance
+ {
+ get
+ {
+ if (_activePathManager == null)
+ {
+ LogManager.Warning("PathPlanningManager未初始化,创建新实例");
+ _activePathManager = new PathPlanningManager();
+ }
+ return _activePathManager;
+ }
+ }
+
+ #endregion
+
#region 静态方法
///
diff --git a/src/Core/PathPlanningManagerEventArgs.cs b/src/Core/PathPlanningManagerEventArgs.cs
index 373eb0b..8907fed 100644
--- a/src/Core/PathPlanningManagerEventArgs.cs
+++ b/src/Core/PathPlanningManagerEventArgs.cs
@@ -346,7 +346,12 @@ namespace NavisworksTransport.Core
///
/// 优化
///
- Optimization
+ Optimization,
+
+ ///
+ /// 从数据库加载
+ ///
+ DatabaseLoad
}
#endregion
diff --git a/src/Core/PathPlanningModels.cs b/src/Core/PathPlanningModels.cs
index 7afe631..0c2ca47 100644
--- a/src/Core/PathPlanningModels.cs
+++ b/src/Core/PathPlanningModels.cs
@@ -408,6 +408,27 @@ namespace NavisworksTransport
///
public double VehicleHeight { get; set; } = 2.0;
+ // 数据库分析相关属性
+ ///
+ /// 碰撞数量(从数据库加载)
+ ///
+ public int? CollisionCount { get; set; }
+
+ ///
+ /// 安全评分(从数据库加载)
+ ///
+ public double? SafetyScore { get; set; }
+
+ ///
+ /// 效率评分(从数据库加载)
+ ///
+ public double? EfficiencyScore { get; set; }
+
+ ///
+ /// 综合评分(从数据库加载)
+ ///
+ public double? OverallScore { get; set; }
+
///
/// 构造函数
///
diff --git a/src/UI/WPF/ViewModels/PathAnalysisViewModel.cs b/src/UI/WPF/ViewModels/PathAnalysisViewModel.cs
index d4e69a2..2a01fe0 100644
--- a/src/UI/WPF/ViewModels/PathAnalysisViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathAnalysisViewModel.cs
@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
-using NavisworksTransport.Utils;
+using System.Windows.Input;
namespace NavisworksTransport.UI.WPF.ViewModels
{
@@ -31,7 +31,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public ObservableCollection AvailablePaths { get; set; }
///
- /// 选中的路径列表(用于对比分析)
+ /// 选中的路径列表(用于对比分析和结果显示)
///
public ObservableCollection SelectedPaths { get; set; }
@@ -99,6 +99,26 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
public ObservableCollection BottleneckLocations { get; set; }
+ ///
+ /// 开始分析命令
+ ///
+ public ICommand StartAnalysisCommand { get; private set; }
+
+ ///
+ /// 全选命令
+ ///
+ public ICommand SelectAllCommand { get; private set; }
+
+ ///
+ /// 清空选择命令
+ ///
+ public ICommand ClearSelectionCommand { get; private set; }
+
+ ///
+ /// 导出报告命令
+ ///
+ public ICommand ExportReportCommand { get; private set; }
+
#endregion
#region 构造函数
@@ -111,7 +131,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
InitializeCollections();
- LoadDemoData();
+ InitializeCommands();
+
+ // 确保PathPlanningManager的数据库已初始化
+ EnsurePathDatabaseInitialized();
+
+ LoadPathData();
LogManager.Info("PathAnalysisViewModel初始化完成");
}
catch (Exception ex)
@@ -120,6 +145,43 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 初始化命令
+ ///
+ private void InitializeCommands()
+ {
+ StartAnalysisCommand = new RelayCommand(ExecuteStartAnalysis, CanExecuteStartAnalysis);
+ SelectAllCommand = new RelayCommand(SelectAll);
+ ClearSelectionCommand = new RelayCommand(ClearSelection);
+ ExportReportCommand = new RelayCommand(ExportReport, CanExportReport);
+ }
+
+ private bool CanExecuteStartAnalysis()
+ {
+ return !IsAnalyzing && AvailablePaths.Any(p => p.IsSelected);
+ }
+
+ private void ExecuteStartAnalysis()
+ {
+ PerformAnalysis();
+ }
+
+ ///
+ /// 确保PathPlanningManager的路径数据库已初始化
+ ///
+ private void EnsurePathDatabaseInitialized()
+ {
+ try
+ {
+ var manager = PathPlanningManager.Instance;
+ manager.EnsureDatabaseInitialized();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"确保数据库初始化失败: {ex.Message}", ex);
+ }
+ }
+
#endregion
#region 初始化方法
@@ -136,163 +198,109 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
///
- /// 加载演示数据
+ /// 加载真实路径数据
///
- private void LoadDemoData()
+ private void LoadPathData()
{
try
{
- // 加载演示路径数据
- var demoPath1 = new PathAnalysisItem
+ // 从PathPlanningManager获取所有路径(包括数据库中的历史路径)
+ var allRoutes = PathPlanningManager.Instance.GetAllRoutes();
+
+ if (allRoutes == null || allRoutes.Count == 0)
{
- Name = "自动路径_20250103_141523",
- Type = "自动生成",
- Length = 98.5,
- EstimatedTime = 147,
- CollisionCount = 2,
- AffectedObjects = 5,
- AverageSpeed = 0.67,
- Score = 82,
- IsSelected = true
- };
+ LogManager.Info("当前没有可用的路径数据");
+ AnalysisStatus = "暂无可用路径数据,请先规划路径";
+ return;
+ }
- var demoPath2 = new PathAnalysisItem
+ // 清空现有数据
+ AvailablePaths.Clear();
+
+ // 将路径数据转换为UI显示项
+ foreach (var route in allRoutes)
{
- Name = "手动路径_20250103_102045",
- Type = "手动规划",
- Length = 125.3,
- EstimatedTime = 188,
- CollisionCount = 0,
- AffectedObjects = 3,
- AverageSpeed = 0.67,
- Score = 95,
- IsSelected = true
- };
+ var item = new PathAnalysisItem
+ {
+ RouteId = route.Id,
+ Name = route.Name,
+ Type = route.CreatedTime != default(DateTime) ? "历史路径" : "当前会话",
+ Length = Math.Round(route.TotalLength, 2),
+ EstimatedTime = (int)route.EstimatedTime,
+ IsSelected = false
+ };
- var demoPath3 = new PathAnalysisItem
- {
- Name = "自动路径_20250103_093012",
- Type = "自动生成",
- Length = 105.8,
- EstimatedTime = 159,
- CollisionCount = 4,
- AffectedObjects = 8,
- AverageSpeed = 0.67,
- Score = 68,
- IsSelected = false
- };
+ // 如果数据库中有分析结果,加载相关数据
+ if (route.CollisionCount.HasValue)
+ {
+ item.CollisionCount = route.CollisionCount.Value;
+ item.Score = (int)route.OverallScore.GetValueOrDefault(0);
+ item.AffectedObjects = route.CollisionCount.Value; // 简化:使用碰撞数作为受影响对象数
+ }
+ else
+ {
+ item.CollisionCount = 0;
+ item.Score = 0;
+ item.AffectedObjects = 0;
+ }
- var demoPath4 = new PathAnalysisItem
- {
- Name = "手动路径_20250102_160230",
- Type = "手动规划",
- Length = 132.6,
- EstimatedTime = 199,
- CollisionCount = 1,
- AffectedObjects = 4,
- AverageSpeed = 0.67,
- Score = 78,
- IsSelected = false
- };
+ // 计算平均速度
+ if (route.EstimatedTime > 0)
+ {
+ item.AverageSpeed = Math.Round(route.TotalLength / route.EstimatedTime, 2);
+ }
- AvailablePaths.Add(demoPath1);
- AvailablePaths.Add(demoPath2);
- AvailablePaths.Add(demoPath3);
- AvailablePaths.Add(demoPath4);
+ // 监听选择状态变化,以刷新命令状态
+ item.PropertyChanged += (s, e) =>
+ {
+ if (e.PropertyName == nameof(PathAnalysisItem.IsSelected))
+ {
+ CommandManager.InvalidateRequerySuggested();
+ }
+ };
- // 添加选中的路径到对比列表
- SelectedPaths.Add(demoPath1);
- SelectedPaths.Add(demoPath2);
+ AvailablePaths.Add(item);
+ }
- // 加载优化建议
- LoadOptimizationSuggestions();
-
- // 加载瓶颈位置
- LoadBottleneckLocations();
-
- // 计算推荐路径
- UpdateRecommendedPath();
-
- LogManager.Info("路径分析演示数据加载完成");
+ LogManager.Info($"加载路径数据完成:共{AvailablePaths.Count}条路径(包括历史路径)");
+ AnalysisStatus = $"已加载 {AvailablePaths.Count} 条路径,请选择要分析的路径";
}
catch (Exception ex)
{
- LogManager.Error($"加载路径分析演示数据失败: {ex.Message}", ex);
+ LogManager.Error($"加载真实路径数据失败: {ex.Message}", ex);
+ AnalysisStatus = "加载路径数据失败";
}
}
- ///
- /// 加载优化建议
- ///
- private void LoadOptimizationSuggestions()
- {
- OptimizationSuggestions.Add(new OptimizationSuggestion
- {
- Title = "在电梯口设置等待区",
- Description = "避免多路径在电梯处产生拥堵,提高通行效率",
- Priority = "高",
- Status = "建议采纳"
- });
-
- OptimizationSuggestions.Add(new OptimizationSuggestion
- {
- Title = "优化转弯半径至2.0米",
- Description = "当前1.5米转弯半径过小,增大至2.0米可提高安全性",
- Priority = "高",
- Status = "建议采纳"
- });
-
- OptimizationSuggestions.Add(new OptimizationSuggestion
- {
- Title = "调整作业时间窗口",
- Description = "建议在09:00-10:00执行,避开人员高峰期",
- Priority = "中",
- Status = "可选"
- });
-
- OptimizationSuggestions.Add(new OptimizationSuggestion
- {
- Title = "考虑分批运输",
- Description = "单次运输量过大时,可分2批执行降低碰撞风险",
- Priority = "中",
- Status = "可选"
- });
- }
-
- ///
- /// 加载瓶颈位置
- ///
- private void LoadBottleneckLocations()
- {
- BottleneckLocations.Add(new BottleneckLocation
- {
- Name = "电梯口",
- AffectedPaths = 2,
- Severity = "高风险",
- Suggestion = "设置等待区"
- });
-
- BottleneckLocations.Add(new BottleneckLocation
- {
- Name = "通道转角",
- AffectedPaths = 2,
- Severity = "中等风险",
- Suggestion = "优化转弯半径"
- });
-
- BottleneckLocations.Add(new BottleneckLocation
- {
- Name = "装卸区入口",
- AffectedPaths = 1,
- Severity = "低风险",
- Suggestion = "无需调整"
- });
- }
#endregion
#region 业务逻辑方法
+ ///
+ /// 全选所有路径
+ ///
+ private void SelectAll()
+ {
+ foreach (var path in AvailablePaths)
+ {
+ path.IsSelected = true;
+ }
+ CommandManager.InvalidateRequerySuggested();
+ }
+
+ ///
+ /// 清空所有选择
+ ///
+ private void ClearSelection()
+ {
+ foreach (var path in AvailablePaths)
+ {
+ path.IsSelected = false;
+ }
+ CommandManager.InvalidateRequerySuggested();
+ }
+
///
/// 更新推荐路径
///
@@ -348,15 +356,41 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsAnalyzing = true;
AnalysisStatus = "正在分析...";
- // 模拟分析过程
- System.Threading.Tasks.Task.Delay(2000).ContinueWith(t =>
+ // 获取选中的路径
+ var selectedRoutes = AvailablePaths.Where(p => p.IsSelected).ToList();
+ if (selectedRoutes.Count == 0)
{
+ AnalysisStatus = "请选择要分析的路径";
IsAnalyzing = false;
- UpdateRecommendedPath();
- AnalysisStatus = "分析完成";
- });
+ return;
+ }
- LogManager.Info("开始执行路径分析");
+ // 更新选中路径列表用于UI显示
+ SelectedPaths.Clear();
+ foreach (var route in selectedRoutes)
+ {
+ SelectedPaths.Add(route);
+ }
+
+ // 执行真实的路径分析
+ var result = PathPlanningManager.Instance.AnalyzePathsAndCompare(
+ selectedRoutes.Select(p => p.RouteId).ToList(),
+ AnalysisStrategy
+ );
+
+ if (result != null)
+ {
+ // 更新UI数据
+ UpdateAnalysisResults(result);
+ AnalysisStatus = "分析完成";
+ LogManager.Info($"路径分析完成,最佳路径: {result.BestRouteName}");
+ }
+ else
+ {
+ AnalysisStatus = "分析失败";
+ }
+
+ IsAnalyzing = false;
}
catch (Exception ex)
{
@@ -366,6 +400,143 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 导出报告
+ ///
+ private void ExportReport()
+ {
+ try
+ {
+ if (RecommendedPath == null || SelectedPaths.Count == 0)
+ {
+ LogManager.Warning("没有分析结果可以导出");
+ return;
+ }
+
+ // 生成报告文件名
+ var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
+ var fileName = $"路径分析报告_{timestamp}.txt";
+ var filePath = System.IO.Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
+ fileName
+ );
+
+ // 生成报告内容
+ var report = new System.Text.StringBuilder();
+ report.AppendLine("====================================");
+ report.AppendLine(" 物流路径分析报告");
+ report.AppendLine("====================================");
+ report.AppendLine();
+ report.AppendLine($"生成时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
+ report.AppendLine($"分析策略:{AnalysisStrategy}");
+ report.AppendLine();
+
+ report.AppendLine("【分析路径列表】");
+ report.AppendLine("----------------------------------------");
+ foreach (var path in SelectedPaths)
+ {
+ report.AppendLine($"路径名称:{path.Name}");
+ report.AppendLine($" - 长度:{path.Length:F2} 米");
+ report.AppendLine($" - 预估时间:{path.EstimatedTime} 秒");
+ report.AppendLine($" - 碰撞数量:{path.CollisionCount}");
+ report.AppendLine($" - 综合评分:{path.Score}");
+ report.AppendLine();
+ }
+
+ report.AppendLine("【推荐路径】");
+ report.AppendLine("----------------------------------------");
+ if (RecommendedPath != null)
+ {
+ report.AppendLine($"推荐路径:{RecommendedPath.Name}");
+ report.AppendLine($"推荐理由:基于{AnalysisStrategy}策略,该路径具有最优综合评分");
+ report.AppendLine();
+ }
+
+ report.AppendLine("【优化建议】");
+ report.AppendLine("----------------------------------------");
+ if (OptimizationSuggestions.Count > 0)
+ {
+ int index = 1;
+ foreach (var suggestion in OptimizationSuggestions)
+ {
+ report.AppendLine($"{index}. {suggestion.Title}");
+ index++;
+ }
+ }
+ else
+ {
+ report.AppendLine("暂无优化建议");
+ }
+
+ // 写入文件
+ System.IO.File.WriteAllText(filePath, report.ToString(), System.Text.Encoding.UTF8);
+
+ AnalysisStatus = $"报告已导出到:{filePath}";
+ LogManager.Info($"分析报告已导出:{filePath}");
+
+ // 打开文件所在目录并选中文件
+ System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{filePath}\"");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"导出报告失败:{ex.Message}", ex);
+ AnalysisStatus = "导出报告失败";
+ }
+ }
+
+ ///
+ /// 判断是否可以导出报告
+ ///
+ private bool CanExportReport()
+ {
+ return SelectedPaths != null && SelectedPaths.Count > 0 && RecommendedPath != null;
+ }
+
+ ///
+ /// 更新分析结果到UI
+ ///
+ private void UpdateAnalysisResults(PathComparisonResult result)
+ {
+ // 更新路径的碰撞和评分数据
+ foreach (var analysis in result.Analyses)
+ {
+ // 更新AvailablePaths中的数据
+ var pathItem = AvailablePaths.FirstOrDefault(p => p.RouteId == analysis.RouteId);
+ if (pathItem != null)
+ {
+ pathItem.CollisionCount = analysis.CollisionCount;
+ pathItem.Score = (int)analysis.OverallScore;
+ pathItem.AverageSpeed = pathItem.Length / pathItem.EstimatedTime;
+ pathItem.AffectedObjects = analysis.CollisionCount; // 简化:使用碰撞数作为受影响对象数
+ }
+
+ // 同时更新SelectedPaths中的数据
+ var selectedItem = SelectedPaths.FirstOrDefault(p => p.RouteId == analysis.RouteId);
+ if (selectedItem != null)
+ {
+ selectedItem.CollisionCount = analysis.CollisionCount;
+ selectedItem.Score = (int)analysis.OverallScore;
+ selectedItem.AverageSpeed = selectedItem.Length / selectedItem.EstimatedTime;
+ selectedItem.AffectedObjects = analysis.CollisionCount;
+ }
+ }
+
+ // 设置推荐路径
+ RecommendedPath = SelectedPaths.FirstOrDefault(p => p.RouteId == result.BestRouteId);
+
+ // 更新优化建议
+ OptimizationSuggestions.Clear();
+ foreach (var suggestion in result.Suggestions)
+ {
+ OptimizationSuggestions.Add(new OptimizationSuggestion
+ {
+ Title = suggestion,
+ Priority = "中",
+ Status = "待处理"
+ });
+ }
+ }
+
#endregion
#region INotifyPropertyChanged实现
@@ -385,8 +556,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
/// 路径分析项目
///
- public class PathAnalysisItem
+ public class PathAnalysisItem : INotifyPropertyChanged
{
+ private bool _isSelected;
+ private int _collisionCount;
+ private int _affectedObjects;
+ private double _averageSpeed;
+ private int _score;
+
+ /// 路径ID
+ public string RouteId { get; set; }
+
/// 路径名称
public string Name { get; set; }
@@ -400,19 +580,66 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public int EstimatedTime { get; set; }
/// 碰撞次数
- public int CollisionCount { get; set; }
+ public int CollisionCount
+ {
+ get => _collisionCount;
+ set
+ {
+ _collisionCount = value;
+ OnPropertyChanged();
+ }
+ }
/// 受影响对象数
- public int AffectedObjects { get; set; }
+ public int AffectedObjects
+ {
+ get => _affectedObjects;
+ set
+ {
+ _affectedObjects = value;
+ OnPropertyChanged();
+ }
+ }
/// 平均速度(m/s)
- public double AverageSpeed { get; set; }
+ public double AverageSpeed
+ {
+ get => _averageSpeed;
+ set
+ {
+ _averageSpeed = value;
+ OnPropertyChanged();
+ }
+ }
/// 综合评分
- public int Score { get; set; }
+ public int Score
+ {
+ get => _score;
+ set
+ {
+ _score = value;
+ OnPropertyChanged();
+ }
+ }
/// 是否被选中用于分析
- public bool IsSelected { get; set; }
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set
+ {
+ _isSelected = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
}
///
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index b6955a8..60a2aff 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -1174,7 +1174,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (isEditingPoint)
{
// 修改路径点模式 - 尝试确认修改
- success = _pathPlanningManager.ConfirmEditPoint();
+ success = _pathPlanningManager.UpdatePointPosition();
if (success)
{
operationMessage = "路径点修改已确认";
@@ -1195,7 +1195,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (wasInPreviewMode)
{
// 预览模式 - 先确认预览点,然后立即完成编辑
- var confirmedPoint = _pathPlanningManager.ConfirmPreviewPoint();
+ var confirmedPoint = _pathPlanningManager.ConvertPreviewToPathPoint();
if (confirmedPoint != null)
{
LogManager.Info($"[UI-预览模式] 预览点已确认: {confirmedPoint.Name},现在完成编辑");
@@ -1344,7 +1344,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"已从Core数据删除路径点: {corePoint.Name}");
// 调用PathPlanningManager的3D删除方法
- _pathPlanningManager.RemovePathPointFrom3D(corePoint);
+ _pathPlanningManager.RemovePathPoint(corePoint);
// 触发UI同步更新事件
_pathPlanningManager.RaisePathPointsListUpdated(coreRoute, "删除路径点并重新分配类型");
@@ -2209,7 +2209,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_pathPlanningManager.ErrorOccurred += OnPathPlanningError;
LogManager.Info("*** PathEditingViewModel已成功订阅PathPlanningManager事件,包括RouteGenerated和ErrorOccurred ***");
-
+
// 验证事件订阅是否成功
var routeGeneratedField = _pathPlanningManager.GetType().GetEvent("RouteGenerated");
if (routeGeneratedField != null)
@@ -2220,6 +2220,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Error("*** RouteGenerated事件不存在!!! ***");
}
+
+ // 初始化加载现有路径(包括从数据库加载的历史路径)
+ RefreshPathRoutes();
+ LogManager.Info("*** 已从PathPlanningManager加载现有路径到UI ***");
}
catch (Exception ex)
{
@@ -2604,6 +2608,49 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 手工路径生成(如果需要特殊处理)
LogManager.Info($"手工路径生成完成: {e.Route.Name}");
}
+ else if (e.GenerationMethod == RouteGenerationMethod.DatabaseLoad)
+ {
+ // 从数据库加载的历史路径
+ LogManager.Info($"*** 开始处理数据库加载路径: {e.Route.Name} ***");
+
+ // 创建对应的 WPF ViewModel
+ var dbPathViewModel = new PathRouteViewModel
+ {
+ Name = e.Route.Name,
+ Description = e.Route.Description,
+ IsActive = false // 历史路径默认不激活
+ };
+
+ // 转换路径点
+ foreach (var corePoint in e.Route.Points)
+ {
+ var wpfPoint = new PathPointViewModel
+ {
+ Id = corePoint.Id,
+ Name = corePoint.Name,
+ X = corePoint.X,
+ Y = corePoint.Y,
+ Z = corePoint.Z,
+ Type = corePoint.Type
+ };
+ dbPathViewModel.Points.Add(wpfPoint);
+ }
+
+ LogManager.Info($"*** 已创建PathRouteViewModel(数据库路径),包含 {dbPathViewModel.Points.Count} 个点 ***");
+
+ // 检查是否已存在同名路径,避免重复添加
+ var existingPath = PathRoutes.FirstOrDefault(p => p.Name == e.Route.Name);
+ if (existingPath == null)
+ {
+ // 添加到 UI 列表
+ PathRoutes.Add(dbPathViewModel);
+ LogManager.Info($"*** 数据库路径已添加到UI列表: {e.Route.Name},当前PathRoutes.Count = {PathRoutes.Count} ***");
+ }
+ else
+ {
+ LogManager.Info($"*** 数据库路径已存在,跳过: {e.Route.Name} ***");
+ }
+ }
}, "处理路径生成事件");
}
catch (Exception ex)
diff --git a/src/UI/WPF/ViewModels/TimeTagViewModel.cs b/src/UI/WPF/ViewModels/TimeTagViewModel.cs
index 4b295e6..dd85090 100644
--- a/src/UI/WPF/ViewModels/TimeTagViewModel.cs
+++ b/src/UI/WPF/ViewModels/TimeTagViewModel.cs
@@ -161,7 +161,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (route == null)
{
LogManager.Info("路径为空,加载演示数据");
- LoadDemoData();
return;
}
@@ -173,7 +172,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (!result.IsSuccessful)
{
LogManager.Warning($"时标计算失败: {result.ErrorMessage},回退到演示数据");
- LoadDemoData();
return;
}
@@ -211,8 +209,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"加载路径时间数据失败: {ex.Message}", ex);
- // 加载失败时回退到演示数据
- LoadDemoData();
}
}
@@ -248,48 +244,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
- ///
- /// 加载演示数据
- ///
- private void LoadDemoData()
- {
- try
- {
- // 加载时间分段演示数据
- TimeSegments.Add(new TimeSegmentItem
- {
- Index = 1,
- Length = 9.70,
- Speed = 0.80,
- Duration = 12.1,
- CumulativeTime = 12.1,
- Remarks = "通道限速"
- });
-
- TimeSegments.Add(new TimeSegmentItem
- {
- Index = 2,
- Length = 6.40,
- Speed = 0.70,
- Duration = 10.7,
- CumulativeTime = 22.8,
- Remarks = "拐角减速"
- });
-
- // 移除硬编码的等待时间,使用真实的路径数据
-
- // 更新总时长并生成时间轴预览数据
- TotalDuration = 22.8; // 只计算实际路径时间
- GenerateTimelineItems();
-
- LogManager.Info("时间标签演示数据加载完成");
- }
- catch (Exception ex)
- {
- LogManager.Error($"加载时间标签演示数据失败: {ex.Message}", ex);
- }
- }
-
#endregion
#region 业务逻辑方法
diff --git a/src/UI/WPF/Views/PathAnalysisDialog.xaml b/src/UI/WPF/Views/PathAnalysisDialog.xaml
index 962cc8e..796e00a 100644
--- a/src/UI/WPF/Views/PathAnalysisDialog.xaml
+++ b/src/UI/WPF/Views/PathAnalysisDialog.xaml
@@ -118,82 +118,59 @@ NavisworksTransport 路径规划分析对话框 - 采用与主界面一致的Nav
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
+
@@ -204,103 +181,50 @@ NavisworksTransport 路径规划分析对话框 - 采用与主界面一致的Nav
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -310,69 +234,25 @@ NavisworksTransport 路径规划分析对话框 - 采用与主界面一致的Nav
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs b/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs
index 7313f27..aeefd31 100644
--- a/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs
+++ b/src/UI/WPF/Views/PathAnalysisDialog.xaml.cs
@@ -1,5 +1,7 @@
using System;
using System.Windows;
+using System.Windows.Controls;
+using NavisworksTransport.UI.WPF.ViewModels;
using NavisworksTransport.Utils;
namespace NavisworksTransport.UI.WPF.Views
@@ -18,39 +20,36 @@ namespace NavisworksTransport.UI.WPF.Views
try
{
InitializeComponent();
- LogManager.Info("PathAnalysisDialog初始化完成");
-
+
+ // 绑定ViewModel
+ DataContext = new ViewModels.PathAnalysisViewModel();
+
+ LogManager.Info("PathAnalysisDialog初始化完成,已绑定PathAnalysisViewModel");
+
// 设置窗口标题包含当前时间
Title = $"路径规划分析 - 多路径对比 [{DateTime.Now:MM-dd HH:mm}]";
-
- // 加载演示数据(后续可以替换为实际数据绑定)
- LoadDemoData();
}
catch (Exception ex)
{
LogManager.Error($"初始化PathAnalysisDialog失败: {ex.Message}", ex);
}
}
-
+
///
- /// 加载演示数据到UI控件
- /// 这里提供静态演示数据,实际使用时应该绑定到ViewModel
+ /// 分析策略 RadioButton 选中事件
///
- private void LoadDemoData()
+ private void StrategyRadioButton_Checked(object sender, RoutedEventArgs e)
{
- try
+ if (sender is RadioButton rb && rb.Tag is string strategy)
{
- // 这里可以设置一些初始化的演示数据
- // 目前UI已经包含了静态的演示数据,后续可以通过DataContext绑定动态数据
-
- LogManager.Info("路径分析演示数据加载完成");
- }
- catch (Exception ex)
- {
- LogManager.Error($"加载路径分析演示数据失败: {ex.Message}", ex);
+ if (DataContext is PathAnalysisViewModel viewModel)
+ {
+ viewModel.AnalysisStrategy = strategy;
+ LogManager.Info($"用户切换分析策略: {strategy}");
+ }
}
}
-
+
///
/// 关闭按钮点击事件
///