Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

449 lines
9.2 KiB
C++

//-------------------------------------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TGMatrix 类
// = Version : ver2.0
// = Author : wlw
// = CreateDate : 2002-09-09
// = Description: TGMatrix 定义
// = Maintainers:
//
//-------------------------------------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TGMatrix.h"
TGMatrix::TGMatrix()
{
InitIdentity();
}
TGMatrix::~TGMatrix()
{
}
double* TGMatrix::operator [](int i) const
{
return (double*)(matrix[i]);
}
bool TGMatrix::CanReverse() const
{
double temp = Rank();
return !EQUAL_ZERO(temp);
}
void TGMatrix::GetCoordSys(TPGeCoordSys&sys) const
{
sys.Reset();
sys.TransformBy(this);
}
void TGMatrix::Init()
{
memset((void*)matrix,0,sizeof(double)*16);
matrix[3][3] = 1.0;
}
void TGMatrix::InitIdentity()
{
Init();matrix[0][0] = 1.0;
matrix[1][1] = 1.0;
matrix[2][2] = 1.0;
}
TGMatrix::TGMatrix(const TGMatrix&m2)
{
memcpy(matrix,m2[0],sizeof(double)*16);
}
TGMatrix& TGMatrix::operator = (const TGMatrix&m2)
{
memcpy(matrix,m2[0],sizeof(double)*16);
return *this;
}
TGMatrix& TGMatrix::operator = (const float*m)
{
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 4;j++)
{
matrix[i][j] = m[i*4+j];
}
}
return *this;
}
void TGMatrix::Export(float*m) const
{
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 4;j++)
{
m[i*4+j] = (float)(matrix[i][j]);
}
}
}
void TGMatrix::Transform3D(TGPoint&point) const
{
double a = matrix[0][0]*point.x+matrix[1][0]*point.y+matrix[2][0]*point.z+matrix[3][0];
double b = matrix[0][1]*point.x+matrix[1][1]*point.y+matrix[2][1]*point.z+matrix[3][1];
double c = matrix[0][2]*point.x+matrix[1][2]*point.y+matrix[2][2]*point.z+matrix[3][2];
double w = matrix[0][3]*point.x+matrix[1][3]*point.y+matrix[2][3]*point.z+matrix[3][3];
point.x = a/w;
point.y = b/w;
point.z = c/w;
}
void TGMatrix::Transform2D(TGPoint&point) const
{
double a = matrix[0][0]*point.x+matrix[1][0]*point.y+matrix[3][0];
double b = matrix[0][1]*point.x+matrix[1][1]*point.y+matrix[3][1];
double w = matrix[0][3]*point.x+matrix[1][3]*point.y+matrix[3][3];
point.x = a/w;
point.y = b/w;
}
void TGMatrix::Transform(TGVector3D&vt) const
{
double a = matrix[0][0]*vt.x+matrix[1][0]*vt.y+matrix[2][0]*vt.z;
double b = matrix[0][1]*vt.x+matrix[1][1]*vt.y+matrix[2][1]*vt.z;
double c = matrix[0][2]*vt.x+matrix[1][2]*vt.y+matrix[2][2]*vt.z;
double w = matrix[0][3]*vt.x+matrix[1][3]*vt.y+matrix[2][3]*vt.z+matrix[3][3];
vt.x = a/w;
vt.y = b/w;
vt.z = c/w;
}
void TGMatrix::Transform(TGVector2D&vt) const
{
double a = matrix[0][0]*vt.x+matrix[1][0]*vt.y;
double b = matrix[0][1]*vt.x+matrix[1][1]*vt.y;
double w = matrix[0][3]*vt.x+matrix[1][3]*vt.y+matrix[3][3];
vt.x = a/w;
vt.y = b/w;
}
TGMatrix& TGMatrix::operator *= (const TGMatrix &m2)
{
GTransformMatrix r;
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 4;j++)
{
r[i][j] = 0.0;
for (int k = 0;k < 4;k++)
{
r[i][j] += matrix[i][k]*m2[k][j];
}
}
}
memcpy(matrix,r,sizeof(double)*16);
return *this;
}
TGMatrix TGMatrix::operator *(const TGMatrix&m2) const
{
TGMatrix r;
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 4;j++)
{
r[i][j] = 0.0;
for (int k = 0;k < 4;k++)
{
r[i][j] += matrix[i][k]*m2[k][j];
}
}
}
return r;
}
bool TGMatrix::Reverse()
{
double r = Rank();
if (EQUAL_ZERO(r))
{
return false;
}
TGMatrix m(*this);
double row[4];
for (long j = 0;j < 4;j++)
{
memcpy(row,m[j],4*sizeof(double));
memset(m[j],0,4*sizeof(double));
for (long i = 0;i < 4;i++)
{
m[j][i] = 1;
(*this)[i][j] = m.Rank()/r;
m[j][i] = 0;
}
memcpy(m[j],row,4*sizeof(double));
}
return true;
}
double TGMatrix::Rank() const
{
const TGMatrix& m = *this;
double r = 0;
r += m[0][0]*m[1][1]*m[2][2]*m[3][3];
r -= m[0][0]*m[1][1]*m[2][3]*m[3][2];
r -= m[0][0]*m[1][2]*m[2][1]*m[3][3];
r += m[0][0]*m[1][2]*m[2][3]*m[3][1];
r -= m[0][0]*m[1][3]*m[2][2]*m[3][1];
r += m[0][0]*m[1][3]*m[2][1]*m[3][2];
r -= m[0][1]*m[1][0]*m[2][2]*m[3][3];
r += m[0][1]*m[1][0]*m[2][3]*m[3][2];
r += m[0][1]*m[1][2]*m[2][0]*m[3][3];
r -= m[0][1]*m[1][2]*m[2][3]*m[3][0];
r -= m[0][1]*m[1][3]*m[2][0]*m[3][2];
r += m[0][1]*m[1][3]*m[2][2]*m[3][0];
r += m[0][2]*m[1][0]*m[2][1]*m[3][3];
r -= m[0][2]*m[1][0]*m[2][3]*m[3][1];
r -= m[0][2]*m[1][1]*m[2][0]*m[3][3];
r += m[0][2]*m[1][1]*m[2][3]*m[3][0];
r += m[0][2]*m[1][3]*m[2][0]*m[3][1];
r -= m[0][2]*m[1][3]*m[2][1]*m[3][0];
r -= m[0][3]*m[1][0]*m[2][1]*m[3][2];
r += m[0][3]*m[1][0]*m[2][2]*m[3][1];
r += m[0][3]*m[1][1]*m[2][0]*m[3][2];
r -= m[0][3]*m[1][1]*m[2][2]*m[3][0];
r -= m[0][3]*m[1][2]*m[2][0]*m[3][1];
r += m[0][3]*m[1][2]*m[2][1]*m[3][0];
return r;
}
void TGMatrix::Swap()
{
Exchange((*this)[0][1],(*this)[1][0]);
Exchange((*this)[0][2],(*this)[2][0]);
Exchange((*this)[0][3],(*this)[3][0]);
Exchange((*this)[1][2],(*this)[2][1]);
Exchange((*this)[1][3],(*this)[3][1]);
Exchange((*this)[2][3],(*this)[3][2]);
}
void TGMatrix::CreateMoveMatrix(double cx,double cy,double cz)
{
matrix[3][0] = cx;
matrix[3][1] = cy;
matrix[3][2] = cz;
}
void TGMatrix::CreateMoveMatrix(double cx,double cy)
{
matrix[3][0] = cx;
matrix[3][1] = cy;
}
void TGMatrix::CreateMoveMatrix(const TGVector3D&vt)
{
matrix[3][0] = vt.x;
matrix[3][1] = vt.y;
matrix[3][2] = vt.z;
}
void TGMatrix::CreateMoveMatrix(const TGVector2D&vt)
{
matrix[3][0] = vt.x;
matrix[3][1] = vt.y;
}
void TGMatrix::CreateScaleMatrix(double sx,double sy,double sz)
{
matrix[0][0] = sx;
matrix[1][1] = sy;
matrix[2][2] = sz;
}
void TGMatrix::CreateScaleMatrix(double sx,double sy)
{
matrix[0][0] = sx;
matrix[1][1] = sy;
}
void TGMatrix::CreateRotateMatrix(double angle,const TGPoint&basePoint)
{
double C = cos(angle),S = sin(angle);
matrix[0][0] = C;
matrix[0][1] = S;
matrix[1][0] = -S;
matrix[1][1] = C;
matrix[3][0] = (1-C)*basePoint.x+basePoint.y*S;
matrix[3][1] = (1-C)*basePoint.y-basePoint.x*S;
}
void TGMatrix::CreateScaleMatrix(double sx,double sy,double sz,const TGPoint&basePoint)
{
matrix[0][0] = sx;
matrix[1][1] = sy;
matrix[2][2] = sz;
matrix[3][0] = (1-sx)*basePoint.x;
matrix[3][1] = (1-sy)*basePoint.y;
matrix[3][2] = (1-sz)*basePoint.z;
}
void TGMatrix::CreateScaleMatrix(double sx,double sy,const TGPoint&basePoint)
{
matrix[0][0] = sx;
matrix[1][1] = sy;
matrix[3][0] = (1-sx)*basePoint.x;
matrix[3][1] = (1-sy)*basePoint.y;
}
void TGMatrix::CreateXRotateMatrix(double angle)
{
matrix[1][1] = cos(angle);
matrix[2][2] = matrix[1][1];
matrix[1][2] = sin(angle);
matrix[2][1] = -matrix[1][2];
}
void TGMatrix::CreateYRotateMatrix(double angle)
{
matrix[0][0] = cos(angle);
matrix[2][2] = matrix[0][0];
matrix[2][0] = sin(angle);
matrix[0][2] = -matrix[2][0];
}
void TGMatrix::CreateZRotateMatrix(double angle)
{
matrix[0][0] = cos(angle);
matrix[1][1] = matrix[0][0];
matrix[0][1] = sin(angle);
matrix[1][0] = -matrix[0][1];
}
void TGMatrix::CreateRotateMatrix(double angle,const TPGeLine3D&axis)
{
TGVector3D vt(axis);
if (!vt.Normalize())
{
return;
}
double a = vt.x,b = vt.y,c = vt.z;
double x = axis.basePoint.x,y = axis.basePoint.y,z = axis.basePoint.z;
double v = sqrt(c*c+b*b);
TGMatrix &taMat = *this,uaMat,rxMat,uxMat,ryMat,uyMat,rzmat;
taMat[3][0] = -x;
taMat[3][1] = -y;
taMat[3][2] = -z;
uaMat[3][0] = x;
uaMat[3][1] = y;
uaMat[3][2] = z;
rxMat[1][1] = rxMat[2][2] = c/v;
rxMat[1][2] = b/v;
rxMat[2][1] = -rxMat[1][2];
uxMat[1][1] = uxMat[2][2] = c/v;
uxMat[1][2] = -b/v;
uxMat[2][1] = -uxMat[1][2];
ryMat[0][0] = ryMat[2][2] = v;
ryMat[0][2] = a;
ryMat[2][0] = -a;
uyMat[0][0] = uyMat[2][2] = v;
uyMat[0][2] = -a;
uyMat[2][0] = a;
rzmat[0][0] = rzmat[1][1] = cos(angle);
rzmat[0][1] = sin(angle);
rzmat[1][0] = -rzmat[0][1];
taMat *= rxMat;
taMat *= ryMat;
taMat *= rzmat;
taMat *= uyMat;
taMat *= uxMat;
taMat *= uaMat;
}
bool TGMatrix::CreateXYProjectMatrix(const TGPoint&pt,bool bParallel)
{
if (EQUAL_ZEROD(pt.z))
{
return false;
}
CreateXYProjectMatrix();
matrix[2][0] = -pt.x/pt.z;
matrix[2][1] = -pt.y/pt.z;
if (!bParallel)
{
matrix[2][3] = -1/pt.z;
}
return true;
}
bool TGMatrix::CreateProjectMatrix(const TPGePlane&plane,const TGPoint&pt,bool bParallel)
{
if (bParallel)
{
double A = plane.a;
double B = plane.b;
double C = plane.c;
double D = plane.d;
TGVector3D vt = pt;
vt.Normalize();
double dot = A*vt[0]+B*vt[1]+C*vt[2];
if (EQUAL_ZERO(dot))
{
return false;
}
else
{
matrix[0][0] = 1.0-vt[0]*A/dot;
matrix[1][0] = -vt[0]*B/dot;
matrix[2][0] = -vt[0]*C/dot;
matrix[3][0] = -vt[0]*D/dot;
matrix[0][1] = -vt[1]*A/dot;
matrix[1][1] = 1.0-vt[1]*B/dot;
matrix[2][1] = -vt[1]*C/dot;
matrix[3][1] = -vt[1]*D/dot;
matrix[0][2] = -vt[2]*A/dot;
matrix[1][2] = -vt[2]*B/dot;
matrix[2][2] = 1.0-vt[2]*C/dot;
matrix[3][2] = -vt[2]*D/dot;
return true;
}
}
else
{
if (plane.HitTest(pt).Is(GR_IN))
{
return false;
}
TGPoint pt2(pt);
TGMatrix mPlane,mProject;
mPlane.SetCoordSys(plane);
(*this) *= mPlane;
mPlane.Transform3D(pt2);
mProject.CreateXYProjectMatrix(pt2,bParallel);
(*this) *= mProject;
mPlane.Reverse();
(*this) *= mPlane;
return true;
}
}