NOTE/对象遍历

本文深入探讨了JavaScript中对象的概念及其与关联数组或Map的差异,解释了下标操作符、点操作符如何访问对象属性,以及如何通过forin循环、hasOwnProperty()和Object.keys()、Object.getOwnPropertyNames()进行属性枚举。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript中的对象概念非常不同,要把它当作其它语言的关联数组(如PHP)或者Map(如Java)来理解的话,还是有很大的不一样——由于原型链属性描述符(主要是[[Enumerable]])的存在。

一个对象字面量{}Object作为原型,它有继承自原型链的不可枚举的toString方法。下面将以对象字面量为例。

  • 下标操作符、点操作符可以访问到自身属性或继承自原型链的任何属性,除非出现了属性覆盖
    var a ={}; a.toString返回toString方法
    var a ={toString:"a"}; a.toString返回字符串"a"

  • for in循环将枚举的自身属性和继承自原型链的所有[[Enumerable]]的属性

  • "key" in obj的判断中,判断自身属性或继承自原型链的属性的存在性
    "toString" in {}返回true

  • obj.hasOwnProperty()的判断中,只判断自身属性的存在性
    ({}).hasOwnProperty("toString")返回false
    ({toString:"a"}).hasOwnProperty("toString")返回true

  • Object.keys()可返回自身[[Enumerable]]的属性组成的数组,不包括原型链上继承的属性
    Object.keys({a:1})返回["a"],不包含原型链上的toString等内容

  • Object.getOwnPropertyNames()可以返回自身任何属性组成的数组,不包括原型链上继承的属性

类目语句自身属性原型链上继承的属性
可枚举属性不可枚举属性可枚举属性不可枚举属性
访问obj.prop
obj["prop"]
循环for key in obj
判断key in objTRUETRUETRUETRUE
obj.hasOwnProperty(key)TRUETRUEFALSEFALSE
列举Object.keys(obj)
Object.getOwnPropertyNames(obj)

可以通过以下方式避免遍历过程中的原型链干扰:

  • 在get/set方法中为每一个键加上前缀
  • Object.create(null)来创建一个没有原型的对象

这些都可以在StringMap的解决方案里找到。

