# 多路径方案实现策略

基于Roy-T.AStar库实现多路径选择功能的详细技术方案。

## 核心原理

Roy-T.AStar库本身不提供多路径功能，但通过巧妙操作可以实现：

- **关键洞察**：A*使用Duration（时间）作为成本，而Duration = Distance / Velocity
- **核心技术**：通过动态调整边的Velocity来影响路径选择

## 1. 多路径生成器架构

```csharp
public class MultiPathFinder
{
    private readonly GridMap _gridMap;
    
    public class PathOption
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public List<Point3D> Path { get; set; }
        public PathStrategy Strategy { get; set; }
        public double Score { get; set; } // 综合评分
        public Dictionary<string, double> Metrics { get; set; } // 各项指标
    }
    
    public enum PathStrategy
    {
        Shortest,      // 最短距离
        Safest,        // 最安全（远离障碍）
        Straightest,   // 最少转弯
        Fastest,       // 最快（考虑拥堵）
        Balanced       // 平衡所有因素
    }
    
    public List<PathOption> FindMultiplePaths(Point3D start, Point3D end)
    {
        var options = new List<PathOption>();
        
        // 生成不同策略的路径
        options.Add(FindShortestPath(start, end));
        options.Add(FindSafestPath(start, end));
        options.Add(FindStraightestPath(start, end));
        options.Add(FindLeastCongestedPath(start, end));
        
        // 评估和排序
        EvaluateAndRankPaths(options);
        
        return options;
    }
}
```

## 2. 不同路径策略的实现

### 2.1 最短路径（标准A*）

```csharp
private PathOption FindShortestPath(Point3D start, Point3D end)
{
    // 所有边使用统一速度，纯粹基于距离
    var uniformVelocity = Velocity.FromKilometersPerHour(5);
    var grid = Grid.CreateGridWithLateralConnections(gridSize, cellSize, uniformVelocity);
    
    // 标准网格转换
    ApplyBasicObstacles(grid, _gridMap);
    
    var pathfinder = new PathFinder();
    var path = pathfinder.FindPath(ToGridPos(start), ToGridPos(end), grid);
    
    return new PathOption
    {
        Name = "最短路径",
        Description = "距离最短，不考虑其他因素",
        Path = ConvertToWorldPath(path),
        Strategy = PathStrategy.Shortest,
        Metrics = new Dictionary<string, double>
        {
            ["总距离"] = CalculateTotalDistance(path),
            ["转弯次数"] = CountTurns(path),
            ["预计时间"] = EstimateTime(path),
            ["安全系数"] = CalculateSafetyScore(path)
        }
    };
}
```

### 2.2 最安全路径（避开危险区域）

```csharp
private PathOption FindSafestPath(Point3D start, Point3D end)
{
    var baseVelocity = Velocity.FromKilometersPerHour(5);
    var grid = Grid.CreateGridWithLateralConnections(gridSize, cellSize, baseVelocity);
    
    // 关键：修改危险区域的边速度
    for (int x = 0; x < gridMap.Width; x++)
    {
        for (int y = 0; y < gridMap.Height; y++)
        {
            var cell = gridMap.Cells[x, y];
            var pos = new GridPosition(x, y);
            
            // 计算危险系数
            double dangerLevel = CalculateDangerLevel(cell, gridMap);
            
            if (dangerLevel > 0)
            {
                // 危险区域速度降低（成本增加）
                var safetyVelocity = baseVelocity * (1.0 - dangerLevel * 0.8);
                
                // 重新设置该节点所有出边的速度
                foreach (var neighbor in GetValidNeighbors(pos, gridMap))
                {
                    grid.RemoveEdge(pos, neighbor);
                    grid.AddEdge(pos, neighbor, safetyVelocity);
                }
            }
        }
    }
    
    var path = FindPath(start, end, grid);
    return new PathOption { Name = "最安全路径", ... };
}

private double CalculateDangerLevel(GridCell cell, GridMap gridMap)
{
    double danger = 0;
    
    // 1. 靠近障碍物增加危险度
    if (cell.DistanceToNearestObstacle < 2.0)
        danger += 0.5 * (2.0 - cell.DistanceToNearestObstacle) / 2.0;
    
    // 2. 狭窄通道增加危险度
    if (cell.PassageWidth < 3.0)
        danger += 0.3 * (3.0 - cell.PassageWidth) / 3.0;
    
    // 3. 高度受限区域增加危险度
    if (cell.ClearanceHeight < 4.0)
        danger += 0.2 * (4.0 - cell.ClearanceHeight) / 4.0;
    
    return Math.Min(danger, 0.95); // 最大危险度0.95
}
```

