diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 10dc9a1..efbd2ca 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -975,7 +975,7 @@ namespace NavisworksTransport.Core.Animation
startPosition = ApplyGroundPathObjectLiftOffset(startPosition);
}
- ApplyLegacyYawPoseUpdate(startPosition);
+ ApplyTrackedTranslationOnly(startPosition);
SyncTrackedRotationToDisplayedPose(CurrentControlledObject ?? _animatedObject);
_hasGroundRealObjectBasePose = false;
@@ -1878,9 +1878,8 @@ namespace NavisworksTransport.Core.Animation
_currentFrameIndex = 0; // 重置当前帧索引,确保从第一帧开始
_pausedProgress = 0.0; // 重置暂停进度
- // 初始化动画状态时不再强行覆盖 _currentYaw 为第一帧的 yaw
- // 这样在 ApplyLegacyYawPoseUpdate(firstFrame.Position, firstFrame.YawRadians) 时
- // deltaYaw = firstFrame.YawRadians - 物体初始Yaw,从而产生旋转增量让物体转向
+ // 初始化动画状态时不再强行覆盖 _currentYaw 为第一帧的 yaw,
+ // 由记录姿态应用链自行解释第一帧姿态。
if (_animationFrames != null && _animationFrames.Count > 0)
{
@@ -2119,7 +2118,7 @@ namespace NavisworksTransport.Core.Animation
if (_currentFrameIndex != lastFrameIndex)
{
_currentFrameIndex = lastFrameIndex;
- ApplyAnimationFramePose(_animationFrames[_currentFrameIndex], _currentFrameIndex);
+ ApplyRecordedPose(_animationFrames[_currentFrameIndex], _currentFrameIndex);
LogManager.Info("[动画结束] 当前尚未到最后一帧,已补落最终姿态");
}
else
@@ -2683,9 +2682,10 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 更新对象位置和朝向(支持绕物体中心旋转)
+ /// 仅按业务跟踪点执行平移,不改变当前姿态语义。
+ /// PreserveInitialPose 起点搬运等链路应显式使用此入口,而不是借用旧 yaw 链。
///
- private void ApplyLegacyYawPoseUpdate(Point3D newPosition, double newYaw = double.NaN)
+ private void ApplyTrackedTranslationOnly(Point3D newPosition)
{
try
{
@@ -2699,50 +2699,8 @@ namespace NavisworksTransport.Core.Animation
newPosition.Z - _trackedPosition.Z
);
- Transform3D incrementalTransform;
-
- if (!double.IsNaN(newYaw))
- {
- // 有旋转:需要实现"绕物体当前位置自转"
- // 由于Transform3DComponents.Rotation总是绕世界原点旋转
- // 我们需要手动计算旋转导致的位置偏移,并补偿
-
- double deltaYaw = newYaw - _currentYaw;
- //LogManager.Debug($"[UpdateObjectPosition] 当前yaw={_currentYaw * 180 / Math.PI:F2}度, 目标yaw={newYaw * 180 / Math.PI:F2}度, 旋转增量deltaYaw={deltaYaw * 180 / Math.PI:F2}度");
-
- // 计算绕当前位置旋转的等效变换:
- // 1. 如果绕原点旋转deltaYaw,当前位置_trackedPosition会移动到哪里?
- double cos = Math.Cos(deltaYaw);
- double sin = Math.Sin(deltaYaw);
- double rotatedX = _trackedPosition.X * cos - _trackedPosition.Y * sin;
- double rotatedY = _trackedPosition.X * sin + _trackedPosition.Y * cos;
-
- // 2. 但我们希望物体绕自己旋转,位置移动到newPosition
- // 所以需要的平移 = newPosition - (旋转后的位置)
- var compensatedTranslation = new Vector3D(
- newPosition.X - rotatedX,
- newPosition.Y - rotatedY,
- newPosition.Z - _trackedPosition.Z // Z保持deltaPos
- );
-
- // 3. 组合:先旋转(绕原点),再平移(补偿+目标位置)
- var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
- var components = identity.Factor();
- components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
- components.Translation = compensatedTranslation;
-
- incrementalTransform = components.Combine();
-
- _currentYaw = newYaw;
- _trackedRotation = Rotation3D.Identity;
- _hasTrackedRotation = false;
- }
- else
- {
- // 纯平移
- incrementalTransform = Transform3D.CreateTranslation(deltaPos);
- LogManager.Debug($"[LegacyYawPose] 纯平移: ({deltaPos.X:F2},{deltaPos.Y:F2},{deltaPos.Z:F2})");
- }
+ Transform3D incrementalTransform = Transform3D.CreateTranslation(deltaPos);
+ LogManager.Debug($"[TrackedTranslation] 纯平移: ({deltaPos.X:F2},{deltaPos.Y:F2},{deltaPos.Z:F2})");
// 应用增量变换(false = 增量模式)
doc.Models.OverridePermanentTransform(modelItems, incrementalTransform, false);
@@ -3056,10 +3014,9 @@ namespace NavisworksTransport.Core.Animation
ApplyResolvedObjectPose(
_savedObjectPosition,
- _savedObjectYaw,
_savedObjectRotation,
_savedObjectHasCustomRotation,
- frameIndex: -1,
+ -1,
planarHostYawRadians: _savedObjectYaw);
LogHostActualPoseAxes(obj, "[PAM恢复后宿主姿态]", false);
@@ -3128,10 +3085,9 @@ namespace NavisworksTransport.Core.Animation
ApplyResolvedObjectPose(
targetPosition,
- targetYawRadians,
targetRotation,
hasCustomRotation,
- frameIndex: -1,
+ -1,
planarHostYawRadians: targetYawRadians);
LogHostActualPoseAxes(obj, "[动画姿态复用后宿主姿态]", false);
@@ -3246,7 +3202,7 @@ namespace NavisworksTransport.Core.Animation
// 更新对象位置和朝向,复用动画主播放与恢复使用的同一入口。
var frameData = _animationFrames[_currentFrameIndex];
- ApplyAnimationFramePose(frameData, _currentFrameIndex);
+ ApplyRecordedPose(frameData, _currentFrameIndex);
// 更新碰撞高亮
UpdateCollisionHighlightFromFrame();
@@ -5488,11 +5444,11 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 保留给旧单轴调用方:按当前宿主 up 轴映射成三轴角度修正。
+ /// 单轴兼容入口:按当前宿主 up 轴映射成三轴角度修正。
///
public void SetObjectRotationCorrection(double rotationCorrection)
{
- SetObjectRotationCorrection(CreateLegacyUpAxisCorrection(rotationCorrection));
+ SetObjectRotationCorrection(CreateSingleAxisUpCorrection(rotationCorrection));
}
///
@@ -5529,14 +5485,14 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 保留给旧单轴调用方:按当前宿主 up 轴映射成三轴角度修正。
+ /// 单轴兼容入口:按当前宿主 up 轴映射成三轴角度修正。
///
public void SetObjectRotationCorrectionDirect(double rotationCorrection)
{
- SetObjectRotationCorrectionDirect(CreateLegacyUpAxisCorrection(rotationCorrection));
+ SetObjectRotationCorrectionDirect(CreateSingleAxisUpCorrection(rotationCorrection));
}
- private LocalEulerRotationCorrection CreateLegacyUpAxisCorrection(double rotationCorrection)
+ private LocalEulerRotationCorrection CreateSingleAxisUpCorrection(double rotationCorrection)
{
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
return adapter.HostType == CoordinateSystemType.YUp
@@ -5692,7 +5648,7 @@ namespace NavisworksTransport.Core.Animation
if (_currentFrameIndex < _animationFrames.Count)
{
var frameData = _animationFrames[_currentFrameIndex];
- ApplyAnimationFramePose(frameData, _currentFrameIndex);
+ ApplyRecordedPose(frameData, _currentFrameIndex);
// 更新碰撞高亮(基于预计算结果)
UpdateCollisionHighlightFromFrame();
@@ -5719,7 +5675,7 @@ namespace NavisworksTransport.Core.Animation
UpdateFPSCounterAndCheckSwitch();
}
- private void ApplyAnimationFramePose(AnimationFrame frameData, int frameIndex)
+ private void ApplyRecordedPose(AnimationFrame frameData, int frameIndex)
{
if (frameData == null)
{
@@ -5728,16 +5684,16 @@ namespace NavisworksTransport.Core.Animation
ApplyResolvedObjectPose(
frameData.Position,
- ResolveAnimationFramePlaybackYawRadians(frameData),
frameData.Rotation,
frameData.HasCustomRotation,
frameIndex,
- frameData.PlanarHostYawRadians);
+ frameData.PlanarHostYawRadians.HasValue
+ ? (double?)ResolveAnimationFramePlaybackYawRadians(frameData)
+ : null);
}
private void ApplyResolvedObjectPose(
Point3D targetPosition,
- double resolvedYawRadians,
Rotation3D targetRotation,
bool hasCustomRotation,
int frameIndex,
@@ -5746,7 +5702,7 @@ namespace NavisworksTransport.Core.Animation
if (ShouldUsePlanarRealObjectPureIncrementFrames(_route?.PathType ?? PathType.Ground, IsRealObjectMode) &&
planarHostYawRadians.HasValue)
{
- ApplyPlanarAnimationFrame(targetPosition, planarHostYawRadians.Value);
+ ApplyPlanarTrackedPose(targetPosition, planarHostYawRadians.Value);
return;
}
@@ -5756,13 +5712,9 @@ namespace NavisworksTransport.Core.Animation
return;
}
- if (_route?.PathType == PathType.Ground || _route?.PathType == PathType.Hoisting)
- {
- throw new InvalidOperationException(
- $"平面路径播放帧 {frameIndex} 缺少完整姿态,禁止退回旧 yaw 链路。");
- }
-
- ApplyLegacyYawPoseUpdate(targetPosition, resolvedYawRadians);
+ string pathTypeName = (_route?.PathType ?? PathType.Ground).GetDisplayName();
+ throw new InvalidOperationException(
+ $"{pathTypeName}记录姿态 {frameIndex} 缺少完整姿态,禁止退回旧 yaw 链路。");
}
private double ResolveAnimationFramePlaybackYawRadians(AnimationFrame frameData)
@@ -5802,9 +5754,9 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 专门用于Ground路径动画帧播放。使用业务跟踪点 _trackedPosition 作为当前位置,不读取实时包围盒中心回写主链。
+ /// 应用平面路径的已记录姿态。使用业务跟踪点 _trackedPosition 作为当前位置,不读取实时包围盒中心回写主链。
///
- private void ApplyPlanarAnimationFrame(Point3D targetPosition, double targetYawRadians)
+ private void ApplyPlanarTrackedPose(Point3D targetPosition, double targetYawRadians)
{
var controlledObject = CurrentControlledObject;
if (controlledObject == null) return;
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index ebf343a..3211e45 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -826,50 +826,10 @@ namespace NavisworksTransport
}
else
{
- // 旧二维候选验证仍沿用“回到 CAD 原始位置再应用增量”的成熟语义。
- doc.Models.ResetPermanentTransform(modelItems);
-
- var originalBounds = testAnimatedObject.BoundingBox();
- var originalPos = new Point3D(
- (originalBounds.Min.X + originalBounds.Max.X) / 2,
- (originalBounds.Min.Y + originalBounds.Max.Y) / 2,
- (originalBounds.Min.Z + originalBounds.Max.Z) / 2
- );
- var originalYaw = ModelItemTransformHelper.GetYawFromTransform(testAnimatedObject.Transform);
-
- var deltaPos = new Vector3D(
- targetPosition.X - originalPos.X,
- targetPosition.Y - originalPos.Y,
- targetPosition.Z - originalPos.Z
- );
- double deltaYaw = targetYaw - originalYaw;
-
- Transform3D transform;
- if (Math.Abs(deltaYaw) > 0.001)
- {
- double cos = Math.Cos(deltaYaw);
- double sin = Math.Sin(deltaYaw);
- double rotatedX = originalPos.X * cos - originalPos.Y * sin;
- double rotatedY = originalPos.X * sin + originalPos.Y * cos;
-
- var compensatedTranslation = new Vector3D(
- targetPosition.X - rotatedX,
- targetPosition.Y - rotatedY,
- deltaPos.Z
- );
-
- var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
- var components = identity.Factor();
- components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
- components.Translation = compensatedTranslation;
- transform = components.Combine();
- }
- else
- {
- transform = Transform3D.CreateTranslation(deltaPos);
- }
-
- doc.Models.OverridePermanentTransform(modelItems, transform, false);
+ throw new InvalidOperationException(
+ $"ClashDetective候选恢复缺少完整姿态:对象 {testAnimatedObject.DisplayName}," +
+ $"目标跟踪点=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3})," +
+ $"TrackedYaw={targetYaw:F6}rad。");
}
var tempTestName = $"临时验证_{confirmedCount + 1}_{i}_{DateTime.Now:HHmmss_fff}";
diff --git a/src/Utils/CollisionSceneHelper.cs b/src/Utils/CollisionSceneHelper.cs
index 39a49c2..3a34371 100644
--- a/src/Utils/CollisionSceneHelper.cs
+++ b/src/Utils/CollisionSceneHelper.cs
@@ -98,49 +98,47 @@ namespace NavisworksTransport.Utils
{
if (animatedObject == null) return null;
- try
+ var pam = PathAnimationManager.GetInstance();
+ if (pam == null || !pam.ControlsAnimatedObject(animatedObject))
{
- // 从PathAnimationManager获取当前实际朝向
- var pam = PathAnimationManager.GetInstance();
- var currentYaw = pam.CurrentYaw;
- var currentRotation = pam.TrackedRotation;
- var hasCustomRotation = pam.HasTrackedRotation;
- var currentState = pam.GetObjectCurrentPosition(animatedObject);
- pam.SaveObjectState(animatedObject);
+ throw new InvalidOperationException(
+ $"保存碰撞场景前的动画物体状态必须复用 PathAnimationManager:对象 {animatedObject.DisplayName} 不受当前动画管理器控制。");
+ }
- var state = ModelItemTransformHelper.SaveObjectState(
- animatedObject,
- currentYaw,
- currentState.Position,
- currentRotation,
- hasCustomRotation);
-
- LogManager.Info(string.Format("已保存动画物体状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°, customRotation={5}",
- animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
- currentYaw * 180 / Math.PI, state.HasCustomRotation));
- if (state.HasCustomRotation && state.Rotation != null)
- {
- var linear = new Transform3D(state.Rotation).Linear;
- LogManager.Info(string.Format(
- "[报告姿态保存] {0} 保存姿态: " +
- "位置=({1:F3},{2:F3},{3:F3}), " +
- "X=({4:F4},{5:F4},{6:F4}), " +
- "Y=({7:F4},{8:F4},{9:F4}), " +
- "Z=({10:F4},{11:F4},{12:F4})",
- animatedObject.DisplayName,
- state.Position.X, state.Position.Y, state.Position.Z,
- linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
- linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
- linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
- }
-
- return state;
- }
- catch (Exception ex)
+ // 从 PathAnimationManager 获取当前实际姿态,不再退回工具层旧 yaw 快照语义。
+ var currentYaw = pam.CurrentYaw;
+ var currentRotation = pam.TrackedRotation;
+ var hasCustomRotation = pam.HasTrackedRotation;
+ var currentState = pam.GetObjectCurrentPosition(animatedObject);
+ pam.SaveObjectState(animatedObject);
+
+ var state = new ModelItemTransformHelper.ObjectStateSnapshot
{
- LogManager.Error(string.Format("保存动画物体状态失败: {0}", ex.Message), ex);
- return null;
+ Position = currentState.Position,
+ Rotation = currentRotation,
+ HasCustomRotation = hasCustomRotation
+ };
+
+ LogManager.Info(string.Format("已保存动画物体状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°, customRotation={5}",
+ animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
+ currentYaw * 180 / Math.PI, state.HasCustomRotation));
+ if (state.HasCustomRotation && state.Rotation != null)
+ {
+ var linear = new Transform3D(state.Rotation).Linear;
+ LogManager.Info(string.Format(
+ "[报告姿态保存] {0} 保存姿态: " +
+ "位置=({1:F3},{2:F3},{3:F3}), " +
+ "X=({4:F4},{5:F4},{6:F4}), " +
+ "Y=({7:F4},{8:F4},{9:F4}), " +
+ "Z=({10:F4},{11:F4},{12:F4})",
+ animatedObject.DisplayName,
+ state.Position.X, state.Position.Y, state.Position.Z,
+ linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
+ linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
+ linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
}
+
+ return state;
}
///
@@ -152,76 +150,34 @@ namespace NavisworksTransport.Utils
{
if (animatedObject == null || state == null) return;
- try
+ if (state.HasCustomRotation && state.Rotation != null)
{
- if (state.HasCustomRotation && state.Rotation != null)
- {
- var linear = new Transform3D(state.Rotation).Linear;
- LogManager.Info(string.Format(
- "[报告姿态恢复] {0} 恢复目标姿态: " +
- "位置=({1:F3},{2:F3},{3:F3}), " +
- "X=({4:F4},{5:F4},{6:F4}), " +
- "Y=({7:F4},{8:F4},{9:F4}), " +
- "Z=({10:F4},{11:F4},{12:F4})",
- animatedObject.DisplayName,
- state.Position.X, state.Position.Y, state.Position.Z,
- linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
- linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
- linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
- }
-
- var pam = PathAnimationManager.GetInstance();
- if (pam != null && pam.ControlsAnimatedObject(animatedObject))
- {
- pam.RestoreAnimatedObjectState(animatedObject);
- LogManager.Info(string.Format(
- "动画物体已通过PathAnimationManager恢复状态: {0}, customRotation={1}",
- animatedObject.DisplayName,
- state.HasCustomRotation));
- return;
- }
-
- if (state.HasCustomRotation)
- {
- bool isVirtualWithCustomRotation = VirtualObjectManager.Instance.IsVirtualObjectActive &&
- VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
- if (isVirtualWithCustomRotation)
- {
- ModelItemTransformHelper.RestoreObjectStateWithScale(animatedObject, state);
- }
- else
- {
- ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
- }
-
- LogManager.Info(string.Format("动画物体已通过状态快照恢复三维姿态: {0}", animatedObject.DisplayName));
- return;
- }
-
- // 检查是否是虚拟物体
- bool isVirtual = VirtualObjectManager.Instance.IsVirtualObjectActive &&
- VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
-
- if (isVirtual)
- {
- // 虚拟物体:使用带当前缩放的移动方法
- ModelItemTransformHelper.MoveItemToPositionAndYawWithCurrentScale(
- animatedObject, state.Position, state.YawRadians);
- LogManager.Info(string.Format("虚拟物体已恢复到原始状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°",
- animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
- state.YawRadians * 180 / Math.PI));
- }
- else
- {
- // 普通物体:使用标准恢复
- ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
- LogManager.Info(string.Format("动画物体已恢复到原始状态: {0}", animatedObject.DisplayName));
- }
+ var linear = new Transform3D(state.Rotation).Linear;
+ LogManager.Info(string.Format(
+ "[报告姿态恢复] {0} 恢复目标姿态: " +
+ "位置=({1:F3},{2:F3},{3:F3}), " +
+ "X=({4:F4},{5:F4},{6:F4}), " +
+ "Y=({7:F4},{8:F4},{9:F4}), " +
+ "Z=({10:F4},{11:F4},{12:F4})",
+ animatedObject.DisplayName,
+ state.Position.X, state.Position.Y, state.Position.Z,
+ linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
+ linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
+ linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
}
- catch (Exception ex)
+
+ var pam = PathAnimationManager.GetInstance();
+ if (pam == null || !pam.ControlsAnimatedObject(animatedObject))
{
- LogManager.Error(string.Format("恢复动画物体状态失败: {0}", ex.Message), ex);
+ throw new InvalidOperationException(
+ $"恢复碰撞场景前的动画物体状态必须复用 PathAnimationManager:对象 {animatedObject.DisplayName} 不受当前动画管理器控制。");
}
+
+ pam.RestoreAnimatedObjectState(animatedObject);
+ LogManager.Info(string.Format(
+ "动画物体已通过PathAnimationManager恢复状态: {0}, customRotation={1}",
+ animatedObject.DisplayName,
+ state.HasCustomRotation));
}
}
}
diff --git a/src/Utils/ModelItemTransformHelper.cs b/src/Utils/ModelItemTransformHelper.cs
index eb2f8d6..20e76ee 100644
--- a/src/Utils/ModelItemTransformHelper.cs
+++ b/src/Utils/ModelItemTransformHelper.cs
@@ -1237,197 +1237,8 @@ namespace NavisworksTransport.Utils
public class ObjectStateSnapshot
{
public Point3D Position { get; set; }
- public double YawRadians { get; set; }
public Rotation3D Rotation { get; set; }
public bool HasCustomRotation { get; set; }
- public Transform3D Transform { get; set; }
- }
-
- ///
- /// 保存物体当前状态
- /// 注意:YawRadians 通过当前位置计算,因为 Transform 返回的是CAD原始值
- ///
- public static ObjectStateSnapshot SaveObjectState(
- ModelItem item,
- double? currentYaw = null,
- Point3D currentPosition = null,
- Rotation3D currentRotation = null,
- bool hasCustomRotation = false)
- {
- if (item == null) return null;
-
- var bounds = item.BoundingBox();
-
- // 🔥 关键:如果提供了当前朝向(如 PathAnimationManager._currentYaw),使用它
- // 否则从 Transform 获取(但这可能不是实际朝向)
- double yaw;
- if (currentYaw.HasValue)
- {
- yaw = currentYaw.Value;
- }
- else
- {
- // 尝试通过包围盒方向计算(如果物体有几何特征)
- yaw = GetYawFromTransform(item.Transform);
- LogManager.Debug($"[SaveObjectState] 未提供当前朝向,使用Transform: {yaw * 180 / Math.PI:F2}°");
- }
-
- return new ObjectStateSnapshot
- {
- Position = currentPosition ?? new Point3D(bounds.Center.X, bounds.Center.Y, bounds.Min.Z),
- YawRadians = yaw,
- Rotation = currentRotation ?? Rotation3D.Identity,
- HasCustomRotation = hasCustomRotation,
- Transform = item.Transform
- };
- }
-
- ///
- /// 从状态快照恢复物体位置和朝向(标准版本,会重置缩放)
- ///
- public static void RestoreObjectState(ModelItem item, ObjectStateSnapshot state)
- {
- RestoreObjectStateInternal(item, state, preserveScale: false);
- }
-
- ///
- /// 从状态快照恢复物体位置和朝向(保留缩放版本,用于虚拟物体)
- ///
- public static void RestoreObjectStateWithScale(ModelItem item, ObjectStateSnapshot state)
- {
- RestoreObjectStateInternal(item, state, preserveScale: true);
- }
-
- ///
- /// 从状态快照恢复物体位置的内部实现
- ///
- private static void RestoreObjectStateInternal(ModelItem item, ObjectStateSnapshot state, bool preserveScale)
- {
- if (item == null || state == null) return;
-
- if (state.HasCustomRotation)
- {
- if (preserveScale)
- {
- MoveItemToPositionAndRotationWithCurrentScale(item, state.Position, state.Rotation);
- }
- else
- {
- MoveItemToPositionAndRotation(item, state.Position, state.Rotation);
- }
- return;
- }
-
- var doc = Application.ActiveDocument;
- var modelItems = new ModelItemCollection { item };
-
- // 1. 先回到CAD原始位置
- doc.Models.ResetPermanentTransform(modelItems);
-
- // 2. 从CAD原始位置移动到保存的位置
- // 获取CAD原始状态
- var originalBounds = item.BoundingBox();
- var originalCenterPos = originalBounds.Center;
- var originalYaw = GetYawFromTransform(item.Transform);
-
- // 计算到保存位置的增量
- var deltaPos = new Vector3D(
- state.Position.X - originalCenterPos.X,
- state.Position.Y - originalCenterPos.Y,
- state.Position.Z - originalCenterPos.Z
- );
- double deltaYaw = state.YawRadians - originalYaw;
-
- // 应用增量变换
- Transform3D transform;
- if (Math.Abs(deltaYaw) > 0.001)
- {
- double cos = Math.Cos(deltaYaw);
- double sin = Math.Sin(deltaYaw);
- double rotatedX = originalCenterPos.X * cos - originalCenterPos.Y * sin;
- double rotatedY = originalCenterPos.X * sin + originalCenterPos.Y * cos;
-
- var compensatedTranslation = new Vector3D(
- state.Position.X - rotatedX,
- state.Position.Y - rotatedY,
- state.Position.Z - originalCenterPos.Z
- );
-
- var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
- var components = identity.Factor();
- components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
- components.Translation = compensatedTranslation;
- transform = components.Combine();
- }
- else
- {
- transform = Transform3D.CreateTranslation(deltaPos);
- }
-
- doc.Models.OverridePermanentTransform(modelItems, transform, false);
- }
-
- ///
- /// 将物体移动到指定位置和朝向,同时保持当前缩放(专为虚拟物体设计)
- ///
- public static void MoveItemToPositionAndYawWithCurrentScale(ModelItem item, Point3D targetPosition, double targetYaw)
- {
- var doc = Application.ActiveDocument;
- var modelItems = new ModelItemCollection { item };
-
- // 获取当前变换中的缩放
- var currentTransform = item.Transform;
- var currentComponents = currentTransform.Factor();
- var currentScale = currentComponents.Scale;
-
- // 重置到CAD原始状态
- doc.Models.ResetPermanentTransform(modelItems);
-
- // 获取CAD原始状态
- var originalBounds = item.BoundingBox();
- var originalCenterPos = originalBounds.Center;
- var originalYaw = GetYawFromTransform(item.Transform);
-
- // 计算从CAD原始位置到目标位置的增量
- var deltaPos = new Vector3D(
- targetPosition.X - originalCenterPos.X,
- targetPosition.Y - originalCenterPos.Y,
- targetPosition.Z - originalCenterPos.Z
- );
- double deltaYaw = targetYaw - originalYaw;
-
- // 构建变换组件,保留原有缩放
- var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
- var components = identity.Factor();
- components.Scale = currentScale; // 保留当前缩放
-
- if (Math.Abs(deltaYaw) > 0.001)
- {
- components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
- }
-
- // 计算平移(考虑旋转带来的位置偏移)
- if (Math.Abs(deltaYaw) > 0.001)
- {
- double cos = Math.Cos(deltaYaw);
- double sin = Math.Sin(deltaYaw);
- double rotatedX = originalCenterPos.X * cos - originalCenterPos.Y * sin;
- double rotatedY = originalCenterPos.X * sin + originalCenterPos.Y * cos;
-
- components.Translation = new Vector3D(
- targetPosition.X - rotatedX,
- targetPosition.Y - rotatedY,
- targetPosition.Z - originalCenterPos.Z
- );
- }
- else
- {
- components.Translation = deltaPos;
- }
-
- // 应用组合变换
- Transform3D transform = components.Combine();
- doc.Models.OverridePermanentTransform(modelItems, transform, false);
}
}
}