# Navisworks API 常用模式 ## 1. 模型遍历 ### 遍历所有模型项 ```csharp // 获取所有模型项 IEnumerable 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); ```