### 2.3 最少转弯路径（直线优先）

```csharp
private PathOption FindStraightestPath(Point3D start, Point3D end)
{
    var grid = Grid.CreateGridWithLateralConnections(gridSize, cellSize, baseVelocity);
    
    // 计算主方向
    var dx = Math.Abs(end.X - start.X);
    var dy = Math.Abs(end.Y - start.Y);
    bool preferHorizontal = dx > dy;
    
    // 关键：为不同方向的边设置不同速度
    for (int x = 0; x < gridMap.Width; x++)
    {
        for (int y = 0; y < gridMap.Height; y++)
        {
            var pos = new GridPosition(x, y);
            
            if (preferHorizontal)
            {
                // 水平方向高速（低成本）
                if (x + 1 < gridMap.Width)
                {
                    SetEdgeVelocity(grid, pos, new GridPosition(x + 1, y), 
                        Velocity.FromKilometersPerHour(10));
                }
                
                // 垂直方向低速（高成本，避免转弯）
                if (y + 1 < gridMap.Height)
                {
                    SetEdgeVelocity(grid, pos, new GridPosition(x, y + 1), 
                        Velocity.FromKilometersPerHour(2));
                }
            }
            else
            {
                // 相反设置
                // ...
            }
        }
    }
    
    // 额外奖励：连续直线段
    ApplyStraightLineBonus(grid, start, end);
    
    var path = FindPath(start, end, grid);
    return new PathOption { Name = "最少转弯路径", ... };
}

private void ApplyStraightLineBonus(Grid grid, Point3D start, Point3D end)
{
    // 检测并奖励直线段
    var direction = NormalizeDirection(end - start);
    
    // 沿主方向的直线路径获得速度加成
    for (int i = 0; i < maxSteps; i++)
    {
        var currentPos = start + direction * i * stepSize;
        var gridPos = ToGridPosition(currentPos);
        
        if (IsValidPosition(gridPos))
        {
            // 直线方向的边获得额外速度加成
            BoostDirectionalEdges(grid, gridPos, direction, 
                Velocity.FromKilometersPerHour(15));
        }
    }
}
```

### 2.4 避免拥堵路径

```csharp
private PathOption FindLeastCongestedPath(Point3D start, Point3D end)
{
    var grid = CreateBaseGrid();
    
    // 基于历史数据或实时数据调整速度
    foreach (var congestionZone in _congestionData.Zones)
    {
        foreach (var gridPos in GetGridPositionsInZone(congestionZone))
        {
            // 拥堵区域降速
            var congestionVelocity = baseVelocity * (1.0 - congestionZone.CongestionLevel);
            UpdateNodeVelocity(grid, gridPos, congestionVelocity);
        }
    }
    
    // 考虑时间因素
    if (_timeBasedCongestion != null)
    {
        var currentTime = DateTime.Now.TimeOfDay;
        ApplyTimeBasedCongestion(grid, currentTime);
    }
    
    var path = FindPath(start, end, grid);
    return new PathOption { Name = "避堵路径", ... };
}
```

## 3. 生成互不相同的替代路径

### 3.1 排斥力场方法

