add ground object lift adjustment
This commit is contained in:
parent
6020bfa979
commit
da5f8a1ae1
@ -64,6 +64,8 @@
|
||||
<Compile Include="UnitTests\CoordinateSystem\ObjectStartPlacementRequestTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalRailOffsetResolverTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\CanonicalTrackedPositionResolverTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\GroundPathObjectLiftOffsetTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\GroundPassageSpaceOffsetTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\FragmentRepresentativePoseHelperTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\HoistingCoordinateHelperTests.cs" />
|
||||
<Compile Include="UnitTests\CoordinateSystem\HoistingRealObjectPoseHelperTests.cs" />
|
||||
|
||||
17
UnitTests/CoordinateSystem/GroundPassageSpaceOffsetTests.cs
Normal file
17
UnitTests/CoordinateSystem/GroundPassageSpaceOffsetTests.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NavisworksTransport.Core;
|
||||
|
||||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
{
|
||||
[TestClass]
|
||||
public class GroundPassageSpaceOffsetTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void GroundPassageSpaceVerticalOffset_ShouldStayAtHalfHeight_WhenHeightAlreadyIncludesLift()
|
||||
{
|
||||
double verticalOffset = PathPointRenderPlugin.ResolveGroundPathObjectSpaceVerticalOffset(5.7);
|
||||
|
||||
Assert.AreEqual(2.85, verticalOffset, 1e-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NavisworksTransport.Core.Animation;
|
||||
using NavisworksTransport.Utils.CoordinateSystem;
|
||||
using System.Numerics;
|
||||
|
||||
namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
{
|
||||
[TestClass]
|
||||
public class GroundPathObjectLiftOffsetTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void YUp_GroundPathLift_ShouldOffsetAlongHostY()
|
||||
{
|
||||
Vector3 offset = PathAnimationManager.ResolveGroundPathObjectLiftOffsetVector(1.25, CoordinateSystemType.YUp);
|
||||
|
||||
AssertVector(offset, 0.0, 1.25, 0.0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ZUp_GroundPathLift_ShouldOffsetAlongHostZ()
|
||||
{
|
||||
Vector3 offset = PathAnimationManager.ResolveGroundPathObjectLiftOffsetVector(1.25, CoordinateSystemType.ZUp);
|
||||
|
||||
AssertVector(offset, 0.0, 0.0, 1.25);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GroundPathLift_ShouldReturnZero_WhenLiftIsNotPositive()
|
||||
{
|
||||
Vector3 offset = PathAnimationManager.ResolveGroundPathObjectLiftOffsetVector(0.0, CoordinateSystemType.ZUp);
|
||||
|
||||
AssertVector(offset, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
private static void AssertVector(Vector3 actual, double x, double y, double z, double tolerance = 1e-6)
|
||||
{
|
||||
Assert.AreEqual(x, actual.X, tolerance);
|
||||
Assert.AreEqual(y, actual.Y, tolerance);
|
||||
Assert.AreEqual(z, actual.Z, tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
Assert.AreEqual(ObjectStartPlacementMode.PreserveInitialPose, request.PlacementMode);
|
||||
Assert.IsTrue(request.PreserveInitialPose);
|
||||
Assert.AreEqual(LocalEulerRotationCorrection.Zero, request.RotationCorrection);
|
||||
Assert.AreEqual(0.0, request.VerticalLiftInMeters, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -21,11 +22,23 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
{
|
||||
var correction = new LocalEulerRotationCorrection(15.0, 30.0, 45.0);
|
||||
|
||||
var request = ObjectStartPlacementRequest.CreateRotationCorrection(correction);
|
||||
var request = ObjectStartPlacementRequest.CreateRotationCorrection(correction, 0.35);
|
||||
|
||||
Assert.AreEqual(ObjectStartPlacementMode.AlignToPathPose, request.PlacementMode);
|
||||
Assert.IsFalse(request.PreserveInitialPose);
|
||||
Assert.AreEqual(correction, request.RotationCorrection);
|
||||
Assert.AreEqual(0.35, request.VerticalLiftInMeters, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TranslationOnlyRequest_ShouldKeepVerticalLift()
|
||||
{
|
||||
var request = ObjectStartPlacementRequest.CreateTranslationOnly(0.28);
|
||||
|
||||
Assert.AreEqual(ObjectStartPlacementMode.PreserveInitialPose, request.PlacementMode);
|
||||
Assert.IsTrue(request.PreserveInitialPose);
|
||||
Assert.AreEqual(LocalEulerRotationCorrection.Zero, request.RotationCorrection);
|
||||
Assert.AreEqual(0.28, request.VerticalLiftInMeters, 1e-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,6 +133,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
|
||||
// === 角度修正 ===
|
||||
private LocalEulerRotationCorrection _objectRotationCorrection = LocalEulerRotationCorrection.Zero; // 物体绕宿主 X/Y/Z 轴的角度修正
|
||||
private double _groundPathObjectLiftHeight; // 地面路径物体额外提升高度(模型单位)
|
||||
|
||||
// === 碰撞排除列表缓存管理(从LogisticsAnimationManager迁移)===
|
||||
private ModelItem _currentCachedAnimationObject;
|
||||
@ -767,6 +768,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
{
|
||||
// 地面路径:路径点在接触面上,动画跟踪点统一使用几何中心
|
||||
startPosition = ResolveGroundTrackedCenter(startPosition, GetAnimatedObjectGroundContactHeight());
|
||||
startPosition = ApplyGroundPathObjectLiftOffset(startPosition);
|
||||
LogManager.Debug($"[移动到起点] 地面路径中心点=({startPosition.X:F2},{startPosition.Y:F2},{startPosition.Z:F2})");
|
||||
}
|
||||
|
||||
@ -970,6 +972,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
else
|
||||
{
|
||||
startPosition = ResolveGroundTrackedCenter(startPosition, GetAnimatedObjectGroundContactHeight());
|
||||
startPosition = ApplyGroundPathObjectLiftOffset(startPosition);
|
||||
}
|
||||
|
||||
UpdateObjectPosition(startPosition);
|
||||
@ -1293,10 +1296,13 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
|
||||
framePosition = ResolveGroundTrackedCenter(framePosition, GetAnimatedObjectGroundContactHeight());
|
||||
framePosition = ApplyGroundPathObjectLiftOffset(framePosition);
|
||||
|
||||
yawRadians = ComputeYawOnPath(i, allSampledPoints, edgeIndex, edgeProgress);
|
||||
previousFramePoint = ResolveGroundTrackedCenter(sampledPreviousPoint, GetAnimatedObjectGroundContactHeight());
|
||||
nextFramePoint = ResolveGroundTrackedCenter(sampledNextPoint, GetAnimatedObjectGroundContactHeight());
|
||||
previousFramePoint = ApplyGroundPathObjectLiftOffset(
|
||||
ResolveGroundTrackedCenter(sampledPreviousPoint, GetAnimatedObjectGroundContactHeight()));
|
||||
nextFramePoint = ApplyGroundPathObjectLiftOffset(
|
||||
ResolveGroundTrackedCenter(sampledNextPoint, GetAnimatedObjectGroundContactHeight()));
|
||||
|
||||
if ((_route.PathType == PathType.Ground || _route.PathType == PathType.Hoisting) &&
|
||||
i > 0 &&
|
||||
@ -5461,6 +5467,34 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyObjectStartPlacementRequest(ObjectStartPlacementRequest request)
|
||||
{
|
||||
_objectStartPlacementMode = request.PlacementMode;
|
||||
if (_objectStartPlacementMode != ObjectStartPlacementMode.PreserveInitialPose)
|
||||
{
|
||||
_hasPathPreservedPoseRotation = false;
|
||||
}
|
||||
|
||||
_objectRotationCorrection = request.RotationCorrection;
|
||||
_groundPathObjectLiftHeight = UnitsConverter.ConvertFromMeters(request.VerticalLiftInMeters);
|
||||
|
||||
LogManager.Info(
|
||||
$"[起点摆放] 已应用物体调整请求: 模式={_objectStartPlacementMode}, 角度={_objectRotationCorrection}, " +
|
||||
$"提升高度={request.VerticalLiftInMeters:F3}m");
|
||||
|
||||
if (_animatedObject != null && _pathPoints != null && _pathPoints.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
MoveObjectToPathStartUsingCurrentPlacementMode();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[起点摆放] 应用物体调整请求失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保留给旧单轴调用方:按当前宿主 up 轴映射成三轴角度修正。
|
||||
/// </summary>
|
||||
@ -5479,6 +5513,12 @@ namespace NavisworksTransport.Core.Animation
|
||||
LogManager.Debug($"[角度修正] 直接设置角度修正值: {_objectRotationCorrection}(不触发旋转)");
|
||||
}
|
||||
|
||||
public void SetObjectStartVerticalLiftDirect(double verticalLiftInMeters)
|
||||
{
|
||||
_groundPathObjectLiftHeight = UnitsConverter.ConvertFromMeters(verticalLiftInMeters);
|
||||
LogManager.Debug($"[起点摆放] 直接设置地面路径提升高度: {verticalLiftInMeters:F3}m");
|
||||
}
|
||||
|
||||
public void SetObjectStartPlacementMode(ObjectStartPlacementMode placementMode)
|
||||
{
|
||||
_objectStartPlacementMode = placementMode;
|
||||
@ -5512,6 +5552,36 @@ namespace NavisworksTransport.Core.Animation
|
||||
: new LocalEulerRotationCorrection(0.0, 0.0, rotationCorrection);
|
||||
}
|
||||
|
||||
internal static Vector3 ResolveGroundPathObjectLiftOffsetVector(
|
||||
double verticalLiftModelUnits,
|
||||
CoordinateSystemType hostType)
|
||||
{
|
||||
if (verticalLiftModelUnits <= 0.0)
|
||||
{
|
||||
return Vector3.Zero;
|
||||
}
|
||||
|
||||
var adapter = new HostCoordinateAdapter(hostType);
|
||||
return Vector3.Normalize(adapter.HostUpVector3) * (float)verticalLiftModelUnits;
|
||||
}
|
||||
|
||||
private Point3D ApplyGroundPathObjectLiftOffset(Point3D trackedCenter)
|
||||
{
|
||||
if (_route == null || _route.PathType != PathType.Ground || _groundPathObjectLiftHeight <= 0.0)
|
||||
{
|
||||
return trackedCenter;
|
||||
}
|
||||
|
||||
Vector3 offset = ResolveGroundPathObjectLiftOffsetVector(
|
||||
_groundPathObjectLiftHeight,
|
||||
CoordinateSystemManager.Instance.ResolvedType);
|
||||
|
||||
return new Point3D(
|
||||
trackedCenter.X + offset.X,
|
||||
trackedCenter.Y + offset.Y,
|
||||
trackedCenter.Z + offset.Z);
|
||||
}
|
||||
|
||||
#region 动画实现方法
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1594,7 +1594,7 @@ namespace NavisworksTransport
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground)
|
||||
{
|
||||
// 地面路径:路径点是地面位置,通行空间底面在地面,中心需要向上偏移半个高度
|
||||
verticalOffset = height / 2.0;
|
||||
verticalOffset = ResolveGroundPathObjectSpaceVerticalOffset(height);
|
||||
}
|
||||
else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
|
||||
{
|
||||
@ -2314,7 +2314,12 @@ namespace NavisworksTransport
|
||||
/// <param name="passageAlongPath">沿路径方向的通行空间尺寸(模型单位)</param>
|
||||
/// <param name="passageNormalToPathVertical">垂直段的高度(物体长度 + 2×安全间隙,模型单位)</param>
|
||||
/// <param name="passageNormalToPathHorizontal">水平段的高度(物体高度 + 2×安全间隙,模型单位)</param>
|
||||
public void SetPassageSpaceParameters(double passageAcrossPath, double passageNormalToPath, double passageAlongPath, double passageNormalToPathVertical, double passageNormalToPathHorizontal)
|
||||
public void SetPassageSpaceParameters(
|
||||
double passageAcrossPath,
|
||||
double passageNormalToPath,
|
||||
double passageAlongPath,
|
||||
double passageNormalToPathVertical,
|
||||
double passageNormalToPathHorizontal)
|
||||
{
|
||||
// 直接存储模型单位(调用方已转换)
|
||||
_passageAlongPath = passageAlongPath;
|
||||
@ -2329,6 +2334,11 @@ namespace NavisworksTransport
|
||||
RefreshNormalPaths();
|
||||
}
|
||||
|
||||
internal static double ResolveGroundPathObjectSpaceVerticalOffset(double objectSpaceHeight)
|
||||
{
|
||||
return objectSpaceHeight / 2.0;
|
||||
}
|
||||
|
||||
#region 颜色管理
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -357,6 +357,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 角度修正相关字段
|
||||
private LocalEulerRotationCorrection _objectRotationCorrection = LocalEulerRotationCorrection.Zero; // 物体绕宿主 X/Y/Z 轴的角度修正
|
||||
private double _objectGroundLiftHeightInMeters;
|
||||
|
||||
// 移动物体原始尺寸(米,在选择物体时保存)
|
||||
private double _objectOriginalLength; // 物体原始长度(X方向)
|
||||
@ -1688,7 +1689,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
if (!isSameObject)
|
||||
{
|
||||
_pathAnimationManager?.SetObjectRotationCorrectionDirect(LocalEulerRotationCorrection.Zero);
|
||||
_pathAnimationManager?.SetObjectStartVerticalLiftDirect(0.0);
|
||||
ObjectRotationCorrection = LocalEulerRotationCorrection.Zero;
|
||||
_objectGroundLiftHeightInMeters = 0.0;
|
||||
LogManager.Debug("[选择物体] 已重置角度修正值为0(新物体)");
|
||||
}
|
||||
else
|
||||
@ -2124,6 +2127,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
_pathAnimationManager.RestoreObjectToCADPosition();
|
||||
_pathAnimationManager.ClearAnimationResults();
|
||||
_pathAnimationManager.SetObjectRotationCorrectionDirect(LocalEulerRotationCorrection.Zero);
|
||||
_pathAnimationManager.SetObjectStartVerticalLiftDirect(0.0);
|
||||
_pathAnimationManager.SetObjectStartPlacementMode(ObjectStartPlacementMode.AlignToPathPose);
|
||||
LogManager.Info("已清除PathAnimationManager中的动画数据并归位物体");
|
||||
}
|
||||
@ -2133,6 +2137,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 3. 重置角度修正值为0
|
||||
ObjectRotationCorrection = LocalEulerRotationCorrection.Zero;
|
||||
_objectGroundLiftHeightInMeters = 0.0;
|
||||
LogManager.Debug("[清除物体] 已重置角度修正值为0");
|
||||
|
||||
// 4. 重置属性
|
||||
@ -2159,20 +2164,29 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
var dialog = new Views.EditRotationWindow(_objectRotationCorrection);
|
||||
bool enableGroundLift = CurrentPathRoute?.PathType == PathType.Ground;
|
||||
var dialog = new Views.EditRotationWindow(
|
||||
_objectRotationCorrection,
|
||||
_objectGroundLiftHeightInMeters,
|
||||
enableGroundLift);
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
var placementRequest = dialog.AdjustmentRequest;
|
||||
if (placementRequest.PreserveInitialPose)
|
||||
{
|
||||
ApplyTranslationOnlyObjectPlacement();
|
||||
return;
|
||||
}
|
||||
|
||||
_pathAnimationManager?.SetObjectStartPlacementMode(ObjectStartPlacementMode.AlignToPathPose);
|
||||
_objectGroundLiftHeightInMeters = placementRequest.VerticalLiftInMeters;
|
||||
_pathAnimationManager?.ApplyObjectStartPlacementRequest(placementRequest);
|
||||
ObjectRotationCorrection = placementRequest.RotationCorrection;
|
||||
LogManager.Info($"物体角度修正已更新: {_objectRotationCorrection}");
|
||||
UpdateMainStatus($"物体角度修正: {_objectRotationCorrection}");
|
||||
|
||||
string liftSummary = enableGroundLift
|
||||
? $", 提升高度={_objectGroundLiftHeightInMeters:F3}m"
|
||||
: string.Empty;
|
||||
string statusSummary = placementRequest.PreserveInitialPose
|
||||
? $"物体已调整为平移模式{liftSummary}"
|
||||
: $"物体角度修正: {_objectRotationCorrection}{liftSummary}";
|
||||
|
||||
LogManager.Info(
|
||||
$"物体调整已更新: 模式={placementRequest.PlacementMode}, 角度={_objectRotationCorrection}, " +
|
||||
$"提升高度={_objectGroundLiftHeightInMeters:F3}m");
|
||||
UpdateMainStatus(statusSummary);
|
||||
|
||||
// 更新通行空间可视化(考虑旋转后的尺寸)
|
||||
UpdatePassageSpaceVisualization();
|
||||
@ -2196,6 +2210,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
_objectRotationCorrection = LocalEulerRotationCorrection.Zero;
|
||||
_pathAnimationManager.SetObjectRotationCorrectionDirect(LocalEulerRotationCorrection.Zero);
|
||||
_pathAnimationManager.SetObjectStartVerticalLiftDirect(0.0);
|
||||
_pathAnimationManager.SetObjectStartPlacementMode(ObjectStartPlacementMode.PreserveInitialPose);
|
||||
OnPropertyChanged(nameof(ObjectRotationCorrection));
|
||||
|
||||
@ -4463,7 +4478,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 地面路径:物体的长度方向(X轴,前进方向)朝向路径方向
|
||||
// 通行空间沿路径方向 = X方向尺寸(长度),垂直于路径方向 = Y方向尺寸(宽度),高度上方加间隙(下方不需要,因为有地面)
|
||||
passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向)
|
||||
passageNormalToPath = effectiveHeight + safetyMargin; // 法线方向高度 + 间隙(法线方向,只有上方)
|
||||
passageNormalToPath = effectiveHeight + (_objectGroundLiftHeightInMeters * metersToUnitsPassage) + safetyMargin; // 物体高度 + 提升高度 + 上方间隙
|
||||
passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向)
|
||||
// 地面路径不需要分段参数
|
||||
passageNormalToPathVertical = passageNormalToPath;
|
||||
@ -4507,7 +4522,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 物体的长度方向(X轴,前进方向)朝向路径方向
|
||||
// 通行空间沿路径方向 = X方向尺寸(长度),垂直于路径方向 = Y方向尺寸(宽度),高度上方加间隙(下方不需要,因为有地面)
|
||||
passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向)
|
||||
passageNormalToPath = effectiveHeight + safetyMargin; // 局部up方向高度 + 间隙(法线方向,只有上方)
|
||||
passageNormalToPath = effectiveHeight + (_objectGroundLiftHeightInMeters * metersToUnitsPassage) + safetyMargin; // 物体高度 + 提升高度 + 上方间隙
|
||||
passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向)
|
||||
// 地面路径不需要分段参数
|
||||
passageNormalToPathVertical = passageNormalToPath;
|
||||
@ -4551,7 +4566,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
passageAlongPath,
|
||||
passageNormalToPathVertical,
|
||||
passageNormalToPathHorizontal);
|
||||
LogManager.Debug($"[通行空间可视化] 已设置通行空间参数: 沿路径={passageAlongPath / metersToUnitsPassage:F2}m, 垂直路径={passageAcrossPath / metersToUnitsPassage:F2}m, 法线={passageNormalToPath / metersToUnitsPassage:F2}m, 安全间隙={_safetyMarginInMeters:F2}m");
|
||||
LogManager.Debug($"[通行空间可视化] 已设置通行空间参数: 沿路径={passageAlongPath / metersToUnitsPassage:F2}m, 垂直路径={passageAcrossPath / metersToUnitsPassage:F2}m, 法线={passageNormalToPath / metersToUnitsPassage:F2}m, 提升高度={_objectGroundLiftHeightInMeters:F2}m, 安全间隙={_safetyMarginInMeters:F2}m");
|
||||
|
||||
// 根据路径类型决定是否切换到物体通行空间模式
|
||||
bool enableObjectSpace = false;
|
||||
|
||||
@ -346,7 +346,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
<Button Content="选择物体"
|
||||
Command="{Binding SelectAnimatedObjectCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="调整角度"
|
||||
<Button Content="调整物体"
|
||||
Command="{Binding EditObjectRotationCommand}"
|
||||
IsEnabled="{Binding HasSelectedAnimatedObject}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
@ -383,7 +383,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
<Run Text="m"/>
|
||||
</TextBlock>
|
||||
<Button Grid.Column="2"
|
||||
Content="调整角度"
|
||||
Content="调整物体"
|
||||
Command="{Binding EditObjectRotationCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Margin="10,0,0,0"/>
|
||||
|
||||
@ -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="400"
|
||||
Title="调整物体" Height="430" Width="400"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
@ -25,8 +25,8 @@
|
||||
<!-- 标题栏 -->
|
||||
<Border Grid.Row="0" Background="#FFF8FBFF" BorderBrush="#FFD4E7FF" BorderThickness="0,0,0,1" Padding="20,15">
|
||||
<StackPanel>
|
||||
<TextBlock Text="调整物体角度" FontWeight="SemiBold" FontSize="14" Foreground="#FF2B579A"/>
|
||||
<TextBlock Text="设置物体在路径起点处绕宿主 X/Y/Z 轴的旋转角度" FontSize="10" Foreground="#FF666666" Margin="0,3,0,0"/>
|
||||
<TextBlock Text="调整物体" FontWeight="SemiBold" FontSize="14" Foreground="#FF2B579A"/>
|
||||
<TextBlock Text="设置物体在路径起点处的角度修正;地面路径可额外输入提升高度" FontSize="10" Foreground="#FF666666" Margin="0,3,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@ -95,6 +95,31 @@
|
||||
BorderThickness="1"/>
|
||||
<TextBlock Grid.Column="2" Text="°" VerticalAlignment="Center" FontSize="11" Foreground="#FF666666" Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
|
||||
<Grid Margin="0,0,0,12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="50"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="提升高度:" VerticalAlignment="Center" FontSize="11" Foreground="#FF333333"/>
|
||||
<TextBox Grid.Column="1"
|
||||
x:Name="GroundLiftTextBox"
|
||||
Text="{Binding GroundPathLiftHeightInMeters, StringFormat=0.###, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding IsGroundLiftEnabled}"
|
||||
Height="28"
|
||||
VerticalContentAlignment="Center"
|
||||
Padding="8,0"
|
||||
FontSize="11"
|
||||
BorderBrush="#FFCCCCCC"
|
||||
BorderThickness="1"/>
|
||||
<TextBlock Grid.Column="2" Text="m" VerticalAlignment="Center" FontSize="11" Foreground="#FF666666" Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="{Binding GroundLiftHint}"
|
||||
FontSize="10"
|
||||
Foreground="#FF666666"
|
||||
Margin="0,0,0,12"/>
|
||||
|
||||
<!-- 快捷按钮 -->
|
||||
<TextBlock Text="快捷角度(作用于当前焦点输入框):" FontSize="10" Foreground="#FF666666" Margin="0,0,0,8"/>
|
||||
|
||||
@ -19,8 +19,10 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
private double _rotationXDegrees;
|
||||
private double _rotationYDegrees;
|
||||
private double _rotationZDegrees;
|
||||
private double _groundPathLiftHeightInMeters;
|
||||
private RotationAxisTarget _activeAxisTarget = RotationAxisTarget.Z;
|
||||
private ObjectStartPlacementRequest _adjustmentRequest;
|
||||
private readonly bool _isGroundLiftEnabled;
|
||||
|
||||
public double RotationXDegrees
|
||||
{
|
||||
@ -67,9 +69,31 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
public LocalEulerRotationCorrection RotationCorrection =>
|
||||
new LocalEulerRotationCorrection(RotationXDegrees, RotationYDegrees, RotationZDegrees);
|
||||
|
||||
public double GroundPathLiftHeightInMeters
|
||||
{
|
||||
get => _groundPathLiftHeightInMeters;
|
||||
set
|
||||
{
|
||||
if (Math.Abs(_groundPathLiftHeightInMeters - value) > 1e-9)
|
||||
{
|
||||
_groundPathLiftHeightInMeters = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGroundLiftEnabled => _isGroundLiftEnabled;
|
||||
|
||||
public string GroundLiftHint => _isGroundLiftEnabled
|
||||
? "仅地面路径生效,用于模拟物体下方物流小车带来的整体抬升。"
|
||||
: "提升高度当前仅对地面路径生效。";
|
||||
|
||||
public ObjectStartPlacementRequest AdjustmentRequest => _adjustmentRequest;
|
||||
|
||||
public EditRotationWindow(LocalEulerRotationCorrection currentRotation)
|
||||
public EditRotationWindow(
|
||||
LocalEulerRotationCorrection currentRotation,
|
||||
double currentGroundLiftHeightInMeters,
|
||||
bool isGroundLiftEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -77,7 +101,9 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
RotationXDegrees = currentRotation.XDegrees;
|
||||
RotationYDegrees = currentRotation.YDegrees;
|
||||
RotationZDegrees = currentRotation.ZDegrees;
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(currentRotation);
|
||||
_isGroundLiftEnabled = isGroundLiftEnabled;
|
||||
GroundPathLiftHeightInMeters = currentGroundLiftHeightInMeters;
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(currentRotation, currentGroundLiftHeightInMeters);
|
||||
DataContext = this;
|
||||
Loaded += (sender, args) => ZAxisTextBox.Focus();
|
||||
}
|
||||
@ -145,14 +171,24 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
|
||||
private void OnConfirmClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(RotationCorrection);
|
||||
if (!ValidateGroundLiftHeight())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(RotationCorrection, GroundPathLiftHeightInMeters);
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnTranslateClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.TranslationOnly;
|
||||
if (!ValidateGroundLiftHeight())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_adjustmentRequest = ObjectStartPlacementRequest.CreateTranslationOnly(GroundPathLiftHeightInMeters);
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
@ -186,5 +222,17 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateGroundLiftHeight()
|
||||
{
|
||||
if (GroundPathLiftHeightInMeters < 0.0)
|
||||
{
|
||||
MessageBox.Show("提升高度必须大于或等于 0。", "输入错误", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
GroundLiftTextBox.Focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,31 +11,43 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
public struct ObjectStartPlacementRequest : IEquatable<ObjectStartPlacementRequest>
|
||||
{
|
||||
public static readonly ObjectStartPlacementRequest TranslationOnly =
|
||||
new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose);
|
||||
new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose, 0.0);
|
||||
|
||||
public ObjectStartPlacementRequest(
|
||||
LocalEulerRotationCorrection rotationCorrection,
|
||||
ObjectStartPlacementMode placementMode)
|
||||
ObjectStartPlacementMode placementMode,
|
||||
double verticalLiftInMeters)
|
||||
{
|
||||
RotationCorrection = rotationCorrection;
|
||||
PlacementMode = placementMode;
|
||||
VerticalLiftInMeters = verticalLiftInMeters;
|
||||
}
|
||||
|
||||
public LocalEulerRotationCorrection RotationCorrection { get; }
|
||||
|
||||
public ObjectStartPlacementMode PlacementMode { get; }
|
||||
|
||||
public double VerticalLiftInMeters { get; }
|
||||
|
||||
public bool PreserveInitialPose => PlacementMode == ObjectStartPlacementMode.PreserveInitialPose;
|
||||
|
||||
public static ObjectStartPlacementRequest CreateRotationCorrection(LocalEulerRotationCorrection rotationCorrection)
|
||||
public static ObjectStartPlacementRequest CreateRotationCorrection(
|
||||
LocalEulerRotationCorrection rotationCorrection,
|
||||
double verticalLiftInMeters = 0.0)
|
||||
{
|
||||
return new ObjectStartPlacementRequest(rotationCorrection, ObjectStartPlacementMode.AlignToPathPose);
|
||||
return new ObjectStartPlacementRequest(rotationCorrection, ObjectStartPlacementMode.AlignToPathPose, verticalLiftInMeters);
|
||||
}
|
||||
|
||||
public static ObjectStartPlacementRequest CreateTranslationOnly(double verticalLiftInMeters = 0.0)
|
||||
{
|
||||
return new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose, verticalLiftInMeters);
|
||||
}
|
||||
|
||||
public bool Equals(ObjectStartPlacementRequest other)
|
||||
{
|
||||
return RotationCorrection.Equals(other.RotationCorrection) &&
|
||||
PlacementMode == other.PlacementMode;
|
||||
PlacementMode == other.PlacementMode &&
|
||||
VerticalLiftInMeters.Equals(other.VerticalLiftInMeters);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
@ -47,13 +59,16 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (RotationCorrection.GetHashCode() * 397) ^ (int)PlacementMode;
|
||||
int hashCode = RotationCorrection.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ (int)PlacementMode;
|
||||
hashCode = (hashCode * 397) ^ VerticalLiftInMeters.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"PlacementMode={PlacementMode}, Rotation={RotationCorrection}";
|
||||
return $"PlacementMode={PlacementMode}, Rotation={RotationCorrection}, VerticalLiftInMeters={VerticalLiftInMeters:F3}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user