约束保留门型偏好,评估改用固定宿主X轴前向,结果加回路径yaw

This commit is contained in:
tian 2026-05-29 01:44:23 +08:00
parent 649c7b50f1
commit c67dee4f11
4 changed files with 15 additions and 47 deletions

View File

@ -2229,10 +2229,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
return ObjectPassageProjectionOptimizationResult.CreateFailure("动画物体为空,无法自动调整。");
}
if (!TryCreatePassageProjectionAxes(request, out Vector3 hostSide, out Vector3 hostUp))
{
return ObjectPassageProjectionOptimizationResult.CreateFailure("路径方向退化,无法计算通行截面。");
}
// 固定评估坐标系:前向=宿主X轴截面=YZ平面
CoordinateSystemType hst = CoordinateSystemManager.Instance.ResolvedType;
var hostUp = hst == CoordinateSystemType.YUp ? Vector3.UnitY : Vector3.UnitZ;
var hostSide = Vector3.Cross(Vector3.UnitX, hostUp);
var originalCorrection = _objectRotationCorrection;
double originalLiftInMeters = _objectGroundLiftHeightInMeters;
@ -2244,37 +2244,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
request,
correction =>
{
// 从 correction 扣除路径 yaw动画链路会在起点再次加上
// 这样 targetYaw = pathYaw + (correctionY - pathYaw) = correctionY
CoordinateSystemType hst = CoordinateSystemManager.Instance.ResolvedType;
double pyAdj = 0;
if (PathTargetFrameResolver.TryResolvePlanarHostYaw(request.HostPathForward, hst, out double pyRad))
{
pyAdj = pyRad * 180.0 / Math.PI;
}
var corr = correction;
var baseAdjusted = new LocalEulerRotationCorrection(
corr.XDegrees,
hst == CoordinateSystemType.YUp ? corr.YDegrees - pyAdj : corr.YDegrees,
hst == CoordinateSystemType.ZUp ? corr.ZDegrees - pyAdj : corr.ZDegrees);
var placementRequest = ObjectStartPlacementRequest.CreateRotationCorrection(
baseAdjusted,
correction,
originalLiftInMeters);
_pathAnimationManager.ApplyObjectStartPlacementRequest(placementRequest);
BoundingBox3D bounds = animatedObject.BoundingBox();
var baseScore = CalculateMeasuredAabbProjectionScore(bounds, hostSide, hostUp);
var score = new ObjectPassageProjectionScore(
baseScore.WidthAcrossPath,
baseScore.HeightAlongHostUp + request.VehicleHeightModelUnits);
var score = CalculateMeasuredAabbProjectionScore(bounds, hostSide, hostUp);
// 按门型约束过滤:宽门要求 Width >= Height高门要求 Height >= Width
bool meetsConstraint = request.RequireWidthLarger
? score.WidthAcrossPath >= score.HeightAlongHostUp
: score.HeightAlongHostUp >= score.WidthAcrossPath;
if (!meetsConstraint)
{
return ObjectPassageProjectionScore.Invalid;
}
return score;
});
@ -2282,17 +2263,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 计算上下偏移:应用最优旋转后,使物体底面贴合物流车高度
if (result.Success && CurrentPathRoute?.PathType == PathType.Ground)
{
CoordinateSystemType hst = CoordinateSystemManager.Instance.ResolvedType;
double pyAdj = 0;
if (PathTargetFrameResolver.TryResolvePlanarHostYaw(request.HostPathForward, hst, out double pyRad))
{
pyAdj = pyRad * 180.0 / Math.PI;
}
var optimalBaseAdjusted = new LocalEulerRotationCorrection(
result.Correction.XDegrees,
hst == CoordinateSystemType.YUp ? result.Correction.YDegrees - pyAdj : result.Correction.YDegrees,
hst == CoordinateSystemType.ZUp ? result.Correction.ZDegrees - pyAdj : result.Correction.ZDegrees);
var measureRequest = ObjectStartPlacementRequest.CreateRotationCorrection(optimalBaseAdjusted, 0);
var measureRequest = ObjectStartPlacementRequest.CreateRotationCorrection(result.Correction, 0);
_pathAnimationManager.ApplyObjectStartPlacementRequest(measureRequest);
BoundingBox3D measureBounds = animatedObject.BoundingBox();

View File

@ -150,7 +150,7 @@
<CheckBox x:Name="WidthLargerCheckBox"
IsChecked="{Binding RequireWidthLarger}"
Content="宽 > 高(否则高 > 宽)"
ToolTip="根据物流通道门型选择:默认宽扁门,物体放平穿过;取消则为高窄门,物体立起穿过。"
ToolTip="根据物流通道门型选择"
FontSize="10"
Foreground="#FF666666"
Margin="0,0,0,8"/>

View File

@ -28,8 +28,8 @@ namespace NavisworksTransport.UI.WPF.Views
private readonly ObjectPassageProjectionOptimizationRequest _autoAdjustmentRequest;
private readonly Func<ObjectPassageProjectionOptimizationResult> _autoAdjustmentProvider;
private readonly bool _isGroundLiftEnabled;
private bool _requireWidthLarger = false;
private double _vehicleHeightInMeters = 0.15;
private bool _requireWidthLarger = false;
/// <summary>
/// 门型偏好true=宽>高false=高>宽(默认)
@ -40,9 +40,6 @@ namespace NavisworksTransport.UI.WPF.Views
set => _requireWidthLarger = value;
}
/// <summary>
/// 物流车辆高度(米),默认 0.15m
/// </summary>
public double VehicleHeightInMeters
{
get => _vehicleHeightInMeters;
@ -177,8 +174,10 @@ namespace NavisworksTransport.UI.WPF.Views
return;
}
PathTargetFrameResolver.TryResolvePlanarHostYaw(_autoAdjustmentRequest.HostPathForward, CoordinateSystemManager.Instance.ResolvedType, out double yawRad);
RotationXDegrees = NormalizeDisplayDegrees(result.Correction.XDegrees);
RotationYDegrees = NormalizeDisplayDegrees(result.Correction.YDegrees);
RotationYDegrees = NormalizeDisplayDegrees(result.Correction.YDegrees + yawRad * 180.0 / Math.PI);
RotationZDegrees = NormalizeDisplayDegrees(result.Correction.ZDegrees);
if (result.ComputedLiftOffsetMeters.HasValue)
{

View File

@ -13,8 +13,7 @@ namespace NavisworksTransport.Utils.CoordinateSystem
Vector3 hostPathForward,
Vector3 hostUp,
double areaRelativeTieTolerance = 0.01,
Quaternion? baselineHostRotation = null,
bool requireWidthLarger = true)
Quaternion? baselineHostRotation = null)
{
SizeX = sizeX;
SizeY = sizeY;
@ -23,7 +22,6 @@ namespace NavisworksTransport.Utils.CoordinateSystem
HostUp = hostUp;
AreaRelativeTieTolerance = areaRelativeTieTolerance;
BaselineHostRotation = Quaternion.Normalize(baselineHostRotation ?? Quaternion.Identity);
RequireWidthLarger = requireWidthLarger;
}
public double SizeX { get; }
@ -41,12 +39,12 @@ namespace NavisworksTransport.Utils.CoordinateSystem
public Quaternion BaselineHostRotation { get; }
/// <summary>
/// 是否要求通行截面宽度 >= 高度宽扁门。false 表示高窄门(高度 >= 宽度)。
/// 门型偏好true=宽>高false=高>宽
/// </summary>
public bool RequireWidthLarger { get; set; }
/// <summary>
/// 物体下方物流车辆高度(模型单位),自动调整时加到通行截面高度上。
/// 物体下方物流车辆高度(模型单位)
/// </summary>
public double VehicleHeightModelUnits { get; set; }
}