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