重构视角控制辅助类,优化聚焦方法;记录相关API使用方法
This commit is contained in:
parent
78158c1cb1
commit
c28f9762bc
@ -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
|
||||
/// <summary>
|
||||
/// 视角控制工具类 - 基于实际项目经验
|
||||
/// </summary>
|
||||
public static class ViewpointHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 聚焦到单个模型对象(精确控制占屏比例)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 聚焦到碰撞点(两个对象的中间位置)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 聚焦到指定点和大小的区域(ZoomBox法)
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
@ -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 通用视角设置方法
|
||||
|
||||
/// <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>
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user