gp_Dir描述了三维空间中的一个单位向量。
gp_Dir的定义。
class gp_Dir
{
public:
...
private:
gp_XYZ coord;
};
默认情况下,位置为原点,方向为x轴方向。
inline gp_Dir::gp_Dir () : coord(1.,0.,0.)
{
}
gp_Dir 是一个单位向量,因此构造函数接收参数时,需要归一化。同时,零向量不能形成方向向量。
inline gp_Dir::gp_Dir (const gp_XYZ& XYZ)
{
Standard_Real X = XYZ.X();
Standard_Real Y = XYZ.Y();
Standard_Real Z = XYZ.Z();
Standard_Real D = sqrt(X * X + Y * Y + Z * Z);
Standard_ConstructionError_Raise_if (D <= gp::Resolution(), "gp_Dir() - input vector has zero norm");
coord.SetX(X / D);
coord.SetY(Y / D);
coord.SetZ(Z / D);
}
x,y,z任一分量改变时,都需要重新归一化。如改变x分量时:
inline void gp_Dir::SetX (const Standard_Real X)
{
Standard_Real Y = coord.Y();
Standard_Real Z = coord.Z();
Standard_Real D = sqrt (X * X + Y * Y + Z * Z);
Standard_ConstructionError_Raise_if (D <= gp::Resolution(), "gp_Dir::SetX() - result vector has zero norm");
coord.SetX(X / D);
coord.SetY(Y / D);
coord.SetZ(Z / D);
}
方向的相等判断:夹角为0度。
inline Standard_Boolean gp_Dir::IsEqual(const gp_Dir& Other, const Standard_Real AngularTolerance) const
{
return Angle (Other) <= AngularTolerance;
}
垂直判断:方向的夹角为90度。
inline Standard_Boolean gp_Dir::IsNormal(const gp_Dir& Other,const Standard_Real AngularTolerance) const
{
Standard_Real Ang = M_PI / 2.0 - Angle (Other);
if (Ang < 0) Ang = - Ang;
return Ang <= AngularTolerance;
}
平行判断:方向的夹角为0度或180度。
inline Standard_Boolean gp_Dir::IsParallel(const gp_Dir& Other, const Standard_Real AngularTolerance) const
{
Standard_Real Ang = Angle (Other);
return Ang <= AngularTolerance || M_PI - Ang <= AngularTolerance;
}
相反判断:方向的夹角为180度。
inline Standard_Boolean gp_Dir::IsOpposite(const gp_Dir& Other,const Standard_Real AngularTolerance) const
{
return M_PI - Angle (Other) <= AngularTolerance;
}
方向的夹角,范围是[0, 180]。注意在一定的范围内,arccos提供最佳的计算精度,否则arcsin提供最佳的计算精度。
Standard_Real gp_Dir::Angle (const gp_Dir& Other) const
{
Standard_Real Cosinus = coord.Dot (Other.coord);
if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
return acos (Cosinus);
else {
Standard_Real Sinus = (coord.Crossed (Other.coord)).Modulus ();
if(Cosinus < 0.0)
return M_PI - asin (Sinus);
else
return asin (Sinus);
}
}
方向的夹角,范围是[-180, 180]。注意Vref定义了正方向,当两个方向的叉积与Vref的方向相同时,角度为正,否则角度为负。
Standard_Real gp_Dir::AngleWithRef (const gp_Dir& Other,const gp_Dir& Vref) const
{
Standard_Real Ang;
gp_XYZ XYZ = coord.Crossed (Other.coord);
Standard_Real Cosinus = coord.Dot(Other.coord);
Standard_Real Sinus = XYZ.Modulus ();
if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
Ang = acos (Cosinus);
else {
if(Cosinus < 0.0)
Ang = M_PI - asin (Sinus);
else
Ang = asin (Sinus);
}
if (XYZ.Dot (Vref.coord) >= 0.0)
return Ang;
else
return -Ang;
}
方向的叉积。返回值是单位向量,注意当两个方向平行时,无法计算叉积。
inline void gp_Dir::Cross (const gp_Dir& Right)
{
coord.Cross (Right.coord);
Standard_Real D = coord.Modulus ();
Standard_ConstructionError_Raise_if (D <= gp::Resolution(), "gp_Dir::Cross() - result vector has zero norm");
coord.Divide (D);
}
方向的镜像。对方向做对称变换,V是对称变换的中心。
void gp_Dir::Mirror (const gp_Dir& V)
{
const gp_XYZ& XYZ = V.coord;
Standard_Real A = XYZ.X();
Standard_Real B = XYZ.Y();
Standard_Real C = XYZ.Z();
Standard_Real X = coord.X();
Standard_Real Y = coord.Y();
Standard_Real Z = coord.Z();
Standard_Real M1 = 2.0 * A * B;
Standard_Real M2 = 2.0 * A * C;
Standard_Real M3 = 2.0 * B * C;
Standard_Real XX = ((2.0 * A * A) - 1.0) * X + M1 * Y + M2 * Z;
Standard_Real YY = M1 * X + ((2.0 * B * B) - 1.0) * Y + M3 * Z;
Standard_Real ZZ = M2 * X + M3 * Y + ((2.0 * C * C) - 1.0) * Z;
coord.SetCoord(XX,YY,ZZ);
}
参数是gp_Ax2坐标系统时,镜像后需要取反。
void gp_Dir::Mirror (const gp_Ax2& A2)
{
const gp_Dir& Vz = A2.Direction();
Mirror(Vz);
Reverse();
}
方向的旋转,A1是旋转轴,Ang是旋转角度。
inline void gp_Dir::Rotate (const gp_Ax1& A1, const Standard_Real Ang)
{
gp_Trsf T;
T.SetRotation (A1, Ang);
coord.Multiply (T.HVectorialPart ());
}
方向的变换。
void gp_Dir::Transform (const gp_Trsf& T)
{
if (T.Form() == gp_Identity || T.Form() == gp_Translation)
{
}
else if (T.Form() == gp_PntMirror) //中心对称
{
coord.Reverse();
}
else if (T.Form() == gp_Scale) //缩放
{
if (T.ScaleFactor() < 0.0)
{
coord.Reverse();
}
}
else
{
coord.Multiply (T.HVectorialPart());
Standard_Real D = coord.Modulus();
coord.Divide(D);
if (T.ScaleFactor() < 0.0)
{
coord.Reverse();
}
}
}