# 路径分析功能深化设计方案

> 版本: 1.0  
> 日期: 2026-02-14  
> 适用范围: 大型装置内精密组件物流仿真

---

## 一、项目背景与目标

### 1.1 背景

- **应用场景**: 大型装置内进行精密组件物流仿真
- **核心目标**: 确保组件能安全到达安装位置（终点）
- **最高优先级**: 减少碰撞（安全性）
- **次要优先级**: 路径复杂度/效率（时间成本）
- **不涉及**: 经济成本

### 1.2 设计原则

1. **实用优先**: 指标不在于多，而在于有用
2. **聚焦终点**: 核心目标是"找出到同一安装位置的最佳路径"
3. **可解释性**: 每个指标和评分都要有明确的物理意义
4. **可操作性**: 建议要具体，告诉用户"怎么做"

---

## 二、策略模式

### 2.1 三种分析策略

| 策略 | 权重配置（安全/效率/转弯/直达） | 适用场景 |
|-----|--------------------------------|---------|
| **安全优先** | 50% / 30% / 10% / 10% | 精密/易损组件，首次运输 |
| **效率优先** | 20% / 50% / 15% / 15% | 紧急任务，多次往返 |
| **平衡模式** | 35% / 35% / 15% / 15% | 通用场景（默认） |

### 2.2 权重配置代码

```csharp
public static class AnalysisStrategies
{
    public const string SafetyFirst = "安全优先";
    public const string EfficiencyFirst = "效率优先";
    public const string Balanced = "平衡模式";
    
    // 权重顺序: 安全、效率、转弯、直达
    public static readonly Dictionary<string, double[]> Weights = new Dictionary<string, double[]>
    {
        [SafetyFirst] = new[] { 0.50, 0.30, 0.10, 0.10 },
        [EfficiencyFirst] = new[] { 0.20, 0.50, 0.15, 0.15 },
        [Balanced] = new[] { 0.35, 0.35, 0.15, 0.15 }
    };
}
```

---

## 三、指标体系（4维度）

### 3.1 安全性（碰撞风险指数）- 权重最高

```csharp
// 基础碰撞分（100分制）
// 0次=100分, 1次=80分, 2次=60分, 3次=40分, 4次+=20分
BaseScore = Max(0, 100 - CollisionCount * 20);

// 碰撞热点扣分（3米范围内≥2次碰撞视为热点）
// 每个热点扣15分
HotspotPenalty = HotspotCount * 15;

// 最终安全分
SafetyScore = Max(0, BaseScore - HotspotPenalty);
```

### 3.2 效率（通行效率指数）

```csharp
// 速度分（以1.0 m/s为理想速度）
ActualSpeed = TotalLength / EstimatedTime;
SpeedScore = Min(100, ActualSpeed / 1.0 * 100);

// 时间效率（与组内最短时间的比值）
TimeEfficiency = GroupMinTime / EstimatedTime * 100;

// 综合效率分（速度70% + 时间效率30%）
EfficiencyScore = SpeedScore * 0.7 + TimeEfficiency * 0.3;
```

### 3.3 可行性（转弯难度系数）

```csharp
// 从 PathRoute.Edges 统计
ArcEdgeCount = Edges.Count(e => e.SegmentType == PathSegmentType.Arc);
TotalEdgeCount = Edges.Count;

// 转弯次数扣分（每次扣8分）
TurnPenalty = ArcEdgeCount * 8;

// 小半径惩罚
MinRadius = Edges
    .Where(e => e.SegmentType == PathSegmentType.Arc)
    .Select(e => e.Trajectory?.ActualRadius ?? double.MaxValue)
    .DefaultIfEmpty(double.MaxValue)
    .Min();
    
RadiusPenalty = MinRadius < 2.0 ? 20 : 0;

// 转弯难度分
TurnDifficultyScore = Max(0, 100 - TurnPenalty - RadiusPenalty);
```

### 3.4 直达性（路径曲折度）

```csharp
// 计算起点到终点的直线距离
StartPoint = Points.First().Position;
EndPoint = Points.Last().Position;
StraightDistance = Distance(StartPoint, EndPoint);

// 曲折度（≥1.0）
Tortuosity = TotalLength / StraightDistance;

// 曲折度分
TortuosityScore = Max(0, 100 - (Tortuosity - 1.0) * 50);
```



---

