223 lines
10 KiB
C#
223 lines
10 KiB
C#
using System;
|
|
using Autodesk.Navisworks.Api;
|
|
using NavisworksTransport.Core;
|
|
using NavisworksTransport.Core.Animation;
|
|
|
|
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.Item1Position, collision.Item1YawRadians, collision.Item1Rotation,
|
|
collision.Item1HasCustomRotation, collision.HasPositionInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将动画物体移动到碰撞位置并聚焦到碰撞场景(通用版本)
|
|
/// </summary>
|
|
/// <param name="hitObject">被撞对象</param>
|
|
/// <param name="animatedObject">动画物体(运动物体)</param>
|
|
/// <param name="item1Position">碰撞位置</param>
|
|
/// <param name="item1YawRadians">碰撞朝向</param>
|
|
/// <param name="item1Rotation">碰撞完整姿态</param>
|
|
/// <param name="item1HasCustomRotation">是否有完整姿态</param>
|
|
/// <param name="hasPositionInfo">是否有位置信息</param>
|
|
public static void MoveToCollisionAndFocus(ModelItem hitObject, ModelItem animatedObject,
|
|
Point3D item1Position, double item1YawRadians, Rotation3D item1Rotation,
|
|
bool item1HasCustomRotation, 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 && item1Position != null)
|
|
{
|
|
var pam = PathAnimationManager.GetInstance();
|
|
bool useAnimationPipeline = pam != null &&
|
|
pam.ControlsAnimatedObject(animatedObject) &&
|
|
item1HasCustomRotation &&
|
|
item1Rotation != null;
|
|
|
|
// 检查是否是虚拟物体
|
|
bool isVirtual = VirtualObjectManager.Instance.IsVirtualObjectActive &&
|
|
VirtualObjectManager.Instance.CurrentVirtualObject == animatedObject;
|
|
|
|
if (useAnimationPipeline)
|
|
{
|
|
pam.MoveAnimatedObjectToPose(
|
|
animatedObject,
|
|
item1Position,
|
|
item1YawRadians,
|
|
item1Rotation,
|
|
true);
|
|
|
|
LogManager.Info(string.Format(
|
|
"运动物体已通过动画链路移动到碰撞位置: 位置=({0:F2}, {1:F2}, {2:F2}), customRotation={3}",
|
|
item1Position.X, item1Position.Y, item1Position.Z,
|
|
true));
|
|
}
|
|
else if (item1HasCustomRotation && item1Rotation != null)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"三维碰撞点恢复必须复用动画主链路,当前对象未受 PathAnimationManager 控制: {animatedObject.DisplayName}");
|
|
}
|
|
else
|
|
{
|
|
var bounds = animatedObject.BoundingBox();
|
|
double halfHeight = (bounds.Max.Z - bounds.Min.Z) / 2.0;
|
|
var targetGroundPosition = new Point3D(
|
|
item1Position.X,
|
|
item1Position.Y,
|
|
item1Position.Z - halfHeight
|
|
);
|
|
|
|
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}°",
|
|
targetGroundPosition.X, targetGroundPosition.Y, targetGroundPosition.Z,
|
|
item1YawRadians * 180 / Math.PI));
|
|
}
|
|
}
|
|
}
|
|
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.CurrentRotation;
|
|
var hasCustomRotation = pam.HasCurrentRotation;
|
|
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));
|
|
|
|
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
|
|
{
|
|
var pam = PathAnimationManager.GetInstance();
|
|
if (state.HasCustomRotation)
|
|
{
|
|
if (pam != null && ReferenceEquals(pam.AnimatedObject, animatedObject))
|
|
{
|
|
pam.RestoreAnimatedObjectState(animatedObject);
|
|
LogManager.Info(string.Format("动画物体已通过PathAnimationManager恢复三维姿态: {0}", animatedObject.DisplayName));
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|