我正在学习NX二次开发,用的是Visual Studio 2019,ug版本是12.0,开发平台是c++,uf函数为主nxopen函数为辅。需要你辅助我开发,重点注意开发模版是c++,优先使用uf函数,要求你先搞清楚你提供给我的代码真实有效性,语句与标点符号的正确位置,避免出现ug12.0没有提供的接口成员出现!确保所有方法调用都符合 NX12 的 API 签名,深度思考下再回答,每次回答前先回顾下前面的所有对话避免问题重复出现,每行代码都用中文注解具体意思与作用。
//==============================================================================
// 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\studio\daoqiaotool\ui\daoqiaotool.cpp
//
// This file was generated by the NX Block UI Styler
// Created by: MICH-ROG
// Version: NX 12
// Date: 08-16-2025 (Format: mm-dd-yyyy)
// Time: 17:45 (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 "daoqiaotool.hpp"
using namespace NXOpen;
using namespace NXOpen::BlockStyler;
//------------------------------------------------------------------------------
// Initialize static variables
//------------------------------------------------------------------------------
Session *(daoqiaotool::theSession) = NULL;
UI *(daoqiaotool::theUI) = NULL;
//------------------------------------------------------------------------------
// Constructor for NX Styler class
//------------------------------------------------------------------------------
daoqiaotool::daoqiaotool()
{
try
{
// Initialize the NX Open C++ API environment
daoqiaotool::theSession = NXOpen::Session::GetSession();
daoqiaotool::theUI = UI::GetUI();
theDlxFileName = "daoqiaotool.dlx";
theDialog = daoqiaotool::theUI->CreateDialog(theDlxFileName);
// Registration of callback functions
theDialog->AddApplyHandler(make_callback(this, &daoqiaotool::apply_cb));
theDialog->AddOkHandler(make_callback(this, &daoqiaotool::ok_cb));
theDialog->AddUpdateHandler(make_callback(this, &daoqiaotool::update_cb));
theDialog->AddInitializeHandler(make_callback(this, &daoqiaotool::initialize_cb));
theDialog->AddDialogShownHandler(make_callback(this, &daoqiaotool::dialogShown_cb));
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
throw;
}
}
//------------------------------------------------------------------------------
// Destructor for NX Styler class
//------------------------------------------------------------------------------
daoqiaotool::~daoqiaotool()
{
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)
{
daoqiaotool *thedaoqiaotool = NULL;
try
{
UF_initialize(); //开发的许可函数,初始化
thedaoqiaotool = new daoqiaotool();
// The following method shows the dialog immediately
thedaoqiaotool->Show();
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
if(thedaoqiaotool != NULL)
{
delete thedaoqiaotool;
thedaoqiaotool = 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 -----
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
}
int daoqiaotool::Show()
{
try
{
theDialog->Show();
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
return 0;
}
//------------------------------------------------------------------------------
//---------------------Block UI Styler Callback Functions--------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//Callback Name: initialize_cb
//------------------------------------------------------------------------------
void daoqiaotool::initialize_cb()
{
try
{
group2 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group2"));
enum0 = dynamic_cast<NXOpen::BlockStyler::Enumeration*>(theDialog->TopBlock()->FindBlock("enum0"));
group0 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group0"));
chuliao_edge = dynamic_cast<NXOpen::BlockStyler::CurveCollector*>(theDialog->TopBlock()->FindBlock("chuliao_edge"));
bianjie_edge = dynamic_cast<NXOpen::BlockStyler::CurveCollector*>(theDialog->TopBlock()->FindBlock("bianjie_edge"));
group = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group"));
expression_clcq = dynamic_cast<NXOpen::BlockStyler::ExpressionBlock*>(theDialog->TopBlock()->FindBlock("expression_clcq"));
expression_dqjiaodu = dynamic_cast<NXOpen::BlockStyler::ExpressionBlock*>(theDialog->TopBlock()->FindBlock("expression_dqjiaodu"));
group1 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group1"));
vector0 = dynamic_cast<NXOpen::BlockStyler::SpecifyVector*>(theDialog->TopBlock()->FindBlock("vector0"));
expression_daoxie = dynamic_cast<NXOpen::BlockStyler::ExpressionBlock*>(theDialog->TopBlock()->FindBlock("expression_daoxie"));
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
daoqiaotool::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 daoqiaotool::dialogShown_cb()
{
try
{
//---- Enter your callback code here -----
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
}
//------------------------------------------------------------------------------
//Callback Name: apply_cb
//------------------------------------------------------------------------------
int daoqiaotool::apply_cb()
{
int errorCode = 0;
try
{
// 获取NX会话和工作部件
NXOpen::Session* theSession = NXOpen::Session::GetSession();
NXOpen::Part* workPart = theSession->Parts()->Work();
NXOpen::UI* theUI = NXOpen::UI::GetUI();
// ===== 1. 获取用户界面输入参数 =====
// 获取出料边曲线
std::vector<NXOpen::Curve*> dischargeCurves;
if (chuliao_edge) {
std::unique_ptr<NXOpen::BlockStyler::PropertyList> props(chuliao_edge->GetProperties());
std::vector<NXOpen::TaggedObject*> selObjs = props->GetTaggedObjectVector("SelectedObjects");
for (NXOpen::TaggedObject* obj : selObjs) {
if (NXOpen::Curve* curve = dynamic_cast<NXOpen::Curve*>(obj)) {
dischargeCurves.push_back(curve); // 将选中的曲线添加到出料边曲线列表
}
}
}
// ====== 1. 获取选中的边对象 ======
std::vector<NXOpen::Edge*> selectedEdges;
if (bianjie_edge)
{
// 直接获取选中的对象
std::vector<NXOpen::TaggedObject*> selObjs = bianjie_edge->GetSelectedObjects();
// 遍历所有选中对象,筛选出边类型
for (NXOpen::TaggedObject* obj : selObjs)
{
if (NXOpen::Edge* edge = dynamic_cast<NXOpen::Edge*>(obj))
{
selectedEdges.push_back(edge);
}
}
}
// 获取出料沉桥值
double materialThickness = 0.0;
if (expression_clcq) {
std::unique_ptr<NXOpen::BlockStyler::PropertyList> props(expression_clcq->GetProperties());
materialThickness = props->GetDouble("Value"); // 从表达式控件获取数值
}
// 获取倒桥角度值
double currentAngle = 0.0;
if (expression_dqjiaodu) {
std::unique_ptr<NXOpen::BlockStyler::PropertyList> props(expression_dqjiaodu->GetProperties());
currentAngle = props->GetDouble("Value"); // 从表达式控件获取数值
}
// 获取倒斜角深度值
double daoxieValue = 0.0;
if (expression_daoxie) {
std::unique_ptr<NXOpen::BlockStyler::PropertyList> props(expression_clcq->GetProperties());
materialThickness = props->GetDouble("Value"); // 从表达式控件获取数值
}
// 获取矢量方向(默认Z轴方向)
NXOpen::Vector3d directionVector(0.0, 0.0, 1.0);
if (vector0) {
std::unique_ptr<NXOpen::BlockStyler::PropertyList> props(vector0->GetProperties());
directionVector = props->GetVector("Vector"); // 获取用户指定的矢量方向
}
//获取ui枚举索引值
int iType = 0;
iType = this->enum0->GetProperties()->GetEnum("Value");
if (iType == 0)
{
}
else
{
}
//---- Enter your callback code here -----
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
errorCode = 1;
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
return errorCode;
}
//------------------------------------------------------------------------------
//Callback Name: update_cb
//------------------------------------------------------------------------------
int daoqiaotool::update_cb(NXOpen::BlockStyler::UIBlock* block)
{
try
{
if(block == enum0)
{
//---------Enter your code here-----------
}
else if(block == chuliao_edge)
{
//---------Enter your code here-----------
}
else if(block == bianjie_edge)
{
//---------Enter your code here-----------
}
else if(block == expression_clcq)
{
//---------Enter your code here-----------
}
else if(block == expression_dqjiaodu)
{
//---------Enter your code here-----------
}
else if(block == vector0)
{
//---------Enter your code here-----------
}
else if(block == expression_daoxie)
{
//---------Enter your code here-----------
}
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
return 0;
}
//------------------------------------------------------------------------------
//Callback Name: ok_cb
//------------------------------------------------------------------------------
int daoqiaotool::ok_cb()
{
int errorCode = 0;
try
{
errorCode = apply_cb();
}
catch(exception& ex)
{
//---- Enter your exception handling code here -----
errorCode = 1;
daoqiaotool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what());
}
return errorCode;
}
//------------------------------------------------------------------------------
//Function Name: GetBlockProperties
//Description: Returns the propertylist of the specified BlockID
//------------------------------------------------------------------------------
PropertyList* daoqiaotool::GetBlockProperties(const char *blockID)
{
return theDialog->GetBlockProperties(blockID);
}
帮我把下面拉伸的功能加到上面“if (iType == 0)
{”里面,拉伸截面用“chuliao_edge”,起始位置用“expression_clcq”,结束位置固定“100”,取消偏置,方向用“vector0”,
拔模用“expression_dqjiaodu”,“动态偏置方向判断”改为“动态拔模方向判断”,取消曲线配对部分,直接用“bianjie_edge”做投影判断,:以下是参考部分“try {
// 设置撤销标记
NXOpen::Session::UndoMarkId markId2 = theSession->SetUndoMark(
NXOpen::Session::MarkVisibilityVisible, "出料边拉伸求差");
// 验证延伸曲线是否可用
if (extendedCurves.empty()) {
throw std::runtime_error("没有可用的延伸曲线作为拉伸截面");
}
// 选择第一条延伸曲线作为拉伸截面
NXOpen::Curve* curveForExtrude = extendedCurves[0];
// 创建主拉伸构建器(用于最终特征)
NXOpen::Features::ExtrudeBuilder* mainExtrudeBuilder =
workPart->Features()->CreateExtrudeBuilder(nullptr);
// 创建主截面对象(独立资源)
NXOpen::Section* mainSection = workPart->Sections()->CreateSection(
0.001, 0.001, 0.05); // 距离公差0.001mm,角度公差0.05度
mainExtrudeBuilder->SetSection(mainSection);
// 创建曲线选择规则
std::vector<NXOpen::Curve*> sectionCurves2;
sectionCurves2.push_back(curveForExtrude);
NXOpen::SelectionIntentRule* curveRule2 =
workPart->ScRuleFactory()->CreateRuleCurveDumb(sectionCurves2);
// 获取曲线中点作为帮助点
NXOpen::Point3d helpPoint2(0.0, 0.0, 0.0);
{
tag_t curveTag = curveForExtrude->Tag();
UF_EVAL_p_t evaluator = NULL;
double limits[2];
if (UF_EVAL_initialize(curveTag, &evaluator) == 0) {
if (UF_EVAL_ask_limits(evaluator, limits) == 0) {
if (limits[0] > limits[1]) std::swap(limits[0], limits[1]);
double midParam = (limits[0] + limits[1]) / 2.0;
double midPoint[3];
if (UF_EVAL_evaluate(evaluator, 0, midParam, midPoint, NULL) == 0) {
helpPoint2 = NXOpen::Point3d(midPoint[0], midPoint[1], midPoint[2]);
}
}
UF_EVAL_free(evaluator);
}
}
// 添加曲线到主截面
std::vector<NXOpen::SelectionIntentRule*> rules2;
rules2.push_back(curveRule2);
mainSection->AddToSection(
rules2, // 曲线规则集合
curveForExtrude, // 主要曲线对象
nullptr, // 不指定曲线起点
nullptr, // 不指定曲线终点
helpPoint2, // 帮助点(中点)
NXOpen::Section::ModeCreate // 创建模式
);
// 设置拉伸方向(与第一个拉伸相同)
NXOpen::Point3d origin(0.0, 0.0, 0.0);
NXOpen::Direction* extrudeDirection2 =
workPart->Directions()->CreateDirection(
origin,
directionVector, // 使用相同的方向矢量
NXOpen::SmartObject::UpdateOptionWithinModeling
);
mainExtrudeBuilder->SetDirection(extrudeDirection2);
// 设置拉伸范围
NXOpen::GeometricUtilities::Limits* limitsObj2 = mainExtrudeBuilder->Limits();
// 起始距离 = 材料厚度(与第一个拉伸相同)
limitsObj2->StartExtend()->Value()->SetRightHandSide(
std::to_string(materialThickness).c_str());
// 结束距离 = 扫描高度 + 10mm
limitsObj2->EndExtend()->Value()->SetRightHandSide(
std::to_string(scanHeight + 10.0).c_str());
// ===== 关键修改:动态偏置方向判断逻辑 =====
double endOffsetValue = 100.0; // 默认正偏置100mm
bool canProject = false; // 投影验证结果标志
// ===== 第一步:创建临时拉伸体进行投影验证(使用独立资源)=====
try {
// 创建临时拉伸构建器(用于投影验证)
NXOpen::Features::ExtrudeBuilder* tempExtrudeBuilder =
workPart->Features()->CreateExtrudeBuilder(nullptr);
// 创建临时截面(不与主截面共享)
NXOpen::Section* tempSection = workPart->Sections()->CreateSection(
0.001, 0.001, 0.05);
tempExtrudeBuilder->SetSection(tempSection);
// 复制曲线规则到临时截面
std::vector<NXOpen::Curve*> tempCurves;
tempCurves.push_back(curveForExtrude);
NXOpen::SelectionIntentRule* tempRule =
workPart->ScRuleFactory()->CreateRuleCurveDumb(tempCurves);
std::vector<NXOpen::SelectionIntentRule*> tempRules;
tempRules.push_back(tempRule);
tempSection->AddToSection(
tempRules,
curveForExtrude,
nullptr,
nullptr,
helpPoint2,
NXOpen::Section::ModeCreate
);
// 复制方向设置
tempExtrudeBuilder->SetDirection(extrudeDirection2);
// 复制拉伸范围
NXOpen::GeometricUtilities::Limits* tempLimits = tempExtrudeBuilder->Limits();
tempLimits->StartExtend()->Value()->SetRightHandSide(
std::to_string(materialThickness).c_str());
tempLimits->EndExtend()->Value()->SetRightHandSide(
std::to_string(scanHeight + 10.0).c_str());
// 设置临时偏置(默认正偏置100)
NXOpen::GeometricUtilities::FeatureOffset* tempOffset = tempExtrudeBuilder->Offset();
tempOffset->SetOption(NXOpen::GeometricUtilities::TypeNonsymmetricOffset);
tempOffset->StartOffset()->SetRightHandSide("0");
tempOffset->EndOffset()->SetRightHandSide("100");
// 设置布尔操作类型为创建(避免影响模型)
tempExtrudeBuilder->BooleanOperation()->SetType(
NXOpen::GeometricUtilities::BooleanOperation::BooleanTypeCreate);
// 提交临时拉伸特征
NXOpen::NXObject* tempFeature = tempExtrudeBuilder->Commit();
// 检查是否成功创建特征
if (!tempFeature) {
throw std::runtime_error("临时拉伸特征创建失败");
}
// 获取临时实体
std::vector<NXOpen::Body*> tempBodies;
if (NXOpen::Features::Extrude* extrudeFeature =
dynamic_cast<NXOpen::Features::Extrude*>(tempFeature)) {
tempBodies = extrudeFeature->GetBodies();
}
// ===== 曲线配对逻辑(找出与第一条延伸曲线配对的边界曲线)=====
NXOpen::Curve* targetBoundaryCurve = nullptr;
{
// 1. 确保有两条延伸曲线和两条边界曲线
if (extendedCurves.size() < 2 || boundaryCurves.size() < 2) {
throw std::runtime_error("需要两条延伸曲线和两条边界曲线");
}
// 2. 获取两条延伸曲线和两条边界曲线
NXOpen::Curve* extCurve1 = extendedCurves[0];
NXOpen::Curve* extCurve2 = extendedCurves[1];
NXOpen::Curve* bndCurve1 = boundaryCurves[0];
NXOpen::Curve* bndCurve2 = boundaryCurves[1];
// 3. 计算所有曲线的中点
struct CurveMidPoint {
NXOpen::Curve* curve;
double midPoint[3];
};
// 计算中点函数
auto calculateMidPoint = [](NXOpen::Curve* curve) -> double* {
static double midPoint[3] = { 0 };
UF_EVAL_p_t evaluator = NULL;
if (UF_EVAL_initialize(curve->Tag(), &evaluator) == 0) {
double limits[2];
if (UF_EVAL_ask_limits(evaluator, limits) == 0) {
double midParam = (limits[0] + limits[1]) / 2.0;
UF_EVAL_evaluate(evaluator, 0, midParam, midPoint, NULL);
}
UF_EVAL_free(evaluator);
}
return midPoint;
};
// 存储所有曲线的中点
CurveMidPoint extMid1 = { extCurve1, {0} };
memcpy(extMid1.midPoint, calculateMidPoint(extCurve1), 3 * sizeof(double));
CurveMidPoint extMid2 = { extCurve2, {0} };
memcpy(extMid2.midPoint, calculateMidPoint(extCurve2), 3 * sizeof(double));
CurveMidPoint bndMid1 = { bndCurve1, {0} };
memcpy(bndMid1.midPoint, calculateMidPoint(bndCurve1), 3 * sizeof(double));
CurveMidPoint bndMid2 = { bndCurve2, {0} };
memcpy(bndMid2.midPoint, calculateMidPoint(bndCurve2), 3 * sizeof(double));
// 4. 计算距离函数
auto distance = [](double p1[3], double p2[3]) -> double {
double dx = p1[0] - p2[0];
double dy = p1[1] - p2[1];
double dz = p1[2] - p2[2];
return sqrt(dx * dx + dy * dy + dz * dz);
};
// 5. 计算所有可能的距离组合
double d11 = distance(extMid1.midPoint, bndMid1.midPoint); // 延伸1-边界1
double d12 = distance(extMid1.midPoint, bndMid2.midPoint); // 延伸1-边界2
double d21 = distance(extMid2.midPoint, bndMid1.midPoint); // 延伸2-边界1
double d22 = distance(extMid2.midPoint, bndMid2.midPoint); // 延伸2-边界2
// 6. 找出最短距离的组合
struct Pairing {
NXOpen::Curve* extCurve;
NXOpen::Curve* bndCurve;
double distance;
};
std::vector<Pairing> allPairs = {
{extCurve1, bndCurve1, d11},
{extCurve1, bndCurve2, d12},
{extCurve2, bndCurve1, d21},
{extCurve2, bndCurve2, d22}
};
// 7. 找出最短距离的组合
auto minPair = *std::min_element(allPairs.begin(), allPairs.end(),
[](const Pairing& a, const Pairing& b) {
return a.distance < b.distance;
});
// 8. 从原始集合中移除已配对的曲线
std::vector<NXOpen::Curve*> remainingExtCurves = { extCurve1, extCurve2 };
std::vector<NXOpen::Curve*> remainingBndCurves = { bndCurve1, bndCurve2 };
auto removeCurve = [](std::vector<NXOpen::Curve*>& vec, NXOpen::Curve* curve) {
vec.erase(std::remove(vec.begin(), vec.end(), curve), vec.end());
};
removeCurve(remainingExtCurves, minPair.extCurve);
removeCurve(remainingBndCurves, minPair.bndCurve);
// 9. 创建最终配对结果
std::vector<std::pair<NXOpen::Curve*, NXOpen::Curve*>> closestPairs;
// 第一对:最短距离组合
closestPairs.push_back({ minPair.extCurve, minPair.bndCurve });
// 第二对:剩余曲线组合
if (!remainingExtCurves.empty() && !remainingBndCurves.empty()) {
closestPairs.push_back({ remainingExtCurves[0], remainingBndCurves[0] });
}
// 10. 验证配对结果
if (closestPairs.size() != 2) {
throw std::runtime_error("无法创建完整的配对组合");
}
// 11. 找出与extendedCurves[0]配对的边界曲线
for (const auto& pair : closestPairs) {
if (pair.first == curveForExtrude) { // 使用当前截面曲线
targetBoundaryCurve = pair.second;
break;
}
}
//// 12. 高亮显示目标边界曲线
//if (targetBoundaryCurve) {
// UF_DISP_set_highlight(targetBoundaryCurve->Tag(), 1); // 高亮显示
// UF_DISP_refresh();
//}
}
// ===== 投影验证逻辑 =====
canProject = false;
if (targetBoundaryCurve && !tempBodies.empty()) {
// 创建曲线链表
uf_list_p_t curveList = NULL;
if (UF_MODL_create_list(&curveList) == 0) {
// 添加目标边界曲线到链表
tag_t curveTag = targetBoundaryCurve->Tag();
if (UF_MODL_put_list_item(curveList, curveTag) == 0) {
// 获取实体所有面
uf_list_p_t faceList = NULL;
tag_t bodyTag = tempBodies[0]->Tag();
if (UF_MODL_ask_body_faces(bodyTag, &faceList) == 0) {
// 归一化投影方向
double dirMagnitude = sqrt(directionVector.X * directionVector.X +
directionVector.Y * directionVector.Y +
directionVector.Z * directionVector.Z);
if (dirMagnitude > 1e-6) {
double projDirection[3] = {
directionVector.X / dirMagnitude,
directionVector.Y / dirMagnitude,
directionVector.Z / dirMagnitude
};
// 执行投影
tag_t projCurveFeatTag = NULL_TAG;
int status = UF_MODL_create_proj_curves(
curveList, // 输入曲线列表
faceList, // 目标面列表
0, // 使用投影向量
projDirection, // 投影方向矢量
&projCurveFeatTag
);
// 处理投影结果
if (status == 0 && projCurveFeatTag != NULL_TAG) {
canProject = true;
// 删除临时投影特征
UF_OBJ_delete_object(projCurveFeatTag);
}
}
// 释放面链表
UF_MODL_delete_list(&faceList);
}
}
// 释放曲线链表
UF_MODL_delete_list(&curveList);
}
}
// ===== 清理临时资源 =====
// 销毁临时构建器
tempExtrudeBuilder->Destroy();
// 销毁临时截面
tempSection->Destroy();
// 删除临时特征
if (tempFeature) {
std::vector<NXOpen::TaggedObject*> toDelete(1);
toDelete[0] = tempFeature;
theSession->UpdateManager()->AddObjectsToDeleteList(toDelete);
}
}
catch (std::exception& ex) {
// 临时验证失败时使用默认设置
canProject = false;
char warnMsg[256];
snprintf(warnMsg, sizeof(warnMsg), "投影验证失败: %s\n使用默认偏置设置", ex.what());
theUI->NXMessageBox()->Show("MICH-明:提示警告",
NXOpen::NXMessageBox::DialogTypeWarning, warnMsg);
}
// ===== 第二步:根据验证结果设置最终偏置值 =====
if (!canProject) {
endOffsetValue = -100.0; // 负偏置-100mm
}
// ===== 设置偏置模式 =====
// 获取拉伸特征的偏置构建器
NXOpen::GeometricUtilities::FeatureOffset* featureOffset = mainExtrudeBuilder->Offset();
// 设置非对称偏置(两侧不同距离)
featureOffset->SetOption(NXOpen::GeometricUtilities::TypeNonsymmetricOffset);
// 设置具体偏置值
featureOffset->StartOffset()->SetRightHandSide("0"); // 起始端偏置0
// 动态设置偏置值
char offsetValueStr[32];
snprintf(offsetValueStr, sizeof(offsetValueStr), "%.2f", endOffsetValue);
featureOffset->EndOffset()->SetRightHandSide(offsetValueStr);
// 设置拔模类型:从起始位置简单拔模
mainExtrudeBuilder->Draft()->SetDraftOption(
NXOpen::GeometricUtilities::SimpleDraft::SimpleDraftTypeSimpleFromStart);
// 设置前拔模角度(从截面开始处拔模)
mainExtrudeBuilder->Draft()->FrontDraftAngle()->SetRightHandSide(
std::to_string(currentAngle).c_str());
// 设置后拔模角度(这里设为0,因为只需要单边拔模)
mainExtrudeBuilder->Draft()->BackDraftAngle()->SetRightHandSide("0");
// ===== 设置布尔操作 =====
// 设置操作类型:求差(从第一个拉伸实体中减去此拉伸)
mainExtrudeBuilder->BooleanOperation()->SetType(
NXOpen::GeometricUtilities::BooleanOperation::BooleanTypeSubtract);
// 设置目标体(第一个拉伸实体)
std::vector<NXOpen::Body*> targetBodies;
if (firstExtrudeBody) {
targetBodies.push_back(firstExtrudeBody);
mainExtrudeBuilder->BooleanOperation()->SetTargetBodies(targetBodies);
}
else {
throw std::runtime_error("第一个拉伸实体未找到");
}
// ===== 执行拉伸操作 =====
NXOpen::NXObject* featureNXObject2 = mainExtrudeBuilder->Commit();
// 检查是否成功创建特征
if (!featureNXObject2) {
throw std::runtime_error("出料一创建失败");
}
//// 显示偏置方向信息
//char offsetMsg[256];
//snprintf(offsetMsg, sizeof(offsetMsg),
// "使用偏置方向: %s\n投影验证结果: %s",
// (endOffsetValue > 0) ? "正偏置(100mm)" : "负偏置(-100mm)",
// canProject ? "成功" : "失败");
//theUI->NXMessageBox()->Show("偏置设置",
// NXOpen::NXMessageBox::DialogTypeInformation, offsetMsg);
// 获取创建的实体
NXOpen::Features::Extrude* extrudeFeature2 =
dynamic_cast<NXOpen::Features::Extrude*>(featureNXObject2);
std::vector<NXOpen::Body*> resultBodies2;
if (extrudeFeature2) {
resultBodies2 = extrudeFeature2->GetBodies();
}
// 清理资源
mainExtrudeBuilder->Destroy();
mainSection->Destroy();”