重构虚拟物体管理器;修复碰撞历史列表自动移动物体的bug
This commit is contained in:
parent
1b26e7b640
commit
eec957ad2e
@ -345,6 +345,22 @@ namespace NavisworksTransport.Commands
|
||||
{
|
||||
UpdateProgress(92, "生成默认路径截图...");
|
||||
|
||||
// 记录截图前虚拟物体实际位置和朝向
|
||||
var virtualObject = VirtualObjectManager.Instance.CurrentVirtualObject;
|
||||
if (virtualObject != null)
|
||||
{
|
||||
var bounds = virtualObject.BoundingBox();
|
||||
var actualYaw = ModelItemTransformHelper.GetYawFromTransform(virtualObject.Transform);
|
||||
var pam = PathAnimationManager.GetInstance();
|
||||
LogManager.Info(string.Format("[默认截图前] 虚拟物体实际位置: ({0:F2},{1:F2},{2:F2}), 实际朝向: {3:F2}°, PAM记录朝向: {4:F2}°",
|
||||
bounds.Center.X, bounds.Center.Y, bounds.Min.Z,
|
||||
actualYaw * 180 / Math.PI, pam.CurrentYaw * 180 / Math.PI));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[默认截图前] 无法获取虚拟物体");
|
||||
}
|
||||
|
||||
// 获取当前视窗尺寸
|
||||
var generator = new NavigationMapGenerator();
|
||||
var viewportSize = generator.GetCurrentViewportSize();
|
||||
@ -359,6 +375,18 @@ namespace NavisworksTransport.Commands
|
||||
System.Drawing.Imaging.ImageFormat.Jpeg,
|
||||
"overview"
|
||||
);
|
||||
|
||||
// 记录截图后虚拟物体实际位置和朝向
|
||||
virtualObject = VirtualObjectManager.Instance.CurrentVirtualObject;
|
||||
if (virtualObject != null)
|
||||
{
|
||||
var bounds = virtualObject.BoundingBox();
|
||||
var actualYaw = ModelItemTransformHelper.GetYawFromTransform(virtualObject.Transform);
|
||||
var pam = PathAnimationManager.GetInstance();
|
||||
LogManager.Info(string.Format("[默认截图后] 虚拟物体实际位置: ({0:F2},{1:F2},{2:F2}), 实际朝向: {3:F2}°, PAM记录朝向: {4:F2}°",
|
||||
bounds.Center.X, bounds.Center.Y, bounds.Min.Z,
|
||||
actualYaw * 180 / Math.PI, pam.CurrentYaw * 180 / Math.PI));
|
||||
}
|
||||
|
||||
if (screenshotPath != null)
|
||||
{
|
||||
|
||||
@ -412,15 +412,13 @@ namespace NavisworksTransport
|
||||
ModelItem objectObject = null;
|
||||
if (testInfo.IsVirtualObject)
|
||||
{
|
||||
// 显示虚拟物体
|
||||
// 创建虚拟物体(保留现有变换如果尺寸相同)
|
||||
var modelToMeters = UnitsConverter.GetUnitsToMetersConversionFactor();
|
||||
VirtualObjectManager.Instance.ShowVirtualObject(
|
||||
objectObject = VirtualObjectManager.Instance.CreateVirtualObject(
|
||||
testInfo.VirtualObjectLength * modelToMeters,
|
||||
testInfo.VirtualObjectWidth * modelToMeters,
|
||||
testInfo.VirtualObjectHeight * modelToMeters
|
||||
);
|
||||
objectObject = VirtualObjectManager.Instance.CurrentVirtualObject
|
||||
?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 显示虚拟物体失败");
|
||||
) ?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 获取虚拟物体失败");
|
||||
}
|
||||
else if (testInfo.ObjectModelIndex.HasValue && !string.IsNullOrEmpty(testInfo.ObjectPathId))
|
||||
{
|
||||
@ -446,8 +444,10 @@ namespace NavisworksTransport
|
||||
throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法重建物体对象: IsVirtualObject={testInfo.IsVirtualObject}, ObjectModelIndex={testInfo.ObjectModelIndex}, ObjectPathId={testInfo.ObjectPathId}");
|
||||
}
|
||||
|
||||
// 如果是虚拟物体,将其移动到路径起点
|
||||
if (testInfo.IsVirtualObject && !string.IsNullOrEmpty(testInfo.RouteId))
|
||||
// 如果是虚拟物体且是新创建的(不是已存在的),将其移动到路径起点
|
||||
// 注意:如果虚拟物体已存在(动画刚结束),保持当前位置(终点),不要移动到起点
|
||||
if (testInfo.IsVirtualObject && !string.IsNullOrEmpty(testInfo.RouteId) &&
|
||||
!VirtualObjectManager.Instance.IsVirtualObjectActive)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -471,6 +471,10 @@ namespace NavisworksTransport
|
||||
LogManager.Warning($"[LoadClashDetectiveResultsFromDatabase] 移动虚拟物体到起点失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else if (testInfo.IsVirtualObject && VirtualObjectManager.Instance.IsVirtualObjectActive)
|
||||
{
|
||||
LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 虚拟物体已存在,保持当前位置(终点),不移动到起点");
|
||||
}
|
||||
|
||||
// 3. 从数据库读取被撞物体信息(包含碰撞时运动物体的位置和朝向)
|
||||
var collisionObjectsSql = @"
|
||||
|
||||
@ -3,21 +3,23 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using NavisworksTransport.Utils;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 虚拟物体管理器 - 负责创建和管理虚拟物体几何体
|
||||
/// 通过追加预制的单位立方体NWC文件并缩放来创建指定尺寸的虚拟物体
|
||||
/// 设计原则:
|
||||
/// 1. 虚拟物体只创建一次(创建会载入模型,开销大)
|
||||
/// 2. 不用时可以隐藏,或移动到CAD原始位置(不改变尺寸)
|
||||
/// 3. 移动位置和朝向时,只使用变换,不修改尺寸
|
||||
/// 4. 修改尺寸只在创建或尺寸参数变更时进行(会触发文档更新事件)
|
||||
/// </summary>
|
||||
public class VirtualObjectManager
|
||||
{
|
||||
private static VirtualObjectManager _instance;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 单例实例
|
||||
/// </summary>
|
||||
public static VirtualObjectManager Instance
|
||||
{
|
||||
get
|
||||
@ -39,28 +41,14 @@ namespace NavisworksTransport.Core
|
||||
private ModelItem _virtualObjectModelItem;
|
||||
private Model _virtualObjectModel;
|
||||
private bool _isVirtualObjectActive;
|
||||
|
||||
// 🔥 新增:标记是否正在更新虚拟物体,用于避免触发缓存重建
|
||||
private bool _isUpdatingVirtualObject = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在更新虚拟物体(用于外部检测是否应该跳过缓存重建)
|
||||
/// </summary>
|
||||
public bool IsUpdatingVirtualObject => _isUpdatingVirtualObject;
|
||||
|
||||
// 🔥 记住虚拟物体的尺寸变换参数(避免动态计算)
|
||||
private double _currentLengthMeters = 0;
|
||||
private double _currentWidthMeters = 0;
|
||||
private double _currentHeightMeters = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 当前虚拟物体ModelItem
|
||||
/// </summary>
|
||||
public ModelItem CurrentVirtualObject => _virtualObjectModelItem;
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟物体是否激活
|
||||
/// </summary>
|
||||
public bool IsVirtualObjectActive => _isVirtualObjectActive;
|
||||
|
||||
private VirtualObjectManager()
|
||||
@ -68,384 +56,380 @@ namespace NavisworksTransport.Core
|
||||
_isVirtualObjectActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示虚拟物体
|
||||
/// </summary>
|
||||
/// <param name="lengthMeters">长度(米)</param>
|
||||
/// <param name="widthMeters">宽度(米)</param>
|
||||
/// <param name="heightMeters">高度(米)</param>
|
||||
public void ShowVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
|
||||
#region 1. 创建(只执行一次,开销大)
|
||||
|
||||
public ModelItem CreateVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
// 🔥 设置标志,防止文档变化事件触发缓存重建
|
||||
_isUpdatingVirtualObject = true;
|
||||
|
||||
try
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 检查虚拟物体模型是否已存在
|
||||
if (_virtualObjectModel != null)
|
||||
// 检查是否已存在且尺寸相同
|
||||
if (_virtualObjectModel != null &&
|
||||
Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) >= 0 &&
|
||||
Math.Abs(_currentLengthMeters - lengthMeters) < 0.001 &&
|
||||
Math.Abs(_currentWidthMeters - widthMeters) < 0.001 &&
|
||||
Math.Abs(_currentHeightMeters - heightMeters) < 0.001)
|
||||
{
|
||||
int currentIndex = doc.Models.IndexOf(_virtualObjectModel);
|
||||
if (currentIndex >= 0)
|
||||
{
|
||||
// 模型存在,显示它并更新尺寸
|
||||
LogManager.Info($"虚拟物体模型已存在(索引: {currentIndex}),显示并更新尺寸");
|
||||
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
doc.Models.SetHidden(modelItems, false);
|
||||
|
||||
// 获取实际的几何体项
|
||||
_virtualObjectModelItem = _virtualObjectModel.RootItem;
|
||||
var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem);
|
||||
if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem))
|
||||
{
|
||||
_virtualObjectModelItem = geometryItem;
|
||||
}
|
||||
|
||||
// 清除覆盖变换(之前动画移动和旋转的累积)
|
||||
modelItems.Clear();
|
||||
modelItems.Add(_virtualObjectModelItem);
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
|
||||
// 重置变换并缩放到目标尺寸
|
||||
ResetVirtualObjectTransform();
|
||||
ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
_isVirtualObjectActive = true;
|
||||
LogManager.Info($"虚拟物体更新成功");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"已保存的虚拟物体模型不在文档中,需要重新创建");
|
||||
}
|
||||
LogManager.Info($"虚拟物体已存在且尺寸相同,直接返回");
|
||||
_isVirtualObjectActive = true;
|
||||
return _virtualObjectModelItem;
|
||||
}
|
||||
|
||||
// 模型不存在,创建新的
|
||||
CreateVirtualObjectInternal(doc, lengthMeters, widthMeters, heightMeters);
|
||||
// 检查是否已存在但尺寸不同
|
||||
if (_virtualObjectModel != null &&
|
||||
Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) >= 0)
|
||||
{
|
||||
LogManager.Info($"虚拟物体已存在但尺寸不同,更新尺寸");
|
||||
UpdateVirtualObjectSize(lengthMeters, widthMeters, heightMeters);
|
||||
_isVirtualObjectActive = true;
|
||||
return _virtualObjectModelItem;
|
||||
}
|
||||
|
||||
// 创建新的虚拟物体
|
||||
LogManager.Info($"=== 创建虚拟物体 ===");
|
||||
LogManager.Info($"目标尺寸: {lengthMeters:F2}m x {widthMeters:F2}m x {heightMeters:F2}m");
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
var unitCubePath = GetUnitCubeFilePath();
|
||||
|
||||
if (string.IsNullOrEmpty(unitCubePath) || !File.Exists(unitCubePath))
|
||||
{
|
||||
throw new FileNotFoundException($"找不到单位立方体文件: {unitCubePath}");
|
||||
}
|
||||
|
||||
int modelCountBefore = doc.Models.Count;
|
||||
if (!doc.TryAppendFile(unitCubePath))
|
||||
{
|
||||
throw new InvalidOperationException($"无法追加文件: {unitCubePath}");
|
||||
}
|
||||
|
||||
int modelCountAfter = doc.Models.Count;
|
||||
if (modelCountAfter <= modelCountBefore)
|
||||
{
|
||||
throw new InvalidOperationException("追加文件后模型数量未增加");
|
||||
}
|
||||
|
||||
_virtualObjectModel = doc.Models.Last();
|
||||
_virtualObjectModelItem = _virtualObjectModel.RootItem;
|
||||
|
||||
var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem);
|
||||
if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem))
|
||||
{
|
||||
_virtualObjectModelItem = geometryItem;
|
||||
}
|
||||
|
||||
_currentLengthMeters = lengthMeters;
|
||||
_currentWidthMeters = widthMeters;
|
||||
_currentHeightMeters = heightMeters;
|
||||
ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
_isVirtualObjectActive = true;
|
||||
LogManager.Info($"虚拟物体创建成功");
|
||||
|
||||
return _virtualObjectModelItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"显示虚拟物体失败: {ex.Message}");
|
||||
LogManager.Error($"创建虚拟物体失败: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 🔥 清除标志
|
||||
_isUpdatingVirtualObject = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏虚拟物体
|
||||
/// </summary>
|
||||
#endregion
|
||||
|
||||
#region 2. 显示/隐藏
|
||||
|
||||
public void ShowVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
if (_virtualObjectModel == null ||
|
||||
Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) < 0)
|
||||
{
|
||||
CreateVirtualObject(lengthMeters, widthMeters, heightMeters);
|
||||
return;
|
||||
}
|
||||
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
Application.ActiveDocument.Models.SetHidden(modelItems, false);
|
||||
_isVirtualObjectActive = true;
|
||||
LogManager.Info("虚拟物体已显示");
|
||||
}
|
||||
|
||||
public void HideVirtualObject()
|
||||
{
|
||||
if (_virtualObjectModelItem == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_virtualObjectModelItem != null)
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
doc.Models.SetHidden(modelItems, true);
|
||||
|
||||
LogManager.Info($"已隐藏虚拟物体模型");
|
||||
}
|
||||
|
||||
// 隐藏时设置为非激活状态,但保留模型引用
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
Application.ActiveDocument.Models.SetHidden(modelItems, true);
|
||||
_isVirtualObjectActive = false;
|
||||
LogManager.Info("虚拟物体已隐藏");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"隐藏虚拟物体失败: {ex.Message}");
|
||||
_isVirtualObjectActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建虚拟物体(内部方法)
|
||||
/// </summary>
|
||||
private void CreateVirtualObjectInternal(Document doc, double lengthMeters, double widthMeters, double heightMeters)
|
||||
#endregion
|
||||
|
||||
#region 3. 移动位置和朝向
|
||||
|
||||
public void MoveVirtualObject(Point3D position, double yawRadians)
|
||||
{
|
||||
LogManager.Info($"=== 创建虚拟物体 ===");
|
||||
LogManager.Info($"目标尺寸: {lengthMeters:F2}m × {widthMeters:F2}m × {heightMeters:F2}m");
|
||||
if (_virtualObjectModelItem == null) return;
|
||||
|
||||
// 加载新的虚拟物体模型
|
||||
LoadNewVirtualObjectModel(doc);
|
||||
|
||||
// 获取实际的几何体项
|
||||
_virtualObjectModelItem = _virtualObjectModel.RootItem;
|
||||
var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem);
|
||||
if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem))
|
||||
try
|
||||
{
|
||||
_virtualObjectModelItem = geometryItem;
|
||||
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($"虚拟物体已移动");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"移动虚拟物体失败: {ex.Message}");
|
||||
}
|
||||
|
||||
// 重置变换并缩放到目标尺寸
|
||||
ResetVirtualObjectTransform();
|
||||
ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
// 设置状态
|
||||
_isVirtualObjectActive = true;
|
||||
|
||||
LogManager.Info($"虚拟物体创建成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载新的虚拟物体模型
|
||||
/// </summary>
|
||||
private void LoadNewVirtualObjectModel(Document doc)
|
||||
public void ResetToCADPosition()
|
||||
{
|
||||
LogManager.Info($"需要加载新的虚拟物体模型");
|
||||
if (_virtualObjectModelItem == null) return;
|
||||
|
||||
// 1. 获取单位立方体文件路径
|
||||
var unitCubePath = GetUnitCubeFilePath();
|
||||
if (string.IsNullOrEmpty(unitCubePath) || !File.Exists(unitCubePath))
|
||||
try
|
||||
{
|
||||
throw new FileNotFoundException($"找不到单位立方体文件: {unitCubePath}");
|
||||
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);
|
||||
|
||||
// 重新应用缩放
|
||||
var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
|
||||
var components = identity.Factor();
|
||||
components.Scale = currentScale;
|
||||
|
||||
Transform3D newTransform = components.Combine();
|
||||
doc.Models.OverridePermanentTransform(modelItems, newTransform, false);
|
||||
|
||||
LogManager.Info("虚拟物体已恢复到CAD原始位置");
|
||||
}
|
||||
|
||||
LogManager.Info($"单位立方体文件: {unitCubePath}");
|
||||
|
||||
// 2. 记录追加前的模型数量
|
||||
int modelCountBefore = doc.Models.Count;
|
||||
LogManager.Info($"追加前模型数量: {modelCountBefore}");
|
||||
|
||||
// 3. 追加单位立方体文件
|
||||
if (!doc.TryAppendFile(unitCubePath))
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException($"无法追加文件: {unitCubePath}");
|
||||
LogManager.Error($"恢复虚拟物体失败: {ex.Message}");
|
||||
}
|
||||
|
||||
// 4. 验证并获取新追加的模型
|
||||
int modelCountAfter = doc.Models.Count;
|
||||
LogManager.Info($"追加后模型数量: {modelCountAfter}");
|
||||
|
||||
if (modelCountAfter <= modelCountBefore)
|
||||
{
|
||||
throw new InvalidOperationException("追加文件后模型数量未增加");
|
||||
}
|
||||
|
||||
// 保存模型引用(最后一个模型就是刚追加的)
|
||||
_virtualObjectModel = doc.Models.Last();
|
||||
|
||||
LogManager.Info($"虚拟物体模型: {_virtualObjectModel.FileName}");
|
||||
LogManager.Info($"虚拟物体根项: {_virtualObjectModel.RootItem.DisplayName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// 重置虚拟物体变换为单位矩阵(公开方法,供批处理使用)
|
||||
/// </summary>
|
||||
public void ResetVirtualObjectTransform()
|
||||
#endregion
|
||||
|
||||
#region 4. 修改尺寸
|
||||
|
||||
public void UpdateVirtualObjectSize(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
if (_virtualObjectModel == null) return;
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
_isUpdatingVirtualObject = true;
|
||||
|
||||
// 创建单位变换矩阵
|
||||
Transform3D identityTransform = new Transform3D();
|
||||
Transform3DComponents identityComponents = identityTransform.Factor();
|
||||
|
||||
// 应用单位变换
|
||||
Units currentUnits = _virtualObjectModel.Units;
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, currentUnits, identityTransform, false);
|
||||
|
||||
LogManager.Info("已重置虚拟物体变换");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新应用当前记录的缩放(用于ResetPermanentTransform后恢复缩放)
|
||||
/// </summary>
|
||||
public void ReapplyCurrentScale()
|
||||
{
|
||||
if (_currentLengthMeters > 0 && _currentWidthMeters > 0 && _currentHeightMeters > 0)
|
||||
try
|
||||
{
|
||||
LogManager.Info($"重新应用虚拟物体缩放: {_currentLengthMeters:F2}m × {_currentWidthMeters:F2}m × {_currentHeightMeters:F2}m");
|
||||
ScaleVirtualObject(_currentLengthMeters, _currentWidthMeters, _currentHeightMeters);
|
||||
_currentLengthMeters = lengthMeters;
|
||||
_currentWidthMeters = widthMeters;
|
||||
_currentHeightMeters = heightMeters;
|
||||
|
||||
// 获取当前位置和旋转
|
||||
var currentTransform = _virtualObjectModelItem.Transform;
|
||||
var currentComponents = currentTransform.Factor();
|
||||
var currentTranslation = currentComponents.Translation;
|
||||
var currentRotation = currentComponents.Rotation;
|
||||
|
||||
// 应用新缩放
|
||||
ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
// 如果之前有位置/旋转,重新应用
|
||||
bool hasTranslation = currentTranslation.X != 0 || currentTranslation.Y != 0 || currentTranslation.Z != 0;
|
||||
// 使用 ToAxisAndAngle 检查是否有旋转
|
||||
var rotationResult = currentRotation.ToAxisAndAngle();
|
||||
bool hasRotation = Math.Abs(rotationResult.Angle) > 0.001;
|
||||
if (hasTranslation || hasRotation)
|
||||
{
|
||||
var newTransform = _virtualObjectModelItem.Transform;
|
||||
var newComponents = newTransform.Factor();
|
||||
newComponents.Translation = currentTranslation;
|
||||
newComponents.Rotation = currentRotation;
|
||||
|
||||
Transform3D combinedTransform = newComponents.Combine();
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { _virtualObjectModelItem };
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, _virtualObjectModel.Units, combinedTransform, false);
|
||||
}
|
||||
|
||||
LogManager.Info($"虚拟物体尺寸已更新");
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
LogManager.Warning("无法重新应用缩放:当前尺寸记录无效");
|
||||
_isUpdatingVirtualObject = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缩放虚拟物体到目标尺寸
|
||||
/// 使用DocumentModels.SetModelUnitsAndTransform方法进行模型级缩放
|
||||
/// </summary>
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
private void ScaleVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
if (_virtualObjectModel == null || _virtualObjectModelItem == null) return;
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 🔥 记住尺寸参数(避免动态计算)
|
||||
_currentLengthMeters = lengthMeters;
|
||||
_currentWidthMeters = widthMeters;
|
||||
_currentHeightMeters = heightMeters;
|
||||
|
||||
// 获取单位转换因子(米到模型单位)
|
||||
double metersToUnits = Utils.UnitsConverter.GetMetersToUnitsConversionFactor(doc.Units);
|
||||
|
||||
// 🔥 对于虚拟物体,直接应用缩放比例(不动态读取当前尺寸)
|
||||
// 原因:虚拟物体可能被旋转,导致包围盒尺寸不准确
|
||||
// 单位立方体是 0.01m × 0.01m × 0.01m
|
||||
// X方向 = 物体长度(前进方向),Y方向 = 物体宽度(侧面),Z方向 = 物体高度
|
||||
double baseSizeMeters = 0.01;
|
||||
double scaleX = lengthMeters / baseSizeMeters; // X方向 = 物体长度(前进方向)
|
||||
double scaleY = widthMeters / baseSizeMeters; // Y方向 = 物体宽度(侧面)
|
||||
double scaleZ = heightMeters / baseSizeMeters; // Z方向 = 物体高度
|
||||
double scaleX = lengthMeters / baseSizeMeters;
|
||||
double scaleY = widthMeters / baseSizeMeters;
|
||||
double scaleZ = heightMeters / baseSizeMeters;
|
||||
|
||||
LogManager.Info($"目标尺寸: 长度={lengthMeters:F2}m, 宽度={widthMeters:F2}m, 高度={heightMeters:F2}m");
|
||||
LogManager.Info($"缩放比例: X(长度)={scaleX:F2}, Y(宽度)={scaleY:F2}, Z(高度)={scaleZ:F2}");
|
||||
|
||||
// 使用Transform3DComponents进行缩放
|
||||
// 获取当前模型的变换并分解
|
||||
Transform3D currentTransform = _virtualObjectModel.Transform;
|
||||
Transform3DComponents transformComponents = currentTransform.Factor();
|
||||
|
||||
// 获取当前值
|
||||
Vector3D currentTranslation = transformComponents.Translation;
|
||||
Rotation3D currentRotation = transformComponents.Rotation;
|
||||
Vector3D currentScale = transformComponents.Scale;
|
||||
|
||||
LogManager.Info($"当前变换 - 平移: ({currentTranslation.X:F2}, {currentTranslation.Y:F2}, {currentTranslation.Z:F2})");
|
||||
LogManager.Info($"当前变换 - 缩放: ({currentScale.X:F2}, {currentScale.Y:F2}, {currentScale.Z:F2})");
|
||||
|
||||
// 🔥 直接应用新的缩放值(不乘以当前缩放,避免累积)
|
||||
var currentTransform = _virtualObjectModel.Transform;
|
||||
var transformComponents = currentTransform.Factor();
|
||||
transformComponents.Scale = new Vector3D(scaleX, scaleY, scaleZ);
|
||||
|
||||
// 组合成新的变换
|
||||
Transform3D newTransform = transformComponents.Combine();
|
||||
|
||||
// 获取当前模型单位
|
||||
Units currentUnits = _virtualObjectModel.Units;
|
||||
|
||||
// 应用新的变换
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, currentUnits, newTransform, false);
|
||||
|
||||
// 验证缩放结果
|
||||
var newBoundingBox = _virtualObjectModelItem.BoundingBox();
|
||||
double newLength = newBoundingBox.Max.X - newBoundingBox.Min.X;
|
||||
double newWidth = newBoundingBox.Max.Y - newBoundingBox.Min.Y;
|
||||
double newHeight = newBoundingBox.Max.Z - newBoundingBox.Min.Z;
|
||||
|
||||
double newLengthMeters = newLength / metersToUnits;
|
||||
double newWidthMeters = newWidth / metersToUnits;
|
||||
double newHeightMeters = newHeight / metersToUnits;
|
||||
|
||||
LogManager.Info($"缩放后尺寸: {newLengthMeters:F2}m × {newWidthMeters:F2}m × {newHeightMeters:F2}m");
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, _virtualObjectModel.Units, newTransform, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除虚拟物体(使用 TryRemoveFile 真正删除模型)
|
||||
/// 从Transform中提取Yaw角度(简化版本)
|
||||
/// </summary>
|
||||
public void RemoveVirtualObject()
|
||||
private double GetYawFromTransform(Transform3D transform)
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
// 使用ModelItemTransformHelper中的方法
|
||||
return ModelItemTransformHelper.GetYawFromTransform(transform);
|
||||
}
|
||||
catch { }
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理虚拟物体(用于程序退出或切换文档时)
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_virtualObjectModel != null)
|
||||
{
|
||||
// 动态查找模型索引
|
||||
int currentIndex = doc.Models.IndexOf(_virtualObjectModel);
|
||||
|
||||
if (currentIndex >= 0)
|
||||
var doc = Application.ActiveDocument;
|
||||
int index = doc.Models.IndexOf(_virtualObjectModel);
|
||||
if (index >= 0)
|
||||
{
|
||||
// 使用 TryRemoveFile 真正删除模型
|
||||
bool removed = doc.TryRemoveFile(currentIndex);
|
||||
|
||||
if (removed)
|
||||
{
|
||||
LogManager.Info($"已删除虚拟物体模型(索引: {currentIndex})");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"删除虚拟物体模型失败(索引: {currentIndex})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"虚拟物体模型不在文档中,无法删除");
|
||||
doc.TryRemoveFile(index);
|
||||
}
|
||||
}
|
||||
|
||||
// 清理引用
|
||||
_virtualObjectModel = null;
|
||||
_virtualObjectModelItem = null;
|
||||
_isVirtualObjectActive = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"删除虚拟物体失败: {ex.Message}");
|
||||
LogManager.Error($"清理虚拟物体失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_virtualObjectModel = null;
|
||||
_virtualObjectModelItem = null;
|
||||
_isVirtualObjectActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单位立方体文件路径
|
||||
/// </summary>
|
||||
private ModelItem FindFirstGeometryItem(ModelItem item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
if (item.HasGeometry) return item;
|
||||
foreach (var child in item.Children)
|
||||
{
|
||||
var result = FindFirstGeometryItem(child);
|
||||
if (result != null) return result;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private string GetUnitCubeFilePath()
|
||||
{
|
||||
// 方法1:从插件目录获取
|
||||
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
|
||||
var pluginDir = Path.GetDirectoryName(assemblyLocation);
|
||||
|
||||
// 尝试多个可能的位置(现在统一放在resources目录下)
|
||||
var possiblePaths = new[]
|
||||
string pluginDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
string[] possiblePaths = new[]
|
||||
{
|
||||
Path.Combine(pluginDir, "resources", "unit_cube.nwc"),
|
||||
// 开发时的备用位置
|
||||
Path.Combine(pluginDir, "..", "..", "resources", "unit_cube.nwc"),
|
||||
@"c:\Users\Tellme\apps\NavisworksTransport\resources\unit_cube.nwc"
|
||||
};
|
||||
|
||||
foreach (var path in possiblePaths)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(path);
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
LogManager.Info($"找到单位立方体文件: {fullPath}");
|
||||
return fullPath;
|
||||
}
|
||||
if (File.Exists(path))
|
||||
return path;
|
||||
}
|
||||
|
||||
LogManager.Warning($"在以下位置未找到单位立方体文件:");
|
||||
foreach (var path in possiblePaths)
|
||||
{
|
||||
LogManager.Warning($" - {Path.GetFullPath(path)}");
|
||||
}
|
||||
|
||||
return null;
|
||||
return possiblePaths[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找第一个包含几何体的ModelItem
|
||||
/// </summary>
|
||||
private ModelItem FindFirstGeometryItem(ModelItem root)
|
||||
{
|
||||
if (root.HasGeometry)
|
||||
return root;
|
||||
|
||||
foreach (var child in root.Children)
|
||||
{
|
||||
var result = FindFirstGeometryItem(child);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
RemoveVirtualObject();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -2403,7 +2403,29 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
if (collisionObject?.ModelItem == null) return;
|
||||
|
||||
// 从历史记录中获取运动物体
|
||||
var animatedObject = SelectedClashDetectiveResult?.AnimatedObject;
|
||||
var selectedResult = SelectedClashDetectiveResult;
|
||||
var animatedObject = selectedResult?.AnimatedObject;
|
||||
|
||||
// 如果是虚拟物体且尚未创建,现在创建它
|
||||
if (selectedResult?.Record?.IsVirtualObject == true && animatedObject == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
double unitsToMeters = UnitsConverter.GetUnitsToMetersConversionFactor(Autodesk.Navisworks.Api.Application.ActiveDocument.Units);
|
||||
// 创建并显示虚拟物体(尺寸从模型单位转换为米)
|
||||
animatedObject = VirtualObjectManager.Instance.CreateVirtualObject(
|
||||
selectedResult.VirtualObjectLength * unitsToMeters,
|
||||
selectedResult.VirtualObjectWidth * unitsToMeters,
|
||||
selectedResult.VirtualObjectHeight * unitsToMeters);
|
||||
selectedResult.AnimatedObject = animatedObject;
|
||||
LogManager.Info($"[碰撞构件] 创建虚拟物体并聚焦: {selectedResult.VirtualObjectLength:F2}x{selectedResult.VirtualObjectWidth:F2}x{selectedResult.VirtualObjectHeight:F2}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[碰撞构件] 创建虚拟物体失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
if (animatedObject == null)
|
||||
{
|
||||
LogManager.Warning($"[碰撞构件] 未找到运动物体,仅聚焦到被撞对象: {collisionObject.DisplayName}");
|
||||
@ -2434,12 +2456,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
collisionObject.Item1YawRadians,
|
||||
collisionObject.HasPositionInfo);
|
||||
|
||||
// 🔥 关键:如果是虚拟物体,重新应用缩放(因为MoveItemToPositionAndYaw会重置变换)
|
||||
if (VirtualObjectManager.Instance.IsVirtualObjectActive &&
|
||||
VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject)
|
||||
{
|
||||
VirtualObjectManager.Instance.ReapplyCurrentScale();
|
||||
}
|
||||
// 🔥 虚拟物体缩放已通过MoveItemToPositionAndYawWithCurrentScale保留
|
||||
|
||||
UpdateMainStatus($"已聚焦到碰撞构件: {collisionObject.DisplayName}");
|
||||
LogManager.Info($"聚焦到碰撞构件: {collisionObject.DisplayName}");
|
||||
@ -3064,28 +3081,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
var resultViewModel = new ClashDetectiveResultViewModel(record, RefreshClashDetectiveResultsList);
|
||||
|
||||
// 加载运动物体(Item1)
|
||||
// 虚拟物体:只记录尺寸(数据库中是模型单位),等用户点击时再创建
|
||||
// 真实物体:尝试解析PathId获取引用
|
||||
if (record.IsVirtualObject)
|
||||
{
|
||||
// 使用虚拟物体,设置历史记录中的尺寸(数据库中是模型单位)
|
||||
resultViewModel.VirtualObjectLength = record.VirtualObjectLength;
|
||||
resultViewModel.VirtualObjectWidth = record.VirtualObjectWidth;
|
||||
resultViewModel.VirtualObjectHeight = record.VirtualObjectHeight;
|
||||
|
||||
// 显示对应尺寸的虚拟物体(ShowVirtualObject需要米单位)
|
||||
try
|
||||
{
|
||||
double unitsToMeters = UnitsConverter.GetUnitsToMetersConversionFactor(Autodesk.Navisworks.Api.Application.ActiveDocument.Units);
|
||||
VirtualObjectManager.Instance.ShowVirtualObject(
|
||||
record.VirtualObjectLength * unitsToMeters,
|
||||
record.VirtualObjectWidth * unitsToMeters,
|
||||
record.VirtualObjectHeight * unitsToMeters);
|
||||
resultViewModel.AnimatedObject = VirtualObjectManager.Instance.CurrentVirtualObject;
|
||||
LogManager.Info($"[碰撞历史] 使用虚拟物体(尺寸:{record.VirtualObjectLength:F2}x{record.VirtualObjectWidth:F2}x{record.VirtualObjectHeight:F2}): {resultViewModel.AnimatedObject?.DisplayName ?? "未找到"} for TestName={record.TestName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[碰撞历史] 显示虚拟物体失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else if (record.ObjectModelIndex.HasValue && !string.IsNullOrEmpty(record.ObjectPathId))
|
||||
{
|
||||
|
||||
@ -62,8 +62,22 @@ namespace NavisworksTransport.Utils
|
||||
item1Position.Z - halfHeight
|
||||
);
|
||||
|
||||
// 检查是否是虚拟物体
|
||||
bool isVirtual = VirtualObjectManager.Instance.IsVirtualObjectActive &&
|
||||
VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
|
||||
|
||||
// 使用工具方法从CAD原始状态移动到目标位置
|
||||
ModelItemTransformHelper.MoveItemToPositionAndYaw(animatedObject, targetGroundPosition, item1YawRadians);
|
||||
if (isVirtual)
|
||||
{
|
||||
// 虚拟物体:保留当前缩放
|
||||
ModelItemTransformHelper.MoveItemToPositionAndYawWithCurrentScale(
|
||||
animatedObject, targetGroundPosition, item1YawRadians);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 普通物体:标准移动
|
||||
ModelItemTransformHelper.MoveItemToPositionAndYaw(animatedObject, targetGroundPosition, item1YawRadians);
|
||||
}
|
||||
|
||||
LogManager.Info(string.Format("运动物体已移动到碰撞位置: ({0:F2}, {1:F2}, {2:F2}), 朝向: {3:F2}°",
|
||||
targetGroundPosition.X, targetGroundPosition.Y, targetGroundPosition.Z,
|
||||
@ -116,8 +130,25 @@ namespace NavisworksTransport.Utils
|
||||
|
||||
try
|
||||
{
|
||||
ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
|
||||
LogManager.Info(string.Format("动画物体已恢复到原始状态: {0}", animatedObject.DisplayName));
|
||||
// 检查是否是虚拟物体
|
||||
bool isVirtual = VirtualObjectManager.Instance.IsVirtualObjectActive &&
|
||||
VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
|
||||
|
||||
if (isVirtual)
|
||||
{
|
||||
// 虚拟物体:使用带当前缩放的移动方法
|
||||
ModelItemTransformHelper.MoveItemToPositionAndYawWithCurrentScale(
|
||||
animatedObject, state.Position, state.YawRadians);
|
||||
LogManager.Info(string.Format("虚拟物体已恢复到原始状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°",
|
||||
animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
|
||||
state.YawRadians * 180 / Math.PI));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 普通物体:使用标准恢复
|
||||
ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
|
||||
LogManager.Info(string.Format("动画物体已恢复到原始状态: {0}", animatedObject.DisplayName));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -281,10 +281,25 @@ namespace NavisworksTransport.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从状态快照恢复物体位置
|
||||
/// 先回到CAD原始位置,再移动到保存的位置
|
||||
/// 从状态快照恢复物体位置和朝向(标准版本,会重置缩放)
|
||||
/// </summary>
|
||||
public static void RestoreObjectState(ModelItem item, ObjectStateSnapshot state)
|
||||
{
|
||||
RestoreObjectStateInternal(item, state, preserveScale: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从状态快照恢复物体位置和朝向(保留缩放版本,用于虚拟物体)
|
||||
/// </summary>
|
||||
public static void RestoreObjectStateWithScale(ModelItem item, ObjectStateSnapshot state)
|
||||
{
|
||||
RestoreObjectStateInternal(item, state, preserveScale: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从状态快照恢复物体位置的内部实现
|
||||
/// </summary>
|
||||
private static void RestoreObjectStateInternal(ModelItem item, ObjectStateSnapshot state, bool preserveScale)
|
||||
{
|
||||
if (item == null || state == null) return;
|
||||
|
||||
@ -340,5 +355,72 @@ namespace NavisworksTransport.Utils
|
||||
|
||||
doc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将物体移动到指定位置和朝向,同时保持当前缩放(专为虚拟物体设计)
|
||||
/// </summary>
|
||||
public static void MoveItemToPositionAndYawWithCurrentScale(ModelItem item, Point3D targetPosition, double targetYaw)
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { item };
|
||||
|
||||
// 获取当前变换中的缩放
|
||||
var currentTransform = item.Transform;
|
||||
var currentComponents = currentTransform.Factor();
|
||||
var currentScale = currentComponents.Scale;
|
||||
|
||||
// 重置到CAD原始状态
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
|
||||
// 获取CAD原始状态
|
||||
var originalBounds = item.BoundingBox();
|
||||
var originalGroundPos = new Point3D(
|
||||
originalBounds.Center.X,
|
||||
originalBounds.Center.Y,
|
||||
originalBounds.Min.Z
|
||||
);
|
||||
var originalYaw = GetYawFromTransform(item.Transform);
|
||||
|
||||
// 计算从CAD原始位置到目标位置的增量
|
||||
var deltaPos = new Vector3D(
|
||||
targetPosition.X - originalGroundPos.X,
|
||||
targetPosition.Y - originalGroundPos.Y,
|
||||
targetPosition.Z - originalGroundPos.Z
|
||||
);
|
||||
double deltaYaw = targetYaw - originalYaw;
|
||||
|
||||
// 构建变换组件,保留原有缩放
|
||||
var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
|
||||
var components = identity.Factor();
|
||||
components.Scale = currentScale; // 保留当前缩放
|
||||
|
||||
if (Math.Abs(deltaYaw) > 0.001)
|
||||
{
|
||||
components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
|
||||
}
|
||||
|
||||
// 计算平移(考虑旋转带来的位置偏移)
|
||||
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.Translation = new Vector3D(
|
||||
targetPosition.X - rotatedX,
|
||||
targetPosition.Y - rotatedY,
|
||||
deltaPos.Z
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
components.Translation = deltaPos;
|
||||
}
|
||||
|
||||
// 应用组合变换
|
||||
Transform3D transform = components.Combine();
|
||||
doc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,7 +373,7 @@ namespace NavisworksTransport.Utils
|
||||
Math.Max(boundingBox.Max.Y - boundingBox.Min.Y, boundingBox.Max.Z - boundingBox.Min.Z)
|
||||
);
|
||||
|
||||
LogManager.Info($"聚焦到模型元素: {modelItem.DisplayName}, 最大边: {maxDimension:F2}");
|
||||
LogManager.Debug($"聚焦到模型元素: {modelItem.DisplayName}, 最大边: {maxDimension:F2}");
|
||||
|
||||
// 3. 计算相机位置(使用模型标准视角方向)
|
||||
Point3D cameraPosition = CalculateCameraPosition(center, maxDimension, viewAngleDegrees, targetViewRatio);
|
||||
@ -382,7 +382,7 @@ namespace NavisworksTransport.Utils
|
||||
Vector3D upVector = doc.FrontRightTopViewUpVector;
|
||||
ApplyViewpoint(cameraPosition, center, upVector, useAlignDirection: true);
|
||||
|
||||
LogManager.Info($"视角已调整: 标准前右上视角, 目标占据视图{targetViewRatio:P0}");
|
||||
LogManager.Debug($"视角已调整: 标准前右上视角, 目标占据视图{targetViewRatio:P0}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user