• Eigen 由三点求平面方程及平面法向量


    Eigen 由三点求平面方程及平面法向量

    一、原理

      已知三点 P 1 ( x 1 , y 1 , z 1 ) P1(x_1,y_1,z_1) P1(x1,y1,z1) P 2 ( x 2 , y 2 , z 2 ) P2(x_2,y_2,z_2) P2(x2,y2,z2) P 3 ( x 2 , y 2 , z 2 ) P3(x_2,y_2,z_2) P3(x2,y2,z2),要求该三点所确定的平面方程及法向量。我们知道两点共线,三点一定共面,平面的法向量一定垂直于平面中任意两点之间的连线。所以求解的思路就是找到一个向量 n n n与平面的两条不平行的直线垂直即可,即计算 n n n与平面中两个向量的叉乘。
      做平面中的两个向量 V 1 = P 1 P 2 = ( x 2 − x 1 , y 2 − y 1 , z 2 − z 1 ) V_1=P_1P_2=(x_2-x_1,y_2-y_1,z_2-z_1) V1=P1P2=(x2x1,y2y1,z2z1) V 2 = P 1 P 3 = ( x 3 − x 1 , y 3 − y 1 , z 3 − z 1 ) V_2=P_1P_3=(x_3-x_1,y_3-y_1,z_3-z_1) V2=P1P3=(x3x1,y3y1,z3z1),平面法向量和这两个向量都垂直,因此法向量 n n n:
    n = V 1 × V 2 = ∣ i j k x 2 − x 1 y 2 − y 1 z 2 − z 1 x 3 − x 1 y 3 − y 1 z 3 − z 1 ∣ = a i + b j + c k = ( a , b , c ) n=V_1 \times V_2 = \left| ijkx2x1y2y1z2z1x3x1y3y1z3z1

    \right|=ai+bj+ck=(a,b,c) n=V1×V2= ix2x1x3x1jy2y1y3y1kz2z1z3z1 =ai+bj+ck=(a,b,c)
    其中:
    a = ( y 2 − y 1 ) ∗ ( z 3 − z 1 ) − ( y 3 − y 1 ) ∗ ( z 2 − z 1 ) b = ( z 2 − z 1 ) ∗ ( x 3 − x 1 ) − ( z 3 − z 1 ) ∗ ( x 2 − x 1 ) c = ( x 2 − x 1 ) ∗ ( y 3 − y 1 ) − ( x 3 − x 1 ) ∗ ( y 2 − y 1 ) a=(y_2-y_1)*(z_3-z_1)-(y_3-y_1)*(z_2-z_1)\\ b=(z_2-z_1)*(x_3-x_1)-(z_3-z_1)*(x_2-x_1)\\ c=(x_2-x_1)*(y_3-y_1)-(x_3-x_1)*(y_2-y_1) a=(y2y1)(z3z1)(y3y1)(z2z1)b=(z2z1)(x3x1)(z3z1)(x2x1)c=(x2x1)(y3y1)(x3x1)(y2y1)

    平面方程为: a ( x − x 1 ) + b ( y − y 1 ) + c ( z − z 1 ) = 0 a(x-x_1)+b(y-y_1)+c(z-z_1)=0 a(xx1)+b(yy1)+c(zz1)=0,所以 d = − a ∗ x 1 − b ∗ y 1 − c ∗ z 1 d=-a*x_1-b*y_1-c*z_1 d=ax1by1cz1,平面方程为:
    a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0

    二、Eigen实现

    void getNormalBy3Points(
        const Eigen::Vector3d &P1,
        const Eigen::Vector3d &P2,
        const Eigen::Vector3d &P3,
              Eigen::Vector3d &normal)
    {
        Eigen::Vector3d V1=P1-P2;
        Eigen::Vector3d V2=P1-P3;
        normal=V1.cross(V2);
    }
    void getPlaneBy3Points(
        const Eigen::Vector3d &P1,
        const Eigen::Vector3d &P2,
        const Eigen::Vector3d &P3,
              Eigen::Vector4d &plane_coeff)
    {
        Eigen::Vector3d V1=P1-P2;
        Eigen::Vector3d V2=P1-P3;
        Eigen::Vector3d normal;
        normal=V1.cross(V2);
        plane_coeff.block<3,1>(0,0)=normal;
        plane_coeff(3)=-plane_coeff(0)*P1(0)-plane_coeff(1)*P1(1)-plane_coeff(2)*P1(2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    主函数代码如下:

    Eigen::Vector3d P1(0,0,0);
    Eigen::Vector3d P2(1,0,0);
    Eigen::Vector3d P3(0,1,0);
    
    Eigen::Vector3d normal;
    Eigen::Vector4d plane_coeff;
    
    getNormalBy3Points(P1,P2,P3,normal);
    getPlaneBy3Points(P1,P2,P3,plane_coeff);
    
    std::cout<<normal.transpose()<<std::endl;
    std::cout<<plane_coeff.transpose()<<std::endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出如下:

    0 0 1
    0  0  1 -0
    
    • 1
    • 2

    最好用别的数据测试一下,这个测试数据太简单了。

  • 相关阅读:
    linux docker常用命令记录
    centos7搭建maven私服nexus
    Java之使用递归查询多级树形结构数据
    Qt 6 资料汇总
    python小项目之利用pygame实现代码雨动画效果(附源码 可供学习)
    文献学习01_Attention Is All You Need_20221119
    在 GeoServer 上发布 Shapefile 文件作为 WMS 数据
    深入剖析Java框架源码的设计之重载与重写、构造方法的区别详解
    作用域安全的构造函数
    【SLAM】坐标系变换与外参标定
  • 原文地址:https://blog.csdn.net/qq_39400324/article/details/126835006