using System; using Autodesk.Navisworks.Api; namespace NavisworksTransport.Utils { /// /// ModelItem变换辅助工具 /// 提供临时移动和恢复物体位置的通用方法 /// public static class ModelItemTransformHelper { /// /// 临时移动物体到指定位置 /// /// 要移动的物体 /// 目标位置(物体中心) /// 用于恢复的偏移向量 public static Vector3D MoveItemToPosition(ModelItem item, Point3D targetPosition) { var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; // 计算当前中心位置 var currentBounds = item.BoundingBox(); var currentPos = new Point3D( (currentBounds.Min.X + currentBounds.Max.X) / 2, (currentBounds.Min.Y + currentBounds.Max.Y) / 2, (currentBounds.Min.Z + currentBounds.Max.Z) / 2 ); // 计算偏移 var offset = new Vector3D( targetPosition.X - currentPos.X, targetPosition.Y - currentPos.Y, targetPosition.Z - currentPos.Z ); // 应用变换 var transform = Transform3D.CreateTranslation(offset); doc.Models.OverridePermanentTransform(modelItems, transform, false); return offset; } /// /// 从Transform3D中提取Yaw角度(绕Z轴旋转,单位:弧度) /// /// 变换矩阵 /// Yaw角度(弧度) public static double GetYawFromTransform(Transform3D transform) { if (transform == null) return 0.0; try { var components = transform.Factor(); return GetYawFromRotation(components.Rotation); } catch (Exception) { return 0.0; } } /// /// 从 Rotation3D 中提取 XY 平面的 yaw 角(弧度)。 /// public static double GetYawFromRotation(Rotation3D rotation) { if (rotation == null) { return 0.0; } try { var rotationResult = rotation.ToAxisAndAngle(); double angle = rotationResult.Angle; double ux = rotationResult.Axis.X; double uy = rotationResult.Axis.Y; double uz = rotationResult.Axis.Z; double cos = Math.Cos(angle); double sin = Math.Sin(angle); double vx = cos + ux * ux * (1 - cos); double vy = uz * sin + ux * uy * (1 - cos); return Math.Atan2(vy, vx); } catch (Exception) { return 0.0; } } /// /// 获取变换后局部 X 轴在世界坐标中的方向,通常可作为物体主朝向。 /// public static Vector3D GetForwardDirectionFromTransform(Transform3D transform) { return GetAxisDirectionFromTransform(transform, 0, new Vector3D(1, 0, 0)); } /// /// 获取变换后局部 Z 轴在世界坐标中的方向,可作为构件顶/底面法向。 /// public static Vector3D GetUpDirectionFromTransform(Transform3D transform) { return GetAxisDirectionFromTransform(transform, 2, new Vector3D(0, 0, 1)); } /// /// 根据世界轴对齐包围盒和物体变换,估算物体在局部坐标系中的尺寸。 /// 适用于刚性箱体类对象,用于顶/底面对接点推导。 /// public static Vector3D EstimateLocalBoxSize(BoundingBox3D bounds, Transform3D transform) { double halfXWorld = Math.Max(0.0, (bounds.Max.X - bounds.Min.X) / 2.0); double halfYWorld = Math.Max(0.0, (bounds.Max.Y - bounds.Min.Y) / 2.0); double halfZWorld = Math.Max(0.0, (bounds.Max.Z - bounds.Min.Z) / 2.0); if (transform == null) { return new Vector3D(halfXWorld * 2.0, halfYWorld * 2.0, halfZWorld * 2.0); } try { var forward = GetForwardDirectionFromTransform(transform); var localY = GetAxisDirectionFromTransform(transform, 1, new Vector3D(0, 1, 0)); var up = GetUpDirectionFromTransform(transform); double[,] matrix = { { Math.Abs(forward.X), Math.Abs(localY.X), Math.Abs(up.X) }, { Math.Abs(forward.Y), Math.Abs(localY.Y), Math.Abs(up.Y) }, { Math.Abs(forward.Z), Math.Abs(localY.Z), Math.Abs(up.Z) } }; double[] worldHalfExtents = { halfXWorld, halfYWorld, halfZWorld }; double[] localHalfExtents = SolveLinearSystem3x3(matrix, worldHalfExtents); return new Vector3D( Math.Max(0.0, localHalfExtents[0] * 2.0), Math.Max(0.0, localHalfExtents[1] * 2.0), Math.Max(0.0, localHalfExtents[2] * 2.0)); } catch (Exception) { return new Vector3D(halfXWorld * 2.0, halfYWorld * 2.0, halfZWorld * 2.0); } } /// /// 根据箱体局部尺寸和世界原点方向,推导“背离球心”的真实长轴方向。 /// 先选局部最长轴,再用箱体中心相对世界原点的方向决定正负。 /// public static Vector3D GetLongestAxisDirectionAwayFromOrigin(BoundingBox3D bounds, Transform3D transform) { Vector3D localSize = EstimateLocalBoxSize(bounds, transform); int longestAxisIndex = 0; double longestAxisLength = localSize.X; if (localSize.Y > longestAxisLength) { longestAxisIndex = 1; longestAxisLength = localSize.Y; } if (localSize.Z > longestAxisLength) { longestAxisIndex = 2; } Vector3D axisDirection = GetAxisDirectionFromTransform( transform, longestAxisIndex, longestAxisIndex == 0 ? new Vector3D(1, 0, 0) : longestAxisIndex == 1 ? new Vector3D(0, 1, 0) : new Vector3D(0, 0, 1)); Vector3D awayFromOrigin = new Vector3D(bounds.Center.X, bounds.Center.Y, bounds.Center.Z); double awayLengthSquared = awayFromOrigin.X * awayFromOrigin.X + awayFromOrigin.Y * awayFromOrigin.Y + awayFromOrigin.Z * awayFromOrigin.Z; if (awayLengthSquared < 1e-9) { return axisDirection; } double dot = axisDirection.X * awayFromOrigin.X + axisDirection.Y * awayFromOrigin.Y + axisDirection.Z * awayFromOrigin.Z; if (dot < 0.0) { return new Vector3D(-axisDirection.X, -axisDirection.Y, -axisDirection.Z); } return axisDirection; } private static Vector3D GetAxisDirectionFromTransform(Transform3D transform, int axisIndex, Vector3D fallback) { if (transform == null) { return fallback; } try { var linear = transform.Linear; var direction = new Vector3D( linear.Get(0, axisIndex), linear.Get(1, axisIndex), linear.Get(2, axisIndex)); double lengthSquared = direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z; if (lengthSquared < 1e-9) { return fallback; } double length = Math.Sqrt(lengthSquared); return new Vector3D(direction.X / length, direction.Y / length, direction.Z / length); } catch (Exception) { return fallback; } } private static double[] SolveLinearSystem3x3(double[,] matrix, double[] values) { double determinant = matrix[0, 0] * (matrix[1, 1] * matrix[2, 2] - matrix[1, 2] * matrix[2, 1]) - matrix[0, 1] * (matrix[1, 0] * matrix[2, 2] - matrix[1, 2] * matrix[2, 0]) + matrix[0, 2] * (matrix[1, 0] * matrix[2, 1] - matrix[1, 1] * matrix[2, 0]); if (Math.Abs(determinant) < 1e-9) { return new[] { values[0], values[1], values[2] }; } double inverseDeterminant = 1.0 / determinant; double[,] inverse = { { (matrix[1, 1] * matrix[2, 2] - matrix[1, 2] * matrix[2, 1]) * inverseDeterminant, (matrix[0, 2] * matrix[2, 1] - matrix[0, 1] * matrix[2, 2]) * inverseDeterminant, (matrix[0, 1] * matrix[1, 2] - matrix[0, 2] * matrix[1, 1]) * inverseDeterminant }, { (matrix[1, 2] * matrix[2, 0] - matrix[1, 0] * matrix[2, 2]) * inverseDeterminant, (matrix[0, 0] * matrix[2, 2] - matrix[0, 2] * matrix[2, 0]) * inverseDeterminant, (matrix[0, 2] * matrix[1, 0] - matrix[0, 0] * matrix[1, 2]) * inverseDeterminant }, { (matrix[1, 0] * matrix[2, 1] - matrix[1, 1] * matrix[2, 0]) * inverseDeterminant, (matrix[0, 1] * matrix[2, 0] - matrix[0, 0] * matrix[2, 1]) * inverseDeterminant, (matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0]) * inverseDeterminant } }; return new[] { inverse[0, 0] * values[0] + inverse[0, 1] * values[1] + inverse[0, 2] * values[2], inverse[1, 0] * values[0] + inverse[1, 1] * values[1] + inverse[1, 2] * values[2], inverse[2, 0] * values[0] + inverse[2, 1] * values[1] + inverse[2, 2] * values[2] }; } /// /// 恢复物体到原位置 /// /// 要恢复的物体 /// 原始移动偏移向量 public static void RestoreItemPosition(ModelItem item, Vector3D originalOffset) { var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; // 反向偏移 var restoreOffset = new Vector3D(-originalOffset.X, -originalOffset.Y, -originalOffset.Z); var restoreTransform = Transform3D.CreateTranslation(restoreOffset); doc.Models.OverridePermanentTransform(modelItems, restoreTransform, false); } /// /// 将物体移动到指定位置和朝向(先回到CAD原始位置,再移动) /// 适用于碰撞位置还原等场景 /// /// 要移动的物体 /// 目标位置(地面位置,即包围盒底面) /// 目标朝向(弧度,绕Z轴) public static void MoveItemToPositionAndYaw(ModelItem item, Point3D targetPosition, double targetYaw) { var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; // 🔥 关键:先回到CAD原始位置,确保从已知状态开始计算 doc.Models.ResetPermanentTransform(modelItems); // 获取CAD原始状态 var originalBounds = item.BoundingBox(); var originalGroundPos = new Point3D( originalBounds.Center.X, originalBounds.Center.Y, originalBounds.Min.Z ); var originalYaw = GetYawFromTransform(item.Transform); // 计算从CAD原始位置到目标位置的增量 var deltaPos = new Vector3D( targetPosition.X - originalGroundPos.X, targetPosition.Y - originalGroundPos.Y, targetPosition.Z - originalGroundPos.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 = originalGroundPos.X * cos - originalGroundPos.Y * sin; double rotatedY = originalGroundPos.X * sin + originalGroundPos.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); } /// /// 将物体移动到指定位置和完整三维朝向(先回到CAD原始位置,再移动) /// public static void MoveItemToPositionAndRotation(ModelItem item, Point3D targetPosition, Rotation3D targetRotation) { ApplyAbsoluteTransform(item, targetPosition, targetRotation, preserveCurrentScale: false); } /// /// 将物体移动到指定位置和完整三维朝向,同时保留当前缩放。 /// public static void MoveItemToPositionAndRotationWithCurrentScale(ModelItem item, Point3D targetPosition, Rotation3D targetRotation) { ApplyAbsoluteTransform(item, targetPosition, targetRotation, preserveCurrentScale: true); } /// /// 将物体移动到指定中心点和完整三维朝向,同时保留当前缩放。 /// 适用于参考杆、辅助几何等以几何中心作为定位基准的场景。 /// public static void MoveItemToCenterAndRotationWithCurrentScale(ModelItem item, Point3D targetCenter, Rotation3D targetRotation) { if (item == null) { throw new ArgumentNullException(nameof(item)); } var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; var currentComponents = item.Transform.Factor(); Vector3D currentScale = currentComponents.Scale; doc.Models.ResetPermanentTransform(modelItems); var originalBounds = item.BoundingBox(); Point3D originalCenter = originalBounds.Center; var rotationTransform = new Transform3D(targetRotation); var linear = rotationTransform.Linear; var rotatedCenter = new Point3D( linear.Get(0, 0) * originalCenter.X + linear.Get(0, 1) * originalCenter.Y + linear.Get(0, 2) * originalCenter.Z, linear.Get(1, 0) * originalCenter.X + linear.Get(1, 1) * originalCenter.Y + linear.Get(1, 2) * originalCenter.Z, linear.Get(2, 0) * originalCenter.X + linear.Get(2, 1) * originalCenter.Y + linear.Get(2, 2) * originalCenter.Z); var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)); var components = identity.Factor(); components.Scale = currentScale; components.Rotation = targetRotation; components.Translation = new Vector3D( targetCenter.X - rotatedCenter.X, targetCenter.Y - rotatedCenter.Y, targetCenter.Z - rotatedCenter.Z); doc.Models.OverridePermanentTransform(modelItems, components.Combine(), false); } /// /// 将物体移动到指定中心点和完整三维朝向。 /// 仅应用位置和旋转,不保留当前缩放。 /// 适用于缩放已经在 Model 层完成的参考杆等场景。 /// public static void MoveItemToCenterAndRotation(ModelItem item, Point3D targetCenter, Rotation3D targetRotation) { if (item == null) { throw new ArgumentNullException(nameof(item)); } var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; doc.Models.ResetPermanentTransform(modelItems); var originalBounds = item.BoundingBox(); Point3D originalCenter = originalBounds.Center; var rotationTransform = new Transform3D(targetRotation); var linear = rotationTransform.Linear; var rotatedCenter = new Point3D( linear.Get(0, 0) * originalCenter.X + linear.Get(0, 1) * originalCenter.Y + linear.Get(0, 2) * originalCenter.Z, linear.Get(1, 0) * originalCenter.X + linear.Get(1, 1) * originalCenter.Y + linear.Get(1, 2) * originalCenter.Z, linear.Get(2, 0) * originalCenter.X + linear.Get(2, 1) * originalCenter.Y + linear.Get(2, 2) * originalCenter.Z); var translation = new Vector3D( targetCenter.X - rotatedCenter.X, targetCenter.Y - rotatedCenter.Y, targetCenter.Z - rotatedCenter.Z); doc.Models.OverridePermanentTransform(modelItems, new Transform3D(targetRotation, translation), false); } /// /// 将物体的局部正 X 端面中心对齐到目标点,并保留当前缩放。 /// 适用于单位立方体/单位圆柱体沿 +X 定义长度方向的参考杆资源。 /// public static void MoveItemPositiveXEndToPointAndRotationWithCurrentScale(ModelItem item, Point3D targetPoint, Rotation3D targetRotation) { if (item == null) { throw new ArgumentNullException(nameof(item)); } var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; var currentComponents = item.Transform.Factor(); Vector3D currentScale = currentComponents.Scale; doc.Models.ResetPermanentTransform(modelItems); var originalBounds = item.BoundingBox(); Point3D originalPositiveXEndCenter = new Point3D( originalBounds.Max.X, originalBounds.Center.Y, originalBounds.Center.Z); var rotationTransform = new Transform3D(targetRotation); var linear = rotationTransform.Linear; var rotatedPositiveXEndCenter = new Point3D( linear.Get(0, 0) * originalPositiveXEndCenter.X + linear.Get(0, 1) * originalPositiveXEndCenter.Y + linear.Get(0, 2) * originalPositiveXEndCenter.Z, linear.Get(1, 0) * originalPositiveXEndCenter.X + linear.Get(1, 1) * originalPositiveXEndCenter.Y + linear.Get(1, 2) * originalPositiveXEndCenter.Z, linear.Get(2, 0) * originalPositiveXEndCenter.X + linear.Get(2, 1) * originalPositiveXEndCenter.Y + linear.Get(2, 2) * originalPositiveXEndCenter.Z); var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)); var components = identity.Factor(); components.Scale = currentScale; components.Rotation = targetRotation; components.Translation = new Vector3D( targetPoint.X - rotatedPositiveXEndCenter.X, targetPoint.Y - rotatedPositiveXEndCenter.Y, targetPoint.Z - rotatedPositiveXEndCenter.Z); doc.Models.OverridePermanentTransform(modelItems, components.Combine(), false); } /// /// 将物体的局部正 X 端面中心对齐到目标点。 /// 仅应用位置和旋转,不保留当前缩放。 /// 适用于缩放已经在 Model 层完成、Item 层只负责定位的场景。 /// public static void MoveItemPositiveXEndToPointAndRotation(ModelItem item, Point3D targetPoint, Rotation3D targetRotation) { if (item == null) { throw new ArgumentNullException(nameof(item)); } var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; doc.Models.ResetPermanentTransform(modelItems); var originalBounds = item.BoundingBox(); Point3D originalPositiveXEndCenter = new Point3D( originalBounds.Max.X, originalBounds.Center.Y, originalBounds.Center.Z); var rotationTransform = new Transform3D(targetRotation); var linear = rotationTransform.Linear; var rotatedPositiveXEndCenter = new Point3D( linear.Get(0, 0) * originalPositiveXEndCenter.X + linear.Get(0, 1) * originalPositiveXEndCenter.Y + linear.Get(0, 2) * originalPositiveXEndCenter.Z, linear.Get(1, 0) * originalPositiveXEndCenter.X + linear.Get(1, 1) * originalPositiveXEndCenter.Y + linear.Get(1, 2) * originalPositiveXEndCenter.Z, linear.Get(2, 0) * originalPositiveXEndCenter.X + linear.Get(2, 1) * originalPositiveXEndCenter.Y + linear.Get(2, 2) * originalPositiveXEndCenter.Z); var translation = new Vector3D( targetPoint.X - rotatedPositiveXEndCenter.X, targetPoint.Y - rotatedPositiveXEndCenter.Y, targetPoint.Z - rotatedPositiveXEndCenter.Z); doc.Models.OverridePermanentTransform(modelItems, new Transform3D(targetRotation, translation), false); } private static void ApplyAbsoluteTransform(ModelItem item, Point3D targetPosition, Rotation3D targetRotation, bool preserveCurrentScale) { var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; Vector3D currentScale = new Vector3D(1, 1, 1); if (preserveCurrentScale) { var currentComponents = item.Transform.Factor(); currentScale = currentComponents.Scale; } doc.Models.ResetPermanentTransform(modelItems); var originalBounds = item.BoundingBox(); var originalGroundPos = new Point3D( originalBounds.Center.X, originalBounds.Center.Y, originalBounds.Min.Z ); var rotationTransform = new Transform3D(targetRotation); var linear = rotationTransform.Linear; var rotatedGroundPos = new Point3D( linear.Get(0, 0) * originalGroundPos.X + linear.Get(0, 1) * originalGroundPos.Y + linear.Get(0, 2) * originalGroundPos.Z, linear.Get(1, 0) * originalGroundPos.X + linear.Get(1, 1) * originalGroundPos.Y + linear.Get(1, 2) * originalGroundPos.Z, linear.Get(2, 0) * originalGroundPos.X + linear.Get(2, 1) * originalGroundPos.Y + linear.Get(2, 2) * originalGroundPos.Z ); var translation = new Vector3D( targetPosition.X - rotatedGroundPos.X, targetPosition.Y - rotatedGroundPos.Y, targetPosition.Z - rotatedGroundPos.Z ); Transform3D transform; if (preserveCurrentScale) { var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)); var components = identity.Factor(); components.Scale = currentScale; components.Rotation = targetRotation; components.Translation = translation; transform = components.Combine(); } else { transform = new Transform3D(targetRotation, translation); } doc.Models.OverridePermanentTransform(modelItems, transform, false); } /// /// 将物体移动到指定位置和朝向,同时保持缩放比例 /// 专为虚拟物体设计,避免缩放被覆盖 /// /// 要移动的物体 /// 目标位置(地面位置) /// 目标朝向(弧度) /// X方向缩放 /// Y方向缩放 /// Z方向缩放 public static void MoveItemToPositionAndYawWithScale(ModelItem item, Point3D targetPosition, double targetYaw, double scaleX, double scaleY, double scaleZ) { var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; // 重置到CAD原始状态 doc.Models.ResetPermanentTransform(modelItems); // 获取CAD原始状态 var originalBounds = item.BoundingBox(); var originalGroundPos = new Point3D( originalBounds.Center.X, originalBounds.Center.Y, originalBounds.Min.Z ); var originalYaw = GetYawFromTransform(item.Transform); // 计算从CAD原始位置到目标位置的增量 var deltaPos = new Vector3D( targetPosition.X - originalGroundPos.X, targetPosition.Y - originalGroundPos.Y, targetPosition.Z - originalGroundPos.Z ); double deltaYaw = targetYaw - originalYaw; // 构建变换组件 var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)); var components = identity.Factor(); // 应用缩放 components.Scale = new Vector3D(scaleX, scaleY, scaleZ); // 应用旋转 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 = originalGroundPos.X * cos - originalGroundPos.Y * sin; double rotatedY = originalGroundPos.X * sin + originalGroundPos.Y * cos; components.Translation = new Vector3D( targetPosition.X - rotatedX, targetPosition.Y - rotatedY, deltaPos.Z ); } else { components.Translation = deltaPos; } // 应用组合变换 Transform3D transform = components.Combine(); doc.Models.OverridePermanentTransform(modelItems, transform, false); } /// /// 物体状态快照,用于保存和恢复 /// public class ObjectStateSnapshot { public Point3D Position { get; set; } public double YawRadians { get; set; } public Transform3D Transform { get; set; } } /// /// 保存物体当前状态 /// 注意:YawRadians 通过当前位置计算,因为 Transform 返回的是CAD原始值 /// public static ObjectStateSnapshot SaveObjectState(ModelItem item, double? currentYaw = null) { 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 = new Point3D(bounds.Center.X, bounds.Center.Y, bounds.Min.Z), YawRadians = yaw, 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; var doc = Application.ActiveDocument; var modelItems = new ModelItemCollection { item }; // 1. 先回到CAD原始位置 doc.Models.ResetPermanentTransform(modelItems); // 2. 从CAD原始位置移动到保存的位置 // 获取CAD原始状态 var originalBounds = item.BoundingBox(); var originalGroundPos = new Point3D( originalBounds.Center.X, originalBounds.Center.Y, originalBounds.Min.Z ); var originalYaw = GetYawFromTransform(item.Transform); // 计算到保存位置的增量 var deltaPos = new Vector3D( state.Position.X - originalGroundPos.X, state.Position.Y - originalGroundPos.Y, state.Position.Z - originalGroundPos.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 = originalGroundPos.X * cos - originalGroundPos.Y * sin; double rotatedY = originalGroundPos.X * sin + originalGroundPos.Y * cos; var compensatedTranslation = new Vector3D( state.Position.X - rotatedX, state.Position.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); } /// /// 将物体移动到指定位置和朝向,同时保持当前缩放(专为虚拟物体设计) /// 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 originalGroundPos = new Point3D( originalBounds.Center.X, originalBounds.Center.Y, originalBounds.Min.Z ); var originalYaw = GetYawFromTransform(item.Transform); // 计算从CAD原始位置到目标位置的增量 var deltaPos = new Vector3D( targetPosition.X - originalGroundPos.X, targetPosition.Y - originalGroundPos.Y, targetPosition.Z - originalGroundPos.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 = originalGroundPos.X * cos - originalGroundPos.Y * sin; double rotatedY = originalGroundPos.X * sin + originalGroundPos.Y * cos; components.Translation = new Vector3D( targetPosition.X - rotatedX, targetPosition.Y - rotatedY, deltaPos.Z ); } else { components.Translation = deltaPos; } // 应用组合变换 Transform3D transform = components.Combine(); doc.Models.OverridePermanentTransform(modelItems, transform, false); } } }