NavisworksTransport/src/Utils/CollisionSceneHelper.cs

184 lines
9.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

using System;
using 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));
}
}
}