NavisworksTransport/src/Utils/CollisionSceneHelper.cs

228 lines
11 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, viewAngleDegrees: 60.0, targetViewRatio: 0.25);
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.Info(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;
try
{
// 从PathAnimationManager获取当前实际朝向
var pam = PathAnimationManager.GetInstance();
var currentYaw = pam.CurrentYaw;
var currentRotation = pam.TrackedRotation;
var hasCustomRotation = pam.HasTrackedRotation;
var currentState = pam.GetObjectCurrentPosition(animatedObject);
pam.SaveObjectState(animatedObject);
var state = ModelItemTransformHelper.SaveObjectState(
animatedObject,
currentYaw,
currentState.Position,
currentRotation,
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;
}
catch (Exception ex)
{
LogManager.Error(string.Format("保存动画物体状态失败: {0}", ex.Message), ex);
return null;
}
}
/// <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;
try
{
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))
{
pam.RestoreAnimatedObjectState(animatedObject);
LogManager.Info(string.Format(
"动画物体已通过PathAnimationManager恢复状态: {0}, customRotation={1}",
animatedObject.DisplayName,
state.HasCustomRotation));
return;
}
if (state.HasCustomRotation)
{
bool isVirtualWithCustomRotation = VirtualObjectManager.Instance.IsVirtualObjectActive &&
VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
if (isVirtualWithCustomRotation)
{
ModelItemTransformHelper.RestoreObjectStateWithScale(animatedObject, state);
}
else
{
ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
}
LogManager.Info(string.Format("动画物体已通过状态快照恢复三维姿态: {0}", animatedObject.DisplayName));
return;
}
// 检查是否是虚拟物体
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)
{
LogManager.Error(string.Format("恢复动画物体状态失败: {0}", ex.Message), ex);
}
}
}
}