如下图,已知 A、B、C 三个点,求 B 点的 法向量,即(fCosSita, fSinSita),Sita 为 法线按逆时针方向和水平方向的夹角。
先计算线段AB的单位垂线段2,再计算线段BC 的单位垂线段1,最后对 1 和 2 求和,得到3,即为 B 点的法线。
代码如下:
void CalcNormVec(POINT& ptA, POINT& ptB, POINT& ptC, float* pfCosSita, float* pfSinSita)
{
//先用B点坐标减A点坐标。
float fVec1_x = ptB.x - ptA.x;
float fVec1_y = ptB.y - ptA.y;
//单位化。
float fMod = sqrt(fVec1_x * fVec1_x + fVec1_y * fVec1_y);
fVec1_x /= fMod;
fVec1_y /= fMod;
//计算垂线。
float fPerpendicularVec1_x = -fVec1_y;
float fPerpendicularVec1_y = fVec1_x;
//再用C点坐标减B点坐标。
float fVec2_x = ptC.x - ptB.x;
float fVec2_y = ptC.y - ptB.y;
//单位化。
fMod = sqrt(fVec2_x * fVec2_x + fVec2_y * fVec2_y);
fVec2_x /= fMod;
fVec2_y /= fMod;
//计算垂线。
float fPerpendicularVec2_x = -fVec2_y;
float fPerpendicularVec2_y = fVec2_x;
//求和。
float fSumX = fPerpendicularVec1_x + fPerpendicularVec2_x;
float fSumY = fPerpendicularVec1_y + fPerpendicularVec2_y;
//单位化。
fMod = sqrt(fSumX * fSumX + fSumY * fSumY);
float fCosSita = fSumX / fMod;
float fSinSita = fSumY / fMod;
if (pfCosSita)
*pfCosSita = fCosSita;
if (pfSinSita)
*pfSinSita = fSinSita;
return;
}