268 lines
9.8 KiB
C#
268 lines
9.8 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// 路径分析服务 - 简化版
|
||
/// 负责路径碰撞分析和评分计算
|
||
/// </summary>
|
||
public class PathAnalysisService
|
||
{
|
||
private readonly PathDatabase _database;
|
||
|
||
public PathAnalysisService(PathDatabase database)
|
||
{
|
||
_database = database ?? throw new ArgumentNullException(nameof(database));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分析单条路径
|
||
/// </summary>
|
||
/// <param name="route">路径对象</param>
|
||
/// <param name="strategy">分析策略:安全优先/效率优先</param>
|
||
/// <returns>分析结果</returns>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对比多条路径,返回最佳路径和建议
|
||
/// </summary>
|
||
/// <param name="routes">路径列表</param>
|
||
/// <param name="strategy">分析策略</param>
|
||
/// <returns>对比结果</returns>
|
||
public PathComparisonResult CompareRoutes(List<PathRoute> routes, string strategy = "安全优先")
|
||
{
|
||
if (routes == null || routes.Count == 0)
|
||
throw new ArgumentException("路径列表不能为空");
|
||
|
||
var result = new PathComparisonResult
|
||
{
|
||
Strategy = strategy,
|
||
Analyses = new List<PathAnalysisResult>()
|
||
};
|
||
|
||
// 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行碰撞检测
|
||
/// 注意:实际的碰撞检测需要在路径动画执行时进行
|
||
/// 这里优先从数据库加载已有的碰撞结果
|
||
/// </summary>
|
||
private List<CollisionResult> DetectCollisions(PathRoute route)
|
||
{
|
||
try
|
||
{
|
||
// 先尝试从数据库获取已有的碰撞数据
|
||
var existingCount = _database.GetCollisionCount(route.Id);
|
||
|
||
if (existingCount > 0)
|
||
{
|
||
LogManager.Info($"从数据库加载碰撞数据: {route.Name}, 碰撞数={existingCount}");
|
||
// 返回空列表,碰撞数量已经从数据库获取
|
||
return new List<CollisionResult>();
|
||
}
|
||
|
||
// 如果数据库没有碰撞数据,返回空列表
|
||
// TODO: 未来可以在这里触发实际的碰撞检测
|
||
LogManager.Info($"路径{route.Name}暂无碰撞数据");
|
||
return new List<CollisionResult>();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"获取碰撞数据失败: {route.Name}, {ex.Message}", ex);
|
||
return new List<CollisionResult>();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算安全评分(100分制)
|
||
/// 碰撞越少分数越高
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算效率评分(100分制)
|
||
/// 路径越短、速度越快分数越高
|
||
/// </summary>
|
||
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));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成优化建议(基于简单规则)
|
||
/// </summary>
|
||
private List<string> GenerateSuggestions(List<PathAnalysisResult> analyses,
|
||
List<PathRoute> routes, string strategy)
|
||
{
|
||
var suggestions = new List<string>();
|
||
|
||
// 规则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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 路径对比结果
|
||
/// </summary>
|
||
public class PathComparisonResult
|
||
{
|
||
/// <summary>最佳路径ID</summary>
|
||
public string BestRouteId { get; set; }
|
||
|
||
/// <summary>最佳路径名称</summary>
|
||
public string BestRouteName { get; set; }
|
||
|
||
/// <summary>分析策略</summary>
|
||
public string Strategy { get; set; }
|
||
|
||
/// <summary>所有路径的分析结果</summary>
|
||
public List<PathAnalysisResult> Analyses { get; set; }
|
||
|
||
/// <summary>优化建议列表</summary>
|
||
public List<string> Suggestions { get; set; }
|
||
}
|
||
}
|