refactor: 清理 fragment/参考姿态残留命名(默认轴约定一致性)

RealObjectRailAxisConventionResolver:
- 头注释改为默认轴约定语义,参数 referenceAxisX/Y/Z → defaultAxisX/Y/Z

PathAnimationManager:
- 字段 _realObjectReference* → _realObjectDefault*(默认轴约定)
- 方法 RealObjectReferenceRotation → RealObjectDefaultConvention、
  ReferenceBasedRealObjectPlanarPose → DefaultConventionRealObjectPlanarPose
- ResolveCurrentRotationBaseline 参数 hasReferenceRotation/referenceRotation → hasDefaultRotation/defaultRotation

RealObjectPlanarPoseSolver:
- TryCreatePlanarPoseFromReferencePose → FromDefaultPose、
  参数 referenceRotation → defaultRotation、fixedReferenceAxis → fixedDefaultAxis
- 属性 SelectedReferenceAxis* → SelectedDefaultAxis*(含测试同步)

测试: 方法名/局部变量 referenceRotation → defaultRotation 同步
  (VirtualObjectReferencePose 虚拟物体资产参考姿态为有效概念,保留)

TestAutomationHttpService: 过时错误文案(fragment 姿态解析失败)→ 盒内/层级链描述

验证: 单元 185/185、集成 25/25
This commit is contained in:
tian 2026-08-06 00:16:00 +08:00
parent 29da68f6d3
commit 869bfd3787
8 changed files with 162 additions and 163 deletions

View File

@ -227,8 +227,8 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
isRealObjectMode: true,
hasTrackedRotation: true,
trackedRotation: trackedRotation,
hasReferenceRotation: false,
referenceRotation: Rotation3D.Identity,
hasDefaultRotation: false,
defaultRotation: Rotation3D.Identity,
transformRotation: Rotation3D.Identity,
hasActualGeometryRotation: true,
actualGeometryRotation: actualGeometryRotation);
@ -250,8 +250,8 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
isRealObjectMode: true,
hasTrackedRotation: true,
trackedRotation: trackedRotation,
hasReferenceRotation: false,
referenceRotation: Rotation3D.Identity,
hasDefaultRotation: false,
defaultRotation: Rotation3D.Identity,
transformRotation: Rotation3D.Identity,
hasActualGeometryRotation: true,
actualGeometryRotation: actualGeometryRotation);

View File

