NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

前两天有网友在QQ群里提了一个问题,关于求向量夹角的问题。

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 他是先求面的矢量方向,然后用向量求角度,自己写的函数求角度。他得到的是锐角

后来群里大家推荐他用UF_VEC3_angle_between这个函数,结果测试还是锐角。

这个时候的我还在等待着他们讨论完问题的答案(因为我不会)......

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 大致就是他想判断两个向量之间的夹角是锐角还是钝角

举例的模型

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 也有人说直接判断边更快,凹凸边。

用到的pk函数是

PK_EDGE_ask_convexity   PK_EDGE_convexity_convex_c :边缘是凸的。
PK_EDGE_convexity_concave_c :边缘是凹的。

 锐角就是凹边,PK帮助上有讲的

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 讨论了一会,群里一个女网友(我有两只猫)发了方法

我不会数学计算两个向量之间的夹角,我只会用函数UF_VEC3_angle_between去计算NX二次开发-UFUN已知两个向量方向求夹角角度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;
    LineCoords1.end_point[0] = 0.0;
    LineCoords1.end_point[1] = 100.0;
    LineCoords1.end_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;
    LineCoords2.end_point[0] = 110.0;
    LineCoords2.end_point[1] = 80.0;
    LineCoords2.end_point[2] = 0.0;
    tag_t Line2Tag = NULL_TAG;
    UF_CURVE_create_line(&LineCoords2, &Line2Tag);

    //直线1的向量方向,终点减起点
    double Vec1[3] = {LineCoords1.end_point[0]-LineCoords1.start_point[0], LineCoords1.end_point[1]-LineCoords1.start_point[1], LineCoords1.end_point[2]-LineCoords1.start_point[2]};

    //直线2的向量方向,终点减起点
    double Vec2[3] = {LineCoords2.end_point[0]-LineCoords2.start_point[0], LineCoords2.end_point[1]-LineCoords2.start_point[1], LineCoords2.end_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 Handler
//------------------------------------------------------------------------------
extern "C" DllExport int ufusr_ask_unload()
{
    return (int)NXOpen::Session::LibraryUnloadOptionImmediately;
}

 

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

先说两个动画的区别

我做了一个是锐角一个是钝角的

这个函数就是输入两个向量,求向量夹角的

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;

对应的就是这个动画

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

如果夹角是大于90度的钝角,那么ss2就是大于0的,直接输出钝角值

对应就是下面这个动画

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

判断顺时针方向是锐角还是钝角?

如下图

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

 

NX二次开发-使用数学方法计算两个向量之间的夹角(计算顺逆判断锐角还是钝角)

 

在她的代码里用到了round四舍五入值,我demo里没用。如果要用的话,

vs2010和vs2012的math头文件里是没有round函数的,自己写一个函数就好了。

百度上都有

double round(double r)
{
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

 

根据她的代码,我是这样分析的过程,

我的数学不是很好,如果谁发现有错误的地方,请底部留言。谢谢

 

阿飞

2021年10月17日

 

上一篇:2021-09-20


下一篇:CF1445E four points