From 7c4783dca6f33ecb51fe1ab8bb6ca140db3976cb Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Wed, 5 Aug 2026 23:53:39 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B8=85=E7=90=86=20fragment=20?=
=?UTF-8?q?=E5=8F=82=E8=80=83=E5=A7=BF=E6=80=81=E6=AE=8B=E7=95=99=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=EF=BC=880.18.2=20=E9=BB=98=E8=AE=A4=E8=BD=B4=E7=BA=A6?=
=?UTF-8?q?=E5=AE=9A=E5=90=8E=E7=9A=84=E6=AD=BB=E4=BB=A3=E7=A0=81=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
删除:
- RealObjectReferencePoseResolver: TryResolveFromModelItem / TryResolveFromFragmentMatrices
(fragment 代表姿态解析链,已无调用者;保留诊断用 TryDetectDefaultUpAxis)
- RealObjectReferencePose.cs(无引用死文件)
- PathAnimationManager: _realObjectReferenceHostSemantic* 字段(无消费)
- FragmentRepresentativePoseHelper: TryGetRepresentativeRotation(ModelItem/矩阵集合)
与 TryInterpretRepresentativeFrame(仅死链使用;保留诊断用 TryGetRepresentativeFrame)
- 测试:RealObjectReferencePoseResolverTests(测死链)、
FragmentRepresentativePoseHelperTests 缩减至在用方法
保留(非残留):
- GeometryHelper/GeometryCacheManager fragment(几何三角形生成)
- FragmentDefaultUpContext / RealObjectRailAxisConventionResolver(在用)
- TestAutomationHttpService(集成测试服务)
验证:单元测试 187/187、集成真实物体动画 3/3、F1 Rail+42" Completed
---
NavisworksTransport.UnitTests.csproj | 1 -
TransportPlugin.csproj | 1 -
.../FragmentRepresentativePoseHelperTests.cs | 108 +------
.../RealObjectReferencePoseResolverTests.cs | 160 ----------
src/Core/Animation/PathAnimationManager.cs | 9 -
.../FragmentRepresentativePoseHelper.cs | 141 +-------
.../RealObjectReferencePose.cs | 67 ----
.../RealObjectReferencePoseResolver.cs | 302 +-----------------
8 files changed, 22 insertions(+), 767 deletions(-)
delete mode 100644 UnitTests/CoordinateSystem/RealObjectReferencePoseResolverTests.cs
delete mode 100644 src/Utils/CoordinateSystem/RealObjectReferencePose.cs
diff --git a/NavisworksTransport.UnitTests.csproj b/NavisworksTransport.UnitTests.csproj
index 7068f09..5c6b277 100644
--- a/NavisworksTransport.UnitTests.csproj
+++ b/NavisworksTransport.UnitTests.csproj
@@ -103,7 +103,6 @@
-
diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj
index 958e086..96c805d 100644
--- a/TransportPlugin.csproj
+++ b/TransportPlugin.csproj
@@ -364,7 +364,6 @@
-
diff --git a/UnitTests/CoordinateSystem/FragmentRepresentativePoseHelperTests.cs b/UnitTests/CoordinateSystem/FragmentRepresentativePoseHelperTests.cs
index 751eba4..cea12c2 100644
--- a/UnitTests/CoordinateSystem/FragmentRepresentativePoseHelperTests.cs
+++ b/UnitTests/CoordinateSystem/FragmentRepresentativePoseHelperTests.cs
@@ -1,6 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NavisworksTransport.Utils.CoordinateSystem;
-using System;
using System.Numerics;
namespace NavisworksTransport.UnitTests.CoordinateSystem
@@ -8,71 +7,6 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
[TestClass]
public class FragmentRepresentativePoseHelperTests
{
- [TestMethod]
- public void ShouldAverageFragmentMatrices_AndIgnoreTranslation()
- {
- Quaternion expectedRotation = Quaternion.Normalize(
- Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)(Math.PI / 6.0)));
-
- double[] fragmentMatrix1 = CreateFragmentMatrix(expectedRotation, new Vector3(10.0f, 20.0f, 30.0f));
- double[] fragmentMatrix2 = CreateFragmentMatrix(expectedRotation, new Vector3(-3.0f, 8.0f, 1.0f));
-
- bool ok = FragmentRepresentativePoseHelper.TryGetRepresentativeRotation(
- new[] { fragmentMatrix1, fragmentMatrix2 },
- out Quaternion representativeRotation);
-
- Assert.IsTrue(ok);
- AssertVector(
- Vector3.Transform(Vector3.UnitX, representativeRotation),
- Vector3.Transform(Vector3.UnitX, expectedRotation),
- 1e-4);
- AssertVector(
- Vector3.Transform(Vector3.UnitY, representativeRotation),
- Vector3.Transform(Vector3.UnitY, expectedRotation),
- 1e-4);
- AssertVector(
- Vector3.Transform(Vector3.UnitZ, representativeRotation),
- Vector3.Transform(Vector3.UnitZ, expectedRotation),
- 1e-4);
- }
-
- [TestMethod]
- public void ShouldIgnoreQuaternionSignWhenAveragingFragments()
- {
- Quaternion expectedRotation = Quaternion.Normalize(
- Quaternion.CreateFromAxisAngle(Vector3.UnitX, (float)(Math.PI / 4.0)));
- Quaternion oppositeSignRotation = new Quaternion(
- -expectedRotation.X,
- -expectedRotation.Y,
- -expectedRotation.Z,
- -expectedRotation.W);
-
- bool ok = FragmentRepresentativePoseHelper.TryGetRepresentativeRotation(
- new[] { expectedRotation, oppositeSignRotation },
- out Quaternion representativeRotation);
-
- Assert.IsTrue(ok);
- AssertVector(
- Vector3.Transform(Vector3.UnitY, representativeRotation),
- Vector3.Transform(Vector3.UnitY, expectedRotation),
- 1e-4);
- AssertVector(
- Vector3.Transform(Vector3.UnitZ, representativeRotation),
- Vector3.Transform(Vector3.UnitZ, expectedRotation),
- 1e-4);
- }
-
- [TestMethod]
- public void ShouldFail_WhenNoFragmentRotationsAreAvailable()
- {
- bool ok = FragmentRepresentativePoseHelper.TryGetRepresentativeRotation(
- Array.Empty(),
- out Quaternion representativeRotation);
-
- Assert.IsFalse(ok);
- Assert.AreEqual(Quaternion.Identity, representativeRotation);
- }
-
[TestMethod]
public void ShouldPreserveAxes_ForObservedYUpRealObjectFragmentBasis()
{
@@ -126,47 +60,11 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
AssertVector(Vector3.Transform(Vector3.UnitZ, frame.Rotation), axisZ, 1e-4);
}
- [TestMethod]
- public void TryInterpretRepresentativeFrame_YUpHost_WithFragmentDefaultUpZ_ShouldMapZToHostY()
- {
- var raw = new FragmentRepresentativePoseHelper.RepresentativeFrame(
- new Vector3(1.0f, 0.0f, 0.0f),
- new Vector3(0.0f, 0.0f, -1.0f),
- new Vector3(0.0f, 1.0f, 0.0f),
- Quaternion.Identity);
-
- bool ok = FragmentRepresentativePoseHelper.TryInterpretRepresentativeFrame(
- raw,
- "Z",
- "Y",
- out var interpreted);
-
- Assert.IsTrue(ok);
- AssertVector(interpreted.AxisX, new Vector3(1.0f, 0.0f, 0.0f), 1e-4);
- AssertVector(interpreted.AxisY, new Vector3(0.0f, 1.0f, 0.0f), 1e-4);
- AssertVector(interpreted.AxisZ, new Vector3(0.0f, 0.0f, 1.0f), 1e-4);
- }
-
- private static double[] CreateFragmentMatrix(Quaternion rotation, Vector3 translation)
- {
- Vector3 axisX = Vector3.Transform(Vector3.UnitX, rotation);
- Vector3 axisY = Vector3.Transform(Vector3.UnitY, rotation);
- Vector3 axisZ = Vector3.Transform(Vector3.UnitZ, rotation);
-
- return new[]
- {
- (double)axisX.X, (double)axisX.Y, (double)axisX.Z, 0.0,
- (double)axisY.X, (double)axisY.Y, (double)axisY.Z, 0.0,
- (double)axisZ.X, (double)axisZ.Y, (double)axisZ.Z, 0.0,
- (double)translation.X, (double)translation.Y, (double)translation.Z, 1.0
- };
- }
-
private static void AssertVector(Vector3 actual, Vector3 expected, double tolerance)
{
- Assert.AreEqual(expected.X, actual.X, tolerance);
- Assert.AreEqual(expected.Y, actual.Y, tolerance);
- Assert.AreEqual(expected.Z, actual.Z, tolerance);
+ Assert.AreEqual(expected.X, actual.X, tolerance, "X 分量");
+ Assert.AreEqual(expected.Y, actual.Y, tolerance, "Y 分量");
+ Assert.AreEqual(expected.Z, actual.Z, tolerance, "Z 分量");
}
}
}
diff --git a/UnitTests/CoordinateSystem/RealObjectReferencePoseResolverTests.cs b/UnitTests/CoordinateSystem/RealObjectReferencePoseResolverTests.cs
deleted file mode 100644
index 0faa079..0000000
--- a/UnitTests/CoordinateSystem/RealObjectReferencePoseResolverTests.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using NavisworksTransport.Utils.CoordinateSystem;
-using System.Collections.Generic;
-using System.Numerics;
-
-namespace NavisworksTransport.UnitTests.CoordinateSystem
-{
- [TestClass]
- public class RealObjectReferencePoseResolverTests
- {
- [TestMethod]
- public void YUp_HostWithFragmentDefaultZ_ShouldInterpretRepresentativeFrameToHostSemantics()
- {
- var fragmentMatrices = new List
- {
- CreateMatrix(
- axisX: new Vector3(1.0f, 0.0f, 0.0f),
- axisY: new Vector3(0.0f, 1.0f, 0.0f),
- axisZ: new Vector3(0.0f, 0.0f, 1.0f))
- };
-
- bool ok = RealObjectReferencePoseResolver.TryResolveFromFragmentMatrices(
- fragmentMatrices,
- fragmentDefaultUpAxis: "Z",
- hostUpAxis: "Y",
- out RealObjectReferencePose pose);
-
- Assert.IsTrue(ok);
- AssertVector(pose.RawAxisX, 1.0, 0.0, 0.0);
- AssertVector(pose.RawAxisY, 0.0, 1.0, 0.0);
- AssertVector(pose.RawAxisZ, 0.0, 0.0, 1.0);
- AssertVector(pose.AxisX, 1.0, 0.0, 0.0);
- AssertVector(pose.AxisY, 0.0, 0.0, 1.0);
- AssertVector(pose.AxisZ, 0.0, -1.0, 0.0);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostWorldXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveY, pose.HostWorldYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostWorldZAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostSemanticXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostSemanticYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.NegativeY, pose.HostSemanticZAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostUpLocalAxis);
- }
-
- [TestMethod]
- public void YUp_WorldAxisMapping_ShouldFollowRawRepresentativeFrame()
- {
- var fragmentMatrices = new List
- {
- CreateMatrix(
- axisX: new Vector3(0.0f, 0.0f, 1.0f),
- axisY: new Vector3(1.0f, 0.0f, 0.0f),
- axisZ: new Vector3(0.0f, 1.0f, 0.0f))
- };
-
- bool ok = RealObjectReferencePoseResolver.TryResolveFromFragmentMatrices(
- fragmentMatrices,
- fragmentDefaultUpAxis: "Z",
- hostUpAxis: "Y",
- out RealObjectReferencePose pose);
-
- Assert.IsTrue(ok);
- Assert.AreEqual(LocalAxisDirection.PositiveY, pose.HostWorldXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostWorldYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostWorldZAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostSemanticXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostSemanticYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.NegativeY, pose.HostSemanticZAxisLocalAxis);
- }
-
- [TestMethod]
- public void DetectDefaultUpAxis_ShouldReturnZ_WhenRepresentativeZMatchesHostUp()
- {
- var fragmentMatrices = new List
- {
- CreateMatrix(
- axisX: new Vector3(1.0f, 0.0f, 0.0f),
- axisY: new Vector3(0.0f, 0.0f, -1.0f),
- axisZ: new Vector3(0.0f, 1.0f, 0.0f))
- };
-
- bool ok = RealObjectReferencePoseResolver.TryDetectDefaultUpAxis(
- fragmentMatrices,
- "Y",
- out string detectedAxis,
- out float yAlignment,
- out float zAlignment);
-
- Assert.IsTrue(ok);
- Assert.AreEqual("Z", detectedAxis);
- Assert.AreEqual(0.0, yAlignment, 1e-6);
- Assert.AreEqual(1.0, zAlignment, 1e-6);
- }
-
- [TestMethod]
- public void YUp_WorldAxisMapping_ShouldAcceptSlightlyRotatedRawFragmentFrame()
- {
- var fragmentMatrices = new List
- {
- CreateMatrix(
- axisX: Vector3.Normalize(new Vector3(0.9980f, 0.0638f, 0.0f)),
- axisY: new Vector3(0.0f, 0.0f, -1.0f),
- axisZ: Vector3.Normalize(new Vector3(-0.0638f, 0.9980f, 0.0f)))
- };
-
- bool ok = RealObjectReferencePoseResolver.TryResolveFromFragmentMatrices(
- fragmentMatrices,
- fragmentDefaultUpAxis: "Y",
- hostUpAxis: "Y",
- out RealObjectReferencePose pose);
-
- Assert.IsTrue(ok);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostWorldXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostWorldYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.NegativeY, pose.HostWorldZAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveX, pose.HostSemanticXAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveY, pose.HostSemanticYAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveZ, pose.HostSemanticZAxisLocalAxis);
- Assert.AreEqual(LocalAxisDirection.PositiveY, pose.HostUpLocalAxis);
- }
-
- [TestMethod]
- public void YUp_WorldAxisMapping_ShouldRejectAmbiguousRawFragmentFrame()
- {
- var fragmentMatrices = new List
- {
- CreateMatrix(
- axisX: Vector3.Normalize(new Vector3(0.80f, 0.60f, 0.0f)),
- axisY: new Vector3(0.0f, 0.0f, -1.0f),
- axisZ: Vector3.Normalize(new Vector3(-0.60f, 0.80f, 0.0f)))
- };
-
- bool ok = RealObjectReferencePoseResolver.TryResolveFromFragmentMatrices(
- fragmentMatrices,
- fragmentDefaultUpAxis: "Y",
- hostUpAxis: "Y",
- out RealObjectReferencePose pose);
-
- Assert.IsFalse(ok);
- Assert.IsNull(pose);
- }
-
- private static double[] CreateMatrix(Vector3 axisX, Vector3 axisY, Vector3 axisZ)
- {
- return new double[]
- {
- axisX.X, axisX.Y, axisX.Z, 0.0,
- axisY.X, axisY.Y, axisY.Z, 0.0,
- axisZ.X, axisZ.Y, axisZ.Z, 0.0,
- 0.0, 0.0, 0.0, 1.0
- };
- }
-
- private static void AssertVector(Vector3 actual, double x, double y, double z, double tolerance = 1e-6)
- {
- Assert.AreEqual(x, actual.X, tolerance);
- Assert.AreEqual(y, actual.Y, tolerance);
- Assert.AreEqual(z, actual.Z, tolerance);
- }
- }
-}
diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 5d9966e..755b02d 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -119,9 +119,6 @@ namespace NavisworksTransport.Core.Animation
private LocalAxisDirection _realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
private LocalAxisDirection _realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
private LocalAxisDirection _realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
- private LocalAxisDirection _realObjectReferenceHostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
- private LocalAxisDirection _realObjectReferenceHostSemanticYAxisLocalAxis = LocalAxisDirection.PositiveY;
- private LocalAxisDirection _realObjectReferenceHostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
private LocalAxisDirection _realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
private bool _hasRealObjectReferenceRotation = false;
private LocalAxisDirection _realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
@@ -5411,9 +5408,6 @@ namespace NavisworksTransport.Core.Animation
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
- _realObjectReferenceHostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
- _realObjectReferenceHostSemanticYAxisLocalAxis = hostUpLocal;
- _realObjectReferenceHostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_hasRealObjectReferenceRotation = true;
LogManager.Info(
@@ -5513,9 +5507,6 @@ namespace NavisworksTransport.Core.Animation
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
- _realObjectReferenceHostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
- _realObjectReferenceHostSemanticYAxisLocalAxis = LocalAxisDirection.PositiveY;
- _realObjectReferenceHostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
_hasRealObjectReferenceRotation = false;
_realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
diff --git a/src/Utils/CoordinateSystem/FragmentRepresentativePoseHelper.cs b/src/Utils/CoordinateSystem/FragmentRepresentativePoseHelper.cs
index 4982a2b..830085f 100644
--- a/src/Utils/CoordinateSystem/FragmentRepresentativePoseHelper.cs
+++ b/src/Utils/CoordinateSystem/FragmentRepresentativePoseHelper.cs
@@ -2,19 +2,16 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
-using Autodesk.Navisworks.Api;
-using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
-using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
namespace NavisworksTransport.Utils.CoordinateSystem
{
///
- /// Fragment 代表姿态辅助工具。
- ///
- /// 语义:
- /// - 从 fragment 的 world 矩阵中提取旋转
- /// - 对多个 fragment 旋转做同半球加权平均
- /// - 返回一个可作为真实物体参考位姿的代表旋转
+ /// Fragment 代表帧辅助工具(诊断用途)。
+ ///
+ /// 说明:真实物体姿态链已不依赖 fragment(0.18.2 起使用默认轴约定,
+ /// forward=+X、up=宿主 up)。本工具仅保留系统诊断面板
+ /// (SystemManagementViewModel 方法5:Fragment 矩阵分析)所需的
+ /// TryGetRepresentativeFrame / TryExtractRotationFromFragmentMatrix。
///
public static class FragmentRepresentativePoseHelper
{
@@ -37,58 +34,8 @@ namespace NavisworksTransport.Utils.CoordinateSystem
}
///
- /// 从 ModelItem 的 fragment 几何中提取代表旋转。
+ /// 从 fragment 矩阵集合中提取代表帧。
///
- public static bool TryGetRepresentativeRotation(ModelItem item, out Quaternion representativeRotation)
- {
- representativeRotation = Quaternion.Identity;
-
- if (item == null)
- {
- return false;
- }
-
- try
- {
- var selection = ComApiBridge.ToInwOpSelection(new ModelItemCollection { item });
- var fragmentInfos = GeometryHelper.GetAllFragments(selection);
- return TryGetRepresentativeRotation(
- fragmentInfos.Select(fragmentInfo => fragmentInfo.TransformMatrix),
- out representativeRotation);
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[fragment代表姿态] 从ModelItem提取失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 从 fragment 矩阵集合中提取代表旋转。
- ///
- public static bool TryGetRepresentativeRotation(
- IEnumerable fragmentMatrices,
- out Quaternion representativeRotation)
- {
- representativeRotation = Quaternion.Identity;
-
- if (fragmentMatrices == null)
- {
- return false;
- }
-
- var fragmentRotations = new List();
- foreach (double[] fragmentMatrix in fragmentMatrices)
- {
- if (TryExtractRotationFromFragmentMatrix(fragmentMatrix, out Quaternion fragmentRotation))
- {
- fragmentRotations.Add(fragmentRotation);
- }
- }
-
- return TryGetRepresentativeRotation(fragmentRotations, out representativeRotation);
- }
-
public static bool TryGetRepresentativeFrame(
IEnumerable fragmentMatrices,
out RepresentativeFrame representativeFrame)
@@ -121,80 +68,10 @@ namespace NavisworksTransport.Utils.CoordinateSystem
return true;
}
- public static bool TryInterpretRepresentativeFrame(
- RepresentativeFrame rawFrame,
- string fragmentDefaultUpAxis,
- string hostUpAxis,
- out RepresentativeFrame interpretedFrame)
- {
- interpretedFrame = default;
-
- bool hostIsYUp = string.Equals(hostUpAxis, "Y", StringComparison.OrdinalIgnoreCase);
- bool fragmentIsYUp = string.Equals(fragmentDefaultUpAxis, "Y", StringComparison.OrdinalIgnoreCase);
-
- Vector3 semanticAxisX = rawFrame.AxisX;
- Vector3 semanticAxisY;
- Vector3 semanticAxisZ;
-
- if (hostIsYUp == fragmentIsYUp)
- {
- semanticAxisY = rawFrame.AxisY;
- semanticAxisZ = rawFrame.AxisZ;
- }
- else if (hostIsYUp)
- {
- // fragment 按 ZUp 解释,宿主按 YUp 解释:X 保持,Y 取原始 Z,Z 由右手系重建。
- semanticAxisY = rawFrame.AxisZ;
- semanticAxisZ = Vector3.Normalize(Vector3.Cross(semanticAxisX, semanticAxisY));
- }
- else
- {
- // fragment 按 YUp 解释,宿主按 ZUp 解释:X 保持,Z 取原始 Y,Y 由右手系重建。
- semanticAxisZ = rawFrame.AxisY;
- semanticAxisY = Vector3.Normalize(Vector3.Cross(semanticAxisZ, semanticAxisX));
- }
-
- if (!TryNormalize(semanticAxisX, out semanticAxisX) ||
- !TryNormalize(semanticAxisY, out semanticAxisY) ||
- !TryNormalize(semanticAxisZ, out semanticAxisZ))
- {
- return false;
- }
-
- // 用解释后的三轴重新正交化,保证右手系稳定。
- Vector3 axisX = semanticAxisX;
- Vector3 axisY = semanticAxisY - Vector3.Dot(semanticAxisY, axisX) * axisX;
- if (!TryNormalize(axisY, out axisY))
- {
- return false;
- }
-
- Vector3 axisZ = Vector3.Cross(axisX, axisY);
- if (!TryNormalize(axisZ, out axisZ))
- {
- return false;
- }
-
- if (hostIsYUp && Vector3.Dot(axisY, semanticAxisY) < 0.0f)
- {
- axisY = -axisY;
- axisZ = -axisZ;
- }
- else if (!hostIsYUp && Vector3.Dot(axisZ, semanticAxisZ) < 0.0f)
- {
- axisY = -axisY;
- axisZ = -axisZ;
- }
-
- Quaternion rotation = Quaternion.Normalize(CreateQuaternionFromBasis(axisX, axisY, axisZ));
- interpretedFrame = new RepresentativeFrame(axisX, axisY, axisZ, rotation);
- return true;
- }
-
///
- /// 从 fragment 旋转集合中提取代表旋转。
+ /// 从 fragment 旋转集合中提取代表旋转(同半球加权平均)。
///
- public static bool TryGetRepresentativeRotation(
+ private static bool TryGetRepresentativeRotation(
IEnumerable fragmentRotations,
out Quaternion representativeRotation)
{
diff --git a/src/Utils/CoordinateSystem/RealObjectReferencePose.cs b/src/Utils/CoordinateSystem/RealObjectReferencePose.cs
deleted file mode 100644
index 0f47001..0000000
--- a/src/Utils/CoordinateSystem/RealObjectReferencePose.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System.Numerics;
-
-namespace NavisworksTransport.Utils.CoordinateSystem
-{
- ///
- /// 真实物体在当前宿主语义下解释后的参考姿态。
- /// 这不是 fragment 原始几何框架,而是已经结合 Fragment默认Up 解释后的结果。
- ///
- public sealed class RealObjectReferencePose
- {
- public RealObjectReferencePose(
- Quaternion rotation,
- Vector3 rawAxisX,
- Vector3 rawAxisY,
- Vector3 rawAxisZ,
- Vector3 axisX,
- Vector3 axisY,
- Vector3 axisZ,
- LocalAxisDirection hostWorldXAxisLocalAxis,
- LocalAxisDirection hostWorldYAxisLocalAxis,
- LocalAxisDirection hostWorldZAxisLocalAxis,
- LocalAxisDirection hostSemanticXAxisLocalAxis,
- LocalAxisDirection hostSemanticYAxisLocalAxis,
- LocalAxisDirection hostSemanticZAxisLocalAxis,
- LocalAxisDirection hostUpLocalAxis,
- int fragmentCount,
- string fragmentDefaultUpAxis,
- string hostUpAxis)
- {
- Rotation = rotation;
- RawAxisX = rawAxisX;
- RawAxisY = rawAxisY;
- RawAxisZ = rawAxisZ;
- AxisX = axisX;
- AxisY = axisY;
- AxisZ = axisZ;
- HostWorldXAxisLocalAxis = hostWorldXAxisLocalAxis;
- HostWorldYAxisLocalAxis = hostWorldYAxisLocalAxis;
- HostWorldZAxisLocalAxis = hostWorldZAxisLocalAxis;
- HostSemanticXAxisLocalAxis = hostSemanticXAxisLocalAxis;
- HostSemanticYAxisLocalAxis = hostSemanticYAxisLocalAxis;
- HostSemanticZAxisLocalAxis = hostSemanticZAxisLocalAxis;
- HostUpLocalAxis = hostUpLocalAxis;
- FragmentCount = fragmentCount;
- FragmentDefaultUpAxis = fragmentDefaultUpAxis;
- HostUpAxis = hostUpAxis;
- }
-
- public Quaternion Rotation { get; }
- public Vector3 RawAxisX { get; }
- public Vector3 RawAxisY { get; }
- public Vector3 RawAxisZ { get; }
- public Vector3 AxisX { get; }
- public Vector3 AxisY { get; }
- public Vector3 AxisZ { get; }
- public LocalAxisDirection HostWorldXAxisLocalAxis { get; }
- public LocalAxisDirection HostWorldYAxisLocalAxis { get; }
- public LocalAxisDirection HostWorldZAxisLocalAxis { get; }
- public LocalAxisDirection HostSemanticXAxisLocalAxis { get; }
- public LocalAxisDirection HostSemanticYAxisLocalAxis { get; }
- public LocalAxisDirection HostSemanticZAxisLocalAxis { get; }
- public LocalAxisDirection HostUpLocalAxis { get; }
- public int FragmentCount { get; }
- public string FragmentDefaultUpAxis { get; }
- public string HostUpAxis { get; }
- }
-}
diff --git a/src/Utils/CoordinateSystem/RealObjectReferencePoseResolver.cs b/src/Utils/CoordinateSystem/RealObjectReferencePoseResolver.cs
index 13ab441..caf7508 100644
--- a/src/Utils/CoordinateSystem/RealObjectReferencePoseResolver.cs
+++ b/src/Utils/CoordinateSystem/RealObjectReferencePoseResolver.cs
@@ -1,305 +1,23 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Numerics;
-using System.Runtime.InteropServices;
-using Autodesk.Navisworks.Api;
-using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
namespace NavisworksTransport.Utils.CoordinateSystem
{
///
- /// 统一的真实物体参考姿态解析入口。
- /// 负责:
- /// 1. 从 fragment 提取代表姿态
- /// 2. 按 Fragment默认Up 解释成当前宿主语义下的真实姿态
- /// 3. 为 Ground / Hoisting / Rail 提供统一参考姿态来源
+ /// 真实物体 fragment 姿态解析入口(仅保留诊断用途)。
+ ///
+ /// 说明:真实物体姿态链已不依赖 fragment(0.18.2 起使用默认轴约定,
+ /// forward=+X、up=宿主 up)。原 TryResolveFromModelItem /
+ /// TryResolveFromFragmentMatrices(fragment 代表姿态解析链)已删除。
+ /// 本类仅保留系统诊断面板(SystemManagementViewModel 方法5)使用的
+ /// TryDetectDefaultUpAxis。
///
public static class RealObjectReferencePoseResolver
{
- private const float WorldAxisMinimumAlignment = 0.98f;
- private const float SemanticAxisMinimumAlignment = 0.985f;
- private const float MinimumBestToSecondGap = 0.02f;
-
- public static bool TryResolveFromModelItem(
- ModelItem sourceObject,
- Document doc,
- out RealObjectReferencePose referencePose)
- {
- referencePose = null;
-
- if (sourceObject == null)
- {
- return false;
- }
-
- try
- {
- var selection = ComApiBridge.ToInwOpSelection(new ModelItemCollection { sourceObject });
- var fragmentInfos = GeometryHelper.GetAllFragments(selection);
- try
- {
- var fragmentMatrices = fragmentInfos
- .Where(fragmentInfo => fragmentInfo.TransformMatrix != null && fragmentInfo.TransformMatrix.Length == 16)
- .Select(fragmentInfo => fragmentInfo.TransformMatrix)
- .ToList();
-
- return TryResolveFromFragmentMatrices(fragmentMatrices, doc, out referencePose);
- }
- finally
- {
- if (fragmentInfos != null)
- {
- foreach (var fragmentInfo in fragmentInfos)
- {
- if (fragmentInfo?.Fragment != null)
- {
- try
- {
- Marshal.ReleaseComObject(fragmentInfo.Fragment);
- }
- catch
- {
- }
- }
- }
- }
-
- if (selection != null)
- {
- try
- {
- Marshal.ReleaseComObject(selection);
- }
- catch
- {
- }
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[真实物体参考姿态] 从 fragment 提取代表姿态失败: {ex.Message}");
- return false;
- }
- }
-
- public static bool TryResolveFromFragmentMatrices(
- IReadOnlyCollection fragmentMatrices,
- Document doc,
- out RealObjectReferencePose referencePose)
- {
- string fragmentDefaultUpAxis = FragmentDefaultUpContext.GetCurrentDocumentFragmentDefaultUpAxis(doc);
- string hostUpAxis = FragmentDefaultUpContext.GetCurrentHostUpAxis(doc);
- return TryResolveFromFragmentMatrices(fragmentMatrices, fragmentDefaultUpAxis, hostUpAxis, out referencePose);
- }
-
- public static bool TryResolveFromFragmentMatrices(
- IReadOnlyCollection fragmentMatrices,
- string fragmentDefaultUpAxis,
- string hostUpAxis,
- out RealObjectReferencePose referencePose)
- {
- referencePose = null;
-
- if (fragmentMatrices == null || fragmentMatrices.Count == 0)
- {
- return false;
- }
-
- if (!FragmentRepresentativePoseHelper.TryGetRepresentativeFrame(fragmentMatrices, out var rawFrame))
- {
- return false;
- }
-
- if (!FragmentRepresentativePoseHelper.TryInterpretRepresentativeFrame(
- rawFrame,
- fragmentDefaultUpAxis,
- hostUpAxis,
- out var interpretedFrame))
- {
- return false;
- }
-
- if (!TryResolveSemanticLocalAxes(
- rawFrame,
- interpretedFrame,
- out var hostSemanticXAxisLocalAxis,
- out var hostSemanticYAxisLocalAxis,
- out var hostSemanticZAxisLocalAxis))
- {
- return false;
- }
-
- if (!TryResolveWorldLocalAxes(
- rawFrame,
- out var hostWorldXAxisLocalAxis,
- out var hostWorldYAxisLocalAxis,
- out var hostWorldZAxisLocalAxis))
- {
- return false;
- }
-
- referencePose = new RealObjectReferencePose(
- interpretedFrame.Rotation,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- interpretedFrame.AxisX,
- interpretedFrame.AxisY,
- interpretedFrame.AxisZ,
- hostWorldXAxisLocalAxis,
- hostWorldYAxisLocalAxis,
- hostWorldZAxisLocalAxis,
- hostSemanticXAxisLocalAxis,
- hostSemanticYAxisLocalAxis,
- hostSemanticZAxisLocalAxis,
- string.Equals(hostUpAxis, "Y", StringComparison.OrdinalIgnoreCase)
- ? hostSemanticYAxisLocalAxis
- : hostSemanticZAxisLocalAxis,
- fragmentMatrices.Count,
- fragmentDefaultUpAxis,
- hostUpAxis);
- return true;
- }
-
- private static bool TryResolveWorldLocalAxes(
- FragmentRepresentativePoseHelper.RepresentativeFrame rawFrame,
- out LocalAxisDirection hostWorldXAxisLocalAxis,
- out LocalAxisDirection hostWorldYAxisLocalAxis,
- out LocalAxisDirection hostWorldZAxisLocalAxis)
- {
- hostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
- hostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
- hostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
-
- if (!TryMatchRawAxisDirection(
- Vector3.UnitX,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- WorldAxisMinimumAlignment,
- out hostWorldXAxisLocalAxis))
- {
- return false;
- }
-
- if (!TryMatchRawAxisDirection(
- Vector3.UnitY,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- WorldAxisMinimumAlignment,
- out hostWorldYAxisLocalAxis))
- {
- return false;
- }
-
- if (!TryMatchRawAxisDirection(
- Vector3.UnitZ,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- WorldAxisMinimumAlignment,
- out hostWorldZAxisLocalAxis))
- {
- return false;
- }
-
- return true;
- }
-
- private static bool TryResolveSemanticLocalAxes(
- FragmentRepresentativePoseHelper.RepresentativeFrame rawFrame,
- FragmentRepresentativePoseHelper.RepresentativeFrame interpretedFrame,
- out LocalAxisDirection hostSemanticXAxisLocalAxis,
- out LocalAxisDirection hostSemanticYAxisLocalAxis,
- out LocalAxisDirection hostSemanticZAxisLocalAxis)
- {
- hostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
- hostSemanticYAxisLocalAxis = LocalAxisDirection.PositiveY;
- hostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
-
- if (!TryMatchRawAxisDirection(
- interpretedFrame.AxisX,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- SemanticAxisMinimumAlignment,
- out hostSemanticXAxisLocalAxis))
- {
- return false;
- }
-
- if (!TryMatchRawAxisDirection(
- interpretedFrame.AxisY,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- SemanticAxisMinimumAlignment,
- out hostSemanticYAxisLocalAxis))
- {
- return false;
- }
-
- if (!TryMatchRawAxisDirection(
- interpretedFrame.AxisZ,
- rawFrame.AxisX,
- rawFrame.AxisY,
- rawFrame.AxisZ,
- SemanticAxisMinimumAlignment,
- out hostSemanticZAxisLocalAxis))
- {
- return false;
- }
-
- return true;
- }
-
- private static bool TryMatchRawAxisDirection(
- Vector3 targetAxis,
- Vector3 rawAxisX,
- Vector3 rawAxisY,
- Vector3 rawAxisZ,
- float minimumAlignment,
- out LocalAxisDirection axisDirection)
- {
- axisDirection = LocalAxisDirection.PositiveX;
- float bestAlignment = float.NegativeInfinity;
- float secondBestAlignment = float.NegativeInfinity;
-
- TryUpdateBestMatch(targetAxis, rawAxisX, LocalAxisDirection.PositiveX, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
- TryUpdateBestMatch(targetAxis, -rawAxisX, LocalAxisDirection.NegativeX, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
- TryUpdateBestMatch(targetAxis, rawAxisY, LocalAxisDirection.PositiveY, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
- TryUpdateBestMatch(targetAxis, -rawAxisY, LocalAxisDirection.NegativeY, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
- TryUpdateBestMatch(targetAxis, rawAxisZ, LocalAxisDirection.PositiveZ, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
- TryUpdateBestMatch(targetAxis, -rawAxisZ, LocalAxisDirection.NegativeZ, ref bestAlignment, ref secondBestAlignment, ref axisDirection);
-
- return bestAlignment >= minimumAlignment
- && bestAlignment - secondBestAlignment >= MinimumBestToSecondGap;
- }
-
- private static void TryUpdateBestMatch(
- Vector3 targetAxis,
- Vector3 candidateAxis,
- LocalAxisDirection candidateDirection,
- ref float bestAlignment,
- ref float secondBestAlignment,
- ref LocalAxisDirection bestDirection)
- {
- float alignment = Vector3.Dot(Vector3.Normalize(targetAxis), Vector3.Normalize(candidateAxis));
- if (alignment > bestAlignment)
- {
- secondBestAlignment = bestAlignment;
- bestAlignment = alignment;
- bestDirection = candidateDirection;
- }
- else if (alignment > secondBestAlignment)
- {
- secondBestAlignment = alignment;
- }
- }
-
+ ///
+ /// 从 fragment 矩阵检测物体的默认 Up 轴(Y 或 Z 更贴近宿主 up)。
+ ///
public static bool TryDetectDefaultUpAxis(
IReadOnlyCollection fragmentMatrices,
string hostUpAxis,