Clarify ground tracked-point semantics
This commit is contained in:
parent
348b3a75bf
commit
8a7563a4fe
10
AGENTS.md
10
AGENTS.md
@ -296,6 +296,16 @@ var rotation = new Rotation3D(qw, qx, qy, qz); // 错误
|
|||||||
- 走平面姿态链
|
- 走平面姿态链
|
||||||
- 已禁止偷偷退回旧 `yaw` 方案
|
- 已禁止偷偷退回旧 `yaw` 方案
|
||||||
- 起点、逐帧、终点、通行空间,必须共享同一套尺寸语义
|
- 起点、逐帧、终点、通行空间,必须共享同一套尺寸语义
|
||||||
|
- `Ground + 真实物体` 的业务跟踪点固定为**原始包围盒中心**
|
||||||
|
- 旋转后的实时 `BoundingBox.Center` 只允许用于:
|
||||||
|
- 诊断旋转后漂移
|
||||||
|
- 计算当帧补偿
|
||||||
|
- 校验补偿结果
|
||||||
|
- 不允许把实时 `BoundingBox.Center` 直接当成:
|
||||||
|
- 起点目标跟踪点
|
||||||
|
- 逐帧业务跟踪点
|
||||||
|
- 碰撞记录主语义跟踪点
|
||||||
|
- 如果 `Ground` 出现“起点正确但越走越偏”或“起点偏了但拐弯后偏差反而减小”,优先检查是否把实时包围盒中心误当成了业务跟踪点
|
||||||
|
|
||||||
#### Rail
|
#### Rail
|
||||||
|
|
||||||
|
|||||||
@ -149,6 +149,23 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
|||||||
Assert.IsFalse(PathAnimationManager.ShouldUseRealObjectOverrideRotation(false));
|
Assert.IsFalse(PathAnimationManager.ShouldUseRealObjectOverrideRotation(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition_ShouldEnableOnlyForGroundRealObjects()
|
||||||
|
{
|
||||||
|
Assert.IsTrue(PathAnimationManager.ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
PathType.Ground,
|
||||||
|
isRealObjectMode: true));
|
||||||
|
Assert.IsFalse(PathAnimationManager.ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
PathType.Ground,
|
||||||
|
isRealObjectMode: false));
|
||||||
|
Assert.IsFalse(PathAnimationManager.ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
PathType.Hoisting,
|
||||||
|
isRealObjectMode: true));
|
||||||
|
Assert.IsFalse(PathAnimationManager.ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
PathType.Rail,
|
||||||
|
isRealObjectMode: true));
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ResolveHoistingPoseSourceLabel_ShouldDescribeCachedBasePose()
|
public void ResolveHoistingPoseSourceLabel_ShouldDescribeCachedBasePose()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -111,8 +111,19 @@
|
|||||||
|
|
||||||
- `AnimatedObjectTrackedPosition` 的唯一语义:
|
- `AnimatedObjectTrackedPosition` 的唯一语义:
|
||||||
- 当前动画主链路使用的跟踪点位置。
|
- 当前动画主链路使用的跟踪点位置。
|
||||||
- 当前主链路已经切到:
|
- `Ground + 真实物体` 当前必须明确区分两类“中心”:
|
||||||
- 几何中心跟踪。
|
- 业务跟踪点应固定为物体**原始包围盒中心**
|
||||||
|
- 不是旋转后的实时包围盒中心
|
||||||
|
- 实时包围盒中心的用途仅限于:
|
||||||
|
- 诊断旋转后漂移
|
||||||
|
- 计算当帧补偿
|
||||||
|
- 验证补偿结果
|
||||||
|
- 不允许把实时包围盒中心直接回写成 `Ground` 路径的业务跟踪点定义。
|
||||||
|
- 这条规则的直接影响范围包括:
|
||||||
|
- 起点落位
|
||||||
|
- 逐帧补偿
|
||||||
|
- 动画日志
|
||||||
|
- 碰撞与结果记录语义
|
||||||
- 如果后续动画跟踪点再变,数据库和碰撞结果语义必须同步更新。
|
- 如果后续动画跟踪点再变,数据库和碰撞结果语义必须同步更新。
|
||||||
|
|
||||||
### 4.4 虚拟物体资源
|
### 4.4 虚拟物体资源
|
||||||
|
|||||||
@ -186,7 +186,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
|
|
||||||
private Transform3D _originalTransform;
|
private Transform3D _originalTransform;
|
||||||
private Point3D _originalCenter; // 存储部件的原始中心位置
|
private Point3D _originalCenter; // 存储部件的原始中心位置
|
||||||
private Point3D _trackedPosition; // 动画管理器内部跟踪的位置状态,不等于宿主即时读回位置
|
private Point3D _trackedPosition; // 动画管理器内部业务跟踪点,不等于宿主即时读回的实时包围盒中心
|
||||||
private AnimationState _currentState = AnimationState.Idle;
|
private AnimationState _currentState = AnimationState.Idle;
|
||||||
private double _pausedProgress = 0.0; // 暂停时的进度(0-1之间)
|
private double _pausedProgress = 0.0; // 暂停时的进度(0-1之间)
|
||||||
private double _currentYaw = 0.0; // 当前偏航角(弧度)
|
private double _currentYaw = 0.0; // 当前偏航角(弧度)
|
||||||
@ -484,7 +484,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
}
|
}
|
||||||
|
|
||||||
var originalBoundingBox = objectToRestore.BoundingBox();
|
var originalBoundingBox = objectToRestore.BoundingBox();
|
||||||
_trackedPosition = GetTrackedObjectPosition(objectToRestore);
|
_trackedPosition = ResolveInitialBusinessTrackedPosition(objectToRestore);
|
||||||
|
|
||||||
string objectName = isVirtual ? "虚拟物体" : objectToRestore.DisplayName;
|
string objectName = isVirtual ? "虚拟物体" : objectToRestore.DisplayName;
|
||||||
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
||||||
@ -525,7 +525,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
{
|
{
|
||||||
_originalTransform = animatedObject.Transform;
|
_originalTransform = animatedObject.Transform;
|
||||||
_originalCenter = animatedObject.BoundingBox().Center;
|
_originalCenter = animatedObject.BoundingBox().Center;
|
||||||
_trackedPosition = GetTrackedObjectPosition(animatedObject);
|
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
|
||||||
SyncTrackedRotationToObjectReference(animatedObject, isVirtualObject: false);
|
SyncTrackedRotationToObjectReference(animatedObject, isVirtualObject: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,7 +689,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
ResetRealObjectReferenceRotation();
|
ResetRealObjectReferenceRotation();
|
||||||
_originalTransform = animatedObject.Transform;
|
_originalTransform = animatedObject.Transform;
|
||||||
_originalCenter = animatedObject.BoundingBox().Center;
|
_originalCenter = animatedObject.BoundingBox().Center;
|
||||||
_trackedPosition = GetTrackedObjectPosition(animatedObject);
|
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
|
||||||
if (isVirtualObject)
|
if (isVirtualObject)
|
||||||
{
|
{
|
||||||
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
||||||
@ -808,12 +808,12 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
UpdateObjectPosition(startPosition, planarRotation);
|
UpdateObjectPosition(startPosition, planarRotation);
|
||||||
LogManager.Info("[移动到起点] 地面/吊装路径已应用完整三维姿态");
|
LogManager.Info("[移动到起点] 地面/吊装路径已应用完整三维姿态");
|
||||||
|
|
||||||
var startAppliedPoint = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
var startAppliedPoint = GetLiveBoundingBoxCenter(CurrentControlledObject ?? _animatedObject);
|
||||||
LogManager.Info(
|
LogManager.Info(
|
||||||
$"[路径起点诊断] 起点应用后实际trackedPoint=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), " +
|
$"[路径起点诊断] 起点应用后实际包围盒中心=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), " +
|
||||||
$"相对目标偏差=({startAppliedPoint.X - startPosition.X:F3},{startAppliedPoint.Y - startPosition.Y:F3},{startAppliedPoint.Z - startPosition.Z:F3})");
|
$"相对目标偏差=({startAppliedPoint.X - startPosition.X:F3},{startAppliedPoint.Y - startPosition.Y:F3},{startAppliedPoint.Z - startPosition.Z:F3})");
|
||||||
|
|
||||||
// 🔥 起点不再进行二次补偿,旋转偏移由 MoveItemIncrementallyToTrackedPositionAndRotation 内部处理
|
// Ground 起点不再进行二次补偿;业务跟踪点语义由 _trackedPosition 主链负责
|
||||||
if (IsRealObjectMode && _route.PathType == PathType.Ground)
|
if (IsRealObjectMode && _route.PathType == PathType.Ground)
|
||||||
{
|
{
|
||||||
var startOffset = new Vector3D(
|
var startOffset = new Vector3D(
|
||||||
@ -875,9 +875,9 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
// 使用 UpdateObjectPosition 统一处理移动和旋转
|
// 使用 UpdateObjectPosition 统一处理移动和旋转
|
||||||
UpdateObjectPosition(startPosition, yaw);
|
UpdateObjectPosition(startPosition, yaw);
|
||||||
|
|
||||||
var startAppliedPoint = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
var startAppliedPoint = GetLiveBoundingBoxCenter(CurrentControlledObject ?? _animatedObject);
|
||||||
LogManager.Info(
|
LogManager.Info(
|
||||||
$"[路径起点诊断] 起点应用后实际trackedPoint=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), " +
|
$"[路径起点诊断] 起点应用后实际包围盒中心=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), " +
|
||||||
$"相对目标偏差=({startAppliedPoint.X - startPosition.X:F3},{startAppliedPoint.Y - startPosition.Y:F3},{startAppliedPoint.Z - startPosition.Z:F3})");
|
$"相对目标偏差=({startAppliedPoint.X - startPosition.X:F3},{startAppliedPoint.Y - startPosition.Y:F3},{startAppliedPoint.Z - startPosition.Z:F3})");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +922,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
ResetRealObjectReferenceRotation();
|
ResetRealObjectReferenceRotation();
|
||||||
_originalTransform = animatedObject.Transform;
|
_originalTransform = animatedObject.Transform;
|
||||||
_originalCenter = animatedObject.BoundingBox().Center;
|
_originalCenter = animatedObject.BoundingBox().Center;
|
||||||
_trackedPosition = GetTrackedObjectPosition(animatedObject);
|
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
|
||||||
if (isVirtualObject)
|
if (isVirtualObject)
|
||||||
{
|
{
|
||||||
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
||||||
@ -989,11 +989,11 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
||||||
_hasGroundRealObjectStartCompensation = false;
|
_hasGroundRealObjectStartCompensation = false;
|
||||||
|
|
||||||
var startAppliedPoint = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
var startAppliedPoint = GetLiveBoundingBoxCenter(CurrentControlledObject ?? _animatedObject);
|
||||||
LogManager.Info(
|
LogManager.Info(
|
||||||
$"[平移到起点] 已按终点原始位姿残差搬运到起点: 路径point0=({pathStartPoint.X:F3},{pathStartPoint.Y:F3},{pathStartPoint.Z:F3}), " +
|
$"[平移到起点] 已按终点原始位姿残差搬运到起点: 路径point0=({pathStartPoint.X:F3},{pathStartPoint.Y:F3},{pathStartPoint.Z:F3}), " +
|
||||||
$"目标trackedPoint=({startPosition.X:F3},{startPosition.Y:F3},{startPosition.Z:F3}), " +
|
$"目标trackedPoint=({startPosition.X:F3},{startPosition.Y:F3},{startPosition.Z:F3}), " +
|
||||||
$"实际trackedPoint=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), 路径类型={_route.PathType.GetDisplayName()}");
|
$"实际包围盒中心=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), 路径类型={_route.PathType.GetDisplayName()}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -2786,8 +2786,11 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var actualHostPosition = GetTrackedObjectPosition(controlledObject);
|
var actualHostPosition = GetLiveBoundingBoxCenter(controlledObject);
|
||||||
currentPositionForTransform = actualHostPosition;
|
if (!(IsRealObjectMode && _route?.PathType == PathType.Ground))
|
||||||
|
{
|
||||||
|
currentPositionForTransform = actualHostPosition;
|
||||||
|
}
|
||||||
LogManager.Info(
|
LogManager.Info(
|
||||||
$"[动画姿态入口] {controlledObject.DisplayName} 宿主即时读回点=({actualHostPosition.X:F3},{actualHostPosition.Y:F3},{actualHostPosition.Z:F3})");
|
$"[动画姿态入口] {controlledObject.DisplayName} 宿主即时读回点=({actualHostPosition.X:F3},{actualHostPosition.Y:F3},{actualHostPosition.Z:F3})");
|
||||||
|
|
||||||
@ -2830,26 +2833,12 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
$"Y=({targetLinear.Get(0, 1):F4},{targetLinear.Get(1, 1):F4},{targetLinear.Get(2, 1):F4}), " +
|
$"Y=({targetLinear.Get(0, 1):F4},{targetLinear.Get(1, 1):F4},{targetLinear.Get(2, 1):F4}), " +
|
||||||
$"Z=({targetLinear.Get(0, 2):F4},{targetLinear.Get(1, 2):F4},{targetLinear.Get(2, 2):F4})");
|
$"Z=({targetLinear.Get(0, 2):F4},{targetLinear.Get(1, 2):F4},{targetLinear.Get(2, 2):F4})");
|
||||||
|
|
||||||
// 🔥 Ground 路径使用带旋转偏移补偿的新方法
|
ModelItemTransformHelper.MoveItemIncrementallyToPositionAndRotation(
|
||||||
// Rail/Hoisting 保持原行为
|
controlledObject,
|
||||||
if (_route?.PathType == PathType.Ground && IsRealObjectMode)
|
currentPositionForTransform,
|
||||||
{
|
currentRotation,
|
||||||
ModelItemTransformHelper.MoveItemIncrementallyToTrackedPositionAndRotation(
|
appliedTargetPosition,
|
||||||
controlledObject,
|
appliedTargetRotation);
|
||||||
currentPositionForTransform,
|
|
||||||
currentRotation,
|
|
||||||
appliedTargetPosition,
|
|
||||||
appliedTargetRotation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModelItemTransformHelper.MoveItemIncrementallyToPositionAndRotation(
|
|
||||||
controlledObject,
|
|
||||||
currentPositionForTransform,
|
|
||||||
currentRotation,
|
|
||||||
appliedTargetPosition,
|
|
||||||
appliedTargetRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
_trackedPosition = appliedTargetPosition;
|
_trackedPosition = appliedTargetPosition;
|
||||||
_trackedRotation = appliedTargetRotation;
|
_trackedRotation = appliedTargetRotation;
|
||||||
@ -2858,7 +2847,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
|
|
||||||
if (isRailRealObject)
|
if (isRailRealObject)
|
||||||
{
|
{
|
||||||
Point3D hostActualAfter = GetTrackedObjectPosition(controlledObject);
|
Point3D hostActualAfter = GetLiveBoundingBoxCenter(controlledObject);
|
||||||
LogManager.Debug(
|
LogManager.Debug(
|
||||||
$"[Rail姿态应用] 宿主最终跟踪中心=({hostActualAfter.X:F3},{hostActualAfter.Y:F3},{hostActualAfter.Z:F3}), " +
|
$"[Rail姿态应用] 宿主最终跟踪中心=({hostActualAfter.X:F3},{hostActualAfter.Y:F3},{hostActualAfter.Z:F3}), " +
|
||||||
$"目标跟踪中心=({newPosition.X:F3},{newPosition.Y:F3},{newPosition.Z:F3}), " +
|
$"目标跟踪中心=({newPosition.X:F3},{newPosition.Y:F3},{newPosition.Z:F3}), " +
|
||||||
@ -3797,7 +3786,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
{
|
{
|
||||||
_originalTransform = animatedObject.Transform;
|
_originalTransform = animatedObject.Transform;
|
||||||
_originalCenter = animatedObject.BoundingBox().Center;
|
_originalCenter = animatedObject.BoundingBox().Center;
|
||||||
_trackedPosition = GetTrackedObjectPosition(animatedObject);
|
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
|
||||||
|
|
||||||
// 保持当前的 _currentYaw(因为物体可能已经被 MoveObjectToPathStart 旋转)
|
// 保持当前的 _currentYaw(因为物体可能已经被 MoveObjectToPathStart 旋转)
|
||||||
// 不要从 Transform 中提取,因为 Transform 返回的是原始值,不是当前值
|
// 不要从 Transform 中提取,因为 Transform 返回的是原始值,不是当前值
|
||||||
@ -3814,7 +3803,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
LogManager.Info($"[CreateAnimation] 动画已创建,状态设置为Ready");
|
LogManager.Info($"[CreateAnimation] 动画已创建,状态设置为Ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Point3D GetTrackedObjectPosition(ModelItem item)
|
private Point3D GetLiveBoundingBoxCenter(ModelItem item)
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
@ -3825,6 +3814,24 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return bounds?.Center ?? new Point3D(0, 0, 0);
|
return bounds?.Center ?? new Point3D(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Point3D ResolveInitialBusinessTrackedPosition(ModelItem item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return new Point3D(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
_route?.PathType ?? PathType.Ground,
|
||||||
|
IsRealObjectMode) &&
|
||||||
|
_originalCenter != null)
|
||||||
|
{
|
||||||
|
return _originalCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetLiveBoundingBoxCenter(item);
|
||||||
|
}
|
||||||
|
|
||||||
private Point3D ResolveGroundTrackedCenter(Point3D groundContactPoint, double objectHeight)
|
private Point3D ResolveGroundTrackedCenter(Point3D groundContactPoint, double objectHeight)
|
||||||
{
|
{
|
||||||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||||||
@ -3892,7 +3899,7 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point3D currentTrackedCenter = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
Point3D currentTrackedCenter = GetLiveBoundingBoxCenter(CurrentControlledObject ?? _animatedObject);
|
||||||
Point3D semanticTrackedCenter = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
|
Point3D semanticTrackedCenter = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
|
||||||
_route,
|
_route,
|
||||||
referencePoint,
|
referencePoint,
|
||||||
@ -3979,6 +3986,13 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return isRealObjectMode;
|
return isRealObjectMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool ShouldUseOriginalBoundingBoxCenterForBusinessTrackedPosition(
|
||||||
|
PathType pathType,
|
||||||
|
bool isRealObjectMode)
|
||||||
|
{
|
||||||
|
return isRealObjectMode && pathType == PathType.Ground;
|
||||||
|
}
|
||||||
|
|
||||||
private void SyncTrackedRotationToDisplayedPose(ModelItem sourceObject)
|
private void SyncTrackedRotationToDisplayedPose(ModelItem sourceObject)
|
||||||
{
|
{
|
||||||
if (sourceObject == null)
|
if (sourceObject == null)
|
||||||
@ -5584,14 +5598,14 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 专门用于Ground路径动画帧播放。使用 _trackedPosition 作为当前位置,不重新读取包围盒。
|
/// 专门用于Ground路径动画帧播放。使用业务跟踪点 _trackedPosition 作为当前位置,不读取实时包围盒中心回写主链。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ApplyGroundAnimationFrame(Point3D targetPosition, Rotation3D targetRotation)
|
private void ApplyGroundAnimationFrame(Point3D targetPosition, Rotation3D targetRotation)
|
||||||
{
|
{
|
||||||
var controlledObject = CurrentControlledObject;
|
var controlledObject = CurrentControlledObject;
|
||||||
if (controlledObject == null) return;
|
if (controlledObject == null) return;
|
||||||
|
|
||||||
// 使用 _trackedPosition 作为当前位置(几何中心),不重新读取包围盒
|
// 使用业务跟踪点 _trackedPosition 作为当前位置,不把实时包围盒中心混入主链
|
||||||
Point3D currentPosition = _trackedPosition;
|
Point3D currentPosition = _trackedPosition;
|
||||||
Rotation3D currentRotation = _hasTrackedRotation ? _trackedRotation : Rotation3D.Identity;
|
Rotation3D currentRotation = _hasTrackedRotation ? _trackedRotation : Rotation3D.Identity;
|
||||||
|
|
||||||
|
|||||||
@ -591,122 +591,6 @@ namespace NavisworksTransport.Utils
|
|||||||
LogIncrementalTransformActual(item, targetPosition, targetRotation);
|
LogIncrementalTransformActual(item, targetPosition, targetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MoveItemIncrementallyToTrackedPositionAndRotation(
|
|
||||||
ModelItem item,
|
|
||||||
Point3D currentTrackedPosition,
|
|
||||||
Rotation3D currentRotation,
|
|
||||||
Point3D targetTrackedPosition,
|
|
||||||
Rotation3D targetRotation)
|
|
||||||
{
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
var doc = Application.ActiveDocument;
|
|
||||||
var modelItems = new ModelItemCollection { item };
|
|
||||||
|
|
||||||
Rotation3D deltaRotation = BuildDeltaRotation(currentRotation, targetRotation);
|
|
||||||
var currentLinear = new Transform3D(currentRotation).Linear;
|
|
||||||
var targetLinear = new Transform3D(targetRotation).Linear;
|
|
||||||
|
|
||||||
LogManager.Info(
|
|
||||||
$"[模型增量补偿] {item.DisplayName} 当前trackedPoint=({currentTrackedPosition.X:F3},{currentTrackedPosition.Y:F3},{currentTrackedPosition.Z:F3}), " +
|
|
||||||
$"目标trackedPoint=({targetTrackedPosition.X:F3},{targetTrackedPosition.Y:F3},{targetTrackedPosition.Z:F3})");
|
|
||||||
// LogManager.Debug(
|
|
||||||
// $"[模型增量补偿] {item.DisplayName} 当前旋转: " +
|
|
||||||
// $"X=({currentLinear.Get(0, 0):F4},{currentLinear.Get(1, 0):F4},{currentLinear.Get(2, 0):F4}), " +
|
|
||||||
// $"Y=({currentLinear.Get(0, 1):F4},{currentLinear.Get(1, 1):F4},{currentLinear.Get(2, 1):F4}), " +
|
|
||||||
// $"Z=({currentLinear.Get(0, 2):F4},{currentLinear.Get(1, 2):F4},{currentLinear.Get(2, 2):F4})");
|
|
||||||
// LogManager.Debug(
|
|
||||||
// $"[模型增量补偿] {item.DisplayName} 目标旋转: " +
|
|
||||||
// $"X=({targetLinear.Get(0, 0):F4},{targetLinear.Get(1, 0):F4},{targetLinear.Get(2, 0):F4}), " +
|
|
||||||
// $"Y=({targetLinear.Get(0, 1):F4},{targetLinear.Get(1, 1):F4},{targetLinear.Get(2, 1):F4}), " +
|
|
||||||
// $"Z=({targetLinear.Get(0, 2):F4},{targetLinear.Get(1, 2):F4},{targetLinear.Get(2, 2):F4})");
|
|
||||||
|
|
||||||
// LogGeometryLevelTransforms(item, "[模型增量补偿应用前][GeometryAPI]");
|
|
||||||
|
|
||||||
// 第1步:将物体中心移到原点(此时几何中心在原点)
|
|
||||||
var toOrigin = Transform3D.CreateTranslation(new Vector3D(
|
|
||||||
-currentTrackedPosition.X,
|
|
||||||
-currentTrackedPosition.Y,
|
|
||||||
-currentTrackedPosition.Z));
|
|
||||||
doc.Models.OverridePermanentTransform(modelItems, toOrigin, false);
|
|
||||||
|
|
||||||
// 第2步:在原点旋转
|
|
||||||
var rotationOnlyComponents = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)).Factor();
|
|
||||||
rotationOnlyComponents.Rotation = deltaRotation;
|
|
||||||
var rotationOnly = rotationOnlyComponents.Combine();
|
|
||||||
doc.Models.OverridePermanentTransform(modelItems, rotationOnly, false);
|
|
||||||
|
|
||||||
// 🔥 关键:读取旋转后、平移前的包围盒中心(相对于几何中心的偏移)
|
|
||||||
Point3D centerAfterRotation = item.BoundingBox()?.Center ?? new Point3D(0, 0, 0);
|
|
||||||
|
|
||||||
// 这就是目标旋转下,BoundingBox中心相对于几何中心的偏移
|
|
||||||
var rotationOffset = new Vector3D(
|
|
||||||
centerAfterRotation.X,
|
|
||||||
centerAfterRotation.Y,
|
|
||||||
centerAfterRotation.Z);
|
|
||||||
LogManager.Info(
|
|
||||||
$"[模型增量补偿] {item.DisplayName} 旋转后包围盒中心=({centerAfterRotation.X:F3},{centerAfterRotation.Y:F3},{centerAfterRotation.Z:F3}), " +
|
|
||||||
$"旋转偏移量=({rotationOffset.X:F3},{rotationOffset.Y:F3},{rotationOffset.Z:F3})");
|
|
||||||
|
|
||||||
// 🔥 关键修正:我们要几何中心对齐目标,而不是 BoundingBox 中心对齐目标
|
|
||||||
// rotationOffset = 旋转后 BoundingBox 中心相对于原点的位置
|
|
||||||
// 几何中心在原点,相对于 BoundingBox 中心的偏移 = -rotationOffset
|
|
||||||
// 所以 BoundingBox 中心应该位于 target + rotationOffset,才能让几何中心对齐 target
|
|
||||||
var adjustedTargetPosition = new Point3D(
|
|
||||||
targetTrackedPosition.X + rotationOffset.X,
|
|
||||||
targetTrackedPosition.Y + rotationOffset.Y,
|
|
||||||
targetTrackedPosition.Z + rotationOffset.Z);
|
|
||||||
LogManager.Info(
|
|
||||||
$"[模型增量补偿] {item.DisplayName} 调整后目标位置=({adjustedTargetPosition.X:F3},{adjustedTargetPosition.Y:F3},{adjustedTargetPosition.Z:F3}), " +
|
|
||||||
$"补偿量=(+{rotationOffset.X:F3},+{rotationOffset.Y:F3},+{rotationOffset.Z:F3})");
|
|
||||||
|
|
||||||
// 第3步:预落位到调整后的目标位置
|
|
||||||
var provisionalToTarget = Transform3D.CreateTranslation(new Vector3D(
|
|
||||||
adjustedTargetPosition.X,
|
|
||||||
adjustedTargetPosition.Y,
|
|
||||||
adjustedTargetPosition.Z));
|
|
||||||
doc.Models.OverridePermanentTransform(modelItems, provisionalToTarget, false);
|
|
||||||
|
|
||||||
Point3D actualTrackedPosition = item.BoundingBox()?.Center ?? new Point3D(0, 0, 0);
|
|
||||||
var correctionTranslation = new Vector3D(
|
|
||||||
adjustedTargetPosition.X - actualTrackedPosition.X,
|
|
||||||
adjustedTargetPosition.Y - actualTrackedPosition.Y,
|
|
||||||
adjustedTargetPosition.Z - actualTrackedPosition.Z);
|
|
||||||
|
|
||||||
LogManager.Info(
|
|
||||||
$"[模型增量补偿] {item.DisplayName} 预落位后实际trackedPoint=({actualTrackedPosition.X:F3},{actualTrackedPosition.Y:F3},{actualTrackedPosition.Z:F3}), " +
|
|
||||||
$"纠偏平移=({correctionTranslation.X:F3},{correctionTranslation.Y:F3},{correctionTranslation.Z:F3})");
|
|
||||||
|
|
||||||
if (Math.Abs(correctionTranslation.X) > 1e-6 ||
|
|
||||||
Math.Abs(correctionTranslation.Y) > 1e-6 ||
|
|
||||||
Math.Abs(correctionTranslation.Z) > 1e-6)
|
|
||||||
{
|
|
||||||
var correction = Transform3D.CreateTranslation(correctionTranslation);
|
|
||||||
doc.Models.OverridePermanentTransform(modelItems, correction, false);
|
|
||||||
LogManager.Info($"[模型增量补偿] {item.DisplayName} 已应用纠偏平移");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogManager.Info($"[模型增量补偿] {item.DisplayName} 纠偏平移太小,跳过应用");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🔥 验证纠偏后的实际位置(包围盒中心应该偏离目标,但几何中心对齐目标)
|
|
||||||
Point3D finalTrackedPosition = item.BoundingBox()?.Center ?? new Point3D(0, 0, 0);
|
|
||||||
// 几何中心 = BoundingBox中心 - rotationOffset(因为rotationOffset是BoundingBox中心相对于几何中心的偏移)
|
|
||||||
var geometricCenterDeviation = new Vector3D(
|
|
||||||
targetTrackedPosition.X - (finalTrackedPosition.X - rotationOffset.X),
|
|
||||||
targetTrackedPosition.Y - (finalTrackedPosition.Y - rotationOffset.Y),
|
|
||||||
targetTrackedPosition.Z - (finalTrackedPosition.Z - rotationOffset.Z));
|
|
||||||
LogManager.Info(
|
|
||||||
$"[模型增量补偿] {item.DisplayName} 最终包围盒中心=({finalTrackedPosition.X:F3},{finalTrackedPosition.Y:F3},{finalTrackedPosition.Z:F3}), " +
|
|
||||||
$"几何中心偏差=({geometricCenterDeviation.X:F3},{geometricCenterDeviation.Y:F3},{geometricCenterDeviation.Z:F3})");
|
|
||||||
|
|
||||||
// LogIncrementalTransformActual(item, targetTrackedPosition, targetRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 读取物体当前实际几何姿态。
|
/// 读取物体当前实际几何姿态。
|
||||||
/// 优先使用 ModelGeometry.ActiveTransform,因为 ModelItem.Transform 只反映原始设计变换。
|
/// 优先使用 ModelGeometry.ActiveTransform,因为 ModelItem.Transform 只反映原始设计变换。
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user