NavisworksTransport/doc/working/最少转弯路径算法Plan20250909.md

154 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

⎿ 最少转弯路径实现计划基于Roy-T.AStar官方API
实施策略:严格保护现有算法
阶段一:数据结构扩展
1. 添加路径策略枚举
位置src/PathPlanning/PathPlanningModels.cs
public enum PathStrategy
{
Shortest = 0, // 默认:标准最短路径(现有行为)
Straightest = 1 // 新增:直线优先路径
}
2. 扩展AutoPathFinder方法签名
位置src/PathPlanning/AutoPathFinder.cs
- 新增重载FindPath(..., PathStrategy strategy = PathStrategy.Shortest)
- 保留所有现有方法不变
阶段二:核心算法实现
3. 实现方向感知的网格转换
新增方法ConvertToAStarGridWithStrategy()
private Grid ConvertToAStarGridWithStrategy(GridMap gridMap, Point3D startPos, Point3D endPos, PathStrategy strategy,
double objectHeight)
{
if (strategy == PathStrategy.Shortest) {
// 调用现有方法保证100%兼容
return ConvertToAStarGridWith2_5D(gridMap, channelCoverage, objectHeight);
}
// 直线优先实现
return ConvertToAStarGridStraightest(gridMap, startPos, endPos, objectHeight);
}
4. 直线优先算法核心
基于文档第127行的AddEdge模式
private Grid ConvertToAStarGridStraightest(GridMap gridMap, Point3D start, Point3D end, double objectHeight)
{
// 1. 计算主方向
double dx = Math.Abs(end.X - start.X);
double dy = Math.Abs(end.Y - start.Y);
bool preferHorizontal = dx > dy;
// 2. 差异化速度设置基于文档的Velocity.FromKilometersPerHour
var mainDirectionVelocity = Velocity.FromKilometersPerHour(10); // 主方向:低成本
var crossDirectionVelocity = Velocity.FromKilometersPerHour(2); // 次方向:高成本
var diagonalVelocity = Velocity.FromKilometersPerHour(5); // 对角线:中等成本
// 3. 按现有模式创建和断开网格文档第104-108行
var grid = Grid.CreateGridWithLateralConnections(gridSize, cellSize, mainDirectionVelocity);
// 先断开所有连接
for (int x = 0; x < gridMap.Width; x++) {
for (int y = 0; y < gridMap.Height; y++) {
grid.DisconnectNode(new GridPosition(x, y));
}
}
// 4. 智能连接根据方向设置不同速度文档第115-126行模式
for (int x = 0; x < gridMap.Width; x++) {
for (int y = 0; y < gridMap.Height; y++) {
if (IsPassableWithHeight(gridMap.Cells[x, y], objectHeight)) {
var pos = new GridPosition(x, y);
// 水平连接
if (x + 1 < gridMap.Width && IsPassableWithHeight(gridMap.Cells[x + 1, y], objectHeight)) {
var rightPos = new GridPosition(x + 1, y);
var velocity = preferHorizontal ? mainDirectionVelocity : crossDirectionVelocity;
grid.AddEdge(pos, rightPos, velocity);
grid.AddEdge(rightPos, pos, velocity);
}
// 垂直连接
if (y + 1 < gridMap.Height && IsPassableWithHeight(gridMap.Cells[x, y + 1], objectHeight)) {
var bottomPos = new GridPosition(x, y + 1);
var velocity = preferHorizontal ? crossDirectionVelocity : mainDirectionVelocity;
grid.AddEdge(pos, bottomPos, velocity);
grid.AddEdge(bottomPos, pos, velocity);
}
// 对角线连接可选
if (x + 1 < gridMap.Width && y + 1 < gridMap.Height &&
IsPassableWithHeight(gridMap.Cells[x + 1, y + 1], objectHeight)) {
var diagonalPos = new GridPosition(x + 1, y + 1);
grid.AddEdge(pos, diagonalPos, diagonalVelocity);
grid.AddEdge(diagonalPos, pos, diagonalVelocity);
}
}
}
}
return grid;
}
阶段三集成到现有流程
5. 扩展PathPlanningManager调用
位置src/Core/PathPlanningManager.cs
- 在AutoPlanPath方法中添加可选策略参数
- 默认值确保现有调用完全不变
6. 策略路由逻辑
public Task<PathRoute> AutoPlanPath(..., PathStrategy strategy = PathStrategy.Shortest)
{
// 现有逻辑保持不变...
// 策略感知的路径查找
pathResult = pathFinder.FindPath(startPoint.Position, endPoint.Position, gridMap, channelCoverage, objectHeight,
strategy);
}
阶段四:质量保证
7. 兼容性验证
- ✅ 所有现有单元测试必须通过
- ✅ 默认调用行为与当前完全一致
- ✅ 现有UI调用无需任何修改
8. 功能验证
- ✅ 对比两种策略的路径差异
- ✅ 验证直线优先路径确实减少转弯
- ✅ 性能测试确保无显著性能影响
9. 调试支持
基于文档第237行的日志模式
LogManager.Info($"[直线优先] 主方向: {(preferHorizontal ? "水平" : "垂直")}, 起点({start.X:F2},{start.Y:F2}),
终点({end.X:F2},{end.Y:F2})");
LogManager.Info($"[速度设置] 主方向: {mainDirectionVelocity.InKilometersPerHour}km/h, 次方向:
{crossDirectionVelocity.InKilometersPerHour}km/h");
交付成果
1. 零破坏性扩展现有功能100%保持原样
2. 基于官方API使用Roy-T.AStar文档化的最佳实践
3. 易于使用:通过可选参数启用新功能
4. 充分测试:确保稳定性和兼容性
5. 详细日志:便于调试和性能分析
测试用例设计
- 现有路径 vs 直线优先路径的转弯次数对比
- 长距离直线路径的优化效果验证
- 复杂地形下的算法鲁棒性测试