NX⼆次开发-使⽤数学⽅法计算两个向量之间的夹⾓(计算顺逆判断锐⾓还是钝⾓)
前两天有⽹友在QQ⾥提了⼀个问题,关于求向量夹⾓的问题。
他是先求⾯的⽮量⽅向,然后⽤向量求⾓度,⾃⼰写的函数求⾓度。他得到的是锐⾓
后来⾥⼤家推荐他⽤UF_VEC3_angle_between这个函数,结果测试还是锐⾓。
这个时候的我还在等待着他们讨论完问题的答案(因为我不会)......
⼤致就是他想判断两个向量之间的夹⾓是锐⾓还是钝⾓
举例的模型
也有⼈说直接判断边更快,凹凸边。
⽤到的pk函数是
PK_EDGE_ask_convexity  PK_EDGE_convexity_convex_c :边缘是凸的。
PK_EDGE_convexity_concave_c :边缘是凹的。
锐⾓就是凹边,PK帮助上有讲的
讨论了⼀会,⾥⼀个⼥⽹友(我有两只猫)发了⽅法
我不会数学计算两个向量之间的夹⾓,我只会⽤函数UF_VEC3_angle_between去计算
在QQ⾥,有个⼥⽹友在⾥⾯发了⼀下数学⽅法计算两个向量之间的夹⾓,我收藏记录⼀下。
这是她QQ⾥发的代码
#define  _USE_MATH_DEFINES
#include <math.h>
/* 起始向量*/
double x0 = 0, y0 = 0, z0 = 1;
/* ⽬标向量*/
double x1 = 0, y1 = 1, z1 = 0;
/
* 计算夹⾓*/
double dot = x0*x1+y0*y1+z0*z1;
double aDot = std::round(std::acos(dot) * 180 / M_PI)
/* 计算顺逆*/
double ss2 = (y0*z1-z0*y1) + (z0*x1-x0*z1) +(x0*y1-y0*x1);
double(ss2 < 0)
aDot = 360 - aDot;
#define  _USE_MATH_DEFINES
#include <math.h>
double getVecAngle(const double vec0[3], const double vec1[3])
{
/
* 起始向量*/
double x0, y0, z0;
/* ⽬标向量*/
double x1, y1, z1;
double ret_val = 0.f;
/* 向量单位化  */
double magnitude = std::sqrt(vec0[0] * vec0[0] + vec0[1] * vec0[1] + vec0[2] * vec0[2]);
if (std::fabs(magnitude) < 1e-6) {
// 0向量没意义
return ret_val;
}
x0 = vec0[0] / magnitude;
y0 = vec0[1] / magnitude;
z0 = vec0[2] / magnitude;
magnitude = std::sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]);
if (std::fabs(magnitude) < 1e-6) {
// 0向量没意义
return ret_val;
}
x1 = vec1[0] / magnitude;
y1 = vec1[1] / magnitude;
z1 = vec1[2] / magnitude;
ret_val = (((y0*z1 - z0*y1) + (z0*x1 - x0*z1) + (x0*y1 - y0*x1)) < 0.f) ? (std::round(std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI)) : (360 - std::round(std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI));
return ret_val;
}
这是我的demo
//NX9_NXOpenCPP_Wizard1
#define  _USE_MATH_DEFINES
#include <stdio.h>
#include <math.h>
// Mandatory UF Includes
#include <uf.h>
#include <uf_object_types.h>
// Internal Includes
#include <NXOpen/ListingWindow.hxx>
#include <NXOpen/NXMessageBox.hxx>
#include <NXOpen/UI.hxx>
// Internal+External Includes
#include <NXOpen/Annotations.hxx>
#include <NXOpen/Assemblies_Component.hxx>
#include <NXOpen/Assemblies_ComponentAssembly.hxx> #include <NXOpen/Body.hxx>
#include <NXOpen/BodyCollection.hxx>
#include <NXOpen/Face.hxx>
#include <NXOpen/Line.hxx>
#include <NXOpen/NXException.hxx>
#include <NXOpen/NXObject.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/Session.hxx>
#include <uf.h>
#include <uf_ui.h>
#include <uf_vec.h>
#include <uf_curve.h>
// Std C++ Includes
#include <iostream>
#include <sstream>
using namespace NXOpen;
using std::string;
using std::exception;
using std::stringstream;
using std::endl;
using std::cout;
using std::cerr;
//------------------------------------------------------------------------------// NXOpen c++ test class
//------------------------------------------------------------------------------class MyClass
{
/
/ class members
public:
static Session *theSession;
static UI *theUI;
MyClass();
~MyClass();
void do_it();
void print(const NXString &);
void print(const string &);
void print(const char*);
private:
Part *workPart, *displayPart;
NXMessageBox *mb;
ListingWindow *lw;
LogFile *lf;
};
//------------------------------------------------------------------------------// Initialize static variables
//------------------------------------------------------------------------------Session *(MyClass::theSession) = NULL;
UI *(MyClass::theUI) = NULL;
//------------------------------------------------------------------------------// Constructor
//------------------------------------------------------------------------------MyClass::MyClass()
{
// Initialize the NX Open C++ API environment
MyClass::theSession = NXOpen::Session::GetSession();    MyClass::theUI = UI::GetUI();
mb = theUI->NXMessageBox();
lw = theSession->ListingWindow();
lf = theSession->LogFile();
workPart = theSession->Parts()->Work();
displayPart = theSession->Parts()->Display();
}
//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
MyClass::~MyClass()
{
}
//------------------------------------------------------------------------------
// Print string to listing window or stdout
//------------------------------------------------------------------------------
void MyClass::print(const NXString &msg)
{
if(! lw->IsOpen() ) lw->Open();
lw->WriteLine(msg);
}
void MyClass::print(const string &msg)
{
if(! lw->IsOpen() ) lw->Open();
lw->WriteLine(msg);
}
void MyClass::print(const char * msg)
{
if(! lw->IsOpen() ) lw->Open();
lw->WriteLine(msg);
}
double round(double r)
{
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
double getVecAngle(const double vec0[3], const double vec1[3])
{
/* 起始向量*/
double x0, y0, z0;
/* ⽬标向量*/
double x1, y1, z1;
double ret_val = 0.f;
/* 向量单位化  */
double magnitude = std::sqrt(vec0[0] * vec0[0] + vec0[1] * vec0[1] + vec0[2] * vec0[2]);
if (std::fabs(magnitude) < 1e-6) {
// 0向量没意义
return ret_val;
}
x0 = vec0[0] / magnitude;
y0 = vec0[1] / magnitude;
z0 = vec0[2] / magnitude;
magnitude = std::sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]);
if (std::fabs(magnitude) < 1e-6) {
// 0向量没意义
return ret_val;
}
x1 = vec1[0] / magnitude;
y1 = vec1[1] / magnitude;
z1 = vec1[2] / magnitude;
ret_val = (((y0*z1 - z0*y1) + (z0*x1 - x0*z1) + (x0*y1 - y0*x1)) < 0.f) ? (std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI) : (360 - std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI); ///* 计算顺逆*/
double ss2 = (y0*z1-z0*y1) + (z0*x1-x0*z1) +(x0*y1-y0*x1);
if (ss2 < 0)
ret_val = 360 - ret_val;
return ret_val;
}
//------------------------------------------------------------------------------
// Do something
//------------------------------------------------------------------------------
void MyClass::do_it()
{
// TODO: add your code here
UF_initialize();
//创建直线1
UF_CURVE_line_t LineCoords1;
LineCoords1.start_point[0] = 0.0;
LineCoords1.start_point[1] = 0.0;
LineCoords1.start_point[2] = 0.0;
tag_t Line1Tag = NULL_TAG;
UF_CURVE_create_line(&LineCoords1, &Line1Tag);
//创建直线2
UF_CURVE_line_t LineCoords2;
LineCoords2.start_point[0] = 0.0;
LineCoords2.start_point[1] = 0.0;
LineCoords2.start_point[2] = 0.0;
tag_t Line2Tag = NULL_TAG;
UF_CURVE_create_line(&LineCoords2, &Line2Tag);
//直线1的向量⽅向,终点减起点
double Vec1[3] = {d_point[0]-LineCoords1.start_point[0], d_point[1]-LineCoords1.start_point[1], d_point[2]-LineCoords1.start_point[2]};
//直线2的向量⽅向,终点减起点
double Vec2[3] = {d_point[0]-LineCoords2.start_point[0], d_point[1]-LineCoords2.start_point[1], d_point[2]-LineCoords2.start_point[2]};
double ret_val = getVecAngle(Vec1, Vec2);
//打印
char msg[256];
sprintf(msg, "%f",ret_val );
uc1601(msg, 1);
UF_terminate();
}
//------------------------------------------------------------------------------
// Entry point(s) for unmanaged internal NXOpen C/C++ programs
//------------------------------------------------------------------------------
//  Explicit Execution
extern"C" DllExport void ufusr( char *parm, int *returnCode, int rlen )
{
try
{
// Create NXOpen C++ class instance
MyClass *theMyClass;
theMyClass = new MyClass();
theMyClass->do_it();
delete theMyClass;
}
catch (const NXException& e1)
{
UI::GetUI()->NXMessageBox()->Show("NXException", NXOpen::NXMessageBox::DialogTypeError, e1.Message());
}
catch (const exception& e2)
{
UI::GetUI()->NXMessageBox()->Show("Exception", NXOpen::NXMessageBox::DialogTypeError, e2.what());
}
catch (...)
{
UI::GetUI()->NXMessageBox()->Show("Exception", NXOpen::NXMessageBox::DialogTypeError, "Unknown Exception.");
}
}
//------------------------------------------------------------------------------
// Unload Handlerwriteline用什么替代
//------------------------------------------------------------------------------
extern"C" DllExport int ufusr_ask_unload()
{
return (int)NXOpen::Session::LibraryUnloadOptionImmediately;
}
先说两个动画的区别
我做了⼀个是锐⾓⼀个是钝⾓的
这个函数就是输⼊两个向量,求向量夹⾓的
double getVecAngle(const double vec0[3], const double vec1[3])
{
/* 起始向量*/
double x0, y0, z0;
/* ⽬标向量*/
double x1, y1, z1;
double ret_val = 0.f;
/* 向量单位化  */
double magnitude = std::sqrt(vec0[0] * vec0[0] + vec0[1] * vec0[1] + vec0[2] * vec0[2]);
if (std::fabs(magnitude) < 1e-6) {
/
/ 0向量没意义
return ret_val;
}
x0 = vec0[0] / magnitude;
y0 = vec0[1] / magnitude;
z0 = vec0[2] / magnitude;
magnitude = std::sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]);
if (std::fabs(magnitude) < 1e-6) {
// 0向量没意义
return ret_val;
}
x1 = vec1[0] / magnitude;
y1 = vec1[1] / magnitude;
z1 = vec1[2] / magnitude;
ret_val = (((y0*z1 - z0*y1) + (z0*x1 - x0*z1) + (x0*y1 - y0*x1)) < 0.f) ? (std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI) : (360 - std::acos(x0*x1 + y0*y1 + z0*z1) * 180 / M_PI);
///* 计算顺逆*/
double ss2 = (y0*z1-z0*y1) + (z0*x1-x0*z1) +(x0*y1-y0*x1);
if (ss2 < 0)
ret_val = 360 - ret_val;
return ret_val;
}
其中,这⾥⾯的这句判断,应该就是判断是锐⾓还是钝⾓的,以顺时针⽅向为例,如果夹⾓是⼩于90度的锐⾓,那么ss2就是⼩于0的,然后⽤360减去锐⾓的值,得到钝⾓///* 计算顺逆*/
double ss2 = (y0*z1-z0*y1) + (z0*x1-x0*z1) +(x0*y1-y0*x1);
if (ss2 < 0)
ret_val = 360 - ret_val;
对应的就是这个动画
如果夹⾓是⼤于90度的钝⾓,那么ss2就是⼤于0的,直接输出钝⾓值
对应就是下⾯这个动画
判断顺时针⽅向是锐⾓还是钝⾓?
如下图
在她的代码⾥⽤到了round四舍五⼊值,我demo⾥没⽤。如果要⽤的话,
vs2010和vs2012的math头⽂件⾥是没有round函数的,⾃⼰写⼀个函数就好了。
double round(double r)
{
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
补充,我后来去搜了⼀下
判断夹⾓是锐⾓还是钝⾓,⽤dot点乘应该也就可以了。判断点乘的值
//a·b > 0 点乘⼤于0 两个向量⽅向基本相同夹⾓在0°90°之间
//a·b = 0 点乘等于0 正交
//a·b < 0 点乘⼩于0 两个向量⽅向基本相反夹⾓在90°-180°之间
对应公式
double dot = x0*x1+y0*y1+z0*z1;
我的数学不是很好,上⾯的东西理解的不全,如果谁发现有错误的地⽅,请底部留⾔。谢谢
对应的UFUN函数版
阿飞
2021年10⽉17⽇

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。