完成工具类skills
This commit is contained in:
parent
cb7e1c0e17
commit
2b151ebee5
@ -6,18 +6,35 @@
|
||||
|
||||
## 工具类总览
|
||||
|
||||
| 工具类 | 文件 | 用途 | 优先级 |
|
||||
|--------|------|------|--------|
|
||||
| **DialogHelper** | `src/Utils/DialogHelper.cs` | 对话框Owner设置和置顶显示 | ⭐⭐⭐ 必须 |
|
||||
| **UnitsConverter** | `src/Utils/UnitsConverter.cs` | 单位转换(米↔模型单位) | ⭐⭐⭐ 必须 |
|
||||
| **LogManager** | `src/Utils/LogManager.cs` | 日志记录 | ⭐⭐⭐ 必须 |
|
||||
| **GeometryHelper** | `src/Utils/GeometryHelper.cs` | 3D几何计算 | ⭐⭐⭐ |
|
||||
| **PathHelper** | `src/Utils/PathHelper.cs` | 路径相关工具 | ⭐⭐⭐ |
|
||||
| **CoordinateConverter** | `src/Utils/CoordinateConverter.cs` | 坐标系转换 | ⭐⭐ |
|
||||
| **ModelHighlightHelper** | `src/Utils/ModelHighlightHelper.cs` | 模型高亮显示 | ⭐⭐ |
|
||||
| **NavisworksSelectionHelper** | `src/Utils/NavisworksSelectionHelper.cs` | 选择集操作 | ⭐⭐ |
|
||||
| **ViewpointHelper** | `src/Utils/ViewpointHelper.cs` | 视点操作 | ⭐⭐ |
|
||||
| **SectionClipHelper** | `src/Utils/SectionClipHelper.cs` | 剖切操作 | ⭐ |
|
||||
### 核心工具类(⭐⭐⭐ 必须)
|
||||
|
||||
| 工具类 | 文件 | 用途 |
|
||||
|--------|------|------|
|
||||
| **DialogHelper** | `src/Utils/DialogHelper.cs` | 对话框Owner设置和置顶显示 |
|
||||
| **UnitsConverter** | `src/Utils/UnitsConverter.cs` | 单位转换(米↔模型单位) |
|
||||
| **LogManager** | `src/Utils/LogManager.cs` | 日志记录 |
|
||||
| **GeometryHelper** | `src/Utils/GeometryHelper.cs` | 3D几何计算 |
|
||||
| **PathHelper** | `src/Utils/PathHelper.cs` | 文件路径相关工具 |
|
||||
|
||||
### 重要工具类(⭐⭐ 推荐)
|
||||
|
||||
| 工具类 | 文件 | 用途 |
|
||||
|--------|------|------|
|
||||
| **CoordinateConverter** | `src/Utils/CoordinateConverter.cs` | 2D地图↔3D世界坐标转换 |
|
||||
| **ModelHighlightHelper** | `src/Utils/ModelHighlightHelper.cs` | 模型高亮显示 |
|
||||
| **NavisworksSelectionHelper** | `src/Utils/NavisworksSelectionHelper.cs` | 选择集操作 |
|
||||
| **ViewpointHelper** | `src/Utils/ViewpointHelper.cs` | 视点操作 |
|
||||
| **NavisworksApiHelper** | `src/Utils/NavisworksApiHelper.cs` | API通用工具 |
|
||||
| **VisibilityHelper** | `src/Utils/VisibilityHelper.cs` | 可见性管理 |
|
||||
|
||||
### 专项工具类(⭐ 按需使用)
|
||||
|
||||
| 工具类 | 文件 | 用途 |
|
||||
|--------|------|------|
|
||||
| **SectionClipHelper** | `src/Utils/SectionClipHelper.cs` | 剖切操作(性能优化) |
|
||||
| **BoundingBoxGeometryUtils** | `src/Utils/BoundingBoxGeometryUtils.cs` | 包围盒几何计算 |
|
||||
| **FloorDetector** | `src/Utils/FloorDetector.cs` | 楼层检测 |
|
||||
| **GeometryCacheManager** | `src/Utils/GeometryCacheManager.cs` | 几何缓存管理 |
|
||||
|
||||
## 快速参考
|
||||
|
||||
@ -58,13 +75,52 @@ LogManager.Warning("警告信息");
|
||||
LogManager.Error("错误信息", exception);
|
||||
```
|
||||
|
||||
### 几何计算
|
||||
|
||||
```csharp
|
||||
// ❌ 错误:自己实现距离计算
|
||||
double dx = p2.X - p1.X;
|
||||
double dy = p2.Y - p1.Y;
|
||||
double distance = Math.Sqrt(dx*dx + dy*dy);
|
||||
|
||||
// ✅ 正确:使用 GeometryHelper
|
||||
double distance = GeometryHelper.Distance(p1, p2);
|
||||
double angle = GeometryHelper.AngleBetweenDegrees(v1, v2);
|
||||
```
|
||||
|
||||
### 模型高亮
|
||||
|
||||
```csharp
|
||||
// ✅ 使用 ModelHighlightHelper 高亮对象
|
||||
ModelHighlightHelper.HighlightItems("myCategory", modelItems);
|
||||
ModelHighlightHelper.ClearCategory("myCategory");
|
||||
ModelHighlightHelper.ClearAllHighlights();
|
||||
```
|
||||
|
||||
### 视角调整
|
||||
|
||||
```csharp
|
||||
// ✅ 使用 ViewpointHelper 调整视角
|
||||
ViewpointHelper.AdjustViewpointToPathCenter(path);
|
||||
ViewpointHelper.FocusOnModelItem(modelItem, 45, 0.25);
|
||||
Viewpoint saved = ViewpointHelper.SaveCurrentViewpoint();
|
||||
ViewpointHelper.RestoreViewpoint(saved);
|
||||
```
|
||||
|
||||
## 详细文档
|
||||
|
||||
- [DialogHelper 使用指南](utils/DialogHelper.md)
|
||||
- [UnitsConverter 使用指南](utils/UnitsConverter.md)
|
||||
- [LogManager 使用指南](utils/LogManager.md)
|
||||
- [GeometryHelper 使用指南](utils/GeometryHelper.md)
|
||||
- [ModelHighlightHelper 使用指南](utils/ModelHighlightHelper.md)
|
||||
- [DialogHelper 使用指南](utils/DialogHelper.md) - 对话框Owner设置和置顶显示
|
||||
- [UnitsConverter 使用指南](utils/UnitsConverter.md) - 单位转换(极其重要)
|
||||
- [LogManager 使用指南](utils/LogManager.md) - 日志记录
|
||||
- [GeometryHelper 使用指南](utils/GeometryHelper.md) - 3D几何计算
|
||||
- [PathHelper 使用指南](utils/PathHelper.md) - 文件路径工具
|
||||
- [CoordinateConverter 使用指南](utils/CoordinateConverter.md) - 2D/3D坐标转换
|
||||
- [ModelHighlightHelper 使用指南](utils/ModelHighlightHelper.md) - 模型高亮
|
||||
- [NavisworksSelectionHelper 使用指南](utils/NavisworksSelectionHelper.md) - 选择集操作
|
||||
- [ViewpointHelper 使用指南](utils/ViewpointHelper.md) - 视点操作
|
||||
- [SectionClipHelper 使用指南](utils/SectionClipHelper.md) - 剖切操作
|
||||
- [NavisworksApiHelper 使用指南](utils/NavisworksApiHelper.md) - API通用工具
|
||||
- [VisibilityHelper 使用指南](utils/VisibilityHelper.md) - 可见性管理
|
||||
|
||||
## 使用检查清单
|
||||
|
||||
@ -76,6 +132,12 @@ LogManager.Error("错误信息", exception);
|
||||
- [ ] 需要几何计算?→ 使用 **GeometryHelper**
|
||||
- [ ] 需要高亮模型?→ 使用 **ModelHighlightHelper**
|
||||
- [ ] 需要处理选择集?→ 使用 **NavisworksSelectionHelper**
|
||||
- [ ] 需要调整视角?→ 使用 **ViewpointHelper**
|
||||
- [ ] 需要坐标转换?→ 使用 **CoordinateConverter**
|
||||
- [ ] 需要文件路径操作?→ 使用 **PathHelper**
|
||||
- [ ] 需要剖切优化?→ 使用 **SectionClipHelper**
|
||||
- [ ] 需要显示/隐藏对象?→ 使用 **VisibilityHelper**
|
||||
- [ ] 需要线程安全操作?→ 使用 **NavisworksApiHelper**
|
||||
|
||||
## 禁止行为
|
||||
|
||||
@ -86,6 +148,7 @@ LogManager.Error("错误信息", exception);
|
||||
3. ❌ 使用 `Console.WriteLine` 输出日志
|
||||
4. ❌ 自己实现距离/角度计算(已有 GeometryHelper)
|
||||
5. ❌ 自己实现集合的线程安全包装(使用 ThreadSafeObservableCollection)
|
||||
6. ❌ 自己实现缓存刷新逻辑(使用 NavisworksApiHelper.SafeCacheRefresh)
|
||||
|
||||
## 扩展阅读
|
||||
|
||||
|
||||
182
.agents/skills/project-tools/utils/CoordinateConverter.md
Normal file
182
.agents/skills/project-tools/utils/CoordinateConverter.md
Normal file
@ -0,0 +1,182 @@
|
||||
# CoordinateConverter 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/CoordinateConverter.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
负责 2D 地图坐标与 3D 世界坐标之间的转换,用于导航地图和路径规划可视化。
|
||||
|
||||
## 核心概念
|
||||
|
||||
- **地图坐标(MapPoint2D)**:2D 像素坐标,原点在左上角,Y轴向下
|
||||
- **世界坐标(Point3D)**:3D 模型坐标,单位与文档单位一致
|
||||
- **通道边界(ChannelBounds)**:定义了有效转换的区域范围
|
||||
|
||||
## 构造函数
|
||||
|
||||
```csharp
|
||||
// 使用通道边界和地图尺寸创建转换器
|
||||
var converter = new CoordinateConverter(
|
||||
channelBounds: bounds, // ChannelBounds 对象
|
||||
mapWidth: 800, // 地图窗口宽度(像素)
|
||||
mapHeight: 600 // 地图窗口高度(像素)
|
||||
);
|
||||
```
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 坐标转换
|
||||
|
||||
```csharp
|
||||
// 2D地图坐标 → 3D世界坐标
|
||||
MapPoint2D mapPoint = new MapPoint2D(400, 300);
|
||||
Point3D worldPoint = converter.MapToWorld(mapPoint);
|
||||
|
||||
// 3D世界坐标 → 2D地图坐标
|
||||
Point3D worldPoint = new Point3D(x, y, z);
|
||||
MapPoint2D mapPoint = converter.WorldToMap(worldPoint);
|
||||
|
||||
// 批量转换
|
||||
var worldPoints = converter.MapToWorldBatch(mapPoints);
|
||||
var mapPoints = converter.WorldToMapBatch(worldPoints);
|
||||
```
|
||||
|
||||
### 有效性检查
|
||||
|
||||
```csharp
|
||||
// 检查地图坐标是否在有效范围内
|
||||
bool isValid = converter.IsValidMapPoint(mapPoint);
|
||||
|
||||
// 检查世界坐标是否在通道范围内
|
||||
bool isValid = converter.IsValidWorldPoint(worldPoint);
|
||||
```
|
||||
|
||||
### 距离计算
|
||||
|
||||
```csharp
|
||||
// 计算两个地图点之间的像素距离
|
||||
double pixelDistance = converter.CalculateMapDistance(point1, point2);
|
||||
|
||||
// 计算两个世界坐标点之间的距离(模型单位)
|
||||
double worldDistance = converter.CalculateWorldDistance(point1, point2);
|
||||
```
|
||||
|
||||
### 视图操作
|
||||
|
||||
```csharp
|
||||
// 放大视图
|
||||
converter.ZoomIn(factor: 1.5, centerPoint: mapCenter);
|
||||
|
||||
// 缩小视图
|
||||
converter.ZoomOut(factor: 1.5, centerPoint: mapCenter);
|
||||
|
||||
// 平移视图
|
||||
converter.Pan(deltaX: 100, deltaY: -50);
|
||||
|
||||
// 重置视图到最佳适应
|
||||
converter.ResetView();
|
||||
|
||||
// 计算最佳适应视图
|
||||
converter.CalculateBestFitView();
|
||||
```
|
||||
|
||||
### 尺寸更新
|
||||
|
||||
```csharp
|
||||
// 更新地图尺寸(窗口大小变化时)
|
||||
converter.UpdateMapSize(newWidth: 1024, newHeight: 768);
|
||||
|
||||
// 更新通道边界
|
||||
converter.UpdateChannelBounds(newChannelBounds);
|
||||
```
|
||||
|
||||
### 辅助方法
|
||||
|
||||
```csharp
|
||||
// 获取地图中心点的世界坐标
|
||||
Point3D center = converter.GetMapCenterInWorld();
|
||||
|
||||
// 调整高程
|
||||
Point3D adjusted = converter.AdjustElevation(worldPoint, elevationOffset: 0.5);
|
||||
|
||||
// 获取地图缩放比例
|
||||
converter.GetMapScale(out double scaleX, out double scaleY);
|
||||
|
||||
// 获取转换器信息摘要
|
||||
string info = converter.ToString();
|
||||
```
|
||||
|
||||
## 属性
|
||||
|
||||
```csharp
|
||||
// 地图尺寸
|
||||
converter.MapWidth = 800;
|
||||
converter.MapHeight = 600;
|
||||
|
||||
// 通道边界
|
||||
converter.ChannelBounds = newChannelBounds;
|
||||
|
||||
// 默认高程(Z坐标)
|
||||
converter.DefaultElevation = 10.0;
|
||||
|
||||
// 缩放因子(限制范围 0.1 - 50.0)
|
||||
converter.ZoomFactor = 2.0;
|
||||
|
||||
// 偏移量
|
||||
converter.OffsetX = 100;
|
||||
converter.OffsetY = 50;
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:基本的坐标转换
|
||||
|
||||
```csharp
|
||||
// 创建转换器
|
||||
var bounds = new ChannelBounds(minPoint, maxPoint);
|
||||
var converter = new CoordinateConverter(bounds, 800, 600);
|
||||
|
||||
// 用户在地图上点击的位置
|
||||
var clickPoint = new MapPoint2D(400, 300);
|
||||
|
||||
// 转换为世界坐标进行路径规划
|
||||
Point3D worldPoint = converter.MapToWorld(clickPoint);
|
||||
LogManager.Info($"点击位置对应世界坐标: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2})");
|
||||
```
|
||||
|
||||
### 示例2:路径点批量转换
|
||||
|
||||
```csharp
|
||||
// 将规划好的路径点转换为地图坐标显示
|
||||
var pathWorldPoints = pathRoute.Points.Select(p => p.Position);
|
||||
var pathMapPoints = converter.WorldToMapBatch(pathWorldPoints);
|
||||
|
||||
// 在地图上绘制路径
|
||||
foreach (var mapPoint in pathMapPoints)
|
||||
{
|
||||
DrawPointOnMap(mapPoint.X, mapPoint.Y);
|
||||
}
|
||||
```
|
||||
|
||||
### 示例3:响应窗口大小变化
|
||||
|
||||
```csharp
|
||||
// 地图控件大小变化时更新转换器
|
||||
void OnMapSizeChanged(double newWidth, double newHeight)
|
||||
{
|
||||
converter.UpdateMapSize(newWidth, newHeight);
|
||||
converter.CalculateBestFitView();
|
||||
|
||||
// 重绘地图...
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **Y轴翻转**:地图坐标系 Y 轴向下(屏幕坐标),世界坐标系 Y 轴向上,转换时自动处理
|
||||
2. **边距设置**:从配置读取 `MarginRatio`,默认 10%,确保内容不会贴边显示
|
||||
3. **Z坐标处理**:`MapToWorld` 返回的 Z 坐标使用 `DefaultElevation`,可通过 `AdjustElevation` 调整
|
||||
4. **缩放限制**:缩放因子限制在 0.1 - 50.0 范围内,防止过度缩放
|
||||
5. **线程安全**:此类的实例方法不是线程安全的,需要在单线程中使用或使用外部锁
|
||||
130
.agents/skills/project-tools/utils/ModelHighlightHelper.md
Normal file
130
.agents/skills/project-tools/utils/ModelHighlightHelper.md
Normal file
@ -0,0 +1,130 @@
|
||||
# ModelHighlightHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/ModelHighlightHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
统一管理 Navisworks 临时高亮,支持按类别高亮与清除。使用不同颜色区分不同类型的对象(碰撞结果、通道预览、动画物体等)。
|
||||
|
||||
## 颜色定义
|
||||
|
||||
| 类别 | 颜色 | RGB | 用途 |
|
||||
|------|------|-----|------|
|
||||
| `PrecomputeCollisionResultsCategory` | Material Purple | (156, 39, 176) | 预计算碰撞结果 |
|
||||
| `ManualTargetsCategory` | 橙色 | (255, 170, 0) | 手工指定对象 |
|
||||
| `AnimatedObjectCategory` | Amber/Yellow | (255, 193, 7) | 动画物体 |
|
||||
| `ClashDetectiveResultsCategory` | 红色 | Color.Red | ClashDetective碰撞结果 |
|
||||
| `ChannelPreviewCategory` | 绿色 | Color.Green | 通道预览 |
|
||||
| `excludedObjects` | Material Green | (76, 175, 80) | 排除对象 |
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 基础高亮操作
|
||||
|
||||
```csharp
|
||||
// 高亮指定对象集合(使用类别默认颜色)
|
||||
ModelHighlightHelper.HighlightItems("myCategory", modelItems);
|
||||
|
||||
// 清除指定类别的高亮
|
||||
ModelHighlightHelper.ClearCategory("myCategory");
|
||||
|
||||
// 清除所有高亮
|
||||
ModelHighlightHelper.ClearAllHighlights();
|
||||
|
||||
// 清除碰撞相关高亮
|
||||
ModelHighlightHelper.ClearCollisionHighlights();
|
||||
```
|
||||
|
||||
### 碰撞结果高亮
|
||||
|
||||
```csharp
|
||||
// 按类别管理碰撞高亮
|
||||
ModelHighlightHelper.ManageCollisionHighlightsByCategory(
|
||||
"collisionResults",
|
||||
collisionResultsList,
|
||||
clearOtherCategories: false
|
||||
);
|
||||
|
||||
// 高亮ClashDetective结果
|
||||
ModelHighlightHelper.HighlightClashDetectiveResults(
|
||||
testName,
|
||||
getResultsFunc
|
||||
);
|
||||
|
||||
// 清除ClashDetective高亮
|
||||
ModelHighlightHelper.ClearClashDetectiveHighlights();
|
||||
```
|
||||
|
||||
### 获取高亮状态
|
||||
|
||||
```csharp
|
||||
// 获取当前高亮快照
|
||||
var highlights = ModelHighlightHelper.GetActiveHighlightSnapshot();
|
||||
foreach (var info in highlights)
|
||||
{
|
||||
LogManager.Info($"类别: {info.Category}, 颜色: {info.Color}, 数量: {info.Count}");
|
||||
}
|
||||
|
||||
// 获取类别颜色
|
||||
Color color = ModelHighlightHelper.GetCategoryColor("myCategory");
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:高亮碰撞检测结果
|
||||
|
||||
```csharp
|
||||
// 获取碰撞结果
|
||||
var collisions = collisionDetector.DetectCollisions();
|
||||
|
||||
// 高亮显示碰撞对象(使用预计算碰撞类别)
|
||||
var collidingItems = collisions.Select(c => c.Item2).ToList();
|
||||
ModelHighlightHelper.HighlightItems(
|
||||
ModelHighlightHelper.PrecomputeCollisionResultsCategory,
|
||||
collidingItems
|
||||
);
|
||||
|
||||
// 操作完成后清除高亮
|
||||
ModelHighlightHelper.ClearCategory(ModelHighlightHelper.PrecomputeCollisionResultsCategory);
|
||||
```
|
||||
|
||||
### 示例2:高亮通道预览
|
||||
|
||||
```csharp
|
||||
// 高亮显示通道对象
|
||||
var channelItems = GetChannelItems();
|
||||
ModelHighlightHelper.HighlightItems(
|
||||
ModelHighlightHelper.ChannelPreviewCategory,
|
||||
channelItems
|
||||
);
|
||||
|
||||
// 清除时只清除通道预览,不影响其他高亮
|
||||
ModelHighlightHelper.ClearCategory(ModelHighlightHelper.ChannelPreviewCategory);
|
||||
```
|
||||
|
||||
### 示例3:多类别管理
|
||||
|
||||
```csharp
|
||||
// 同时高亮不同类型对象
|
||||
ModelHighlightHelper.HighlightItems("doors", doorItems);
|
||||
ModelHighlightHelper.HighlightItems("elevators", elevatorItems);
|
||||
ModelHighlightHelper.HighlightItems("stairs", stairItems);
|
||||
|
||||
// 只清除门的高亮
|
||||
ModelHighlightHelper.ClearCategory("doors");
|
||||
|
||||
// 清除所有高亮
|
||||
ModelHighlightHelper.ClearAllHighlights();
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **类别颜色自动管理**:每个类别有预定义颜色,也可以使用自定义类别(默认白色)
|
||||
2. **自动去重**:同一对象在不同类别中可能被多次高亮,后设置的会覆盖先前的
|
||||
3. **线程安全**:内部使用锁保护,可从多线程调用
|
||||
4. **清除策略**:
|
||||
- 清除单个类别:`ClearCategory()`
|
||||
- 清除所有碰撞相关:`ClearCollisionHighlights()`
|
||||
- 清除全部:`ClearAllHighlights()`
|
||||
108
.agents/skills/project-tools/utils/NavisworksApiHelper.md
Normal file
108
.agents/skills/project-tools/utils/NavisworksApiHelper.md
Normal file
@ -0,0 +1,108 @@
|
||||
# NavisworksApiHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/NavisworksApiHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
提供 Navisworks API 通用工具方法,包括缓存刷新、线程安全操作、模型项查找等。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 缓存刷新
|
||||
|
||||
```csharp
|
||||
// 安全的缓存刷新(轻量级)
|
||||
NavisworksApiHelper.SafeCacheRefresh("MyComponent");
|
||||
|
||||
// 线程安全的缓存刷新(自动确保在UI线程执行)
|
||||
NavisworksApiHelper.SafeCacheRefreshUIThread("MyComponent");
|
||||
```
|
||||
|
||||
### 线程检查与执行
|
||||
|
||||
```csharp
|
||||
// 检查当前是否在主UI线程
|
||||
bool isUIThread = NavisworksApiHelper.IsOnUIThread();
|
||||
|
||||
// 在UI线程执行操作(无返回值)
|
||||
NavisworksApiHelper.ExecuteOnUIThread(() =>
|
||||
{
|
||||
// 这段代码确保在UI线程执行
|
||||
document.CurrentSelection.Clear();
|
||||
});
|
||||
|
||||
// 在UI线程执行操作(有返回值)
|
||||
var result = NavisworksApiHelper.ExecuteOnUIThread(() =>
|
||||
{
|
||||
return document.CurrentSelection.SelectedItems.Count;
|
||||
});
|
||||
```
|
||||
|
||||
### 模型项操作
|
||||
|
||||
```csharp
|
||||
// 获取ModelItem的显示名称(安全)
|
||||
string name = NavisworksApiHelper.GetModelItemName(modelItem);
|
||||
|
||||
// 使用PathId查找ModelItem
|
||||
ModelItem item = NavisworksApiHelper.FindModelItemByPathId(modelIndex, pathId);
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:API操作后刷新缓存
|
||||
|
||||
```csharp
|
||||
// 执行某些API操作
|
||||
document.Models.SetHidden(items, true);
|
||||
|
||||
// 刷新缓存以确保状态同步
|
||||
NavisworksApiHelper.SafeCacheRefresh("VisibilityManager");
|
||||
```
|
||||
|
||||
### 示例2:确保在UI线程操作
|
||||
|
||||
```csharp
|
||||
// 在后台线程中需要操作UI
|
||||
Task.Run(() =>
|
||||
{
|
||||
// 后台计算...
|
||||
var result = DoCalculation();
|
||||
|
||||
// 回到UI线程更新界面
|
||||
NavisworksApiHelper.ExecuteOnUIThread(() =>
|
||||
{
|
||||
StatusText = $"计算完成: {result}";
|
||||
ProgressBar.Value = 100;
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 示例3:查找模型项
|
||||
|
||||
```csharp
|
||||
// 从路径ID恢复模型项引用
|
||||
var item = NavisworksApiHelper.FindModelItemByPathId(0, "1/2/3/4");
|
||||
if (item != null)
|
||||
{
|
||||
LogManager.Info($"找到模型项: {item.DisplayName}");
|
||||
}
|
||||
```
|
||||
|
||||
### 示例4:获取模型项名称(安全)
|
||||
|
||||
```csharp
|
||||
// 安全的获取名称,处理空值和异常
|
||||
string name = NavisworksApiHelper.GetModelItemName(modelItem);
|
||||
// 如果 modelItem 为 null,返回 "未知对象"
|
||||
// 如果获取失败,返回 "获取失败"
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **缓存刷新机制**:使用空集合的 `SetHidden` 操作触发缓存更新,开销极小
|
||||
2. **线程安全**:`SafeCacheRefreshUIThread` 会自动检查当前线程,必要时切换到UI线程
|
||||
3. **异常处理**:所有方法内部都处理了异常,不会抛出错误
|
||||
4. **日志前缀**:传入的日志前缀用于标识调用来源,便于调试
|
||||
202
.agents/skills/project-tools/utils/NavisworksSelectionHelper.md
Normal file
202
.agents/skills/project-tools/utils/NavisworksSelectionHelper.md
Normal file
@ -0,0 +1,202 @@
|
||||
# NavisworksSelectionHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/NavisworksSelectionHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
提供 Navisworks 选择状态管理帮助功能,包括选择状态查询、格式化显示、事件订阅等。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 选择状态查询
|
||||
|
||||
```csharp
|
||||
// 获取当前选择状态信息(同步)
|
||||
SelectionStateResult result = NavisworksSelectionHelper.GetCurrentSelectionState();
|
||||
|
||||
// 获取当前选择状态信息(异步)
|
||||
SelectionStateResult result = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
|
||||
|
||||
// 快速检查是否有选中项
|
||||
bool hasSelection = NavisworksSelectionHelper.HasSelectedItems();
|
||||
```
|
||||
|
||||
### 设置选择
|
||||
|
||||
```csharp
|
||||
// 设置单个模型项为选中状态
|
||||
bool success = NavisworksSelectionHelper.SetModelSelection(modelItem);
|
||||
|
||||
// 设置多个模型项为选中状态
|
||||
bool success = NavisworksSelectionHelper.SetModelSelection(modelItems);
|
||||
// 传入 null 或空集合会清除选择
|
||||
```
|
||||
|
||||
### 选择文本格式化
|
||||
|
||||
```csharp
|
||||
// 格式化选择状态文本
|
||||
string text = NavisworksSelectionHelper.FormatSelectionText(
|
||||
count: result.Count,
|
||||
selectedItems: result.SelectedItems,
|
||||
unitName: "个模型", // 单位名称
|
||||
maxDisplayCount: 3, // 最多显示名称数量
|
||||
maxTotalLength: 80 // 最大总长度
|
||||
);
|
||||
|
||||
// 基于选择结果对象格式化
|
||||
string text = NavisworksSelectionHelper.FormatSelectionText(
|
||||
selectionResult: result,
|
||||
unitName: "个对象",
|
||||
maxDisplayCount: 3,
|
||||
maxTotalLength: 80
|
||||
);
|
||||
```
|
||||
|
||||
### 选择事件订阅
|
||||
|
||||
```csharp
|
||||
// 订阅选择变化事件
|
||||
var subscription = NavisworksSelectionHelper.SubscribeToSelectionChanges(
|
||||
async (selectionResult) =>
|
||||
{
|
||||
// 处理选择变化
|
||||
LogManager.Info($"选择变化: {selectionResult.Count} 个对象");
|
||||
},
|
||||
uiStateManager: _uiStateManager // 可选,用于确保UI线程执行
|
||||
);
|
||||
|
||||
// 取消订阅(使用完释放)
|
||||
subscription.Dispose();
|
||||
```
|
||||
|
||||
## SelectionStateResult 属性
|
||||
|
||||
```csharp
|
||||
public class SelectionStateResult
|
||||
{
|
||||
public bool Success { get; set; } // 操作是否成功
|
||||
public int Count { get; set; } // 选择数量
|
||||
public List<ModelItem> SelectedItems { get; set; } // 选择的项目列表
|
||||
public bool HasSelection { get; set; } // 是否有选择
|
||||
public string ErrorMessage { get; set; } // 错误信息(失败时)
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:检查并显示选择状态
|
||||
|
||||
```csharp
|
||||
// 获取选择状态
|
||||
var result = NavisworksSelectionHelper.GetCurrentSelectionState();
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
LogManager.Error($"获取选择状态失败: {result.ErrorMessage}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 格式化显示
|
||||
string statusText = NavisworksSelectionHelper.FormatSelectionText(result);
|
||||
StatusLabel.Text = statusText;
|
||||
|
||||
// 启用/禁用相关按钮
|
||||
EditButton.IsEnabled = result.Count == 1;
|
||||
DeleteButton.IsEnabled = result.Count > 0;
|
||||
```
|
||||
|
||||
### 示例2:同步UI选择状态
|
||||
|
||||
```csharp
|
||||
// 在ViewModel中保持选择状态同步
|
||||
private void UpdateSelectionState()
|
||||
{
|
||||
var result = NavisworksSelectionHelper.GetCurrentSelectionState();
|
||||
|
||||
if (result.Count > 0)
|
||||
{
|
||||
// 更新属性
|
||||
SelectedItems = result.SelectedItems;
|
||||
SelectionText = NavisworksSelectionHelper.FormatSelectionText(result);
|
||||
|
||||
// 如果有单个选择,显示详细信息
|
||||
if (result.Count == 1)
|
||||
{
|
||||
var item = result.SelectedItems[0];
|
||||
SelectedItemName = item.DisplayName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedItems = new List<ModelItem>();
|
||||
SelectionText = "请选择模型对象";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 示例3:订阅选择变化事件
|
||||
|
||||
```csharp
|
||||
public class MyViewModel : IDisposable
|
||||
{
|
||||
private SelectionEventSubscription _selectionSubscription;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// 订阅选择变化
|
||||
_selectionSubscription = NavisworksSelectionHelper.SubscribeToSelectionChanges(
|
||||
OnSelectionChanged,
|
||||
uiStateManager: _uiStateManager
|
||||
);
|
||||
}
|
||||
|
||||
private async Task OnSelectionChanged(SelectionStateResult result)
|
||||
{
|
||||
// 此方法在UI线程执行(通过uiStateManager)
|
||||
if (result.HasSelection)
|
||||
{
|
||||
SelectionText = NavisworksSelectionHelper.FormatSelectionText(result);
|
||||
await LoadSelectionDetails(result.SelectedItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectionText = "请在主界面中选择需要设置的对象";
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_selectionSubscription?.Dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 示例4:程序化设置选择
|
||||
|
||||
```csharp
|
||||
// 选择特定对象
|
||||
var targetItem = FindModelItemById(id);
|
||||
if (targetItem != null)
|
||||
{
|
||||
bool success = NavisworksSelectionHelper.SetModelSelection(targetItem);
|
||||
if (success)
|
||||
{
|
||||
// 聚焦到该对象
|
||||
ViewpointHelper.FocusOnModelItem(targetItem, 45, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
// 清除选择
|
||||
NavisworksSelectionHelper.SetModelSelection(null);
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **线程安全**:`GetCurrentSelectionState` 等方法是线程安全的,但设置选择最好在UI线程执行
|
||||
2. **事件处理**:选择变化事件使用 `async void` 内部处理,确保不会阻塞UI
|
||||
3. **订阅管理**:使用 `SelectionEventSubscription` 模式确保事件正确取消订阅,避免内存泄漏
|
||||
4. **格式化限制**:`FormatSelectionText` 会自动处理长名称截断和多个项目的显示
|
||||
5. **空值处理**:所有方法都处理了空值情况,不会抛出异常
|
||||
140
.agents/skills/project-tools/utils/PathHelper.md
Normal file
140
.agents/skills/project-tools/utils/PathHelper.md
Normal file
@ -0,0 +1,140 @@
|
||||
# PathHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/PathHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
提供文件路径相关的通用方法,包括插件目录管理、文件名处理、截图生成等。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 目录操作
|
||||
|
||||
```csharp
|
||||
// 获取插件目录路径
|
||||
string pluginDir = PathHelper.GetPluginDirectory();
|
||||
// 返回: C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin
|
||||
|
||||
// 获取截图目录路径
|
||||
string screenshotDir = PathHelper.GetScreenshotDirectory();
|
||||
|
||||
// 获取报告目录路径
|
||||
string reportDir = PathHelper.GetReportDirectory();
|
||||
|
||||
// 确保目录存在(不存在则创建)
|
||||
PathHelper.EnsureDirectoryExists("C:\\MyFolder\\SubFolder");
|
||||
```
|
||||
|
||||
### 文件名处理
|
||||
|
||||
```csharp
|
||||
// 清理文件名中的非法字符
|
||||
string safeName = PathHelper.SanitizeFileName("文件<名称>:非法*字符?");
|
||||
// 返回: "文件名称非法字符"
|
||||
|
||||
// 生成带时间戳的文件名
|
||||
string fileName = PathHelper.GenerateTimestampedFileName("screenshot", "png");
|
||||
// 返回: "screenshot_20240225_143052.png"
|
||||
```
|
||||
|
||||
### 路径计算
|
||||
|
||||
```csharp
|
||||
// 计算从HTML文件到目标文件的相对路径
|
||||
string relativePath = PathHelper.GetRelativePath(
|
||||
@"C:\reports\index.html",
|
||||
@"C:\images\photo.png"
|
||||
);
|
||||
// 返回: "../images/photo.png"
|
||||
```
|
||||
|
||||
### 图像格式转换
|
||||
|
||||
```csharp
|
||||
// ImageFormat 转文件扩展名
|
||||
string ext = PathHelper.ImageFormatToExtension(ImageFormat.Jpeg); // "jpg"
|
||||
string ext = PathHelper.ImageFormatToExtension(ImageFormat.Png); // "png"
|
||||
|
||||
// 文件扩展名转 ImageFormat
|
||||
ImageFormat format = PathHelper.ExtensionToImageFormat(".jpg"); // Jpeg
|
||||
ImageFormat format = PathHelper.ExtensionToImageFormat(".png"); // Png
|
||||
```
|
||||
|
||||
### 截图生成
|
||||
|
||||
```csharp
|
||||
// 生成场景截图到默认目录
|
||||
string path = PathHelper.GenerateSceneScreenshot(
|
||||
sceneName: "collision_view",
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
format: ImageFormat.Png,
|
||||
prefix: "collision"
|
||||
);
|
||||
// 返回: 截图文件完整路径
|
||||
|
||||
// 生成场景截图到指定目录
|
||||
string path = PathHelper.GenerateSceneScreenshotToDirectory(
|
||||
outputDirectory: @"C:\MyScreenshots",
|
||||
sceneName: "path_view",
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
format: ImageFormat.Jpeg,
|
||||
prefix: "path"
|
||||
);
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:生成带时间戳的报告文件
|
||||
|
||||
```csharp
|
||||
// 生成报告文件名
|
||||
string reportDir = PathHelper.GetReportDirectory();
|
||||
PathHelper.EnsureDirectoryExists(reportDir);
|
||||
|
||||
string safeRouteName = PathHelper.SanitizeFileName(route.Name);
|
||||
string reportFile = PathHelper.GenerateTimestampedFileName(
|
||||
$"collision_report_{safeRouteName}",
|
||||
"html"
|
||||
);
|
||||
string fullPath = Path.Combine(reportDir, reportFile);
|
||||
|
||||
// 保存报告...
|
||||
```
|
||||
|
||||
### 示例2:批量处理文件名
|
||||
|
||||
```csharp
|
||||
// 清理多个文件名
|
||||
var fileNames = new[] { "文件:1", "名称*2", "测试?3" };
|
||||
var safeNames = fileNames.Select(f => PathHelper.SanitizeFileName(f));
|
||||
// 结果: "文件1", "名称2", "测试3"
|
||||
```
|
||||
|
||||
### 示例3:生成碰撞报告截图
|
||||
|
||||
```csharp
|
||||
// 在显示碰撞结果后生成截图
|
||||
string screenshotPath = PathHelper.GenerateSceneScreenshot(
|
||||
sceneName: $"collision_{collisionId}",
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
format: ImageFormat.Png,
|
||||
prefix: "collision"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(screenshotPath))
|
||||
{
|
||||
LogManager.Info($"截图已保存: {screenshotPath}");
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **目录自动创建**:`GenerateSceneScreenshot` 会自动创建必要的目录
|
||||
2. **非法字符处理**:`SanitizeFileName` 会移除所有 Windows 文件系统不支持的字符
|
||||
3. **时间戳格式**:使用 `yyyyMMdd_HHmmss` 格式,确保文件名唯一且可排序
|
||||
4. **相对路径**:`GetRelativePath` 返回的路径使用正斜杠(/),适合在 HTML 中使用
|
||||
213
.agents/skills/project-tools/utils/SectionClipHelper.md
Normal file
213
.agents/skills/project-tools/utils/SectionClipHelper.md
Normal file
@ -0,0 +1,213 @@
|
||||
# SectionClipHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/SectionClipHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
剖面盒辅助类,用于优化碰撞检测性能。通过设置视口剖面盒,只处理路径周围的对象,大幅减少需要检测的对象数量。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 设置剖面盒
|
||||
|
||||
```csharp
|
||||
// 根据路径点列表设置剖面盒
|
||||
bool success = SectionClipHelper.SetClipBoxByPath(
|
||||
pathPoints: points,
|
||||
marginInMeters: 2.0, // 水平边距(米)
|
||||
heightMarginInMeters: 1.0 // 高度边距(米)
|
||||
);
|
||||
|
||||
// 根据路径点设置剖面盒(支持分别设置上下边距)
|
||||
bool success = SectionClipHelper.SetClipBoxByPathWithMargins(
|
||||
pathPoints: points,
|
||||
marginInMeters: 2.0,
|
||||
heightMarginBottomInMeters: 0.5, // 底部边距
|
||||
heightMarginTopInMeters: 2.0 // 顶部边距
|
||||
);
|
||||
|
||||
// 根据单个点设置剖面盒(用于吊装路径等)
|
||||
bool success = SectionClipHelper.SetClipBoxByPoint(
|
||||
centerPoint: point,
|
||||
rangeMeters: 10.0, // 范围(米)
|
||||
heightRangeMeters: 5.0 // 高度范围(米)
|
||||
);
|
||||
|
||||
// 根据楼层设置剖面盒
|
||||
bool success = SectionClipHelper.SetClipBoxByFloor(
|
||||
floorItem: floor,
|
||||
marginMeters: 1.0
|
||||
);
|
||||
```
|
||||
|
||||
### 清除剖面盒
|
||||
|
||||
```csharp
|
||||
// 清除剖面盒,显示全部模型
|
||||
SectionClipHelper.ClearClipBox();
|
||||
```
|
||||
|
||||
### 状态查询
|
||||
|
||||
```csharp
|
||||
// 检查剖面盒是否已启用
|
||||
bool isEnabled = SectionClipHelper.IsClipBoxEnabled;
|
||||
|
||||
// 获取当前剖面盒
|
||||
if (SectionClipHelper.TryGetCurrentClipBox(out BoundingBox3D clipBox))
|
||||
{
|
||||
LogManager.Info($"剖面盒范围: {clipBox.Min} - {clipBox.Max}");
|
||||
}
|
||||
```
|
||||
|
||||
### 包含性测试
|
||||
|
||||
```csharp
|
||||
// 测试点是否在剖面盒内
|
||||
bool isInside = SectionClipHelper.IsPointInClipBox(point);
|
||||
|
||||
// 测试包围盒是否与剖面盒相交
|
||||
bool intersects = SectionClipHelper.IntersectsClipBox(itemBox);
|
||||
|
||||
// 使用角点检测(排除大包围盒假阳性)
|
||||
bool intersects = SectionClipHelper.IntersectsByCornerPoints(itemBox, clipBox);
|
||||
|
||||
// 使用棱上自适应采样检测(长物体不会漏检)
|
||||
bool intersects = SectionClipHelper.IntersectsByEdgeSampling(
|
||||
itemBox, clipBox, minSamplesPerEdge: 3
|
||||
);
|
||||
```
|
||||
|
||||
### 统计功能
|
||||
|
||||
```csharp
|
||||
// 统计剖面盒内/外的对象数量
|
||||
SectionClipHelper.CountObjectsInClipBox(
|
||||
out int totalCount,
|
||||
out int insideCount,
|
||||
out int outsideCount
|
||||
);
|
||||
|
||||
// 使用角点检测统计(排除大包围盒假阳性)
|
||||
SectionClipHelper.CountObjectsInClipBoxByCorners(
|
||||
out int totalCount,
|
||||
out int insideCount,
|
||||
out int outsideCount,
|
||||
out int largeBoxFiltered,
|
||||
debugDetails: detailsList // 可选的详细信息列表
|
||||
);
|
||||
|
||||
// 测试相交检测(调试用)
|
||||
SectionClipHelper.TestIntersection();
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:路径碰撞检测前设置剖面盒
|
||||
|
||||
```csharp
|
||||
// 获取路径点
|
||||
var pathPoints = pathRoute.Points.Select(p => p.Position).ToList();
|
||||
|
||||
// 设置剖面盒
|
||||
bool success = SectionClipHelper.SetClipBoxByPath(
|
||||
pathPoints,
|
||||
marginInMeters: 2.0, // 路径周围2米
|
||||
heightMarginInMeters: 1.0 // 上下各1米
|
||||
);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// 统计过滤效果
|
||||
SectionClipHelper.CountObjectsInClipBoxByCorners(
|
||||
out int total, out int inside, out int outside, out int filtered
|
||||
);
|
||||
LogManager.Info($"剖面盒过滤: 总数{total}, 盒内{inside}, 过滤{filtered}");
|
||||
|
||||
// 执行碰撞检测(只检测剖面盒内对象)
|
||||
var collisions = collisionDetector.DetectCollisions();
|
||||
}
|
||||
|
||||
// 完成后清除剖面盒
|
||||
SectionClipHelper.ClearClipBox();
|
||||
```
|
||||
|
||||
### 示例2:吊装路径场景
|
||||
|
||||
```csharp
|
||||
// 吊装路径通常只需要关注起吊点周围区域
|
||||
if (liftPoint != null)
|
||||
{
|
||||
SectionClipHelper.SetClipBoxByPoint(
|
||||
liftPoint,
|
||||
rangeMeters: 15.0, // 15米范围
|
||||
heightRangeMeters: 20.0 // 20米高度范围
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 示例3:精确过滤(排除大包围盒假阳性)
|
||||
|
||||
```csharp
|
||||
// 获取剖面盒
|
||||
if (!SectionClipHelper.TryGetCurrentClipBox(out var clipBox))
|
||||
return;
|
||||
|
||||
// 遍历模型进行过滤
|
||||
foreach (var item in modelItems)
|
||||
{
|
||||
var itemBox = item.BoundingBox();
|
||||
|
||||
// 先用包围盒快速排除
|
||||
if (!clipBox.Intersects(itemBox))
|
||||
continue;
|
||||
|
||||
// 再用角点检测精确判断
|
||||
if (!SectionClipHelper.IntersectsByCornerPoints(itemBox, clipBox))
|
||||
{
|
||||
// 包围盒相交但没有角点在盒内,可能是大包围盒假阳性
|
||||
LogManager.Debug($"跳过假阳性: {item.DisplayName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 该对象真正与剖面盒相交,加入检测列表
|
||||
itemsToCheck.Add(item);
|
||||
}
|
||||
```
|
||||
|
||||
### 示例4:长物体检测(使用棱上采样)
|
||||
|
||||
```csharp
|
||||
// 对于长管道等物体,使用棱上采样确保不遗漏
|
||||
if (SectionClipHelper.TryGetCurrentClipBox(out var clipBox))
|
||||
{
|
||||
var itemBox = longPipeItem.BoundingBox();
|
||||
|
||||
// 使用棱上自适应采样(根据物体大小动态计算采样点)
|
||||
if (SectionClipHelper.IntersectsByEdgeSampling(itemBox, clipBox, minSamplesPerEdge: 5))
|
||||
{
|
||||
// 长管道与剖面盒相交
|
||||
itemsToCheck.Add(longPipeItem);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 默认参数
|
||||
|
||||
```csharp
|
||||
private const double DEFAULT_MARGIN_METERS = 2.0; // 默认水平边距
|
||||
private const double DEFAULT_HEIGHT_MARGIN_METERS = 1.0; // 默认高度边距
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **性能优化**:剖面盒可以大幅减少碰撞检测的对象数量,提高性能
|
||||
2. **JSON设置**:使用 JSON 字符串方式设置剖面盒,避免 "Object is Read-Only" 错误
|
||||
3. **过滤策略**:
|
||||
- 先用 `IntersectsClipBox` 快速排除
|
||||
- 再用 `IntersectsByCornerPoints` 排除大包围盒假阳性
|
||||
- 最后用 `IntersectsByEdgeSampling` 确保长物体不遗漏
|
||||
4. **清除责任**:使用完剖面盒后应调用 `ClearClipBox()` 恢复完整视图
|
||||
5. **统计功能**:使用 `CountObjectsInClipBoxByCorners` 查看过滤效果和假阳性数量
|
||||
144
.agents/skills/project-tools/utils/ViewpointHelper.md
Normal file
144
.agents/skills/project-tools/utils/ViewpointHelper.md
Normal file
@ -0,0 +1,144 @@
|
||||
# ViewpointHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/ViewpointHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
提供 Navisworks 视角调整功能,用于自动调整摄像机位置和视角,支持路径居中显示、碰撞位置聚焦等。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 路径视角调整
|
||||
|
||||
```csharp
|
||||
// 智能调整视角到路径中心
|
||||
ViewpointHelper.AdjustViewpointSmart(path, collisions);
|
||||
|
||||
// 调整视角到路径中心,确保整个路径在视野内
|
||||
ViewpointHelper.AdjustViewpointToPathCenter(path);
|
||||
|
||||
// 计算路径的包围盒
|
||||
BoundingBox3D bounds = ViewpointHelper.CalculatePathBoundingBox(path);
|
||||
```
|
||||
|
||||
### 碰撞视角调整
|
||||
|
||||
```csharp
|
||||
// 计算碰撞位置的包围盒
|
||||
BoundingBox3D bounds = ViewpointHelper.CalculateCollisionsBoundingBox(collisions);
|
||||
|
||||
// 聚焦到碰撞对象(两个对象)
|
||||
ViewpointHelper.FocusOnCollision(item1, item2, viewAngleDegrees: 45, targetViewRatio: 0.25);
|
||||
|
||||
// 聚焦到指定位置
|
||||
ViewpointHelper.FocusOnPosition(center, targetSize, viewAngleDegrees: 45, targetViewRatio: 0.25);
|
||||
```
|
||||
|
||||
### 模型元素聚焦
|
||||
|
||||
```csharp
|
||||
// 聚焦到单个模型元素
|
||||
ViewpointHelper.FocusOnModelItem(modelItem, viewAngleDegrees: 45, targetViewRatio: 0.25);
|
||||
// viewAngleDegrees: 视角角度(度)
|
||||
// targetViewRatio: 目标占据视图比例(0.25 = 1/4)
|
||||
```
|
||||
|
||||
### 视角保存与恢复
|
||||
|
||||
```csharp
|
||||
// 保存当前视角
|
||||
Viewpoint savedViewpoint = ViewpointHelper.SaveCurrentViewpoint();
|
||||
|
||||
// 恢复视角
|
||||
ViewpointHelper.RestoreViewpoint(savedViewpoint);
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:生成碰撞报告前调整视角
|
||||
|
||||
```csharp
|
||||
// 保存当前视角
|
||||
Viewpoint originalViewpoint = ViewpointHelper.SaveCurrentViewpoint();
|
||||
|
||||
try
|
||||
{
|
||||
// 调整视角到路径中心
|
||||
ViewpointHelper.AdjustViewpointToPathCenter(path);
|
||||
|
||||
// 生成截图
|
||||
string screenshotPath = PathHelper.GenerateSceneScreenshot(
|
||||
"collision_report", 1920, 1080, ImageFormat.Png
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 恢复原始视角
|
||||
ViewpointHelper.RestoreViewpoint(originalViewpoint);
|
||||
}
|
||||
```
|
||||
|
||||
### 示例2:聚焦到碰撞位置
|
||||
|
||||
```csharp
|
||||
// 检测到碰撞后,聚焦到碰撞对象
|
||||
if (collision.Item1 != null && collision.Item2 != null)
|
||||
{
|
||||
ViewpointHelper.FocusOnCollision(
|
||||
collision.Item1,
|
||||
collision.Item2,
|
||||
viewAngleDegrees: 45, // 45度视角
|
||||
targetViewRatio: 0.3 // 占据视图30%
|
||||
);
|
||||
|
||||
// 高亮碰撞对象
|
||||
ModelHighlightHelper.HighlightItems("collision", new[] { collision.Item1, collision.Item2 });
|
||||
}
|
||||
```
|
||||
|
||||
### 示例3:聚焦到特定模型元素
|
||||
|
||||
```csharp
|
||||
// 用户选择了一个门对象
|
||||
var doorItem = selectedItems.FirstOrDefault();
|
||||
if (doorItem != null)
|
||||
{
|
||||
// 聚焦到该门,45度斜上方视角
|
||||
ViewpointHelper.FocusOnModelItem(doorItem, 45, 0.25);
|
||||
|
||||
LogManager.Info($"已聚焦到: {doorItem.DisplayName}");
|
||||
}
|
||||
```
|
||||
|
||||
### 示例4:路径规划完成后调整视角
|
||||
|
||||
```csharp
|
||||
// 路径规划完成
|
||||
if (pathRoute.Points.Count > 0)
|
||||
{
|
||||
// 智能调整视角
|
||||
ViewpointHelper.AdjustViewpointSmart(pathRoute, collisionResults);
|
||||
|
||||
// 高亮路径点
|
||||
var pathItems = pathRoute.Points.Select(p => p.AssociatedModelItem).Where(i => i != null);
|
||||
ModelHighlightHelper.HighlightItems("pathPreview", pathItems);
|
||||
}
|
||||
```
|
||||
|
||||
## 视角参数说明
|
||||
|
||||
| 参数 | 说明 | 推荐值 |
|
||||
|------|------|--------|
|
||||
| `viewAngleDegrees` | 相机视角角度(度) | 45°(斜上方) |
|
||||
| `targetViewRatio` | 目标占据视图比例 | 0.25(1/4视图) |
|
||||
| `baseDimension` | 基准尺寸计算相机距离 | 路径长度或包围盒最大边 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **视角保存**:在进行视角调整前建议保存当前视角,便于后续恢复
|
||||
2. **异常处理**:方法会抛出 `InvalidOperationException`(无活动文档)和 `ArgumentException`(参数错误),需要适当捕获
|
||||
3. **单位转换**:内部自动使用 `UnitsConverter` 进行米和模型单位的转换
|
||||
4. **标准视角**:`FocusOnModelItem` 和 `FocusOnPosition` 使用模型的标准前右上视角(`FrontRightTopViewVector`)
|
||||
5. **性能考虑**:频繁调整视角可能影响性能,建议在关键操作后统一调整
|
||||
112
.agents/skills/project-tools/utils/VisibilityHelper.md
Normal file
112
.agents/skills/project-tools/utils/VisibilityHelper.md
Normal file
@ -0,0 +1,112 @@
|
||||
# VisibilityHelper 使用指南
|
||||
|
||||
## 文件位置
|
||||
|
||||
`src/Utils/VisibilityHelper.cs`
|
||||
|
||||
## 用途
|
||||
|
||||
可见性管理器,负责 ModelItem 可见性控制的核心业务逻辑,包括显示全部、隔离显示、设置可见性等。
|
||||
|
||||
## 核心方法
|
||||
|
||||
### 显示所有项目
|
||||
|
||||
```csharp
|
||||
// 显示所有模型项目(重置所有隐藏状态)
|
||||
bool success = VisibilityHelper.ShowAllItems();
|
||||
```
|
||||
|
||||
### 隔离显示
|
||||
|
||||
```csharp
|
||||
// 仅显示指定的模型项集合,隐藏其他所有项
|
||||
bool success = VisibilityHelper.IsolateSpecificItems(itemsToShow);
|
||||
|
||||
// 示例:隔离显示路径相关的对象
|
||||
var pathItems = GetPathRelatedItems();
|
||||
VisibilityHelper.IsolateSpecificItems(pathItems);
|
||||
```
|
||||
|
||||
### 设置可见性
|
||||
|
||||
```csharp
|
||||
// 设置指定模型项集合的可见性
|
||||
bool success = VisibilityHelper.SetItemsVisibility(items, isHidden: true); // 隐藏
|
||||
bool success = VisibilityHelper.SetItemsVisibility(items, isHidden: false); // 显示
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:隔离显示碰撞对象
|
||||
|
||||
```csharp
|
||||
// 收集所有碰撞涉及的对象
|
||||
var collisionItems = new ModelItemCollection();
|
||||
foreach (var collision in collisionResults)
|
||||
{
|
||||
if (collision.Item1 != null) collisionItems.Add(collision.Item1);
|
||||
if (collision.Item2 != null) collisionItems.Add(collision.Item2);
|
||||
}
|
||||
|
||||
// 只显示碰撞对象
|
||||
VisibilityHelper.IsolateSpecificItems(collisionItems);
|
||||
|
||||
// 高亮碰撞对象
|
||||
ModelHighlightHelper.HighlightItems("collisions", collisionItems);
|
||||
```
|
||||
|
||||
### 示例2:分步显示/隐藏
|
||||
|
||||
```csharp
|
||||
// 隐藏所有障碍物
|
||||
var obstacles = GetObstacleItems();
|
||||
VisibilityHelper.SetItemsVisibility(obstacles, isHidden: true);
|
||||
|
||||
// 后续操作...
|
||||
|
||||
// 重新显示障碍物
|
||||
VisibilityHelper.SetItemsVisibility(obstacles, isHidden: false);
|
||||
```
|
||||
|
||||
### 示例3:完整的显示重置流程
|
||||
|
||||
```csharp
|
||||
// 清除所有高亮
|
||||
ModelHighlightHelper.ClearAllHighlights();
|
||||
|
||||
// 显示所有项目
|
||||
VisibilityHelper.ShowAllItems();
|
||||
|
||||
// 清除剖面盒
|
||||
SectionClipHelper.ClearClipBox();
|
||||
|
||||
LogManager.Info("视图已重置");
|
||||
```
|
||||
|
||||
### 示例4:通道可视化
|
||||
|
||||
```csharp
|
||||
// 只显示通道相关的对象
|
||||
var channelItems = GetChannelItems();
|
||||
VisibilityHelper.IsolateSpecificItems(channelItems);
|
||||
|
||||
// 调整视角到通道
|
||||
ViewpointHelper.AdjustViewpointToPathCenter(channelPath);
|
||||
|
||||
// 生成通道预览图
|
||||
string screenshot = PathHelper.GenerateSceneScreenshot(
|
||||
"channel_view", 1920, 1080, ImageFormat.Png
|
||||
);
|
||||
|
||||
// 恢复显示所有
|
||||
VisibilityHelper.ShowAllItems();
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **隔离显示原理**:`IsolateSpecificItems` 会先显示所有,然后隐藏不需要的项目
|
||||
2. **祖先节点处理**:隔离显示会自动包含选中项的所有祖先节点,确保路径完整
|
||||
3. **性能考虑**:大量项目的可见性操作可能影响性能,建议批量处理
|
||||
4. **与剖面盒配合**:可以与 `SectionClipHelper` 配合使用,进一步减少可见对象
|
||||
5. **错误处理**:所有方法都返回 `bool` 表示成功/失败,内部已处理异常
|
||||
Loading…
Reference in New Issue
Block a user