293 lines
7.1 KiB
Markdown
293 lines
7.1 KiB
Markdown
# Navisworks API 常用模式
|
||
|
||
## 1. 模型遍历
|
||
|
||
### 遍历所有模型项
|
||
|
||
```csharp
|
||
// 获取所有模型项
|
||
IEnumerable<ModelItem> allItems =
|
||
Application.ActiveDocument.Models.RootItemDescendantsAndSelf;
|
||
|
||
// 遍历特定模型
|
||
foreach (Model model in document.Models)
|
||
{
|
||
foreach (ModelItem item in model.RootItem.DescendantsAndSelf)
|
||
{
|
||
// 处理每个模型项
|
||
}
|
||
}
|
||
```
|
||
|
||
### 获取子节点
|
||
|
||
```csharp
|
||
// 获取所有后代(不包括自己)
|
||
var childItems = selectedItem.DescendantsAndSelf.Where(x => x != selectedItem);
|
||
|
||
// 只获取直接子节点
|
||
foreach (ModelItem child in parentItem.Children) { }
|
||
|
||
// 向上遍历祖先
|
||
var current = selectedItem.Parent;
|
||
while (current != null)
|
||
{
|
||
current = current.Parent;
|
||
}
|
||
```
|
||
|
||
## 2. 搜索和查询
|
||
|
||
### 使用 Search 类
|
||
|
||
```csharp
|
||
Search search = new Search();
|
||
|
||
// 添加搜索条件
|
||
search.SearchConditions.Add(
|
||
SearchCondition.HasCategoryByName(PropertyCategoryNames.Geometry));
|
||
search.SearchConditions.Add(
|
||
SearchCondition.HasPropertyByName(PropertyCategoryNames.Item, DataPropertyNames.ItemHidden)
|
||
.EqualValue(VariantData.FromBoolean(false)));
|
||
|
||
// 设置搜索范围
|
||
search.Selection.SelectAll();
|
||
search.Locations = SearchLocations.DescendantsAndSelf;
|
||
|
||
// 执行搜索
|
||
ModelItemCollection results = search.FindAll(document, false);
|
||
```
|
||
|
||
### 使用 LINQ 查询
|
||
|
||
```csharp
|
||
var results = document.Models.RootItemDescendantsAndSelf
|
||
.Where(x => x.HasGeometry && !x.IsHidden)
|
||
.Where(x => x.ClassDisplayName.ToLower().Contains("wall"));
|
||
```
|
||
|
||
## 3. 选择操作
|
||
|
||
```csharp
|
||
// 获取当前选择
|
||
var currentSelection = document.CurrentSelection.SelectedItems;
|
||
|
||
// 清空选择
|
||
document.CurrentSelection.Clear();
|
||
|
||
// 添加到选择
|
||
document.CurrentSelection.Add(modelItem);
|
||
|
||
// 复制集合到选择
|
||
document.CurrentSelection.CopyFrom(modelItems);
|
||
```
|
||
|
||
## 4. 可见性控制
|
||
|
||
```csharp
|
||
// 隐藏项目
|
||
ModelItemCollection itemsToHide = new ModelItemCollection();
|
||
itemsToHide.Add(modelItem);
|
||
document.Models.SetHidden(itemsToHide, true);
|
||
|
||
// 显示项目
|
||
document.Models.SetHidden(itemsToHide, false);
|
||
|
||
// 检查是否隐藏
|
||
if (modelItem.IsHidden) { }
|
||
```
|
||
|
||
## 5. 文件导出
|
||
|
||
```csharp
|
||
// 保存 NWD 文件
|
||
document.SaveFile(filePath);
|
||
|
||
// 使用导出选项
|
||
var exportOptions = new NwdExportOptions();
|
||
exportOptions.ExcludeHiddenItems = true;
|
||
exportOptions.EmbedXrefs = false;
|
||
exportOptions.PreventObjectPropertyExport = false;
|
||
|
||
document.ExportToNwd(saveFilePath, exportOptions);
|
||
```
|
||
|
||
## 6. Transform 变换操作
|
||
|
||
### 核心概念
|
||
|
||
- `ModelItem.Transform` - 返回设计文件中的原始变换(只读)
|
||
- `OverridePermanentTransform()` - 应用增量变换(累积)
|
||
- `ResetPermanentTransform()` - 清除所有增量变换
|
||
- `ModelItem.BoundingBox()` - 返回当前实际显示的包围盒
|
||
|
||
### 应用变换
|
||
|
||
```csharp
|
||
// 获取原始 Transform
|
||
Transform3D originalTransform = modelItem.Transform;
|
||
|
||
// 应用增量变换
|
||
var doc = Application.ActiveDocument;
|
||
var modelItems = new ModelItemCollection { modelItem };
|
||
doc.Models.OverridePermanentTransform(modelItems, newTransform, false);
|
||
|
||
// 重置到原始位置
|
||
doc.Models.ResetPermanentTransform(modelItems);
|
||
```
|
||
|
||
### 绕物体中心旋转(需要补偿)
|
||
|
||
```csharp
|
||
// 关键:API 的旋转总是绕世界原点(0,0,0)
|
||
// 要实现绕物体中心旋转,需要计算补偿
|
||
|
||
double deltaYaw = newYaw - currentYaw;
|
||
double cos = Math.Cos(deltaYaw);
|
||
double sin = Math.Sin(deltaYaw);
|
||
|
||
// 计算绕原点旋转后的位置
|
||
double rotatedX = currentPosition.X * cos - currentPosition.Y * sin;
|
||
double rotatedY = currentPosition.X * sin + currentPosition.Y * cos;
|
||
|
||
// 计算补偿平移
|
||
var compensatedTranslation = new Vector3D(
|
||
newPosition.X - rotatedX,
|
||
newPosition.Y - rotatedY,
|
||
newPosition.Z - currentPosition.Z
|
||
);
|
||
|
||
// 组合变换
|
||
var identity = Transform3D.CreateTranslation(new Vector3D(0, 0, 0));
|
||
var components = identity.Factor();
|
||
components.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), deltaYaw);
|
||
components.Translation = compensatedTranslation;
|
||
|
||
var incrementalTransform = components.Combine();
|
||
doc.Models.OverridePermanentTransform(modelItems, incrementalTransform, false);
|
||
```
|
||
|
||
## 7. 属性访问
|
||
|
||
### NET API 方式
|
||
|
||
```csharp
|
||
// 查找属性分类
|
||
var category = item.PropertyCategories.FindCategoryByDisplayName("Material");
|
||
|
||
// 基础属性
|
||
string displayName = item.DisplayName;
|
||
string className = item.ClassName;
|
||
bool hasGeometry = item.HasGeometry;
|
||
bool isHidden = item.IsHidden;
|
||
```
|
||
|
||
### COM API 方式(当 NET API 不满足需求时使用)
|
||
|
||
**参考**: `doc/navisworks_api/NET/examples/Basic Examples/CSharp/APICallsCOMPlugin/`
|
||
|
||
```csharp
|
||
using Autodesk.Navisworks.ComApi;
|
||
using Autodesk.Navisworks.Interop.ComApi;
|
||
|
||
// 获取 COM 状态
|
||
ComApi.InwOpState10 state = ComApiBridge.State;
|
||
|
||
// 获取属性节点
|
||
InwOpSelection2 selection = state.CurrentSelection as InwOpSelection2;
|
||
InwGUIPropertyNode2 propertyNode =
|
||
state.GetGUIPropertyNode(selection.Paths()[1], true) as InwGUIPropertyNode2;
|
||
|
||
// 遍历属性分类
|
||
foreach (InwGUIAttribute2 guiAttribute in propertyNode.GUIAttributes())
|
||
{
|
||
foreach (InwOaProperty property in guiAttribute.Properties())
|
||
{
|
||
string name = property.name;
|
||
string value = property.value;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 添加自定义属性(COM API)
|
||
|
||
```csharp
|
||
InwOaPropertyVec propertyVector =
|
||
state.ObjectFactory(nwEObjectType.eObjectType_nwOaPropertyVec);
|
||
|
||
InwOaProperty property =
|
||
state.ObjectFactory(nwEObjectType.eObjectType_nwOaProperty);
|
||
property.name = "CustomProperty1";
|
||
property.UserName = "自定义属性1";
|
||
property.value = value;
|
||
|
||
propertyVector.Properties().Add(property);
|
||
propertyNode.SetUserDefined(0, categoryName, internalName, propertyVector);
|
||
```
|
||
|
||
## 8. 线程安全 - 关键
|
||
|
||
**所有 Navisworks API 调用必须在主 UI 线程中执行**
|
||
|
||
```csharp
|
||
// ❌ 错误:在后台线程调用
|
||
await Task.Run(() =>
|
||
{
|
||
var document = Application.ActiveDocument; // 可能崩溃
|
||
});
|
||
|
||
// ✅ 正确:使用 Dispatcher.Invoke
|
||
await Task.Run(() =>
|
||
{
|
||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
var document = Application.ActiveDocument;
|
||
document.ExportToNwd(path, options); // 安全执行
|
||
});
|
||
});
|
||
```
|
||
|
||
### 检查线程状态
|
||
|
||
```csharp
|
||
var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState();
|
||
bool isMainThread = System.Windows.Application.Current.Dispatcher.CheckAccess();
|
||
```
|
||
|
||
## 9. 碰撞检测 (ClashDetective)
|
||
|
||
```csharp
|
||
// 获取碰撞测试
|
||
document.ClashTestsData.Tests;
|
||
|
||
// 创建碰撞选择
|
||
var selectionA = new ClashSelection(modelItemsA, document);
|
||
var selectionB = new ClashSelection(modelItemsB, document);
|
||
|
||
// 创建碰撞测试
|
||
var clashTest = new ClashTest();
|
||
clashTest.Name = "Test Name";
|
||
clashTest.TestType = ClashTestType.Hard;
|
||
clashTest.SelectionA = selectionA;
|
||
clashTest.SelectionB = selectionB;
|
||
```
|
||
|
||
## 10. TimeLiner 集成
|
||
|
||
```csharp
|
||
// 获取 TimeLiner 数据
|
||
var timeliner = document.Timeliner;
|
||
|
||
// 添加任务
|
||
var task = new TimelinerTask();
|
||
task.Name = "Task Name";
|
||
task.SimulationStatus = SimulationStatus.Active;
|
||
task.StartDate = DateTime.Now;
|
||
task.EndDate = DateTime.Now.AddDays(7);
|
||
|
||
timeliner.Tasks.Add(task);
|
||
|
||
// 关联模型项
|
||
task.Selection.CopyFrom(modelItems);
|
||
```
|