1 三维平面的法向的概念

三维平面的法线,又称为三维平面的法向量,指的是垂直于该平面的三维向量。

三维平面的法向量不具有唯一性,在相反方向的法线也是平面的法线。

根据曲面边界,将指向曲面内部的法线称为inward-pointing normal,指向曲面外部的法线称为outer-pointing normal,一般来讲,会选择outer-pointing normal作为曲面的法线,确定曲面的法向可以通过右手法则。

计算几何 –  求解三维平面法向量-StubbornHuang Blog

可以通过右手定则确定叉积的方向,如下图所示

计算几何 –  求解三维平面法向量-StubbornHuang Blog

2 求解三维平面的法向量

一般来说,三点可以确定一个平面,所以以下代码以三个点作为输入,先通过三个点求解平面的两个三维向量,然后在通过两个向量的叉积求解平面法向量。

#include <iostream>

struct Point3f
{
    float x;
    float y;
    float z;

    Point3f()
    {
        x = 0.0;
        y = 0.0;
        z = 0.0;
    }

    Point3f(float x_in, float y_in, float z_in)
    {
        x = x_in;
        y = y_in;
        z = z_in;
    }
};

typedef Point3f Vector3f;

// 计算两个三维向量的叉积
Vector3f CrossProduct(Vector3f u, Vector3f v) {
    Vector3f result;
    result.x = u.y * v.z - v.y * u.z;
    result.y = u.z * v.x - u.x * v.z;
    result.z = u.x * v.y - u.y * v.x;
    return result;
}

// 计算两个三维向量的差
Vector3f Sub(Vector3f u, Vector3f v)
{
    Vector3f result;
    result.x = u.x - v.x;
    result.y = u.y - v.y;
    result.z = u.z - v.z;
    return result;
}

// 计算三维平面法向
Vector3f CalculPlaneNormal(Point3f p1, Point3f p2, Point3f p3)
{
    return CrossProduct(Sub(p1, p2), Sub(p2, p3));
}

int main()
{
    Point3f point_a(1.0, 2.0, 3.0);
    Point3f point_b(4.0, 5.0, 6.0);
    Point3f point_c(4.0, 8.0, 9.0);

    Vector3f plane_normal = CalculPlaneNormal(point_a, point_b, point_c);

    std::cout << "plane normal = " << plane_normal.x << " " << plane_normal.y << " " << plane_normal.z << std::endl;

    return 0;
}