|
|
发表于 2026-4-15 14:26:17
|
显示全部楼层
- // 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[6] = {0.0};
- int rc = UF_MODL_ask_bounding_box(obj, b);
- if (rc != 0)
- return false;
- for (int i = 0; i < 6; ++i)
- bbox[i] = b[i];
- return true;
- }
- static double BboxDiagonal(const std::array<double, 6> &bb)
- {
- const double dx = bb[3] - bb[0];
- const double dy = bb[4] - bb[1];
- const double dz = bb[5] - bb[2];
- 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[0] - r, bb[1] - r, bb[2] - r, bb[3] + r, bb[4] + r, bb[5] + r};
- }
- static bool BboxIntersects(const std::array<double, 6> &a, const std::array<double, 6> &b)
- {
- bool sep = a[3] < b[0] || a[0] > b[3] ||
- a[4] < b[1] || a[1] > b[4] ||
- a[5] < b[2] || a[2] > b[5];
- return !sep;
- }
- static bool AskMinDistance(tag_t obj1, tag_t obj2, double &dist)
- {
- double pt1[3] = {0.0}, pt2[3] = {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("[ERROR] 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("[ERROR] 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("[ERROR] 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("[ERROR] 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("[INFO] 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;
- }
复制代码 |
|