78 lines
3.3 KiB
C#
78 lines
3.3 KiB
C#
using System;
|
||
using System.Numerics;
|
||
|
||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||
{
|
||
/// <summary>
|
||
/// 真实物体在 Rail 路径下的尺寸语义解析。
|
||
/// 先根据解释后的真实参考姿态解析 rail 轴约定,再使用:
|
||
/// 1. rail 基姿态(零角度时对象与路径框架对齐后的宿主姿态)
|
||
/// 2. 最终姿态(rail 基姿态再叠加宿主轴角度修正)
|
||
/// 共同计算沿 rail forward/side/normal 的有效尺寸。
|
||
///
|
||
/// 关键点:
|
||
/// - 这里不能只吃“角度修正”本身;否则双轴旋转时会漏掉 rail 基姿态语义。
|
||
/// - 目标语义轴来自 rail 基姿态,而不是宿主世界轴。
|
||
/// </summary>
|
||
public static class RealObjectRailExtentResolver
|
||
{
|
||
public static bool TryResolveProjectedSemanticExtents(
|
||
Vector3 referenceAxisX,
|
||
Vector3 referenceAxisY,
|
||
Vector3 referenceAxisZ,
|
||
Vector3 desiredForward,
|
||
CoordinateSystemType hostType,
|
||
double forwardSize,
|
||
double sideSize,
|
||
double upSize,
|
||
Quaternion baselineHostQuaternion,
|
||
Quaternion finalHostQuaternion,
|
||
out ModelAxisConvention convention,
|
||
out (double forwardExtent, double sideExtent, double upExtent) extents)
|
||
{
|
||
convention = null;
|
||
extents = (0.0, 0.0, 0.0);
|
||
|
||
if (!RealObjectRailAxisConventionResolver.TryResolve(
|
||
referenceAxisX,
|
||
referenceAxisY,
|
||
referenceAxisZ,
|
||
desiredForward,
|
||
hostType,
|
||
out convention,
|
||
out _,
|
||
out _))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
Vector3 localSize = convention.CreateScaleVector3(forwardSize, sideSize, upSize);
|
||
Vector3 rotatedLocalX = Vector3.Normalize(Vector3.Transform(Vector3.UnitX, finalHostQuaternion));
|
||
Vector3 rotatedLocalY = Vector3.Normalize(Vector3.Transform(Vector3.UnitY, finalHostQuaternion));
|
||
Vector3 rotatedLocalZ = Vector3.Normalize(Vector3.Transform(Vector3.UnitZ, finalHostQuaternion));
|
||
|
||
Vector3 targetForward = Vector3.Normalize(Vector3.Transform(convention.ForwardUnitVector, baselineHostQuaternion));
|
||
Vector3 targetUp = Vector3.Normalize(Vector3.Transform(convention.UpUnitVector, baselineHostQuaternion));
|
||
Vector3 targetSide = Vector3.Normalize(Vector3.Cross(targetForward, targetUp));
|
||
|
||
extents = (
|
||
ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetForward),
|
||
ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetSide),
|
||
ProjectExtent(localSize, rotatedLocalX, rotatedLocalY, rotatedLocalZ, targetUp));
|
||
return true;
|
||
}
|
||
|
||
private static double ProjectExtent(
|
||
Vector3 localSize,
|
||
Vector3 rotatedLocalX,
|
||
Vector3 rotatedLocalY,
|
||
Vector3 rotatedLocalZ,
|
||
Vector3 targetAxis)
|
||
{
|
||
return Math.Abs(Vector3.Dot(rotatedLocalX, targetAxis)) * localSize.X +
|
||
Math.Abs(Vector3.Dot(rotatedLocalY, targetAxis)) * localSize.Y +
|
||
Math.Abs(Vector3.Dot(rotatedLocalZ, targetAxis)) * localSize.Z;
|
||
}
|
||
}
|
||
}
|