228 lines
11 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|