用API精确计算包围盒的距离,解决多检的问题

This commit is contained in:
tian 2026-01-07 13:50:41 +08:00
parent cbc63809f0
commit f02e5cfc28
2 changed files with 59 additions and 13 deletions

View File

@ -539,9 +539,6 @@ namespace NavisworksTransport.Core.Animation
double yawRadians = ComputeYawOnPath(i, allSampledPoints, edgeIndex, edgeProgress); double yawRadians = ComputeYawOnPath(i, allSampledPoints, edgeIndex, edgeProgress);
// 🔥 调试日志输出framePosition
LogManager.Debug($"[调试] 帧{i}: framePosition=({framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2})");
// 创建帧并检测碰撞 // 创建帧并检测碰撞
var frame = new AnimationFrame var frame = new AnimationFrame
{ {
@ -600,16 +597,9 @@ namespace NavisworksTransport.Core.Animation
var colliderBox = collider.BoundingBox(); var colliderBox = collider.BoundingBox();
// 🔥 调试日志:输出包围盒信息 // 🔥 调试日志:输出包围盒信息
bool intersects = BoundingBoxGeometryUtils.BoundingBoxesIntersectWithTolerance(virtualBoundingBox, colliderBox, _detectionGap); // 使用改进的精确距离检测方法(先检查相交,再计算精确距离)
if (intersects) double preciseDistance = BoundingBoxGeometryUtils.CalculatePreciseDistance(virtualBoundingBox, colliderBox);
{ bool intersects = preciseDistance <= _detectionGap;
double distanceX = Math.Max(0, Math.Max(virtualBoundingBox.Min.X - colliderBox.Max.X, colliderBox.Min.X - virtualBoundingBox.Max.X));
double distanceY = Math.Max(0, Math.Max(virtualBoundingBox.Min.Y - colliderBox.Max.Y, colliderBox.Min.Y - virtualBoundingBox.Max.Y));
double distanceZ = Math.Max(0, Math.Max(virtualBoundingBox.Min.Z - colliderBox.Max.Z, colliderBox.Min.Z - virtualBoundingBox.Max.Z));
double minDistance = Math.Max(distanceX, Math.Max(distanceY, distanceZ));
LogManager.Debug($"[碰撞检测] 帧{i}: 车辆包围盒=[({virtualBoundingBox.Min.X:F2},{virtualBoundingBox.Min.Y:F2},{virtualBoundingBox.Min.Z:F2})-({virtualBoundingBox.Max.X:F2},{virtualBoundingBox.Max.Y:F2},{virtualBoundingBox.Max.Z:F2})], 物体={collider.DisplayName}, 包围盒=[({colliderBox.Min.X:F2},{colliderBox.Min.Y:F2},{colliderBox.Min.Z:F2})-({colliderBox.Max.X:F2},{colliderBox.Max.Y:F2},{colliderBox.Max.Z:F2})], 最小距离={minDistance:F3}m, 检测间隙={_detectionGap:F3}m");
}
if (intersects) if (intersects)
{ {

View File

@ -177,6 +177,62 @@ namespace NavisworksTransport.Utils
box1.Min.Z <= box2.Max.Z && box1.Max.Z >= box2.Min.Z; box1.Min.Z <= box2.Max.Z && box1.Max.Z >= box2.Min.Z;
} }
/// <summary>
/// 使用ClosestPoint方法计算两个包围盒之间的精确距离
/// 这种方法比简单的包围盒相交检测更精确可以避免AABB扩大导致的误报
/// </summary>
/// <param name="box1">第一个包围盒</param>
/// <param name="box2">第二个包围盒</param>
/// <returns>两个包围盒之间的精确距离</returns>
public static double CalculatePreciseDistance(BoundingBox3D box1, BoundingBox3D box2)
{
try
{
// 先检查包围盒是否相交
bool intersects = box1.Intersects(box2);
if (intersects)
{
return 0.0;
}
// 如果不相交使用ClosestPoint方法计算精确距离
// 计算box1上距离box2最近的点
Point3D closestPointOnBox1 = box1.ClosestPoint(box2.Center);
// 计算box2上距离closestPointOnBox1最近的点
Point3D closestPointOnBox2 = box2.ClosestPoint(closestPointOnBox1);
// 计算两个最近点之间的距离
double dx = closestPointOnBox1.X - closestPointOnBox2.X;
double dy = closestPointOnBox1.Y - closestPointOnBox2.Y;
double dz = closestPointOnBox1.Z - closestPointOnBox2.Z;
double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);
return distance;
}
catch (Exception ex)
{
// API调用失败记录错误并抛出异常
LogManager.Error($"[CalculatePreciseDistance] API调用失败: {ex.Message}");
throw new InvalidOperationException($"CalculatePreciseDistance API调用失败: {ex.Message}", ex);
}
}
/// <summary>
/// 使用ClosestPoint方法检查两个包围盒是否在容差范围内相交
/// 这种方法比简单的包围盒相交检测更精确可以避免AABB扩大导致的误报
/// </summary>
/// <param name="box1">第一个包围盒</param>
/// <param name="box2">第二个包围盒</param>
/// <param name="tolerance">容差值</param>
/// <returns>如果包围盒在容差范围内相交则返回true</returns>
public static bool BoundingBoxesIntersectWithTolerancePrecise(BoundingBox3D box1, BoundingBox3D box2, double tolerance)
{
double preciseDistance = CalculatePreciseDistance(box1, box2);
return preciseDistance <= tolerance;
}
/// <summary> /// <summary>
/// 获取包围盒的中心点 /// 获取包围盒的中心点