矩陣類模板

        這是我在做遊戲三維圖形處理中編制的一個矩陣類模板,可以產生整型,浮點,和自定義類型的任意階矩陣和行列式,並且定義了一些常用的三維向量運算函數模板,希望大家給出修改意見。建議大家只看函數生命,不要看具體實現,因爲貼上來之後格式不對頭,由於文件比較長,我將其分爲兩個帖子

                                                  矩陣類模板

//***************************************************************************/
//聲明:                                                                    */
//                                                                          */
//這個版本純粹是處於個人愛好而編寫,其中可能有不少錯誤。主要是爲了讓各位愛好*/
//者相互交流共同提高編程水平。因此,你可以任意修改複製其中的代碼,並可以應用*/
//於任何場合,但由此帶來的問題本人不負任何責任。如果你有什麼建議的話,歡迎與*/
//我聯繫,我們共同探討。                                                    */
//我的郵箱是:[email protected]                                          */
//***************************************************************************/
//                                                                          */
//Matrix.h                                                                  */
//本文件定義了基本的矩陣模板,可以由此複製出各種int,float,double等          */
//等各種類型的矩陣類型。重載了基本的矩陣運算符。爲了滿足矢量處理的          */
//要求,定義了一系列座標變換函數                                            */
//                                                                          */
//                                                                          */
//***************************************************************************/
//版本升級說明:原來的版本中矩陣這一單一類型可以滿足一般的需要,但是當在結構*/
//沒有默認的構造函數,而且在編寫座標變換函數模板時非常不方便,且無法定義各種*/
//常用的特殊矢量。歸根結蒂是因爲原來的模板中只有一個矩陣內數據類型的參數。在*/
//這個版本中將模板參數擴展爲3個,有兩個是矩陣的行和列,取消了構造時的init參 */
//數,統一初始化爲0。這樣矩陣就有了默認的構造函數,且模板參數中有足夠的信息 */
//有效的解決了上面提出的問題。                                              */
//***************************************************************************/
//編寫人:王雲                                                              */
//修改人:王雲
//開始時間:2002.10.18                                                      */
//結束時間:2002.10.19                                                      */
//***************************************************************************/
#include<windows.h>
#include<iostream.h>
#include<math.h>
template<typename ElemType,int r,int c> class Matrix;
//***************************************************************************/
//二維向量和點                                                              */
//***************************************************************************/
typedef Matrix<int,1,2>      Vector2i;
typedef Matrix<int,1,2>      Vertex2i;
typedef Matrix<float,1,2>    Vector2f;
typedef Matrix<float,1,2>    Vertex2f;
typedef Matrix<double,1,2>   Vector2d;
typedef Matrix<double,1,2>   Vertex2d;
//***************************************************************************/
//三維向量和點                                                              */
//***************************************************************************/
typedef Matrix<int,1,3>      Vector3i;
typedef Matrix<int,1,3>      Vertex3i;
typedef Matrix<float,1,3>    Vector3f;
typedef Matrix<float,1,3>    Vertex3f;
typedef Matrix<double,1,3>   Vector3d;
typedef Matrix<double,1,3>   Vertex3d;
//***************************************************************************/
//四維齊次座標和向量                                                        */
//***************************************************************************/
typedef Matrix<int,1,4>      Vector4i;
typedef Matrix<int,1,4>      Vertex4i;
typedef Matrix<float,1,4>    Vector4f;
typedef Matrix<float,1,4>    Vertex4f;
typedef Matrix<double,1,4>   Vector4d;
typedef Matrix<double,1,4>   Vertex4d;
//***************************************************************************/
//常用的向量運算函數模板定義                                                */
//***************************************************************************/
/*
template<typename ElemType,int r,int c>                    //向量在各個局部座標軸上的分量
int VectorProjection(Matrix<ElemType,r,c>& vector,Matrix<ElemType,r,c>*pVectorX,Matrix<ElemType,r,c>*pVectorY,Matrix<ElemType,r,c>* pVectorZ);
*/
template<typename ElemType,int r,int c>                    //計算向量的模
ElemType VectorMo(Matrix<ElemType,r,c>& vector);
template<typename ElemType,int r,int c>                    //向量單位化
Matrix<ElemType,r,c> VectorUnit(Matrix<ElemType,r,c>& vector);
template<typename ElemType,int r,int c>                    //繞x軸旋轉
Matrix<ElemType,r,c> RotateOX(Matrix<ElemType,r,c>& vector,float beta);
template<typename ElemType,int r,int c>                    //繞x軸旋轉
Matrix<ElemType,r,c> RotateOY(Matrix<ElemType,r,c>& vector,float beta);
template<typename ElemType,int r,int c>                    //繞y軸旋轉
Matrix<ElemType,r,c> RotateOZ(Matrix<ElemType,r,c>& vector,float beta);
template<typename ElemType,int r,int c>                    //繞z軸旋轉
Matrix<ElemType,r,c>  RotateON(Matrix<ElemType,r,c>& reel,Matrix<ElemType,r,c>& vector,float beta);
template<typename ElemType,int r,int c>                    //繞任意軸旋轉
Matrix<ElemType,r,c> VectorProduct(Matrix<ElemType,r,c>& va,Matrix<ElemType,r,c>& vb);             //向量積
template<typename ElemType,int r,int c>                    //座標的變換
int CoordinateTransfer(Matrix<ElemType,r,c>& origin,Matrix<ElemType,r,c>& xDirect,Matrix<ElemType,r,c>& yDirect,Matrix<ElemType,r,c>& zDirect,
        Matrix<ElemType,r,c>*& pVertex,int nVertex);    
