184 lines
9.1 KiB
C#
184 lines
9.1 KiB
C#
using System;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Core;
|
||
using NavisworksTransport.Core.Animation;
|
||
using NavisworksTransport.Utils.CoordinateSystem;
|
||
|
||
namespace NavisworksTransport.Utils
|
||
{
|
||
/// <summary>
|
||
/// 碰撞场景辅助类
|
||
/// 提供碰撞场景还原和截图的通用功能
|
||
/// </summary>
|
||
public static class CollisionSceneHelper
|
||
{
|
||
/// <summary>
|
||
/// 将动画物体移动到碰撞位置并聚焦到碰撞场景
|
||
/// </summary>
|
||
/// <param name="collision">碰撞结果</param>
|
||
/// <param name="animatedObject">动画物体(运动物体)</param>
|
||
public static void MoveToCollisionAndFocus(CollisionResult collision, ModelItem animatedObject)
|
||
{
|
||
if (collision == null) return;
|
||
MoveToCollisionAndFocus(collision.Item2 ?? collision.Item1, animatedObject,
|
||
collision.AnimatedObjectTrackedPosition, collision.AnimatedObjectTrackedYawRadians, collision.AnimatedObjectTrackedRotation,
|
||
collision.AnimatedObjectHasTrackedRotation, collision.HasPositionInfo);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将动画物体移动到碰撞位置并聚焦到碰撞场景(通用版本)
|
||
/// </summary>
|
||
/// <param name="hitObject">被撞对象</param>
|
||
/// <param name="animatedObject">动画物体(运动物体)</param>
|
||
/// <param name="animatedObjectTrackedPosition">动画跟踪点位置</param>
|
||
/// <param name="animatedObjectTrackedYawRadians">动画跟踪点对应的碰撞朝向</param>
|
||
/// <param name="animatedObjectTrackedRotation">动画跟踪点对应的碰撞完整姿态</param>
|
||
/// <param name="animatedObjectHasTrackedRotation">是否有完整姿态</param>
|
||
/// <param name="hasPositionInfo">是否有位置信息</param>
|
||
public static void MoveToCollisionAndFocus(ModelItem hitObject, ModelItem animatedObject,
|
||
Point3D animatedObjectTrackedPosition, double animatedObjectTrackedYawRadians, Rotation3D animatedObjectTrackedRotation,
|
||
bool animatedObjectHasTrackedRotation, bool hasPositionInfo)
|
||
{
|
||
try
|
||
{
|
||
if (hitObject != null)
|
||
{
|
||
// 清除之前的高亮
|
||
ModelHighlightHelper.ClearAllHighlights();
|
||
|
||
// 高亮被撞对象(使用碰撞检测结果专用红色)
|
||
ModelHighlightHelper.HighlightItems(ModelHighlightHelper.ClashDetectiveResultsCategory, new[] { hitObject });
|
||
|
||
// 聚焦到被撞对象
|
||
ViewpointHelper.FocusOnModelItem(hitObject, ViewpointHelper.ViewpointStrategy.CollisionCloseUp);
|
||
|
||
LogManager.Info(string.Format("聚焦到被撞对象: {0}", hitObject.DisplayName));
|
||
}
|
||
|
||
// 移动动画物体到碰撞位置
|
||
if (animatedObject != null && hasPositionInfo && animatedObjectTrackedPosition != null)
|
||
{
|
||
var pam = PathAnimationManager.GetInstance();
|
||
bool useAnimationPipeline = pam != null &&
|
||
pam.ControlsAnimatedObject(animatedObject);
|
||
|
||
if (useAnimationPipeline)
|
||
{
|
||
pam.MoveAnimatedObjectToPose(
|
||
animatedObject,
|
||
animatedObjectTrackedPosition,
|
||
animatedObjectTrackedYawRadians,
|
||
animatedObjectTrackedRotation ?? Rotation3D.Identity,
|
||
animatedObjectHasTrackedRotation && animatedObjectTrackedRotation != null);
|
||
|
||
LogManager.Debug(string.Format(
|
||
"运动物体已通过动画链路移动到碰撞位置: 位置=({0:F2}, {1:F2}, {2:F2}), customRotation={3}",
|
||
animatedObjectTrackedPosition.X, animatedObjectTrackedPosition.Y, animatedObjectTrackedPosition.Z,
|
||
animatedObjectHasTrackedRotation && animatedObjectTrackedRotation != null));
|
||
}
|
||
else
|
||
{
|
||
throw new InvalidOperationException(
|
||
$"碰撞点恢复必须复用动画主链路,当前对象未受 PathAnimationManager 控制: {animatedObject.DisplayName}");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error(string.Format("移动并聚焦到碰撞位置失败: {0}", ex.Message), ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存动画物体当前状态
|
||
/// </summary>
|
||
/// <param name="animatedObject">动画物体</param>
|
||
/// <returns>状态快照</returns>
|
||
public static ModelItemTransformHelper.ObjectStateSnapshot SaveAnimatedObjectState(ModelItem animatedObject)
|
||
{
|
||
if (animatedObject == null) return null;
|
||
|
||
var pam = PathAnimationManager.GetInstance();
|
||
if (pam == null || !pam.ControlsAnimatedObject(animatedObject))
|
||
{
|
||
throw new InvalidOperationException(
|
||
$"保存碰撞场景前的动画物体状态必须复用 PathAnimationManager:对象 {animatedObject.DisplayName} 不受当前动画管理器控制。");
|
||
}
|
||
|
||
// 从 PathAnimationManager 获取当前实际姿态,不再退回工具层旧 yaw 快照语义。
|
||
var currentYaw = pam.CurrentYaw;
|
||
var currentRotation = pam.TrackedRotation;
|
||
var hasCustomRotation = pam.HasTrackedRotation;
|
||
var currentState = pam.GetObjectCurrentPosition(animatedObject);
|
||
pam.SaveObjectState(animatedObject);
|
||
|
||
var state = new ModelItemTransformHelper.ObjectStateSnapshot
|
||
{
|
||
Position = currentState.Position,
|
||
Rotation = currentRotation,
|
||
HasCustomRotation = hasCustomRotation
|
||
};
|
||
|
||
LogManager.Info(string.Format("已保存动画物体状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°, customRotation={5}",
|
||
animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
|
||
currentYaw * 180 / Math.PI, state.HasCustomRotation));
|
||
if (state.HasCustomRotation && state.Rotation != null)
|
||
{
|
||
var linear = new Transform3D(state.Rotation).Linear;
|
||
LogManager.Info(string.Format(
|
||
"[报告姿态保存] {0} 保存姿态: " +
|
||
"位置=({1:F3},{2:F3},{3:F3}), " +
|
||
"X=({4:F4},{5:F4},{6:F4}), " +
|
||
"Y=({7:F4},{8:F4},{9:F4}), " +
|
||
"Z=({10:F4},{11:F4},{12:F4})",
|
||
animatedObject.DisplayName,
|
||
state.Position.X, state.Position.Y, state.Position.Z,
|
||
linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
|
||
linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
|
||
linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
|
||
}
|
||
|
||
return state;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 恢复动画物体到保存的状态
|
||
/// </summary>
|
||
/// <param name="animatedObject">动画物体</param>
|
||
/// <param name="state">状态快照</param>
|
||
public static void RestoreAnimatedObjectState(ModelItem animatedObject, ModelItemTransformHelper.ObjectStateSnapshot state)
|
||
{
|
||
if (animatedObject == null || state == null) return;
|
||
|
||
if (state.HasCustomRotation && state.Rotation != null)
|
||
{
|
||
var linear = new Transform3D(state.Rotation).Linear;
|
||
LogManager.Info(string.Format(
|
||
"[报告姿态恢复] {0} 恢复目标姿态: " +
|
||
"位置=({1:F3},{2:F3},{3:F3}), " +
|
||
"X=({4:F4},{5:F4},{6:F4}), " +
|
||
"Y=({7:F4},{8:F4},{9:F4}), " +
|
||
"Z=({10:F4},{11:F4},{12:F4})",
|
||
animatedObject.DisplayName,
|
||
state.Position.X, state.Position.Y, state.Position.Z,
|
||
linear.Get(0, 0), linear.Get(1, 0), linear.Get(2, 0),
|
||
linear.Get(0, 1), linear.Get(1, 1), linear.Get(2, 1),
|
||
linear.Get(0, 2), linear.Get(1, 2), linear.Get(2, 2)));
|
||
}
|
||
|
||
var pam = PathAnimationManager.GetInstance();
|
||
if (pam == null || !pam.ControlsAnimatedObject(animatedObject))
|
||
{
|
||
throw new InvalidOperationException(
|
||
$"恢复碰撞场景前的动画物体状态必须复用 PathAnimationManager:对象 {animatedObject.DisplayName} 不受当前动画管理器控制。");
|
||
}
|
||
|
||
pam.RestoreAnimatedObjectState(animatedObject);
|
||
LogManager.Info(string.Format(
|
||
"动画物体已通过PathAnimationManager恢复状态: {0}, customRotation={1}",
|
||
animatedObject.DisplayName,
|
||
state.HasCustomRotation));
|
||
}
|
||
}
|
||
}
|