NavisworksTransport/src/Utils/CoordinateSystem/RealObjectRailExtentResolver.cs

78 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}