template<typename ElemType,int r,int c>                     //兩個向量的夾角
int VectorAngle(Matrix<ElemType,r,c>& b,Matrix<ElemType,r,c>& a,float* sin,float* cos);
//***************************************************************************/
//矩陣類模板的定義                                                          */
//                                                                          */
//                                                                          */
//***************************************************************************/
template<typename ElemType,int r,int c> class Matrix
{
private:
 int row;                                               //行
 int col;                                               //列
 ElemType* pElemType;                                   //存儲矩陣數據的類型數組

public:
 Matrix();
 Matrix(const Matrix<ElemType,r,c>&A);                  //深度堆拷貝函數必須在所有的運算函數之
                                                        //前定義,否則其它函數的返回給參數傳遞
                                                        //將採用默認的拷貝構造函數,從而得到錯
                                                        //誤的結果
 ~Matrix();

public:
 inline int GetRow() {return row;}
 inline int GetCol() {return col;}

    inline ElemType& operator ()(const int& i,const int& j) {return pElemType[(i-1)*row+j-1];}
 Matrix<ElemType,r,c>& operator = (const Matrix<ElemType,r,c>&A);

 friend Matrix<ElemType,r,c> operator + (const Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);
 friend Matrix<ElemType,r,c> operator - (const Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);
 friend Matrix<ElemType,r,c> operator * (const Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);

                                                        //下面這三個函數是針對常數和矩陣的乘法而
                                                        //定義的,顯然,冗餘非常大,未來的目標是
                                                        //在內部定一個函數模板,來自動匹配類型
    friend Matrix<ElemType,r,c> operator * (const double& scale,const Matrix<ElemType,r,c>& B);
 friend Matrix<ElemType,r,c> operator * (const float& scale,const Matrix<ElemType,r,c>& B);
 friend Matrix<ElemType,r,c> operator * (const int& scale,const Matrix<ElemType,r,c>& B);
   
                                                           //+=操作符之所以要返回對A的常量引用,
                                                        //是爲了能夠使用連等式,即C=A=D+E ,同
                                                        //時,返回值不能作爲左值
 friend const Matrix<ElemType,r,c>& operator +=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);
 friend const Matrix<ElemType,r,c>& operator -=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);
 friend const Matrix<ElemType,r,c>& operator *=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B);

                                                           //下面兩個操作符的重載主要是爲了字符界
                                                        //面下的使用和測試
 friend istream& operator >> (istream& in,Matrix<ElemType,r,c>& A);
 friend ostream& operator << (ostream& out,Matrix<ElemType,r,c>& A);

};

 

 

 

 


