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