## 四、同一起终点分析（核心功能）

### 4.1 路径分组算法

```csharp
// 以终点为主的分组（2米阈值）
public List<EndpointGroup> GroupPathsByEndpoint(List<PathRoute> routes)
{
    const double ENDPOINT_THRESHOLD = 2.0; // 2米
    
    var groups = new List<EndpointGroup>();
    
    foreach (var route in routes)
    {
        var endPoint = route.GetEndPoint()?.Position;
        if (endPoint == null) continue;
        
        // 查找是否已有匹配的组
        var matchingGroup = groups.FirstOrDefault(g => 
            Distance(g.EndPoint, endPoint) < ENDPOINT_THRESHOLD);
        
        if (matchingGroup != null)
        {
            matchingGroup.Routes.Add(route);
            // 更新组中心点
            matchingGroup.EndPoint = AveragePoint(matchingGroup.Routes);
        }
        else
        {
            groups.Add(new EndpointGroup
            {
                GroupId = Guid.NewGuid().ToString("N")[..8],
                EndPoint = endPoint,
                Routes = new List<PathRoute> { route }
            });
        }
    }
    
    return groups;
}
```

### 4.2 组内对比指标

| 对比项 | 计算公式 |
|-------|---------|
| 长度差异率 | (路径长度 - 组内最短) / 最短 × 100% |
| 效率差异率 | (路径时间 - 组内最短) / 最短 × 100% |
| 安全差异 | 碰撞数对比（0次为优） |
| 最佳路径 | 按策略加权评分最高者 |

### 4.3 最佳路径判定逻辑

```csharp
public PathRoute FindBestPathInGroup(EndpointGroup group, string strategy)
{
    // 第一步：计算所有路径的加权评分
    foreach (var route in group.Routes)
    {
        route.WeightedScore = CalculateWeightedScore(route.Analysis, strategy);
    }
    
    // 第二步：按评分排序
    var sortedRoutes = group.Routes.OrderByDescending(r => r.WeightedScore).ToList();
    
    // 第三步：如果前两名评分接近（差距<5分），优先选碰撞少的
    if (sortedRoutes.Count >= 2)
    {
        var first = sortedRoutes[0];
        var second = sortedRoutes[1];
        
        if (Math.Abs(first.WeightedScore - second.WeightedScore) < 5)
        {
            if (second.CollisionCount < first.CollisionCount)
                return second;
        }
    }
    
    return sortedRoutes.First();
}
```

---

## 五、碰撞热点计算

### 5.1 热点定义

- **范围**: 3米半径球体
- **阈值**: 范围内 ≥2 次碰撞
- **数据来源**: `ClashDetectiveCollisionObjects` 表的 `Item1PosX/Y/Z`

### 5.2 热点检测算法

```csharp
public List<CollisionHotspot> DetectHotspots(List<CollisionResult> collisions, double radius = 3.0)
{
    var hotspots = new List<CollisionHotspot>();
    var processed = new HashSet<int>();
    
    for (int i = 0; i < collisions.Count; i++)
    {
        if (processed.Contains(i)) continue;
        
        var center = collisions[i].Center;
        var nearbyCollisions = new List<CollisionResult> { collisions[i] };
        
        // 查找范围内的其他碰撞
        for (int j = i + 1; j < collisions.Count; j++)
        {
            if (processed.Contains(j)) continue;
            
            if (Distance(center, collisions[j].Center) <= radius)
            {
                nearbyCollisions.Add(collisions[j]);
                processed.Add(j);
            }
        }
        
        // 如果达到阈值，创建热点
        if (nearbyCollisions.Count >= 2)
        {
            hotspots.Add(new CollisionHotspot
            {
                Center = CalculateCenter(nearbyCollisions),
                CollisionCount = nearbyCollisions.Count,
                Radius = radius,
                CollidedObjectNames = nearbyCollisions.Select(c => c.Item2.DisplayName).Distinct().ToList()
            });
        }
        
        processed.Add(i);
    }
    
    return hotspots;
}
```

---

## 六、优化建议生成

### 6.1 建议分类

