ObjectARX中矩阵AcGeMatrix3d的使用介绍

1、介绍

  先介绍一下AcGeMatrix3d这个类,常见的点一般是Pt(X,Y,Z),相当于一个1×3矩阵,而矩阵相乘的话一般是第一个矩阵的列数要等于第二个矩阵的行数,所以我一开始天真的认为AcGeMatrix3d是个3×3矩阵,然而看过类介绍后没有发现矩阵相加减这种情况,纳闷平移是怎么用乘法实现的,原来用齐次坐标的概念如下:https://wenku.baidu.com/view/4b0324eae009581b6bd9eb40.html?from=search
在这里插入图片描述

在这里插入图片描述

2、使用例子

  简单说一下三种比较常用的:平移、缩放、旋转;

2.1 平移
  平移有两个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;
}

发布了58 篇原创文章 · 获赞 42 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/m0_37251750/article/details/99674702