```csharp
public List<PathOption> FindAlternativePaths(Point3D start, Point3D end, int count)
{
    var paths = new List<PathOption>();
    var usedNodes = new HashSet<GridPosition>();
    var penaltyMap = new Dictionary<GridPosition, double>();
    
    for (int i = 0; i < count; i++)
    {
        var grid = CreateBaseGrid();
        
        // 对已使用的节点施加排斥力
        foreach (var usedNode in usedNodes)
        {
            // 计算排斥力影响范围
            var affectedNodes = GetNodesInRadius(usedNode, repulsionRadius: 3);
            
            foreach (var node in affectedNodes)
            {
                var distance = CalculateDistance(usedNode, node);
                var penalty = 1.0 / (1.0 + distance); // 距离越近，惩罚越大
                
                // 累积惩罚
                if (!penaltyMap.ContainsKey(node))
                    penaltyMap[node] = 0;
                penaltyMap[node] += penalty * 0.3; // 每条路径贡献30%惩罚
                
                // 应用惩罚：降低该节点的通行速度
                var penaltyFactor = Math.Max(0.1, 1.0 - penaltyMap[node]);
                var penalizedVelocity = baseVelocity * penaltyFactor;
                
                UpdateNodeVelocity(grid, node, penalizedVelocity);
            }
        }
        
        // 查找新路径
        var path = FindPath(start, end, grid);
        paths.Add(new PathOption
        {
            Name = $"替代路径 {i + 1}",
            Path = path,
            Metrics = CalculateMetrics(path)
        });
        
        // 记录使用的节点
        foreach (var node in path.Nodes)
        {
            usedNodes.Add(ToGridPosition(node));
        }
    }
    
    return paths;
}
```

### 3.2 K-最短路径变体

```csharp
public List<PathOption> FindKShortestPaths(Point3D start, Point3D end, int k)
{
    var paths = new List<PathOption>();
    var candidatePaths = new PriorityQueue<Path, double>();
    
    // 找到第一条最短路径
    var firstPath = FindShortestPath(start, end);
    paths.Add(firstPath);
    
    // Yen's K-shortest paths算法的简化版本
    for (int k_i = 1; k_i < k; k_i++)
    {
        var prevPath = paths[k_i - 1].Path;
        
        // 对路径的每个节点作为分叉点
        for (int i = 0; i < prevPath.Count - 1; i++)
        {
            var spurNode = prevPath[i];
            var rootPath = prevPath.Take(i + 1).ToList();
            
            // 创建新网格，移除已用路径的部分边
            var modifiedGrid = CreateGridWithRemovedEdges(
                prevPath.Skip(i).Take(2).ToList());
            
            // 从分叉点找到终点的新路径
            var spurPath = FindPath(spurNode, end, modifiedGrid);
            
            if (spurPath != null)
            {
                var totalPath = rootPath.Concat(spurPath.Skip(1)).ToList();
                var pathCost = CalculatePathCost(totalPath);
                candidatePaths.Enqueue(totalPath, pathCost);
            }
        }
        
        // 选择最佳候选路径
        if (candidatePaths.Count > 0)
        {
            var nextBestPath = candidatePaths.Dequeue();
            paths.Add(new PathOption
            {
                Name = $"第{k_i + 1}短路径",
                Path = nextBestPath
            });
        }
    }
    
    return paths;
}
```

## 4. 路径评估与展示

### 4.1 多维度评估系统

```csharp
public class PathEvaluator
{
    public class PathMetrics
    {
        public double TotalDistance { get; set; }
        public int TurnCount { get; set; }
        public double AverageTurnAngle { get; set; }
        public double SafetyScore { get; set; }
        public double CongestionScore { get; set; }
        public double EstimatedTime { get; set; }
        public double EnergyConsumption { get; set; }
        public double ComfortScore { get; set; } // 基于加速度变化
    }
    
    public PathMetrics EvaluatePath(List<Point3D> path, GridMap gridMap)
    {
        var metrics = new PathMetrics();
        
        // 距离计算
        metrics.TotalDistance = CalculateTotalDistance(path);
        
        // 转弯分析
        var turns = AnalyzeTurns(path);
        metrics.TurnCount = turns.Count;
        metrics.AverageTurnAngle = turns.Any() ? turns.Average() : 0;
        
        // 安全评分
        metrics.SafetyScore = CalculateSafetyScore(path, gridMap);
        
        // 拥堵评分
        metrics.CongestionScore = EstimateCongestion(path);
        
        // 时间估算（考虑速度变化）
        metrics.EstimatedTime = EstimateTraversalTime(path, gridMap);
        
        // 能耗估算（考虑加速、减速、转弯）
        metrics.EnergyConsumption = EstimateEnergyUsage(path);
        
        // 舒适度（基于路径平滑度）
        metrics.ComfortScore = CalculateComfortScore(path);
        
        return metrics;
    }
    
    private double CalculateSafetyScore(List<Point3D> path, GridMap gridMap)
    {
        double totalSafety = 0;
        int segments = 0;
        
        for (int i = 0; i < path.Count - 1; i++)
        {
            var segment = new LineSegment(path[i], path[i + 1]);
            
            // 检查与障碍物的最小距离
            double minDistance = double.MaxValue;
            foreach (var obstacle in gridMap.Obstacles)
            {
                var distance = CalculateDistanceToObstacle(segment, obstacle);
                minDistance = Math.Min(minDistance, distance);
            }
            
            // 距离越远越安全
            double segmentSafety = Math.Min(1.0, minDistance / 5.0);
            totalSafety += segmentSafety;
            segments++;
        }
        
        return segments > 0 ? totalSafety / segments : 0;
    }
}
```

