NavisworksTransport/doc/working/path_analysis_design.md

19 KiB
Raw Blame History

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

版本: 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 权重配置代码

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 安全性(碰撞风险指数)- 权重最高

// 基础碰撞分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 效率(通行效率指数)

// 速度分以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 可行性(转弯难度系数)

// 从 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 直达性(路径曲折度)

// 计算起点到终点的直线距离
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 路径分组算法

// 以终点为主的分组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 最佳路径判定逻辑

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 热点检测算法

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 建议生成示例

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 扩展示意图

-- 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 综合评分计算

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 完整分析流程

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报告结构

<!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