从“选择面”到“选择任何东西”:一个C# NXOpen SelectionType数组的万能配置指南
从“选择面”到“选择任何东西”:一个C# NXOpen SelectionType数组的万能配置指南
在NXOpen二次开发中,对象选择是最基础却又最关键的交互环节。传统做法往往为每种对象类型单独编写选择逻辑——选择面、边、体各有一套代码,这不仅造成代码冗余,更限制了用户操作的灵活性。本文将揭示如何通过SelectionType数组的动态配置,实现真正通用的对象选择器,让用户在一个对话框内自由切换选择面、边、体、特征等多种类型,同时保持代码的健壮性与可维护性。
1. SelectionType数组的核心机制
NXOpen的SelectObject方法通过SelectionType[]参数控制可选对象类型。理解其工作原理是构建通用选择器的第一步:
Selection.SelectionType[] typeArray = new Selection.SelectionType[] { Selection.SelectionType.Faces, Selection.SelectionType.Edges, Selection.SelectionType.Bodies };关键特性:
- 多类型共存:数组可包含任意数量类型,用户可在同一会话中选择不同对象
- 优先级顺序:数组元素的顺序影响选择过滤器的默认激活顺序
- 运行时动态修改:可根据上下文实时调整数组内容
下表展示了常用SelectionType与其对应的NX对象类型:
| SelectionType | NX对象类型 | 典型应用场景 |
|---|---|---|
| Faces | Face | 曲面分析、加工区域定义 |
| Edges | Edge | 倒角、边界条件设置 |
| Bodies | Body | 布尔运算、实体操作 |
| Features | Feature | 特征抑制、参数修改 |
| DatumAxes | DatumAxis | 参考轴创建、对齐操作 |
2. 动态类型配置的实现策略
2.1 可配置的选择器封装
创建一个接受类型参数的方法,取代硬编码的SelectionType数组:
public NXObject SelectDynamic( Selection.SelectionType[] allowedTypes, string prompt = "请选择对象") { UI theUI = UI.GetUI(); Selection.SelectionScope scope = Selection.SelectionScope.WorkPart; bool keepHighlighted = false; Point3d cursor; NXObject selectedObj; theUI.SelectionManager.SelectObject( prompt, prompt, scope, keepHighlighted, allowedTypes, out selectedObj, out cursor); return selectedObj; }调用示例:
// 允许选择面和边 var types = new[] { Selection.SelectionType.Faces, Selection.SelectionType.Edges }; Face face = SelectDynamic(types, "选择加工面或边界") as Face;2.2 类型安全转换的最佳实践
多类型选择需要安全的类型转换机制。推荐使用as运算符配合null检查:
public bool TryConvert<T>(NXObject obj, out T result) where T : class { result = obj as T; return result != null; } // 使用示例 if (TryConvert(selectedObj, out Face face)) { // 处理面对象 } else if (TryConvert(selectedObj, out Edge edge)) { // 处理边对象 }3. 高级交互增强技巧
3.1 上下文感知的类型过滤
根据当前工作状态动态调整可选类型:
public Selection.SelectionType[] GetContextualTypes() { var types = new List<Selection.SelectionType>(); // 如果当前有激活的体 if (WorkPart.Bodies.Any(b => b.IsActive)) { types.Add(Selection.SelectionType.Faces); types.Add(Selection.SelectionType.Edges); } // 如果存在特征树 if (WorkPart.Features.Count > 0) { types.Add(Selection.SelectionType.Features); } return types.ToArray(); }3.2 多阶段选择流程
通过保存选择状态实现复杂的选择逻辑:
public class SelectionSession { public List<NXObject> SelectedObjects { get; } = new List<NXObject>(); public Selection.SelectionType[] AllowedTypes { get; set; } public void RunInteractiveSession() { while (true) { var obj = SelectDynamic(AllowedTypes); if (obj == null) break; SelectedObjects.Add(obj); UpdateUIWithSelection(obj); } } }4. 异常处理与用户体验优化
4.1 健壮的错误处理框架
构建统一的错误处理机制应对各种选择场景:
public T SafeSelect<T>(Selection.SelectionType[] types) where T : NXObject { try { var obj = SelectDynamic(types); if (obj == null) throw new OperationCanceledException(); T specificObj = obj as T; if (specificObj == null) { throw new InvalidCastException( $"选中的对象不是{typeof(T).Name}类型"); } return specificObj; } catch (Exception ex) { UI.GetUI().NXMessageBox.Show("选择错误", MessageBox.DialogType.Error, ex.Message); return null; } }4.2 视觉反馈增强
通过高亮和标签提升交互明确性:
void HighlightWithLabel(NXObject obj, string label) { var highlight = WorkPart.Views.CreateHighlight(); highlight.AddObject(obj); var noteBuilder = WorkPart.Annotations.CreateNoteBuilder(); noteBuilder.Text.Text = label; noteBuilder.Origin.SetPoint(obj.GetBoundingBox().Center); noteBuilder.Commit(); }5. 实战:构建通用选择器组件
将上述技术整合为可复用的选择器组件:
public class UniversalSelector { public SelectionResponse Select( SelectionConfig config, SelectionContext context) { // 动态生成类型数组 var types = GenerateTypes(config, context); // 执行选择 var obj = SelectDynamic(types, config.Prompt); // 处理结果 return ProcessSelection(obj, config.ExpectedType); } private Selection.SelectionType[] GenerateTypes( SelectionConfig config, SelectionContext context) { // 实现动态类型生成逻辑 } private SelectionResponse ProcessSelection( NXObject obj, Type expectedType) { // 实现结果处理和类型转换 } } // 配置类示例 public class SelectionConfig { public string Prompt { get; set; } public Type ExpectedType { get; set; } public bool AllowMultiple { get; set; } }6. 性能优化与高级技巧
对于复杂场景的选择性能优化:
// 预过滤技术示例 public IEnumerable<Face> PrefilterFaces(Func<Face, bool> predicate) { return WorkPart.Bodies .SelectMany(b => b.GetFaces()) .Where(predicate) .ToList(); } // 使用预过滤结果 var candidateFaces = PrefilterFaces(f => f.Area > 10.0); var face = SelectFromCollection( candidateFaces, "请选择大面积面");性能对比表:
| 方法 | 选择响应时间 | 内存占用 | 适用场景 |
|---|---|---|---|
| 标准选择 | 中等 | 低 | 简单选择、少量对象 |
| 预过滤选择 | 快 | 高 | 复杂条件、大型装配体 |
| 区域限制选择 | 最快 | 中等 | 局部区域密集选择 |
在实现通用选择逻辑时,记得始终考虑用户的实际工作流程。一个好的选择器应该像熟练的助手——知道什么时候该严格限制选择类型,什么时候该保持灵活。通过文中的技术组合,你的NXOpen工具将获得前所未有的交互自由度,同时保持代码的清晰与健壮。