### 4.2 用户界面展示

```csharp
public class PathOptionsViewModel
{
    public ObservableCollection<PathOptionDisplay> PathOptions { get; set; }
    
    public class PathOptionDisplay
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public BitmapSource Preview { get; set; } // 路径预览图
        public RadarChart MetricsChart { get; set; } // 雷达图显示各项指标
        public bool IsRecommended { get; set; }
        public string RecommendationReason { get; set; }
    }
    
    public void DisplayPathOptions(List<PathOption> options)
    {
        PathOptions.Clear();
        
        foreach (var option in options)
        {
            var display = new PathOptionDisplay
            {
                Name = option.Name,
                Description = GenerateDescription(option),
                Preview = RenderPathPreview(option.Path),
                MetricsChart = CreateRadarChart(option.Metrics),
                IsRecommended = DetermineIfRecommended(option),
                RecommendationReason = GetRecommendationReason(option)
            };
            
            PathOptions.Add(display);
        }
        
        // 高亮推荐路径
        HighlightRecommendedPath();
    }
    
    private string GenerateDescription(PathOption option)
    {
        var sb = new StringBuilder();
        sb.AppendLine($"策略: {option.Strategy}");
        sb.AppendLine($"距离: {option.Metrics["总距离"]:F2}米");
        sb.AppendLine($"预计时间: {option.Metrics["预计时间"]:F1}分钟");
        sb.AppendLine($"转弯: {option.Metrics["转弯次数"]}次");
        sb.AppendLine($"安全系数: {option.Metrics["安全系数"]:P0}");
        
        // 特点描述
        if (option.Strategy == PathStrategy.Shortest)
            sb.AppendLine("✓ 距离最短，节省时间");
        else if (option.Strategy == PathStrategy.Safest)
            sb.AppendLine("✓ 远离危险区域，安全可靠");
        else if (option.Strategy == PathStrategy.Straightest)
            sb.AppendLine("✓ 转弯最少，便于大型物体");
        
        return sb.ToString();
    }
}
```

## 5. 实施建议

### 5.1 集成到NavisworksTransport

```csharp
// 修改AutoPathFinder.cs
public class AutoPathFinder
{
    private MultiPathFinder _multiPathFinder;
    
    // 新增：多路径查找方法
    public List<PathFindingResult> FindMultiplePaths(
        Point3D start, 
        Point3D end, 
        GridMap gridMap,
        PathPlanningOptions options)
    {
        var results = new List<PathFindingResult>();
        
        // 根据用户选项生成不同策略的路径
        if (options.GenerateShortestPath)
            results.Add(FindPathWithStrategy(start, end, gridMap, PathStrategy.Shortest));
            
        if (options.GenerateSafestPath)
            results.Add(FindPathWithStrategy(start, end, gridMap, PathStrategy.Safest));
            
        if (options.GenerateStraightestPath)
            results.Add(FindPathWithStrategy(start, end, gridMap, PathStrategy.Straightest));
        
        // 如果需要，生成额外的替代路径
        if (options.AlternativePathCount > results.Count)
        {
            var alternatives = FindAlternativePaths(
                start, end, 
                options.AlternativePathCount - results.Count);
            results.AddRange(alternatives);
        }
        
        return results;
    }
}
```

