1. UG NX二次开发基础环境搭建
在开始uc1616函数开发前,我们需要先搭建完整的NX二次开发环境。NX二次开发主要使用C/C++语言,通过NX Open API与UG NX软件进行交互。以下是环境配置的关键步骤:
1.1 开发工具准备
Visual Studio 2012是NX 10.0官方推荐的开发环境,我们需要安装以下组件:
- Visual Studio 2012 Professional或更高版本
- Windows SDK 8.0
- NX 10.0开发包(包含NXOpen头文件和库文件)
安装完成后,需要配置VS2012的项目属性:
- 在"VC++目录"中添加NXOpen头文件路径(通常位于NX安装目录下的UGOPEN目录)
- 在"链接器-输入"中添加NXOpen库文件(如libufun.lib、libugopenint.lib等)
- 设置平台工具集为"Visual Studio 2012 (v110)"
- 目标平台设置为x64
1.2 NX Open API基础结构
NX二次开发采用DLL插件机制,每个自定义功能都编译为独立的DLL文件。核心结构包括:
- ufusr函数:DLL的主入口点,NX加载DLL时调用
- ufusr_ask_unload函数:控制DLL卸载行为
- UF_initialize/UF_terminate:初始化和清理NX Open环境
基础代码框架如下:
cpp复制#include <uf.h>
#include <uf_ui.h>
#define DllExport __declspec(dllexport)
extern "C" DllExport void ufusr(char *param, int *retcode, int param_len)
{
if(UF_initialize() != 0) return;
// 功能代码
UF_terminate();
}
extern "C" DllExport int ufusr_ask_unload(void)
{
return UF_UNLOAD_IMMEDIATELY;
}
2. uc1616函数深度解析
uc1616是NX Open API中用于交互式点选择的核心函数,定义在uf_ui.h头文件中。该函数实现了NX软件中常见的点选择对话框功能。
2.1 函数原型与参数说明
函数完整原型如下:
cpp复制int uc1616(
char * cue, // 用户提示信息
int mode[2], // 选择模式和偏移模式
int point_display_mode, // 临时点显示控制
double point[3] // 返回的点坐标
);
各参数详细说明:
2.1.1 cue参数
- 类型:char*(字符指针)
- 作用:显示在点选择对话框上的提示信息
- 限制:最大40个字符(实际使用建议不超过36字符,因为系统会自动追加PT1等后缀)
2.1.2 mode参数
- 类型:int[2](整型数组)
- 作用:控制点的选择方式和偏移模式
- mode[0]:选择类型
- 0 = 显示菜单由用户选择(推断)
- 1 = 光标位置
- 4 = 现有点
- 5 = 端点
- 6 = 控制点
- 7 = 交点
- 8 = 圆弧/椭圆/球心
- 12 = 象限点
- 13 = 曲线/边上的点
- 14 = 曲面上的点
- mode[1]:偏移模式
- 0 = 无偏移
- 1 = 直角坐标绝对偏移
- 3 = 圆柱坐标偏移
- 4 = 球坐标偏移
- 5 = 3D矢量偏移
2.1.3 point_display_mode参数
- 类型:int
- 作用:控制是否显示临时点
- 0 = 显示临时点
- 1 = 不显示临时点
2.1.4 point参数
- 类型:double[3]
- 作用:输出参数,返回用户选择的点坐标(x,y,z)
- 注意:仅当函数返回值为5时有效
2.2 返回值解析
uc1616函数返回一个整数值,表示用户的操作结果:
| 返回值 | 含义 |
|---|---|
| 1 | 用户点击了"返回"按钮 |
| 2 | 用户点击了"取消"按钮 |
| 5 | 成功获取点坐标 |
| 7 | 没有激活的部件 |
| 8 | 不允许的状态,无法显示对话框 |
3. uc1616实战应用示例
下面通过一个完整的示例展示uc1616的实际应用场景。
3.1 基础点选择功能实现
cpp复制#include <uf.h>
#include <uf_ui.h>
#include <stdio.h>
#define DllExport __declspec(dllexport)
extern "C" DllExport void ufusr(char *param, int *retcode, int param_len)
{
// 初始化NX Open环境
if(UF_initialize() != 0) {
uc1601("NX Open初始化失败!", 1);
return;
}
// 设置点选择参数
char cue[] = "请选择圆心位置";
int mode[2] = {8, 0}; // 8=圆心, 0=无偏移
int display_mode = 0; // 显示临时点
double point[3] = {0}; // 存储点坐标
// 调用uc1616函数
int response = uc1616(cue, mode, display_mode, point);
// 处理返回结果
switch(response) {
case 5: {
char msg[256];
sprintf_s(msg, "成功选择圆心:\nX=%.2f\nY=%.2f\nZ=%.2f",
point[0], point[1], point[2]);
uc1601(msg, 1);
break;
}
case 1:
uc1601("用户点击了返回", 1);
break;
case 2:
uc1601("用户取消了操作", 1);
break;
case 7:
uc1601("错误:没有激活的部件", 1);
break;
case 8:
uc1601("错误:不允许的状态", 1);
break;
default:
uc1601("未知的返回状态", 1);
}
// 终止NX Open环境
UF_terminate();
}
3.2 高级应用:带偏移的点选择
在实际工程中,我们经常需要在选定点的基础上添加偏移。下面的示例演示如何使用偏移功能:
cpp复制// 设置点选择参数 - 带偏移
char cue[] = "选择基点并设置偏移";
int mode[2] = {0, 1}; // 0=推断选择, 1=直角坐标绝对偏移
int display_mode = 1; // 不显示临时点
double base_point[3] = {0};
// 调用uc1616函数
int response = uc1616(cue, mode, display_mode, base_point);
if(response == 5) {
// 显示偏移对话框
double offset[3] = {10.0, 10.0, 0.0}; // 默认偏移值
if(UF_UI_ask_offset("输入偏移量", base_point, offset) == UF_UI_OK) {
// 计算最终点位置
double final_point[3] = {
base_point[0] + offset[0],
base_point[1] + offset[1],
base_point[2] + offset[2]
};
// 显示结果
char msg[256];
sprintf_s(msg, "基点: (%.2f,%.2f,%.2f)\n偏移: (%.2f,%.2f,%.2f)\n结果: (%.2f,%.2f,%.2f)",
base_point[0], base_point[1], base_point[2],
offset[0], offset[1], offset[2],
final_point[0], final_point[1], final_point[2]);
uc1601(msg, 1);
}
}
4. 常见问题与调试技巧
4.1 常见错误排查
-
DLL加载失败
- 检查是否使用了正确的NX版本(NX 10.0对应NX1000宏定义)
- 确认DLL是64位编译(NX 10.0只支持64位)
- 检查依赖的NX Open库是否正确链接
-
uc1616返回错误代码7
- 确保调用函数时有激活的工作部件
- 在调用前使用UF_PART_ask_display_part检查当前显示部件
-
点坐标不正确
- 确认工作坐标系是否正确
- 检查mode参数设置是否合理
- 验证point数组是否已正确初始化
4.2 调试技巧
-
日志输出
cpp复制FILE* log_file = fopen("debug_log.txt", "a"); fprintf(log_file, "uc1616 called with mode=%d,%d\n", mode[0], mode[1]); fclose(log_file); -
使用UF_UI函数显示调试信息
cpp复制char debug_msg[256]; sprintf_s(debug_msg, "Current mode: %d,%d", mode[0], mode[1]); UF_UI_set_status(debug_msg); -
断点调试
- 在VS2012中设置NX为启动程序
- 配置调试器附加到NX进程
- 设置断点后通过NX菜单调用DLL功能
4.3 性能优化建议
-
减少初始化开销
- 将UF_initialize/UF_terminate放在DLL入口/出口处
- 避免在循环中重复初始化
-
合理使用临时点显示
- 频繁操作时设置point_display_mode=1减少图形刷新
- 最终确认时再显示临时点
-
缓存常用数据
- 缓存当前工作部件句柄
- 重用mode数组减少内存分配
5. 扩展应用与进阶技巧
5.1 与其他NX Open函数结合使用
uc1616通常与其他NX Open函数配合使用,实现更复杂的功能:
cpp复制// 创建基于选择点的基准平面
tag_t plane_tag = NULL_TAG;
double plane_origin[3] = {0};
double plane_normal[3] = {0, 0, 1};
// 让用户选择点
int response = uc1616("选择基准平面原点", mode, 0, plane_origin);
if(response == 5) {
// 创建基准平面
UF_FEATURE_SIGN sign = UF_NULLSIGN;
char plane_name[30] = "基准平面";
double box_size[2] = {100.0, 100.0};
UF_MODL_create_fixed_dplane(
plane_origin,
plane_normal,
plane_name,
box_size,
&sign,
&plane_tag
);
if(plane_tag != NULL_TAG) {
uc1601("基准平面创建成功", 1);
}
}
5.2 自定义点选择界面
对于需要更复杂交互的场景,可以基于uc1616开发自定义点选择界面:
-
多重点选择
cpp复制double points[10][3]; // 存储多个点 int point_count = 0; while(point_count < 10) { char cue[40]; sprintf_s(cue, "选择第%d个点(ESC结束)", point_count+1); int response = uc1616(cue, mode, 0, points[point_count]); if(response == 5) { point_count++; } else if(response == 2) { break; // 用户取消 } } -
条件过滤
cpp复制// 只允许选择圆弧中心 int mode[2] = {8, 0}; // 8=圆弧中心 int response = uc1616("请选择圆弧中心", mode, 0, point); if(response == 5) { // 验证选择的对象确实是圆弧 tag_t object; UF_UI_ask_sel_object(&object); if(UF_MODL_ask_object_type(object) == UF_circle_type) { uc1601("有效的圆弧中心选择", 1); } else { uc1601("错误:选择的对象不是圆弧", 1); } }
5.3 实际工程应用案例
案例:孔阵列定位系统
cpp复制// 1. 选择基准点
double base_point[3];
int response = uc1616("选择阵列基准点", mode, 0, base_point);
if(response == 5) {
// 2. 设置阵列参数
int row_count = 3;
int col_count = 4;
double row_spacing = 20.0;
double col_spacing = 15.0;
// 3. 创建孔阵列
for(int i = 0; i < row_count; i++) {
for(int j = 0; j < col_count; j++) {
double hole_point[3] = {
base_point[0] + j * col_spacing,
base_point[1] + i * row_spacing,
base_point[2]
};
// 创建简单孔
UF_FEATURE_SIGN sign = UF_NULLSIGN;
tag_t hole_tag;
double diameter = 5.0;
double depth = 10.0;
double tip_angle = 118.0;
UF_MODL_create_simple_hole(
hole_point,
diameter,
depth,
tip_angle,
&sign,
&hole_tag
);
}
}
uc1601("孔阵列创建完成", 1);
}