利用四元树来计算一个坐标点绕任意轴旋转后,新坐标点的推导过程

本文深入探讨了利用四元树进行坐标点绕任意轴旋转的计算过程,并通过OSG库中的实现代码展示了从四元树到旋转矩阵及矩阵到四元树的转换方法。同时,详细介绍了如何将矩阵转换为四元树,以及从四元树转换回矩阵的流程。

 利用四元树来计算一个坐标点绕任意轴旋转后,新坐标点的推导过程(参考《(中文版)3D数学基础图形与游戏开发.pdf》):

 

 

参考源代码:

void Quaternion::setToRotateAboutAxis(const Vector3 &axis, float theta)

{

// The axis of rotation must be normalized

assert(fabs(vectorMag(axis) – 1.0f) < .01f);

// Compute the half angle and its sin

float thetaOver2 = theta * .5f;

float sinThetaOver2 = sin(thetaOver2);

// Set the values

w = cos(thetaOver2);

x = axis.x * sinThetaOver2;

y = axis.y * sinThetaOver2;

z = axis.z * sinThetaOver2;

}

 

最终的R(n, θ)矩阵为:

――――――

OSG中将四元树转换为矩阵(Matrix_implementation.cpp):

#define QX  q._v[0]

#define QY  q._v[1]

#define QZ  q._v[2]

#define QW  q._v[3]

void Matrix_implementation::setRotate(const Quat& q)

{

double length2 = q.length2();

。。。。。。

rlength2 = 2.0/length2;

 

x2 = rlength2*QX;

        y2 = rlength2*QY;

        z2 = rlength2*QZ;

       

        xx = QX * x2;

        xy = QX * y2;

        xz = QX * z2;        

yy = QY * y2;

        yz = QY * z2;

        zz = QZ * z2;

       

        wx = QW * x2;

        wy = QW * y2;

        wz = QW * z2;

_mat[0][0] = 1.0 - (yy + zz);

        _mat[1][0] = xy - wz;

        _mat[2][0] = xz + wy;       

       

        _mat[0][1] = xy + wz;

        _mat[1][1] = 1.0 - (xx + zz);

        _mat[2][1] = yz - wx;

        

        _mat[0][2] = xz - wy;

        _mat[1][2] = yz + wx;

        _mat[2][2] = 1.0 - (xx + yy);

}

――――――

3.从矩阵转换到四元树:

OSG中将矩阵转换为四元树(Matrix_implementation.cpp):

#define QX  q._v[0]

#define QY  q._v[1]

#define QZ  q._v[2]

#define QW  q._v[3]

Quat Matrix_implementation::getRotate() const

{

    Quat q;

    value_type s;

    value_type tq[4];

    int    i, j;

    // Use tq to store the largest trace

    tq[0] = 1 + _mat[0][0]+_mat[1][1]+_mat[2][2];

    tq[1] = 1 + _mat[0][0]-_mat[1][1]-_mat[2][2];

    tq[2] = 1 - _mat[0][0]+_mat[1][1]-_mat[2][2];

    tq[3] = 1 - _mat[0][0]-_mat[1][1]+_mat[2][2];

 

    // 找4个中最大的

    j = 0;

    for(i=1;i<4;i++) j = (tq[i]>tq[j])? i : j;

 

    // check the diagonal

    if (j==0)

    {

        /* perform instant calculation */

        QW = tq[0];

        QX = _mat[1][2]-_mat[2][1];

        QY = _mat[2][0]-_mat[0][2];

        QZ = _mat[0][1]-_mat[1][0];

    }

    else if (j==1)

    {

        QW = _mat[1][2]-_mat[2][1];

        QX = tq[1];

        QY = _mat[0][1]+_mat[1][0];

        QZ = _mat[2][0]+_mat[0][2];

    }

    else if (j==2)

    {

        QW = _mat[2][0]-_mat[0][2];

        QX = _mat[0][1]+_mat[1][0];

        QY = tq[2];

        QZ = _mat[1][2]+_mat[2][1];

    }

    else /* if (j==3) */

    {

        QW = _mat[0][1]-_mat[1][0];

        QX = _mat[2][0]+_mat[0][2];

        QY = _mat[1][2]+_mat[2][1];

        QZ = tq[3];

    }

 

    s = sqrt(0.25/tq[j]);

    QW *= s;

    QX *= s;

    QY *= s;

    QZ *= s;

 

    return q;

}