| 类别 | 触发条件 | 建议内容 |
|-----|---------|---------|
| **安全建议** | 碰撞数>0 | 发现X次碰撞，其中Y个热点，建议检查碰撞位置 |
| **效率建议** | 长度差异率>30% | 该路径比组内最短路径长X%，建议优化路线 |
| **转弯建议** | 转弯次数>3 | 路径包含X个转弯，建议减少急转弯 |
| **直达建议** | 直达性<70% | 路径较为曲折，建议考虑更直接的路线 |
| **组内对比** | 组内路径>1 | 本组共X条路径，推荐【路径名】为最佳选择 |

### 6.2 建议生成示例

```csharp
public List<string> GenerateSuggestions(PathDetailedAnalysis analysis, EndpointGroup group)
{
    var suggestions = new List<string>();
    
    // 安全建议
    if (analysis.CollisionCount > 0)
    {
        if (analysis.HotspotCount > 0)
            suggestions.Add($"🔴 发现{analysis.CollisionCount}次碰撞，其中{analysis.HotspotCount}个热点区域，建议重点检查热点位置");
        else
            suggestions.Add($"⚠️ 发现{analysis.CollisionCount}次碰撞，建议优化路径避让");
    }
    else
    {
        suggestions.Add("✅ 无碰撞，安全性良好");
    }
    
    // 组内对比建议
    if (group?.Routes.Count > 1)
    {
        var lengthDiff = (analysis.TotalLength - group.MinLength) / group.MinLength * 100;
        if (lengthDiff > 30)
            suggestions.Add($"📊 该路径比组内最短路径长{lengthDiff:F1}%，建议考虑更短路线");
        
        // 推荐最佳路径
        if (analysis.RouteId == group.BestRouteId)
            suggestions.Add($"🏆 该路径是本组到『{group.EndPointName}』的最佳选择");
    }
    
    return suggestions;
}
```

---

## 七、数据库扩展

### 7.1 扩展示意图

```sql
-- AnalysisResults 表扩展字段
ALTER TABLE AnalysisResults ADD COLUMN 
    TurnDifficultyScore REAL,      -- 转弯难度分
    TortuosityScore REAL,          -- 直达性分
    HotspotCount INTEGER,          -- 热点数量
    AnalysisStrategy TEXT,         -- 分析策略
    GroupId TEXT,                  -- 所属终点组ID
    GroupRanking INTEGER;          -- 在组内排名

-- 新增热点表（可选）
CREATE TABLE IF NOT EXISTS CollisionHotspots (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    RouteId TEXT NOT NULL,
    CenterX REAL,
    CenterY REAL,
    CenterZ REAL,
    Radius REAL,
    CollisionCount INTEGER,
    CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY(RouteId) REFERENCES PathRoutes(Id) ON DELETE CASCADE
);
```

---

## 八、复用现有代码清单

| 功能 | 复用代码 | 文件路径 |
|-----|---------|---------|
| 通道属性获取 | `CategoryAttributeManager.GetLogisticsPropertyValue()` | `src/Core/Properties/CategoryAttributeManager.cs` |
| 碰撞数据获取 | `PathDatabase.GetClashDetectiveResultsByPath()` | `src/Core/PathDatabase.cs` |
| 碰撞对象位置 | `ClashDetectiveCollisionObjects` 表 | `src/Core/PathDatabase.cs` |
| 路径点位置 | `PathRoute.GetSortedPoints()` | `src/Core/PathPlanningModels.cs` |
| 路径边分析 | `PathRoute.Edges` | `src/Core/PathPlanningModels.cs` |
| 单位转换 | `UnitsConverter.ConvertToMeters()` | `src/Utils/UnitsConverter.cs` |
| 距离计算 | `GeometryHelper.Distance()` | `src/Utils/GeometryHelper.cs` |
| 报告目录 | `PathHelper.GetReportDirectory()` | `src/Utils/PathHelper.cs` |
| HTML报告模板 | `CollisionReportHtmlGenerator` | `src/Utils/CollisionReportHtmlGenerator.cs` |

---

## 九、分阶段实施计划

### Phase 1: 核心算法与数据结构（基础）

| 任务 | 文件 | 说明 |
|-----|------|------|
| 1.1 数据模型 | `src/Core/Models/PathAnalysisModels.cs` | 新建，定义分析相关模型 |
| 1.2 分析引擎 | `src/Core/PathAnalysisEngine.cs` | 新建，核心计算逻辑 |
| 1.3 数据库扩展 | `src/Core/PathDatabase.cs` | 修改，增加新字段和方法 |
| 1.4 服务扩展 | `src/Core/PathAnalysisService.cs` | 修改，集成新算法 |

