NXOpen如何实现自动范围选择
有个需求要求无UI根据一条曲线自动计算范围进行自动选择目前没有什么头绪// AutoSelectByCurveSkeleton.cpp
// NX Open C++ / UFUN skeleton: no UI, auto-select bodies by one curve range.
#include <uf.h>
#include <uf_obj.h>
#include <uf_modl.h>
#include <uf_part.h>
#include <uf_ui.h>
#include <uf_group.h>
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
namespace
{
struct Config
{
double k = 0.02;
double rMin = 2.0;
double tol = 0.01;
std::string groupName = "AUTO_SELECT_BY_CURVE";
};
static void Log(const std::string &msg)
{
UF_UI_open_listing_window();
UF_UI_write_listing_window(msg.c_str());
UF_UI_write_listing_window("\n");
}
static bool ParseTagFromEnv(const char *key, tag_t &tag)
{
const char *v = std::getenv(key);
if (!v || std::strlen(v) == 0)
return false;
char *end = nullptr;
unsigned long long raw = std::strtoull(v, &end, 10);
if (end == v)
return false;
tag = static_cast<tag_t>(raw);
return (tag != NULL_TAG);
}
static bool AskBoundingBox(tag_t obj, std::array<double, 6> &bbox)
{
double b = {0.0};
int rc = UF_MODL_ask_bounding_box(obj, b);
if (rc != 0)
return false;
for (int i = 0; i < 6; ++i)
bbox = b;
return true;
}
static double BboxDiagonal(const std::array<double, 6> &bb)
{
const double dx = bb - bb;
const double dy = bb - bb;
const double dz = bb - bb;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
static std::array<double, 6> ExpandBbox(const std::array<double, 6> &bb, double r)
{
return {bb - r, bb - r, bb - r, bb + r, bb + r, bb + r};
}
static bool BboxIntersects(const std::array<double, 6> &a, const std::array<double, 6> &b)
{
bool sep = a < b || a > b ||
a < b || a > b ||
a < b || a > b;
return !sep;
}
static bool AskMinDistance(tag_t obj1, tag_t obj2, double &dist)
{
double pt1 = {0.0}, pt2 = {0.0};
int rc = UF_MODL_ask_minimum_dist(obj1, obj2, 0, nullptr, 0, nullptr, &dist, pt1, pt2);
return rc == 0;
}
static std::vector<tag_t> CollectSolidBodiesInWorkPart()
{
std::vector<tag_t> bodies;
tag_t part = UF_PART_ask_display_part();
if (part == NULL_TAG)
return bodies;
tag_t obj = NULL_TAG;
while (UF_OBJ_cycle_objs_in_part(part, UF_solid_type, &obj) == 0 && obj != NULL_TAG)
{
int type = 0;
int subtype = 0;
UF_OBJ_ask_type_and_subtype(obj, &type, &subtype);
if (subtype == UF_solid_body_subtype)
bodies.push_back(obj);
}
return bodies;
}
static tag_t FindCurveFromEnvOrFail()
{
tag_t curve = NULL_TAG;
if (!ParseTagFromEnv("NX_CURVE_TAG", curve))
{
Log(" Missing env NX_CURVE_TAG. Example: set NX_CURVE_TAG=123456");
return NULL_TAG;
}
int type = 0, subtype = 0;
if (UF_OBJ_ask_type_and_subtype(curve, &type, &subtype) != 0)
{
Log(" Invalid curve tag.");
return NULL_TAG;
}
if (type != UF_line_type && type != UF_circle_type && type != UF_conic_type && type != UF_spline_type && type != UF_curve_type)
{
Log(" Tag is not a supported curve object.");
return NULL_TAG;
}
return curve;
}
static tag_t CreateGroupWithMembers(const std::string &name, const std::vector<tag_t> &members)
{
if (members.empty())
return NULL_TAG;
tag_t groupTag = NULL_TAG;
int rc = UF_GROUP_create(name.c_str(), static_cast<int>(members.size()), const_cast<tag_t *>(members.data()), &groupTag);
if (rc != 0)
return NULL_TAG;
return groupTag;
}
static int Run(const Config &cfg)
{
tag_t curve = FindCurveFromEnvOrFail();
if (curve == NULL_TAG)
return 1;
std::array<double, 6> curveBb{};
if (!AskBoundingBox(curve, curveBb))
{
Log(" Failed to query curve bounding box.");
return 2;
}
const double curveScale = BboxDiagonal(curveBb);
const double R = std::max(curveScale * cfg.k, cfg.rMin);
const auto expanded = ExpandBbox(curveBb, R);
auto allBodies = CollectSolidBodiesInWorkPart();
std::vector<tag_t> coarse;
coarse.reserve(allBodies.size());
for (tag_t b : allBodies)
{
std::array<double, 6> bb{};
if (!AskBoundingBox(b, bb))
continue;
if (BboxIntersects(expanded, bb))
coarse.push_back(b);
}
std::vector<tag_t> selected;
selected.reserve(coarse.size());
for (tag_t b : coarse)
{
double d = std::numeric_limits<double>::max();
if (!AskMinDistance(curve, b, d))
continue;
if (d <= R + cfg.tol)
selected.push_back(b);
}
tag_t group = CreateGroupWithMembers(cfg.groupName, selected);
Log(" Auto select by curve done.");
Log("curve tag: " + std::to_string(static_cast<unsigned long long>(curve)));
Log("curve scale (bbox diagonal): " + std::to_string(curveScale));
Log("radius R: " + std::to_string(R));
Log("total bodies: " + std::to_string(allBodies.size()));
Log("coarse candidates: " + std::to_string(coarse.size()));
Log("selected: " + std::to_string(selected.size()));
Log("group tag: " + std::to_string(static_cast<unsigned long long>(group)));
return 0;
}
}
extern "C" DllExport void ufusr(char *param, int *returnCode, int rlen)
{
UF_initialize();
Config cfg;
int rc = Run(cfg);
if (returnCode)
*returnCode = rc;
UF_terminate();
}
extern "C" DllExport int ufusr_ask_unload(void)
{
return UF_UNLOAD_IMMEDIATELY;
}
jesson3264 发表于 2026-4-15 14:26
虽然看不懂 但666
页:
[1]