//============================================================================== // WARNING!! This file is overwritten by the Block UI Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\NXopen\BaiduSyncdisk\Application\gaiyansetool.cpp // // This file was generated by the NX Block UI Styler // Created by: MICH-ROG // Version: NX 12 // Date: 07-31-2025 (Format: mm-dd-yyyy) // Time: 16:55 (Format: hh-mm) // //============================================================================== //============================================================================== // Purpose: This TEMPLATE file contains C++ source to guide you in the // construction of your Block application dialog. The generation of your // dialog file (.dlx extension) is the first step towards dialog construction // within NX. You must now create a NX Open application that // utilizes this file (.dlx). // // The information in this file provides you with the following: // // 1. Help on how to load and display your Block UI Styler dialog in NX // using APIs provided in NXOpen.BlockStyler namespace // 2. The empty callback methods (stubs) associated with your dialog items // have also been placed in this file. These empty methods have been // created simply to start you along with your coding requirements. // The method name, argument list and possible return values have already // been provided for you. //============================================================================== //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include "gaiyansetool.hpp" using namespace NXOpen; using namespace NXOpen::BlockStyler; // 辅助结构体存储面信息 struct FaceInfo { TaggedObject* faceObj; double centerZ; int faceType; double radius; }; //------------------------------------------------------------------------------ // Initialize static variables //------------------------------------------------------------------------------ Session *(gaiyansetool::theSession) = NULL; UI *(gaiyansetool::theUI) = NULL; //------------------------------------------------------------------------------ // Constructor for NX Styler class //------------------------------------------------------------------------------ gaiyansetool::gaiyansetool() { try { // Initialize the NX Open C++ API environment gaiyansetool::theSession = NXOpen::Session::GetSession(); gaiyansetool::theUI = UI::GetUI(); theDlxFileName = "gaiyansetool.dlx"; theDialog = gaiyansetool::theUI->CreateDialog(theDlxFileName); // Registration of callback functions theDialog->AddApplyHandler(make_callback(this, &gaiyansetool::apply_cb)); theDialog->AddOkHandler(make_callback(this, &gaiyansetool::ok_cb)); theDialog->AddUpdateHandler(make_callback(this, &gaiyansetool::update_cb)); theDialog->AddInitializeHandler(make_callback(this, &gaiyansetool::initialize_cb)); theDialog->AddDialogShownHandler(make_callback(this, &gaiyansetool::dialogShown_cb)); } catch(exception& ex) { //---- Enter your exception handling code here ----- throw; } } //------------------------------------------------------------------------------ // Destructor for NX Styler class //------------------------------------------------------------------------------ gaiyansetool::~gaiyansetool() { if (theDialog != NULL) { delete theDialog; theDialog = NULL; } } //------------------------------- DIALOG LAUNCHING --------------------------------- // // Before invoking this application one needs to open any part/empty part in NX // because of the behavior of the blocks. // // Make sure the dlx file is in one of the following locations: // 1.) From where NX session is launched // 2.) $UGII_USER_DIR/application // 3.) For released applications, using UGII_CUSTOM_DIRECTORY_FILE is highly // recommended. This variable is set to a full directory path to a file // containing a list of root directories for all custom applications. // e.g., UGII_CUSTOM_DIRECTORY_FILE=$UGII_BASE_DIR\ugii\menus\custom_dirs.dat // // You can create the dialog using one of the following way: // // 1. USER EXIT // // 1) Create the Shared Library -- Refer "Block UI Styler programmer's guide" // 2) Invoke the Shared Library through File->Execute->NX Open menu. // //------------------------------------------------------------------------------ extern "C" DllExport void ufusr(char *param, int *retcod, int param_len) { gaiyansetool *thegaiyansetool = NULL; try { UF_initialize(); //开发的许可函数,初始化 thegaiyansetool = new gaiyansetool(); // The following method shows the dialog immediately thegaiyansetool->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } if(thegaiyansetool != NULL) { delete thegaiyansetool; thegaiyansetool = NULL; }UF_terminate(); //释放许可函数,结束化 } //------------------------------------------------------------------------------ // This method specifies how a shared image is unloaded from memory // within NX. This method gives you the capability to unload an // internal NX Open application or user exit from NX. Specify any // one of the three constants as a return value to determine the type // of unload to perform: // // // Immediately : unload the library as soon as the automation program has completed // Explicitly : unload the library from the "Unload Shared Image" dialog // AtTermination : unload the library when the NX session terminates // // // NOTE: A program which associates NX Open applications with the menubar // MUST NOT use this option since it will UNLOAD your NX Open application image // from the menubar. //------------------------------------------------------------------------------ extern "C" DllExport int ufusr_ask_unload() { //return (int)Session::LibraryUnloadOptionExplicitly; return (int)Session::LibraryUnloadOptionImmediately; //return (int)Session::LibraryUnloadOptionAtTermination; } //------------------------------------------------------------------------------ // Following method cleanup any housekeeping chores that may be needed. // This method is automatically called by NX. //------------------------------------------------------------------------------ extern "C" DllExport void ufusr_cleanup(void) { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } int gaiyansetool::Show() { try { theDialog->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //---------------------Block UI Styler Callback Functions-------------------------- //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //Callback Name: initialize_cb //------------------------------------------------------------------------------ void gaiyansetool::initialize_cb() { try { group1 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group1")); enum0 = dynamic_cast<NXOpen::BlockStyler::Enumeration*>(theDialog->TopBlock()->FindBlock("enum0")); group0 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group0")); face1 = dynamic_cast<NXOpen::BlockStyler::FaceCollector*>(theDialog->TopBlock()->FindBlock("face1")); group = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group")); color1 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color1")); color2 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color2")); color3 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color3")); color4 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color4")); bu1 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu1")); bu2 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu2")); bu3 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu3")); bu4 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu4")); color5 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color5")); color6 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color6")); color7 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color7")); color8 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color8")); bu5 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu5")); bu6 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu6")); bu7 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu7")); bu8 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu8")); color9 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color9")); color10 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color10")); color11 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color11")); color12 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color12")); bu9 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu9")); bu10 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu10")); bu11 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu11")); bu12 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu12")); group2 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group2")); dbpface = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("dbpface")); gtbody = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("gtbody")); arcface = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("arcface")); gaodipoints = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("gaodipoints")); Keyway1 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("Keyway1")); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: dialogShown_cb //This callback is executed just before the dialog launch. Thus any value set //here will take precedence and dialog will be launched showing that value. //------------------------------------------------------------------------------ void gaiyansetool::dialogShown_cb() { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: apply_cb //------------------------------------------------------------------------------ int gaiyansetool::apply_cb() { int errorCode = 0; try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Callback Name: update_cb //------------------------------------------------------------------------------ int gaiyansetool::update_cb(NXOpen::BlockStyler::UIBlock* block) { try { if (block == enum0) { //---------Enter your code here----------- } else if (block == face1) { //---------Enter your code here----------- } else if (block == color1) { //---------Enter your code here----------- } else if (block == color2) { //---------Enter your code here----------- } else if (block == color3) { //---------Enter your code here----------- } else if (block == color4) { //---------Enter your code here----------- } else if (block == bu1) { try { if (color1 != nullptr) { //获取ui枚举索引值 int iType = 0; iType = this->enum0->GetProperties()->GetEnum("Value"); // ⚙️ 1. 获取属性列表 PropertyList* colorProps = color1->GetProperties(); // 🎨 2. 获取颜色值:关键属性名为 "Value",返回整数向量 std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; // 取第一个值为颜色索引 delete colorProps;// 🧹 3. 释放属性列表内存(必须!) //char msg[256];//调试// //sprintf(msg, "%d", iType); //uc1601(msg, 1);// // ====== 以下是应用颜色到面的逻辑 ====== if (face1 != nullptr) { // 获取选中的面 std::vector<NXOpen::TaggedObject*> vFaces = face1->GetSelectedObjects(); if (vFaces.empty()) { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeError, "未选择面!"); return 0; } if (iType == 0) { // 🖌️ 遍历所有面并设置颜色 for (auto face : vFaces) { tag_t faceTag = face->Tag(); UF_OBJ_set_color(faceTag, colorID); // 应用颜色 UF_DISP_set_highlight(faceTag, 0); //高亮,0=不高亮,1=高亮 } } else { // 模式1:给选中面所在的实体设置颜色 std::set<tag_t> processedBodies;// 用于记录已处理的实体 for (auto face : vFaces) { tag_t faceTag = face->Tag(); tag_t bodyTag = NULL_TAG; // 获取面所属的实体 UF_MODL_ask_face_body(faceTag, &bodyTag); if (bodyTag != NULL_TAG && processedBodies.find(bodyTag) == processedBodies.end()) { // 清除实体上所有面的单独颜色设置(关键修复) uf_list_p_t faceList = NULL; UF_MODL_ask_body_faces(bodyTag, &faceList); int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t bodyFaceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &bodyFaceTag); // 重置面颜色继承 UF_OBJ_set_color(bodyFaceTag, colorID); } UF_MODL_delete_list(&faceList); // 设置实体颜色 UF_OBJ_set_color(bodyTag, colorID); UF_DISP_set_highlight(bodyTag, 0); processedBodies.insert(bodyTag); // 添加到已处理集合 } } } // 清空选择并刷新显示 vFaces.clear(); face1->SetSelectedObjects(vFaces); UF_DISP_refresh(); } } else { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "color1未初始化!"); } } catch (exception& ex) { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, ex.what()); } } // 这行结束 else if (block == bu2) { //---------Enter your code here----------- } else if (block == bu3) { //---------Enter your code here----------- } else if (block == bu4) { //---------Enter your code here----------- } else if (block == color5) { //---------Enter your code here----------- } else if (block == color6) { //---------Enter your code here----------- } else if (block == color7) { //---------Enter your code here----------- } else if (block == color8) { //---------Enter your code here----------- } else if (block == bu5) { //---------Enter your code here----------- } else if (block == bu6) { //---------Enter your code here----------- } else if (block == bu7) { //---------Enter your code here----------- } else if (block == bu8) { //---------Enter your code here----------- } else if (block == color9) { //---------Enter your code here----------- } else if (block == color10) { //---------Enter your code here----------- } else if (block == color11) { //---------Enter your code here----------- } else if (block == color12) { //---------Enter your code here----------- } else if (block == bu9) { //---------Enter your code here----------- } else if (block == bu10) { //---------Enter your code here----------- } else if (block == bu11) { //---------Enter your code here----------- } else if (block == bu12) { //---------Enter your code here----------- } else if (block == dbpface) { try { // 确保face1控件已初始化 if (face1 != nullptr) { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前显示部件的标签 if (displayPart == NULL_TAG) // 检查是否成功获取显示部件 { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); // 显示错误消息 return 0; // 退出函数 } // 2. 收集所有可见实体 std::vector<tag_t> allObjects; // 存储可见实体的容器 tag_t currentObject = NULL_TAG; // 当前处理的对象标签 // 遍历部件中的所有实体对象 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 获取第一个实体对象 while (currentObject != NULL_TAG) // 循环直到没有更多实体 { // 获取对象的显示属性 UF_OBJ_disp_props_t disp_props; // 声明显示属性结构体 if (UF_OBJ_ask_display_properties(currentObject, &disp_props) == 0) // 获取对象的显示属性 { // 检查对象是否显示(未隐藏) if (UF_OBJ_NOT_BLANKED == disp_props.blank_status) // 检查对象是否显示 { // 检查对象所在图层状态 int layer_status = 0; // 存储图层状态 if (UF_LAYER_ask_status(disp_props.layer, &layer_status) == 0) // 获取图层状态 { // 检查图层是否可见(活动图层或参考图层) if ( layer_status == UF_LAYER_WORK_LAYER || // 工作图层(可见可编辑) layer_status == UF_LAYER_ACTIVE_LAYER || // 活动图层(可见可选) layer_status == UF_LAYER_REFERENCE_LAYER) // 参考图层(仅可见) { allObjects.push_back(currentObject); // 将可见实体添加到容器 } } } } // 获取下一个对象 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 继续遍历下一个实体 } if (allObjects.empty()) // 检查是否有可见实体 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); // 显示提示消息 return 0; // 退出函数 } // 3. 收集所有面 std::vector<TaggedObject*> allFaces; for (tag_t objectTag : allObjects) { // 获取对象上的所有面 uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(objectTag, &faceList) != 0) continue; int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 创建NXOpen::Face对象并添加到列表 NXOpen::Face* face = dynamic_cast<NXOpen::Face*>(NXOpen::NXObjectManager::Get(faceTag)); if (face) allFaces.push_back(face); } // 释放面列表内存 if (faceList) UF_MODL_delete_list(&faceList); } // ================ 使用UF函数过滤水平面 ================ std::vector<TaggedObject*> horizontalFaces; const double tolerance = 0.0175; // 约1度(弧度) const double z_axis[3] = { 0.0, 0.0, 1.0 }; // 绝对Z轴方向 for (auto faceObj : allFaces) { tag_t faceTag = faceObj->Tag(); int faceType = 0; // 获取面类型 if (UF_MODL_ask_face_type(faceTag, &faceType) == 0 && faceType == UF_MODL_PLANAR_FACE) { double direction[3] = { 0.0, 0.0, 0.0 }; double point[3] = { 0.0, 0.0, 0.0 }; double box[6] = { 0.0 }; double rad = 0.0; double rad_data[2] = { 0.0 }; int status = 0; // 获取面数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) { // 计算法向与Z轴的点积 double dot = z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]; // 法向平行于Z轴(点积接近1或-1) if (fabs(fabs(dot) - 1.0) < tolerance) { horizontalFaces.push_back(faceObj); } } } } // ================ 结束过滤代码 ================ // ================ 找出Z方向最高的水平面 ================ std::vector<TaggedObject*> highestFaces; double maxZ = -DBL_MAX; // 初始化为最小可能值 // 1. 找出最高Z值 for (auto faceObj : horizontalFaces) { tag_t faceTag = faceObj->Tag(); double box[6]; // [xmin, ymin, zmin, xmax, ymax, zmax] // 获取面的包围盒 if (UF_MODL_ask_bounding_box(faceTag, box) == 0) { // 使用包围盒的zmax作为面的高度 double zMax = box[5]; // 更新最大Z值 if (zMax > maxZ) { maxZ = zMax; } } } // 2. 收集所有位于最高Z值位置的面 const double zTolerance = 0.001; // Z值容差(1毫米) for (auto faceObj : horizontalFaces) { tag_t faceTag = faceObj->Tag(); double box[6]; if (UF_MODL_ask_bounding_box(faceTag, box) == 0) { double zMax = box[5]; // 检查是否在最高Z值位置(考虑容差) if (fabs(zMax - maxZ) < zTolerance) { highestFaces.push_back(faceObj); } } } // ================ 结束最高面选择 ================ // 4. 设置到FaceCollector控件 - 使用最高水平面 face1->SetSelectedObjects(highestFaces); // 5. 刷新界面 UF_DISP_refresh(); //// 显示成功消息 //char msg[256]; //sprintf(msg, "已选择 %d 个最高水平面 (Z = %.2f)", (int)highestFaces.size(), maxZ); //theUI->NXMessageBox()->Show("操作成功", NXMessageBox::DialogTypeInformation, msg); } else { theUI->NXMessageBox()->Show("MICH-明:提示错误", NXMessageBox::DialogTypeError, "面选择控件未初始化!"); } } catch (exception& ex) { theUI->NXMessageBox()->Show("MICH-明:提示异常错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } else if (block == gtbody) { try { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前工作部件 if (displayPart == NULL_TAG) // 检查部件是否有效 { theUI->NXMessageBox()->Show("MICH-明错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); return 0; } // 2. 收集所有可见实体 std::vector<tag_t> allBodies; // 存储所有可见实体 tag_t currentBody = NULL_TAG; UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); // 开始遍历实体 while (currentBody != NULL_TAG) // 遍历所有实体 { UF_OBJ_disp_props_t disp_props; if (UF_OBJ_ask_display_properties(currentBody, &disp_props) == 0) // 获取显示属性 { // 仅处理未隐藏实体 if (disp_props.blank_status == UF_OBJ_NOT_BLANKED) // 检查可见性 { int layer_status = 0; UF_LAYER_ask_status(disp_props.layer, &layer_status); // 获取图层状态 // 检查可见图层 if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) { allBodies.push_back(currentBody); // 添加到可见实体列表 } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); // 获取下一个实体 } if (allBodies.empty()) // 检查是否有可见实体 { theUI->NXMessageBox()->Show("MICH-明提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); return 0; } // 3. 收集需要着色的实体 std::set<tag_t> targetBodies; // 使用set避免重复 const double tolerance = 0.0175; // 约1度(弧度)的法向容差 const double z_axis[3] = { 0.0, 0.0, 1.0 }; // Z轴方向向量 const double z_tolerance = 0.001; // Z坐标容差(1毫米) // 遍历所有实体 for (tag_t bodyTag : allBodies) { uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(bodyTag, &faceList) != 0) continue; // 获取实体所有面 int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); // 获取面数量 double minZ = DBL_MAX; // 初始化最小Z值为最大值 tag_t lowestFace = NULL_TAG; // 存储最低水平面 // 遍历实体的每个面 for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面标签 int faceType = 0; if (UF_MODL_ask_face_type(faceTag, &faceType) != 0) continue; // 获取面类型 // 只处理平面 if (faceType == UF_MODL_PLANAR_FACE) { double direction[3] = { 0 }; // 面法向 double point[3] = { 0 }; // 面上一点 double box[6] = { 0 }; // 面边界框 double rad = 0, rad_data[2] = { 0 }; int status = 0; // 获取面几何数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) { // 计算法向与Z轴的点积 double dot = z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]; // 检查是否为水平面(法向平行Z轴) if (fabs(fabs(dot) - 1.0) < tolerance) { // 获取面的最低点Z坐标(边界框Zmin) double faceMinZ = box[2]; // 更新最低水平面 if (faceMinZ < minZ) { minZ = faceMinZ; lowestFace = faceTag; } } } } } // 检查是否找到最低水平面且高于XY平面 if (lowestFace != NULL_TAG && minZ > z_tolerance) { targetBodies.insert(bodyTag); // 添加到目标实体集合 } UF_MODL_delete_list(&faceList); // 释放面列表内存 } // 4. 检查是否有符合条件的实体 if (targetBodies.empty()) { theUI->NXMessageBox()->Show("MICH-明提示", NXMessageBox::DialogTypeInformation, "未找到符合要求实体!"); return 0; } // 5. 着色处理 if (color5 != nullptr) // 确保颜色控件有效 { try { // 获取选择的颜色 PropertyList* colorProps = color5->GetProperties(); std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; // 提取颜色ID delete colorProps; // 释放属性对象 // 6. 为实体着色(保留面颜色重置) for (tag_t bodyTag : targetBodies) // 遍历目标实体 { // 重置实体所有面的颜色为继承 uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(bodyTag, &faceList) == 0) { int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); UF_OBJ_set_color(faceTag, colorID); // 0=继承实体颜色 } UF_MODL_delete_list(&faceList); // 释放面列表 } // 设置实体颜色 UF_OBJ_set_color(bodyTag, colorID); UF_DISP_set_highlight(bodyTag, 0); // 取消高亮 } UF_DISP_refresh(); // 刷新显示 //// 显示结果信息 //char msg[256]; //snprintf(msg, sizeof(msg), "已为 %zu 个实体设置颜色", targetBodies.size()); //theUI->NXMessageBox()->Show("着色完成", NXMessageBox::DialogTypeInformation, msg); } catch (std::exception& ex) { theUI->NXMessageBox()->Show("MICH-明提示:着色错误", NXMessageBox::DialogTypeError, ex.what()); } } else { theUI->NXMessageBox()->Show("MICH-明错误提示", NXMessageBox::DialogTypeError, "颜色选择控件未初始化!"); } } catch (std::exception& ex) { theUI->NXMessageBox()->Show("MICH-明:系统错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } else if(block == arcface) { try { if (face1 != nullptr) // 确保面选择控件有效 { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前显示的部件标签 if (displayPart == NULL_TAG) // 检查是否获取成功 { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); // 显示错误信息 return 0; // 提前返回 } // 2. 收集可见实体并筛选最低点高于Z0的实体 std::vector<tag_t> filteredObjects; // 存储符合条件的实体标签 tag_t currentObject = NULL_TAG; // 当前遍历的实体 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 开始遍历部件中的实体 while (currentObject != NULL_TAG) // 遍历所有实体 { // 检查实体的显示属性 UF_OBJ_disp_props_t disp_props; // 存储显示属性 if (UF_OBJ_ask_display_properties(currentObject, &disp_props) == 0) // 获取显示属性 { // 检查实体是否未被隐藏 if (UF_OBJ_NOT_BLANKED == disp_props.blank_status) // 实体可见 { int layer_status = 0; // 图层状态 if (UF_LAYER_ask_status(disp_props.layer, &layer_status) == 0) // 获取图层状态 { // 检查是否在可见图层上 if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) { // 计算实体的边界框 double bbox[6] = { 0 }; // [xmin, ymin, zmin, xmax, ymax, zmax] if (UF_MODL_ask_bounding_box(currentObject, bbox) == 0) // 获取边界框 { // 检查实体最低点是否高于Z0 if (bbox[2] > 0.0) // bbox[2] 是 Zmin { filteredObjects.push_back(currentObject); // 添加到筛选列表 //// 调试信息:显示实体的最低点高度 //char debugMsg[256]; // 调试信息缓冲区 //snprintf(debugMsg, sizeof(debugMsg), // "实体 %d 最低点: %.2f", currentObject, bbox[2]); // 格式化信息 // 使用NXMessageBox替代theUFUI //theUI->NXMessageBox()->Show("调试信息", NXMessageBox::DialogTypeInformation, debugMsg); // 显示调试信息 } } } } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 获取下一个实体 } //// 显示筛选后的实体数量 //char objCountMsg[256]; // 消息缓冲区 //snprintf(objCountMsg, sizeof(objCountMsg), // "找到最低点高于Z0的实体数量: %zu", filteredObjects.size()); // 格式化消息 //theUI->NXMessageBox()->Show("实体筛选", NXMessageBox::DialogTypeInformation, objCountMsg); // 显示消息 if (filteredObjects.empty()) // 检查是否有符合条件的实体 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "没有符合条件的实体!"); // 显示提示 return 0; // 提前返回 } // 3. 从筛选后的实体中收集所有圆弧面 std::vector<NXOpen::TaggedObject*> allFaces; // 存储所有面对象 for (tag_t objectTag : filteredObjects) // 遍历筛选后的实体 { uf_list_p_t faceList = nullptr; // 面列表指针 if (UF_MODL_ask_body_faces(objectTag, &faceList) != 0) continue; // 获取实体所有面 // 自动释放列表内存的RAII封装 auto listDeleter = [](uf_list_p_t* list) { if (*list) UF_MODL_delete_list(list); }; // 自定义删除器 std::unique_ptr<uf_list_p_t, decltype(listDeleter)> listGuard(&faceList, listDeleter); // 智能指针管理 int faceCount = 0; // 面数量 UF_MODL_ask_list_count(faceList, &faceCount); // 获取面数量 for (int i = 0; i < faceCount; i++) // 遍历所有面 { tag_t faceTag = NULL_TAG; // 面标签 UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面标签 if (auto face = dynamic_cast<NXOpen::Face*>(NXOpen::NXObjectManager::Get(faceTag))) // 转换为面对象 { allFaces.push_back(face); // 添加到面列表 } } } // 4. 收集所有圆弧面(包括圆柱、圆锥和圆角面) std::vector<NXOpen::TaggedObject*> allArcFaces; // 存储圆弧面对象 int cylinderCount = 0, coneCount = 0, blendCount = 0; // 各类面计数器 for (auto faceObj : allFaces) // 遍历所有面 { tag_t faceTag = faceObj->Tag(); // 获取面标签 int faceType = 0; // 面类型 double point[3] = { 0 }; // 点坐标 double dir[3] = { 0 }; // 方向向量 double box[6] = { 0 }; // 边界框 double radius = 0; // 半径 double rad_data[2] = { 0 }; // 半径数据 int norm_dir = 0; // 法线方向 // 获取面数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, dir, box, &radius, rad_data, &norm_dir) != 0) continue; // 跳过获取失败的面 // 只收集圆弧相关面类型 if (faceType == 16) // 圆柱面 { cylinderCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 7) // 圆锥面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 19) // 圆环曲面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 18) // 球面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 23) // 圆角面 { blendCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } } //// 显示圆弧面统计信息 //char debugMsg[256]; // 消息缓冲区 //snprintf(debugMsg, sizeof(debugMsg), // "从筛选实体中找到圆弧面总数: %zu\n圆柱面: %d\n圆锥面: %d\n圆角面: %d", // allArcFaces.size(), cylinderCount, coneCount, blendCount); // 格式化消息 //theUI->NXMessageBox()->Show("圆弧面统计", NXMessageBox::DialogTypeInformation, debugMsg); // 显示消息 if (allArcFaces.empty()) // 检查是否有圆弧面 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "筛选实体中没有圆弧面!"); // 显示提示 return 0; // 提前返回 } // 5. 直接选择所有圆弧面 face1->SetSelectedObjects(allArcFaces); // 设置选中的面 UF_DISP_refresh(); // 刷新显示 //// 显示最终结果 //char msg[256]; // 结果消息缓冲区 //snprintf(msg, sizeof(msg), "已选择 %zu 个圆弧面", allArcFaces.size()); // 格式化消息 //theUI->NXMessageBox()->Show("操作成功", NXMessageBox::DialogTypeInformation, msg); // 显示结果 } } catch (std::exception& ex) // 捕获异常 { theUI->NXMessageBox()->Show("MICH-明:系统错误", NXMessageBox::DialogTypeError, ex.what()); // 显示错误信息 } //---------Enter your code here----------- } else if(block == gaodipoints) { try { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); if (displayPart == NULL_TAG) { theUI->NXMessageBox()->Show("MICH-明错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); return 0; } // 2. 收集所有可见实体 std::vector<tag_t> allBodies; tag_t currentBody = NULL_TAG; UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); while (currentBody != NULL_TAG) { UF_OBJ_disp_props_t disp_props; if (UF_OBJ_ask_display_properties(currentBody, &disp_props) == 0) { if (disp_props.blank_status == UF_OBJ_NOT_BLANKED) { int layer_status = 0; UF_LAYER_ask_status(disp_props.layer, &layer_status); if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) { allBodies.push_back(currentBody); } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); } if (allBodies.empty()) { theUI->NXMessageBox()->Show("MICH-明提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); return 0; } // 3. 收集目标实体和它们的最大边界面 std::set<tag_t> targetBodies; std::vector<tag_t> targetFaces; // 存储最大边界上的面 const double normal_tolerance = 0.0175; // 法向容差≈1°(弧度) const double coord_tolerance = 0.001; // 坐标容差(1毫米) const double z_axis[3] = { 0.0, 0.0, 1.0 }; // Z轴方向向量 // 遍历所有实体 for (tag_t bodyTag : allBodies) { // 3.1 获取实体的边界框 double bodyMinPoint[3], bodyMaxPoint[3]; if (UF_MODL_ask_bounding_box(bodyTag, bodyMinPoint, bodyMaxPoint) != 0) continue; // 3.2 获取实体的所有面 uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(bodyTag, &faceList) != 0) continue; int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); // 3.3 遍历实体的每个面 for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); int faceType = 0; if (UF_MODL_ask_face_type(faceTag, &faceType) != 0) continue; // 只处理平面 if (faceType == UF_MODL_PLANAR_FACE) { double direction[3] = { 0 }; // 面法向 double point[3] = { 0 }; // 面上一点 double box[6] = { 0 }; // 面边界框 double rad = 0, rad_data[2] = { 0 }; int status = 0; // 获取面几何数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) { // 3.4 检查是否为垂直平面(平行于Z轴) // 法向与Z轴的点积应接近0(垂直) double dot = z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]; if (fabs(dot) < normal_tolerance) { // 3.5 检查面是否位于实体的最大边界上 bool isMaxBoundaryFace = false; // 检查X方向最大边界 if (fabs(box[3] - bodyMaxPoint[0]) < coord_tolerance) { // 法向应与X轴正方向一致(朝外) if (direction[0] > 0.5) { isMaxBoundaryFace = true; } } // 检查Y方向最大边界 else if (fabs(box[4] - bodyMaxPoint[1]) < coord_tolerance) { // 法向应与Y轴正方向一致(朝外) if (direction[1] > 0.5) { isMaxBoundaryFace = true; } } // 检查X方向最小边界(法向朝外) if (!isMaxBoundaryFace && fabs(box[0] - bodyMinPoint[0]) < coord_tolerance) { if (direction[0] < -0.5) { isMaxBoundaryFace = true; } } // 检查Y方向最小边界(法向朝外) else if (!isMaxBoundaryFace && fabs(box[1] - bodyMinPoint[1]) < coord_tolerance) { if (direction[1] < -0.5) { isMaxBoundaryFace = true; } } // 3.6 如果是最大边界上的面,添加到结果 if (isMaxBoundaryFace) { targetBodies.insert(bodyTag); targetFaces.push_back(faceTag); } } } } } UF_MODL_delete_list(&faceList); // 释放面列表内存 } // 4. 检查是否有符合条件的实体 if (targetBodies.empty()) { theUI->NXMessageBox()->Show("MICH-明提示", NXMessageBox::DialogTypeInformation, "未找到符合要求的实体!"); return 0; } // 5. 着色处理 if (color5 != nullptr) { try { // 获取选择的颜色 PropertyList* colorProps = color5->GetProperties(); std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; delete colorProps; // 6. 为实体和边界面着色 for (tag_t faceTag : targetFaces) { UF_OBJ_set_color(faceTag, colorID); // 为边界面着色 } // 刷新显示 UF_DISP_refresh(); // 显示结果信息 char msg[256]; snprintf(msg, sizeof(msg), "已为 %zu 个实体的 %zu 个边界面设置颜色", targetBodies.size(), targetFaces.size()); theUI->NXMessageBox()->Show("着色完成", NXMessageBox::DialogTypeInformation, msg); } catch (std::exception& ex) { theUI->NXMessageBox()->Show("MICH-明提示:着色错误", NXMessageBox::DialogTypeError, ex.what()); } } else { theUI->NXMessageBox()->Show("MICH-明错误提示", NXMessageBox::DialogTypeError, "颜色选择控件未初始化!"); } } catch (std::exception& ex) { theUI->NXMessageBox()->Show("MICH-明:系统错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //Callback Name: ok_cb //------------------------------------------------------------------------------ int gaiyansetool::ok_cb() { int errorCode = 0; try { errorCode = apply_cb(); } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Function Name: GetBlockProperties //Description: Returns the propertylist of the specified BlockID //------------------------------------------------------------------------------ PropertyList* gaiyansetool::GetBlockProperties(const char *blockID) { return theDialog->GetBlockProperties(blockID); } 提示严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) E0140 函数调用中的参数太多 gaiyansetool D:\NXopen\BaiduSyncdisk\studio\gaiyansetool\gaiyansetool.cpp 1083
08-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值