From c28f9762bc5300e129518feb63bfb144cbde55b4 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Tue, 10 Feb 2026 15:04:46 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=A7=86=E8=A7=92=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E8=BE=85=E5=8A=A9=E7=B1=BB=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=81=9A=E7=84=A6=E6=96=B9=E6=B3=95=EF=BC=9B=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=9B=B8=E5=85=B3API=E4=BD=BF=E7=94=A8=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/design/2026/NavisworksAPI使用方法.md | 427 +++++++++++++++++++++++ src/Utils/ViewpointHelper.cs | 158 +++++---- 2 files changed, 517 insertions(+), 68 deletions(-) diff --git a/doc/design/2026/NavisworksAPI使用方法.md b/doc/design/2026/NavisworksAPI使用方法.md index 93441de..8aa50a9 100644 --- a/doc/design/2026/NavisworksAPI使用方法.md +++ b/doc/design/2026/NavisworksAPI使用方法.md @@ -3678,3 +3678,430 @@ public static void SaveAndRestoreViewpointExample() 3. **理解每个属性的作用**:不要混淆"视图方向"和"向上向量" 4. **正确的设置顺序很重要**:Position → Rotation → AlignDirection → WorldUpVector 5. **使用 CreateCopy() 而不是 new Viewpoint()**:保留当前视角的其他属性 + +## 13. 视角控制(Viewpoint)API + +基于 Focus 功能实现的真实API用法总结(ViewpointHelper开发经验)。 + +### 13.1 核心API概念 + +**关键发现**:`ModelItem.Transform` **不反映** override 后的位置变化,获取实际位置应使用 `BoundingBox().Center`。 + +#### 视角控制的核心类 + +| 类/方法 | 用途 | 关键特性 | +|---------|------|---------| +| `Viewpoint` | 视角状态对象 | 可修改 Position、Rotation、WorldUpVector | +| `doc.CurrentViewpoint.Value` | 获取当前视角 | 需要用 `CreateCopy()` 创建副本修改 | +| `AlignDirection(Vector3D)` | 旋转相机指向方向 | 使用最短路径旋转 | +| `AlignUp(Vector3D)` | 旋转相机对齐向上向量 | 围绕视线方向旋转 | +| `ZoomBox(BoundingBox3D)` | 强制适应视图 | **会覆盖**相机距离设置 | +| `Rotation3D()` | 清除旋转状态 | 用于创建标准视角(俯视图等) | + +### 13.2 聚焦到模型对象的两种方法 + +#### 方法一:距离计算法(精确控制物体占屏比例) + +适用于**聚焦到单个对象**,精确控制物体在视图中的占比。 + +```csharp +// ✅ 正确:计算相机距离实现目标占比 +public void FocusOnModelItem(ModelItem item, double viewAngleDegrees = 45.0, + double targetViewRatio = 0.25) +{ + Document doc = Application.ActiveDocument; + + // 1. 获取对象包围盒 + var boundingBox = item.BoundingBox(); + Point3D targetCenter = boundingBox.Center; + double targetSize = Math.Max(boundingBox.Size.X, boundingBox.Size.Y); + + // 2. 计算相机距离(使用FOV公式) + double fovRadians = viewAngleDegrees * Math.PI / 180.0; + double cameraDistance = (targetSize / 2.0) / Math.Tan(fovRadians / 2.0) / targetViewRatio; + + // 3. 计算相机位置(使用模型标准视角向量) + Vector3D viewDirection = doc.FrontRightTopViewVector; // 标准45度视角 + Vector3D upVector = doc.FrontRightTopViewUpVector; + + Point3D cameraPosition = new Point3D( + targetCenter.X - viewDirection.X * cameraDistance, + targetCenter.Y - viewDirection.Y * cameraDistance, + targetCenter.Z - viewDirection.Z * cameraDistance + ); + + // 4. 应用视角 + ApplyViewpoint(cameraPosition, targetCenter, upVector, useAlignDirection: true); +} + +// 通用视角应用方法 +private static void ApplyViewpoint(Point3D cameraPosition, Point3D targetPoint, + Vector3D upVector, bool useAlignDirection) +{ + Document doc = Application.ActiveDocument; + Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy(); + + newViewpoint.Position = cameraPosition; + + if (useAlignDirection) + { + // 使用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 + { + // 使用Rotation直接设置(适用于标准视角) + newViewpoint.Rotation = new Rotation3D(); + newViewpoint.WorldUpVector = new UnitVector3D(upVector.X, upVector.Y, upVector.Z); + } + + doc.CurrentViewpoint.CopyFrom(newViewpoint); +} +``` + +**关键公式**: +``` +cameraDistance = (targetSize / 2) / tan(FOV / 2) / targetViewRatio + +示例: +- targetSize = 2米, FOV = 45°, ratio = 0.25 (25%占屏) +- cameraDistance = 1.0 / tan(22.5°) / 0.25 ≈ 9.66 米 +``` + +#### 方法二:ZoomBox法(确保完整可见) + +适用于**显示路径、多个对象或大型物体**,确保完全可见。 + +```csharp +// ✅ 正确:使用ZoomBox确保完整可见性 +public void FocusOnBoundingBox(BoundingBox3D bounds, double marginRatio = 0.1) +{ + Document doc = Application.ActiveDocument; + + // 1. 计算扩展后的包围盒(添加边距) + Vector3D size = bounds.Size; + Vector3D margin = new Vector3D( + size.X * marginRatio, + size.Y * marginRatio, + size.Z * marginRatio + ); + + BoundingBox3D expandedBox = new BoundingBox3D( + new Point3D(bounds.Min.X - margin.X, bounds.Min.Y - margin.Y, bounds.Min.Z - margin.Z), + new Point3D(bounds.Max.X + margin.X, bounds.Max.Y + margin.Y, bounds.Max.Z + margin.Z) + ); + + // 2. 设置相机位置(估算) + Point3D targetCenter = expandedBox.Center; + Vector3D viewDirection = doc.FrontRightTopViewVector; + double estimatedDistance = Math.Max(size.X, size.Y) * 2.0; + + Point3D cameraPosition = new Point3D( + targetCenter.X - viewDirection.X * estimatedDistance, + targetCenter.Y - viewDirection.Y * estimatedDistance, + targetCenter.Z - viewDirection.Z * estimatedDistance + ); + + // 3. 应用视角(设置Rotation和UpVector) + ApplyViewpoint(cameraPosition, targetCenter, doc.FrontRightTopViewUpVector, + useAlignDirection: false); + + // 4. 关键:使用ZoomBox强制适应视图 + doc.ActiveView.ZoomBox(expandedBox); // ZoomBox会覆盖相机距离 +} +``` + +### 13.3 模型标准视角向量 + +**重要发现**:Navisworks 提供模型特定的标准视角向量。 + +```csharp +// ✅ 获取模型的标准视角方向(45度俯视) +Vector3D standardViewDirection = doc.FrontRightTopViewVector; +Vector3D standardUpVector = doc.FrontRightTopViewUpVector; + +// 其他可用视角向量: +// - FrontViewVector / FrontViewUpVector // 正视图 +// - TopViewVector / TopViewUpVector // 俯视图 +// - RightViewVector / RightViewUpVector // 右视图 +// - FrontRightTopViewVector / ... // 45度俯视(最常用) +``` + +**使用场景**: +- **Focus功能**:使用 `FrontRightTopViewVector` 保持与UI一致的标准视角 +- **正视图截图**:使用 `FrontViewVector` 获取正交投影效果 +- **俯视图分析**:使用 `TopViewVector` 进行平面分析 + +### 13.4 相机距离计算方法对比 + +| 方法 | 适用场景 | 优点 | 缺点 | +|------|---------|------|------| +| FOV公式法 | 单个对象聚焦 | 精确控制占屏比例 | 需要计算目标尺寸 | +| ZoomBox法 | 路径/多对象显示 | 确保完全可见,自动计算距离 | 覆盖相机位置设置 | +| 固定距离 | 快速预览 | 简单快速 | 对象大小不一时效果差 | + +**FOV计算代码详解**: + +```csharp +// 计算相机距离的完整公式 +private static double CalculateCameraDistance(double targetSize, double fovDegrees, + double targetRatio) +{ + // 1. 转换FOV为弧度 + double fovRadians = fovDegrees * Math.PI / 180.0; + + // 2. 计算半角正切值 + double halfFovTan = Math.Tan(fovRadians / 2.0); + + // 3. 计算目标在FOV中占据一半时的距离 + // targetSize/2 是目标半宽,halfFovTan 是半角正切 + double distanceForFullTarget = (targetSize / 2.0) / halfFovTan; + + // 4. 根据目标占屏比例调整距离 + // ratio=0.5表示目标占视图50%,距离减半 + double finalDistance = distanceForFullTarget / targetRatio; + + return finalDistance; +} + +// 使用示例: +// targetSize=3m, FOV=45°, ratio=0.25 → distance ≈ 14.5m +// 这意味着相机距离目标14.5米时,3米宽的物体将占据视图的25% +``` + +### 13.5 常见错误和解决方案 + +#### 错误1:混用距离计算和ZoomBox + +```csharp +// ❌ 错误:先设置相机距离,再用ZoomBox覆盖 +var viewpoint = doc.CurrentViewpoint.Value.CreateCopy(); +viewpoint.Position = calculatedPosition; // 设置位置 +doc.CurrentViewpoint.CopyFrom(viewpoint); +doc.ActiveView.ZoomBox(bounds); // ZoomBox会覆盖之前的距离设置! + +// ✅ 正确:二选一 +// 方案A:只用距离计算(不调用ZoomBox) +viewpoint.Position = calculatedPosition; +doc.CurrentViewpoint.CopyFrom(viewpoint); + +// 方案B:用ZoomBox(距离会被自动计算) +doc.ActiveView.ZoomBox(bounds); +``` + +#### 错误2:忽略Rotation3D的影响 + +```csharp +// ❌ 错误:不清除旋转直接设置视角 +var viewpoint = doc.CurrentViewpoint.Value.CreateCopy(); +viewpoint.Position = newPosition; +viewpoint.AlignDirection(newDirection); // 可能受原有旋转影响 +doc.CurrentViewpoint.CopyFrom(viewpoint); + +// ✅ 正确:创建新Rotation3D清除旋转状态 +var viewpoint = doc.CurrentViewpoint.Value.CreateCopy(); +viewpoint.Rotation = new Rotation3D(); // 清除旋转 +viewpoint.AlignDirection(newDirection); // 从标准状态开始 +viewpoint.AlignUp(newUpVector); +doc.CurrentViewpoint.CopyFrom(viewpoint); +``` + +#### 错误3:使用错误的向上向量 + +```csharp +// ❌ 错误:假设世界Z轴是向上向量 +Vector3D upVector = new Vector3D(0, 0, 1); + +// ✅ 正确:使用模型的标准向上向量 +Vector3D upVector = doc.FrontRightTopViewUpVector; + +// 或者根据需要计算正确的向上向量 +// 例如:俯视图中,Y轴可能是向上 +Vector3D topViewUp = new Vector3D(0, 1, 0); +``` + +### 13.6 实用工具代码 + +```csharp +/// +/// 视角控制工具类 - 基于实际项目经验 +/// +public static class ViewpointHelper +{ + /// + /// 聚焦到单个模型对象(精确控制占屏比例) + /// + public static void FocusOnModelItem(ModelItem item, double viewAngleDegrees = 45.0, + double targetViewRatio = 0.25) + { + if (item == null) return; + + var bounds = item.BoundingBox(); + Point3D targetCenter = bounds.Center; + double targetSize = Math.Max(bounds.Size.X, bounds.Size.Y); + + // 计算相机距离 + double cameraDistance = CalculateCameraDistance( + targetSize, viewAngleDegrees, targetViewRatio); + + // 使用模型标准视角 + Document doc = Application.ActiveDocument; + Vector3D viewDir = doc.FrontRightTopViewVector; + Vector3D upVector = doc.FrontRightTopViewUpVector; + + Point3D cameraPos = new Point3D( + targetCenter.X - viewDir.X * cameraDistance, + targetCenter.Y - viewDir.Y * cameraDistance, + targetCenter.Z - viewDir.Z * cameraDistance + ); + + ApplyViewpoint(cameraPos, targetCenter, upVector, useAlignDirection: true); + } + + /// + /// 聚焦到碰撞点(两个对象的中间位置) + /// + public static void FocusOnCollision(ModelItem item1, ModelItem item2, + double viewAngleDegrees = 45.0) + { + var bounds1 = item1.BoundingBox(); + var bounds2 = item2.BoundingBox(); + + // 计算碰撞中心(两个包围盒最近的点) + Point3D collisionCenter = CalculateCollisionCenter(bounds1, bounds2); + double maxSize = Math.Max( + Math.Max(bounds1.Size.X, bounds1.Size.Y), + Math.Max(bounds2.Size.X, bounds2.Size.Y) + ); + + double cameraDistance = CalculateCameraDistance( + maxSize, viewAngleDegrees, 0.35); + + Document doc = Application.ActiveDocument; + Vector3D viewDir = doc.FrontRightTopViewVector; + Vector3D upVector = doc.FrontRightTopViewUpVector; + + Point3D cameraPos = new Point3D( + collisionCenter.X - viewDir.X * cameraDistance, + collisionCenter.Y - viewDir.Y * cameraDistance, + collisionCenter.Z - viewDir.Z * cameraDistance + ); + + ApplyViewpoint(cameraPos, collisionCenter, upVector, useAlignDirection: true); + } + + /// + /// 聚焦到指定点和大小的区域(ZoomBox法) + /// + public static void FocusOnPosition(Point3D center, double size, + double marginRatio = 0.1) + { + Document doc = Application.ActiveDocument; + + // 创建目标包围盒 + double halfSize = size / 2.0; + double margin = size * marginRatio; + + BoundingBox3D targetBox = new BoundingBox3D( + new Point3D(center.X - halfSize - margin, center.Y - halfSize - margin, + center.Z - halfSize - margin), + new Point3D(center.X + halfSize + margin, center.Y + halfSize + margin, + center.Z + halfSize + margin) + ); + + // 先设置视角方向 + Vector3D viewDir = doc.FrontRightTopViewVector; + Vector3D upVector = doc.FrontRightTopViewUpVector; + double distance = size * 2.0; + + Point3D cameraPos = new Point3D( + center.X - viewDir.X * distance, + center.Y - viewDir.Y * distance, + center.Z - viewDir.Z * distance + ); + + ApplyViewpoint(cameraPos, center, upVector, useAlignDirection: false); + + // 使用ZoomBox确保可见 + doc.ActiveView.ZoomBox(targetBox); + } + + // 私有辅助方法... + private static double CalculateCameraDistance(double targetSize, double fovDegrees, + double ratio) + { + double fovRadians = fovDegrees * Math.PI / 180.0; + return (targetSize / 2.0) / Math.Tan(fovRadians / 2.0) / ratio; + } + + private static void ApplyViewpoint(Point3D cameraPos, Point3D target, + Vector3D upVector, bool useAlignDirection) + { + Document doc = Application.ActiveDocument; + Viewpoint vp = doc.CurrentViewpoint.Value.CreateCopy(); + + vp.Position = cameraPos; + + if (useAlignDirection) + { + Vector3D lookDir = new Vector3D( + target.X - cameraPos.X, + target.Y - cameraPos.Y, + target.Z - cameraPos.Z); + lookDir.Normalize(); + vp.AlignDirection(lookDir); + vp.AlignUp(upVector); + } + else + { + vp.Rotation = new Rotation3D(); + vp.WorldUpVector = new UnitVector3D(upVector.X, upVector.Y, upVector.Z); + } + + doc.CurrentViewpoint.CopyFrom(vp); + } +} +``` + +### 13.7 视角控制最佳实践 + +1. **选择合适的聚焦方法**: + - 单个对象精确聚焦 → 距离计算法 + - 路径或区域显示 → ZoomBox法 + - 碰撞点查看 → 碰撞中心计算 + 距离法 + +2. **使用模型标准视角向量**: + - 不要硬编码向量值 + - 使用 `doc.FrontRightTopViewVector` 等API + +3. **理解ZoomBox的副作用**: + - ZoomBox会覆盖相机距离设置 + - ZoomBox后不要再调整Position来微调距离 + +4. **正确处理Rotation3D**: + - 创建新视角时,先用 `new Rotation3D()` 清除旋转 + - 再使用 `AlignDirection` 设置精确方向 + +5. **保存和恢复视角**: + ```csharp + // 保存 + Viewpoint savedView = doc.CurrentViewpoint.Value.CreateCopy(); + + // ... 修改视角 ... + + // 恢复 + doc.CurrentViewpoint.CopyFrom(savedView); + ``` + +--- + +**文档版本**:2026.2 +**最后更新**:基于 ViewpointHelper 重构经验(聚焦功能实现) +**适用版本**:Navisworks Manage 2026 diff --git a/src/Utils/ViewpointHelper.cs b/src/Utils/ViewpointHelper.cs index 97dd9a0..51fb996 100644 --- a/src/Utils/ViewpointHelper.cs +++ b/src/Utils/ViewpointHelper.cs @@ -104,31 +104,14 @@ namespace NavisworksTransport.Utils 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. 创建当前视角的副本(关键:使用 CreateCopy 而不是 new Viewpoint()) - Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy(); - - // 设置标准俯视图的相机配置 - // 相机位置:在目标正上方 - newViewpoint.Position = cameraPosition; - - // 直接设置 Rotation 为无旋转(单位四元数),实现标准的俯视图 - // 这样可以彻底清除任何旋转,使视图与世界坐标轴对齐 - newViewpoint.Rotation = new Rotation3D(); - - // 设置向上向量:Y 轴向上(标准俯视图的向上方向) - newViewpoint.WorldUpVector = new UnitVector3D(0, 1, 0); - - // 4. 扩展路径包围盒,避免边缘贴得太近 + // 3. 计算扩展边距 double boxWidth = viewBoundingBox.Max.X - viewBoundingBox.Min.X; double expansionFactor = VIEW_BOUNDING_BOX_EXPANSION_FACTOR + (EXPANSION_METERS / baseDimension); double expansionMargin = boxWidth * (expansionFactor - 1) / 2; - BoundingBox3D expandedViewBoundingBox = BoundingBoxGeometryUtils.ExpandBoundingBox(viewBoundingBox, expansionMargin); - // 5. 使用 ZoomBox 调整视野范围(使用扩展后的视野包围盒,确保整个路径都在视野内) - newViewpoint.ZoomBox(expandedViewBoundingBox); - - // 6. 应用视角到文档 - doc.CurrentViewpoint.CopyFrom(newViewpoint); + // 4. 应用视角(使用通用方法,带 ZoomBox) + Vector3D upVector = new Vector3D(0, 1, 0); // Y轴向上 + ApplyViewpointWithZoomBox(cameraPosition, focusCenter, upVector, viewBoundingBox, expansionMargin); LogManager.Info($"视角已调整完成: 俯视图(已摆正), 基准尺寸={baseDimension:F2}米, 相机距离={cameraDistanceMeters:F2}米, FOV=自动, 包围盒扩展系数={VIEW_BOUNDING_BOX_EXPANSION_FACTOR:F1}, 扩展边距={expansionMargin:F2}米"); } @@ -277,6 +260,88 @@ namespace NavisworksTransport.Utils System.Threading.Thread.Sleep(VIEW_UPDATE_DELAY_MS); } + #region 通用视角设置方法 + + /// + /// 应用视角设置(核心通用方法) + /// + /// 相机位置 + /// 目标点(相机看向的位置) + /// 相机上方向 + /// 是否使用 AlignDirection/AlignUp(true)还是直接设置 Rotation(false) + 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); + } + + /// + /// 应用视角并缩放视野(使用 ZoomBox) + /// + /// 相机位置 + /// 目标点 + /// 相机上方向 + /// 视野包围盒(用于 ZoomBox) + /// 包围盒扩展边距 + 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 模型元素聚焦方法 /// @@ -326,31 +391,9 @@ namespace NavisworksTransport.Utils // 3. 计算相机位置(使用模型标准视角方向) Point3D cameraPosition = CalculateCameraPosition(center, maxDimension, viewAngleDegrees, targetViewRatio); - // 4. 创建视角并设置相机 - Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy(); - newViewpoint.Position = cameraPosition; - - // 获取模型的标准视角向量 - Vector3D viewDirection = doc.FrontRightTopViewVector; - viewDirection.Normalize(); - - // 使用 AlignDirection 设置相机朝向(看向目标方向) - // 方向是从相机指向目标 - Vector3D lookDirection = new Vector3D( - center.X - cameraPosition.X, - center.Y - cameraPosition.Y, - center.Z - cameraPosition.Z - ); - lookDirection.Normalize(); - newViewpoint.AlignDirection(lookDirection); - - // 使用 AlignUp 设置相机的上方向(基于模型的标准上方向) + // 4. 应用视角(使用通用方法) Vector3D upVector = doc.FrontRightTopViewUpVector; - upVector.Normalize(); - newViewpoint.AlignUp(upVector); - - // 5. 应用视角(不使用 ZoomBox,让相机距离决定视野比例) - doc.CurrentViewpoint.CopyFrom(newViewpoint); + ApplyViewpoint(cameraPosition, center, upVector, useAlignDirection: true); LogManager.Info($"视角已调整: 标准前右上视角, 目标占据视图{targetViewRatio:P0}"); } @@ -446,30 +489,9 @@ namespace NavisworksTransport.Utils // 计算相机位置(使用模型标准视角方向) Point3D cameraPosition = CalculateCameraPosition(center, targetSize, viewAngleDegrees, 0.25); - // 创建视角并设置相机 - Viewpoint newViewpoint = doc.CurrentViewpoint.Value.CreateCopy(); - newViewpoint.Position = cameraPosition; - - // 获取模型的标准视角向量 - Vector3D viewDirection = doc.FrontRightTopViewVector; - viewDirection.Normalize(); - - // 使用 AlignDirection 设置相机朝向 - Vector3D lookDirection = new Vector3D( - center.X - cameraPosition.X, - center.Y - cameraPosition.Y, - center.Z - cameraPosition.Z - ); - lookDirection.Normalize(); - newViewpoint.AlignDirection(lookDirection); - - // 使用 AlignUp 设置相机的上方向 + // 应用视角(使用通用方法) Vector3D upVector = doc.FrontRightTopViewUpVector; - upVector.Normalize(); - newViewpoint.AlignUp(upVector); - - // 应用视角(不使用 ZoomBox,让相机距离决定视野比例) - doc.CurrentViewpoint.CopyFrom(newViewpoint); + ApplyViewpoint(cameraPosition, center, upVector, useAlignDirection: true); } catch (Exception ex) {