refactor: 清理 fragment 参考姿态残留代码(0.18.2 默认轴约定后的死代码)
删除: - 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
This commit is contained in:
parent
10e93b1c32
commit
7c4783dca6
@ -103,7 +103,6 @@
|
|||||||
<Compile Include="UnitTests\CoordinateSystem\ProjectReferenceFrameTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\ProjectReferenceFrameTests.cs" />
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RealObjectPlanarPoseSolverTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\RealObjectPlanarPoseSolverTests.cs" />
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RealObjectProjectedExtentResolverTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\RealObjectProjectedExtentResolverTests.cs" />
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RealObjectReferencePoseResolverTests.cs" />
|
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RealObjectRailAxisConventionResolverTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\RealObjectRailAxisConventionResolverTests.cs" />
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RealObjectRailExtentResolverTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\RealObjectRailExtentResolverTests.cs" />
|
||||||
<Compile Include="UnitTests\CoordinateSystem\RotatedObjectExtentHelperTests.cs" />
|
<Compile Include="UnitTests\CoordinateSystem\RotatedObjectExtentHelperTests.cs" />
|
||||||
|
|||||||
@ -364,7 +364,6 @@
|
|||||||
<Compile Include="src\Utils\CoordinateSystem\CanonicalTrackedPositionResolver.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\CanonicalTrackedPositionResolver.cs" />
|
||||||
<Compile Include="src\Utils\CoordinateSystem\FragmentDefaultUpContext.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\FragmentDefaultUpContext.cs" />
|
||||||
<Compile Include="src\Utils\CoordinateSystem\FragmentRepresentativePoseHelper.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\FragmentRepresentativePoseHelper.cs" />
|
||||||
<Compile Include="src\Utils\CoordinateSystem\RealObjectReferencePose.cs" />
|
|
||||||
<Compile Include="src\Utils\CoordinateSystem\RealObjectReferencePoseResolver.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\RealObjectReferencePoseResolver.cs" />
|
||||||
<Compile Include="src\Utils\CoordinateSystem\HoistingRealObjectPoseHelper.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\HoistingRealObjectPoseHelper.cs" />
|
||||||
<Compile Include="src\Utils\CoordinateSystem\PathTargetFrame.cs" />
|
<Compile Include="src\Utils\CoordinateSystem\PathTargetFrame.cs" />
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using NavisworksTransport.Utils.CoordinateSystem;
|
using NavisworksTransport.Utils.CoordinateSystem;
|
||||||
using System;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||||
@ -8,71 +7,6 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
|||||||
[TestClass]
|
[TestClass]
|
||||||
public class FragmentRepresentativePoseHelperTests
|
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<double[]>(),
|
|
||||||
out Quaternion representativeRotation);
|
|
||||||
|
|
||||||
Assert.IsFalse(ok);
|
|
||||||
Assert.AreEqual(Quaternion.Identity, representativeRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ShouldPreserveAxes_ForObservedYUpRealObjectFragmentBasis()
|
public void ShouldPreserveAxes_ForObservedYUpRealObjectFragmentBasis()
|
||||||
{
|
{
|
||||||
@ -126,47 +60,11 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
|||||||
AssertVector(Vector3.Transform(Vector3.UnitZ, frame.Rotation), axisZ, 1e-4);
|
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)
|
private static void AssertVector(Vector3 actual, Vector3 expected, double tolerance)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(expected.X, actual.X, tolerance);
|
Assert.AreEqual(expected.X, actual.X, tolerance, "X 分量");
|
||||||
Assert.AreEqual(expected.Y, actual.Y, tolerance);
|
Assert.AreEqual(expected.Y, actual.Y, tolerance, "Y 分量");
|
||||||
Assert.AreEqual(expected.Z, actual.Z, tolerance);
|
Assert.AreEqual(expected.Z, actual.Z, tolerance, "Z 分量");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<double[]>
|
|
||||||
{
|
|
||||||
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<double[]>
|
|
||||||
{
|
|
||||||
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<double[]>
|
|
||||||
{
|
|
||||||
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<double[]>
|
|
||||||
{
|
|
||||||
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<double[]>
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -119,9 +119,6 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
private LocalAxisDirection _realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
private LocalAxisDirection _realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
||||||
private LocalAxisDirection _realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
private LocalAxisDirection _realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
||||||
private LocalAxisDirection _realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
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 LocalAxisDirection _realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
|
||||||
private bool _hasRealObjectReferenceRotation = false;
|
private bool _hasRealObjectReferenceRotation = false;
|
||||||
private LocalAxisDirection _realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
|
private LocalAxisDirection _realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
|
||||||
@ -5411,9 +5408,6 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
||||||
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
||||||
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
||||||
_realObjectReferenceHostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
|
||||||
_realObjectReferenceHostSemanticYAxisLocalAxis = hostUpLocal;
|
|
||||||
_realObjectReferenceHostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
|
||||||
_hasRealObjectReferenceRotation = true;
|
_hasRealObjectReferenceRotation = true;
|
||||||
|
|
||||||
LogManager.Info(
|
LogManager.Info(
|
||||||
@ -5513,9 +5507,6 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
||||||
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
||||||
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
||||||
_realObjectReferenceHostSemanticXAxisLocalAxis = LocalAxisDirection.PositiveX;
|
|
||||||
_realObjectReferenceHostSemanticYAxisLocalAxis = LocalAxisDirection.PositiveY;
|
|
||||||
_realObjectReferenceHostSemanticZAxisLocalAxis = LocalAxisDirection.PositiveZ;
|
|
||||||
_realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
|
_realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
|
||||||
_hasRealObjectReferenceRotation = false;
|
_hasRealObjectReferenceRotation = false;
|
||||||
_realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
|
_realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
|
||||||
|
|||||||
@ -2,19 +2,16 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
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
|
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fragment 代表姿态辅助工具。
|
/// Fragment 代表帧辅助工具(诊断用途)。
|
||||||
///
|
///
|
||||||
/// 语义:
|
/// 说明:真实物体姿态链已不依赖 fragment(0.18.2 起使用默认轴约定,
|
||||||
/// - 从 fragment 的 world 矩阵中提取旋转
|
/// forward=+X、up=宿主 up)。本工具仅保留系统诊断面板
|
||||||
/// - 对多个 fragment 旋转做同半球加权平均
|
/// (SystemManagementViewModel 方法5:Fragment 矩阵分析)所需的
|
||||||
/// - 返回一个可作为真实物体参考位姿的代表旋转
|
/// TryGetRepresentativeFrame / TryExtractRotationFromFragmentMatrix。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class FragmentRepresentativePoseHelper
|
public static class FragmentRepresentativePoseHelper
|
||||||
{
|
{
|
||||||
@ -37,58 +34,8 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从 ModelItem 的 fragment 几何中提取代表旋转。
|
/// 从 fragment 矩阵集合中提取代表帧。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从 fragment 矩阵集合中提取代表旋转。
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryGetRepresentativeRotation(
|
|
||||||
IEnumerable<double[]> fragmentMatrices,
|
|
||||||
out Quaternion representativeRotation)
|
|
||||||
{
|
|
||||||
representativeRotation = Quaternion.Identity;
|
|
||||||
|
|
||||||
if (fragmentMatrices == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fragmentRotations = new List<Quaternion>();
|
|
||||||
foreach (double[] fragmentMatrix in fragmentMatrices)
|
|
||||||
{
|
|
||||||
if (TryExtractRotationFromFragmentMatrix(fragmentMatrix, out Quaternion fragmentRotation))
|
|
||||||
{
|
|
||||||
fragmentRotations.Add(fragmentRotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TryGetRepresentativeRotation(fragmentRotations, out representativeRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetRepresentativeFrame(
|
public static bool TryGetRepresentativeFrame(
|
||||||
IEnumerable<double[]> fragmentMatrices,
|
IEnumerable<double[]> fragmentMatrices,
|
||||||
out RepresentativeFrame representativeFrame)
|
out RepresentativeFrame representativeFrame)
|
||||||
@ -121,80 +68,10 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
|||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从 fragment 旋转集合中提取代表旋转。
|
/// 从 fragment 旋转集合中提取代表旋转(同半球加权平均)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool TryGetRepresentativeRotation(
|
private static bool TryGetRepresentativeRotation(
|
||||||
IEnumerable<Quaternion> fragmentRotations,
|
IEnumerable<Quaternion> fragmentRotations,
|
||||||
out Quaternion representativeRotation)
|
out Quaternion representativeRotation)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,67 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 真实物体在当前宿主语义下解释后的参考姿态。
|
|
||||||
/// 这不是 fragment 原始几何框架,而是已经结合 Fragment默认Up 解释后的结果。
|
|
||||||
/// </summary>
|
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,305 +1,23 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Autodesk.Navisworks.Api;
|
|
||||||
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
|
|
||||||
|
|
||||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 统一的真实物体参考姿态解析入口。
|
/// 真实物体 fragment 姿态解析入口(仅保留诊断用途)。
|
||||||
/// 负责:
|
///
|
||||||
/// 1. 从 fragment 提取代表姿态
|
/// 说明:真实物体姿态链已不依赖 fragment(0.18.2 起使用默认轴约定,
|
||||||
/// 2. 按 Fragment默认Up 解释成当前宿主语义下的真实姿态
|
/// forward=+X、up=宿主 up)。原 TryResolveFromModelItem /
|
||||||
/// 3. 为 Ground / Hoisting / Rail 提供统一参考姿态来源
|
/// TryResolveFromFragmentMatrices(fragment 代表姿态解析链)已删除。
|
||||||
|
/// 本类仅保留系统诊断面板(SystemManagementViewModel 方法5)使用的
|
||||||
|
/// TryDetectDefaultUpAxis。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class RealObjectReferencePoseResolver
|
public static class RealObjectReferencePoseResolver
|
||||||
{
|
{
|
||||||
private const float WorldAxisMinimumAlignment = 0.98f;
|
/// <summary>
|
||||||
private const float SemanticAxisMinimumAlignment = 0.985f;
|
/// 从 fragment 矩阵检测物体的默认 Up 轴(Y 或 Z 更贴近宿主 up)。
|
||||||
private const float MinimumBestToSecondGap = 0.02f;
|
/// </summary>
|
||||||
|
|
||||||
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<double[]> 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<double[]> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryDetectDefaultUpAxis(
|
public static bool TryDetectDefaultUpAxis(
|
||||||
IReadOnlyCollection<double[]> fragmentMatrices,
|
IReadOnlyCollection<double[]> fragmentMatrices,
|
||||||
string hostUpAxis,
|
string hostUpAxis,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user