using System;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Utils.CoordinateSystem;
using System.Numerics;

namespace NavisworksTransport.Utils
{
    /// <summary>
    /// ModelItem变换辅助工具
    /// 提供临时移动和恢复物体位置的通用方法
    /// </summary>
    public static class ModelItemTransformHelper
    {
        /// <summary>
        /// 临时移动物体到指定位置
        /// </summary>
        /// <param name="item">要移动的物体</param>
        /// <param name="targetPosition">目标位置（物体中心）</param>
        /// <returns>用于恢复的偏移向量</returns>
        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;
        }

        /// <summary>
        /// 从Transform3D中提取Yaw角度（绕Z轴旋转，单位：弧度）
        /// </summary>
        /// <param name="transform">变换矩阵</param>
        /// <returns>Yaw角度（弧度）</returns>
        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;
            }
        }

        /// <summary>
        /// 从 Rotation3D 中提取 XY 平面的 yaw 角（弧度）。
        /// </summary>
        public static double GetYawFromRotation(Rotation3D rotation)
        {
            if (rotation == null)
            {
                return 0.0;
            }

            try
            {
                var linear = new Transform3D(rotation).Linear;
                Vector3 hostForward = new Vector3(
                    (float)linear.Get(0, 0),
                    (float)linear.Get(1, 0),
                    (float)linear.Get(2, 0));

                // 转 canonical (ZUp)，在 XY 平面算 yaw
                var adapter = new HostCoordinateAdapter(CoordinateSystemManager.Instance.ResolvedType);
                Vector3 canonicalForward = adapter.ToCanonicalVector3(hostForward);
                canonicalForward.Z = 0f;
                if (canonicalForward.LengthSquared() < 1e-9f)
                {
                    return 0.0;
                }

                canonicalForward = Vector3.Normalize(canonicalForward);
                return System.Math.Atan2(canonicalForward.Y, canonicalForward.X);
            }
            catch (Exception)
            {
                return 0.0;
            }
        }

        /// <summary>
        /// 获取变换后局部 X 轴在世界坐标中的方向，通常可作为物体主朝向。
        /// </summary>
        public static Vector3D GetForwardDirectionFromTransform(Transform3D transform)
        {
            return GetAxisDirectionFromTransform(transform, 0, new Vector3D(1, 0, 0));
        }

        /// <summary>
        /// 获取变换后局部 Z 轴在世界坐标中的方向，可作为构件顶/底面法向。
        /// </summary>
        public static Vector3D GetUpDirectionFromTransform(Transform3D transform)
        {
            return GetAxisDirectionFromTransform(transform, 2, new Vector3D(0, 0, 1));
        }

        /// <summary>
        /// 根据模型局部轴约定，获取指定局部轴在世界坐标中的方向。
        /// </summary>
        public static Vector3D GetDirectionFromTransform(
            Transform3D transform,
            LocalAxisDirection axisDirection)
        {
            GetAxisIndexAndSign(axisDirection, out int axisIndex, out int sign);
            Vector3D fallback = GetFallbackAxis(axisDirection);
            Vector3D direction = GetAxisDirectionFromTransform(transform, axisIndex, fallback);

            return sign >= 0
                ? direction
                : new Vector3D(-direction.X, -direction.Y, -direction.Z);
        }

        /// <summary>
        /// 获取绑定在物体局部坐标中的稳定底面锚点。
        /// 适用于带俯仰/侧倾的三维姿态对象，避免使用世界 AABB 底面中心导致锚点漂移。
        /// </summary>
        public static Point3D GetStableBottomAnchorPoint(BoundingBox3D bounds, Transform3D transform)
        {
            if (bounds == null)
            {
                return new Point3D(0, 0, 0);
            }

            if (transform == null)
            {
                return new Point3D(bounds.Center.X, bounds.Center.Y, bounds.Min.Z);
            }

            var up = GetUpDirectionFromTransform(transform);
            var localSize = EstimateLocalBoxSize(bounds, transform);
            double halfHeight = localSize.Z / 2.0;

            return new Point3D(
                bounds.Center.X - up.X * halfHeight,
                bounds.Center.Y - up.Y * halfHeight,
                bounds.Center.Z - up.Z * halfHeight);
        }

        /// <summary>
        /// 使用宿主坐标系的 up 轴，从世界 AABB 中提取“底部锚点”。
        /// 适用于真实模型仍保持宿主坐标语义（如 Y-up 模型）的场景。
        /// </summary>
        public static Point3D GetHostBottomAnchorPoint(BoundingBox3D bounds, HostCoordinateAdapter adapter)
        {
            if (bounds == null)
            {
                return new Point3D(0, 0, 0);
            }

            if (adapter == null)
            {
                throw new ArgumentNullException(nameof(adapter));
            }

            switch (adapter.HostUpAxisIndex)
            {
                case 1:
                    return new Point3D(bounds.Center.X, bounds.Min.Y, bounds.Center.Z);
                case 2:
                default:
                    return new Point3D(bounds.Center.X, bounds.Center.Y, bounds.Min.Z);
            }
        }

        /// <summary>
        /// 使用宿主坐标系的 up 轴，从世界 AABB 中提取高度。
        /// 适用于真实模型仍保持宿主坐标语义（如 Y-up 模型）的场景。
        /// </summary>
        public static double GetHostHeight(BoundingBox3D bounds, HostCoordinateAdapter adapter)
        {
            if (bounds == null)
            {
                return 0.0;
            }

            if (adapter == null)
            {
                throw new ArgumentNullException(nameof(adapter));
            }

            switch (adapter.HostUpAxisIndex)
            {
                case 1:
                    return bounds.Max.Y - bounds.Min.Y;
                case 2:
                default:
                    return bounds.Max.Z - bounds.Min.Z;
            }
        }

        /// <summary>
        /// 根据世界轴对齐包围盒和物体变换，估算物体在局部坐标系中的尺寸。
        /// 适用于刚性箱体类对象，用于顶/底面对接点推导。
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// 根据箱体局部尺寸和世界原点方向，推导“背离球心”的真实长轴方向。
        /// 先选局部最长轴，再用箱体中心相对世界原点的方向决定正负。
        /// </summary>
        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 void GetAxisIndexAndSign(LocalAxisDirection axisDirection, out int axisIndex, out int sign)
        {
            switch (axisDirection)
            {
                case LocalAxisDirection.PositiveX:
                    axisIndex = 0;
                    sign = 1;
                    break;
                case LocalAxisDirection.NegativeX:
                    axisIndex = 0;
                    sign = -1;
                    break;
                case LocalAxisDirection.PositiveY:
                    axisIndex = 1;
                    sign = 1;
                    break;
                case LocalAxisDirection.NegativeY:
                    axisIndex = 1;
                    sign = -1;
                    break;
                case LocalAxisDirection.PositiveZ:
                    axisIndex = 2;
                    sign = 1;
                    break;
                case LocalAxisDirection.NegativeZ:
                    axisIndex = 2;
                    sign = -1;
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(axisDirection), axisDirection, null);
            }
        }

        private static Vector3D GetFallbackAxis(LocalAxisDirection axisDirection)
        {
            switch (axisDirection)
            {
                case LocalAxisDirection.PositiveX:
                    return new Vector3D(1, 0, 0);
                case LocalAxisDirection.NegativeX:
                    return new Vector3D(-1, 0, 0);
                case LocalAxisDirection.PositiveY:
                    return new Vector3D(0, 1, 0);
                case LocalAxisDirection.NegativeY:
                    return new Vector3D(0, -1, 0);
                case LocalAxisDirection.PositiveZ:
                    return new Vector3D(0, 0, 1);
                case LocalAxisDirection.NegativeZ:
                    return new Vector3D(0, 0, -1);
                default:
                    throw new ArgumentOutOfRangeException(nameof(axisDirection), axisDirection, null);
            }
        }

        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]
            };
        }

        /// <summary>
        /// 恢复物体到原位置
        /// </summary>
        /// <param name="item">要恢复的物体</param>
        /// <param name="originalOffset">原始移动偏移向量</param>
        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);
        }

        /// <summary>
        /// 将物体移动到指定位置和朝向（先回到CAD原始位置，再移动）
        /// 适用于碰撞位置还原等场景
        /// </summary>
        /// <param name="item">要移动的物体</param>
        /// <param name="targetPosition">目标位置（动画跟踪点，当前统一为几何中心）</param>
        /// <param name="targetYaw">目标朝向（弧度，绕Z轴）</param>
        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 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;

            // 应用增量变换
            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(
                    targetPosition.X - rotatedX,
                    targetPosition.Y - rotatedY,
                    targetPosition.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);
        }

        /// <summary>
        /// 将物体移动到指定位置和完整三维朝向（先回到CAD原始位置，再移动）
        /// </summary>
        public static void MoveItemToPositionAndRotation(ModelItem item, Point3D targetPosition, Rotation3D targetRotation)
        {
            ApplyAbsoluteTransform(item, targetPosition, targetRotation, preserveCurrentScale: false);
        }

        /// <summary>
        /// 将物体移动到指定位置和完整三维朝向，同时保留当前缩放。
        /// </summary>
        public static void MoveItemToPositionAndRotationWithCurrentScale(ModelItem item, Point3D targetPosition, Rotation3D targetRotation)
        {
            ApplyAbsoluteTransform(item, targetPosition, targetRotation, preserveCurrentScale: true);
        }

        /// <summary>
        /// 基于物体当前实际姿态，增量移动到目标位置和完整三维朝向。
        /// 适用于动画过程中的真实模型物体，避免每次回到 CAD 原始状态导致位置跑偏。
        /// </summary>
        public static void MoveItemIncrementallyToPositionAndRotation(
            ModelItem item,
            Point3D currentPosition,
            Rotation3D currentRotation,
            Point3D targetPosition,
            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 deltaLinear = new Transform3D(deltaRotation).Linear;
            var currentLinear = new Transform3D(currentRotation).Linear;
            var targetLinear = new Transform3D(targetRotation).Linear;

            var rotatedCurrentPosition = new Point3D(
                deltaLinear.Get(0, 0) * currentPosition.X + deltaLinear.Get(0, 1) * currentPosition.Y + deltaLinear.Get(0, 2) * currentPosition.Z,
                deltaLinear.Get(1, 0) * currentPosition.X + deltaLinear.Get(1, 1) * currentPosition.Y + deltaLinear.Get(1, 2) * currentPosition.Z,
                deltaLinear.Get(2, 0) * currentPosition.X + deltaLinear.Get(2, 1) * currentPosition.Y + deltaLinear.Get(2, 2) * currentPosition.Z);

            var translation = new Vector3D(
                targetPosition.X - rotatedCurrentPosition.X,
                targetPosition.Y - rotatedCurrentPosition.Y,
                targetPosition.Z - rotatedCurrentPosition.Z);

            LogManager.Debug(
                $"[模型增量姿态] {item.DisplayName} 当前=({currentPosition.X:F3},{currentPosition.Y:F3},{currentPosition.Z:F3}), " +
                $"目标=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                $"平移=({translation.X:F3},{translation.Y:F3},{translation.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})");

            LogManager.Debug(
                $"[模型增量姿态] {item.DisplayName} 增量旋转: " +
                $"X=({deltaLinear.Get(0, 0):F4},{deltaLinear.Get(1, 0):F4},{deltaLinear.Get(2, 0):F4}), " +
                $"Y=({deltaLinear.Get(0, 1):F4},{deltaLinear.Get(1, 1):F4},{deltaLinear.Get(2, 1):F4}), " +
                $"Z=({deltaLinear.Get(0, 2):F4},{deltaLinear.Get(1, 2):F4},{deltaLinear.Get(2, 2):F4}), " +
                $"旋后当前点=({rotatedCurrentPosition.X:F3},{rotatedCurrentPosition.Y:F3},{rotatedCurrentPosition.Z:F3})");

            LogGeometryLevelTransforms(item, "[模型增量姿态应用前][GeometryAPI]");

            // 用显式三步法应用三维增量位姿：
            // 1. 把当前锚点移到原点
            // 2. 绕原点旋转到目标姿态
            // 3. 再把锚点移到目标位置
            // 这与旧 yaw 链路的补偿语义一致，只是从二维扩展到三维。
            var toOrigin = Transform3D.CreateTranslation(new Vector3D(
                -currentPosition.X,
                -currentPosition.Y,
                -currentPosition.Z));
            doc.Models.OverridePermanentTransform(modelItems, toOrigin, false);

            var rotationOnlyComponents = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)).Factor();
            rotationOnlyComponents.Rotation = deltaRotation;
            var rotationOnly = rotationOnlyComponents.Combine();
            doc.Models.OverridePermanentTransform(modelItems, rotationOnly, false);

            var toTarget = Transform3D.CreateTranslation(new Vector3D(
                targetPosition.X,
                targetPosition.Y,
                targetPosition.Z));
            doc.Models.OverridePermanentTransform(modelItems, toTarget, false);

            LogIncrementalTransformActual(item, targetPosition, targetRotation);
        }

        /// <summary>
        /// 合并三次绕宿主轴的旋转 + 一次平移为单次 OverridePermanentTransform 调用。
        /// 等价于依次调用三次 MoveItemIncrementallyByAxisRotationAndTranslation，但 NW API 调用次数减少 66%。
        /// </summary>
        public static void MoveItemCombinedAxisRotationAndTranslation(
            ModelItem item,
            Point3D trackedPosition,
            Vector3 axis1, double angle1Radians,
            Vector3 axis2, double angle2Radians,
            Vector3 axis3, double angle3Radians,
            Point3D targetPosition)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));

            // 用 System.Numerics 合成三个旋转
            var q1 = Quaternion.CreateFromAxisAngle(Vector3.Normalize(axis1), (float)angle1Radians);
            var q2 = Quaternion.CreateFromAxisAngle(Vector3.Normalize(axis2), (float)angle2Radians);
            var q3 = Quaternion.CreateFromAxisAngle(Vector3.Normalize(axis3), (float)angle3Radians);
            // q3 * q2 * q1: apply q1 first, then q2, then q3（与 Override 左乘积累顺序一致）
            var totalQ = Quaternion.Normalize(q3 * q2 * q1);

            // 计算旋后跟踪点位置
            var tp = new Vector3((float)trackedPosition.X, (float)trackedPosition.Y, (float)trackedPosition.Z);
            var rotatedTp = Vector3.Transform(tp, totalQ);

            // 计算组合变换（调用方已在 RestoreObjectToCADPosition 中执行 ResetPermanentTransform，此处不重复）
            var doc = Application.ActiveDocument;
            var modelItems = new ModelItemCollection { item };

            var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
            var components = identity.Factor();
            components.Rotation = new Rotation3D(totalQ.X, totalQ.Y, totalQ.Z, totalQ.W);
            components.Translation = new Vector3D(
                targetPosition.X - rotatedTp.X,
                targetPosition.Y - rotatedTp.Y,
                targetPosition.Z - rotatedTp.Z);
            var combined = components.Combine();

            LogManager.Debug(
                $"[组合旋转平移] tracked=({trackedPosition.X:F3},{trackedPosition.Y:F3},{trackedPosition.Z:F3}), " +
                $"target=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                $"translation=({components.Translation.X:F3},{components.Translation.Y:F3},{components.Translation.Z:F3})");

            doc.Models.OverridePermanentTransform(modelItems, combined, false);
        }

        /// <summary>
        /// 直接对当前显示结果施加宿主轴旋转增量，再补一段平移把业务跟踪点拉回目标点。
        /// 不先构造 targetRotation，也不从 current/target 姿态反推 deltaRotation。
        /// </summary>
        public static void MoveItemIncrementallyByAxisRotationAndTranslation(
            ModelItem item,
            Point3D currentPosition,
            Vector3 hostAxis,
            double deltaAngleRadians,
            Point3D targetPosition)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (hostAxis.LengthSquared() < 1e-12f)
            {
                throw new ArgumentException("hostAxis must be non-zero.", nameof(hostAxis));
            }

            Vector3 normalizedHostAxis = Vector3.Normalize(hostAxis);
            Rotation3D deltaRotation = new Rotation3D(
                new UnitVector3D(normalizedHostAxis.X, normalizedHostAxis.Y, normalizedHostAxis.Z),
                deltaAngleRadians);
            Matrix3 deltaLinear = new Transform3D(deltaRotation).Linear;
            Point3D rotatedCurrentPosition = new Point3D(
                deltaLinear.Get(0, 0) * currentPosition.X + deltaLinear.Get(0, 1) * currentPosition.Y + deltaLinear.Get(0, 2) * currentPosition.Z,
                deltaLinear.Get(1, 0) * currentPosition.X + deltaLinear.Get(1, 1) * currentPosition.Y + deltaLinear.Get(1, 2) * currentPosition.Z,
                deltaLinear.Get(2, 0) * currentPosition.X + deltaLinear.Get(2, 1) * currentPosition.Y + deltaLinear.Get(2, 2) * currentPosition.Z);

            Vector3D compensatedTranslation = new Vector3D(
                targetPosition.X - rotatedCurrentPosition.X,
                targetPosition.Y - rotatedCurrentPosition.Y,
                targetPosition.Z - rotatedCurrentPosition.Z);

            LogManager.Debug(
                $"[模型纯增量旋转平移] {item.DisplayName} 当前=({currentPosition.X:F3},{currentPosition.Y:F3},{currentPosition.Z:F3}), " +
                $"目标=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                $"Axis=({normalizedHostAxis.X:F4},{normalizedHostAxis.Y:F4},{normalizedHostAxis.Z:F4}), " +
                $"Angle={deltaAngleRadians * 180.0 / Math.PI:F2}°, " +
                $"旋后当前点=({rotatedCurrentPosition.X:F3},{rotatedCurrentPosition.Y:F3},{rotatedCurrentPosition.Z:F3}), " +
                $"平移=({compensatedTranslation.X:F3},{compensatedTranslation.Y:F3},{compensatedTranslation.Z:F3})");

            var doc = Application.ActiveDocument;
            var modelItems = new ModelItemCollection { item };
            LogGeometryLevelTransforms(item, "[模型纯增量旋转平移应用前][GeometryAPI]");

            var toOrigin = Transform3D.CreateTranslation(new Vector3D(
                -currentPosition.X,
                -currentPosition.Y,
                -currentPosition.Z));
            doc.Models.OverridePermanentTransform(modelItems, toOrigin, false);

            var rotationOnlyComponents = Transform3D.CreateTranslation(new Vector3D(0, 0, 0)).Factor();
            rotationOnlyComponents.Rotation = deltaRotation;
            var rotationOnly = rotationOnlyComponents.Combine();
            doc.Models.OverridePermanentTransform(modelItems, rotationOnly, false);

            var toTarget = Transform3D.CreateTranslation(new Vector3D(
                targetPosition.X,
                targetPosition.Y,
                targetPosition.Z));
            doc.Models.OverridePermanentTransform(modelItems, toTarget, false);

            LogGeometryLevelTransforms(item, "[模型纯增量旋转平移应用后][GeometryAPI]");
        }

        /// <summary>
        /// 读取物体当前实际几何姿态。
        /// 优先使用 ModelGeometry.ActiveTransform，因为 ModelItem.Transform 只反映原始设计变换。
        /// </summary>
        public static bool TryGetCurrentGeometryRotation(ModelItem item, out Rotation3D rotation)
        {
            rotation = Rotation3D.Identity;
            if (item == null)
            {
                return false;
            }

            try
            {
                ModelGeometry geometry = item.FindFirstGeometry() ?? item.Geometry;
                if (geometry?.ActiveTransform == null)
                {
                    return false;
                }

                rotation = geometry.ActiveTransform.Factor().Rotation;
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[当前几何姿态] 读取 ActiveTransform 失败: {ex.Message}");
                return false;
            }
        }

        public static bool TryGetCurrentOverrideRotation(ModelItem item, out Rotation3D rotation)
        {
            rotation = Rotation3D.Identity;
            if (item == null)
            {
                return false;
            }

            try
            {
                ModelGeometry geometry = item.FindFirstGeometry() ?? item.Geometry;
                if (geometry?.PermanentOverrideTransform == null)
                {
                    return true;
                }

                rotation = geometry.PermanentOverrideTransform.Factor().Rotation;
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[当前覆盖姿态] 读取 PermanentOverrideTransform 失败: {ex.Message}");
                return false;
            }
        }

        public static bool TryResolveOverrideRotationForFinalTarget(
            ModelItem item,
            Rotation3D finalTargetRotation,
            out Rotation3D overrideRotation)
        {
            overrideRotation = Rotation3D.Identity;
            if (item == null)
            {
                return false;
            }

            try
            {
                ModelGeometry geometry = item.FindFirstGeometry() ?? item.Geometry;
                Transform3D originalTransform = geometry?.OriginalTransform ?? item.Transform;
                Rotation3D originalRotation = originalTransform.Factor().Rotation;
                var originalInverse = originalRotation.Invert();
                var overrideTransform = Transform3D.Multiply(
                    new Transform3D(originalInverse),
                    new Transform3D(finalTargetRotation));
                overrideRotation = overrideTransform.Factor().Rotation;
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[覆盖姿态换算] 计算 override 姿态失败: {ex.Message}");
                return false;
            }
        }

        public static void LogCurrentGeometryTransformsForDebug(ModelItem item, string prefix)
        {
            LogGeometryLevelTransforms(item, prefix);
        }

        private static void LogIncrementalTransformActual(ModelItem item, Point3D targetPosition, Rotation3D targetRotation)
        {
            try
            {
                var actualBounds = item.BoundingBox();
                var actualTransform = item.Transform;
                var actualRotation = actualTransform.Factor().Rotation;
                var actualLinear = new Transform3D(actualRotation).Linear;
                var targetLinear = new Transform3D(targetRotation).Linear;
            var actualPosition = actualBounds.Center;

                LogManager.Debug(
                    $"[模型增量姿态] {item.DisplayName} 立即读回位置(可能滞后): " +
                    $"实际=({actualPosition.X:F3},{actualPosition.Y:F3},{actualPosition.Z:F3}), " +
                    $"期望=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                    $"偏差=({actualPosition.X - targetPosition.X:F3},{actualPosition.Y - targetPosition.Y:F3},{actualPosition.Z - targetPosition.Z:F3})");

                LogManager.Debug(
                    $"[模型增量姿态] {item.DisplayName} 立即读回旋转(可能滞后/不反映override): " +
                    $"实际X=({actualLinear.Get(0, 0):F4},{actualLinear.Get(1, 0):F4},{actualLinear.Get(2, 0):F4}), " +
                    $"实际Y=({actualLinear.Get(0, 1):F4},{actualLinear.Get(1, 1):F4},{actualLinear.Get(2, 1):F4}), " +
                    $"实际Z=({actualLinear.Get(0, 2):F4},{actualLinear.Get(1, 2):F4},{actualLinear.Get(2, 2):F4}), " +
                    $"期望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]");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[模型增量姿态] 输出应用后日志失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 将物体移动到指定中心点和完整三维朝向，同时保留当前缩放。
        /// 仅适用于“几何中心就是业务定位点”的实体，例如参考杆、辅助几何、虚拟包围盒。
        /// 不适用于真实模型物体的动画、碰撞验证或场景恢复；真实模型应使用增量三步法，
        /// 即先将固定参考点移到原点，再旋转，再移动到目标位置。
        /// </summary>
        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);
        }

        /// <summary>
        /// 将物体移动到指定中心点和完整三维朝向。
        /// 仅应用位置和旋转，不保留当前缩放。
        /// 仅适用于“几何中心就是业务定位点”的实体，例如缩放已经在 Model 层完成的参考杆。
        /// 不适用于真实模型物体的动画、碰撞验证或场景恢复；真实模型应使用增量三步法，
        /// 即先将固定参考点移到原点，再旋转，再移动到目标位置。
        /// </summary>
        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);
        }

        /// <summary>
        /// 将物体的局部正 X 端面中心对齐到目标点，并保留当前缩放。
        /// 适用于单位立方体/单位圆柱体沿 +X 定义长度方向的参考杆资源。
        /// </summary>
        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);
        }

        /// <summary>
        /// 将物体的局部正 X 端面中心对齐到目标点。
        /// 仅应用位置和旋转，不保留当前缩放。
        /// 适用于缩放已经在 Model 层完成、Item 层只负责定位的场景。
        /// </summary>
        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);
            ModelGeometry geometry = item.FindFirstGeometry() ?? item.Geometry;

            if (preserveCurrentScale)
            {
                var currentBaseTransform = geometry?.PermanentOverrideTransform ?? item.Transform;
                var currentComponents = currentBaseTransform.Factor();
                currentScale = currentComponents.Scale;
            }

            doc.Models.ResetPermanentTransform(modelItems);

            var originalTransform = geometry?.OriginalTransform ?? item.Transform;
            var originalComponents = originalTransform.Factor();
            var originalRotation = originalComponents.Rotation;
            var originalBounds = geometry?.BoundingBox ?? item.BoundingBox();
            var originalCenterPos = originalBounds.Center;

            Rotation3D deltaRotation = BuildDeltaRotation(originalRotation, targetRotation);
            var rotationTransform = new Transform3D(deltaRotation);
            var linear = rotationTransform.Linear;

            var rotatedCenterPos = new Point3D(
                linear.Get(0, 0) * originalCenterPos.X + linear.Get(0, 1) * originalCenterPos.Y + linear.Get(0, 2) * originalCenterPos.Z,
                linear.Get(1, 0) * originalCenterPos.X + linear.Get(1, 1) * originalCenterPos.Y + linear.Get(1, 2) * originalCenterPos.Z,
                linear.Get(2, 0) * originalCenterPos.X + linear.Get(2, 1) * originalCenterPos.Y + linear.Get(2, 2) * originalCenterPos.Z
            );

            var translation = new Vector3D(
                targetPosition.X - rotatedCenterPos.X,
                targetPosition.Y - rotatedCenterPos.Y,
                targetPosition.Z - rotatedCenterPos.Z
            );

            Transform3D transform;
            if (preserveCurrentScale)
            {
                var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
                var components = identity.Factor();
                components.Scale = currentScale;
                components.Rotation = deltaRotation;
                components.Translation = translation;
                transform = components.Combine();
            }
            else
            {
                transform = new Transform3D(deltaRotation, translation);
            }

            LogAbsoluteTransformDiagnostics(item, originalRotation, targetRotation, deltaRotation, originalCenterPos, targetPosition, translation);
            doc.Models.OverridePermanentTransform(modelItems, transform, false);
            LogAbsoluteTransformActual(item, preserveCurrentScale, currentScale, targetPosition, targetRotation);
        }

        private static Rotation3D BuildDeltaRotation(Rotation3D originalRotation, Rotation3D targetRotation)
        {
            var originalInverse = originalRotation.Invert();
            var deltaTransform = Transform3D.Multiply(
                new Transform3D(targetRotation),
                new Transform3D(originalInverse));
            return deltaTransform.Factor().Rotation;
        }

        private static void LogAbsoluteTransformDiagnostics(
            ModelItem item,
            Rotation3D originalRotation,
            Rotation3D targetRotation,
            Rotation3D deltaRotation,
            Point3D originalTrackedPosition,
            Point3D targetPosition,
            Vector3D translation)
        {
            try
            {
                var originalLinear = new Transform3D(originalRotation).Linear;
                var targetLinear = new Transform3D(targetRotation).Linear;
                var deltaLinear = new Transform3D(deltaRotation).Linear;

                LogManager.Debug(
                    $"[模型姿态] {item.DisplayName} 原始: " +
                    $"X=({originalLinear.Get(0, 0):F4},{originalLinear.Get(1, 0):F4},{originalLinear.Get(2, 0):F4}), " +
                    $"Y=({originalLinear.Get(0, 1):F4},{originalLinear.Get(1, 1):F4},{originalLinear.Get(2, 1):F4}), " +
                    $"Z=({originalLinear.Get(0, 2):F4},{originalLinear.Get(1, 2):F4},{originalLinear.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})");

                LogManager.Debug(
                    $"[模型姿态] {item.DisplayName} 增量: " +
                    $"X=({deltaLinear.Get(0, 0):F4},{deltaLinear.Get(1, 0):F4},{deltaLinear.Get(2, 0):F4}), " +
                    $"Y=({deltaLinear.Get(0, 1):F4},{deltaLinear.Get(1, 1):F4},{deltaLinear.Get(2, 1):F4}), " +
                    $"Z=({deltaLinear.Get(0, 2):F4},{deltaLinear.Get(1, 2):F4},{deltaLinear.Get(2, 2):F4}), " +
                    $"原始跟踪点=({originalTrackedPosition.X:F3},{originalTrackedPosition.Y:F3},{originalTrackedPosition.Z:F3}), " +
                    $"目标跟踪点=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                    $"平移=({translation.X:F3},{translation.Y:F3},{translation.Z:F3})");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[模型姿态] 输出诊断日志失败: {ex.Message}");
            }
        }

        private static void LogAbsoluteTransformActual(
            ModelItem item,
            bool preserveCurrentScale,
            Vector3D currentScale,
            Point3D targetPosition,
            Rotation3D targetRotation)
        {
            try
            {
                Transform3D actualTransform = item.Transform;
                var actualComponents = actualTransform.Factor();
                var actualRotation = actualComponents.Rotation;
                var actualScale = actualComponents.Scale;
                var actualLinear = new Transform3D(actualRotation).Linear;
                var targetLinear = new Transform3D(targetRotation).Linear;
                var actualBounds = item.BoundingBox();
                Point3D actualCenter = actualBounds?.Center ?? new Point3D(0, 0, 0);

                LogManager.Debug(
                    $"[模型姿态应用后] {item.DisplayName} PreserveScale={preserveCurrentScale}, " +
                    $"输入Scale=({currentScale.X:F4},{currentScale.Y:F4},{currentScale.Z:F4}), " +
                    $"实际Scale=({actualScale.X:F4},{actualScale.Y:F4},{actualScale.Z:F4}), " +
                    $"目标中心=({targetPosition.X:F3},{targetPosition.Y:F3},{targetPosition.Z:F3}), " +
                    $"实际中心=({actualCenter.X:F3},{actualCenter.Y:F3},{actualCenter.Z:F3})");

                LogManager.Debug(
                    $"[模型姿态应用后] {item.DisplayName} 目标Transform轴: " +
                    $"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})");

                LogManager.Debug(
                    $"[模型姿态应用后] {item.DisplayName} 实际Transform轴: " +
                    $"X=({actualLinear.Get(0, 0):F4},{actualLinear.Get(1, 0):F4},{actualLinear.Get(2, 0):F4}), " +
                    $"Y=({actualLinear.Get(0, 1):F4},{actualLinear.Get(1, 1):F4},{actualLinear.Get(2, 1):F4}), " +
                    $"Z=({actualLinear.Get(0, 2):F4},{actualLinear.Get(1, 2):F4},{actualLinear.Get(2, 2):F4})");

                LogGeometryLevelTransforms(item, "[模型姿态应用后][GeometryAPI]");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[模型姿态应用后] 输出诊断日志失败: {ex.Message}");
            }
        }

        private static void LogGeometryLevelTransforms(ModelItem item, string prefix)
        {
            if (item == null)
            {
                return;
            }

            try
            {
                ModelGeometry geometry = item.FindFirstGeometry() ?? item.Geometry;
                if (geometry == null)
                {
                    LogManager.Debug($"{prefix} Geometry=null");
                    return;
                }

                LogManager.Debug(
                    $"{prefix} GeometryType={geometry.GetType().FullName}, " +
                    $"FragmentCount={geometry.FragmentCount}, " +
                    $"BoundsCenter=({geometry.BoundingBox.Center.X:F3},{geometry.BoundingBox.Center.Y:F3},{geometry.BoundingBox.Center.Z:F3})");

                LogTransformProperty(geometry.OriginalTransform, $"{prefix} OriginalTransform");
                LogTransformProperty(geometry.PermanentOverrideTransform, $"{prefix} PermanentOverrideTransform");
                LogTransformProperty(geometry.PermanentTransform, $"{prefix} PermanentTransform");
                LogTransformProperty(geometry.ActiveTransform, $"{prefix} ActiveTransform");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"{prefix} 读取几何层当前变换失败: {ex.Message}");
            }
        }

        private static void LogTransformProperty(Transform3D transform, string prefix)
        {
            if (transform == null)
            {
                LogManager.Debug($"{prefix}=null");
                return;
            }

            try
            {
                var linear = transform.Linear;
                var components = transform.Factor();
                LogManager.Debug(
                    $"{prefix}: " +
                    $"X=({linear.Get(0, 0):F4},{linear.Get(1, 0):F4},{linear.Get(2, 0):F4}), " +
                    $"Y=({linear.Get(0, 1):F4},{linear.Get(1, 1):F4},{linear.Get(2, 1):F4}), " +
                    $"Z=({linear.Get(0, 2):F4},{linear.Get(1, 2):F4},{linear.Get(2, 2):F4}), " +
                    $"T=({components.Translation.X:F3},{components.Translation.Y:F3},{components.Translation.Z:F3})");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"{prefix} 读取失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 将物体移动到指定位置和朝向，同时保持缩放比例
        /// 专为虚拟物体设计，避免缩放被覆盖
        /// </summary>
        /// <param name="item">要移动的物体</param>
        /// <param name="targetPosition">目标位置（地面位置）</param>
        /// <param name="targetYaw">目标朝向（弧度）</param>
        /// <param name="scaleX">X方向缩放</param>
        /// <param name="scaleY">Y方向缩放</param>
        /// <param name="scaleZ">Z方向缩放</param>
        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 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 = 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 = 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);
        }

        /// <summary>
        /// 物体状态快照，用于保存和恢复
        /// </summary>
        public class ObjectStateSnapshot
        {
            public Point3D Position { get; set; }
            public Rotation3D Rotation { get; set; }
            public bool HasCustomRotation { get; set; }
        }
    }
}