//***************************************************************************/
//常用的向量運算函數模板實現代碼                                            */
//***************************************************************************/
template<typename ElemType,int r,int c>
ElemType VectorMo(Matrix<ElemType,r,c>& vector)
{
 ElemType a=vector(1,1),
       b=vector(1,2),
    c=vector(1,3);
 return sqrt(a*a+b*b+c*c);
}
template<typename ElemType,int r,int c>                    //向量單位化
Matrix<ElemType,r,c> VectorUnit(Matrix<ElemType,r,c>& vector)
{
 /*
 Matrix<ElemType,r,c> result;
 ElemType mo=1/VectorMo(vector);
 result=mo*vector;
    return result;
 */
 return 1/VectorMo(vector)*vector;
}
template<typename ElemType,int r,int c>  
Matrix<ElemType,r,c> RotateOX(Matrix<ElemType,r,c>& vector,float beta)

{
 Matrix<ElemType,r,c> result;
                                                           //爲了減少下面調用函數的次數,增加空間暫
                                                        //時存放旋轉軸的各個分量
 ElemType x=vector(1,1);
 ElemType y=vector(1,2);
 ElemType z=vector(1,3);
 
 result(1,1)=x;
 result(1,2)=y*cos(beta)-z*sin(beta);
 result(1,3)=y*sin(beta)+z*cos(beta);

    return result;
}
template<typename ElemType,int r,int c>  
Matrix<ElemType,r,c> RotateOY(Matrix<ElemType,r,c>& vector,float beta)
{
 Matrix<ElemType,r,c> result;
                                                           //爲了減少下面調用函數的次數,增加空間暫
                                                        //時存放旋轉軸的各個分量
 ElemType x=vector(1,1);
 ElemType y=vector(1,2);
 ElemType z=vector(1,3);

 result(1,1)=x*cos(beta)+z*sin(beta);
 result(1,2)=y;
 result(1,3)=-x*sin(beta)+z*cos(beta);

 return result;
}
template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> RotateOZ(Matrix<ElemType,r,c>& vector,float beta)
{
 Matrix<ElemType,r,c> result;
                                                           //爲了減少下面調用函數的次數,增加空間暫
                                                        //時存放旋轉軸的各個分量
 ElemType x=vector(1,1);
 ElemType y=vector(1,2);
 ElemType z=vector(1,3);

 result(1,1)=x*cos(beta)-y*sin(beta);
 result(1,2)=x*sin(beta)+y*cos(beta);
 result(1,3)=z;

 return result;
}
template<typename ElemType,int r,int c>
Matrix<ElemType,r,c>  RotateON(Matrix<ElemType,r,c>& reel,Matrix<ElemType,r,c>& vector,float beta)
{
 Matrix<ElemType,r,c> result;
                                                           //爲了減少下面調用函數的次數,增加空間暫
                                                        //時存放旋轉軸的各個分量
 ElemType reelX=reel(1,1);
 ElemType reelY=reel(1,2);
 ElemType reelZ=reel(1,3);
                                                           //爲了減少頻繁的大量運算,增加空間暫時
                                                        //存放過原點的旋轉軸與x,y,z軸的夾角的餘
                                                        //弦值
 ElemType s=sqrt( reelX*reelX + reelY*reelY + reelZ*reelZ );
 ElemType n1=reelX/s;
 ElemType n2=reelY/s;
 ElemType n3=reelZ/s;
                                                           //爲了減少計算次數,暫時存放常用的數據
 ElemType n1n1=n1*n1,
          n2n2=n2*n2,
    n3n3=n3*n3,
    n1n3=n1*n3,
    n1n2=n1*n2,
    n2n3=n2*n3;
                                                        //爲了減少計算次數,暫時存放旋轉角度的
                                                        //正弦值和餘弦值
 ElemType cosBeta=cos(beta),
       sinBeta=sin(beta);
                                                           //核心,計算旋轉後的各個分量
    result(1,1)=reelX*( n1n1+(1-n1n1)*cosBeta )+reelY*( n1n2*(1-cosBeta)-n3*sinBeta )+reelZ*( n1n3*(1-cosBeta)+n2*sinBeta );
 result(1,2)=reelX*( n1n2*(1-cosBeta)+n3*sinBeta )+reelY*( n2n2+(1-n2n2)*cosBeta )+reelZ*( n2n3*(1-cosBeta)-n1*sinBeta );
 result(1,3)=reelX*( n1n3*(1-cosBeta)-n2*sinBeta )+reelY*( n2n3*(1-cosBeta)+n1*sinBeta )+reelZ*( n3n3+(1-n3n3)*cosBeta );

 return result;
}
template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> VectorProduct(Matrix<ElemType,r,c>& va,Matrix<ElemType,r,c>& vb)             //向量積
{
 Matrix<ElemType,r,c> result(1,3,0);
 result(1,1)=va(1,2)*vb(1,3)-va(1,3)*vb)*vb(1,2);
 result(1,2)=va(1,3)*vb(1,1)-va(1,1)*vb(1,3);
 result(1,3)=va(1,1)*vb(1,2)-va(1,2)*vb(1,1);
 return result;
}
template<typename ElemType,int r,int c>
int CoordinateTransfer(Matrix<ElemType,r,c>& origin,Matrix<ElemType,r,c>& xDirect,Matrix<ElemType,r,c>& yDirect,Matrix<ElemType,r,c>& zDirect,
        Matrix<ElemType,r,c>*& pVertex,int nVertex)
                                            //座標變換
{
 return 0;
}
template<typename ElemType,int r,int c>
int VectorAngle(Matrix<ElemType,r,c>& b,Matrix<ElemType,r,c>& a,float* sin,float* cos)
{                                                          //求兩個向量夾角的正弦和餘弦
 ElemType ax=a(1,1),
       ay=a(1,2),
       az=a(1,3),
       bx=b(1,1),
       by=b(1,2),
       bz=b(1,3);
 *cos=(ax*bx+ay*by+az*bz)/sqrt(ax*ax+ay*ay+az*az)/sqrt(bx*bx+by*by+bz*bz);
 *sin=sqrt( 1-(*cos * *cos) );
 return 1;
}

 