public void Polygon_Trans4(IFeatureClass pFeatureCls, string strPath, string strFilename, ProgressBar pBar) { if (pFeatureCls == null || strPath == "" || strFilename == "") return; createNewShape(strPath, strFilename, pFeatureCls); IFeatureCursor pFeatCursor = pFeatureCls.Search(null, false); IFeature pFeature = pFeatCursor.NextFeature(); //打开目标图层 IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass(); IWorkspace pWS = pWSF.OpenFromFile(strPath, 0); IFeatureWorkspace pFWS = (IFeatureWorkspace)pWS; IFeatureClass pTargetFClass = pFWS.OpenFeatureClass(strFilename); IWorkspaceEdit pWSEdit = pWS as IWorkspaceEdit; pWSEdit.StartEditOperation(); pWSEdit.StartEditing(false); ITable pTble = (ITable)pFeatureCls; int lCunt = pTble.RowCount(null); pBar.Visible = true; pBar.Minimum = 0; pBar.Maximum = lCunt; pBar.Step = 1; IFeature pNewFeature; IPolygon pOutPolygon; IGeometryCollection pOutGeos; IPolygon pInPolygon; IGeometryCollection pInGeos; IPoint pOutPnt = new PointClass(); IPointCollection pOutPnts; while (pFeature != null) { pBar.PerformStep(); pNewFeature = pTargetFClass.CreateFeature(); pOutPolygon = new PolygonClass(); pOutGeos = pOutPolygon as IGeometryCollection; //获取原图形 pInPolygon = pFeature.Shape as IPolygon; pInGeos = pInPolygon as IGeometryCollection; for (int m = 0; m < pInGeos.GeometryCount; m++) { IGeometry pInGeo = pInGeos.get_Geometry(m); IPointCollection pInPnts = pInGeo as IPointCollection; pOutPnts = new PolygonClass(); object missing = Type.Missing; for (int n = 0; n < pInPnts.PointCount; n++) { IPoint pInPnt = pInPnts.get_Point(n); //转换点坐标 pOutPnt.X = ClsParas4.m_OffY + pInPnt.Y * ClsParas4.m_vb + pInPnt.X * ClsParas4.m_va; pOutPnt.Y = ClsParas4.m_OffX + pInPnt.Y * ClsParas4.m_va - pInPnt.X * ClsParas4.m_vb; pOutPnts.AddPoint(pOutPnt, ref missing, ref missing); } ISegmentCollection pSegmentCols = new RingClass(); pSegmentCols.AddSegmentCollection(pOutPnts as ISegmentCollection); pOutGeos.AddGeometry(pSegmentCols as IGeometry, ref missing, ref missing); } for (int i = 0; i < pFeature.Fields.FieldCount; i++) { if (pNewFeature.Fields.get_Field(i).Name.ToString().Equals("FID", StringComparison.CurrentCultureIgnoreCase) || pNewFeature.Fields.get_Field(i).Name.ToString().Equals("SHAPE", StringComparison.CurrentCultureIgnoreCase)) continue; pNewFeature.set_Value(i, pFeature.get_Value(i)); } pNewFeature.Shape = pOutPolygon as IGeometry; pNewFeature.Store(); pFeature = pFeatCursor.NextFeature(); } pBar.Visible = false; pWSEdit.StopEditOperation(); pWSEdit.StopEditing(true); }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值