ゲームプログラミング技術集 
ひっと

平面上の最近点を求める方法

内積を使って平面上の最近点を求める方法とプログラミング例。

平面上の最近点を求める

平面上の最近点は、内積で求めることができます。
任意の点Aがあり、平面上の点Pと平面の法線ベクトルをNとすると...

平面上の最近点 = A - N * ( PA ・ N )
平面方程式(ax+by+cz+d=0)を使う場合は..
法線N = (a,b,c)
平面上の点P = (a*d, b*d, c*d)
と置き換えると同様に計算できます。

平面上の最近点を求める プログラミング例

点+法線バージョンと、平面方程式バージョンがあります。平面の定義によって使い分けてください。
#include <math.h>

//3Dベクトル
struct Vector3D{
    double x,y,z;
};

//3D頂点 (ベクトルと同じ)
#define Vertex3D Vector3D

//平面    ( ax+by+cz+d=0 )	// ※平面方程式の作成方法はこちら...
struct Plane {
    double a,b,c,d;
};

//ベクトル内積
double dot_product( const Vector3D& vl, const Vector3D vr) {
    return vl.x * vr.x + vl.y * vr.y + vl.z * vr.z;
}

//平面上の最近点を求める その1( P=平面上の点 N=平面の法線 )
Vertex3D NearPosOnPlane( const Vertex3D& A, const Vertex3D& P, const Vertex3D& N )
{
    //PAベクトル(A-P)
    Vector3D PA;
    PA.x = A.x - P.x;
    PA.y = A.y - P.y;
    PA.z = A.z - P.z;
    
    //法線NとPAを内積
    //法線の順方向に点Aがあればd > 0、 逆方向だとd < 0
    double d = dot_product( N, PA );

    //内積値から平面上の最近点を求める
    Vertex3D ret;
    ret.x = A.x - ( N.x * d );
    ret.y = A.y - ( N.y * d );
    ret.z = A.z - ( N.z * d );

    return ret;
}

//平面上の最近点を求める その2(平面方程式 ax+by+cz+d=0 を使う場合 )
Vertex3D NearPosOnPlane2( const Vertex3D& A, const Plane& plane )
{
    //平面方程式から法線と平面上の点を求める

    //平面の法線N( ax+by+cz+d=0 のとき、abcは法線ベクトルで単位ベクトルです )
    Vector3D N;
    N.x = plane.a;
    N.y = plane.b;
    N.z = plane.c;

    //平面上の任意の点P (法線*dは平面上の点)
    Vector3D P;
    P.x = plane.a * plane.d;
    P.y = plane.b * plane.d;
    P.z = plane.c * plane.d;

    return NearPosOnPlane( A,P, N );

}
戻る     次へ