diff --git a/.agents/skills/nw-api/SKILL.md b/.agents/skills/nw-api/SKILL.md index c08dd29..0f96cd5 100644 --- a/.agents/skills/nw-api/SKILL.md +++ b/.agents/skills/nw-api/SKILL.md @@ -16,7 +16,9 @@ description: Navisworks API 开发助手,用于开发 Navisworks 插件。功 | NET API | `doc/navisworks_api/NET/documentation/NET API.chm` | CHM 帮助文件 | | NET API HTML | `doc/navisworks_api/NET/documentation/NetAPIHtml/` | HTML 文档 | -**HTML 文档入口**: `doc/navisworks_api/NET/documentation/NetAPIHtml/html/index.html` +**推荐导航入口**: `doc/navisworks_api/NET/documentation/NetAPIHtml/index.html` + +**原始 HTML 文档入口**: `doc/navisworks_api/NET/documentation/NetAPIHtml/html/index.html` ### API 文档搜索方法 diff --git a/AGENTS.md b/AGENTS.md index 6eb1690..745e39b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -361,19 +361,37 @@ var rotation = new Rotation3D(qw, qx, qy, qz); // 错误 ## 5. 开发原则 -### 5.1 不向后兼容 +### 5.1 彻底禁止 fallback -项目只针对 Navisworks 2026。不要写旧版本兼容代码。 +这是当前项目的第一编码原则,优先级高于其他“先跑起来”的考虑。 -### 5.2 不要随意加 fallback +不允许出现以下行为: -不要为了“先跑起来”就: +- 新姿态链失败时,静默退回旧姿态链 +- 新变换链失败时,静默退回旧变换链 +- 正确姿势/正确位置/正确尺寸语义拿不到时,用“差不多”的旧值、缓存值、默认值顶上 +- 只打印一条 warning,然后继续使用错误语义把流程跑完 + +尤其禁止这类做法: - 偷偷退回旧 `yaw` - 偷偷用硬编码 `Z-up` - 偷偷在错误时给默认值掩盖问题 +- 偷偷在新链失败时自动掉回旧链 +- 读不到当前实际几何旋转时,回退到 `_trackedRotation` +- 读不到当前真实姿态时,回退到 `referenceRotation` +- 读不到当前显示姿态时,回退到 `ModelItem.Transform` -如果完整姿态链失败,应优先暴露问题并修根因。 +正确做法只有两种: + +1. 在进入新链前把前置条件补齐 +2. 直接暴露失败并修根因 + +不允许把“旧链兜底”当成正式实现的一部分。 + +### 5.2 不向后兼容 + +项目只针对 Navisworks 2026。不要写旧版本兼容代码。 ### 5.3 临时补丁不是正式实现 diff --git a/doc/working/2026-04-06-navisworks-transform-api-official-reference.md b/doc/working/2026-04-06-navisworks-transform-api-official-reference.md new file mode 100644 index 0000000..a8be570 --- /dev/null +++ b/doc/working/2026-04-06-navisworks-transform-api-official-reference.md @@ -0,0 +1,1012 @@ +# Navisworks 变换 API 官方原始定义整理 + +更新时间:2026-04-06 + +本文只整理当前讨论中直接用到的 Navisworks .NET API 官方原始定义与语法。 + +原则: + +- 正文尽量保留官方原始内容 +- 不混入项目内部“局部坐标系”“参考姿态”等二次解释 +- 如果官方示例目录中未找到对应 API 的直接示例,就如实记录“未找到直接示例” +- 只在最后增加一段简短归纳 + +--- + +## 1. `DocumentModels.OverridePermanentTransform(...)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_DocumentParts_DocumentModels_OverridePermanentTransform_3_131351c5.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_DocumentParts_DocumentModels_OverridePermanentTransform_3_131351c5.htm) + +官方标题: + +```text +DocumentModels.OverridePermanentTransform Method +``` + +官方定义: + +```text +Apply an incremental transform to a selection. +``` + +官方 C# 语法: + +```csharp +public void OverridePermanentTransform( + IEnumerable items, + Transform3D transform, + bool updateModelTransform +) +``` + +官方 Remarks: + +```text +If the selection contains any files, and the updateModelTransform +parameter is true, then instead of applying a transform to the +fragments, the File Units and Transform will be updated. +``` + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该方法的直接示例代码。 +``` + +--- + +## 2. `DocumentModels.ResetPermanentTransform(...)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_DocumentParts_DocumentModels_ResetPermanentTransform_1_75193b86.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_DocumentParts_DocumentModels_ResetPermanentTransform_1_75193b86.htm) + +官方标题: + +```text +DocumentModels.ResetPermanentTransform Method +``` + +官方定义: + +```text +Reset incremental transforms for all model items contained in the selection. +``` + +官方 C# 语法: + +```csharp +public void ResetPermanentTransform( + IEnumerable items +) +``` + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该方法的直接示例代码。 +``` + +--- + +## 3. `ModelGeometry.ActiveTransform` + +官方文档: + +- [P_Autodesk_Navisworks_Api_ModelGeometry_ActiveTransform.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/P_Autodesk_Navisworks_Api_ModelGeometry_ActiveTransform.htm) + +官方标题: + +```text +ModelGeometry.ActiveTransform Property +``` + +官方定义: + +```text +Returns the currently active transform of the geometry. +``` + +官方 C# 语法: + +```csharp +public Transform3D ActiveTransform { get; } +``` + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该属性的直接示例代码。 +``` + +--- + +## 4. `Transform3D` + +官方文档: + +- [T_Autodesk_Navisworks_Api_Transform3D.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/T_Autodesk_Navisworks_Api_Transform3D.htm) + +官方标题: + +```text +Transform3D Class +``` + +官方定义: + +```text +A generic transformation in 3D space. +``` + +官方 Remarks: + +```text +Considered an immutable value type. +``` + +官方 C# 类型语法: + +```csharp +public class Transform3D : NativeHandle +``` + +官方成员页中可见的相关构造/工厂: + +- `Transform3D(Rotation3D)` +- `Transform3D(Matrix3, Vector3D)` +- `Transform3D(Rotation3D, Vector3D)` +- `CreateIdentity()` +- `CreateTranslation(Vector3D)` + +来源: + +- [AllMembers_T_Autodesk_Navisworks_Api_Transform3D.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/AllMembers_T_Autodesk_Navisworks_Api_Transform3D.htm) + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该类型的直接示例代码。 +``` + +--- + +## 5. `Transform3D(Rotation3D)` + +官方文档: + +- [C_Autodesk_Navisworks_Api_Transform3D_ctor_1_73bf3bc1.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/C_Autodesk_Navisworks_Api_Transform3D_ctor_1_73bf3bc1.htm) + +官方定义: + +```text +Make a transform from a rotation (3D homogenous). +``` + +官方 C# 语法: + +```csharp +public Transform3D( + Rotation3D rotation +) +``` + +--- + +## 6. `Transform3D(Rotation3D, Vector3D)` + +官方文档: + +- [C_Autodesk_Navisworks_Api_Transform3D_ctor_2_499970f8.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/C_Autodesk_Navisworks_Api_Transform3D_ctor_2_499970f8.htm) + +官方定义: + +```text +Make a transform from a rotation and a translation. +``` + +官方 C# 语法: + +```csharp +public Transform3D( + Rotation3D rotation, + Vector3D translation +) +``` + +--- + +## 7. `Transform3D.CreateIdentity()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_CreateIdentity.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_CreateIdentity.htm) + +官方定义: + +```text +Create an identity transform. +``` + +官方 C# 语法: + +```csharp +public static Transform3D CreateIdentity() +``` + +--- + +## 8. `Transform3D.CreateTranslation(Vector3D)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_CreateTranslation_1_aa2b59dc.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_CreateTranslation_1_aa2b59dc.htm) + +官方定义: + +```text +Set matrix to be 3D homogenous translation matrix. +``` + +官方 C# 语法: + +```csharp +public static Transform3D CreateTranslation( + Vector3D translation +) +``` + +--- + +## 9. `Rotation3D(UnitVector3D, Double)` + +官方文档: + +- [C_Autodesk_Navisworks_Api_Rotation3D_ctor_2_a6cb51d1.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/C_Autodesk_Navisworks_Api_Rotation3D_ctor_2_a6cb51d1.htm) + +官方定义: + +```text +Create a rotation as a rotation about an axis by an angle. +``` + +官方 C# 语法: + +```csharp +public Rotation3D( + UnitVector3D axis, + double angle +) +``` + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该构造函数的直接示例代码。 +``` + +--- + +## 10. `Transform3D.Inverse()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Inverse.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Inverse.htm) + +官方定义: + +```text +Return inverse transformation. +``` + +官方 C# 语法: + +```csharp +public Transform3D Inverse() +``` + +--- + +## 11. `Transform3D.Multiply(Transform3D, Transform3D)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Multiply_2_141222c1.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Multiply_2_141222c1.htm) + +官方定义: + +```text +Multiply two transformations in the order supplied. +``` + +官方 C# 语法: + +```csharp +public static Transform3D Multiply( + Transform3D left, + Transform3D right +) +``` + +--- + +## 12. 当前已用实验钉死的最小用法 + +本节不是官方原文,而是基于上面这些官方 API 和本仓库 `ReadTransformTestCommand` 的实验结果整理出的最小结论。 + +### 12.1 宿主世界轴直接转 90° 的 API 参数 + +`90°` 在 API 中应写成弧度: + +```csharp +Math.PI / 2.0 +``` + +宿主世界轴应直接使用世界单位轴: + +```csharp +var hostX = new UnitVector3D(1, 0, 0); +var hostY = new UnitVector3D(0, 1, 0); +var hostZ = new UnitVector3D(0, 0, 1); +``` + +对应的旋转对象写法: + +```csharp +var rx90 = new Rotation3D(hostX, Math.PI / 2.0); +var ry90 = new Rotation3D(hostY, Math.PI / 2.0); +var rz90 = new Rotation3D(hostZ, Math.PI / 2.0); +``` + +如果要直接喂给 `OverridePermanentTransform(...)`: + +```csharp +var transform = new Transform3D(ry90); +doc.Models.OverridePermanentTransform(items, transform, false); +``` + +### 12.2 从当前姿态到目标姿态的纯旋转增量 + +当前实验已经验证: + +```csharp +deltaRotation = currentInverse * target +``` + +在 API 上应写成: + +```csharp +var currentTransform = new Transform3D(currentRotation); +var targetTransform = new Transform3D(targetRotation); +var deltaTransform = Transform3D.Multiply( + currentTransform.Inverse(), + targetTransform); +``` + +已验证: + +- `currentInverse * target` 对 +- `target * currentInverse` 不对 + +### 12.3 纯旋转增量的默认旋转中心 + +当前实验已验证: + +- `OverridePermanentTransform(..., rotationOnly, false)` 的纯旋转增量默认绕宿主原点 `(0,0,0)` 生效 + +因此: + +- 不能把纯旋转理解成“围绕当前业务跟踪点原地自转” +- 对 `Ground + 真实物体`,旋转后必须再单独做位置重对齐 + +--- + +## 9. `Transform3D.Factor(Vector3D worldCenter)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Factor_1_aa2b59dc.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Factor_1_aa2b59dc.htm) + +官方标题: + +```text +Transform3D.Factor Method (Vector3D) +``` + +官方定义: + +```text +Treat as homogenous 3D matrix and factor into scale orientation, scale, rotation and translation components. +``` + +官方 C# 语法: + +```csharp +public Transform3DComponents Factor( + Vector3D worldCenter +) +``` + +目前从官方原文可确认: + +- 该重载显式接收 `worldCenter` +- 说明 `Transform3D` 的分解结果与指定的世界中心有关 + +当前实验用途: + +- 用它比较“同一个旋转增量”在 + - `worldCenter = (0,0,0)` + - `worldCenter = 基线BoundingBox.Center` +- 两种情况下分解出来的 `Translation` +- 以验证 Navisworks 增量旋转是否表现得像“绕宿主原点旋转” + +--- + +## 9. `Transform3DComponents` + +官方文档: + +- [T_Autodesk_Navisworks_Api_Transform3DComponents.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/T_Autodesk_Navisworks_Api_Transform3DComponents.htm) + +官方标题: + +```text +Transform3DComponents Class +``` + +官方定义: + +```text +Affine transform represented as individual components that combine to form complete transform. Immutable. +``` + +官方 Remarks: + +```text +Affine transform represented as individual components that combine to form complete transform. Immutable. M = c' * so' * s * so * r * c * t * p, where so is scale orientation, s is scale, c is center, r is rotation and t is translation. +``` + +官方 C# 类型语法: + +```csharp +public class Transform3DComponents : NativeHandle +``` + +官方示例情况: + +```text +在官方 NET examples 目录中,未找到该类型的直接示例代码。 +``` + +--- + +## 10. `Transform3DComponents.Translation` + +官方文档: + +- [P_Autodesk_Navisworks_Api_Transform3DComponents_Translation.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/P_Autodesk_Navisworks_Api_Transform3DComponents_Translation.htm) + +官方定义: + +```text +The translation component of the transform. +``` + +官方 C# 语法: + +```csharp +public Vector3D Translation { get; set; } +``` + +--- + +## 11. `Transform3DComponents.Rotation` + +官方文档: + +- [P_Autodesk_Navisworks_Api_Transform3DComponents_Rotation.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/P_Autodesk_Navisworks_Api_Transform3DComponents_Rotation.htm) + +官方定义: + +```text +The rotation component of the transform. +``` + +官方 C# 语法: + +```csharp +public Rotation3D Rotation { get; set; } +``` + +--- + +## 12. `Transform3DComponents.Scale` + +官方文档: + +- [P_Autodesk_Navisworks_Api_Transform3DComponents_Scale.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/P_Autodesk_Navisworks_Api_Transform3DComponents_Scale.htm) + +官方定义: + +```text +The scale component of the transform. +``` + +官方 C# 语法: + +```csharp +public Vector3D Scale { get; set; } +``` + +--- + +## 13. `Transform3DComponents.Combine()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3DComponents_Combine.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3DComponents_Combine.htm) + +官方定义: + +```text +Combine components together into a composite transform. +``` + +官方 C# 语法: + +```csharp +public Transform3D Combine() +``` + +--- + +## 14. `Transform3D.Multiply(Transform3D, Transform3D)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Multiply_2_141222c1.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Multiply_2_141222c1.htm) + +官方定义: + +```text +Multiply two transforms in the order that the arguments are given, and return the result. +``` + +官方 C# 语法: + +```csharp +public static Transform3D Multiply( + Transform3D leftTransform, + Transform3D rightTransform +) +``` + +--- + +## 15. `Transform3D.Factor()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Factor.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Factor.htm) + +官方定义: + +```text +Treat as homogenous 3D matrix and factor into scale orientation, scale, rotation and translation components. +``` + +官方 C# 语法: + +```csharp +public Transform3DComponents Factor() +``` + +--- + +## 16. `Transform3D.Inverse()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_Inverse.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_Inverse.htm) + +官方定义: + +```text +Return inverse of matrix. Matrix must be non-singular (non-zero determinant). +``` + +官方 C# 语法: + +```csharp +public Transform3D Inverse() +``` + +官方异常说明: + +```text +ObjectDisposedException +Object has been Disposed +``` + +--- + +## 17. `Transform3D.TranslateRight(Vector3D, Transform3D)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Transform3D_TranslateRight_2_9ab750ca.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Transform3D_TranslateRight_2_9ab750ca.htm) + +官方定义: + +```text +Translate a transform by a vector. +``` + +官方 C# 语法: + +```csharp +public static Transform3D TranslateRight( + Vector3D translation, + Transform3D transform +) +``` + +--- + +## 18. `Rotation3D` + +官方文档: + +- [T_Autodesk_Navisworks_Api_Rotation3D.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/T_Autodesk_Navisworks_Api_Rotation3D.htm) + +官方 C# 类型语法: + +```csharp +public class Rotation3D : NativeHandle +``` + +--- + +## 19. `Rotation3D(UnitVector3D, Double)` + +官方文档: + +- [C_Autodesk_Navisworks_Api_Rotation3D_ctor_2_afd1d818.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/C_Autodesk_Navisworks_Api_Rotation3D_ctor_2_afd1d818.htm) + +官方定义: + +```text +Creates rotation about given axis by angle in radians +``` + +官方 C# 语法: + +```csharp +public Rotation3D( + UnitVector3D axis, + double angle +) +``` + +--- + +## 20. `Rotation3D.CreateFromEulerAngles(Double, Double, Double)` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Rotation3D_CreateFromEulerAngles_3_d36b82d7.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Rotation3D_CreateFromEulerAngles_3_d36b82d7.htm) + +官方定义: + +```text +Creates a Euler angle rotation. +Parameters are in radians. +Rotation is created by combination of rotations about X, Y and Z axes. +``` + +官方 C# 语法: + +```csharp +public static Rotation3D CreateFromEulerAngles( + double x, + double y, + double z +) +``` + +--- + +## 21. `Rotation3D.ToAxisAndAngle()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Rotation3D_ToAxisAndAngle.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Rotation3D_ToAxisAndAngle.htm) + +官方定义: + +```text +Calculates an axis and angle representation of this rotation. +``` + +官方 C# 语法: + +```csharp +public AxisAndAngleResult ToAxisAndAngle() +``` + +--- + +## 22. `Rotation3D.ToEulerAngles()` + +官方文档: + +- [M_Autodesk_Navisworks_Api_Rotation3D_ToEulerAngles.htm](/C:/Users/Tellme/apps/NavisworksTransport/doc/navisworks_api/NET/documentation/NetAPIHtml/html/M_Autodesk_Navisworks_Api_Rotation3D_ToEulerAngles.htm) + +官方定义: + +```text +Calculates the Euler angles for this rotation. +``` + +官方 C# 语法: + +```csharp +public EulerAngleResult ToEulerAngles() +``` + +--- + +## 23. 由官方 API 原始定义直接能表达的增量求法 + +这一节不引入项目术语,只把前面几条官方定义并列摆出: + +```text +currentTransform = 当前生效的几何变换(ModelGeometry.ActiveTransform) +targetTransform = 目标完整 Transform3D +currentInverse = currentTransform.Inverse() +incrementalTransform = Transform3D.Multiply(targetTransform, currentInverse) +OverridePermanentTransform(..., incrementalTransform, ...) +``` + +这一段的依据完全来自前文官方定义: + +- `ActiveTransform` = Returns the currently active transform of the geometry. +- `Inverse()` = Return inverse of matrix. +- `Multiply(left, right)` = Multiply two transforms in the order that the arguments are given. +- `OverridePermanentTransform(...)` = Apply an incremental transform to a selection. + +这里只说明“这些 API 可以这样直接串起来表达完整当前变换 -> 目标变换 -> 增量变换”,不额外添加项目侧解释。 + +--- + +## 24. 官方示例检索结果 + +检索范围: + +```text +C:\Users\Tellme\apps\NavisworksTransport\doc\navisworks_api\NET\examples\ +``` + +检索关键词: + +```text +OverridePermanentTransform +ResetPermanentTransform +ActiveTransform +Transform3DComponents +CreateTranslation +new Transform3D( +``` + +检索结论: + +```text +当前官方 NET examples 目录中,未找到这些 API 的直接示例代码。 +``` + +因此本文中的“示例”部分不补写项目侧示例,只保留官方文档中的原始定义与语法。 + +--- + +## 25. 2026-04-06 Transform API 实验结论 + +以下结论来自仓库内实验按钮: + +- [ReadTransformTestCommand.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Commands/ReadTransformTestCommand.cs) + +实验对象: + +```text +Chair Lounge Couch Double +``` + +实验日志位置: + +```text +C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\logs\debug.log +``` + +### 25.1 纯旋转增量的真实行为 + +实验结果表明: + +- 对真实物体调用 + - `OverridePermanentTransform(..., rotationOnly, false)` +- 其视觉效果等价于: + - **绕宿主原点 `(0,0,0)` 旋转** + +已验证的旋转: + +- `X + 90°` +- `Y + 90°` +- `Z + 90°` + +实验日志中,这三项都满足: + +```text +按原点旋转预期Center == 实际Center +误差 = (0, 0, 0) +``` + +因此当前可以视为已证实: + +- `.NET API` 下的纯旋转增量默认不是“围绕对象当前中心自转” +- 而是“围绕宿主原点旋转” + +### 25.2 `Factor(worldCenter)` 的语义价值 + +实验结果表明: + +- 对同一个纯旋转增量: + - `Factor(Vector3D.Zero)` 得到的 `Translation = (0,0,0)` + - `Factor(基线Center)` 会得到非零 `Translation` + +这说明: + +- `Transform3D` 的分解结果确实依赖 `worldCenter` +- `Factor(worldCenter)` 可以用于分析“同一变换相对于不同世界中心的平移语义” + +但它只是: + +- **分解分析 API** + +不是: + +- “设置旋转中心”的构造 API + +### 25.3 “绕指定中心旋转”的三种 API 组合实验 + +我们验证了三种做法,目标都是尝试复现 UI 中“指定变换中心后旋转”的效果。 + +#### 做法 A:直接把 `T(center) * R * T(-center)` 当作增量 + +结果: + +- 不成立 +- 对基线中心的误差为: + +```text +(427.280, -492.199, 0.000) +``` + +#### 做法 B:完整目标左乘 + +做法: + +```text +target = centerRotation * current +incremental = target * current.Inverse() +``` + +结果: + +- 与做法 A 等价 +- 同样不成立 + +#### 做法 C:完整目标右乘 + +做法: + +```text +target = current * centerRotation +incremental = target * current.Inverse() +``` + +结果: + +- 也不成立 +- 误差更大: + +```text +(693.643, 0.000, -689.804) +``` + +### 25.4 当前可以正式采用的结论 + +基于本轮实验,当前可以采用以下工程结论: + +1. `OverridePermanentTransform(..., false)` 的纯旋转增量,默认绕宿主原点旋转。 +2. 当前 `.NET API` 暴露的这套: + - `Transform3D.CreateTranslation` + - `Rotation3D` + - `Transform3D.Multiply` + - `OverridePermanentTransform` + 不能直接复现 UI 的“指定变换中心旋转”语义。 +3. 因此对 `Ground` 这类业务链,不能把问题继续建模成“通过 API 复刻 UI 中心旋转”。 +4. 对 `Ground` 更可靠的策略应是: + - 接受旋转默认绕宿主原点 + - 再基于业务跟踪点语义做位置重对齐 + +### 25.5 当前未证实的事项 + +以下事项目前仍未在原始 API 文档中找到明确说明: + +1. UI 中“变换中心”是否有对应的 .NET API 可直接读写。 +2. UI 的“变换中心旋转”是否走的是另一套未公开的内部机制。 +3. 是否存在未被当前文档索引捕获的 COM API / UI API 可直接设置该中心。 + +--- + +## 26. 归纳 + +基于以上官方原始定义,可以先得到一个非常克制的结论: + +1. `OverridePermanentTransform(...)` 的官方语义就是“应用增量变换”。 +2. `ResetPermanentTransform(...)` 的官方语义就是“重置这层增量变换”。 +3. `ModelGeometry.ActiveTransform` 表示“当前生效的几何变换”。 +4. `Transform3D` / `Transform3DComponents` 官方暴露的核心概念是: + - 平移 + - 旋转 + - 缩放 +5. `Transform3D.Multiply(...)` 官方明确说明“按参数给定顺序相乘”。 +6. `Transform3D.Inverse()` 官方明确是“返回矩阵逆”。 +7. `Rotation3D(UnitVector3D, Double)` 官方明确是“绕给定轴、按弧度创建旋转”。 +8. `Rotation3D.CreateFromEulerAngles(...)` 官方明确是“按 X/Y/Z 轴组合欧拉旋转,参数单位为弧度”。 +9. 这些官方定义里并没有把“局部业务坐标系解释”当成变换 API 的主语。 + +因此,从官方原始定义可以直接得到一个非常具体的增量表达方式: + +- 当前变换:`ModelGeometry.ActiveTransform` +- 目标变换:调用方构造的 `targetTransform` +- 增量变换:`Transform3D.Multiply(targetTransform, currentTransform.Inverse())` +- 应用:`OverridePermanentTransform(...)` + +因此,后续如果要重构真实物体变换工具,更合理的方向是: + +- 先把工具方法收成“宿主坐标系下的平移 / 旋转 / 缩放” +- 再在需要时把它们组合成完整 `Transform3D` +- 再用 `currentTransform.Inverse()` 和 `Transform3D.Multiply(...)` 求增量 +- 最后把这个增量变换交给 `OverridePermanentTransform(...)` + +而不是在变换工具层继续传播 `reference axis / local axis / hostUpLocalAxis` 之类的概念。 + +--- + +## 27. 2026-04-06 当天追加结论 + +基于当天对真实物体、Ground 起点、逐帧、实验按钮的连续实验,可以再补充一条更直接的工程结论: + +1. 对 Navisworks 当前这套增量 API,真正稳定的做法只有**最简单的增量法**: + - 直接构造宿主坐标系下的旋转增量 + - 直接构造宿主坐标系下的平移增量 + - 按业务需要分步应用 +2. 对真实物体来说,旋转和平移不需要再引入“物体局部映射”来解释 API 行为。 +3. 也就是说,变换主语应始终是: + - 宿主坐标系下绕哪根轴旋转 + - 宿主坐标系下平移多少 +4. 如果继续把问题建模成: + - 先解释物体局部轴 + - 再把宿主旋转翻译成局部旋转 + - 再去重建完整目标姿态 + 这条链在真实物体上非常容易把问题复杂化,而且会引入额外歧义。 +5. 因此,后续 Ground 真实物体变换链的工程方向应当是: + - 只保留宿主坐标系增量变换 + - 旋转和平移分开处理 + - 不再在变换工具层传播“局部坐标系 / 局部轴映射”概念 + +一句话总结: + +- **只有最简单的宿主坐标系增量法,才能尽量无副作用地做真实物体变换。** +- **旋转和平移不需要物体局部映射,局部坐标的概念可以从这条变换链里彻底移除。** diff --git a/doc/working/2026-04-08-ground-remove-fragment-dependency-plan.md b/doc/working/2026-04-08-ground-remove-fragment-dependency-plan.md new file mode 100644 index 0000000..e99339b --- /dev/null +++ b/doc/working/2026-04-08-ground-remove-fragment-dependency-plan.md @@ -0,0 +1,136 @@ +# Ground 去 Fragment 依赖实施方案 + +更新时间:2026-04-08 + +## 1. 这份方案现在只解决什么 + +只解决一件事: + +- `Ground + 真实物体` 主链里,尽量去掉 `fragment` 参考姿态依赖 + +只允许改动: + +- `PathAnimationManager.cs` +- 必要时补少量日志 + +明确不做: + +- 不新建大范围工具链 +- 不改 `Hoisting` +- 不改 `Rail` +- 不重写 `ModelItemTransformHelper` +- 不删除 `RealObjectReferencePoseResolver` +- 不做“整项目去 fragment” + +这份方案的目标是:**缩小修改范围,先把 Ground 主链收干净。** + +--- + +## 2. 当前已确认的事实 + +1. `Ground` 的变换更适合走最简单的宿主增量法: + - 宿主旋转增量 + - 宿主平移增量 +2. `Ground` 这条链不应该再扩散 `local/reference/fragment` 概念。 +3. `fragment` 现在的问题,不在于“所有地方都要立刻删”,而在于: + - Ground 主链还会读它 + - 导致姿态来源不稳定 + +--- + +## 3. 只保留的改造目标 + +这轮只保留 3 个具体目标: + +1. `Ground` 初始化时,不再优先读 fragment 参考姿态 +2. `Ground` 平面姿态求解时,不再走 fragment 参考旋转入口 +3. `Ground` 不再允许 fragment planar fallback + +只要这 3 点做到,就算这一轮完成。 + +--- + +## 4. 当前 Ground 需要处理的入口 + +### 4.1 初始化入口 + +当前重点看: + +- `SyncTrackedRotationToObjectReference(...)` + +要求: + +- 当 `PathType == Ground` 且是真实物体时 +- 不再去走 `TryCaptureRealObjectReferenceRotation(...)` +- 直接改用当前实际几何姿态,或现有非 fragment 入口 + +### 4.2 平面姿态求解入口 + +当前重点看: + +- `TryGetRealObjectReferenceRotation(...)` +- `TryCreateReferenceBasedRealObjectPlanarPoseSolution(...)` + +要求: + +- `Ground` 不再从这里拿 fragment 参考旋转 +- `Ground` 单独走非 fragment 的姿态来源 + +### 4.3 fallback 入口 + +当前重点看: + +- `ShouldAllowFragmentPlanarFallback(PathType pathType)` + +要求: + +- `Ground` 改成和 `Hoisting` 一样,不再允许 fragment planar fallback + +--- + +## 5. 实施顺序 + +只按下面顺序做,不扩展: + +1. 先改 `Ground` 初始化入口 +2. 再改 `Ground` 平面姿态求解入口 +3. 最后关掉 `Ground` 的 fragment fallback + +每一步都要求: + +- 先看日志 +- 只改 `Ground` +- 不顺手改别的路径 + +--- + +## 6. 验证标准 + +这轮不追求“大而全测试矩阵”,只看 3 条: + +1. 起点 + - `Ground + 真实物体` 到起点后不再读 fragment 姿态 + +2. 逐帧 + - `Ground` 播放时姿态来源不再依赖 fragment + +3. fallback + - `Ground` 关闭 fragment fallback 后,主链要么成功,要么明确报错 + - 不允许再偷偷回退 + +--- + +## 7. 当前停止线 + +如果做到下面这句话,就先停: + +- **Ground 主链不再依赖 fragment,但 Hoisting / Rail / 通用参考姿态系统暂时不动。** + +不要在这一轮里再继续追求: + +- 抽象统一工具类 +- 清理全部 reference/local 命名 +- 一次性删光 fragment 代码 +- 统一三类路径的所有姿态入口 + +这些都属于下一轮的事。