Add rail mount placement controls and persistence
This commit is contained in:
parent
921dc07856
commit
3a5693a453
@ -58,6 +58,7 @@
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalRailPoseBuilderTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalPlanarPoseBuilderTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\ObjectSpaceOrientationHelperTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\ObjectStartPlacementRequestTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalRailOffsetResolverTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalTrackedPositionResolverTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\FragmentRepresentativePoseHelperTests.cs" />
|
||||
|
||||
@ -336,6 +336,7 @@
|
||||
<Compile Include="src\Utils\CoordinateSystem\CanonicalBounds3.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\LocalAxisPoseBuilder.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\LocalEulerRotationCorrection.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\ObjectStartPlacementRequest.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\CanonicalPlanarPoseBuilder.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\CanonicalRailOffsetResolver.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\CanonicalRailPoseBuilder.cs" />
|
||||
|
||||
@ -91,6 +91,27 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
AssertVector(trackedCenter, 0.0, 0.0, 2.0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RailNormalOffset_ShouldAddExtraDisplacementAlongRailNormal()
|
||||
{
|
||||
PathRoute route = new PathRoute
|
||||
{
|
||||
PathType = PathType.Rail,
|
||||
RailMountMode = RailMountMode.OverRail,
|
||||
RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine,
|
||||
RailNormalOffset = 1.5
|
||||
};
|
||||
|
||||
RailLocalFrame frame = new RailLocalFrame(Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ);
|
||||
Vector3 trackedCenter = CanonicalRailOffsetResolver.ResolveTrackedCenter(
|
||||
route,
|
||||
Vector3.Zero,
|
||||
frame,
|
||||
4.0);
|
||||
|
||||
AssertVector(trackedCenter, 0.0, 0.0, 3.5);
|
||||
}
|
||||
|
||||
private static void AssertVector(Vector3 actual, double x, double y, double z)
|
||||
{
|
||||
Assert.AreEqual(x, actual.X, 1e-6);
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NavisworksTransport.Utils.CoordinateSystem;
|
||||
|
||||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
{
|
||||
[TestClass]
|
||||
public class ObjectStartPlacementRequestTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TranslationOnly_ShouldPreserveInitialPoseAndClearRotationCorrection()
|
||||
{
|
||||
var request = ObjectStartPlacementRequest.TranslationOnly;
|
||||
|
||||
Assert.AreEqual(ObjectStartPlacementMode.PreserveInitialPose, request.PlacementMode);
|
||||
Assert.IsTrue(request.PreserveInitialPose);
|
||||
Assert.AreEqual(LocalEulerRotationCorrection.Zero, request.RotationCorrection);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotationCorrectionRequest_ShouldKeepCorrectionAndAlignToPathPose()
|
||||
{
|
||||
var correction = new LocalEulerRotationCorrection(15.0, 30.0, 45.0);
|
||||
|
||||
var request = ObjectStartPlacementRequest.CreateRotationCorrection(correction);
|
||||
|
||||
Assert.AreEqual(ObjectStartPlacementMode.AlignToPathPose, request.PlacementMode);
|
||||
Assert.IsFalse(request.PreserveInitialPose);
|
||||
Assert.AreEqual(correction, request.RotationCorrection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,6 +38,7 @@ namespace NavisworksTransport.UnitTests.Core
|
||||
""pathType"": ""Rail"",
|
||||
""railMountMode"": ""OverRail"",
|
||||
""railPathDefinitionMode"": ""RailCenterLine"",
|
||||
""railNormalOffset"": 0.25,
|
||||
""railPreferredNormal"": { ""x"": -0.2, ""y"": 0.5, ""z"": 0.8 },
|
||||
""totalLength"": 10.0,
|
||||
""objectLimits"": { ""maxLength"": 0, ""maxWidth"": 0, ""maxHeight"": 0, ""safetyMargin"": 0 },
|
||||
@ -57,6 +58,7 @@ namespace NavisworksTransport.UnitTests.Core
|
||||
var importedRoutes = manager.ImportFromJson(filePath);
|
||||
Assert.AreEqual(1, importedRoutes.Count);
|
||||
Assert.IsNotNull(importedRoutes[0].RailPreferredNormal);
|
||||
Assert.AreEqual(0.25, importedRoutes[0].RailNormalOffset, 1e-6);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -78,7 +80,7 @@ namespace NavisworksTransport.UnitTests.Core
|
||||
<PathPlanningData xmlns=""http://www.3ds.com/delmia/pathplanning"" version=""1.0"" generator=""test"" timestamp=""2026-03-25T00:00:00"">
|
||||
<ProjectInfo name=""test"" description=""test"" units=""meters"" coordinateSystem=""Global"" />
|
||||
<Routes>
|
||||
<Route id=""route-1"" name=""rail-test"" description="""" pathType=""Rail"" railMountMode=""OverRail"" railPathDefinitionMode=""RailCenterLine"" railPreferredNormalX=""0.0"" railPreferredNormalY=""1.0"" railPreferredNormalZ=""-0.5"" totalLength=""10.0"" maxObjectLength=""0.0"" maxObjectWidth=""0.0"" maxObjectHeight=""0.0"" safetyMargin=""0.0"" gridSize=""1.0"" liftHeight=""0.0"" created=""2026-03-25T00:00:00"">
|
||||
<Route id=""route-1"" name=""rail-test"" description="""" pathType=""Rail"" railMountMode=""OverRail"" railPathDefinitionMode=""RailCenterLine"" railNormalOffset=""0.25"" railPreferredNormalX=""0.0"" railPreferredNormalY=""1.0"" railPreferredNormalZ=""-0.5"" totalLength=""10.0"" maxObjectLength=""0.0"" maxObjectWidth=""0.0"" maxObjectHeight=""0.0"" safetyMargin=""0.0"" gridSize=""1.0"" liftHeight=""0.0"" created=""2026-03-25T00:00:00"">
|
||||
<Points>
|
||||
<Point id=""p1"" name=""start"" type=""StartPoint"" index=""0"" x=""0"" y=""0"" z=""0"" created=""2026-03-25T00:00:00"" />
|
||||
<Point id=""p2"" name=""end"" type=""EndPoint"" index=""1"" x=""10"" y=""0"" z=""0"" created=""2026-03-25T00:00:00"" />
|
||||
@ -91,6 +93,7 @@ namespace NavisworksTransport.UnitTests.Core
|
||||
var importedRoutes = manager.ImportFromXml(filePath);
|
||||
Assert.AreEqual(1, importedRoutes.Count);
|
||||
Assert.IsNotNull(importedRoutes[0].RailPreferredNormal);
|
||||
Assert.AreEqual(0.25, importedRoutes[0].RailNormalOffset, 1e-6);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,27 @@
|
||||
- `YUp` 模型下,终端安装仿真、`Rail` 姿态、真实物体与虚拟物体通行空间、起点与动画主链路已基本跑通。
|
||||
- 地面路径在 `YUp` 模型下:
|
||||
- 虚拟物体起点姿态、动画姿态、转弯姿态已恢复正常。
|
||||
- 当前已禁止地面/吊装路径偷偷退回旧 `yaw` 链路。
|
||||
- 真实物体地面路径当前已恢复到可用状态:
|
||||
- 起点落位补偿已接入;
|
||||
- 逐帧补偿会随当前目标姿态一起旋转,不再使用固定世界补偿矢量;
|
||||
- 动画结束后不再因恢复链或重复落最后一帧而再次跳动。
|
||||
- `Ground + 真实物体` 的逐帧姿态约束已经明确:
|
||||
- 动画播放阶段只允许绕宿主 `up` 轴转动;
|
||||
- 不再在播放阶段每帧重建完整三维姿态。
|
||||
- `Ground/Hoisting + 真实物体` 的前进轴语义当前已固定:
|
||||
- 对象级前进轴统一按 `PositiveX` 解释;
|
||||
- 不再因为路径初始方向更偏 `Z` 就把对象前进轴自动切换成 `PositiveZ`。
|
||||
- 当前已禁止地面/吊装路径偷偷退回旧 `yaw` 链路。
|
||||
- 碰撞检测/恢复主链路已稳定:
|
||||
- `ClashDetective` 三维恢复不能再先 `ResetPermanentTransform`。
|
||||
- 碰撞恢复、自动报告、自动截图已重新对齐到动画主链路。
|
||||
- 虚拟物体资源问题已确认并修复:
|
||||
- 旧 `unit_cube.nwc` 局部几何中心不在原点,会导致虚拟物体中心偏差。
|
||||
- 新 `unit_cube.nwc` 已替换为几何中心在原点的版本。
|
||||
- 旋转适配入口当前稳定分流:
|
||||
- 虚拟物体继续走 `HostCoordinateAdapter` 的 `Legacy` 入口;
|
||||
- 真实物体走 `Direct` 入口;
|
||||
- 两者不能再强行共用同一条旋转转换链。
|
||||
|
||||
## 2. 当前坐标系架构
|
||||
|
||||
@ -63,6 +77,10 @@
|
||||
- 当前规则:
|
||||
- 先解释真实物体参考姿态,再做路径对齐
|
||||
- 不能跳过这一步,直接拿 fragment 世界轴去猜业务姿态
|
||||
- 当前补充规则:
|
||||
- `Ground/Hoisting` 的真实物体“对象前进轴”与 fragment 参考姿态解释是两层语义;
|
||||
- fragment 负责解释真实参考姿态;
|
||||
- 对象前进轴当前在 `Ground/Hoisting` 上固定按 `PositiveX` 语义使用,不再做“按路径方向选最近轴”的自动切换。
|
||||
|
||||
### 4.1 Rotation / 矩阵语义
|
||||
|
||||
@ -102,6 +120,15 @@
|
||||
- 目前稳定可用的是:`Y` 轴转动。
|
||||
- `X / Z` 轴在起点静态预览或直线段里可能看起来合理,但路径一旦拐弯,逐帧按宿主世界轴重算会让“俯仰/侧倾”语义发生耦合,表现成不符合现场直觉的侧旋。
|
||||
- 因此当前阶段,对地面路径应按“只稳定支持 `Y` 轴转动”使用;`X / Z` 轴播放链问题留待后续专项修复。
|
||||
- 当前新增稳定规则(2026-03-25):
|
||||
- `Ground + 真实物体` 的播放阶段不能再每帧应用完整三维姿态;
|
||||
- 必须以起点基姿态为基线,只叠加宿主 `up` 轴上的单轴旋转。
|
||||
- 当前新增稳定规则(2026-03-25):
|
||||
- `Ground + 真实物体` 的起点目标点语义仍然是路径跟踪点,不允许修改路径点本身;
|
||||
- 如真实物体起点落位存在固定偏差,应把补偿施加到物体位置,而不是回写路径点或路径跟踪点语义。
|
||||
- 当前新增稳定规则(2026-03-25):
|
||||
- `Ground + 真实物体` 的补偿不是固定世界矢量;
|
||||
- 起点测得的偏差必须随当前目标姿态一起旋转后,再参与逐帧位置应用。
|
||||
- `YUp` 吊装路径创建主链路已补齐到宿主坐标适配架构:
|
||||
- 提升、水平移动、下降、终点落地都不能再把世界 `Z` 硬编码成“向上”。
|
||||
- 终点必须使用用户最后一次点击的地面点,不能回填起点地面高程。
|
||||
@ -223,10 +250,35 @@
|
||||
- 保存/恢复姿态
|
||||
- 关键碰撞恢复
|
||||
- 虚拟物体应用后中心/偏差
|
||||
- 真实物体地面路径:
|
||||
- `[路径起点诊断]`
|
||||
- `[路径起点补偿]`
|
||||
- `[Ground路径补偿]`
|
||||
- 已降级或删除:
|
||||
- 大量重复逐帧宿主姿态轴日志
|
||||
- 虚拟物体 `Transform` 即时读回日志(容易误导)
|
||||
|
||||
## 6. 当前 Navisworks 变换 API 结论
|
||||
|
||||
- `ModelItem.Transform`
|
||||
- 只表示原始设计文件变换;
|
||||
- 不反映 `OverridePermanentTransform` 后的当前显示姿态。
|
||||
- `ModelGeometry.ActiveTransform`
|
||||
- 是当前几何实际生效的变换;
|
||||
- 当前项目里,凡是要读“当前姿态/当前位置”,优先使用这一层。
|
||||
- `ModelGeometry`
|
||||
- 关键四层语义:
|
||||
- `OriginalTransform`
|
||||
- `PermanentOverrideTransform`
|
||||
- `PermanentTransform`
|
||||
- `ActiveTransform`
|
||||
- `OverridePermanentTransform(...)`
|
||||
- 官方语义是增量变换;
|
||||
- 不是“直接设成最终世界姿态”。
|
||||
- `ResetPermanentTransform(...)`
|
||||
- 清掉的是永久增量层;
|
||||
- 不会修改原始设计文件变换。
|
||||
|
||||
## 6. 当前还值得继续观察的点
|
||||
|
||||
- 空轨路径里仍有一个旧 warning:
|
||||
|
||||
@ -205,6 +205,9 @@ namespace NavisworksTransport.Core.Animation
|
||||
private Rotation3D _savedObjectRotation = Rotation3D.Identity;
|
||||
private bool _savedObjectHasCustomRotation = false;
|
||||
private bool _hasSavedObjectState = false;
|
||||
private ObjectStartPlacementMode _objectStartPlacementMode = ObjectStartPlacementMode.AlignToPathPose;
|
||||
private Rotation3D _railPreservedPoseRotation = Rotation3D.Identity;
|
||||
private bool _hasRailPreservedPoseRotation = false;
|
||||
|
||||
private bool IsVirtualObjectMode => _animatedObjectMode == AnimatedObjectMode.VirtualObject;
|
||||
private bool IsRealObjectMode => _animatedObjectMode == AnimatedObjectMode.RealObject;
|
||||
@ -637,6 +640,8 @@ namespace NavisworksTransport.Core.Animation
|
||||
/// <returns>是否成功移动</returns>
|
||||
public bool MoveObjectToPathStart(ModelItem animatedObject = null, List<Point3D> pathPoints = null)
|
||||
{
|
||||
_objectStartPlacementMode = ObjectStartPlacementMode.AlignToPathPose;
|
||||
|
||||
// 前置检查:必须有路径
|
||||
if (_route == null)
|
||||
{
|
||||
@ -859,6 +864,97 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveObjectToPathStartPreservingInitialPose(ModelItem animatedObject = null, List<Point3D> pathPoints = null)
|
||||
{
|
||||
_objectStartPlacementMode = ObjectStartPlacementMode.PreserveInitialPose;
|
||||
|
||||
if (_route == null)
|
||||
{
|
||||
LogManager.Error("[平移到起点] 路径为空,无法移动物体到路径起点");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (CurrentControlledObject != null || IsVirtualObjectMode)
|
||||
{
|
||||
RestoreObjectToCADPosition();
|
||||
LogManager.Info($"[平移到起点] 已恢复物体到原始状态, _currentYaw={_currentYaw * 180 / Math.PI:F2}°");
|
||||
}
|
||||
|
||||
if (animatedObject != null)
|
||||
{
|
||||
_animatedObject = animatedObject;
|
||||
bool isVirtualObject =
|
||||
VirtualObjectManager.Instance.IsVirtualObjectActive &&
|
||||
ReferenceEquals(animatedObject, VirtualObjectManager.Instance.CurrentVirtualObject);
|
||||
_animatedObjectMode = isVirtualObject
|
||||
? AnimatedObjectMode.VirtualObject
|
||||
: AnimatedObjectMode.RealObject;
|
||||
ResetRealObjectReferenceRotation();
|
||||
_originalTransform = animatedObject.Transform;
|
||||
_originalCenter = animatedObject.BoundingBox().Center;
|
||||
_trackedPosition = GetTrackedObjectPosition(animatedObject);
|
||||
if (isVirtualObject)
|
||||
{
|
||||
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
||||
_trackedRotation = _originalTransform.Factor().Rotation;
|
||||
_hasTrackedRotation = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SyncTrackedRotationToObjectReference(animatedObject, isVirtualObject: false);
|
||||
}
|
||||
}
|
||||
|
||||
if (pathPoints != null)
|
||||
{
|
||||
_pathPoints = pathPoints;
|
||||
}
|
||||
|
||||
if (_pathPoints == null || _pathPoints.Count < 2)
|
||||
{
|
||||
LogManager.Warning("[平移到起点] 没有可用的路径点");
|
||||
return false;
|
||||
}
|
||||
|
||||
Point3D pathStartPoint = _pathPoints[0];
|
||||
Point3D startPosition = pathStartPoint;
|
||||
if (_route.PathType == PathType.Hoisting)
|
||||
{
|
||||
startPosition = ResolveGroundTrackedCenter(startPosition, GetAnimatedObjectGroundContactHeight());
|
||||
}
|
||||
else if (_route.PathType == PathType.Rail)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
startPosition = ResolveGroundTrackedCenter(startPosition, GetAnimatedObjectGroundContactHeight());
|
||||
}
|
||||
|
||||
UpdateObjectPosition(startPosition);
|
||||
_hasGroundRealObjectBasePose = false;
|
||||
_groundRealObjectStartCompensation = new Vector3D(0, 0, 0);
|
||||
_hasGroundRealObjectStartCompensation = false;
|
||||
|
||||
var startAppliedPoint = GetTrackedObjectPosition(CurrentControlledObject ?? _animatedObject);
|
||||
LogManager.Info(
|
||||
$"[平移到起点] 已保持初始位姿移动到起点: 路径point0=({pathStartPoint.X:F3},{pathStartPoint.Y:F3},{pathStartPoint.Z:F3}), " +
|
||||
$"目标trackedPoint=({startPosition.X:F3},{startPosition.Y:F3},{startPosition.Z:F3}), " +
|
||||
$"实际trackedPoint=({startAppliedPoint.X:F3},{startAppliedPoint.Y:F3},{startAppliedPoint.Z:F3}), 路径类型={_route.PathType.GetDisplayName()}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"保持初始位姿平移到路径起点失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预计算所有动画帧和碰撞信息
|
||||
/// </summary>
|
||||
@ -872,7 +968,20 @@ namespace NavisworksTransport.Core.Animation
|
||||
if (_animatedObject != null && _route != null && _route.Points != null && _route.Points.Count > 0)
|
||||
{
|
||||
var pathPoints = _route.Points.Select(p => p.Position).ToList();
|
||||
MoveObjectToPathStart(_animatedObject, pathPoints);
|
||||
MoveObjectToPathStartUsingCurrentPlacementMode(_animatedObject, pathPoints);
|
||||
if (_route.PathType == PathType.Rail &&
|
||||
_objectStartPlacementMode == ObjectStartPlacementMode.PreserveInitialPose &&
|
||||
_hasTrackedRotation)
|
||||
{
|
||||
_railPreservedPoseRotation = _trackedRotation;
|
||||
_hasRailPreservedPoseRotation = true;
|
||||
LogManager.Info("[预计算] Rail平移模式已锁定起点姿态为整段动画旋转基线");
|
||||
}
|
||||
else
|
||||
{
|
||||
_railPreservedPoseRotation = Rotation3D.Identity;
|
||||
_hasRailPreservedPoseRotation = false;
|
||||
}
|
||||
LogManager.Info("[预计算] 物体已移动到路径起点");
|
||||
}
|
||||
|
||||
@ -1169,11 +1278,18 @@ namespace NavisworksTransport.Core.Animation
|
||||
};
|
||||
|
||||
if (_route.PathType == PathType.Rail &&
|
||||
TryCreateRailPathRotation(
|
||||
previousFramePoint,
|
||||
framePosition,
|
||||
nextFramePoint,
|
||||
out var railRotation))
|
||||
_objectStartPlacementMode == ObjectStartPlacementMode.PreserveInitialPose &&
|
||||
_hasRailPreservedPoseRotation)
|
||||
{
|
||||
frame.Rotation = _railPreservedPoseRotation;
|
||||
frame.HasCustomRotation = true;
|
||||
}
|
||||
else if (_route.PathType == PathType.Rail &&
|
||||
TryCreateRailPathRotation(
|
||||
previousFramePoint,
|
||||
framePosition,
|
||||
nextFramePoint,
|
||||
out var railRotation))
|
||||
{
|
||||
frame.Rotation = railRotation;
|
||||
frame.HasCustomRotation = true;
|
||||
@ -1622,7 +1738,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
if (needsReset)
|
||||
{
|
||||
LogManager.Info($"[动画开始] 物体不在起点,重置到起点: {mismatchSummary}");
|
||||
MoveObjectToPathStart();
|
||||
MoveObjectToPathStartUsingCurrentPlacementMode();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4623,6 +4739,8 @@ namespace NavisworksTransport.Core.Animation
|
||||
/// </summary>
|
||||
public void SetObjectRotationCorrection(LocalEulerRotationCorrection rotationCorrection)
|
||||
{
|
||||
_objectStartPlacementMode = ObjectStartPlacementMode.AlignToPathPose;
|
||||
_hasRailPreservedPoseRotation = false;
|
||||
_objectRotationCorrection = rotationCorrection;
|
||||
|
||||
// 如果动画已创建,更新物体到起点的朝向
|
||||
@ -4658,6 +4776,23 @@ namespace NavisworksTransport.Core.Animation
|
||||
LogManager.Debug($"[角度修正] 直接设置角度修正值: {_objectRotationCorrection}(不触发旋转)");
|
||||
}
|
||||
|
||||
public void SetObjectStartPlacementMode(ObjectStartPlacementMode placementMode)
|
||||
{
|
||||
_objectStartPlacementMode = placementMode;
|
||||
if (placementMode != ObjectStartPlacementMode.PreserveInitialPose)
|
||||
{
|
||||
_hasRailPreservedPoseRotation = false;
|
||||
}
|
||||
LogManager.Debug($"[起点摆放] 当前模式已设置为: {_objectStartPlacementMode}");
|
||||
}
|
||||
|
||||
private bool MoveObjectToPathStartUsingCurrentPlacementMode(ModelItem animatedObject = null, List<Point3D> pathPoints = null)
|
||||
{
|
||||
return _objectStartPlacementMode == ObjectStartPlacementMode.PreserveInitialPose
|
||||
? MoveObjectToPathStartPreservingInitialPose(animatedObject, pathPoints)
|
||||
: MoveObjectToPathStart(animatedObject, pathPoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保留给旧单轴调用方:按当前宿主 up 轴映射成三轴角度修正。
|
||||
/// </summary>
|
||||
|
||||
@ -50,6 +50,7 @@ namespace NavisworksTransport
|
||||
public string pathType { get; set; }
|
||||
public string railMountMode { get; set; }
|
||||
public string railPathDefinitionMode { get; set; }
|
||||
public double railNormalOffset { get; set; }
|
||||
public JsonVector3 railPreferredNormal { get; set; }
|
||||
public double totalLength { get; set; }
|
||||
public JsonObjectLimits objectLimits { get; set; }
|
||||
@ -287,6 +288,7 @@ namespace NavisworksTransport
|
||||
pathType = route.PathType.ToString(),
|
||||
railMountMode = route.RailMountMode.ToString(),
|
||||
railPathDefinitionMode = route.RailPathDefinitionMode.ToString(),
|
||||
railNormalOffset = Math.Round(route.RailNormalOffset, exportSettings?.Precision ?? 3),
|
||||
railPreferredNormal = route.RailPreferredNormal != null ? new
|
||||
{
|
||||
x = Math.Round(route.RailPreferredNormal.X, exportSettings?.Precision ?? 3),
|
||||
@ -542,6 +544,8 @@ namespace NavisworksTransport
|
||||
route.RailPathDefinitionMode = railPathDefinitionMode;
|
||||
}
|
||||
|
||||
route.RailNormalOffset = jsonRoute.railNormalOffset;
|
||||
|
||||
if (jsonRoute.railPreferredNormal != null)
|
||||
{
|
||||
route.RailPreferredNormal = new Point3D(
|
||||
@ -1409,6 +1413,7 @@ namespace NavisworksTransport
|
||||
routeElement.SetAttribute("pathType", route.PathType.ToString());
|
||||
routeElement.SetAttribute("railMountMode", route.RailMountMode.ToString());
|
||||
routeElement.SetAttribute("railPathDefinitionMode", route.RailPathDefinitionMode.ToString());
|
||||
routeElement.SetAttribute("railNormalOffset", route.RailNormalOffset.ToString("F3"));
|
||||
if (route.RailPreferredNormal != null)
|
||||
{
|
||||
routeElement.SetAttribute("railPreferredNormalX", route.RailPreferredNormal.X.ToString("F3"));
|
||||
@ -1557,6 +1562,11 @@ namespace NavisworksTransport
|
||||
route.RailPathDefinitionMode = railPathDefinitionMode;
|
||||
}
|
||||
|
||||
if (double.TryParse(routeNode.Attributes?["railNormalOffset"]?.Value, out var railNormalOffset))
|
||||
{
|
||||
route.RailNormalOffset = railNormalOffset;
|
||||
}
|
||||
|
||||
if (double.TryParse(routeNode.Attributes?["railPreferredNormalX"]?.Value, out var railPreferredNormalX) &&
|
||||
double.TryParse(routeNode.Attributes?["railPreferredNormalY"]?.Value, out var railPreferredNormalY) &&
|
||||
double.TryParse(routeNode.Attributes?["railPreferredNormalZ"]?.Value, out var railPreferredNormalZ))
|
||||
|
||||
@ -101,6 +101,7 @@ namespace NavisworksTransport
|
||||
LiftHeight REAL,
|
||||
RailMountMode INTEGER,
|
||||
RailPathDefinitionMode INTEGER,
|
||||
RailNormalOffset REAL,
|
||||
RailPreferredNormalX REAL,
|
||||
RailPreferredNormalY REAL,
|
||||
RailPreferredNormalZ REAL,
|
||||
@ -466,8 +467,8 @@ namespace NavisworksTransport
|
||||
// 路径长度由 PathRoute.TotalLength 计算属性实时从 Edges/Points 计算
|
||||
var sql = @"
|
||||
INSERT OR REPLACE INTO PathRoutes
|
||||
(Id, Name, EstimatedTime, TurnRadius, IsCurved, MaxObjectLength, MaxObjectWidth, MaxObjectHeight, SafetyMargin, GridSize, PathType, LiftHeight, RailMountMode, RailPathDefinitionMode, RailPreferredNormalX, RailPreferredNormalY, RailPreferredNormalZ, CreatedTime, LastModified)
|
||||
VALUES (@id, @name, @time, @turnRadius, @isCurved, @maxLength, @maxWidth, @maxHeight, @safetyMargin, @gridSize, @pathType, @liftHeightMeters, @railMountMode, @railPathDefinitionMode, @railPreferredNormalX, @railPreferredNormalY, @railPreferredNormalZ, @created, @modified)
|
||||
(Id, Name, EstimatedTime, TurnRadius, IsCurved, MaxObjectLength, MaxObjectWidth, MaxObjectHeight, SafetyMargin, GridSize, PathType, LiftHeight, RailMountMode, RailPathDefinitionMode, RailNormalOffset, RailPreferredNormalX, RailPreferredNormalY, RailPreferredNormalZ, CreatedTime, LastModified)
|
||||
VALUES (@id, @name, @time, @turnRadius, @isCurved, @maxLength, @maxWidth, @maxHeight, @safetyMargin, @gridSize, @pathType, @liftHeightMeters, @railMountMode, @railPathDefinitionMode, @railNormalOffset, @railPreferredNormalX, @railPreferredNormalY, @railPreferredNormalZ, @created, @modified)
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
@ -486,6 +487,7 @@ namespace NavisworksTransport
|
||||
cmd.Parameters.AddWithValue("@liftHeightMeters", route.LiftHeight);
|
||||
cmd.Parameters.AddWithValue("@railMountMode", (int)route.RailMountMode);
|
||||
cmd.Parameters.AddWithValue("@railPathDefinitionMode", (int)route.RailPathDefinitionMode);
|
||||
cmd.Parameters.AddWithValue("@railNormalOffset", route.RailNormalOffset);
|
||||
cmd.Parameters.AddWithValue("@railPreferredNormalX", route.RailPreferredNormal != null ? (object)route.RailPreferredNormal.X : DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@railPreferredNormalY", route.RailPreferredNormal != null ? (object)route.RailPreferredNormal.Y : DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@railPreferredNormalZ", route.RailPreferredNormal != null ? (object)route.RailPreferredNormal.Z : DBNull.Value);
|
||||
@ -1546,6 +1548,7 @@ namespace NavisworksTransport
|
||||
LiftHeight = Convert.ToDouble(reader["LiftHeight"]),
|
||||
RailMountMode = (RailMountMode)Convert.ToInt32(reader["RailMountMode"]),
|
||||
RailPathDefinitionMode = (RailPathDefinitionMode)Convert.ToInt32(reader["RailPathDefinitionMode"]),
|
||||
RailNormalOffset = reader["RailNormalOffset"] != DBNull.Value ? Convert.ToDouble(reader["RailNormalOffset"]) : 0.0,
|
||||
CreatedTime = Convert.ToDateTime(reader["CreatedTime"]),
|
||||
LastModified = Convert.ToDateTime(reader["LastModified"])
|
||||
};
|
||||
@ -2737,8 +2740,8 @@ namespace NavisworksTransport
|
||||
cmd.CommandText = @"
|
||||
SELECT Id, Name, CreatedTime, LastModified,
|
||||
TurnRadius, IsCurved, MaxObjectLength, MaxObjectWidth, MaxObjectHeight,
|
||||
SafetyMargin, GridSize, PathType, LiftHeight, RailMountMode, RailPathDefinitionMode,
|
||||
RailPreferredNormalX, RailPreferredNormalY, RailPreferredNormalZ
|
||||
SafetyMargin, GridSize, PathType, LiftHeight, RailMountMode, RailPathDefinitionMode,
|
||||
RailNormalOffset, RailPreferredNormalX, RailPreferredNormalY, RailPreferredNormalZ
|
||||
FROM PathRoutes
|
||||
WHERE Id = @Id";
|
||||
|
||||
@ -2764,7 +2767,8 @@ namespace NavisworksTransport
|
||||
PathType = (PathType)Convert.ToInt32(reader["PathType"]),
|
||||
LiftHeight = Convert.ToDouble(reader["LiftHeight"]),
|
||||
RailMountMode = (RailMountMode)Convert.ToInt32(reader["RailMountMode"]),
|
||||
RailPathDefinitionMode = (RailPathDefinitionMode)Convert.ToInt32(reader["RailPathDefinitionMode"])
|
||||
RailPathDefinitionMode = (RailPathDefinitionMode)Convert.ToInt32(reader["RailPathDefinitionMode"]),
|
||||
RailNormalOffset = reader["RailNormalOffset"] != DBNull.Value ? Convert.ToDouble(reader["RailNormalOffset"]) : 0.0
|
||||
};
|
||||
|
||||
if (reader["RailPreferredNormalX"] != DBNull.Value &&
|
||||
@ -2812,7 +2816,8 @@ namespace NavisworksTransport
|
||||
{
|
||||
["railmountmode"] = "ALTER TABLE PathRoutes ADD COLUMN RailMountMode INTEGER DEFAULT 0",
|
||||
["railpathdefinitionmode"] = "ALTER TABLE PathRoutes ADD COLUMN RailPathDefinitionMode INTEGER DEFAULT 0",
|
||||
["railpreferrednormalx"] = "ALTER TABLE PathRoutes ADD COLUMN RailPreferredNormalX REAL",
|
||||
["railnormaloffset"] = "ALTER TABLE PathRoutes ADD COLUMN RailNormalOffset REAL DEFAULT 0",
|
||||
["railpreferrednormalx"] = "ALTER TABLE PathRoutes ADD COLUMN RailPreferredNormalX REAL",
|
||||
["railpreferrednormaly"] = "ALTER TABLE PathRoutes ADD COLUMN RailPreferredNormalY REAL",
|
||||
["railpreferrednormalz"] = "ALTER TABLE PathRoutes ADD COLUMN RailPreferredNormalZ REAL"
|
||||
};
|
||||
|
||||
@ -1271,6 +1271,7 @@ namespace NavisworksTransport
|
||||
route.LiftHeight = loadedRoute.LiftHeight;
|
||||
route.RailMountMode = loadedRoute.RailMountMode;
|
||||
route.RailPathDefinitionMode = loadedRoute.RailPathDefinitionMode;
|
||||
route.RailNormalOffset = loadedRoute.RailNormalOffset;
|
||||
route.RailPreferredNormal = loadedRoute.RailPreferredNormal != null
|
||||
? new Point3D(
|
||||
loadedRoute.RailPreferredNormal.X,
|
||||
|
||||
@ -743,6 +743,12 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public Point3D RailPreferredNormal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rail 安装法向偏移(模型单位)。
|
||||
/// 沿 Rail 最终法向对安装参考点施加额外偏移,用于快速微调路径。
|
||||
/// </summary>
|
||||
public double RailNormalOffset { get; set; }
|
||||
|
||||
// 数据库分析相关属性
|
||||
/// <summary>
|
||||
/// 碰撞数量(从数据库加载)
|
||||
@ -784,6 +790,7 @@ namespace NavisworksTransport
|
||||
RailMountMode = RailMountMode.UnderRail;
|
||||
RailPathDefinitionMode = RailPathDefinitionMode.LegacySuspensionPoint;
|
||||
RailPreferredNormal = null;
|
||||
RailNormalOffset = 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -807,6 +814,7 @@ namespace NavisworksTransport
|
||||
RailMountMode = RailMountMode.UnderRail;
|
||||
RailPathDefinitionMode = RailPathDefinitionMode.LegacySuspensionPoint;
|
||||
RailPreferredNormal = null;
|
||||
RailNormalOffset = 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1042,6 +1050,7 @@ namespace NavisworksTransport
|
||||
SafetyMargin = SafetyMargin,
|
||||
RailMountMode = RailMountMode,
|
||||
RailPathDefinitionMode = RailPathDefinitionMode,
|
||||
RailNormalOffset = RailNormalOffset,
|
||||
RailPreferredNormal = RailPreferredNormal != null
|
||||
? new Point3D(RailPreferredNormal.X, RailPreferredNormal.Y, RailPreferredNormal.Z)
|
||||
: null
|
||||
|
||||
@ -2196,7 +2196,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
var dialog = new Views.EditRotationWindow(_objectRotationCorrection);
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
ObjectRotationCorrection = dialog.RotationCorrection;
|
||||
var placementRequest = dialog.AdjustmentRequest;
|
||||
if (placementRequest.PreserveInitialPose)
|
||||
{
|
||||
ApplyTranslationOnlyObjectPlacement();
|
||||
return;
|
||||
}
|
||||
|
||||
_pathAnimationManager?.SetObjectStartPlacementMode(ObjectStartPlacementMode.AlignToPathPose);
|
||||
ObjectRotationCorrection = placementRequest.RotationCorrection;
|
||||
LogManager.Info($"物体角度修正已更新: {_objectRotationCorrection}");
|
||||
UpdateMainStatus($"物体角度修正: {_objectRotationCorrection}");
|
||||
|
||||
@ -2214,6 +2222,40 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTranslationOnlyObjectPlacement()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_pathAnimationManager == null || !HasSelectedAnimatedObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_objectRotationCorrection = LocalEulerRotationCorrection.Zero;
|
||||
_pathAnimationManager.SetObjectRotationCorrectionDirect(LocalEulerRotationCorrection.Zero);
|
||||
_pathAnimationManager.SetObjectStartPlacementMode(ObjectStartPlacementMode.PreserveInitialPose);
|
||||
OnPropertyChanged(nameof(ObjectRotationCorrection));
|
||||
|
||||
if (_pathAnimationManager.MoveObjectToPathStartPreservingInitialPose())
|
||||
{
|
||||
LogManager.Info("[角度修正] 已按平移模式将物体移动到路径起点,保持初始位姿");
|
||||
UpdateMainStatus("物体已平移到路径起点并保持初始位姿");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[角度修正] 平移模式未能将物体移动到路径起点");
|
||||
UpdateMainStatus("平移模式执行失败");
|
||||
}
|
||||
|
||||
UpdatePassageSpaceVisualization();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"平移到路径起点失败: {ex.Message}");
|
||||
UpdateMainStatus($"平移到路径起点失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新物体旋转(应用角度修正)
|
||||
/// </summary>
|
||||
|
||||
@ -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 RailNormalOffsetNudgeStepInMeters = 0.1;
|
||||
private const double DefaultAssemblySphereCenterX = 0.0;
|
||||
private const double DefaultAssemblySphereCenterY = 0.0;
|
||||
private const double DefaultAssemblySphereCenterZ = 0.0;
|
||||
@ -267,6 +268,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
OnPropertyChanged(nameof(CanUsePathLines));
|
||||
OnPropertyChanged(nameof(IsRailRouteSelected));
|
||||
OnPropertyChanged(nameof(SelectedRailMountMode));
|
||||
OnPropertyChanged(nameof(SelectedRailNormalOffsetInMeters));
|
||||
if (!CanUsePathLines && ShowPathLines)
|
||||
{
|
||||
// 吊装和空轨路径不能使用路径线,自动关闭
|
||||
@ -348,6 +350,38 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public double SelectedRailNormalOffsetInMeters
|
||||
{
|
||||
get
|
||||
{
|
||||
var coreRoute = GetSelectedCoreRoute();
|
||||
if (coreRoute == null || coreRoute.PathType != PathType.Rail)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return UnitsConverter.ConvertToMeters(coreRoute.RailNormalOffset);
|
||||
}
|
||||
set
|
||||
{
|
||||
var coreRoute = GetSelectedCoreRoute();
|
||||
if (coreRoute == null || coreRoute.PathType != PathType.Rail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double offsetInModelUnits = UnitsConverter.ConvertFromMeters(value);
|
||||
if (Math.Abs(coreRoute.RailNormalOffset - offsetInModelUnits) < 1e-6)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
coreRoute.RailNormalOffset = offsetInModelUnits;
|
||||
ApplyRailRouteConfigurationChange(coreRoute, $"安装法向偏移已更新为 {value:F3} 米");
|
||||
OnPropertyChanged(nameof(SelectedRailNormalOffsetInMeters));
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyTerminalObjectName
|
||||
{
|
||||
get => _assemblyTerminalObjectName;
|
||||
@ -992,6 +1026,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public ICommand SelectAssemblyInstallationPointCommand { get; private set; }
|
||||
public ICommand ClearAssemblyReferenceRodCommand { get; private set; }
|
||||
public ICommand AnalyzeAssemblyTerminalFaceCommand { get; private set; }
|
||||
public ICommand DecreaseSelectedRailNormalOffsetCommand { get; private set; }
|
||||
public ICommand IncreaseSelectedRailNormalOffsetCommand { get; private set; }
|
||||
|
||||
// 多层吊装命令
|
||||
public ICommand SelectMultiLevelStartPointCommand { get; private set; }
|
||||
@ -1196,6 +1232,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
LogManager.Info($"[Rail构型] {coreRoute.Name}: {logMessage}");
|
||||
}
|
||||
|
||||
private void AdjustSelectedRailNormalOffset(double deltaInMeters)
|
||||
{
|
||||
var coreRoute = GetSelectedCoreRoute();
|
||||
if (coreRoute == null || coreRoute.PathType != PathType.Rail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double currentOffsetInMeters = UnitsConverter.ConvertToMeters(coreRoute.RailNormalOffset);
|
||||
double nextOffsetInMeters = Math.Round(currentOffsetInMeters + deltaInMeters, 3);
|
||||
SelectedRailNormalOffsetInMeters = nextOffsetInMeters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从配置文件加载参数
|
||||
/// </summary>
|
||||
@ -1336,6 +1385,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
SelectAssemblyInstallationPointCommand = new RelayCommand(async () => await ExecuteSelectAssemblyInstallationPointAsync(), () => CanSelectAssemblyInstallationPoint);
|
||||
ClearAssemblyReferenceRodCommand = new RelayCommand(() => ExecuteClearAssemblyReferenceRod());
|
||||
AnalyzeAssemblyTerminalFaceCommand = new RelayCommand(async () => await ExecuteAnalyzeAssemblyTerminalFaceAsync(), () => CanAnalyzeAssemblyTerminalFace);
|
||||
DecreaseSelectedRailNormalOffsetCommand = new RelayCommand(() => AdjustSelectedRailNormalOffset(-RailNormalOffsetNudgeStepInMeters));
|
||||
IncreaseSelectedRailNormalOffsetCommand = new RelayCommand(() => AdjustSelectedRailNormalOffset(RailNormalOffsetNudgeStepInMeters));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -1704,7 +1755,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
Description = $"直线装配路径 - {AssemblyTerminalObjectName}",
|
||||
PathType = PathType.Rail,
|
||||
RailMountMode = AssemblyMountMode,
|
||||
RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine
|
||||
RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine,
|
||||
RailNormalOffset = UnitsConverter.ConvertFromMeters(AssemblyAnchorVerticalOffsetInMeters)
|
||||
};
|
||||
|
||||
if (_hasAssemblyInstallationReference)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<Window x:Class="NavisworksTransport.UI.WPF.Views.EditRotationWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="调整物体角度" Height="360" Width="430"
|
||||
Title="调整物体角度" Height="360" Width="400"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
@ -105,21 +105,21 @@
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="70"
|
||||
Height="28"
|
||||
Margin="0,0,8,0"/>
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="90°"
|
||||
Click="OnQuickAngleClick"
|
||||
Tag="90"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="70"
|
||||
Height="28"
|
||||
Margin="0,0,8,0"/>
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="180°"
|
||||
Click="OnQuickAngleClick"
|
||||
Tag="180"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="70"
|
||||
Height="28"
|
||||
Margin="0,0,8,0"/>
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="270°"
|
||||
Click="OnQuickAngleClick"
|
||||
Tag="270"
|
||||
@ -133,22 +133,28 @@
|
||||
<!-- 按钮栏 -->
|
||||
<Border Grid.Row="2" Background="#FFF8FBFF" BorderBrush="#FFD4E7FF" BorderThickness="0,1,0,0" Padding="20,12">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="恢复初始值"
|
||||
<Button Content="初始值"
|
||||
Click="OnResetClick"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="90"
|
||||
Width="70"
|
||||
Height="32"
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="平移"
|
||||
Click="OnTranslateClick"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="70"
|
||||
Height="32"
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="确认"
|
||||
Click="OnConfirmClick"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Width="90"
|
||||
Width="70"
|
||||
Height="32"
|
||||
Margin="0,0,10,0"/>
|
||||
<Button Content="取消"
|
||||
Click="OnCancelClick"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Width="90"
|
||||
Width="70"
|
||||
Height="32"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@ -20,6 +20,7 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
private double _rotationYDegrees;
|
||||
private double _rotationZDegrees;
|
||||
private RotationAxisTarget _activeAxisTarget = RotationAxisTarget.Z;
|
||||
private ObjectStartPlacementRequest _adjustmentRequest;
|
||||
|
||||
public double RotationXDegrees
|
||||
{
|
||||
@ -66,6 +67,8 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
public LocalEulerRotationCorrection RotationCorrection =>
|
||||
new LocalEulerRotationCorrection(RotationXDegrees, RotationYDegrees, RotationZDegrees);
|
||||
|
||||
public ObjectStartPlacementRequest AdjustmentRequest => _adjustmentRequest;
|
||||
|
||||
public EditRotationWindow(LocalEulerRotationCorrection currentRotation)
|
||||
{
|
||||
try
|
||||
@ -74,6 +77,7 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
RotationXDegrees = currentRotation.XDegrees;
|
||||
RotationYDegrees = currentRotation.YDegrees;
|
||||
RotationZDegrees = currentRotation.ZDegrees;
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(currentRotation);
|
||||
DataContext = this;
|
||||
Loaded += (sender, args) => ZAxisTextBox.Focus();
|
||||
}
|
||||
@ -141,6 +145,14 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
|
||||
private void OnConfirmClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(RotationCorrection);
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnTranslateClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.TranslationOnly;
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
@ -267,116 +267,6 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,10,0,0" Padding="10">
|
||||
<StackPanel>
|
||||
<Label Content="终端安装仿真" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
<Grid Margin="0,5,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="安装方式:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
Margin="6,0,8,0"
|
||||
ItemsSource="{Binding RailMountModeOptions}"
|
||||
SelectedValue="{Binding AssemblyMountMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="DisplayName"
|
||||
ToolTip="选择直线装配路径使用轨上安装还是轨下安装"/>
|
||||
<Label Grid.Column="2"
|
||||
Content="垂直偏移:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="3"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center"
|
||||
Margin="6,0,0,0">
|
||||
<TextBox Text="{Binding AssemblyAnchorVerticalOffsetInMeters, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="米"
|
||||
Style="{StaticResource UnitLabelStyle}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Margin="0,6,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="球心:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center"
|
||||
Margin="6,0,8,0">
|
||||
<TextBox Text="{Binding AssemblySphereCenterX, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="X" Style="{StaticResource UnitLabelStyle}"/>
|
||||
<TextBox Text="{Binding AssemblySphereCenterY, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="Y" Style="{StaticResource UnitLabelStyle}"/>
|
||||
<TextBox Text="{Binding AssemblySphereCenterZ, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="Z" Style="{StaticResource UnitLabelStyle}"/>
|
||||
</StackPanel>
|
||||
<Label Grid.Column="2"
|
||||
Content="终点箱体:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="3"
|
||||
Margin="6,0,0,0"
|
||||
Text="{Binding AssemblyTerminalObjectName}"
|
||||
Style="{StaticResource ReadOnlyTextBoxStyle}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,6,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="装配起点:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="1"
|
||||
Margin="6,0,0,0"
|
||||
Text="{Binding AssemblyStartPointText}"
|
||||
Style="{StaticResource ReadOnlyTextBoxStyle}"/>
|
||||
</Grid>
|
||||
<WrapPanel Margin="0,8,0,0">
|
||||
<Button Content="捕获箱体"
|
||||
Command="{Binding CaptureAssemblyTerminalObjectCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="找端面"
|
||||
Command="{Binding AnalyzeAssemblyTerminalFaceCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
IsEnabled="{Binding CanAnalyzeAssemblyTerminalFace}"/>
|
||||
<Button Content="{Binding AssemblyInstallationPointButtonText}"
|
||||
Command="{Binding SelectAssemblyInstallationPointCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
IsEnabled="{Binding CanSelectAssemblyInstallationPoint}"/>
|
||||
<Button Content="生成辅助线"
|
||||
Command="{Binding GenerateAssemblyReferenceRodCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
IsEnabled="{Binding CanGenerateAssemblyReferenceRod}"/>
|
||||
<Button Content="取起点"
|
||||
Command="{Binding SelectAssemblyStartPointCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
IsEnabled="{Binding CanSelectAssemblyStartPoint}"/>
|
||||
<Button Content="隐藏辅助线"
|
||||
Command="{Binding ClearAssemblyReferenceRodCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域3: 路径编辑 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,10,0,0" Padding="10">
|
||||
<StackPanel>
|
||||
@ -480,8 +370,224 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域4: 路径文件管理 -->
|
||||
|
||||
<!-- 区域4: Rail 创建与参数 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,10,0,0" Padding="10">
|
||||
<StackPanel>
|
||||
<Label Content="终端安装 / Rail" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
<TextBlock Text="创建直线装配 Rail 路径,并在选中 Rail 路径后调整其安装方式。"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,2,0,0"/>
|
||||
|
||||
<Expander Header="创建 Rail 路径" IsExpanded="False" Margin="0,8,0,0">
|
||||
<StackPanel Margin="10,6,0,0">
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="安装方式:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
Margin="6,0,10,0"
|
||||
ItemsSource="{Binding RailMountModeOptions}"
|
||||
SelectedValue="{Binding AssemblyMountMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="DisplayName"
|
||||
ToolTip="选择直线装配路径使用轨上安装还是轨下安装"/>
|
||||
<Label Grid.Column="2"
|
||||
Content="安装法向偏移:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="3"
|
||||
Orientation="Horizontal"
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<TextBox Width="72"
|
||||
Text="{Binding AssemblyAnchorVerticalOffsetInMeters, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="米" Style="{StaticResource UnitLabelStyle}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="终点箱体:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="1"
|
||||
Margin="6,0,10,0"
|
||||
Text="{Binding AssemblyTerminalObjectName}"
|
||||
Style="{StaticResource ReadOnlyTextBoxStyle}"/>
|
||||
<Label Grid.Column="2"
|
||||
Content="装配起点:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="3"
|
||||
Margin="6,0,0,0"
|
||||
Text="{Binding AssemblyStartPointText}"
|
||||
Style="{StaticResource ReadOnlyTextBoxStyle}"/>
|
||||
</Grid>
|
||||
|
||||
<Expander Header="更多创建参数" IsExpanded="False">
|
||||
<StackPanel Margin="10,6,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Content="球心:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<TextBox Width="56"
|
||||
Text="{Binding AssemblySphereCenterX, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="X" Style="{StaticResource UnitLabelStyle}"/>
|
||||
<TextBox Width="56"
|
||||
Text="{Binding AssemblySphereCenterY, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="Y" Style="{StaticResource UnitLabelStyle}"/>
|
||||
<TextBox Width="56"
|
||||
Text="{Binding AssemblySphereCenterZ, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Label Content="Z" Style="{StaticResource UnitLabelStyle}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
<WrapPanel Margin="0,8,0,0">
|
||||
<Button Content="捕获箱体"
|
||||
Command="{Binding CaptureAssemblyTerminalObjectCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="找端面"
|
||||
Command="{Binding AnalyzeAssemblyTerminalFaceCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
IsEnabled="{Binding CanAnalyzeAssemblyTerminalFace}"/>
|
||||
<Button Content="{Binding AssemblyInstallationPointButtonText}"
|
||||
Command="{Binding SelectAssemblyInstallationPointCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
IsEnabled="{Binding CanSelectAssemblyInstallationPoint}"/>
|
||||
<Button Content="生成辅助线"
|
||||
Command="{Binding GenerateAssemblyReferenceRodCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
IsEnabled="{Binding CanGenerateAssemblyReferenceRod}"/>
|
||||
<Button Content="取起点"
|
||||
Command="{Binding SelectAssemblyStartPointCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
IsEnabled="{Binding CanSelectAssemblyStartPoint}"/>
|
||||
<Button Content="隐藏辅助线"
|
||||
Command="{Binding ClearAssemblyReferenceRodCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
<Expander Header="Rail 参数" IsExpanded="True" Margin="0,8,0,0">
|
||||
<StackPanel Margin="10,6,0,0">
|
||||
<StackPanel Visibility="{Binding IsRailRouteSelected, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverse}">
|
||||
<TextBlock Text="选择一条 Rail 路径后,可在这里修改安装方式。"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Foreground="#FF666666"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Visibility="{Binding IsRailRouteSelected, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Content="当前路径:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Margin="6,0,10,0"
|
||||
Text="{Binding SelectedPathRoute.Name}"
|
||||
Style="{StaticResource ReadOnlyTextBoxStyle}"/>
|
||||
<Label Grid.Column="2"
|
||||
Grid.Row="0"
|
||||
Content="安装方式:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<ComboBox Grid.Column="3"
|
||||
Grid.Row="0"
|
||||
Margin="6,0,0,0"
|
||||
ItemsSource="{Binding RailMountModeOptions}"
|
||||
SelectedValue="{Binding SelectedRailMountMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="DisplayName"/>
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Margin="0,6,0,0"
|
||||
Content="安装法向偏移:"
|
||||
Style="{StaticResource ParameterLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
Orientation="Horizontal"
|
||||
Margin="6,6,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<Button Content="-"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Padding="0"
|
||||
Command="{Binding DecreaseSelectedRailNormalOffsetCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<TextBox Width="84"
|
||||
Margin="6,0"
|
||||
HorizontalContentAlignment="Center"
|
||||
Text="{Binding SelectedRailNormalOffsetInMeters, Mode=TwoWay, UpdateSourceTrigger=LostFocus, StringFormat=0.0###}"
|
||||
Style="{StaticResource ParameterInputStyle}"/>
|
||||
<Button Content="+"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Padding="0"
|
||||
Command="{Binding IncreaseSelectedRailNormalOffsetCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Label Content="米"
|
||||
Style="{StaticResource UnitLabelStyle}"
|
||||
Margin="6,0,0,0"/>
|
||||
<TextBlock Text="用于快速沿当前 Rail 法向微调整条路径"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Foreground="#FF666666"
|
||||
VerticalAlignment="Center"
|
||||
Margin="10,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域5: 路径文件管理 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,10,0,0" Padding="10">
|
||||
<StackPanel>
|
||||
<Label Content="路径文件管理" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
@ -508,7 +614,7 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域5: 可视化设置 -->
|
||||
<!-- 区域6: 可视化设置 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,10,0,0" Padding="10">
|
||||
<StackPanel>
|
||||
<Label Content="可视化设置" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
@ -15,9 +15,10 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
// 路径点本身已经是安装参考点(终点锚点)语义。
|
||||
// 动画跟踪中心只需要相对安装参考点沿轨道法向偏移半个高度,
|
||||
// 不能叠加任何“参考线 -> 锚点”旧语义偏移,否则会把终点/逐帧参考点重复平移。
|
||||
return PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
double halfHeightOffset = PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
? -objectHeight / 2.0
|
||||
: objectHeight / 2.0;
|
||||
return halfHeightOffset + route.RailNormalOffset;
|
||||
}
|
||||
|
||||
public static Vector3 ResolveTrackedCenter(
|
||||
|
||||
59
src/Utils/CoordinateSystem/ObjectStartPlacementRequest.cs
Normal file
59
src/Utils/CoordinateSystem/ObjectStartPlacementRequest.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
public enum ObjectStartPlacementMode
|
||||
{
|
||||
AlignToPathPose = 0,
|
||||
PreserveInitialPose = 1
|
||||
}
|
||||
|
||||
public struct ObjectStartPlacementRequest : IEquatable<ObjectStartPlacementRequest>
|
||||
{
|
||||
public static readonly ObjectStartPlacementRequest TranslationOnly =
|
||||
new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose);
|
||||
|
||||
public ObjectStartPlacementRequest(
|
||||
LocalEulerRotationCorrection rotationCorrection,
|
||||
ObjectStartPlacementMode placementMode)
|
||||
{
|
||||
RotationCorrection = rotationCorrection;
|
||||
PlacementMode = placementMode;
|
||||
}
|
||||
|
||||
public LocalEulerRotationCorrection RotationCorrection { get; }
|
||||
|
||||
public ObjectStartPlacementMode PlacementMode { get; }
|
||||
|
||||
public bool PreserveInitialPose => PlacementMode == ObjectStartPlacementMode.PreserveInitialPose;
|
||||
|
||||
public static ObjectStartPlacementRequest CreateRotationCorrection(LocalEulerRotationCorrection rotationCorrection)
|
||||
{
|
||||
return new ObjectStartPlacementRequest(rotationCorrection, ObjectStartPlacementMode.AlignToPathPose);
|
||||
}
|
||||
|
||||
public bool Equals(ObjectStartPlacementRequest other)
|
||||
{
|
||||
return RotationCorrection.Equals(other.RotationCorrection) &&
|
||||
PlacementMode == other.PlacementMode;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ObjectStartPlacementRequest other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (RotationCorrection.GetHashCode() * 397) ^ (int)PlacementMode;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"PlacementMode={PlacementMode}, Rotation={RotationCorrection}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -528,16 +528,18 @@ namespace NavisworksTransport.Utils
|
||||
|
||||
private static double GetBottomOffsetMagnitude(PathRoute route, double objectHeight)
|
||||
{
|
||||
return PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
double baseOffset = PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
? -objectHeight
|
||||
: 0.0;
|
||||
return baseOffset + route.RailNormalOffset;
|
||||
}
|
||||
|
||||
private static double GetObjectSpaceCenterOffsetMagnitude(PathRoute route, double objectSpaceHeight)
|
||||
{
|
||||
return PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
double baseOffset = PathRoute.IsTopPayloadAnchorForMountMode(route.RailMountMode)
|
||||
? -objectSpaceHeight / 2.0
|
||||
: objectSpaceHeight / 2.0;
|
||||
return baseOffset + route.RailNormalOffset;
|
||||
}
|
||||
|
||||
private static Vector3D ResolveRailNormal(Point3D previousPoint, Point3D currentPoint, Point3D nextPoint)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user