-
你先取某个平面,沿法向创建临时坐标系。
-
计算 体在这个坐标系下的包络盒尺寸:体在 X、Y、Z 方向的长度。
-
计算 面在同坐标系下的尺寸:面在 X、Y 方向的边界长度。
-
判断面是否是底面:
-
如果面 X = 体 X,面 Y = 体 Y → 认为是底面。
-
/*****************************************************************************
** NX1899 / VS2017 (v141)
** 功能:遍历实体所有平面,按算法判定“电极底面”并标红
** 说明:保留原有两点(不改):
** 1) 使用 UF_OBJ_cycle_all(DisplayTag_body, object) 遍历对象
** 2) 不改为 UF_MODL_ask_bodies() 取体,而是沿用上面的遍历方式找第一个实体
*****************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include <float.h>
#include <math.h>
#include <uf.h>
#include <uf_ui_types.h>
#include <uf_ui.h>
#include <uf_obj.h>
#include <uf_modl.h>
#include <uf_part.h>
#include <uf_csys.h>
#include <uf_mtx.h>
#include <uf_disp.h>
#ifndef DllExport
#define DllExport __declspec(dllexport)
#endif
/*-------------------- 小工具 & 宏 --------------------*/
static void ECHO(const char *format, ...)
{
char msg[UF_UI_MAX_STRING_BUFSIZE];
va_list args;
va_start(args, format);
vsprintf_s(msg, sizeof(msg), format, args);
va_end(args);
UF_UI_open_listing_window();
UF_UI_write_listing_window(msg);
UF_UI_write_listing_window("\n");
UF_print_syslog(msg, FALSE);
}
#define UF_CALL(X) (report_error(__FILE__, __LINE__, #X, (X)))
static int report_error(const char *file, int line, const char *call, int irc)
{
if (irc)
{
char err[133];
UF_get_fail_message(irc, err);
ECHO("*** ERROR %d at %s:%d\n%s\n%s", irc, file, line, err, call);
}
return irc;
}
/* 将毫米值转换为当前部件单位的值:公制(mm)→原样;英制(inch)→除以25.4 */
static double mm_to_part_units(double v_mm, tag_t part)
{
int units = 0; /* 1=英制, 2=公制(在UF中常量名可能是UF_PART_ENGLISH/UF_PART_METRIC) */
UF_PART_ask_units(part, &units);
if (units == 2 /* metric */) return v_mm;
return v_mm / 25.4; /* english(inch) */
}
/* 生成以 z_axis 为Z的正交基;避免与参考向量共线 */
static void build_ortho_from_z(const double z_axis_in[3], double x_axis[3], double y_axis[3], double z_axis[3])
{
/* 单位化 Z */
double lenz = sqrt(z_axis_in[0] * z_axis_in[0] + z_axis_in[1] * z_axis_in[1] + z_axis_in[2] * z_axis_in[2]);
if (lenz < 1e-12) { z_axis[0] = 0; z_axis[1] = 0; z_axis[2] = 1; }
else { z_axis[0] = z_axis_in[0] / lenz; z_axis[1] = z_axis_in[1] / lenz; z_axis[2] = z_axis_in[2] / lenz; }
/* 选参考向量:尽量远离Z以避免共线 */
double ref[3] = { 1.0, 0.0, 0.0 };
if (fabs(z_axis[0]) > 0.9) { ref[0] = 0.0; ref[1] = 1.0; ref[2] = 0.0; }
/* y = z × ref;若太小换一个ref */
y_axis[0] = z_axis[1] * ref[2] - z_axis[2] * ref[1];
y_axis[1] = z_axis[2] * ref[0] - z_axis[0] * ref[2];
y_axis[2] = z_axis[0] * ref[1] - z_axis[1] * ref[0];
double leny = sqrt(y_axis[0] * y_axis[0] + y_axis[1] * y_axis[1] + y_axis[2] * y_axis[2]);
if (leny < 1e-12)
{
ref[0] = 0.0; ref[1] = 1.0; ref[2] = 0.0;
y_axis[0] = z_axis[1] * ref[2] - z_axis[2] * ref[1];
y_axis[1] = z_axis[2] * ref[0] - z_axis[0] * ref[2];
y_axis[2] = z_axis[0] * ref[1] - z_axis[1] * ref[0];
leny = sqrt(y_axis[0] * y_axis[0] + y_axis[1] * y_axis[1] + y_axis[2] * y_axis[2]);
if (leny < 1e-12) { /* 实在不行给个默认 */
y_axis[0] = 0; y_axis[1] = 1; y_axis[2] = 0;
leny = 1.0;
}
}
y_axis[0] /= leny; y_axis[1] /= leny; y_axis[2] /= leny;
/* x = y × z */
x_axis[0] = y_axis[1] * z_axis[2] - y_axis[2] * z_axis[1];
x_axis[1] = y_axis[2] * z_axis[0] - y_axis[0] * z_axis[2];
x_axis[2] = y_axis[0] * z_axis[1] - y_axis[1] * z_axis[0];
}
/*-------------------- 主逻辑 --------------------*/
extern "C" DllExport void ufusr(char *parm, int *returnCode, int rlen)
{
if (UF_CALL(UF_initialize())) return;
tag_t part = UF_PART_ask_display_part();
if (part == NULL_TAG)
{
ECHO("没有显示部件,退出。");
UF_terminate();
return;
}
/* 1)(按你的要求不改)用 UF_OBJ_cycle_all 找第一个实体体 */
tag_t bodyofwork_tag = NULL_TAG;
tag_t object = NULL_TAG;
tag_t DisplayTag_body = UF_PART_ask_display_part();
object = UF_OBJ_cycle_all(DisplayTag_body, object); /* 注意:你坚持保留这用法 */
while (object != NULL_TAG)
{
int type = 0, subtype = 0;
UF_OBJ_ask_type_and_subtype(object, &type, &subtype);
if (type == UF_solid_type && subtype == 0)
{
UF_OBJ_set_color(object, 1); // 设置颜色
bodyofwork_tag = object;
}
object = UF_OBJ_cycle_all(DisplayTag_body, object);
}
if (bodyofwork_tag == NULL_TAG)
{
ECHO("未找到实体体(按原逻辑遍历),退出。");
UF_terminate();
return;
}
/* 2) 面列表 */
uf_list_p_t face_list = NULL;
UF_CALL(UF_MODL_create_list(&face_list));
UF_CALL(UF_MODL_ask_body_faces(bodyofwork_tag, &face_list));
int face_count = 0;
UF_CALL(UF_MODL_ask_list_count(face_list, &face_count));
ECHO("实体面数:%d", face_count);
/* 公差与偏移,按部件单位换算(你算法写的是 mm) */
const double off_01mm = mm_to_part_units(0.01, part);
const double tol_001mm = mm_to_part_units(0.001, part);
tag_t bottom_face_tag = NULL_TAG;
for (int j = 0; j < face_count; ++j)
{
tag_t face_tag = NULL_TAG;
UF_CALL(UF_MODL_ask_list_item(face_list, j, &face_tag));
int ftype; double P[3], N[3], Box[6], R[3], RadData[3]; int NormDir = 0;
UF_CALL(UF_MODL_ask_face_data(face_tag, &ftype, P, N, Box, R, RadData, &NormDir));
if (ftype != UF_MODL_PLANAR_FACE) continue; /* 只看平面 */
// 2.1 在中心点沿法向偏移 0.01mm 创建基准平面
double P_off[3] = { P[0] + off_01mm * N[0],
P[1] + off_01mm * N[1],
P[2] + off_01mm * N[2] };
tag_t plane_tag = NULL_TAG;
int rc_plane = UF_MODL_create_plane(P_off, N, &plane_tag);
if (rc_plane) { ECHO("create_plane 失败,面 #%d 跳过(rc=%d)", j, rc_plane); continue; }
// 2.2 测量实体到该平面的最小距离
double dist = 0.0, guess1[3] = { P[0], P[1], P[2] }, guess2[3] = { P_off[0], P_off[1], P_off[2] };
double p1[3] = { 0 }, p2[3] = { 0 };
int rc_dist = UF_MODL_ask_minimum_dist(bodyofwork_tag, plane_tag, 0, guess1, 0, guess2, &dist, p1, p2);
if (rc_dist)
{
ECHO("ask_minimum_dist 失败(rc=%d),删除平面后继续。", rc_dist);
UF_OBJ_delete_object(plane_tag);
continue;
}
ECHO("面[%d] 与偏移平面距离 = %.6f (部件单位)", j, dist);
if (dist < tol_001mm)
{
UF_OBJ_delete_object(plane_tag);
continue;
}
// 2.3 以该面法向构造临时坐标系(Z=N),取体包络盒长度
double X[3], Y[3], Z[3];
build_ortho_from_z(N, X, Y, Z);
double mtx[9] = {
X[0], X[1], X[2],
Y[0], Y[1], Y[2],
Z[0], Z[1], Z[2]
};
tag_t mtx_tag = NULL_TAG, tcsys = NULL_TAG;
UF_CALL(UF_CSYS_create_matrix(mtx, &mtx_tag));
UF_CALL(UF_CSYS_create_temp_csys(P, mtx_tag, &tcsys));
// 获取体在临时坐标系下包络盒长度
double min_corner[3], dirs[3][3], lens[3] = { 0 };
UF_CALL(UF_MODL_ask_bounding_box_exact(bodyofwork_tag, tcsys, min_corner, dirs, lens));
// 获取面在同临时坐标系下包络盒长度
double face_min[3], face_dirs[3][3], face_lens[3] = { 0 };
UF_CALL(UF_MODL_ask_bounding_box_exact(face_tag, tcsys, face_min, face_dirs, face_lens));
// 清理临时对象
UF_OBJ_delete_object(tcsys);
UF_OBJ_delete_object(mtx_tag);
UF_OBJ_delete_object(plane_tag);
ECHO("面[%d] 包络盒长度:X=%.6f, Y=%.6f; 体包络长度:X=%.6f, Y=%.6f",
j, face_lens[0], face_lens[1], lens[0], lens[1]);
// 2.4 判断面 X/Y 是否接近体 X/Y
if (fabs(face_lens[0] - lens[0]) < tol_001mm && fabs(face_lens[1] - lens[1]) < tol_001mm)
{
bottom_face_tag = face_tag;
ECHO("面[%d] 判定为底面", j);
break;
}
}
if (bottom_face_tag != NULL_TAG)
{
UF_OBJ_set_color(bottom_face_tag, 186); /* 红色 */
UF_DISP_refresh(); /* 强制刷新显示 */
ECHO("底面已标红。");
}
else
{
ECHO("未找到符合条件的底面。");
}
if (face_list) UF_MODL_delete_list(&face_list);
UF_CALL(UF_terminate());
}
/* 卸载策略 */
extern "C" int ufusr_ask_unload(void)
{
return UF_UNLOAD_IMMEDIATELY;
}
4959

被折叠的 条评论
为什么被折叠?