//***************************************************************************/
//矩陣類模板的實現                                                          */
//***************************************************************************/
template<typename ElemType,int r,int c>
Matrix<ElemType,r,c>::Matrix()
{
 this->row=r;
 this->col=c;
 while(  !(this->pElemType=new ElemType[row*col])  );   //要構造一個矩陣,一定能夠成功
 for(int i=0;i<row*col;i++)
  pElemType[i]=0;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c>::Matrix(const Matrix<ElemType,r,c>&A) //深度堆拷貝構造函數
{
 row=A.row;
 col=A.col;
 while(  !(pElemType=new ElemType[row*col])  );
 for(int i=0;i<row*col;i++)
  pElemType[i]=A.pElemType[i];
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c>::~Matrix()
{
 if(pElemType)
  delete[]pElemType;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c>& Matrix<ElemType,r,c>::operator = (const Matrix<ElemType,r,c>&A)
{
                                                        //因該在這裏插入矩陣行列檢查的語句,下同
 row=A.row;
 col=A.col;
 //while(  !(pElemType=new ElemType[row*col])  );
                                                        //爲提高效率,可以考慮採用內存區拷貝技術
 for(int i=0;i<row*col;i++)
  pElemType[i]=A.pElemType[i];
 cout<<"asdkfjkasdfjdklsfjasdklfj"<<endl;
 return *this;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator + (const Matrix<ElemType,r,c>&A,const Matrix<ElemType,r,c>&B)
{
 Matrix<ElemType,r,c> result=A;                         //注意,這裏使用const類型來構造對象的前
                                                        //提條件是堆拷貝函數的參數也必須是const
                                                        //類型,否則要發生錯誤
 for(int i=0;i<result.row*result.col;i++)
  //result.pElemType[i]=A.pElemType[i]+B.pElemType[i];
  result.pElemType[i]+=B.pElemType[i];
 return result;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator - (const Matrix<ElemType,r,c>&A,const Matrix<ElemType,r,c>&B)
{
 Matrix<ElemType,r,c> result=A;
 for(int i=0;i<result.row*result.col;i++)
  result.pElemType[i]-=B.pElemType[i];
 return result;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator * (const Matrix<ElemType,r,c>&A,const Matrix<ElemType,r,c>&B)
{
                                                        //對於矩陣的乘法,這裏應該插入對兩個操
                                                        //作數行列的檢查
 Matrix<ElemType,r,c> result;
 for(int i=0;i<result.row;i++)
  for(int j=0;j<result.col;j++)
  {                                                  //這裏定義了一個temp,避免了累加時,對
                                                  //矩陣數據數組下標的頻繁引用,省去了頻
                                                  //繁的查找,求出結果時,進行一次引用,
                                                  //較少了乘法的次數,提高了效率
   ElemType temp=0;
   for(int k=0;k<A.col;k++)
    temp+=A.pElemType[i*A.row+k]*B.pElemType[i*k+j];
   result.pElemType[i*result.row+j]=temp;
  }
 return result;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator * (const double& scale,const Matrix<ElemType,r,c>& B)
{
 Matrix<ElemType,r,c> result=B;
 for(int i=0;i<B.row*B.col;i++)
  result.pElemType[i]*=(ElemType)scale;
 return result;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator * (const float& scale,const Matrix<ElemType,r,c>& B)
{
 Matrix<ElemType,r,c> result=B;
 for(int i=0;i<B.row*B.col;i++)
  result.pElemType[i]*=(ElemType)scale;
 return result;
}

template<typename ElemType,int r,int c>
Matrix<ElemType,r,c> operator * (const int& scale,const Matrix<ElemType,r,c>& B)
{
 Matrix<ElemType,r,c> result=B;
 for(int i=0;i<B.row*B.col;i++)
  result.pElemType[i]*=(ElemType)scale;
 return result;
}

template<typename ElemType,int r,int c>
const Matrix<ElemType,r,c>& operator +=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B)
{
 A=A+B;
 return A;
}

template<typename ElemType,int r,int c>
const Matrix<ElemType,r,c>& operator -=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B)
{
 A=A-B;
 return A;
}

template<typename ElemType,int r,int c>
const Matrix<ElemType,r,c>& operator *=(Matrix<ElemType,r,c>& A,const Matrix<ElemType,r,c>& B)
{
 A=A*B;
 return A;
}
template<typename ElemType,int r,int c>
istream& operator >>(istream& in,Matrix<ElemType,r,c>& A)
{
 cout<<"please input the matrix:"<<endl;
 for(int i=0;i<A.row;i++)
  for(int j=0;j<A.col;j++)
   in>>A.pElemType[i*row+j]; 
 return in;
}
template<typename ElemType,int r,int c>
ostream& operator <<(ostream& out,Matrix<ElemType,r,c>& A)
{
 for(int i=0;i<A.row;i++)
 {
  for(int j=0;j<A.col;j++)
  {
   out<<A.pElemType[i*A.row+j];
   out<<"   ";
  }
  out<<endl;
 }
 return out;
}

 

 

//***************************************************************************/
//測試函數                                                                  */
//***************************************************************************/

void main()
{
 Vector3f v;
 v(1,1)=4;
 v(1,2)=2;
 Vector3f r;
 r(1,1)=1;
 cout<<RotateOX(v,3);
 cout<<RotateOY(v,3);

 cout<<v;
 Matrix<int,4,4> matrix;
 matrix(4,4)=235;
 matrix(2,1)=3;
 v=v+v;
 cout<<v;
 cout<<matrix+matrix;
 cout<<matrix*matrix;

 cout<<v;
 cout<<VectorMo(v);
 cout<<VectorUnit(v);
 

}


 

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章