Use actual hoisting pose without fragment fallback
This commit is contained in:
parent
953306fdb1
commit
7ff510daf0
@ -87,5 +87,59 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
|||||||
|
|
||||||
Assert.IsFalse(shouldPreserve);
|
Assert.IsFalse(shouldPreserve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldAllowFragmentPlanarFallback_ShouldDisableHoisting()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(PathAnimationManager.ShouldAllowFragmentPlanarFallback(PathType.Hoisting));
|
||||||
|
Assert.IsTrue(PathAnimationManager.ShouldAllowFragmentPlanarFallback(PathType.Ground));
|
||||||
|
Assert.IsTrue(PathAnimationManager.ShouldAllowFragmentPlanarFallback(PathType.Rail));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ResolveCurrentRotationBaseline_ShouldPreferActualGeometryForHoisting()
|
||||||
|
{
|
||||||
|
Rotation3D trackedRotation = new Rotation3D(0.0, 0.0, 0.0, 1.0);
|
||||||
|
Rotation3D actualGeometryRotation = new Rotation3D(0.0, 0.70710678, 0.0, 0.70710678);
|
||||||
|
|
||||||
|
Rotation3D resolved = PathAnimationManager.ResolveCurrentRotationBaseline(
|
||||||
|
PathType.Hoisting,
|
||||||
|
isRealObjectMode: true,
|
||||||
|
hasTrackedRotation: true,
|
||||||
|
trackedRotation: trackedRotation,
|
||||||
|
hasReferenceRotation: false,
|
||||||
|
referenceRotation: Rotation3D.Identity,
|
||||||
|
transformRotation: Rotation3D.Identity,
|
||||||
|
hasActualGeometryRotation: true,
|
||||||
|
actualGeometryRotation: actualGeometryRotation);
|
||||||
|
|
||||||
|
Assert.AreEqual(actualGeometryRotation.A, resolved.A, 1e-9);
|
||||||
|
Assert.AreEqual(actualGeometryRotation.B, resolved.B, 1e-9);
|
||||||
|
Assert.AreEqual(actualGeometryRotation.C, resolved.C, 1e-9);
|
||||||
|
Assert.AreEqual(actualGeometryRotation.D, resolved.D, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ResolveCurrentRotationBaseline_ShouldKeepTrackedRotationForGround()
|
||||||
|
{
|
||||||
|
Rotation3D trackedRotation = new Rotation3D(0.0, 0.0, 0.38268343, 0.92387953);
|
||||||
|
Rotation3D actualGeometryRotation = new Rotation3D(0.0, 0.70710678, 0.0, 0.70710678);
|
||||||
|
|
||||||
|
Rotation3D resolved = PathAnimationManager.ResolveCurrentRotationBaseline(
|
||||||
|
PathType.Ground,
|
||||||
|
isRealObjectMode: true,
|
||||||
|
hasTrackedRotation: true,
|
||||||
|
trackedRotation: trackedRotation,
|
||||||
|
hasReferenceRotation: false,
|
||||||
|
referenceRotation: Rotation3D.Identity,
|
||||||
|
transformRotation: Rotation3D.Identity,
|
||||||
|
hasActualGeometryRotation: true,
|
||||||
|
actualGeometryRotation: actualGeometryRotation);
|
||||||
|
|
||||||
|
Assert.AreEqual(trackedRotation.A, resolved.A, 1e-9);
|
||||||
|
Assert.AreEqual(trackedRotation.B, resolved.B, 1e-9);
|
||||||
|
Assert.AreEqual(trackedRotation.C, resolved.C, 1e-9);
|
||||||
|
Assert.AreEqual(trackedRotation.D, resolved.D, 1e-9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2774,23 +2774,25 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
Rotation3D currentRotation;
|
Rotation3D currentRotation;
|
||||||
Rotation3D currentRotationForTransform;
|
Rotation3D currentRotationForTransform;
|
||||||
Rotation3D actualGeometryRotation = Rotation3D.Identity;
|
Rotation3D actualGeometryRotation = Rotation3D.Identity;
|
||||||
|
bool hasActualGeometryRotation = false;
|
||||||
Rotation3D appliedTargetRotation = newRotation;
|
Rotation3D appliedTargetRotation = newRotation;
|
||||||
Rotation3D targetRotationForTransform = newRotation;
|
Rotation3D targetRotationForTransform = newRotation;
|
||||||
Point3D appliedTargetPosition = newPosition;
|
Point3D appliedTargetPosition = newPosition;
|
||||||
if (_hasTrackedRotation)
|
Rotation3D referenceRotation = IsRealObjectMode && _hasRealObjectReferenceRotation
|
||||||
{
|
? CoordinateSystemManager.Instance.CreateHostAdapter().FromHostQuaternionDirect(_realObjectReferenceRotation)
|
||||||
currentRotation = _trackedRotation;
|
: Rotation3D.Identity;
|
||||||
}
|
Rotation3D transformRotation = controlledObject.Transform.Factor().Rotation;
|
||||||
else if (IsRealObjectMode && _hasRealObjectReferenceRotation)
|
PathType currentPathType = _route?.PathType ?? PathType.Ground;
|
||||||
{
|
currentRotation = ResolveCurrentRotationBaseline(
|
||||||
currentRotation = CoordinateSystemManager.Instance
|
currentPathType,
|
||||||
.CreateHostAdapter()
|
IsRealObjectMode,
|
||||||
.FromHostQuaternionDirect(_realObjectReferenceRotation);
|
_hasTrackedRotation,
|
||||||
}
|
_trackedRotation,
|
||||||
else
|
_hasRealObjectReferenceRotation,
|
||||||
{
|
referenceRotation,
|
||||||
currentRotation = controlledObject.Transform.Factor().Rotation;
|
transformRotation,
|
||||||
}
|
hasActualGeometryRotation: false,
|
||||||
|
actualGeometryRotation: Rotation3D.Identity);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -2805,6 +2807,17 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
_route?.PathType == PathType.Rail) &&
|
_route?.PathType == PathType.Rail) &&
|
||||||
ModelItemTransformHelper.TryGetCurrentGeometryRotation(controlledObject, out actualGeometryRotation))
|
ModelItemTransformHelper.TryGetCurrentGeometryRotation(controlledObject, out actualGeometryRotation))
|
||||||
{
|
{
|
||||||
|
hasActualGeometryRotation = true;
|
||||||
|
currentRotation = ResolveCurrentRotationBaseline(
|
||||||
|
currentPathType,
|
||||||
|
IsRealObjectMode,
|
||||||
|
_hasTrackedRotation,
|
||||||
|
_trackedRotation,
|
||||||
|
_hasRealObjectReferenceRotation,
|
||||||
|
referenceRotation,
|
||||||
|
transformRotation,
|
||||||
|
hasActualGeometryRotation,
|
||||||
|
actualGeometryRotation);
|
||||||
var trackedLinear = new Transform3D(currentRotation).Linear;
|
var trackedLinear = new Transform3D(currentRotation).Linear;
|
||||||
var actualLinear = new Transform3D(actualGeometryRotation).Linear;
|
var actualLinear = new Transform3D(actualGeometryRotation).Linear;
|
||||||
string poseTag = _route?.PathType == PathType.Rail
|
string poseTag = _route?.PathType == PathType.Rail
|
||||||
@ -3987,6 +4000,42 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return pathType == PathType.Rail || pathType == PathType.Hoisting;
|
return pathType == PathType.Rail || pathType == PathType.Hoisting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool ShouldAllowFragmentPlanarFallback(PathType pathType)
|
||||||
|
{
|
||||||
|
return pathType != PathType.Hoisting;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Rotation3D ResolveCurrentRotationBaseline(
|
||||||
|
PathType pathType,
|
||||||
|
bool isRealObjectMode,
|
||||||
|
bool hasTrackedRotation,
|
||||||
|
Rotation3D trackedRotation,
|
||||||
|
bool hasReferenceRotation,
|
||||||
|
Rotation3D referenceRotation,
|
||||||
|
Rotation3D transformRotation,
|
||||||
|
bool hasActualGeometryRotation,
|
||||||
|
Rotation3D actualGeometryRotation)
|
||||||
|
{
|
||||||
|
if (isRealObjectMode &&
|
||||||
|
pathType == PathType.Hoisting &&
|
||||||
|
hasActualGeometryRotation)
|
||||||
|
{
|
||||||
|
return actualGeometryRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTrackedRotation)
|
||||||
|
{
|
||||||
|
return trackedRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRealObjectMode && hasReferenceRotation)
|
||||||
|
{
|
||||||
|
return referenceRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformRotation;
|
||||||
|
}
|
||||||
|
|
||||||
private void SyncTrackedRotationToDisplayedPose(ModelItem sourceObject)
|
private void SyncTrackedRotationToDisplayedPose(ModelItem sourceObject)
|
||||||
{
|
{
|
||||||
if (sourceObject == null)
|
if (sourceObject == null)
|
||||||
@ -4159,6 +4208,71 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryResolveHoistingActualPose(
|
||||||
|
Vector3 hostForward,
|
||||||
|
out Rotation3D rotation,
|
||||||
|
out Quaternion baselineQuaternion,
|
||||||
|
out LocalAxisDirection selectedAxisDirection,
|
||||||
|
out Vector3 selectedAxisLocal,
|
||||||
|
out Vector3 projectedForward)
|
||||||
|
{
|
||||||
|
rotation = Rotation3D.Identity;
|
||||||
|
baselineQuaternion = Quaternion.Identity;
|
||||||
|
selectedAxisDirection = LocalAxisDirection.PositiveX;
|
||||||
|
selectedAxisLocal = Vector3.UnitX;
|
||||||
|
projectedForward = Vector3.Zero;
|
||||||
|
|
||||||
|
if (_animatedObject == null ||
|
||||||
|
!ModelItemTransformHelper.TryGetCurrentGeometryRotation(_animatedObject, out var actualRotation3D))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var actualRotation = new Quaternion(
|
||||||
|
(float)actualRotation3D.A,
|
||||||
|
(float)actualRotation3D.B,
|
||||||
|
(float)actualRotation3D.C,
|
||||||
|
(float)actualRotation3D.D);
|
||||||
|
|
||||||
|
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||||||
|
Vector3 hostUp = adapter.HostType == CoordinateSystemType.YUp ? Vector3.UnitY : Vector3.UnitZ;
|
||||||
|
if (!HoistingRealObjectPoseHelper.TryCreateRotationFromActualPose(
|
||||||
|
actualRotation,
|
||||||
|
hostForward,
|
||||||
|
hostUp,
|
||||||
|
out baselineQuaternion,
|
||||||
|
out selectedAxisDirection,
|
||||||
|
out selectedAxisLocal,
|
||||||
|
out projectedForward))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotation = adapter.FromHostQuaternionDirect(
|
||||||
|
adapter.ComposeHostQuaternion(baselineQuaternion, _objectRotationCorrection));
|
||||||
|
|
||||||
|
Matrix4x4 baselineLinear = Matrix4x4.CreateFromQuaternion(baselineQuaternion);
|
||||||
|
Matrix4x4 hostComposedLinear = Matrix4x4.CreateFromQuaternion(new Quaternion(
|
||||||
|
(float)rotation.A,
|
||||||
|
(float)rotation.B,
|
||||||
|
(float)rotation.C,
|
||||||
|
(float)rotation.D));
|
||||||
|
|
||||||
|
LogManager.Debug(
|
||||||
|
$"[真实物体平面前进轴] Hoisting 已改用实际几何姿态基线,选中对象轴={selectedAxisDirection}。");
|
||||||
|
LogManager.Debug(
|
||||||
|
$"[真实物体起点姿态] 选中参考轴=({selectedAxisLocal.X:F3},{selectedAxisLocal.Y:F3},{selectedAxisLocal.Z:F3}), " +
|
||||||
|
$"投影前进=({projectedForward.X:F3},{projectedForward.Y:F3},{projectedForward.Z:F3}), " +
|
||||||
|
$"宿主修正={_objectRotationCorrection}, 本地修正=X=0.0°,Y=0.0°,Z=0.0°, " +
|
||||||
|
$"BaselineX=({baselineLinear.M11:F4},{baselineLinear.M21:F4},{baselineLinear.M31:F4}), " +
|
||||||
|
$"BaselineY=({baselineLinear.M12:F4},{baselineLinear.M22:F4},{baselineLinear.M32:F4}), " +
|
||||||
|
$"BaselineZ=({baselineLinear.M13:F4},{baselineLinear.M23:F4},{baselineLinear.M33:F4}), " +
|
||||||
|
$"HostComposeX=({hostComposedLinear.M11:F4},{hostComposedLinear.M21:F4},{hostComposedLinear.M31:F4}), " +
|
||||||
|
$"HostComposeY=({hostComposedLinear.M12:F4},{hostComposedLinear.M22:F4},{hostComposedLinear.M32:F4}), " +
|
||||||
|
$"HostComposeZ=({hostComposedLinear.M13:F4},{hostComposedLinear.M23:F4},{hostComposedLinear.M33:F4})");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static Quaternion Rotation3DToHostQuaternion(Rotation3D rotation)
|
private static Quaternion Rotation3DToHostQuaternion(Rotation3D rotation)
|
||||||
{
|
{
|
||||||
var linear = new Transform3D(rotation).Linear;
|
var linear = new Transform3D(rotation).Linear;
|
||||||
@ -4357,8 +4471,9 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
convention = null;
|
convention = null;
|
||||||
extents = (0.0, 0.0, 0.0);
|
extents = (0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
bool requiresReferenceRotation = _route?.PathType != PathType.Hoisting;
|
||||||
if (!IsRealObjectMode ||
|
if (!IsRealObjectMode ||
|
||||||
!_hasRealObjectReferenceRotation ||
|
(requiresReferenceRotation && !_hasRealObjectReferenceRotation) ||
|
||||||
_realObjectLength <= 0.0 ||
|
_realObjectLength <= 0.0 ||
|
||||||
_realObjectWidth <= 0.0 ||
|
_realObjectWidth <= 0.0 ||
|
||||||
_realObjectHeight <= 0.0)
|
_realObjectHeight <= 0.0)
|
||||||
@ -4386,8 +4501,9 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
convention = null;
|
convention = null;
|
||||||
extents = (0.0, 0.0, 0.0);
|
extents = (0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
bool requiresReferenceRotation = _route?.PathType != PathType.Hoisting;
|
||||||
if (!IsRealObjectMode ||
|
if (!IsRealObjectMode ||
|
||||||
!_hasRealObjectReferenceRotation ||
|
(requiresReferenceRotation && !_hasRealObjectReferenceRotation) ||
|
||||||
_realObjectLength <= 0.0 ||
|
_realObjectLength <= 0.0 ||
|
||||||
_realObjectWidth <= 0.0 ||
|
_realObjectWidth <= 0.0 ||
|
||||||
_realObjectHeight <= 0.0)
|
_realObjectHeight <= 0.0)
|
||||||
@ -4432,6 +4548,38 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_route?.PathType == PathType.Hoisting)
|
||||||
|
{
|
||||||
|
if (!TryResolveHoistingActualPose(
|
||||||
|
hostForward,
|
||||||
|
out var hoistingRotation,
|
||||||
|
out var baselineQuaternion,
|
||||||
|
out var selectedAxisDirection,
|
||||||
|
out _,
|
||||||
|
out _))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalAxisDirection hoistingSemanticUpAxis =
|
||||||
|
adapter.HostType == CoordinateSystemType.YUp
|
||||||
|
? LocalAxisDirection.PositiveY
|
||||||
|
: LocalAxisDirection.PositiveZ;
|
||||||
|
convention = new ModelAxisConvention(selectedAxisDirection, hoistingSemanticUpAxis);
|
||||||
|
|
||||||
|
Quaternion hoistingFinalHostQuaternion = Rotation3DToHostQuaternion(hoistingRotation);
|
||||||
|
extents = RealObjectProjectedExtentResolver.CalculateProjectedSemanticExtents(
|
||||||
|
convention,
|
||||||
|
_realObjectLength,
|
||||||
|
_realObjectWidth,
|
||||||
|
_realObjectHeight,
|
||||||
|
baselineQuaternion,
|
||||||
|
hoistingFinalHostQuaternion,
|
||||||
|
targetFrame.Forward,
|
||||||
|
targetFrame.Up);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!TryCreateRealObjectPlanarPoseSolution(
|
if (!TryCreateRealObjectPlanarPoseSolution(
|
||||||
targetFrame.Forward,
|
targetFrame.Forward,
|
||||||
targetFrame.Up,
|
targetFrame.Up,
|
||||||
@ -4761,6 +4909,12 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_route?.PathType == PathType.Hoisting)
|
||||||
|
{
|
||||||
|
LogManager.Error("[吊装真实物体姿态] 无法基于实际几何姿态生成起点姿态,已禁止回退到 fragment 参考姿态。");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PathTargetFrameResolver.TryCreatePlanarHostFrame(
|
if (!PathTargetFrameResolver.TryCreatePlanarHostFrame(
|
||||||
hostForward,
|
hostForward,
|
||||||
CoordinateSystemManager.Instance.CreateHostAdapter().HostType,
|
CoordinateSystemManager.Instance.CreateHostAdapter().HostType,
|
||||||
@ -4800,27 +4954,10 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
|
|
||||||
private bool TryCreateHoistingRealObjectRotationFromActualPose(Vector3 hostForward, out Rotation3D rotation)
|
private bool TryCreateHoistingRealObjectRotationFromActualPose(Vector3 hostForward, out Rotation3D rotation)
|
||||||
{
|
{
|
||||||
rotation = Rotation3D.Identity;
|
if (!TryResolveHoistingActualPose(
|
||||||
|
|
||||||
if (_animatedObject == null ||
|
|
||||||
!ModelItemTransformHelper.TryGetCurrentGeometryRotation(_animatedObject, out var actualRotation3D))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var actualRotation = new Quaternion(
|
|
||||||
(float)actualRotation3D.A,
|
|
||||||
(float)actualRotation3D.B,
|
|
||||||
(float)actualRotation3D.C,
|
|
||||||
(float)actualRotation3D.D);
|
|
||||||
|
|
||||||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
|
||||||
Vector3 hostUp = adapter.HostType == CoordinateSystemType.YUp ? Vector3.UnitY : Vector3.UnitZ;
|
|
||||||
if (!HoistingRealObjectPoseHelper.TryCreateRotationFromActualPose(
|
|
||||||
actualRotation,
|
|
||||||
hostForward,
|
hostForward,
|
||||||
hostUp,
|
out rotation,
|
||||||
out var baselineQuaternion,
|
out _,
|
||||||
out var selectedAxisDirection,
|
out var selectedAxisDirection,
|
||||||
out var selectedAxisLocal,
|
out var selectedAxisLocal,
|
||||||
out var projectedForward))
|
out var projectedForward))
|
||||||
@ -4828,31 +4965,8 @@ namespace NavisworksTransport.Core.Animation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotation = adapter.FromHostQuaternionDirect(
|
|
||||||
adapter.ComposeHostQuaternion(baselineQuaternion, _objectRotationCorrection));
|
|
||||||
|
|
||||||
Matrix4x4 baselineLinear = Matrix4x4.CreateFromQuaternion(baselineQuaternion);
|
|
||||||
Matrix4x4 hostComposedLinear = Matrix4x4.CreateFromQuaternion(new Quaternion(
|
|
||||||
(float)rotation.A,
|
|
||||||
(float)rotation.B,
|
|
||||||
(float)rotation.C,
|
|
||||||
(float)rotation.D));
|
|
||||||
|
|
||||||
_realObjectPlanarSelectedForwardAxis = selectedAxisDirection;
|
_realObjectPlanarSelectedForwardAxis = selectedAxisDirection;
|
||||||
_hasRealObjectPlanarSelectedForwardAxis = true;
|
_hasRealObjectPlanarSelectedForwardAxis = true;
|
||||||
|
|
||||||
LogManager.Debug(
|
|
||||||
$"[真实物体平面前进轴] Hoisting 已改用实际几何姿态基线,选中对象轴={selectedAxisDirection}。");
|
|
||||||
LogManager.Debug(
|
|
||||||
$"[真实物体起点姿态] 选中参考轴=({selectedAxisLocal.X:F3},{selectedAxisLocal.Y:F3},{selectedAxisLocal.Z:F3}), " +
|
|
||||||
$"投影前进=({projectedForward.X:F3},{projectedForward.Y:F3},{projectedForward.Z:F3}), " +
|
|
||||||
$"宿主修正={_objectRotationCorrection}, 本地修正=X=0.0°,Y=0.0°,Z=0.0°, " +
|
|
||||||
$"BaselineX=({baselineLinear.M11:F4},{baselineLinear.M21:F4},{baselineLinear.M31:F4}), " +
|
|
||||||
$"BaselineY=({baselineLinear.M12:F4},{baselineLinear.M22:F4},{baselineLinear.M32:F4}), " +
|
|
||||||
$"BaselineZ=({baselineLinear.M13:F4},{baselineLinear.M23:F4},{baselineLinear.M33:F4}), " +
|
|
||||||
$"HostComposeX=({hostComposedLinear.M11:F4},{hostComposedLinear.M21:F4},{hostComposedLinear.M31:F4}), " +
|
|
||||||
$"HostComposeY=({hostComposedLinear.M12:F4},{hostComposedLinear.M22:F4},{hostComposedLinear.M32:F4}), " +
|
|
||||||
$"HostComposeZ=({hostComposedLinear.M13:F4},{hostComposedLinear.M23:F4},{hostComposedLinear.M33:F4})");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user