### 5.2 UI集成

```xml
<!-- PathAnalysisDialog.xaml -->
<TabControl>
    <TabItem Header="路径选项">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            
            <!-- 策略选择 -->
            <StackPanel Grid.Row="0" Orientation="Horizontal">
                <CheckBox Content="最短路径" IsChecked="{Binding GenerateShortestPath}"/>
                <CheckBox Content="最安全路径" IsChecked="{Binding GenerateSafestPath}"/>
                <CheckBox Content="最少转弯" IsChecked="{Binding GenerateStraightestPath}"/>
                <CheckBox Content="避开拥堵" IsChecked="{Binding GenerateFastestPath}"/>
            </StackPanel>
            
            <!-- 路径列表 -->
            <ListBox Grid.Row="1" ItemsSource="{Binding PathOptions}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Border BorderBrush="LightGray" BorderThickness="1" Margin="5">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="150"/>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="200"/>
                                </Grid.ColumnDefinitions>
                                
                                <!-- 路径预览 -->
                                <Image Grid.Column="0" Source="{Binding Preview}"/>
                                
                                <!-- 路径信息 -->
                                <StackPanel Grid.Column="1" Margin="10">
                                    <TextBlock Text="{Binding Name}" FontWeight="Bold"/>
                                    <TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
                                </StackPanel>
                                
                                <!-- 指标雷达图 -->
                                <ContentControl Grid.Column="2" Content="{Binding MetricsChart}"/>
                            </Grid>
                        </Border>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            
            <!-- 操作按钮 -->
            <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
                <Button Content="比较路径" Command="{Binding ComparePathsCommand}"/>
                <Button Content="选择路径" Command="{Binding SelectPathCommand}"/>
            </StackPanel>
        </Grid>
    </TabItem>
</TabControl>
```

## 6. 性能优化建议

### 6.1 缓存机制

```csharp
public class PathCache
{
    private readonly Dictionary<PathCacheKey, List<PathOption>> _cache;
    private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5);
    
    public struct PathCacheKey
    {
        public Point3D Start;
        public Point3D End;
        public PathStrategy Strategy;
        public DateTime Timestamp;
        
        public bool IsExpired => DateTime.Now - Timestamp > _cacheExpiration;
    }
    
    public bool TryGetCachedPaths(Point3D start, Point3D end, out List<PathOption> paths)
    {
        var key = new PathCacheKey 
        { 
            Start = RoundToGrid(start), 
            End = RoundToGrid(end) 
        };
        
        if (_cache.TryGetValue(key, out paths) && !key.IsExpired)
        {
            return true;
        }
        
        paths = null;
        return false;
    }
}
```

### 6.2 并行计算

```csharp
public async Task<List<PathOption>> FindMultiplePathsAsync(Point3D start, Point3D end)
{
    var strategies = new[] 
    { 
        PathStrategy.Shortest, 
        PathStrategy.Safest, 
        PathStrategy.Straightest 
    };
    
    // 并行计算不同策略的路径
    var tasks = strategies.Select(strategy => 
        Task.Run(() => FindPathWithStrategy(start, end, strategy))
    ).ToArray();
    
    var results = await Task.WhenAll(tasks);
    
    return results.ToList();
}
```

## 7. 总结

这个多路径方案的核心优势：

1. **不修改Roy-T.AStar源码** - 完全基于库提供的接口
2. **灵活可扩展** - 容易添加新的路径策略
3. **性能优良** - 利用了Roy-T.AStar的高性能实现
4. **用户友好** - 提供直观的比较和选择界面
5. **实用性强** - 适合物流规划的实际需求

关键技术点：

- 通过调整Velocity影响成本计算
- 使用排斥力场生成不同路径
- 多维度评估系统
- 缓存和并行优化

这个方案可以让用户根据具体场景选择最合适的路径，大大提升了系统的实用性和灵活性。
