天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 65|回复: 0

ObjectARX中矩阵AcGeMatrix3d的使用介绍

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
[code]平移
  平移有两个set矩阵的方法setTranslation()和setToTranslation(),试过后发现没有区别;

为了方便debug调试,写了个结构体来转换出矩阵行列值查看:

struct MatrixVector
{
        int nM11;
        int nM12;
        int nM13;
        int nM14;

        int nM21;
        int nM22;
        int nM23;
        int nM24;

        int nM31;
        int nM32;
        int nM33;
        int nM34;

        int nM41;
        int nM42;
        int nM43;
        int nM44;

        MatrixVector()
        {
                nM11 = 1;
                nM12 = 0;
                nM13 = 0;
                nM14 = 0;

                nM21 = 0;
                nM22 = 1;
                nM23 = 0;
                nM24 = 0;

                nM31 = 0;
                nM32 = 0;
                nM33 = 1;
                nM34 = 0;

                nM41 = 0;
                nM42 = 0;
                nM43 = 0;
                nM44 = 1;
        };
};

MatrixVector ConverMatrix(AcGeMatrix3d matxExp)
{
        MatrixVector stuMatrix;

        stuMatrix.nM11 = matxExp.entry[0][0];
        stuMatrix.nM12 = matxExp.entry[0][1];
        stuMatrix.nM13 = matxExp.entry[0][2];
        stuMatrix.nM14 = matxExp.entry[0][3];

        stuMatrix.nM21 = matxExp.entry[1][0];
        stuMatrix.nM22 = matxExp.entry[1][1];
        stuMatrix.nM23 = matxExp.entry[1][2];
        stuMatrix.nM24 = matxExp.entry[1][3];

        stuMatrix.nM31 = matxExp.entry[2][0];
        stuMatrix.nM32 = matxExp.entry[2][1];
        stuMatrix.nM33 = matxExp.entry[2][2];
        stuMatrix.nM34 = matxExp.entry[2][3];

        stuMatrix.nM41 = matxExp.entry[3][0];
        stuMatrix.nM42 = matxExp.entry[3][1];
        stuMatrix.nM43 = matxExp.entry[3][2];
        stuMatrix.nM44 = matxExp.entry[3][3];

        return stuMatrix;
    }
   
    AcGeMatrix3d ConverMatrixVector(MatrixVector stuMatrix)
    {
            AcGeMatrix3d matxExp;
            matxExp.entry[0][0] = stuMatrix.nM11;
            matxExp.entry[0][1] = stuMatrix.nM12;
            matxExp.entry[0][2] = stuMatrix.nM13;
            matxExp.entry[0][3] = stuMatrix.nM14;
   
            matxExp.entry[1][0] = stuMatrix.nM21;
            matxExp.entry[1][1] = stuMatrix.nM22;
            matxExp.entry[1][2] = stuMatrix.nM23;
            matxExp.entry[1][3] = stuMatrix.nM24;
                matxExp.entry[2][0] = stuMatrix.nM31;
                matxExp.entry[2][1] = stuMatrix.nM32;
                matxExp.entry[2][2] = stuMatrix.nM33;
                matxExp.entry[2][3] = stuMatrix.nM34;

                matxExp.entry[3][0] = stuMatrix.nM41;
                matxExp.entry[3][1] = stuMatrix.nM42;
                matxExp.entry[3][2] = stuMatrix.nM43;
                matxExp.entry[3][3] = stuMatrix.nM44;

                return matxExp;
}