### Phase 2: UI可视化（第二步）

| 任务 | 文件 | 说明 |
|-----|------|------|
| 2.1 ViewModel更新 | `src/UI/WPF/ViewModels/PathAnalysisViewModel.cs` | 修改，增加新属性和命令 |
| 2.2 对话框更新 | `src/UI/WPF/Views/PathAnalysisDialog.xaml` | 修改，增加Canvas图表区域 |
| 2.3 图表绘制 | `src/UI/WPF/Views/PathAnalysisDialog.xaml.cs` | 修改，Canvas自绘柱状图和雷达图 |

### Phase 3: HTML报告（第三步）

| 任务 | 文件 | 说明 |
|-----|------|------|
| 3.1 报告生成器 | `src/Core/PathAnalysisReportGenerator.cs` | 新建，HTML生成逻辑 |
| 3.2 报告样式 | 嵌入式CSS | 使用内联样式，无需外部依赖 |

---

## 十、关键算法伪代码

### 10.1 综合评分计算

```csharp
public double CalculateWeightedScore(PathDetailedAnalysis analysis, string strategy)
{
    var weights = AnalysisStrategies.Weights[strategy];
    
    // 各维度分数
    double safety = analysis.SafetyScore;           // 安全
    double efficiency = analysis.EfficiencyScore;   // 效率
    double turn = analysis.TurnDifficultyScore;     // 转弯
    double tortuosity = analysis.TortuosityScore;   // 直达
    
    // 加权计算
    double weightedScore = 
        safety * weights[0] +
        efficiency * weights[1] +
        turn * weights[2] +
        tortuosity * weights[3];
    
    return Math.Round(weightedScore, 1);
}
```

### 10.2 完整分析流程

```csharp
public PathDetailedAnalysis AnalyzePath(PathRoute route, AnalysisContext context)
{
    var analysis = new PathDetailedAnalysis
    {
        RouteId = route.Id,
        RouteName = route.Name
    };
    
    // 1. 获取碰撞数据
    var collisions = GetCollisionsForRoute(route.Id);
    analysis.CollisionCount = collisions.Count;
    
    // 2. 检测热点
    analysis.Hotspots = DetectHotspots(collisions, radius: 3.0);
    analysis.HotspotCount = analysis.Hotspots.Count;
    
    // 3. 计算各维度分数
    analysis.SafetyScore = CalculateSafetyScore(analysis.CollisionCount, analysis.HotspotCount);
    analysis.EfficiencyScore = CalculateEfficiencyScore(route, context.GroupMinTime);
    analysis.TurnDifficultyScore = CalculateTurnDifficultyScore(route.Edges);
    analysis.TortuosityScore = CalculateTortuosityScore(route);
    
    // 4. 计算综合评分
    analysis.WeightedScore = CalculateWeightedScore(analysis, context.Strategy);
    
    return analysis;
}
```

---

## 十一、界面设计要点

### 11.1 路径分析对话框布局

```
+----------------------------------------------------------+
|  路径分析 - 多路径对比                          [关闭]   |
+----------------------------------------------------------+
|  +----------------+  +------------------+  +-----------+ |
|  | 路径选择       |  | 🏆 推荐最佳路径   |  | 💡 优化建议| |
|  | - 路径A        |  | 路径名称          |  | 建议1...  | |
|  | - 路径B [x]    |  | 长度: XXm | 评分  |  | 建议2...  | |
|  | - 路径C [x]    |  +------------------+  | ...       | |
|  |                |  +------------------+  +-----------+ |
|  | [全选][清空]   |  | 📊 多路径对比图表 |                |
|  |                |  | +--------------+ |                |
|  | 策略:          |  | | 柱状图       | |                |
|  | ○ 安全优先     |  | | (4维度对比)  | |                |
|  | ○ 效率优先     |  | +--------------+ |                |
|  | ● 平衡模式     |  | +--------------+ |                |
|  |                |  | | 雷达图       | |                |
|  | [开始分析]     |  | | (组内对比)   | |                |
|  +----------------+  +------------------+                |
|                      +------------------+                |
|                      | 🎯 同终点路径组   |                |
|                      | 组1: 终点 (2条)   |                |
|                      | - 路径B (最佳)    |                |
|                      | - 路径A           |                |
|                      +------------------+                |
+----------------------------------------------------------+
|                                    [导出报告] [关闭]      |
+----------------------------------------------------------+
```

