532 lines
23 KiB
C#
532 lines
23 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Utils.CoordinateSystem;
|
||
|
||
namespace NavisworksTransport.Utils
|
||
{
|
||
/// <summary>
|
||
/// Navisworks 视角调整工具类
|
||
/// 提供自动调整摄像机位置和视角的功能,用于碰撞报告截图
|
||
/// </summary>
|
||
public static class ViewpointHelper
|
||
{
|
||
/// <summary>
|
||
/// 包围盒扩展系数(用于 ZoomBox 调整视野范围)
|
||
/// </summary>
|
||
private const double VIEW_BOUNDING_BOX_EXPANSION_FACTOR = 1.2;
|
||
|
||
/// <summary>
|
||
/// 默认视野扩展范围(米)- 用于调整视角时确保目标完全可见
|
||
/// </summary>
|
||
private const double DEFAULT_VIEW_EXPANSION_METERS = 10.0;
|
||
|
||
/// <summary>
|
||
/// 智能调整视角:调整到路径中心,确保整个路径都在视野内
|
||
/// </summary>
|
||
/// <param name="path">路径对象</param>
|
||
/// <param name="collisions">碰撞结果列表(用于日志记录,不影响视角调整)</param>
|
||
public static void AdjustViewpointSmart(PathRoute path, List<CollisionResult> collisions)
|
||
{
|
||
// 调整视角到路径中心,确保整个路径都在视野内
|
||
AdjustViewpointToPathCenter(path);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调整视角到路径中心,确保整个路径都在视野内
|
||
/// </summary>
|
||
/// <param name="path">路径对象</param>
|
||
/// <exception cref="InvalidOperationException">没有活动的文档</exception>
|
||
/// <exception cref="ArgumentException">路径为空或没有路径点</exception>
|
||
/// <exception cref="InvalidOperationException">路径长度为0</exception>
|
||
public static void AdjustViewpointToPathCenter(PathRoute path)
|
||
{
|
||
// 1. 计算路径起点和终点形成的包围盒(用于聚焦)
|
||
Point3D startPoint = path.Points[0].Position;
|
||
Point3D endPoint = path.Points[path.Points.Count - 1].Position;
|
||
|
||
double minX = Math.Min(startPoint.X, endPoint.X);
|
||
double minY = Math.Min(startPoint.Y, endPoint.Y);
|
||
double minZ = Math.Min(startPoint.Z, endPoint.Z);
|
||
double maxX = Math.Max(startPoint.X, endPoint.X);
|
||
double maxY = Math.Max(startPoint.Y, endPoint.Y);
|
||
double maxZ = Math.Max(startPoint.Z, endPoint.Z);
|
||
BoundingBox3D startEndBoundingBox = new BoundingBox3D(
|
||
new Point3D(minX, minY, minZ),
|
||
new Point3D(maxX, maxY, maxZ)
|
||
);
|
||
|
||
// 2. 计算路径的包围盒(用于视野范围)
|
||
BoundingBox3D pathBoundingBox = CalculatePathBoundingBox(path);
|
||
|
||
// 3. 使用路径长度作为视野基准
|
||
double baseDimension = path.TotalLength;
|
||
|
||
// 4. 调整视角:聚焦起点终点中心,视野覆盖整个路径
|
||
AdjustViewpointToBoundingBox(startEndBoundingBox, pathBoundingBox, baseDimension);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调整视角到指定的包围盒(通用方法)
|
||
/// 设置俯视位置,确保包围盒完整显示在视野中
|
||
/// </summary>
|
||
/// <param name="focusBoundingBox">聚焦包围盒(用于设置相机位置)</param>
|
||
/// <param name="viewBoundingBox">视野包围盒(用于 ZoomBox 调整视野范围)</param>
|
||
/// <param name="baseDimension">基准尺寸(米,用于计算相机距离)</param>
|
||
/// <exception cref="InvalidOperationException">没有活动的文档</exception>
|
||
private static void AdjustViewpointToBoundingBox(BoundingBox3D focusBoundingBox, BoundingBox3D viewBoundingBox, double baseDimension)
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
|
||
Vector3D hostUp = adapter.HostUpVector;
|
||
Vector3D screenUp = adapter.FromCanonicalVector(new Vector3D(0, 1, 0));
|
||
|
||
// 1. 计算聚焦包围盒中心(相机指向的位置)
|
||
Point3D focusCenter = new Point3D(
|
||
(focusBoundingBox.Min.X + focusBoundingBox.Max.X) / 2,
|
||
(focusBoundingBox.Min.Y + focusBoundingBox.Max.Y) / 2,
|
||
(focusBoundingBox.Min.Z + focusBoundingBox.Max.Z) / 2
|
||
);
|
||
|
||
// 2. 设置俯视位置(从上方往下看)
|
||
// 将基准尺寸(米)转换为模型单位
|
||
double baseDimensionInModelUnits = UnitsConverter.ConvertFromMeters(baseDimension);
|
||
double cameraDistance = baseDimensionInModelUnits; // 相机距离设置为基准尺寸的1倍(可调整比例以获得更好视野)
|
||
Point3D cameraPosition = new Point3D(
|
||
focusCenter.X + hostUp.X * cameraDistance,
|
||
focusCenter.Y + hostUp.Y * cameraDistance,
|
||
focusCenter.Z + hostUp.Z * cameraDistance);
|
||
|
||
// 将相机距离转换回米用于日志显示
|
||
double cameraDistanceMeters = UnitsConverter.ConvertToMeters(cameraDistance);
|
||
LogManager.Info($"相机设置: 位置=({cameraPosition.X:F2}, {cameraPosition.Y:F2}, {cameraPosition.Z:F2}), 焦点=({focusCenter.X:F2}, {focusCenter.Y:F2}, {focusCenter.Z:F2}), 相机距离={cameraDistanceMeters:F2}米");
|
||
|
||
// 3. 计算扩展边距
|
||
double boxWidth = viewBoundingBox.Max.X - viewBoundingBox.Min.X;
|
||
double expansionFactor = VIEW_BOUNDING_BOX_EXPANSION_FACTOR + (DEFAULT_VIEW_EXPANSION_METERS / baseDimension);
|
||
double expansionMargin = boxWidth * (expansionFactor - 1) / 2;
|
||
|
||
// 4. 应用视角(使用通用方法,带 ZoomBox)
|
||
ApplyViewpointWithZoomBox(cameraPosition, focusCenter, screenUp, viewBoundingBox, expansionMargin);
|
||
|
||
LogManager.Info(
|
||
$"视角已调整完成: 俯视图(已摆正), HostUp=({hostUp.X:F2},{hostUp.Y:F2},{hostUp.Z:F2}), " +
|
||
$"ScreenUp=({screenUp.X:F2},{screenUp.Y:F2},{screenUp.Z:F2}), 基准尺寸={baseDimension:F2}米, " +
|
||
$"相机距离={cameraDistanceMeters:F2}米, FOV=自动, 包围盒扩展系数={VIEW_BOUNDING_BOX_EXPANSION_FACTOR:F1}, 扩展边距={expansionMargin:F2}米");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算路径的包围盒
|
||
/// </summary>
|
||
/// <param name="path">路径对象</param>
|
||
/// <returns>路径的包围盒</returns>
|
||
/// <exception cref="ArgumentException">路径为空或没有路径点</exception>
|
||
public static BoundingBox3D CalculatePathBoundingBox(PathRoute path)
|
||
{
|
||
if (path == null)
|
||
{
|
||
throw new ArgumentException("路径不能为空");
|
||
}
|
||
|
||
// 参考 BoundingBoxGeometryUtils.CalculateTotalBounds 的方式计算包围盒
|
||
var firstPoint = path.Points[0].Position;
|
||
double minX = firstPoint.X;
|
||
double minY = firstPoint.Y;
|
||
double minZ = firstPoint.Z;
|
||
double maxX = firstPoint.X;
|
||
double maxY = firstPoint.Y;
|
||
double maxZ = firstPoint.Z;
|
||
|
||
foreach (var point in path.Points.Skip(1))
|
||
{
|
||
var pos = point.Position;
|
||
minX = Math.Min(minX, pos.X);
|
||
minY = Math.Min(minY, pos.Y);
|
||
minZ = Math.Min(minZ, pos.Z);
|
||
maxX = Math.Max(maxX, pos.X);
|
||
maxY = Math.Max(maxY, pos.Y);
|
||
maxZ = Math.Max(maxZ, pos.Z);
|
||
}
|
||
|
||
var bounds = new BoundingBox3D(
|
||
new Point3D(minX, minY, minZ),
|
||
new Point3D(maxX, maxY, maxZ)
|
||
);
|
||
|
||
return bounds;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算所有碰撞位置的总包围盒
|
||
/// </summary>
|
||
/// <param name="collisions">碰撞结果列表</param>
|
||
/// <returns>所有碰撞位置的总包围盒</returns>
|
||
/// <exception cref="ArgumentException">碰撞列表为空或没有有效的碰撞位置信息</exception>
|
||
public static BoundingBox3D CalculateCollisionsBoundingBox(List<CollisionResult> collisions)
|
||
{
|
||
if (collisions == null || collisions.Count == 0)
|
||
{
|
||
throw new ArgumentException("碰撞列表为空");
|
||
}
|
||
|
||
// 获取所有碰撞的中心点
|
||
var collisionCenters = collisions
|
||
.Where(c => c.Center != null)
|
||
.Select(c => c.Center)
|
||
.ToList();
|
||
|
||
if (collisionCenters.Count == 0)
|
||
{
|
||
throw new ArgumentException("没有有效的碰撞位置信息");
|
||
}
|
||
|
||
// 创建初始包围盒
|
||
BoundingBox3D bounds = new BoundingBox3D(
|
||
collisionCenters[0],
|
||
collisionCenters[0]
|
||
);
|
||
|
||
// 扩展包围盒以包含所有碰撞位置
|
||
foreach (var center in collisionCenters)
|
||
{
|
||
bounds.Extend(center);
|
||
}
|
||
|
||
return bounds;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存当前视角
|
||
/// </summary>
|
||
/// <returns>当前视角的副本</returns>
|
||
/// <exception cref="InvalidOperationException">没有活动的文档</exception>
|
||
public static Viewpoint SaveCurrentViewpoint()
|
||
{
|
||
try
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
Viewpoint currentViewpoint = doc.CurrentViewpoint.Value;
|
||
return currentViewpoint.CreateCopy();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"保存当前视角失败: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 恢复视角
|
||
/// </summary>
|
||
/// <param name="savedViewpoint">要恢复的视角</param>
|
||
/// <exception cref="InvalidOperationException">没有活动的文档</exception>
|
||
/// <exception cref="ArgumentNullException">视角不能为空</exception>
|
||
public static void RestoreViewpoint(Viewpoint savedViewpoint)
|
||
{
|
||
if (savedViewpoint == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(savedViewpoint));
|
||
}
|
||
|
||
try
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
doc.CurrentViewpoint.CopyFrom(savedViewpoint);
|
||
LogManager.Info("视角已恢复");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"恢复视角失败: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
#region 通用视角设置方法
|
||
|
||
/// <summary>
|
||
/// 应用视角设置(核心通用方法)
|
||
/// </summary>
|
||
/// <param name="cameraPosition">相机位置</param>
|
||
/// <param name="targetPoint">目标点(相机看向的位置)</param>
|
||
/// <param name="upVector">相机上方向</param>
|
||
/// <param name="useAlignDirection">是否使用 AlignDirection/AlignUp(true)还是直接设置 Rotation(false)</param>
|
||
private static void ApplyViewpoint(Point3D cameraPosition, Point3D targetPoint, Vector3D upVector, bool useAlignDirection = true)
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy();
|
||
newViewpoint.Position = cameraPosition;
|
||
|
||
if (useAlignDirection)
|
||
{
|
||
// 方法1:使用 AlignDirection + AlignUp(推荐用于聚焦对象)
|
||
Vector3D lookDirection = new Vector3D(
|
||
targetPoint.X - cameraPosition.X,
|
||
targetPoint.Y - cameraPosition.Y,
|
||
targetPoint.Z - cameraPosition.Z
|
||
);
|
||
lookDirection.Normalize();
|
||
newViewpoint.AlignDirection(lookDirection);
|
||
newViewpoint.AlignUp(upVector);
|
||
}
|
||
else
|
||
{
|
||
// 方法2:直接设置 Rotation 和 WorldUpVector(用于标准俯视图等)
|
||
newViewpoint.Rotation = new Rotation3D();
|
||
newViewpoint.WorldUpVector = new UnitVector3D(upVector.X, upVector.Y, upVector.Z);
|
||
}
|
||
|
||
doc.CurrentViewpoint.CopyFrom(newViewpoint);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用视角并缩放视野(使用 ZoomBox)
|
||
/// </summary>
|
||
/// <param name="cameraPosition">相机位置</param>
|
||
/// <param name="targetPoint">目标点</param>
|
||
/// <param name="upVector">相机上方向</param>
|
||
/// <param name="viewBoundingBox">视野包围盒(用于 ZoomBox)</param>
|
||
/// <param name="expansionMargin">包围盒扩展边距</param>
|
||
private static void ApplyViewpointWithZoomBox(Point3D cameraPosition, Point3D targetPoint, Vector3D upVector, BoundingBox3D viewBoundingBox, double expansionMargin = 0)
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy();
|
||
newViewpoint.Position = cameraPosition;
|
||
|
||
// 使用 AlignDirection + AlignUp
|
||
Vector3D lookDirection = new Vector3D(
|
||
targetPoint.X - cameraPosition.X,
|
||
targetPoint.Y - cameraPosition.Y,
|
||
targetPoint.Z - cameraPosition.Z
|
||
);
|
||
lookDirection.Normalize();
|
||
newViewpoint.AlignDirection(lookDirection);
|
||
newViewpoint.AlignUp(upVector);
|
||
|
||
// 使用 ZoomBox 调整视野
|
||
BoundingBox3D expandedBox = expansionMargin > 0
|
||
? BoundingBoxGeometryUtils.ExpandBoundingBox(viewBoundingBox, expansionMargin)
|
||
: viewBoundingBox;
|
||
newViewpoint.ZoomBox(expandedBox);
|
||
|
||
doc.CurrentViewpoint.CopyFrom(newViewpoint);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 模型元素聚焦方法
|
||
|
||
/// <summary>
|
||
/// 聚焦到指定模型元素
|
||
/// 相机会 positioned 在元素斜上方,使元素占据视图约1/4宽度
|
||
/// </summary>
|
||
/// <param name="modelItem">要聚焦的模型元素</param>
|
||
/// <param name="viewAngleDegrees">视角角度(度,推荐45度斜上方)</param>
|
||
/// <param name="targetViewRatio">目标占据视图比例(1/4 = 0.25)</param>
|
||
public static void FocusOnModelItem(ModelItem modelItem, double viewAngleDegrees, double targetViewRatio)
|
||
{
|
||
if (modelItem == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(modelItem));
|
||
}
|
||
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 1. 获取模型元素的包围盒
|
||
BoundingBox3D boundingBox = modelItem.BoundingBox();
|
||
if (boundingBox == null || boundingBox.Size == new Vector3D(0, 0, 0))
|
||
{
|
||
LogManager.Warning($"模型元素 {modelItem.DisplayName} 没有有效的包围盒,使用默认视角");
|
||
return;
|
||
}
|
||
|
||
// 2. 计算包围盒中心和尺寸
|
||
Point3D center = new Point3D(
|
||
(boundingBox.Min.X + boundingBox.Max.X) / 2,
|
||
(boundingBox.Min.Y + boundingBox.Max.Y) / 2,
|
||
(boundingBox.Min.Z + boundingBox.Max.Z) / 2
|
||
);
|
||
|
||
double maxDimension = Math.Max(
|
||
boundingBox.Max.X - boundingBox.Min.X,
|
||
Math.Max(boundingBox.Max.Y - boundingBox.Min.Y, boundingBox.Max.Z - boundingBox.Min.Z)
|
||
);
|
||
|
||
LogManager.Debug($"聚焦到模型元素: {modelItem.DisplayName}, 最大边: {maxDimension:F2}");
|
||
|
||
// 3. 计算相机位置(使用模型标准视角方向)
|
||
Point3D cameraPosition = CalculateCameraPosition(center, maxDimension, viewAngleDegrees, targetViewRatio);
|
||
|
||
// 4. 应用视角(使用通用方法)
|
||
Vector3D upVector = doc.FrontRightTopViewUpVector;
|
||
ApplyViewpoint(cameraPosition, center, upVector, useAlignDirection: true);
|
||
|
||
LogManager.Debug($"视角已调整: 标准前右上视角, 目标占据视图{targetViewRatio:P0}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"聚焦到模型元素失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 聚焦到多个模型元素(如碰撞中的两个对象)
|
||
/// </summary>
|
||
/// <param name="item1">第一个模型元素(运动物体)</param>
|
||
/// <param name="item2">第二个模型元素(被撞对象)</param>
|
||
/// <param name="viewAngleDegrees">视角角度(度,推荐45度斜上方)</param>
|
||
/// <param name="targetViewRatio">目标占据视图比例(1/4 = 0.25)</param>
|
||
public static void FocusOnCollision(ModelItem item1, ModelItem item2, double viewAngleDegrees, double targetViewRatio)
|
||
{
|
||
if (item1 == null && item2 == null)
|
||
{
|
||
throw new ArgumentException("至少需要一个模型元素");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 计算两个元素的联合包围盒
|
||
BoundingBox3D combinedBounds = null;
|
||
|
||
if (item1 != null)
|
||
{
|
||
combinedBounds = item1.BoundingBox();
|
||
}
|
||
|
||
if (item2 != null)
|
||
{
|
||
if (combinedBounds == null)
|
||
{
|
||
combinedBounds = item2.BoundingBox();
|
||
}
|
||
else
|
||
{
|
||
BoundingBox3D item2Box = item2.BoundingBox();
|
||
combinedBounds.Extend(item2Box.Min);
|
||
combinedBounds.Extend(item2Box.Max);
|
||
}
|
||
}
|
||
|
||
if (combinedBounds == null || combinedBounds.Size == new Vector3D(0, 0, 0))
|
||
{
|
||
LogManager.Warning("碰撞对象没有有效的包围盒");
|
||
return;
|
||
}
|
||
|
||
// 使用联合包围盒的中心点和尺寸
|
||
Point3D center = new Point3D(
|
||
(combinedBounds.Min.X + combinedBounds.Max.X) / 2,
|
||
(combinedBounds.Min.Y + combinedBounds.Max.Y) / 2,
|
||
(combinedBounds.Min.Z + combinedBounds.Max.Z) / 2
|
||
);
|
||
|
||
double maxDimension = Math.Max(
|
||
combinedBounds.Max.X - combinedBounds.Min.X,
|
||
Math.Max(combinedBounds.Max.Y - combinedBounds.Min.Y, combinedBounds.Max.Z - combinedBounds.Min.Z)
|
||
);
|
||
|
||
FocusOnPosition(center, maxDimension, viewAngleDegrees, targetViewRatio);
|
||
|
||
LogManager.Info($"已聚焦到碰撞位置: {item1?.DisplayName} ↔ {item2?.DisplayName}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"聚焦到碰撞位置失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 聚焦到指定位置和尺寸
|
||
/// </summary>
|
||
/// <param name="center">目标中心点</param>
|
||
/// <param name="targetSize">目标尺寸(最大边)</param>
|
||
/// <param name="viewAngleDegrees">视角角度</param>
|
||
/// <param name="targetViewRatio">目标占据视图比例(1/4 = 0.25)</param>
|
||
public static void FocusOnPosition(Point3D center, double targetSize, double viewAngleDegrees, double targetViewRatio)
|
||
{
|
||
Document doc = Application.ActiveDocument;
|
||
if (doc == null || doc.IsClear)
|
||
{
|
||
throw new InvalidOperationException("没有活动的文档");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 计算相机位置(使用模型标准视角方向)
|
||
Point3D cameraPosition = CalculateCameraPosition(center, targetSize, viewAngleDegrees, targetViewRatio);
|
||
|
||
// 应用视角(使用通用方法)
|
||
Vector3D upVector = doc.FrontRightTopViewUpVector;
|
||
ApplyViewpoint(cameraPosition, center, upVector, useAlignDirection: true);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"聚焦到位置失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算相机位置(使用模型标准前右上视角)
|
||
/// 基于 Navisworks 的标准 FrontRightTopViewVector 确定相机方向
|
||
/// </summary>
|
||
private static Point3D CalculateCameraPosition(Point3D center, double targetSize, double viewAngleDegrees, double targetViewRatio)
|
||
{
|
||
// 计算相机距离(标准透视投影公式)
|
||
// 公式:distance = (targetSize / 2) / tan(FOV / 2) / targetViewRatio
|
||
double fovRadians = viewAngleDegrees * Math.PI / 180.0;
|
||
double cameraDistance = (targetSize / 2.0) / Math.Tan(fovRadians / 2.0) / targetViewRatio;
|
||
|
||
// 调试日志:打印计算参数
|
||
LogManager.Debug($"[ViewpointHelper] FOV={viewAngleDegrees:F2}°, targetSize={targetSize:F2}, ratio={targetViewRatio:F2}, " +
|
||
$"distance={cameraDistance:F2}, center=({center.X:F2},{center.Y:F2},{center.Z:F2})");
|
||
|
||
// 获取模型的标准前右上视角向量
|
||
Vector3D viewDirection = Application.ActiveDocument.FrontRightTopViewVector;
|
||
viewDirection.Normalize();
|
||
|
||
// 沿标准视角方向偏移相机位置
|
||
return new Point3D(
|
||
center.X - viewDirection.X * cameraDistance,
|
||
center.Y - viewDirection.Y * cameraDistance,
|
||
center.Z - viewDirection.Z * cameraDistance
|
||
);
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|