修复路径点插入位置问题,新路径点现在会插入到预览连线显示的正确位置
1. 在PathPlanningManager中添加_previewInsertIndex字段保存预览插入索引 2. 添加FindNearestLineSegmentWithIndex等方法计算最近线段和插入位置 3. 修改SetPreviewPoint方法,在设置预览点时计算并保存插入索引 4. 修改ConfirmPreviewPoint方法,使用Insert()而不是Add()进行插入操作 5. 修改ClearPreviewPoint方法,清除预览时也清除保存的插入索引 问题:之前预览连线工作正常能显示正确插入位置,但确认添加时新路径点被错误地添加到路径末尾 解决:现在新路径点会插入到预览时计算出的正确位置,确保路径点顺序符合用户期望 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1e046e1e4d
commit
b7cbc64dd4
@ -49,6 +49,7 @@ namespace NavisworksTransport
|
||||
// 预览点管理
|
||||
private PathPoint _previewPoint = null;
|
||||
private bool _isPreviewMode = false;
|
||||
private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前是否在预览模式
|
||||
@ -1418,6 +1419,19 @@ namespace NavisworksTransport
|
||||
: PathPointType.WayPoint;
|
||||
}
|
||||
|
||||
// 计算预览点应该插入的位置
|
||||
_previewInsertIndex = -1; // 重置插入索引
|
||||
if (CurrentRoute.Points.Count >= 2)
|
||||
{
|
||||
// 如果路径中有至少2个点,计算最佳插入位置
|
||||
var nearestSegment = FindNearestLineSegmentWithIndex(worldPoint, CurrentRoute.Points.ToList());
|
||||
if (nearestSegment.HasValue)
|
||||
{
|
||||
_previewInsertIndex = nearestSegment.Value.insertIndex;
|
||||
LogManager.Info($"预览点计算出插入索引: {_previewInsertIndex},位于 {nearestSegment.Value.prevPoint.Name} 和 {nearestSegment.Value.nextPoint.Name} 之间");
|
||||
}
|
||||
}
|
||||
|
||||
// 创建预览点(不添加到路径中)
|
||||
_previewPoint = new PathPoint
|
||||
{
|
||||
@ -1427,13 +1441,20 @@ namespace NavisworksTransport
|
||||
};
|
||||
|
||||
_isPreviewMode = true;
|
||||
LogManager.Info($"预览点已设置: {_previewPoint.Name}, 位置: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2})");
|
||||
LogManager.Info($"预览点已设置: {_previewPoint.Name}, 位置: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2}), 插入索引: {_previewInsertIndex}");
|
||||
|
||||
// 绘制预览点可视化(灰色)
|
||||
try
|
||||
{
|
||||
DrawPreviewPointVisualization(_previewPoint);
|
||||
LogManager.Info($"预览点3D可视化已更新: {_previewPoint.Name}");
|
||||
|
||||
// 如果路径中有足够的点,绘制预览连线
|
||||
if (CurrentRoute.Points.Count >= 2)
|
||||
{
|
||||
DrawPreviewLinesVisualization(_previewPoint, CurrentRoute.Points.ToList());
|
||||
LogManager.Info($"预览连线已绘制: {_previewPoint.Name}");
|
||||
}
|
||||
}
|
||||
catch (Exception renderEx)
|
||||
{
|
||||
@ -1477,9 +1498,19 @@ namespace NavisworksTransport
|
||||
Type = _previewPoint.Type
|
||||
};
|
||||
|
||||
// 添加到当前路径
|
||||
CurrentRoute.Points.Add(confirmPoint);
|
||||
LogManager.Info($"路径点已确认添加: {confirmPoint.Name}, 位置: ({confirmPoint.Position.X:F2}, {confirmPoint.Position.Y:F2}, {confirmPoint.Position.Z:F2})");
|
||||
// 根据保存的插入索引决定添加方式
|
||||
if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count)
|
||||
{
|
||||
// 在指定位置插入路径点
|
||||
CurrentRoute.Points.Insert(_previewInsertIndex, confirmPoint);
|
||||
LogManager.Info($"路径点已插入到索引 {_previewInsertIndex}: {confirmPoint.Name}, 位置: ({confirmPoint.Position.X:F2}, {confirmPoint.Position.Y:F2}, {confirmPoint.Position.Z:F2})");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果没有有效的插入索引,添加到末尾(原来的行为)
|
||||
CurrentRoute.Points.Add(confirmPoint);
|
||||
LogManager.Info($"路径点已添加到末尾: {confirmPoint.Name}, 位置: ({confirmPoint.Position.X:F2}, {confirmPoint.Position.Y:F2}, {confirmPoint.Position.Z:F2})");
|
||||
}
|
||||
|
||||
// 清除预览状态
|
||||
ClearPreviewPoint();
|
||||
@ -1532,6 +1563,7 @@ namespace NavisworksTransport
|
||||
|
||||
_previewPoint = null;
|
||||
_isPreviewMode = false;
|
||||
_previewInsertIndex = -1; // 清除保存的插入索引
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1551,6 +1583,21 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制预览连线的3D可视化(灰色)
|
||||
/// </summary>
|
||||
/// <param name="previewPoint">预览点</param>
|
||||
/// <param name="pathPoints">当前路径点列表</param>
|
||||
private void DrawPreviewLinesVisualization(PathPoint previewPoint, List<PathPoint> pathPoints)
|
||||
{
|
||||
if (_renderPlugin != null && previewPoint != null && pathPoints != null)
|
||||
{
|
||||
// 绘制预览连线
|
||||
_renderPlugin.RenderPreviewLines(previewPoint, pathPoints);
|
||||
LogManager.Info($"预览连线可视化已绘制: {previewPoint.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除预览点可视化
|
||||
/// </summary>
|
||||
@ -2642,6 +2689,104 @@ namespace NavisworksTransport
|
||||
|
||||
#endregion
|
||||
|
||||
#region 预览插入位置计算方法
|
||||
|
||||
/// <summary>
|
||||
/// 查找预览点应该插入的最近线段和插入索引
|
||||
/// </summary>
|
||||
/// <param name="previewPosition">预览点位置</param>
|
||||
/// <param name="pathPoints">路径点列表</param>
|
||||
/// <returns>最近线段的前后两点以及插入索引,未找到时返回null</returns>
|
||||
private (PathPoint prevPoint, PathPoint nextPoint, int insertIndex)? FindNearestLineSegmentWithIndex(Point3D previewPosition, List<PathPoint> pathPoints)
|
||||
{
|
||||
if (pathPoints == null || pathPoints.Count < 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 对路径点进行排序(按添加顺序,即列表中的索引)
|
||||
var sortedPoints = pathPoints.ToList();
|
||||
|
||||
double minDistance = double.MaxValue;
|
||||
(PathPoint prevPoint, PathPoint nextPoint, int insertIndex)? nearestSegment = null;
|
||||
|
||||
// 遍历相邻的路径点对,找到距离预览点最近的线段
|
||||
for (int i = 0; i < sortedPoints.Count - 1; i++)
|
||||
{
|
||||
var currentPoint = sortedPoints[i];
|
||||
var nextPoint = sortedPoints[i + 1];
|
||||
|
||||
// 计算预览点到线段的距离
|
||||
var distance = CalculatePointToLineSegmentDistance(previewPosition, currentPoint.Position, nextPoint.Position);
|
||||
|
||||
if (distance < minDistance)
|
||||
{
|
||||
minDistance = distance;
|
||||
// 插入索引应该是nextPoint的索引位置,这样新点会插入到currentPoint和nextPoint之间
|
||||
nearestSegment = (currentPoint, nextPoint, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return nearestSegment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算点到线段的最短距离
|
||||
/// </summary>
|
||||
/// <param name="point">目标点</param>
|
||||
/// <param name="lineStart">线段起点</param>
|
||||
/// <param name="lineEnd">线段终点</param>
|
||||
/// <returns>最短距离</returns>
|
||||
private double CalculatePointToLineSegmentDistance(Point3D point, Point3D lineStart, Point3D lineEnd)
|
||||
{
|
||||
// 线段向量
|
||||
var lineVector = new Point3D(lineEnd.X - lineStart.X, lineEnd.Y - lineStart.Y, lineEnd.Z - lineStart.Z);
|
||||
|
||||
// 点到线段起点的向量
|
||||
var pointVector = new Point3D(point.X - lineStart.X, point.Y - lineStart.Y, point.Z - lineStart.Z);
|
||||
|
||||
// 计算线段长度的平方
|
||||
var lineLengthSquared = lineVector.X * lineVector.X + lineVector.Y * lineVector.Y + lineVector.Z * lineVector.Z;
|
||||
|
||||
if (lineLengthSquared == 0)
|
||||
{
|
||||
// 线段退化为点,返回点到点的距离
|
||||
return CalculateDistance(point, lineStart);
|
||||
}
|
||||
|
||||
// 计算投影参数t
|
||||
var t = (pointVector.X * lineVector.X + pointVector.Y * lineVector.Y + pointVector.Z * lineVector.Z) / lineLengthSquared;
|
||||
|
||||
// 将t限制在[0,1]范围内
|
||||
t = Math.Max(0, Math.Min(1, t));
|
||||
|
||||
// 计算线段上最近点
|
||||
var closestPoint = new Point3D(
|
||||
lineStart.X + t * lineVector.X,
|
||||
lineStart.Y + t * lineVector.Y,
|
||||
lineStart.Z + t * lineVector.Z
|
||||
);
|
||||
|
||||
// 返回点到最近点的距离
|
||||
return CalculateDistance(point, closestPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两点间距离
|
||||
/// </summary>
|
||||
/// <param name="point1">第一个点</param>
|
||||
/// <param name="point2">第二个点</param>
|
||||
/// <returns>两点间距离</returns>
|
||||
private double CalculateDistance(Point3D point1, Point3D point2)
|
||||
{
|
||||
var dx = point1.X - point2.X;
|
||||
var dy = point1.Y - point2.Y;
|
||||
var dz = point1.Z - point2.Z;
|
||||
return Math.Sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 静态方法
|
||||
|
||||
/// <summary>
|
||||
|
||||
46
test_insert_position.md
Normal file
46
test_insert_position.md
Normal file
@ -0,0 +1,46 @@
|
||||
# 路径点插入位置修复测试
|
||||
|
||||
## 问题描述
|
||||
修复了预览连线功能工作正常,但确认添加路径点时,新的路径点被错误地添加到路径末尾,而不是插入到预览时计算出来的正确位置的问题。
|
||||
|
||||
## 修改内容
|
||||
|
||||
### 1. 在 PathPlanningManager 中添加字段保存预览插入的索引位置
|
||||
```csharp
|
||||
private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置
|
||||
```
|
||||
|
||||
### 2. 添加了查找最近线段的方法
|
||||
- `FindNearestLineSegmentWithIndex()` - 查找最近线段并返回插入索引
|
||||
- `CalculatePointToLineSegmentDistance()` - 计算点到线段距离
|
||||
- `CalculateDistance()` - 计算两点间距离
|
||||
|
||||
### 3. 修改 SetPreviewPoint 方法
|
||||
- 在设置预览点时,计算并保存最佳插入位置索引
|
||||
- 当路径中有至少2个点时,调用 `FindNearestLineSegmentWithIndex()` 计算插入位置
|
||||
|
||||
### 4. 修改 ConfirmPreviewPoint 方法
|
||||
- 使用保存的 `_previewInsertIndex` 进行 `Insert()` 操作,而不是 `Add()`
|
||||
- 如果没有有效插入索引,则回退到原来的添加到末尾的行为
|
||||
|
||||
### 5. 修改 ClearPreviewPoint 方法
|
||||
- 清除预览时也清除保存的插入索引
|
||||
|
||||
## 测试步骤
|
||||
1. 创建新路径,添加至少2个路径点
|
||||
2. 启用添加路径点模式
|
||||
3. 将鼠标移动到两个现有路径点之间的位置
|
||||
4. 观察预览连线是否正确显示插入位置
|
||||
5. 点击确认添加路径点
|
||||
6. 验证新路径点是否插入到预览显示的正确位置,而不是路径末尾
|
||||
|
||||
## 预期结果
|
||||
- 预览连线正确显示新路径点应该插入的位置
|
||||
- 确认添加时,新路径点插入到预览时计算的正确位置
|
||||
- 路径点顺序符合用户的期望
|
||||
|
||||
## 技术细节
|
||||
- 插入索引的计算基于点到线段的最短距离
|
||||
- 使用了几何算法计算点到线段的垂直距离
|
||||
- 插入索引是最近线段的第二个点的索引位置
|
||||
- 例如:如果最近线段是点1到点2,新点应该插入到索引2的位置
|
||||
Loading…
Reference in New Issue
Block a user