### 11.2 可视化元素（WPF Canvas自绘）

1. **柱状图**: 使用WPF Canvas绘制，展示各路径4维度分数对比（安全/效率/转弯/直达）
   - 每个柱子显示具体分数
   - 路径名称水平显示在柱组下方
   - 右上角显示图例
   
2. **雷达图**: 使用WPF Canvas绘制，展示选中组内所有路径的4维度表现
   - 五边形网格背景
   - 不同颜色区分各路径
   - 最佳路径用粗线标识
   
3. **推荐卡片**: 显示最佳路径名称、长度和综合评分

4. **优化建议列表**: 分类显示安全、效率、转弯等建议

---

## 十二、HTML报告结构

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>路径分析报告</title>
    <style>
        /* 简洁专业风格（蓝白配色） */
        :root { --primary: #2c5aa0; --success: #28a745; --warning: #ffc107; --danger: #dc3545; }
        body { font-family: 'Microsoft YaHei', Arial; margin: 40px; }
        .header { text-align: center; border-bottom: 3px solid var(--primary); padding-bottom: 20px; }
        .best-path-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 12px; }
        .score-bar-container { background: #e9ecef; height: 24px; border-radius: 12px; position: relative; }
        .score-bar { height: 100%; border-radius: 12px; }
        .score-text { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-weight: bold; }
        .comparison-table { width: 100%; border-collapse: collapse; }
        .comparison-table th { background: var(--primary); color: white; padding: 12px; }
        /* ... */
    </style>
</head>
<body>
    <!-- 1. 头部 -->
    <!-- 2. 执行摘要+最佳路径 -->
    <!-- 3. 同终点组分析 -->
    <!-- 4. 详细数据表格（带分数条） -->
    <!-- 5. 优化建议 -->
</body>
</html>
```

**说明**: HTML报告使用纯CSS样式，无需外部JavaScript库，可离线打开。

---

## 十三、风险评估与应对

| 风险 | 影响 | 应对措施 |
|-----|------|---------|
| 碰撞位置数据缺失 | 热点计算失败 | 使用碰撞对象中心点作为近似 |
| 通道属性未设置 | 冗余度无法计算 | 使用默认值，并在报告中提示 |
| 路径无边数据 | 转弯分析失败 | 退化为直线分析 |
| 单一路径无对比 | 组内分析无意义 | 隐藏组内对比部分 |

---

## 十四、验收标准

### 14.1 Phase 1 验收

- [ ] 能正确计算5维度分数
- [ ] 能正确检测碰撞热点（3米范围）
- [ ] 能按策略计算加权评分
- [ ] 数据能正确保存到数据库

### 14.2 Phase 2 验收

- [ ] UI能显示4维度柱状图（WPF Canvas绘制）
- [ ] UI能显示雷达图（WPF Canvas绘制）
- [ ] 同终点组能正确分组（2米阈值）
- [ ] 能正确标识组内最佳路径
- [ ] 优化建议具体且可执行

### 14.3 Phase 3 验收

- [ ] HTML报告能离线打开（纯CSS样式，无外部依赖）
- [ ] 报告包含所有必要信息
- [ ] 表格分数条能正确显示
- [ ] 样式符合专业报告标准

---

## 十五、资源文件路径

所有资源文件统一存放在 `resources` 目录下：

| 文件 | 路径 | 说明 |
|-----|------|------|
| 默认配置 | `resources/default_config.toml` | 系统默认配置模板 |
| 插件名称 | `resources/TransportPlugin.name.txt` | 插件显示名称 |
| 单位立方体 | `resources/unit_cube.nwc` | 虚拟物体碰撞检测用 |

**部署说明**: 编译时资源文件会自动复制到输出目录，部署脚本会将整个 `resources` 文件夹复制到插件目录。

---

## 附录：参考文件

- 现有碰撞报告生成器: `src/Utils/CollisionReportHtmlGenerator.cs`
- 通道属性管理器: `src/Core/Properties/CategoryAttributeManager.cs`
- 路径数据模型: `src/Core/PathPlanningModels.cs`
- 数据库操作: `src/Core/PathDatabase.cs`
- 单位转换: `src/Utils/UnitsConverter.cs`