下面是测试实例代码:

    AcGeMatrix3d matxTran; //平移矩阵
        AcGeMatrix3d matxScale;// 缩放矩阵
       
        AcGeMatrix3d matxRota;// 旋转矩阵
    matxRota.setToRotation(30,AcGeVector3d::kZAxis);
   
        MatrixVector stuMatrix;
        AcGePoint3d ptPos1 = AcGePoint3d(2,2,2);
        AcGePoint3d ptPos2 = AcGePoint3d(2,2,2);

        AcGeVector3d vecTran = AcGeVector3d(1,2,3);

        matxTran.setToTranslation(vecTran);
        stuMatrix = ConverMatrix(matxTran);
    //此时平移矩阵matxTran
        {
          1   0   0   1
          0   1   0   2
          0   0   1   3
          0   0   0   1
    }
   
        matxScale.setToScaling(3);
        stuMatrix = ConverMatrix(matxScale);
     //此时缩放矩阵matxScale
        {
           3   0   0   0
           0   3   0   0
           0   0   3   0
           0   0   0   1
    }
   
        ptPos1.transformBy(matxTran);
        ptPos1.transformBy(matxScale);

        //--------
        AcGeMatrix3d matrxTop = matxScale * matxTran; // 先平移再缩放矩阵
        ptPos2.transformBy(matrxTop);

        // 验证结果ptPos1和ptPos2是一样的等于(9,12,15);
       

        int nTrans = 3;
        AcGeMatrix3d matxExp1;
        AcGeMatrix3d matxExp2;
        matxExp2 = matxExp1.setTranslation(nTrans * AcGeVector3d::kZAxis);
        matxExp2 = matxExp1.setToTranslation(nTrans * AcGeVector3d::kZAxis);
        //两个函数效果一样,此时matxExp1和matxExp2的值是一样的,都是
        {
         1  0   0   0
         0  1   0   0
         0  0   1   3
         0  0   0   1
        }

实现不同方向X Y Z 上缩放比例不同的情况,例如 X方向缩放1倍,Y方向缩放2倍,Z方向缩放3倍:

    MatrixVector stuMatrix;
        stuMatrix.nM11 = 1;
        stuMatrix.nM22 = 2;
        stuMatrix.nM33 = 3;

        //X Y Z 方向缩放不同的矩阵
        AcGeMatrix3d matxScale = ConverMatrixVector(stuMatrix);

        AcGePoint3d ptPos1 = AcGePoint3d(2,2,2);

        ptPos1.transformBy(matxScale);
        ptPos1 = (2,4,6);

如何把矩阵转换成对应的位移、旋转角度和缩放比例?

AcGeMatrix3d tran = m_matrix;
CHCVec3d transLation;
CHCVec3d scale;
CHCVec4d rotate;
GetMatrixData(rotate,scale,transLation,tran);

bool GetMatrixData(CHCVec4d &rVec4d,CHCVec3d &scale3d,CHCVec3d &trans3d,::AcGeMatrix3d mat)
{
        //平移------
        trans3d.x = mat.entry[0][3];
        trans3d.y = mat.entry[1][3];
        trans3d.z = mat.entry[2][3];
        //----------------------------------------
        ::AcGeVector3d vec1(mat.entry[0][0],mat.entry[1][0],mat.entry[2][0]);
        ::AcGeVector3d vec2(mat.entry[0][1],mat.entry[1][1],mat.entry[2][1]);
        ::AcGeVector3d vec3(mat.entry[0][2],mat.entry[1][2],mat.entry[2][2]);

        //缩放---------------------------------------
        scale3d.x = vec1.length();
        scale3d.y = vec2.length();
        scale3d.z = vec3.length();
        //------------------------------------------------

        if (scale3d.x != 0)
        {
                vec1.x = vec1.x/scale3d.x;
                vec1.y = vec1.y/scale3d.x;
                vec1.z = vec1.z/scale3d.x;
        }

        if (scale3d.y != 0)
        {
                vec2.x = vec2.x/scale3d.y;
                vec2.y = vec2.y/scale3d.y;
                vec2.z = vec2.z/scale3d.y;
        }

        if (scale3d.z != 0)
        {
                vec3.x = vec3.x/scale3d.z;
                vec3.y = vec3.y/scale3d.z;
                vec3.z = vec3.z/scale3d.z;
        }

        //旋转-------------------------
        AcGeMatrix2d mat2d;  //旋转矩阵

        mat2d.entry[0][0] = vec1.x;
        mat2d.entry[1][0] = vec1.y;
        mat2d.entry[2][0] = vec1.z;

        mat2d.entry[0][1] = vec2.x;
        mat2d.entry[1][1] = vec2.y;
        mat2d.entry[2][1] = vec2.z;

        mat2d.entry[0][2] = vec3.x;
        mat2d.entry[1][2] = vec3.y;
        mat2d.entry[2][2] = vec3.z;
        //-------------------------------------------------
       
        rVec4d = FromRotationMatrix(mat2d);

        return true;
}
CHCVec4d FromRotationMatrix (const AcGeMatrix2d& kRot)
{
        CHCVec4d quaternion;
        // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
        // article "Quaternion Calculus and Fast Animation".

        double fTrace = kRot.entry[0][0]+kRot.entry[1][1]+kRot.entry[2][2];
        double fRoot = 0.0;

        if ( fTrace > 0.0 )
        {
                // |w| > 1/2, may as well choose w > 1/2
                fRoot = sqrt(fTrace + 1.0f);  // 2w
                quaternion.w = 0.5f*fRoot;
                fRoot = 0.5f/fRoot;  // 1/(4w)
                quaternion.x = (kRot.entry[2][1]-kRot.entry[1][2])*fRoot;
                quaternion.y = (kRot.entry[0][2]-kRot.entry[2][0])*fRoot;
                quaternion.z = (kRot.entry[1][0]-kRot.entry[0][1])*fRoot;
        }
        else
        {
                // |w| <= 1/2
                static size_t s_iNext[3] = { 1, 2, 0 };
                size_t i = 0;
                if ( kRot.entry[1][1] > kRot.entry[0][0] )
                        i = 1;
                if ( kRot.entry[2][2] > kRot.entry[i][i] )
                        i = 2;
                size_t j = s_iNext[i];
                size_t k = s_iNext[j];

                fRoot = sqrt(kRot.entry[i][i]-kRot.entry[j][j]-kRot.entry[k][k] + 1.0f);
                double* apkQuat[3] = { &quaternion.x, &quaternion.y, &quaternion.z };
                *apkQuat[i] = 0.5f*fRoot;
                fRoot = 0.5f/fRoot;
                quaternion.w = (kRot.entry[k][j]-kRot.entry[j][k])*fRoot;
                *apkQuat[j] = (kRot.entry[j][i]+kRot.entry[i][j])*fRoot;
                *apkQuat[k] = (kRot.entry[k][i]+kRot.entry[i][k])*fRoot;
        }

        return quaternion;
}


