增加网格可视化开关,路径优化不成功
This commit is contained in:
parent
9f42c6f381
commit
ceb37e33a4
@ -156,6 +156,7 @@
|
||||
<Compile Include="src\PathPlanning\OptimizedHeightCalculator.cs" />
|
||||
<Compile Include="src\PathPlanning\ChannelBasedGridBuilder.cs" />
|
||||
<Compile Include="src\PathPlanning\VerticalScanProcessor.cs" />
|
||||
<Compile Include="src\PathPlanning\PathOptimizer.cs" />
|
||||
|
||||
<!-- UI - Forms -->
|
||||
<Compile Include="src\UI\Forms\LogisticsPropertyEditDialog.cs">
|
||||
|
||||
@ -48,6 +48,11 @@ namespace NavisworksTransport
|
||||
|
||||
// 预览点管理
|
||||
private PathPoint _previewPoint = null;
|
||||
|
||||
// 网格可视化设置
|
||||
private bool _showWalkableGrid = true;
|
||||
private bool _showObstacleGrid = true;
|
||||
private bool _showUnknownGrid = false;
|
||||
private bool _isPreviewMode = false;
|
||||
private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置
|
||||
|
||||
@ -3101,6 +3106,53 @@ namespace NavisworksTransport
|
||||
|
||||
#region 网格可视化方法
|
||||
|
||||
/// <summary>
|
||||
/// 更新网格可视化设置
|
||||
/// </summary>
|
||||
/// <param name="showWalkable">是否显示可通行网格点</param>
|
||||
/// <param name="showObstacle">是否显示障碍物网格点</param>
|
||||
/// <param name="showUnknown">是否显示未知区域网格点</param>
|
||||
public void UpdateGridVisualizationSettings(bool showWalkable, bool showObstacle, bool showUnknown)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[网格可视化设置] 更新设置: 通行={showWalkable}, 障碍物={showObstacle}, 未知={showUnknown}");
|
||||
|
||||
_showWalkableGrid = showWalkable;
|
||||
_showObstacleGrid = showObstacle;
|
||||
_showUnknownGrid = showUnknown;
|
||||
|
||||
// 如果当前有网格正在显示,重新应用可视化
|
||||
RefreshGridVisualization();
|
||||
|
||||
LogManager.Info("[网格可视化设置] 设置更新完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[网格可视化设置] 更新设置失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新网格可视化(根据当前设置重新显示)
|
||||
/// </summary>
|
||||
private void RefreshGridVisualization()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 清除当前网格可视化
|
||||
ClearGridVisualization();
|
||||
|
||||
// 如果存在当前网格地图,重新应用可视化
|
||||
// 这里需要保存对最后一个gridMap的引用,或者从当前路径规划状态中重新获取
|
||||
LogManager.Info("[网格可视化] 刷新完成 - 需要重新进行路径规划以查看网格");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[网格可视化] 刷新失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在3D视图中可视化网格中的可通行单元格
|
||||
/// 在每个可通行网格的中心绘制一个绿色小球
|
||||
@ -3172,30 +3224,42 @@ namespace NavisworksTransport
|
||||
PathRoute targetRoute = null;
|
||||
string gridTypeName = "";
|
||||
|
||||
// 根据网格类型确定目标路径和名称
|
||||
// 根据网格类型和用户设置确定目标路径和名称
|
||||
if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.通道)
|
||||
{
|
||||
targetRoute = channelRoute;
|
||||
gridTypeName = "通道";
|
||||
channelCells++;
|
||||
if (_showWalkableGrid) // 检查可通行网格开关
|
||||
{
|
||||
targetRoute = channelRoute;
|
||||
gridTypeName = "通道";
|
||||
channelCells++;
|
||||
}
|
||||
}
|
||||
else if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.楼板)
|
||||
{
|
||||
targetRoute = channelRoute; // 开放空间也用绿色显示
|
||||
gridTypeName = "开放";
|
||||
openSpaceCells++;
|
||||
if (_showWalkableGrid) // 检查可通行网格开关
|
||||
{
|
||||
targetRoute = channelRoute; // 开放空间也用绿色显示
|
||||
gridTypeName = "开放";
|
||||
openSpaceCells++;
|
||||
}
|
||||
}
|
||||
else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.Unknown)
|
||||
{
|
||||
targetRoute = unknownRoute;
|
||||
gridTypeName = "空洞";
|
||||
unknownCells++;
|
||||
if (_showUnknownGrid) // 检查未知网格开关
|
||||
{
|
||||
targetRoute = unknownRoute;
|
||||
gridTypeName = "空洞";
|
||||
unknownCells++;
|
||||
}
|
||||
}
|
||||
else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.障碍物)
|
||||
{
|
||||
targetRoute = obstacleRoute;
|
||||
gridTypeName = "障碍";
|
||||
obstacleCells++;
|
||||
if (_showObstacleGrid) // 检查障碍物网格开关
|
||||
{
|
||||
targetRoute = obstacleRoute;
|
||||
gridTypeName = "障碍";
|
||||
obstacleCells++;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有对应的路径,创建并添加网格点
|
||||
|
||||
@ -6,6 +6,7 @@ using Roy_T.AStar.Grids;
|
||||
using Roy_T.AStar.Primitives;
|
||||
using Roy_T.AStar.Paths;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisworksTransport.Core;
|
||||
|
||||
namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
@ -153,6 +154,9 @@ namespace NavisworksTransport.PathPlanning
|
||||
|
||||
LogManager.Info($"[2.5D路径规划] 路径生成完成,最终包含 {finalPath.Count} 个路径点,完成度: {pathResult.CompletionPercentage:F1}%");
|
||||
|
||||
// 路径优化 - 去除共线点
|
||||
pathResult = OptimizePath(pathResult);
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -938,5 +942,71 @@ namespace NavisworksTransport.PathPlanning
|
||||
var dz = point2.Z - point1.Z;
|
||||
return Math.Sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 优化路径(去除共线点等)
|
||||
/// </summary>
|
||||
/// <param name="pathResult">原始路径查找结果</param>
|
||||
/// <returns>优化后的路径查找结果</returns>
|
||||
private PathFindingResult OptimizePath(PathFindingResult pathResult)
|
||||
{
|
||||
if (pathResult == null || pathResult.PathPoints.Count <= 2)
|
||||
{
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 创建临时路径用于优化
|
||||
var tempRoute = new PathRoute("临时优化路径");
|
||||
for (int i = 0; i < pathResult.PathPoints.Count; i++)
|
||||
{
|
||||
var point = pathResult.PathPoints[i];
|
||||
var pathPoint = new PathPoint
|
||||
{
|
||||
Position = point,
|
||||
Index = i,
|
||||
Type = i == 0 ? PathPointType.StartPoint :
|
||||
i == pathResult.PathPoints.Count - 1 ? PathPointType.EndPoint :
|
||||
PathPointType.WayPoint,
|
||||
Name = $"路径点{i}"
|
||||
};
|
||||
tempRoute.Points.Add(pathPoint);
|
||||
}
|
||||
|
||||
// 🔥 暂时关闭路径优化功能,避免斜线问题
|
||||
// TODO: 后续重新设计更可靠的路径优化算法
|
||||
/*
|
||||
// 创建路径优化器并执行优化
|
||||
var optimizerConfig = new PathOptimizer.OptimizationConfig
|
||||
{
|
||||
EnableSimplification = true,
|
||||
CollinearTolerance = 0.01
|
||||
};
|
||||
var optimizer = new PathOptimizer(optimizerConfig);
|
||||
var optimizedRoute = optimizer.OptimizePath(tempRoute);
|
||||
|
||||
if (optimizedRoute != null && optimizedRoute.Points.Count > 0)
|
||||
{
|
||||
// 提取优化后的点位置
|
||||
var optimizedPoints = optimizedRoute.Points.Select(p => p.Position).ToList();
|
||||
|
||||
LogManager.Info($"[路径优化] 点数变化:{pathResult.PathPoints.Count} -> {optimizedPoints.Count}");
|
||||
|
||||
// 更新路径结果
|
||||
pathResult.PathPoints = optimizedPoints;
|
||||
}
|
||||
*/
|
||||
|
||||
LogManager.Info($"[路径生成] 使用原始A*算法结果,未进行路径优化,点数: {pathResult.PathPoints.Count}");
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[路径优化] 优化失败,使用原始路径: {ex.Message}", ex);
|
||||
return pathResult; // 出错时返回原始路径
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[高度检测] 🔍 开始检测位置 ({position.X:F2}, {position.Y:F2}, {position.Z:F2}) 的地面高度,通道数={channelItems?.Count() ?? 0}");
|
||||
//LogManager.Info($"[高度检测] 🔍 开始检测位置 ({position.X:F2}, {position.Y:F2}, {position.Z:F2}) 的地面高度,通道数={channelItems?.Count() ?? 0}");
|
||||
|
||||
// 寻找包含该位置的通道
|
||||
var containingChannel = FindContainingChannel(position, channelItems);
|
||||
@ -51,7 +51,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
return position.Z;
|
||||
}
|
||||
|
||||
LogManager.Info($"[高度检测] ✅ 找到包含通道: {containingChannel.DisplayName}");
|
||||
//LogManager.Info($"[高度检测] ✅ 找到包含通道: {containingChannel.DisplayName}");
|
||||
|
||||
// 检查缓存
|
||||
var cacheKey = GenerateCacheKey(containingChannel, position);
|
||||
@ -103,7 +103,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[高度检测] 🔍 开始检测位置 ({position.X:F2}, {position.Y:F2}, {position.Z:F2}) 的顶面高度,通道数={channelItems?.Count() ?? 0}");
|
||||
//LogManager.Info($"[高度检测] 🔍 开始检测位置 ({position.X:F2}, {position.Y:F2}, {position.Z:F2}) 的顶面高度,通道数={channelItems?.Count() ?? 0}");
|
||||
|
||||
// 寻找包含该位置的通道
|
||||
var containingChannel = FindContainingChannel(position, channelItems);
|
||||
@ -113,7 +113,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
return position.Z;
|
||||
}
|
||||
|
||||
LogManager.Info($"[高度检测] ✅ 找到包含通道: {containingChannel.DisplayName}");
|
||||
//LogManager.Info($"[高度检测] ✅ 找到包含通道: {containingChannel.DisplayName}");
|
||||
|
||||
// 检查缓存
|
||||
var cacheKey = GenerateCacheKey(containingChannel, position);
|
||||
@ -172,8 +172,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
return null;
|
||||
}
|
||||
|
||||
LogManager.Debug($"[高度检测] 开始分析通道几何: {channel.DisplayName}");
|
||||
|
||||
// 获取通道的边界框
|
||||
var bounds = channel.Geometry.BoundingBox;
|
||||
if (bounds == null)
|
||||
@ -194,7 +192,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
// 采样通道高度剖面
|
||||
SampleChannelHeightProfile(channel, heightInfo);
|
||||
|
||||
LogManager.Info($"[高度检测] 通道分析完成: 地面高度={heightInfo.FloorHeight:F2}, 顶面高度={heightInfo.CeilingHeight:F2}");
|
||||
return heightInfo;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -218,7 +215,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
if (IsPositionInChannel(position, channel))
|
||||
{
|
||||
LogManager.Debug($"[高度检测] 找到包含位置的通道: {channel.DisplayName}");
|
||||
//LogManager.Debug($"[高度检测] 找到包含位置的通道: {channel.DisplayName}");
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
|
||||
351
src/PathPlanning/PathOptimizer.cs
Normal file
351
src/PathPlanning/PathOptimizer.cs
Normal file
@ -0,0 +1,351 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using NavisworksTransport.Core;
|
||||
|
||||
namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
/// <summary>
|
||||
/// 路径优化器
|
||||
/// 提供多种路径优化算法,包括简化、平滑、避障等
|
||||
/// </summary>
|
||||
public class PathOptimizer
|
||||
{
|
||||
/// <summary>
|
||||
/// 路径优化配置参数
|
||||
/// </summary>
|
||||
public class OptimizationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用路径简化(去除共线点)
|
||||
/// </summary>
|
||||
public bool EnableSimplification { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 共线检测的容差值(米)
|
||||
/// </summary>
|
||||
public double CollinearTolerance { get; set; } = 0.01;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用路径平滑(未来扩展)
|
||||
/// </summary>
|
||||
public bool EnableSmoothing { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 转弯半径(米,未来扩展)
|
||||
/// </summary>
|
||||
public double TurningRadius { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 圆弧分段数(未来扩展)
|
||||
/// </summary>
|
||||
public int ArcSegments { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用碰撞检测验证(未来扩展)
|
||||
/// </summary>
|
||||
public bool EnableCollisionCheck { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆长度(米,未来扩展)
|
||||
/// </summary>
|
||||
public double VehicleLength { get; set; } = 2.0;
|
||||
|
||||
/// <summary>
|
||||
/// 车辆宽度(米,未来扩展)
|
||||
/// </summary>
|
||||
public double VehicleWidth { get; set; } = 1.0;
|
||||
}
|
||||
|
||||
private readonly OptimizationConfig _config;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="config">优化配置,为null时使用默认配置</param>
|
||||
public PathOptimizer(OptimizationConfig config = null)
|
||||
{
|
||||
_config = config ?? new OptimizationConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 优化路径的主入口
|
||||
/// </summary>
|
||||
/// <param name="originalPath">原始路径</param>
|
||||
/// <returns>优化后的路径</returns>
|
||||
public PathRoute OptimizePath(PathRoute originalPath)
|
||||
{
|
||||
if (originalPath == null)
|
||||
{
|
||||
LogManager.Warning("[路径优化] 原始路径为null");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (originalPath.Points.Count <= 2)
|
||||
{
|
||||
LogManager.Info("[路径优化] 路径点数量≤2,无需优化");
|
||||
return originalPath;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
var originalCount = originalPath.Points.Count;
|
||||
|
||||
LogManager.Info($"[路径优化] 开始优化路径:{originalPath.Name},原始点数:{originalCount}");
|
||||
|
||||
// 复制路径点进行优化
|
||||
var optimizedPoints = new List<PathPoint>(originalPath.Points);
|
||||
|
||||
// 1. 基础简化 - 去除共线点
|
||||
if (_config.EnableSimplification)
|
||||
{
|
||||
LogManager.Info("[路径优化] 执行共线点简化");
|
||||
optimizedPoints = SimplifyCollinearPoints(optimizedPoints);
|
||||
LogManager.Info($"[路径优化] 简化完成,点数:{originalCount} -> {optimizedPoints.Count}");
|
||||
}
|
||||
|
||||
// 2. 未来扩展:路径平滑
|
||||
if (_config.EnableSmoothing)
|
||||
{
|
||||
LogManager.Info("[路径优化] 路径平滑功能尚未实现");
|
||||
// optimizedPoints = SmoothPath(optimizedPoints);
|
||||
}
|
||||
|
||||
// 3. 未来扩展:碰撞检测验证
|
||||
if (_config.EnableCollisionCheck)
|
||||
{
|
||||
LogManager.Info("[路径优化] 碰撞检测功能尚未实现");
|
||||
// ValidatePathCollision(optimizedPoints);
|
||||
}
|
||||
|
||||
// 创建优化后的路径
|
||||
var optimizedRoute = CreateOptimizedRoute(originalPath, optimizedPoints);
|
||||
|
||||
var duration = DateTime.Now - startTime;
|
||||
LogManager.Info($"[路径优化] 优化完成,耗时:{duration.TotalMilliseconds:F1}ms,优化率:{(1.0 - (double)optimizedPoints.Count / originalCount) * 100:F1}%");
|
||||
|
||||
return optimizedRoute;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[路径优化] 优化过程发生异常:{ex.Message}", ex);
|
||||
return originalPath; // 发生异常时返回原始路径
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简化共线点(去除直线上的冗余点)
|
||||
/// </summary>
|
||||
/// <param name="points">原始路径点列表</param>
|
||||
/// <returns>简化后的路径点列表</returns>
|
||||
private List<PathPoint> SimplifyCollinearPoints(List<PathPoint> points)
|
||||
{
|
||||
if (points.Count <= 2) return points;
|
||||
|
||||
var simplified = new List<PathPoint>();
|
||||
simplified.Add(points[0]); // 添加起点
|
||||
|
||||
LogManager.Info($"[共线简化] 开始简化,原始点数:{points.Count}");
|
||||
int removedCount = 0;
|
||||
|
||||
// 遍历中间点,只保留转折点
|
||||
for (int i = 1; i < points.Count - 1; i++)
|
||||
{
|
||||
var prevPoint = points[i - 1];
|
||||
var currPoint = points[i];
|
||||
var nextPoint = points[i + 1];
|
||||
|
||||
// 检查是否在同一直线上
|
||||
bool isCollinear = IsCollinear(prevPoint.Position, currPoint.Position, nextPoint.Position);
|
||||
|
||||
if (!isCollinear)
|
||||
{
|
||||
// 这是一个转折点,需要保留
|
||||
simplified.Add(currPoint);
|
||||
LogManager.Debug($"[共线简化] 保留转折点 {i}:{currPoint.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 这是直线上的冗余点,跳过
|
||||
removedCount++;
|
||||
LogManager.Debug($"[共线简化] 移除冗余点 {i}:{currPoint.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
simplified.Add(points[points.Count - 1]); // 添加终点
|
||||
|
||||
LogManager.Info($"[共线简化] 简化完成,移除了 {removedCount} 个冗余点");
|
||||
return simplified;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查三点是否真正共线(只有当三点都在同一条直线上且方向一致时才返回true)
|
||||
/// 🔥 关键修复:严格检查两个线段的方向是否一致,防止在转折点处错误合并
|
||||
/// </summary>
|
||||
/// <param name="p1">第一个点</param>
|
||||
/// <param name="p2">第二个点(中间点)</param>
|
||||
/// <param name="p3">第三个点</param>
|
||||
/// <returns>如果三点在同一直线上且方向一致返回true</returns>
|
||||
private bool IsCollinear(Point3D p1, Point3D p2, Point3D p3)
|
||||
{
|
||||
const double tolerance = 0.1; // 容差值,单位:模型单位
|
||||
|
||||
// 🔥 修复:首先检查Z坐标,确保是2D路径
|
||||
if (Math.Abs(p1.Z - p2.Z) > tolerance || Math.Abs(p2.Z - p3.Z) > tolerance)
|
||||
{
|
||||
LogManager.Debug($"[共线检测] ❌ 拒绝Z方向变化:({p1.X:F3},{p1.Y:F3},{p1.Z:F3}) -> ({p2.X:F3},{p2.Y:F3},{p2.Z:F3}) -> ({p3.X:F3},{p3.Y:F3},{p3.Z:F3})");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 🔥 关键修复:分别检查两个线段的方向
|
||||
// 线段1: p1 -> p2
|
||||
double dx12 = p2.X - p1.X;
|
||||
double dy12 = p2.Y - p1.Y;
|
||||
|
||||
// 线段2: p2 -> p3
|
||||
double dx23 = p3.X - p2.X;
|
||||
double dy23 = p3.Y - p2.Y;
|
||||
|
||||
// 🔥 修复:使用更严格的容差检查真正的重复点(坐标完全相同)
|
||||
const double duplicatePointTolerance = 0.001; // 用很小的值检查真正的重复点
|
||||
bool isSegment1Zero = Math.Abs(dx12) < duplicatePointTolerance && Math.Abs(dy12) < duplicatePointTolerance;
|
||||
bool isSegment2Zero = Math.Abs(dx23) < duplicatePointTolerance && Math.Abs(dy23) < duplicatePointTolerance;
|
||||
|
||||
if (isSegment1Zero || isSegment2Zero)
|
||||
{
|
||||
// 🔥 关键修复:只有在真正重复点时才认为共线
|
||||
LogManager.Debug($"[共线检测] ✅ 包含真正重复点,视为共线:({p1.X:F3},{p1.Y:F3}) -> ({p2.X:F3},{p2.Y:F3}) -> ({p3.X:F3},{p3.Y:F3})");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 🔥 关键修复:严格检查两个线段是否都是水平或都是垂直
|
||||
bool isSegment1Horizontal = Math.Abs(dy12) < tolerance && Math.Abs(dx12) > tolerance;
|
||||
bool isSegment1Vertical = Math.Abs(dx12) < tolerance && Math.Abs(dy12) > tolerance;
|
||||
|
||||
bool isSegment2Horizontal = Math.Abs(dy23) < tolerance && Math.Abs(dx23) > tolerance;
|
||||
bool isSegment2Vertical = Math.Abs(dx23) < tolerance && Math.Abs(dy23) > tolerance;
|
||||
|
||||
// 🔥 核心逻辑:两个线段必须都是同一种类型(都水平或都垂直)
|
||||
if (isSegment1Horizontal && isSegment2Horizontal)
|
||||
{
|
||||
// 检查水平方向是否一致(同向或反向都可以)
|
||||
bool sameDirection = (dx12 * dx23 > 0) || Math.Abs(dx12) < tolerance || Math.Abs(dx23) < tolerance;
|
||||
if (sameDirection)
|
||||
{
|
||||
LogManager.Debug($"[共线检测] ✅ 水平共线:({p1.X:F3},{p1.Y:F3}) -> ({p2.X:F3},{p2.Y:F3}) -> ({p3.X:F3},{p3.Y:F3})");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"[共线检测] ❌ 水平线段方向相反:dx12={dx12:F3}, dx23={dx23:F3}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (isSegment1Vertical && isSegment2Vertical)
|
||||
{
|
||||
// 检查垂直方向是否一致(同向或反向都可以)
|
||||
bool sameDirection = (dy12 * dy23 > 0) || Math.Abs(dy12) < tolerance || Math.Abs(dy23) < tolerance;
|
||||
if (sameDirection)
|
||||
{
|
||||
LogManager.Debug($"[共线检测] ✅ 垂直共线:({p1.X:F3},{p1.Y:F3}) -> ({p2.X:F3},{p2.Y:F3}) -> ({p3.X:F3},{p3.Y:F3})");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"[共线检测] ❌ 垂直线段方向相反:dy12={dy12:F3}, dy23={dy23:F3}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 🔥 关键:不同类型的线段(一个水平一个垂直,或包含斜线)一律拒绝
|
||||
string seg1Type = isSegment1Horizontal ? "水平" : (isSegment1Vertical ? "垂直" : "斜线");
|
||||
string seg2Type = isSegment2Horizontal ? "水平" : (isSegment2Vertical ? "垂直" : "斜线");
|
||||
LogManager.Debug($"[共线检测] ❌ 线段类型不匹配:线段1={seg1Type}({dx12:F3},{dy12:F3}), 线段2={seg2Type}({dx23:F3},{dy23:F3})");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建优化后的路径对象
|
||||
/// </summary>
|
||||
/// <param name="originalPath">原始路径</param>
|
||||
/// <param name="optimizedPoints">优化后的路径点</param>
|
||||
/// <returns>优化后的路径对象</returns>
|
||||
private PathRoute CreateOptimizedRoute(PathRoute originalPath, List<PathPoint> optimizedPoints)
|
||||
{
|
||||
var optimizedRoute = new PathRoute($"{originalPath.Name}_优化")
|
||||
{
|
||||
Id = originalPath.Id,
|
||||
IsComplete = originalPath.IsComplete,
|
||||
OriginalEndPoint = originalPath.OriginalEndPoint,
|
||||
ActualEndPoint = originalPath.ActualEndPoint,
|
||||
CompletionPercentage = originalPath.CompletionPercentage
|
||||
};
|
||||
|
||||
// 重新分配索引和更新点类型
|
||||
for (int i = 0; i < optimizedPoints.Count; i++)
|
||||
{
|
||||
var point = optimizedPoints[i];
|
||||
point.Index = i;
|
||||
|
||||
// 重新确定点类型
|
||||
if (i == 0)
|
||||
point.Type = PathPointType.StartPoint;
|
||||
else if (i == optimizedPoints.Count - 1)
|
||||
point.Type = PathPointType.EndPoint;
|
||||
else
|
||||
point.Type = PathPointType.WayPoint;
|
||||
|
||||
optimizedRoute.Points.Add(point);
|
||||
}
|
||||
|
||||
// 重新计算路径长度
|
||||
optimizedRoute.RecalculateLength();
|
||||
|
||||
return optimizedRoute;
|
||||
}
|
||||
|
||||
#region 未来扩展方法(暂时保留接口)
|
||||
|
||||
/// <summary>
|
||||
/// 路径平滑处理(未来实现)
|
||||
/// </summary>
|
||||
/// <param name="points">路径点列表</param>
|
||||
/// <returns>平滑后的路径点列表</returns>
|
||||
private List<PathPoint> SmoothPath(List<PathPoint> points)
|
||||
{
|
||||
// TODO: 实现贝塞尔曲线或圆弧平滑
|
||||
LogManager.Info("[路径平滑] 功能尚未实现");
|
||||
return points;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在转角处添加圆弧(未来实现)
|
||||
/// </summary>
|
||||
/// <param name="points">路径点列表</param>
|
||||
/// <returns>添加圆弧后的路径点列表</returns>
|
||||
private List<PathPoint> AddTurningArcs(List<PathPoint> points)
|
||||
{
|
||||
// TODO: 在转角处添加圆弧
|
||||
LogManager.Info("[圆弧转弯] 功能尚未实现");
|
||||
return points;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证路径碰撞(未来实现)
|
||||
/// </summary>
|
||||
/// <param name="points">路径点列表</param>
|
||||
/// <returns>是否通过碰撞检测</returns>
|
||||
private bool ValidatePathCollision(List<PathPoint> points)
|
||||
{
|
||||
// TODO: 实现碰撞检测验证
|
||||
LogManager.Info("[碰撞检测] 功能尚未实现");
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 系统管理相关字段
|
||||
private bool _isAutoSaveEnabled = true;
|
||||
private bool _isDebugModeEnabled = false;
|
||||
|
||||
// 网格可视化开关字段
|
||||
private bool _showWalkableGrid = false;
|
||||
private bool _showObstacleGrid = false;
|
||||
private bool _showUnknownGrid = false;
|
||||
private ObservableCollection<string> _logLevels;
|
||||
private string _selectedLogLevel = "Info";
|
||||
private string _logStatus = "日志系统正常";
|
||||
@ -62,6 +67,51 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
set => SetProperty(ref _isDebugModeEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示可通行网格点
|
||||
/// </summary>
|
||||
public bool ShowWalkableGrid
|
||||
{
|
||||
get => _showWalkableGrid;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _showWalkableGrid, value))
|
||||
{
|
||||
OnGridVisualizationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示障碍物网格点
|
||||
/// </summary>
|
||||
public bool ShowObstacleGrid
|
||||
{
|
||||
get => _showObstacleGrid;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _showObstacleGrid, value))
|
||||
{
|
||||
OnGridVisualizationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示未知区域网格点
|
||||
/// </summary>
|
||||
public bool ShowUnknownGrid
|
||||
{
|
||||
get => _showUnknownGrid;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _showUnknownGrid, value))
|
||||
{
|
||||
OnGridVisualizationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志级别集合
|
||||
/// </summary>
|
||||
@ -244,6 +294,68 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网格可视化设置变更事件处理
|
||||
/// </summary>
|
||||
private void OnGridVisualizationChanged()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"网格可视化设置已更改: 通行={ShowWalkableGrid}, 障碍物={ShowObstacleGrid}, 未知={ShowUnknownGrid}");
|
||||
|
||||
// 通知路径规划管理器更新网格可视化
|
||||
var pathPlanningManager = GetPathPlanningManager();
|
||||
if (pathPlanningManager != null)
|
||||
{
|
||||
// 应用新的可视化设置
|
||||
pathPlanningManager.UpdateGridVisualizationSettings(
|
||||
showWalkable: ShowWalkableGrid,
|
||||
showObstacle: ShowObstacleGrid,
|
||||
showUnknown: ShowUnknownGrid);
|
||||
|
||||
SettingsStatus = "网格可视化设置已更新";
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("无法获取路径规划管理器,网格可视化设置可能不会立即生效");
|
||||
SettingsStatus = "网格可视化设置已保存";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"应用网格可视化设置失败: {ex.Message}", ex);
|
||||
SettingsStatus = "网格可视化设置应用失败";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取路径规划管理器实例
|
||||
/// </summary>
|
||||
/// <returns>路径规划管理器或null</returns>
|
||||
private PathPlanningManager GetPathPlanningManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用PathPlanningManager的静态方法获取活动实例
|
||||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||||
if (pathManager != null)
|
||||
{
|
||||
LogManager.Info("成功获取到活动的PathPlanningManager实例");
|
||||
return pathManager;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("当前没有活动的PathPlanningManager实例");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取PathPlanningManager失败: {ex.Message}", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化系统管理设置
|
||||
/// </summary>
|
||||
|
||||
@ -112,6 +112,40 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 网格可视化开关 -->
|
||||
<Grid Margin="0,10,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Content="网格可视化:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
Width="100"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center"
|
||||
Margin="5,0,0,0">
|
||||
<CheckBox Content="通行"
|
||||
IsChecked="{Binding ShowWalkableGrid}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="显示可通行的网格点"/>
|
||||
<CheckBox Content="障碍物"
|
||||
IsChecked="{Binding ShowObstacleGrid}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="显示障碍物网格点"/>
|
||||
<CheckBox Content="未知"
|
||||
IsChecked="{Binding ShowUnknownGrid}"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="显示未知区域网格点"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 状态显示 -->
|
||||
<Label Content="{Binding SettingsStatus}"
|
||||
Style="{StaticResource StatusLabelStyle}"/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user