@ -9,36 +9,36 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
public class RealObjectPlanarPoseSolverTests
{
[TestMethod]
public void ShouldChooseClosestCandidateAxis_FromRotatedReferencePose()
public void ShouldChooseClosestCandidateAxis_FromRotatedDefaultPose()
{
Quaternion referenceRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)(Math.PI / 6.0));
Quaternion defaultRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)(Math.PI / 6.0));
Vector3 desiredForward = new Vector3(1.0f, 0.2f, 0.1f);
Vector3 desiredUp = Vector3.UnitZ;
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForward,
desiredUp,
out RealObjectPlanarPoseSolution solution);
Assert.IsTrue(ok);
AssertVector(solution.SelectedReferenceAxisLocal, 1.0, 0.0, 0.0);
AssertVector(solution.SelectedDefaultAxisLocal, 1.0, 0.0, 0.0);
Vector3 transformedSelectedAxis = Vector3.Normalize(Vector3.Transform(solution.SelectedReferenceAxisLocal, solution.BaselineRotation));
Vector3 transformedSelectedAxis = Vector3.Normalize(Vector3.Transform(solution.SelectedDefaultAxisLocal, solution.BaselineRotation));
AssertVector(transformedSelectedAxis, desiredForward.X / desiredForward.Length(), desiredForward.Y / desiredForward.Length(), desiredForward.Z / desiredForward.Length(), 1e-4);
}
[TestMethod]
public void ShouldPreferNegativeAxisWhenItMatchesForwardBest()
{
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
Quaternion.Identity,
new Vector3(-0.1f, -1.0f, 0.05f),
Vector3.UnitZ,
out RealObjectPlanarPoseSolution solution);
Assert.IsTrue(ok);
AssertVector(solution.SelectedReferenceAxisLocal, 0.0, -1.0, 0.0);
AssertVector(solution.SelectedDefaultAxisLocal, 0.0, -1.0, 0.0);
}
[TestMethod]
@ -46,21 +46,21 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
{
Vector3 desiredForward = Vector3.Normalize(new Vector3(1.0f, 1.0f, 1.0f));
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
Quaternion.Identity,
desiredForward,
Vector3.UnitY,
out RealObjectPlanarPoseSolution solution);
Assert.IsTrue(ok);
Vector3 transformedSelectedAxis = Vector3.Normalize(Vector3.Transform(solution.SelectedReferenceAxisLocal, solution.BaselineRotation));
Vector3 transformedSelectedAxis = Vector3.Normalize(Vector3.Transform(solution.SelectedDefaultAxisLocal, solution.BaselineRotation));
AssertVector(transformedSelectedAxis, desiredForward.X, desiredForward.Y, desiredForward.Z, 1e-4);
}
[TestMethod]
public void ShouldPreserveReferenceOrthogonalityByApplyingSingleRotationDelta()
public void ShouldPreserveDefaultOrthogonalityByApplyingSingleRotationDelta()
{
Quaternion referenceRotation = Quaternion.Normalize(
Quaternion defaultRotation = Quaternion.Normalize(
Quaternion.CreateFromYawPitchRoll(
(float)(Math.PI / 7.0),
(float)(Math.PI / 9.0),
@ -68,8 +68,8 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
Vector3 desiredForward = Vector3.Normalize(new Vector3(-0.3f, 0.8f, 0.52f));
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForward,
Vector3.UnitZ,
out RealObjectPlanarPoseSolution solution);
@ -89,33 +89,33 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
}
[TestMethod]
public void FixedReferenceAxis_ShouldKeepAxisFamilyAcrossTurn()
public void FixedDefaultAxis_ShouldKeepAxisFamilyAcrossTurn()
{
Quaternion referenceRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)Math.PI);
Quaternion defaultRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)Math.PI);
Vector3 desiredForwardStart = Vector3.Normalize(new Vector3(-0.95f, 0.0f, 0.31f));
Vector3 desiredForwardTurn = Vector3.Normalize(new Vector3(0.22f, 0.0f, 0.97f));
Vector3 desiredUp = Vector3.UnitY;
bool startOk = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
bool startOk = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForwardStart,
desiredUp,
out RealObjectPlanarPoseSolution startSolution);
Assert.IsTrue(startOk);
bool turnOk = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
bool turnOk = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForwardTurn,
desiredUp,
startSolution.SelectedReferenceAxisDirection,
startSolution.SelectedDefaultAxisDirection,
out RealObjectPlanarPoseSolution turnSolution);
Assert.IsTrue(turnOk);
Assert.AreEqual(startSolution.SelectedReferenceAxisDirection, turnSolution.SelectedReferenceAxisDirection);
Assert.AreEqual(startSolution.SelectedDefaultAxisDirection, turnSolution.SelectedDefaultAxisDirection);
Vector3 transformedSelectedAxis = Vector3.Normalize(
Vector3.Transform(turnSolution.SelectedReferenceAxisLocal, turnSolution.BaselineRotation));
Vector3.Transform(turnSolution.SelectedDefaultAxisLocal, turnSolution.BaselineRotation));
AssertVector(
transformedSelectedAxis,
desiredForwardTurn.X,
@ -127,23 +127,23 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
[TestMethod]
public void FixedPositiveX_ShouldNotSwitchToZ_WhenPathLeansTowardZ()
{
Quaternion referenceRotation = Quaternion.Identity;
Quaternion defaultRotation = Quaternion.Identity;
Vector3 desiredForward = Vector3.Normalize(new Vector3(-0.690f, 0.0f, 0.724f));
Vector3 desiredUp = Vector3.UnitY;
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
bool ok = RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForward,
desiredUp,
LocalAxisDirection.PositiveX,
out RealObjectPlanarPoseSolution solution);
Assert.IsTrue(ok);
Assert.AreEqual(LocalAxisDirection.PositiveX, solution.SelectedReferenceAxisDirection);
AssertVector(solution.SelectedReferenceAxisLocal, 1.0, 0.0, 0.0);
Assert.AreEqual(LocalAxisDirection.PositiveX, solution.SelectedDefaultAxisDirection);
AssertVector(solution.SelectedDefaultAxisLocal, 1.0, 0.0, 0.0);
Vector3 transformedSelectedAxis = Vector3.Normalize(
Vector3.Transform(solution.SelectedReferenceAxisLocal, solution.BaselineRotation));
Vector3.Transform(solution.SelectedDefaultAxisLocal, solution.BaselineRotation));
AssertVector(
transformedSelectedAxis,
desiredForward.X,

View File

@ -8,7 +8,7 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
public class RealObjectRailAxisConventionResolverTests
{
[TestMethod]
public void YUp_InterpretedReferencePose_ShouldChoosePositiveXAndPositiveYForRail()
public void YUp_DefaultAxis_ShouldChoosePositiveXAndPositiveYForRail()
{
Vector3 referenceAxisX = new Vector3(-1.0f, 0.0f, 0.0f);
Vector3 referenceAxisY = new Vector3(0.0f, 1.0f, 0.0f);
@ -39,7 +39,7 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
}
[TestMethod]
public void ZUp_InterpretedReferencePose_ShouldChoosePositiveXAndPositiveZForRail()
public void ZUp_DefaultAxis_ShouldChoosePositiveXAndPositiveZForRail()
{
Vector3 referenceAxisX = new Vector3(-1.0f, 0.0f, 0.0f);
Vector3 referenceAxisY = new Vector3(0.0f, 1.0f, 0.0f);

View File

@ -112,15 +112,15 @@ namespace NavisworksTransport.Core.Animation
private double _realObjectLength = 0; // 真实物体长度(模型单位,固定物理尺寸)
private double _realObjectWidth = 0; // 真实物体宽度(模型单位,固定物理尺寸)
private double _realObjectHeight = 0; // 真实物体高度(模型单位,固定物理尺寸)
private Quaternion _realObjectReferenceRotation = Quaternion.Identity;
private Vector3 _realObjectReferenceAxisX = Vector3.UnitX;
private Vector3 _realObjectReferenceAxisY = Vector3.UnitY;
private Vector3 _realObjectReferenceAxisZ = Vector3.UnitZ;
private LocalAxisDirection _realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
private LocalAxisDirection _realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
private LocalAxisDirection _realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
private LocalAxisDirection _realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
private bool _hasRealObjectReferenceRotation = false;
private Quaternion _realObjectDefaultRotation = Quaternion.Identity;
private Vector3 _realObjectDefaultAxisX = Vector3.UnitX;
private Vector3 _realObjectDefaultAxisY = Vector3.UnitY;
private Vector3 _realObjectDefaultAxisZ = Vector3.UnitZ;
private LocalAxisDirection _realObjectDefaultHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
private LocalAxisDirection _realObjectDefaultHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
private LocalAxisDirection _realObjectDefaultHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
private LocalAxisDirection _realObjectDefaultHostUpLocalAxis = LocalAxisDirection.PositiveY;
private bool _hasRealObjectDefaultConvention = false;
private LocalAxisDirection _realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
private bool _hasRealObjectPlanarSelectedForwardAxis = false;
private List<Point3D> _pathPoints;
@ -597,7 +597,7 @@ namespace NavisworksTransport.Core.Animation
_animatedObjectMode = animatedObject == null
? AnimatedObjectMode.None
: AnimatedObjectMode.RealObject;
ResetRealObjectReferenceRotation();
ResetRealObjectDefaultConvention();
if (animatedObject != null)
{
@ -619,7 +619,7 @@ namespace NavisworksTransport.Core.Animation
: (_animatedObject != null ? AnimatedObjectMode.RealObject : AnimatedObjectMode.None);
if (isVirtualObject)
{
ResetRealObjectReferenceRotation();
ResetRealObjectDefaultConvention();
}
_virtualObjectLength = length; // 模型单位
_virtualObjectWidth = width; // 模型单位
@ -762,7 +762,7 @@ namespace NavisworksTransport.Core.Animation
_animatedObjectMode = isVirtualObject
? AnimatedObjectMode.VirtualObject
: AnimatedObjectMode.RealObject;
ResetRealObjectReferenceRotation();
ResetRealObjectDefaultConvention();
_originalTransform = animatedObject.Transform;
_originalCenter = animatedObject.BoundingBox().Center;
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
@ -1018,7 +1018,7 @@ namespace NavisworksTransport.Core.Animation
_animatedObjectMode = isVirtualObject
? AnimatedObjectMode.VirtualObject
: AnimatedObjectMode.RealObject;
ResetRealObjectReferenceRotation();
ResetRealObjectDefaultConvention();
_originalTransform = animatedObject.Transform;
_originalCenter = animatedObject.BoundingBox().Center;
_trackedPosition = ResolveInitialBusinessTrackedPosition(animatedObject);
@ -2898,11 +2898,11 @@ namespace NavisworksTransport.Core.Animation
{
currentRotation = _trackedRotation;
}
else if (IsRealObjectMode && _hasRealObjectReferenceRotation)
else if (IsRealObjectMode && _hasRealObjectDefaultConvention)
{
currentRotation = CoordinateSystemManager.Instance
.CreateHostAdapter()
.FromHostQuaternionDirect(_realObjectReferenceRotation);
.FromHostQuaternionDirect(_realObjectDefaultRotation);
}
else
{
@ -4061,7 +4061,7 @@ namespace NavisworksTransport.Core.Animation
return pathType != PathType.Hoisting && pathType != PathType.Ground;
}
internal static bool ShouldUseReferenceBasedRealObjectPlanarPose(PathType pathType)
internal static bool ShouldUseDefaultConventionRealObjectPlanarPose(PathType pathType)
{
return pathType != PathType.Ground && pathType != PathType.Hoisting;
}
@ -4156,8 +4156,8 @@ namespace NavisworksTransport.Core.Animation
bool isRealObjectMode,
bool hasTrackedRotation,
Rotation3D trackedRotation,
bool hasReferenceRotation,
Rotation3D referenceRotation,
bool hasDefaultRotation,
Rotation3D defaultRotation,
Rotation3D transformRotation,
bool hasActualGeometryRotation,
Rotation3D actualGeometryRotation)
@ -4174,9 +4174,9 @@ namespace NavisworksTransport.Core.Animation
return trackedRotation;
}
if (isRealObjectMode && hasReferenceRotation)
if (isRealObjectMode && hasDefaultRotation)
{
return referenceRotation;
return defaultRotation;
}
return transformRotation;
@ -4660,14 +4660,14 @@ namespace NavisworksTransport.Core.Animation
}
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
if (IsRealObjectMode && _hasRealObjectReferenceRotation)
if (IsRealObjectMode && _hasRealObjectDefaultConvention)
{
if (PathTargetFrameResolver.TryCreateRailHostFrame(_route, previousPoint, currentPoint, nextPoint, out var targetFrame) &&
RealObjectRailAxisConventionResolver.TryResolve(
_realObjectReferenceAxisX,
_realObjectReferenceAxisY,
_realObjectReferenceAxisZ,
_realObjectReferenceHostUpLocalAxis,
_realObjectDefaultAxisX,
_realObjectDefaultAxisY,
_realObjectDefaultAxisZ,
_realObjectDefaultHostUpLocalAxis,
targetFrame.Forward,
adapter.HostType,
out convention,
@ -4681,7 +4681,7 @@ namespace NavisworksTransport.Core.Animation
$"真实物体参考姿态生效, Forward={convention.ForwardAxis}, Up={convention.UpAxis}, " +
$"选中Forward轴={selectedForwardAxis}, 选中Forward世界轴=({selectedForwardWorldAxis.X:F4},{selectedForwardWorldAxis.Y:F4},{selectedForwardWorldAxis.Z:F4}), " +
$"选中Up轴={selectedUpAxis}, 选中Up世界轴=({selectedUpWorldAxis.X:F4},{selectedUpWorldAxis.Y:F4},{selectedUpWorldAxis.Z:F4}), " +
$"宿主Up对应本地轴={_realObjectReferenceHostUpLocalAxis}, " +
$"宿主Up对应本地轴={_realObjectDefaultHostUpLocalAxis}, " +
$"目标Forward=({targetFrame.Forward.X:F4},{targetFrame.Forward.Y:F4},{targetFrame.Forward.Z:F4}), " +
$"目标Up=({targetFrame.Up.X:F4},{targetFrame.Up.Y:F4},{targetFrame.Up.Z:F4})");
return true;
@ -4725,7 +4725,7 @@ namespace NavisworksTransport.Core.Animation
extents = (0.0, 0.0, 0.0);
if (!IsRealObjectMode ||
!_hasRealObjectReferenceRotation ||
!_hasRealObjectDefaultConvention ||
_realObjectLength <= 0.0 ||
_realObjectWidth <= 0.0 ||
_realObjectHeight <= 0.0)
@ -4767,10 +4767,10 @@ namespace NavisworksTransport.Core.Animation
localCorrection);
return RealObjectRailExtentResolver.TryResolveProjectedSemanticExtents(
_realObjectReferenceAxisX,
_realObjectReferenceAxisY,
_realObjectReferenceAxisZ,
_realObjectReferenceHostUpLocalAxis,
_realObjectDefaultAxisX,
_realObjectDefaultAxisY,
_realObjectDefaultAxisZ,
_realObjectDefaultHostUpLocalAxis,
targetFrame.Forward,
adapter.HostType,
_realObjectLength,
@ -4792,9 +4792,9 @@ namespace NavisworksTransport.Core.Animation
convention = null;
extents = (0.0, 0.0, 0.0);
bool requiresReferenceRotation = _route?.PathType != PathType.Hoisting;
bool requiresDefaultConvention = _route?.PathType != PathType.Hoisting;
if (!IsRealObjectMode ||
(requiresReferenceRotation && !_hasRealObjectReferenceRotation) ||
(requiresDefaultConvention && !_hasRealObjectDefaultConvention) ||
_realObjectLength <= 0.0 ||
_realObjectWidth <= 0.0 ||
_realObjectHeight <= 0.0)
@ -4822,9 +4822,9 @@ namespace NavisworksTransport.Core.Animation
convention = null;
extents = (0.0, 0.0, 0.0);
bool requiresReferenceRotation = ShouldUseReferenceBasedRealObjectPlanarPose(_route?.PathType ?? PathType.Ground);
bool requiresDefaultConvention = ShouldUseDefaultConventionRealObjectPlanarPose(_route?.PathType ?? PathType.Ground);
if (!IsRealObjectMode ||
(requiresReferenceRotation && !_hasRealObjectReferenceRotation) ||
(requiresDefaultConvention && !_hasRealObjectDefaultConvention) ||
_realObjectLength <= 0.0 ||
_realObjectWidth <= 0.0 ||
_realObjectHeight <= 0.0)
@ -4865,7 +4865,7 @@ namespace NavisworksTransport.Core.Animation
adapter.HostType == CoordinateSystemType.YUp
? LocalAxisDirection.PositiveY
: LocalAxisDirection.PositiveZ;
convention = new ModelAxisConvention(solution.SelectedReferenceAxisDirection, semanticUpAxis);
convention = new ModelAxisConvention(solution.SelectedDefaultAxisDirection, semanticUpAxis);
Quaternion finalHostQuaternion = adapter.ComposeHostQuaternion(
solution.BaselineRotation,
@ -5271,7 +5271,7 @@ namespace NavisworksTransport.Core.Animation
Matrix4x4 hostComposedLocalAxesLinear = Matrix4x4.CreateFromQuaternion(hostComposedQuaternion);
LogManager.Debug(
$"[真实物体起点姿态] 选中参考轴=({solution.SelectedReferenceAxisLocal.X:F3},{solution.SelectedReferenceAxisLocal.Y:F3},{solution.SelectedReferenceAxisLocal.Z:F3}), " +
$"[真实物体起点姿态] 选中参考轴=({solution.SelectedDefaultAxisLocal.X:F3},{solution.SelectedDefaultAxisLocal.Y:F3},{solution.SelectedDefaultAxisLocal.Z:F3}), " +
$"投影前进=({solution.ProjectedForward.X:F3},{solution.ProjectedForward.Y:F3},{solution.ProjectedForward.Z:F3}), " +
$"宿主修正={_objectRotationCorrection}, 本地修正={localCorrection}, " +
$"hostBaselineLocalXAxis=({hostBaselineLocalAxesLinear.M11:F4},{hostBaselineLocalAxesLinear.M21:F4},{hostBaselineLocalAxesLinear.M31:F4}), " +
@ -5308,12 +5308,12 @@ namespace NavisworksTransport.Core.Animation
{
solution = null;
if (!ShouldUseReferenceBasedRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
if (!ShouldUseDefaultConventionRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
{
return false;
}
if (!TryGetRealObjectReferenceRotation(out var referenceRotation))
if (!TryGetRealObjectDefaultConvention(out var defaultRotation))
{
return false;
}
@ -5326,8 +5326,8 @@ namespace NavisworksTransport.Core.Animation
fixedForwardAxis = LocalAxisDirection.PositiveX;
}
if (!RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromReferencePose(
referenceRotation,
if (!RealObjectPlanarPoseSolver.TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
targetForward,
targetUp,
fixedForwardAxis,
@ -5347,13 +5347,13 @@ namespace NavisworksTransport.Core.Animation
return true;
}
private bool TryGetRealObjectReferenceRotation(out Quaternion referenceRotation)
private bool TryGetRealObjectDefaultConvention(out Quaternion defaultRotation)
{
referenceRotation = Quaternion.Identity;
defaultRotation = Quaternion.Identity;
if (_hasRealObjectReferenceRotation)
if (_hasRealObjectDefaultConvention)
{
referenceRotation = _realObjectReferenceRotation;
defaultRotation = _realObjectDefaultRotation;
return true;
}
@ -5362,12 +5362,12 @@ namespace NavisworksTransport.Core.Animation
return false;
}
if (!ShouldUseReferenceBasedRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
if (!ShouldUseDefaultConventionRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
{
return false;
}
if (!TryCaptureRealObjectReferenceRotation(_animatedObject, out referenceRotation))
if (!TryCaptureRealObjectDefaultConvention(_animatedObject, out defaultRotation))
{
string objectName = _animatedObject?.DisplayName ?? "未知对象";
LogManager.Error($"[真实物体参考姿态] {objectName} 无法获取 fragment 参考姿态,已禁止回退默认姿态。");
@ -5377,9 +5377,9 @@ namespace NavisworksTransport.Core.Animation
return true;
}
private bool TryCaptureRealObjectReferenceRotation(ModelItem sourceObject, out Quaternion referenceRotation)
private bool TryCaptureRealObjectDefaultConvention(ModelItem sourceObject, out Quaternion defaultRotation)
{
referenceRotation = Quaternion.Identity;
defaultRotation = Quaternion.Identity;
if (sourceObject == null)
{
@ -5394,21 +5394,21 @@ namespace NavisworksTransport.Core.Animation
// 用户通过“调整物体”窗口手工指定最终朝向(所见即所得),无需 fragment。
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
referenceRotation = Quaternion.Identity;
_realObjectReferenceRotation = Quaternion.Identity;
_realObjectReferenceAxisX = Vector3.UnitX;
_realObjectReferenceAxisY = Vector3.UnitY;
_realObjectReferenceAxisZ = Vector3.UnitZ;
defaultRotation = Quaternion.Identity;
_realObjectDefaultRotation = Quaternion.Identity;
_realObjectDefaultAxisX = Vector3.UnitX;
_realObjectDefaultAxisY = Vector3.UnitY;
_realObjectDefaultAxisZ = Vector3.UnitZ;
LocalAxisDirection hostUpLocal = adapter.HostType == CoordinateSystemType.YUp
? LocalAxisDirection.PositiveY
: LocalAxisDirection.PositiveZ;
_realObjectReferenceHostUpLocalAxis = hostUpLocal;
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_hasRealObjectReferenceRotation = true;
_realObjectDefaultHostUpLocalAxis = hostUpLocal;
_realObjectDefaultHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectDefaultHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectDefaultHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_hasRealObjectDefaultConvention = true;
LogManager.Info(
$"[真实物体参考姿态] {sourceObject.DisplayName} 使用默认轴约定(不再依赖 fragment: " +
@ -5448,7 +5448,7 @@ namespace NavisworksTransport.Core.Animation
}
if (!isVirtualObject &&
!ShouldUseReferenceBasedRealObjectPlanarPose(_route?.PathType ?? PathType.Ground) &&
!ShouldUseDefaultConventionRealObjectPlanarPose(_route?.PathType ?? PathType.Ground) &&
ModelItemTransformHelper.TryGetCurrentGeometryRotation(sourceObject, out var groundActualGeometryRotation))
{
_trackedRotation = groundActualGeometryRotation;
@ -5464,16 +5464,16 @@ namespace NavisworksTransport.Core.Animation
return;
}
if (!isVirtualObject && TryCaptureRealObjectReferenceRotation(sourceObject, out Quaternion referenceRotation))
if (!isVirtualObject && TryCaptureRealObjectDefaultConvention(sourceObject, out Quaternion defaultRotation))
{
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
_trackedRotation = adapter.FromHostQuaternionDirect(referenceRotation);
_trackedRotation = adapter.FromHostQuaternionDirect(defaultRotation);
_hasTrackedRotation = true;
_currentYaw = ModelItemTransformHelper.GetYawFromRotation(_trackedRotation);
return;
}
if (!ShouldUseReferenceBasedRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
if (!ShouldUseDefaultConventionRealObjectPlanarPose(_route?.PathType ?? PathType.Ground))
{
// Ground/Hoisting 路径:无需参考姿态,使用单位旋转
_trackedRotation = Rotation3D.Identity;
@ -5498,17 +5498,17 @@ namespace NavisworksTransport.Core.Animation
return ModelAxisConvention.CreateVirtualObjectAssetConvention();
}
private void ResetRealObjectReferenceRotation()
private void ResetRealObjectDefaultConvention()
{
_realObjectReferenceRotation = Quaternion.Identity;
_realObjectReferenceAxisX = Vector3.UnitX;
_realObjectReferenceAxisY = Vector3.UnitY;
_realObjectReferenceAxisZ = Vector3.UnitZ;
_realObjectReferenceHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectReferenceHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectReferenceHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_realObjectReferenceHostUpLocalAxis = LocalAxisDirection.PositiveY;
_hasRealObjectReferenceRotation = false;
_realObjectDefaultRotation = Quaternion.Identity;
_realObjectDefaultAxisX = Vector3.UnitX;
_realObjectDefaultAxisY = Vector3.UnitY;
_realObjectDefaultAxisZ = Vector3.UnitZ;
_realObjectDefaultHostWorldXAxisLocalAxis = LocalAxisDirection.PositiveX;
_realObjectDefaultHostWorldYAxisLocalAxis = LocalAxisDirection.PositiveY;
_realObjectDefaultHostWorldZAxisLocalAxis = LocalAxisDirection.PositiveZ;
_realObjectDefaultHostUpLocalAxis = LocalAxisDirection.PositiveY;
_hasRealObjectDefaultConvention = false;
_realObjectPlanarSelectedForwardAxis = LocalAxisDirection.PositiveX;
_hasRealObjectPlanarSelectedForwardAxis = false;
}
@ -5524,9 +5524,9 @@ namespace NavisworksTransport.Core.Animation
{
return HostCoordinateAdapter.RemapHostSemanticCorrectionToLocalAxes(
_objectRotationCorrection,
_realObjectReferenceHostWorldXAxisLocalAxis,
_realObjectReferenceHostWorldYAxisLocalAxis,
_realObjectReferenceHostWorldZAxisLocalAxis);
_realObjectDefaultHostWorldXAxisLocalAxis,
_realObjectDefaultHostWorldYAxisLocalAxis,
_realObjectDefaultHostWorldZAxisLocalAxis);
}
/// <summary>

View File

@ -2824,7 +2824,7 @@ namespace NavisworksTransport.Core.Services
if (!IsSameModelItem(animationViewModel.SelectedAnimatedObject, realObject))
{
string detail = animationViewModel.SelectedAnimatedObject == null
? "选择真实物体失败:物体在当前文档不可用(fragment 姿态解析失败,常见于导出局部模型中的嵌套实例物体;请改用虚拟物体或单层结构物体"
? "选择真实物体失败:物体在当前文档不可用(导出局部模型中未解析到该物体,常见于物体不在路径剖面盒内或层级链不匹配;请改用虚拟物体或确认物体在盒内"
: "选择真实物体失败:动画视图模型未保留选中的对象";
throw new InvalidOperationException(detail);
}

View File

@ -16,30 +16,30 @@ namespace NavisworksTransport.Utils.CoordinateSystem
{
private const float AxisEpsilon = 1e-6f;
public static bool TryCreatePlanarPoseFromReferencePose(
Quaternion referenceRotation,
public static bool TryCreatePlanarPoseFromDefaultPose(
Quaternion defaultRotation,
Vector3 desiredForward,
Vector3 desiredUp,
out RealObjectPlanarPoseSolution solution)
{
return TryCreatePlanarPoseFromReferencePose(
referenceRotation,
return TryCreatePlanarPoseFromDefaultPose(
defaultRotation,
desiredForward,
desiredUp,
null,
out solution);
}
public static bool TryCreatePlanarPoseFromReferencePose(
Quaternion referenceRotation,
public static bool TryCreatePlanarPoseFromDefaultPose(
Quaternion defaultRotation,
Vector3 desiredForward,
Vector3 desiredUp,
LocalAxisDirection? fixedReferenceAxis,
LocalAxisDirection? fixedDefaultAxis,
out RealObjectPlanarPoseSolution solution)
{
solution = null;
if (!TryNormalize(referenceRotation, out Quaternion normalizedReferenceRotation))
if (!TryNormalize(defaultRotation, out Quaternion normalizedReferenceRotation))
{
return false;
}
@ -54,8 +54,8 @@ namespace NavisworksTransport.Utils.CoordinateSystem
return false;
}
CandidateAxis bestCandidate = fixedReferenceAxis.HasValue
? CreateCandidateAxisFromFixedDirection(fixedReferenceAxis.Value, normalizedReferenceRotation)
CandidateAxis bestCandidate = fixedDefaultAxis.HasValue
? CreateCandidateAxisFromFixedDirection(fixedDefaultAxis.Value, normalizedReferenceRotation)
: SelectBestCandidateAxis(
normalizedReferenceRotation,
normalizedForward);
@ -83,12 +83,12 @@ namespace NavisworksTransport.Utils.CoordinateSystem
}
private static CandidateAxis SelectBestCandidateAxis(
Quaternion referenceRotation,
Quaternion defaultRotation,
Vector3 desiredForward)
{
CandidateAxis bestCandidate = CandidateAxis.Invalid;
foreach (var candidate in EnumerateCandidateAxes(referenceRotation))
foreach (var candidate in EnumerateCandidateAxes(defaultRotation))
{
float score = Vector3.Dot(candidate.WorldAxis, desiredForward);
if (bestCandidate.IsInvalid || score > bestCandidate.Score)
@ -106,32 +106,32 @@ namespace NavisworksTransport.Utils.CoordinateSystem
private static CandidateAxis CreateCandidateAxisFromFixedDirection(
LocalAxisDirection direction,
Quaternion referenceRotation)
Quaternion defaultRotation)
{
Vector3 localAxis = GetAxisVector(direction);
Vector3 worldAxis = Vector3.Normalize(Vector3.Transform(localAxis, referenceRotation));
Vector3 worldAxis = Vector3.Normalize(Vector3.Transform(localAxis, defaultRotation));
return new CandidateAxis(direction, localAxis, worldAxis, 0f);
}
private static CandidateAxis[] EnumerateCandidateAxes(Quaternion referenceRotation)
private static CandidateAxis[] EnumerateCandidateAxes(Quaternion defaultRotation)
{
return new[]
{
CreateCandidateAxis(LocalAxisDirection.PositiveX, Vector3.UnitX, referenceRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeX, -Vector3.UnitX, referenceRotation),
CreateCandidateAxis(LocalAxisDirection.PositiveY, Vector3.UnitY, referenceRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeY, -Vector3.UnitY, referenceRotation),
CreateCandidateAxis(LocalAxisDirection.PositiveZ, Vector3.UnitZ, referenceRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeZ, -Vector3.UnitZ, referenceRotation)
CreateCandidateAxis(LocalAxisDirection.PositiveX, Vector3.UnitX, defaultRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeX, -Vector3.UnitX, defaultRotation),
CreateCandidateAxis(LocalAxisDirection.PositiveY, Vector3.UnitY, defaultRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeY, -Vector3.UnitY, defaultRotation),
CreateCandidateAxis(LocalAxisDirection.PositiveZ, Vector3.UnitZ, defaultRotation),
CreateCandidateAxis(LocalAxisDirection.NegativeZ, -Vector3.UnitZ, defaultRotation)
};
}
private static CandidateAxis CreateCandidateAxis(
LocalAxisDirection direction,
Vector3 localAxis,
Quaternion referenceRotation)
Quaternion defaultRotation)
{
Vector3 worldAxis = Vector3.Normalize(Vector3.Transform(localAxis, referenceRotation));
Vector3 worldAxis = Vector3.Normalize(Vector3.Transform(localAxis, defaultRotation));
return new CandidateAxis(direction, localAxis, worldAxis, float.MinValue);
}
@ -263,26 +263,26 @@ namespace NavisworksTransport.Utils.CoordinateSystem
{
public Vector3 ProjectedForward { get; }
public Vector3 DesiredUp { get; }
public LocalAxisDirection SelectedReferenceAxisDirection { get; }
public Vector3 SelectedReferenceAxisLocal { get; }
public Vector3 SelectedReferenceAxisWorld { get; }
public LocalAxisDirection SelectedDefaultAxisDirection { get; }
public Vector3 SelectedDefaultAxisLocal { get; }
public Vector3 SelectedDefaultAxisWorld { get; }
public Quaternion RotationDelta { get; }
public Quaternion BaselineRotation { get; }
public RealObjectPlanarPoseSolution(
Vector3 projectedForward,
Vector3 desiredUp,
LocalAxisDirection selectedReferenceAxisDirection,
Vector3 selectedReferenceAxisLocal,
Vector3 selectedReferenceAxisWorld,
LocalAxisDirection selectedDefaultAxisDirection,
Vector3 selectedDefaultAxisLocal,
Vector3 selectedDefaultAxisWorld,
Quaternion rotationDelta,
Quaternion baselineRotation)
{
ProjectedForward = projectedForward;
DesiredUp = desiredUp;
SelectedReferenceAxisDirection = selectedReferenceAxisDirection;
SelectedReferenceAxisLocal = selectedReferenceAxisLocal;
SelectedReferenceAxisWorld = selectedReferenceAxisWorld;
SelectedDefaultAxisDirection = selectedDefaultAxisDirection;
SelectedDefaultAxisLocal = selectedDefaultAxisLocal;
SelectedDefaultAxisWorld = selectedDefaultAxisWorld;
RotationDelta = rotationDelta;
BaselineRotation = baselineRotation;
}

View File

@ -4,24 +4,23 @@ using System.Numerics;
namespace NavisworksTransport.Utils.CoordinateSystem
{
/// <summary>
/// 根据“已解释为当前宿主语义”的真实物体参考姿态,解析 Rail 路径应使用的局部轴约定。
/// 在“默认局部轴约定”下解析 Rail 路径应使用的局部轴约定。
///
/// 语义:
/// - 真实物体没有资产坐标系,但 fragment 参考姿态经过 Fragment默认Up 解释后,
/// 可以得到“当前宿主语义下”的真实参考三轴。
/// - Rail 与 Ground/Hoisting 的统一点在于:都先解释对象姿态,再进入路径框架。
/// - Rail 的特殊性只在路径框架forward 来自 rail 切向up 来自 rail 法向。
/// - 本解析器只负责回答:对这个真实物体来说,哪个局部 forward 轴最接近当前路径 forward
/// 语义0.18.2 起,真实物体姿态链不依赖 fragment
/// - 真实物体没有资产坐标系姿态链使用默认局部轴forward=+Xup=宿主 up
/// 作为基线,用户通过“调整物体”手工指定最终朝向。
/// - 本解析器只负责回答:在这组默认局部轴中,哪个局部 forward 轴最接近当前路径 forward
/// up 轴始终采用当前宿主语义对应的轴族YUp => +YZUp => +Z
/// - 这样轨道沿 Y 时自动用 +Y 作 forward避免 90° 基线偏差,减少用户调整量。
/// </summary>
public static class RealObjectRailAxisConventionResolver
{
private const float AxisEpsilon = 1e-6f;
public static bool TryResolve(
Vector3 referenceAxisX,
Vector3 referenceAxisY,
Vector3 referenceAxisZ,
Vector3 defaultAxisX,
Vector3 defaultAxisY,
Vector3 defaultAxisZ,
LocalAxisDirection hostUpLocalAxis,
Vector3 desiredForward,
CoordinateSystemType hostType,
@ -44,9 +43,9 @@ namespace NavisworksTransport.Utils.CoordinateSystem
return false;
}
if (!TryNormalize(referenceAxisX, out Vector3 axisX) ||
!TryNormalize(referenceAxisY, out Vector3 axisY) ||
!TryNormalize(referenceAxisZ, out Vector3 axisZ))
if (!TryNormalize(defaultAxisX, out Vector3 axisX) ||
!TryNormalize(defaultAxisY, out Vector3 axisY) ||
!TryNormalize(defaultAxisZ, out Vector3 axisZ))
{
return false;
}

View File

@ -17,9 +17,9 @@ namespace NavisworksTransport.Utils.CoordinateSystem
public static class RealObjectRailExtentResolver
{
public static bool TryResolveProjectedSemanticExtents(
Vector3 referenceAxisX,
Vector3 referenceAxisY,
Vector3 referenceAxisZ,
Vector3 defaultAxisX,
Vector3 defaultAxisY,
Vector3 defaultAxisZ,
LocalAxisDirection hostUpLocalAxis,
Vector3 desiredForward,
CoordinateSystemType hostType,
@ -35,9 +35,9 @@ namespace NavisworksTransport.Utils.CoordinateSystem
extents = (0.0, 0.0, 0.0);
if (!RealObjectRailAxisConventionResolver.TryResolve(
referenceAxisX,
referenceAxisY,
referenceAxisZ,
defaultAxisX,
defaultAxisY,
defaultAxisZ,
hostUpLocalAxis,
desiredForward,
hostType,