146 lines
6.5 KiB
C#
146 lines
6.5 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||
using NavisworksTransport.Utils.CoordinateSystem;
|
||
using System.Numerics;
|
||
|
||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||
{
|
||
[TestClass]
|
||
public class RealObjectProjectedExtentResolverTests
|
||
{
|
||
[TestMethod]
|
||
public void Ground_DualAxisCorrection_ShouldProjectAgainstFinalPose()
|
||
{
|
||
var convention = new ModelAxisConvention(LocalAxisDirection.PositiveX, LocalAxisDirection.PositiveY);
|
||
Vector3 targetForward = Vector3.Normalize(new Vector3(-0.8987f, 0.0f, 0.4386f));
|
||
Vector3 targetUp = Vector3.UnitY;
|
||
|
||
Quaternion baseline = Quaternion.Normalize(Quaternion.CreateFromRotationMatrix(new Matrix4x4(
|
||
-0.8987f, 0.0000f, 0.4386f, 0f,
|
||
0.0000f, 1.0000f, 0.0000f, 0f,
|
||
-0.4386f, 0.0000f,-0.8987f, 0f,
|
||
0f, 0f, 0f, 1f)));
|
||
|
||
var adapter = new HostCoordinateAdapter(CoordinateSystemType.YUp);
|
||
Quaternion final = adapter.ComposeHostQuaternion(
|
||
baseline,
|
||
new LocalEulerRotationCorrection(90.0, 0.0, 90.0));
|
||
|
||
var extents = RealObjectProjectedExtentResolver.CalculateProjectedSemanticExtents(
|
||
convention,
|
||
forwardSize: 6.0,
|
||
sideSize: 2.0,
|
||
upSize: 4.0,
|
||
baseline,
|
||
final,
|
||
targetForward,
|
||
targetUp);
|
||
|
||
Vector3 localSize = convention.CreateScaleVector3(6.0, 2.0, 4.0);
|
||
Vector3 rotatedLocalX = Vector3.Normalize(Vector3.Transform(Vector3.UnitX, final));
|
||
Vector3 rotatedLocalY = Vector3.Normalize(Vector3.Transform(Vector3.UnitY, final));
|
||
Vector3 rotatedLocalZ = Vector3.Normalize(Vector3.Transform(Vector3.UnitZ, final));
|
||
Vector3 targetSide = Vector3.Normalize(Vector3.Cross(targetForward, targetUp));
|
||
|
||
double expectedForward = ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetForward);
|
||
double expectedSide = ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetSide);
|
||
double expectedUp = ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetUp);
|
||
|
||
Assert.AreEqual(expectedForward, extents.forwardExtent, 1e-5);
|
||
Assert.AreEqual(expectedSide, extents.sideExtent, 1e-5);
|
||
Assert.AreEqual(expectedUp, extents.upExtent, 1e-5);
|
||
Assert.AreNotEqual(4.0, extents.upExtent, 1e-3, "双轴旋转后,Ground 的法线尺寸不应停留在旧高度。");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void Ground_DisplayedHostAxesProjection_ShouldKeepXAxisLengthAndSwapXZAsAxesRotate()
|
||
{
|
||
Vector3 targetForward = Vector3.UnitX;
|
||
Vector3 targetUp = Vector3.UnitY;
|
||
|
||
var noCorrection = RealObjectProjectedExtentResolver.CalculateProjectedDisplayedExtents(
|
||
displayedAxisXSize: 6.0,
|
||
displayedAxisYSize: 2.0,
|
||
displayedAxisZSize: 4.0,
|
||
displayedHostAxisX: Vector3.UnitX,
|
||
displayedHostAxisY: Vector3.UnitZ,
|
||
displayedHostAxisZ: -Vector3.UnitY,
|
||
targetForward,
|
||
targetUp);
|
||
|
||
Assert.AreEqual(6.0, noCorrection.forwardExtent, 1e-5);
|
||
Assert.AreEqual(2.0, noCorrection.sideExtent, 1e-5);
|
||
Assert.AreEqual(4.0, noCorrection.upExtent, 1e-5);
|
||
|
||
var xRotated = RealObjectProjectedExtentResolver.CalculateProjectedDisplayedExtents(
|
||
displayedAxisXSize: 6.0,
|
||
displayedAxisYSize: 2.0,
|
||
displayedAxisZSize: 4.0,
|
||
displayedHostAxisX: Vector3.UnitX,
|
||
displayedHostAxisY: Vector3.UnitY,
|
||
displayedHostAxisZ: Vector3.UnitZ,
|
||
targetForward,
|
||
targetUp);
|
||
|
||
Assert.AreEqual(6.0, xRotated.forwardExtent, 1e-5);
|
||
Assert.AreEqual(4.0, xRotated.sideExtent, 1e-5);
|
||
Assert.AreEqual(2.0, xRotated.upExtent, 1e-5);
|
||
|
||
var zRotated = RealObjectProjectedExtentResolver.CalculateProjectedDisplayedExtents(
|
||
displayedAxisXSize: 6.0,
|
||
displayedAxisYSize: 2.0,
|
||
displayedAxisZSize: 4.0,
|
||
displayedHostAxisX: -Vector3.UnitZ,
|
||
displayedHostAxisY: Vector3.UnitX,
|
||
displayedHostAxisZ: -Vector3.UnitY,
|
||
targetForward,
|
||
targetUp);
|
||
|
||
Assert.AreEqual(2.0, zRotated.forwardExtent, 1e-5);
|
||
Assert.AreEqual(6.0, zRotated.sideExtent, 1e-5);
|
||
Assert.AreEqual(4.0, zRotated.upExtent, 1e-5);
|
||
}
|
||
|
||
[TestMethod]
|
||
public void Ground_DisplayedHostAxesProjection_ShouldIgnoreVerticalComponentInForward()
|
||
{
|
||
Vector3 targetUp = Vector3.UnitY;
|
||
Vector3 planarForward = Vector3.Normalize(new Vector3(1f, 0f, 1f));
|
||
Vector3 slopedForward = Vector3.Normalize(new Vector3(1f, 2f, 1f));
|
||
|
||
var planar = RealObjectProjectedExtentResolver.CalculateProjectedDisplayedExtents(
|
||
displayedAxisXSize: 6.0,
|
||
displayedAxisYSize: 2.0,
|
||
displayedAxisZSize: 4.0,
|
||
displayedHostAxisX: Vector3.UnitX,
|
||
displayedHostAxisY: Vector3.UnitZ,
|
||
displayedHostAxisZ: -Vector3.UnitY,
|
||
planarForward,
|
||
targetUp);
|
||
|
||
var sloped = RealObjectProjectedExtentResolver.CalculateProjectedDisplayedExtents(
|
||
displayedAxisXSize: 6.0,
|
||
displayedAxisYSize: 2.0,
|
||
displayedAxisZSize: 4.0,
|
||
displayedHostAxisX: Vector3.UnitX,
|
||
displayedHostAxisY: Vector3.UnitZ,
|
||
displayedHostAxisZ: -Vector3.UnitY,
|
||
slopedForward,
|
||
targetUp);
|
||
|
||
Assert.AreNotEqual(planar.forwardExtent, sloped.forwardExtent, 1e-3, "原始带竖直分量的路径方向会污染 Ground 尺寸投影。");
|
||
}
|
||
|
||
private static double ProjectExtent(
|
||
Vector3 localSize,
|
||
Vector3 rotatedLocalX,
|
||
Vector3 rotatedLocalY,
|
||
Vector3 rotatedLocalZ,
|
||
Vector3 targetAxis)
|
||
{
|
||
return System.Math.Abs(Vector3.Dot(rotatedLocalX, targetAxis)) * localSize.X +
|
||
System.Math.Abs(Vector3.Dot(rotatedLocalY, targetAxis)) * localSize.Y +
|
||
System.Math.Abs(Vector3.Dot(rotatedLocalZ, targetAxis)) * localSize.Z;
|
||
}
|
||
}
|
||
}
|