3、世界坐标变换要先缩放、后旋转、再平移的原因
  一个三维场景中的各个模型一般需要各自建模,再通过坐标变换放到一个统一的世界空间的指定位置上。 这个过程在 3D 图形学中称作“世界变换” 。 世界变换有三种,平移、旋转和缩放 (实际还有不常用的扭曲和镜像,它们不是affine变换)。 这三种变换按各种顺序执行,结果是不同的。 可是实际的应用中一般按照 缩放 -> 旋转 -> 平移的顺序进行。 这样做的原因是可以获得最符合常理的变换结果。

比方说,通过世界变换希望获得的结果可能是:

将一个放在原点的物体(比方说可乐罐)移动到(30,50),让它自身倾斜 45 度,
再放大 2 倍。
1
2
而不希望的结果是:
1.和本地坐标轴成角度的缩放(会导致扭曲,像踩扁的可乐罐)。
2.绕自己几何中心以外位置的原点的旋转 (地球公转式) 和缩放。

而颠倒了上述变换顺序就会得到这样不自然的结果。
具体的说:
当缩放在旋转之后进行时,会发生现象1。
当缩放和旋转在平移之后进行时会发生现象2。

这是因为:在物体刚刚放入世界坐标系的时候使用的是本地坐标,也就是本地和全局坐标系的原点和坐标轴都是重合的(当然两者分别使用了左右手坐标系时除外 - 那是BUG),此时所有物体都“把世界坐标系当做自己的本地坐标系”。
而经过了坐标变换之后:
1.缩放变换不改变坐标轴的走向,也不改变原点的位置,所以两个坐标系仍然重合。
2.旋转变换改变坐标轴的走向,但不改变原点的位置,所以两个坐标系坐标轴不再处于相同走向。
3.平移变换不改变坐标轴走向,但改变原点位置,两个坐标系原点不再重合。
这样就可以解释问什么缩放不能在旋转之后,而缩放和旋转都不能在平移之后了。 于是没有问题的顺序只能是 缩放 -> 旋转 -> 平移 。
  
原文链接:https://blog.csdn.net/m0_37251750/article/details/99674702[/code]

 

 

 

 

ObjectARX中矩阵AcGeMatrix3d的使用介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 09:33 , Processed in 0.119643 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表