Separate asset axis conventions from host coordinates
This commit is contained in:
parent
5e7f9bdf51
commit
1802eda971
@ -59,6 +59,40 @@ namespace NavisworksTransport.UnitTests.CoordinateSystem
|
||||
AssertColumn(linear, 2, 1, 0, 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReferenceRodAssetConvention_ShouldUseXForwardAndZUp()
|
||||
{
|
||||
ModelAxisConvention convention = ModelAxisConvention.CreateReferenceRodAssetConvention();
|
||||
|
||||
Assert.AreEqual(LocalAxisDirection.PositiveX, convention.ForwardAxis);
|
||||
Assert.AreEqual(LocalAxisDirection.PositiveZ, convention.UpAxis);
|
||||
Assert.AreEqual(LocalAxisDirection.NegativeY, convention.SideAxis);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VirtualObjectAssetConvention_CreateScaleVector_ShouldMapLengthWidthHeightToLocalAxes()
|
||||
{
|
||||
ModelAxisConvention convention = ModelAxisConvention.CreateVirtualObjectAssetConvention();
|
||||
|
||||
var scale = convention.CreateScaleVector3(12.0, 5.0, 7.0);
|
||||
|
||||
Assert.AreEqual(12.0, scale.X, 1e-6);
|
||||
Assert.AreEqual(5.0, scale.Y, 1e-6);
|
||||
Assert.AreEqual(7.0, scale.Z, 1e-6);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void YUpConvention_CreateScaleVector_ShouldMapUpSizeToLocalY()
|
||||
{
|
||||
ModelAxisConvention convention = ModelAxisConvention.CreateDefaultForHost(CoordinateSystemType.YUp);
|
||||
|
||||
var scale = convention.CreateScaleVector3(12.0, 5.0, 7.0);
|
||||
|
||||
Assert.AreEqual(12.0, scale.X, 1e-6);
|
||||
Assert.AreEqual(7.0, scale.Y, 1e-6);
|
||||
Assert.AreEqual(5.0, scale.Z, 1e-6);
|
||||
}
|
||||
|
||||
private static void AssertColumn(Matrix4x4 matrix, int column, double x, double y, double z)
|
||||
{
|
||||
switch (column)
|
||||
|
||||
@ -3368,7 +3368,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
{
|
||||
if (_isVirtualObject)
|
||||
{
|
||||
return ModelAxisConvention.CreateDefaultForHost(CoordinateSystemType.ZUp);
|
||||
return ModelAxisConvention.CreateVirtualObjectAssetConvention();
|
||||
}
|
||||
|
||||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||||
@ -3383,7 +3383,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
{
|
||||
if (_isVirtualObject)
|
||||
{
|
||||
return ModelAxisConvention.CreateDefaultForHost(CoordinateSystemType.ZUp);
|
||||
return ModelAxisConvention.CreateVirtualObjectAssetConvention();
|
||||
}
|
||||
|
||||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||||
|
||||
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisworksTransport.Utils.CoordinateSystem;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
{
|
||||
@ -15,6 +16,7 @@ namespace NavisworksTransport.Core
|
||||
public class AssemblyReferencePathManager
|
||||
{
|
||||
private const double ReferenceRodBaseSizeInMeters = 0.01;
|
||||
private static readonly ModelAxisConvention ReferenceRodAxisConvention = ModelAxisConvention.CreateReferenceRodAssetConvention();
|
||||
|
||||
private static AssemblyReferencePathManager _instance;
|
||||
private static readonly object _lock = new object();
|
||||
@ -220,7 +222,7 @@ namespace NavisworksTransport.Core
|
||||
|
||||
var currentTransform = _referenceRodModel.Transform;
|
||||
var components = currentTransform.Factor();
|
||||
components.Scale = new Vector3D(
|
||||
components.Scale = ReferenceRodAxisConvention.CreateScaleVector(
|
||||
lengthInMeters / ReferenceRodBaseSizeInMeters,
|
||||
diameterInMeters / ReferenceRodBaseSizeInMeters,
|
||||
diameterInMeters / ReferenceRodBaseSizeInMeters);
|
||||
@ -265,11 +267,11 @@ namespace NavisworksTransport.Core
|
||||
endPoint.Y - startPoint.Y,
|
||||
endPoint.Z - startPoint.Z));
|
||||
|
||||
// 参考杆资源约定:几何中心在原点,长度轴沿局部 +X。
|
||||
// 参考杆资源约定:几何中心在原点,长度轴沿本地 ForwardAxis。
|
||||
// Navisworks API 文档中 Rotation3D(vector1, vector2) 的语义
|
||||
// 是“将 vector1 旋转到与 vector2 同方向”,这里直接将本地 X 轴对齐参考线方向。
|
||||
// 是“将 vector1 旋转到与 vector2 同方向”,这里直接将资源本地 forward 轴对齐参考线方向。
|
||||
return new Rotation3D(
|
||||
new UnitVector3D(1, 0, 0),
|
||||
new UnitVector3D(ReferenceRodAxisConvention.ForwardVector),
|
||||
new UnitVector3D(tangent));
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisworksTransport.Utils.CoordinateSystem;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
{
|
||||
@ -17,6 +18,7 @@ namespace NavisworksTransport.Core
|
||||
/// </summary>
|
||||
public class VirtualObjectManager
|
||||
{
|
||||
private static readonly ModelAxisConvention VirtualObjectAxisConvention = ModelAxisConvention.CreateVirtualObjectAssetConvention();
|
||||
private static VirtualObjectManager _instance;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
@ -188,62 +190,15 @@ namespace NavisworksTransport.Core
|
||||
|
||||
try
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
|
||||
// 获取当前缩放
|
||||
var currentTransform = _virtualObjectModelItem.Transform;
|
||||
var currentComponents = currentTransform.Factor();
|
||||
var currentScale = currentComponents.Scale;
|
||||
|
||||
// 重置到CAD原始状态
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
|
||||
// 获取CAD原始状态
|
||||
var originalBounds = _virtualObjectModelItem.BoundingBox();
|
||||
var originalGroundPos = new Point3D(
|
||||
originalBounds.Center.X,
|
||||
originalBounds.Center.Y,
|
||||
originalBounds.Min.Z
|
||||
);
|
||||
var originalYaw = GetYawFromTransform(_virtualObjectModelItem.Transform);
|
||||
|
||||
// 计算增量
|
||||
var deltaPos = new Vector3D(
|
||||
position.X - originalGroundPos.X,
|
||||
position.Y - originalGroundPos.Y,
|
||||
position.Z - originalGroundPos.Z
|
||||
);
|
||||
double deltaYaw = yawRadians - originalYaw;
|
||||
|
||||
// 构建变换,保留当前缩放
|
||||
var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
|
||||
var components = identity.Factor();
|
||||
components.Scale = currentScale;
|
||||
|
||||
if (Math.Abs(deltaYaw) > 0.001)
|
||||
{
|
||||
double cos = Math.Cos(deltaYaw);
|
||||
double sin = Math.Sin(deltaYaw);
|
||||
double rotatedX = originalGroundPos.X * cos - originalGroundPos.Y * sin;
|
||||
double rotatedY = originalGroundPos.X * sin + originalGroundPos.Y * cos;
|
||||
|
||||
components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
|
||||
components.Translation = new Vector3D(
|
||||
position.X - rotatedX,
|
||||
position.Y - rotatedY,
|
||||
deltaPos.Z
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
components.Translation = deltaPos;
|
||||
}
|
||||
|
||||
Transform3D transform = components.Combine();
|
||||
doc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
|
||||
LogManager.Debug($"虚拟物体已移动");
|
||||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||||
var hostForward = adapter.FromCanonicalVector(new Vector3D(Math.Cos(yawRadians), Math.Sin(yawRadians), 0));
|
||||
var hostUp = adapter.FromCanonicalVector(new Vector3D(
|
||||
HostCoordinateAdapter.CanonicalUpVector3.X,
|
||||
HostCoordinateAdapter.CanonicalUpVector3.Y,
|
||||
HostCoordinateAdapter.CanonicalUpVector3.Z));
|
||||
var rotation = VirtualObjectAxisConvention.CreateRotation(hostForward, hostUp);
|
||||
MoveVirtualObject(position, rotation);
|
||||
LogManager.Debug($"虚拟物体已按Canonical平面yaw应用完整姿态");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -367,16 +322,14 @@ namespace NavisworksTransport.Core
|
||||
if (_virtualObjectModel == null || _virtualObjectModelItem == null) return;
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
double metersToUnits = Utils.UnitsConverter.GetMetersToUnitsConversionFactor(doc.Units);
|
||||
|
||||
double baseSizeMeters = 0.01;
|
||||
double scaleX = lengthMeters / baseSizeMeters;
|
||||
double scaleY = widthMeters / baseSizeMeters;
|
||||
double scaleZ = heightMeters / baseSizeMeters;
|
||||
|
||||
var currentTransform = _virtualObjectModel.Transform;
|
||||
var transformComponents = currentTransform.Factor();
|
||||
transformComponents.Scale = new Vector3D(scaleX, scaleY, scaleZ);
|
||||
transformComponents.Scale = VirtualObjectAxisConvention.CreateScaleVector(
|
||||
lengthMeters / baseSizeMeters,
|
||||
widthMeters / baseSizeMeters,
|
||||
heightMeters / baseSizeMeters);
|
||||
|
||||
Transform3D newTransform = transformComponents.Combine();
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, _virtualObjectModel.Units, newTransform, false);
|
||||
@ -409,20 +362,6 @@ namespace NavisworksTransport.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Transform中提取Yaw角度(简化版本)
|
||||
/// </summary>
|
||||
private double GetYawFromTransform(Transform3D transform)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用ModelItemTransformHelper中的方法
|
||||
return ModelItemTransformHelper.GetYawFromTransform(transform);
|
||||
}
|
||||
catch { }
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理虚拟物体(用于程序退出或切换文档时)
|
||||
/// </summary>
|
||||
|
||||
@ -108,6 +108,33 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟物体资源的本地轴约定。
|
||||
/// 该约定仅描述资源文件本身的 local forward/up,不代表当前宿主文档的坐标系。
|
||||
/// </summary>
|
||||
public static ModelAxisConvention CreateVirtualObjectAssetConvention()
|
||||
{
|
||||
return new ModelAxisConvention(LocalAxisDirection.PositiveX, LocalAxisDirection.PositiveZ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参考杆资源的本地轴约定。
|
||||
/// 当前资源约定长度轴沿本地 +X,截面 up 沿本地 +Z。
|
||||
/// </summary>
|
||||
public static ModelAxisConvention CreateReferenceRodAssetConvention()
|
||||
{
|
||||
return new ModelAxisConvention(LocalAxisDirection.PositiveX, LocalAxisDirection.PositiveZ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rail 资源的本地轴约定。
|
||||
/// 当前资源约定前进方向沿本地 +X,向上沿本地 +Z。
|
||||
/// </summary>
|
||||
public static ModelAxisConvention CreateRailAssetConvention()
|
||||
{
|
||||
return new ModelAxisConvention(LocalAxisDirection.PositiveX, LocalAxisDirection.PositiveZ);
|
||||
}
|
||||
|
||||
public double GetForwardSize(BoundingBox3D bounds)
|
||||
{
|
||||
return GetAxisExtent(bounds, ForwardAxis);
|
||||
@ -123,6 +150,23 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
return GetAxisExtent(bounds, SideAxis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据 forward/side/up 语义尺寸,构造资源本地 X/Y/Z 的缩放向量。
|
||||
/// </summary>
|
||||
public Vector3D CreateScaleVector(double forwardSize, double sideSize, double upSize)
|
||||
{
|
||||
Vector3 scale = CreateScaleVector3(forwardSize, sideSize, upSize);
|
||||
return new Vector3D(scale.X, scale.Y, scale.Z);
|
||||
}
|
||||
|
||||
public Vector3 CreateScaleVector3(double forwardSize, double sideSize, double upSize)
|
||||
{
|
||||
float scaleX = (float)ResolveLocalAxisScale(0, forwardSize, sideSize, upSize);
|
||||
float scaleY = (float)ResolveLocalAxisScale(1, forwardSize, sideSize, upSize);
|
||||
float scaleZ = (float)ResolveLocalAxisScale(2, forwardSize, sideSize, upSize);
|
||||
return new Vector3(scaleX, scaleY, scaleZ);
|
||||
}
|
||||
|
||||
private static Vector3 GetAxisVector3(LocalAxisDirection axis)
|
||||
{
|
||||
switch (axis)
|
||||
@ -203,6 +247,26 @@ namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
throw new InvalidOperationException("模型局部第三轴不是标准正交轴,无法确定局部轴约定。");
|
||||
}
|
||||
|
||||
private double ResolveLocalAxisScale(int localAxisIndex, double forwardSize, double sideSize, double upSize)
|
||||
{
|
||||
if (MatchesAxis(ForwardAxis, localAxisIndex, out _))
|
||||
{
|
||||
return forwardSize;
|
||||
}
|
||||
|
||||
if (MatchesAxis(UpAxis, localAxisIndex, out _))
|
||||
{
|
||||
return upSize;
|
||||
}
|
||||
|
||||
if (MatchesAxis(SideAxis, localAxisIndex, out _))
|
||||
{
|
||||
return sideSize;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("无法为模型局部轴解析缩放尺寸。");
|
||||
}
|
||||
|
||||
private static bool IsApproximately(Vector3 vector, double x, double y, double z)
|
||||
{
|
||||
return Math.Abs(vector.X - x) < 1e-6 &&
|
||||
|
||||
@ -168,7 +168,7 @@ namespace NavisworksTransport.Utils
|
||||
previousPoint,
|
||||
currentPoint,
|
||||
nextPoint,
|
||||
ModelAxisConvention.CreateDefaultForHost(CoordinateSystemType.ZUp),
|
||||
ModelAxisConvention.CreateRailAssetConvention(),
|
||||
out linearTransform);
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ namespace NavisworksTransport.Utils
|
||||
previousPoint,
|
||||
currentPoint,
|
||||
nextPoint,
|
||||
ModelAxisConvention.CreateDefaultForHost(CoordinateSystemType.ZUp),
|
||||
ModelAxisConvention.CreateRailAssetConvention(),
|
||||
out rotation);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user