Fix rail assembly anchor alignment
This commit is contained in:
parent
3a5693a453
commit
2b6f54898a
@ -73,6 +73,7 @@
|
||||
<Compile Include="UnitTests\CoordinateSystem\PathTargetFrameResolverTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\AssemblyEndFaceAnalyzerTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\AssemblyInstallationReferenceBuilderTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\PathPointVisualizationTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\FragmentDefaultUpContextTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\VirtualGroundPoseCharacterizationTests.cs" />
|
||||
<Compile Include="UnitTests\Properties\AssemblyInfo.cs" />
|
||||
|
||||
32
UnitTests/CoordinateSystem/PathPointVisualizationTests.cs
Normal file
32
UnitTests/CoordinateSystem/PathPointVisualizationTests.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Autodesk.Navisworks.Api;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
{
|
||||
[TestClass]
|
||||
public class PathPointVisualizationTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ResolveVisualizationRadius_WhenVisualizationDiameterIsUnset_ShouldUseDefaultRadius()
|
||||
{
|
||||
var point = new PathPoint(new Point3D(1.0, 2.0, 3.0), "测试点", PathPointType.WayPoint);
|
||||
|
||||
double radius = point.ResolveVisualizationRadius(0.25);
|
||||
|
||||
Assert.AreEqual(0.25, radius, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ResolveVisualizationRadius_WhenVisualizationDiameterIsSpecified_ShouldUseHalfDiameter()
|
||||
{
|
||||
var point = new PathPoint(new Point3D(1.0, 2.0, 3.0), "测试点", PathPointType.WayPoint)
|
||||
{
|
||||
VisualizationDiameter = 0.10
|
||||
};
|
||||
|
||||
double radius = point.ResolveVisualizationRadius(0.25);
|
||||
|
||||
Assert.AreEqual(0.05, radius, 1e-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,6 +191,8 @@ namespace NavisworksTransport.Core.Animation
|
||||
private Vector3D _groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
||||
private bool _hasGroundRealObjectStartCompensation = false;
|
||||
private bool _suppressGroundRealObjectCompensation = false;
|
||||
private Vector3D _railPreservedPoseTrackedCenterOffset = new Vector3D(0, 0, 0);
|
||||
private bool _hasRailPreservedPoseTrackedCenterOffset = false;
|
||||
|
||||
// TimeLiner 集成
|
||||
private TimeLinerIntegrationManager _timeLinerManager;
|
||||
@ -475,6 +477,8 @@ namespace NavisworksTransport.Core.Animation
|
||||
string objectName = isVirtual ? "虚拟物体" : objectToRestore.DisplayName;
|
||||
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
||||
_hasGroundRealObjectStartCompensation = false;
|
||||
_railPreservedPoseTrackedCenterOffset = new Vector3D(0, 0, 0);
|
||||
_hasRailPreservedPoseTrackedCenterOffset = false;
|
||||
LogManager.Info($"[归位] {objectName} 已彻底恢复到原始位置, yaw={_currentYaw:F3}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -743,9 +747,19 @@ namespace NavisworksTransport.Core.Animation
|
||||
{
|
||||
Point3D previousPoint = _pathPoints[0];
|
||||
Point3D nextPoint = _pathPoints.Count > 1 ? _pathPoints[1] : _pathPoints[0];
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousPoint, _pathPoints[0], nextPoint);
|
||||
startPosition = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, startPosition, previousPoint, nextPoint, objectHeight);
|
||||
if (TryResolveRailPreservedPoseTrackedCenter(startPosition, out Point3D preservedTrackedCenter))
|
||||
{
|
||||
startPosition = preservedTrackedCenter;
|
||||
LogManager.Debug(
|
||||
$"[移动到起点] Rail保持姿态补偿: 参考点=({_pathPoints[0].X:F2},{_pathPoints[0].Y:F2},{_pathPoints[0].Z:F2}), " +
|
||||
$"补偿后中心=({startPosition.X:F2},{startPosition.Y:F2},{startPosition.Z:F2})");
|
||||
}
|
||||
else
|
||||
{
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousPoint, _pathPoints[0], nextPoint);
|
||||
startPosition = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, startPosition, previousPoint, nextPoint, objectHeight);
|
||||
LogManager.Debug($"[移动到起点] Rail路径调整: 参考点=({_pathPoints[0].X:F2},{_pathPoints[0].Y:F2},{_pathPoints[0].Z:F2}), 物体中心=({startPosition.X:F2},{startPosition.Y:F2},{startPosition.Z:F2}), 物体高度={objectHeight:F2}, 安装={_route.RailMountMode}, 对接={(PathRoute.IsTopPayloadAnchorForMountMode(_route.RailMountMode) ? "顶面对接" : "底面对接")}");
|
||||
}
|
||||
|
||||
if (TryCreateRailPathRotation(
|
||||
previousPoint,
|
||||
@ -926,10 +940,16 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
else if (_route.PathType == PathType.Rail)
|
||||
{
|
||||
CaptureRailPreservedPoseTrackedCenterOffset();
|
||||
Point3D previousPoint = _pathPoints[0];
|
||||
Point3D nextPoint = _pathPoints.Count > 1 ? _pathPoints[1] : _pathPoints[0];
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousPoint, _pathPoints[0], nextPoint);
|
||||
startPosition = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, startPosition, previousPoint, nextPoint, objectHeight);
|
||||
if (!TryResolveRailPreservedPoseTrackedCenter(startPosition, out Point3D preservedTrackedCenter))
|
||||
{
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousPoint, _pathPoints[0], nextPoint);
|
||||
preservedTrackedCenter = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, startPosition, previousPoint, nextPoint, objectHeight);
|
||||
}
|
||||
|
||||
startPosition = preservedTrackedCenter;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1204,8 +1224,18 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
else if (_route.PathType == PathType.Rail)
|
||||
{
|
||||
framePosition = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, framePosition, p1, p2, objectHeight);
|
||||
LogManager.Debug($"[Rail路径] 调整物体位置: 参考点=({p1.X:F2},{p1.Y:F2},{p1.Z:F2})->({p2.X:F2},{p2.Y:F2},{p2.Z:F2}), 物体中心=({framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2}), 安装={_route.RailMountMode}, 对接={(PathRoute.IsTopPayloadAnchorForMountMode(_route.RailMountMode) ? "顶面对接" : "底面对接")}");
|
||||
if (TryResolveRailPreservedPoseTrackedCenter(framePosition, out Point3D preservedTrackedCenter))
|
||||
{
|
||||
framePosition = preservedTrackedCenter;
|
||||
LogManager.Debug(
|
||||
$"[Rail路径] 保持姿态补偿: 参考点=({p1.X:F2},{p1.Y:F2},{p1.Z:F2})->({p2.X:F2},{p2.Y:F2},{p2.Z:F2}), " +
|
||||
$"物体中心=({framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2})");
|
||||
}
|
||||
else
|
||||
{
|
||||
framePosition = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(_route, framePosition, p1, p2, objectHeight);
|
||||
LogManager.Debug($"[Rail路径] 调整物体位置: 参考点=({p1.X:F2},{p1.Y:F2},{p1.Z:F2})->({p2.X:F2},{p2.Y:F2},{p2.Z:F2}), 物体中心=({framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2}), 安装={_route.RailMountMode}, 对接={(PathRoute.IsTopPayloadAnchorForMountMode(_route.RailMountMode) ? "顶面对接" : "底面对接")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2164,13 +2194,16 @@ namespace NavisworksTransport.Core.Animation
|
||||
Point3D expectedTrackedEndPoint;
|
||||
if (_route.PathType == PathType.Rail)
|
||||
{
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousAnchorPoint, terminalAnchorPoint, terminalAnchorPoint);
|
||||
expectedTrackedEndPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
|
||||
_route,
|
||||
terminalAnchorPoint,
|
||||
previousAnchorPoint,
|
||||
terminalAnchorPoint,
|
||||
objectHeight);
|
||||
if (!TryResolveRailPreservedPoseTrackedCenter(terminalAnchorPoint, out expectedTrackedEndPoint))
|
||||
{
|
||||
double objectHeight = GetAnimatedObjectRailNormalExtent(previousAnchorPoint, terminalAnchorPoint, terminalAnchorPoint);
|
||||
expectedTrackedEndPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
|
||||
_route,
|
||||
terminalAnchorPoint,
|
||||
previousAnchorPoint,
|
||||
terminalAnchorPoint,
|
||||
objectHeight);
|
||||
}
|
||||
}
|
||||
else if (_route.PathType == PathType.Hoisting)
|
||||
{
|
||||
@ -3789,6 +3822,53 @@ namespace NavisworksTransport.Core.Animation
|
||||
return adapter.FromCanonicalPoint(new Point3D(canonicalCenter.X, canonicalCenter.Y, canonicalCenter.Z));
|
||||
}
|
||||
|
||||
private bool TryResolveRailPreservedPoseTrackedCenter(Point3D referencePoint, out Point3D trackedCenter)
|
||||
{
|
||||
trackedCenter = referencePoint;
|
||||
|
||||
if (!IsRealObjectMode ||
|
||||
_route?.PathType != PathType.Rail ||
|
||||
_objectStartPlacementMode != ObjectStartPlacementMode.PreserveInitialPose ||
|
||||
!_hasRailPreservedPoseTrackedCenterOffset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
trackedCenter = new Point3D(
|
||||
referencePoint.X + _railPreservedPoseTrackedCenterOffset.X,
|
||||
referencePoint.Y + _railPreservedPoseTrackedCenterOffset.Y,
|
||||
referencePoint.Z + _railPreservedPoseTrackedCenterOffset.Z);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CaptureRailPreservedPoseTrackedCenterOffset()
|
||||
{
|
||||
_railPreservedPoseTrackedCenterOffset = new Vector3D(0, 0, 0);
|
||||
_hasRailPreservedPoseTrackedCenterOffset = false;
|
||||
|
||||
if (!IsRealObjectMode ||
|
||||
_route?.PathType != PathType.Rail ||
|
||||
_objectStartPlacementMode != ObjectStartPlacementMode.PreserveInitialPose ||
|
||||
_pathPoints == null ||
|
||||
_pathPoints.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Point3D currentTrackedCenter = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
||||
Point3D terminalAnchorPoint = _pathPoints[_pathPoints.Count - 1];
|
||||
_railPreservedPoseTrackedCenterOffset = new Vector3D(
|
||||
currentTrackedCenter.X - terminalAnchorPoint.X,
|
||||
currentTrackedCenter.Y - terminalAnchorPoint.Y,
|
||||
currentTrackedCenter.Z - terminalAnchorPoint.Z);
|
||||
_hasRailPreservedPoseTrackedCenterOffset = true;
|
||||
|
||||
LogManager.Info(
|
||||
$"[Rail保持姿态补偿] 当前跟踪中心=({currentTrackedCenter.X:F3},{currentTrackedCenter.Y:F3},{currentTrackedCenter.Z:F3}), " +
|
||||
$"终点锚点=({terminalAnchorPoint.X:F3},{terminalAnchorPoint.Y:F3},{terminalAnchorPoint.Z:F3}), " +
|
||||
$"固定偏移=({_railPreservedPoseTrackedCenterOffset.X:F3},{_railPreservedPoseTrackedCenterOffset.Y:F3},{_railPreservedPoseTrackedCenterOffset.Z:F3})");
|
||||
}
|
||||
|
||||
private bool TryResolveGroundRealObjectBaseYaw(out double yawRadians)
|
||||
{
|
||||
yawRadians = 0.0;
|
||||
|
||||
@ -375,6 +375,13 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public double? CustomTurnRadius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仅用于视图显示的点直径(模型单位)。
|
||||
/// 为 null 或非正数时使用默认点类型尺寸。
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public double? VisualizationDiameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方向类型(仅吊装路径使用)
|
||||
/// 用于标识吊装路径点的移动方向:垂直、纵向(X轴)、横向(Y轴)
|
||||
@ -395,6 +402,7 @@ namespace NavisworksTransport
|
||||
Notes = string.Empty;
|
||||
SpeedLimit = 0;
|
||||
CustomTurnRadius = null;
|
||||
VisualizationDiameter = null;
|
||||
Direction = HoistingPointDirection.Vertical;
|
||||
}
|
||||
|
||||
@ -415,9 +423,25 @@ namespace NavisworksTransport
|
||||
Notes = string.Empty;
|
||||
SpeedLimit = 0;
|
||||
CustomTurnRadius = null;
|
||||
VisualizationDiameter = null;
|
||||
Direction = HoistingPointDirection.Vertical;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析最终用于渲染的点半径(模型单位)。
|
||||
/// </summary>
|
||||
/// <param name="defaultRadius">默认点半径(模型单位)</param>
|
||||
/// <returns>最终半径(模型单位)</returns>
|
||||
public double ResolveVisualizationRadius(double defaultRadius)
|
||||
{
|
||||
if (!VisualizationDiameter.HasValue || VisualizationDiameter.Value <= 0)
|
||||
{
|
||||
return defaultRadius;
|
||||
}
|
||||
|
||||
return VisualizationDiameter.Value * 0.5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回路径点描述字符串
|
||||
/// </summary>
|
||||
|
||||
@ -2268,7 +2268,8 @@ namespace NavisworksTransport
|
||||
{
|
||||
Center = point.Position,
|
||||
Normal = GetHostUpVector(),
|
||||
Radius = isGridVisualization ? GetRadiusForGridVisualization() : GetRadiusForPointType(point.Type),
|
||||
Radius = point.ResolveVisualizationRadius(
|
||||
isGridVisualization ? GetRadiusForGridVisualization() : GetRadiusForPointType(point.Type)),
|
||||
Color = isGridVisualization ? gridStyle.Color : GetColorForPointType(point.Type),
|
||||
Alpha = isGridVisualization ? gridStyle.Alpha : 1.0,
|
||||
Filled = true,
|
||||
|
||||
@ -125,6 +125,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
private const double DefaultAssemblyReferenceRodLengthInMeters = 20.0;
|
||||
private static readonly double DefaultAssemblyReferenceRodDiameterInMeters = CalculateDefaultAssemblyReferenceRodDiameterInMeters();
|
||||
private const double DefaultAssemblyAnchorVerticalOffsetInMeters = 0.0;
|
||||
private const double AssemblyVisualizationPointDiameterInMeters = 0.10;
|
||||
private const double RailNormalOffsetNudgeStepInMeters = 0.1;
|
||||
private const double DefaultAssemblySphereCenterX = 0.0;
|
||||
private const double DefaultAssemblySphereCenterY = 0.0;
|
||||
@ -2259,7 +2260,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
for (int i = 0; i < _assemblyEndFaceSeedPoints.Count; i++)
|
||||
{
|
||||
AddVisualizationPoint(markerRoute, _assemblyEndFaceSeedPoints[i], $"端面点{i + 1}", PathPointType.WayPoint);
|
||||
AddVisualizationPoint(
|
||||
markerRoute,
|
||||
_assemblyEndFaceSeedPoints[i],
|
||||
$"端面点{i + 1}",
|
||||
PathPointType.WayPoint,
|
||||
UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
|
||||
}
|
||||
|
||||
renderPlugin.RenderPointOnly(markerRoute);
|
||||
@ -2280,11 +2286,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
Id = AssemblyEndFaceCenterPathId,
|
||||
Description = "终端安装端面中心"
|
||||
};
|
||||
AddVisualizationPoint(markerRoute, centerPoint, "端面中心", PathPointType.WayPoint);
|
||||
AddVisualizationPoint(
|
||||
markerRoute,
|
||||
centerPoint,
|
||||
"端面中心",
|
||||
PathPointType.WayPoint,
|
||||
UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
|
||||
renderPlugin.RenderPointOnly(markerRoute);
|
||||
}
|
||||
|
||||
private static void AddVisualizationPoint(PathRoute route, Point3D position, string name, PathPointType type)
|
||||
private static void AddVisualizationPoint(
|
||||
PathRoute route,
|
||||
Point3D position,
|
||||
string name,
|
||||
PathPointType type,
|
||||
double? visualizationDiameter = null)
|
||||
{
|
||||
if (route == null)
|
||||
{
|
||||
@ -2293,7 +2309,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
route.Points.Add(new PathPoint(position, name, type)
|
||||
{
|
||||
Index = route.Points.Count
|
||||
Index = route.Points.Count,
|
||||
VisualizationDiameter = visualizationDiameter
|
||||
});
|
||||
}
|
||||
|
||||
@ -2379,7 +2396,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
};
|
||||
for (int i = 0; i < pickPoints.Count; i++)
|
||||
{
|
||||
AddVisualizationPoint(markerRoute, pickPoints[i], $"安装面点{i + 1}", PathPointType.WayPoint);
|
||||
AddVisualizationPoint(
|
||||
markerRoute,
|
||||
pickPoints[i],
|
||||
$"安装面点{i + 1}",
|
||||
PathPointType.WayPoint,
|
||||
UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
|
||||
}
|
||||
renderPlugin.RenderPointOnly(markerRoute);
|
||||
}
|
||||
@ -2398,7 +2420,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
Id = AssemblyInstallationAnchorPointPathId,
|
||||
Description = "终端安装点"
|
||||
};
|
||||
AddVisualizationPoint(markerRoute, anchorPoint, "安装点", PathPointType.WayPoint);
|
||||
AddVisualizationPoint(
|
||||
markerRoute,
|
||||
anchorPoint,
|
||||
"安装点",
|
||||
PathPointType.WayPoint,
|
||||
UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
|
||||
renderPlugin.RenderPointOnly(markerRoute);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user