📄 dxvector.h
字号:
/*******************************************************************************
* DXVector.h *
*------------*
* Description:
* This is the header file for the vector and matrix classes.
*-------------------------------------------------------------------------------
* Created By: Mike Arnstein Date: 04/11/97
* Copyright (C) 1997 Microsoft Corporation
* All Rights Reserved
*
*-------------------------------------------------------------------------------
* Revisions:
*
*******************************************************************************/
#ifndef DXVector_h
#pragma option push -b -a8 -pc -A- /*P_O_Push*/
#define DXVector_h
#ifndef _INC_MATH
#include <math.h>
#endif
#ifndef _INC_CRTDBG
#include <crtdbg.h>
#endif
//=== Constants ====================================================
//=== Class, Enum, Struct and Union Declarations ===================
class CDXMatrix4x4F;
//=== Enumerated Set Definitions ===================================
//=== Function Type Definitions ====================================
float det4x4( CDXMatrix4x4F *pIn );
float det3x3( float a1, float a2, float a3, float b1, float b2, float b3,
float c1, float c2, float c3 );
float det2x2( float a, float b, float c, float d );
//=== Class, Struct and Union Definitions ==========================
/*** CDXVec ************
* This template implements basic vector operations for each of the
* union types
*/
#define CDXV_C CDXVec<TYPE, eBndType>
#define CDXV_T ((TYPE*)u.D)
#define CDXV_O( OtherVec ) ((TYPE*)OtherVec.u.D)
template<class TYPE, DXBNDTYPE eBndType>
class CDXVec : public DXVEC
{
/*=== Methods =======*/
public:
/*--- Constructors ---*/
CDXVec() { eType = eBndType; ZeroVector(); }
CDXVec(BOOL bInit) { eType = eBndType; if (bInit) ZeroVector(); }
CDXVec( TYPE x, TYPE y, TYPE z, TYPE t )
{ eType = eBndType; CDXV_T[DXB_X] = x; CDXV_T[DXB_Y] = y;
CDXV_T[DXB_Z] = z; CDXV_T[DXB_T] = t; }
CDXVec( const CDXVec& Other ) { memcpy( this, (void *)&Other, sizeof(DXVEC) ); }
CDXVec( const DXVEC Other ) { memcpy( this, &Other, sizeof(DXVEC) ); }
operator TYPE *() { return CDXV_T; }
operator const TYPE *() { return CDXV_T; }
/*--- operations ---*/
void ZeroVector( void ) { memset( u.D, 0, sizeof(TYPE) * 4); }
/*--- operators ---*/
TYPE& operator[]( int index ) const { return CDXV_T[index]; }
TYPE& operator[]( long index ) const { return CDXV_T[index]; }
TYPE& operator[]( USHORT index ) const { return CDXV_T[index]; }
TYPE& operator[]( DWORD index ) const { return CDXV_T[index]; }
CDXV_C operator+(const CDXV_C& v);
CDXV_C operator-(const CDXV_C& v);
void operator=(const CDXV_C& srcVector);
void operator+=(const CDXV_C& vOther);
void operator-=(const CDXV_C& vOther);
BOOL operator==(const CDXV_C& otherVector) const;
BOOL operator!=(const CDXV_C& otherVector) const;
};
template<class TYPE, DXBNDTYPE eBndType>
CDXV_C CDXV_C::operator+( const CDXV_C& srcVector )
{
CDXV_C Result( this );
CDXV_O( Result )[DXB_X] += CDXV_O( srcVector )[DXB_X];
CDXV_O( Result )[DXB_Y] += CDXV_O( srcVector )[DXB_Y];
CDXV_O( Result )[DXB_Z] += CDXV_O( srcVector )[DXB_Z];
CDXV_O( Result )[DXB_T] += CDXV_O( srcVector )[DXB_T];
return Result;
} /* CDXVec::operator+ */
template<class TYPE, DXBNDTYPE eBndType>
CDXV_C CDXV_C::operator-( const CDXV_C& srcVector )
{
CDXV_C Result( this );
CDXV_O( Result )[DXB_X] -= CDXV_O( srcVector )[DXB_X];
CDXV_O( Result )[DXB_Y] -= CDXV_O( srcVector )[DXB_Y];
CDXV_O( Result )[DXB_Z] -= CDXV_O( srcVector )[DXB_Z];
CDXV_O( Result )[DXB_T] -= CDXV_O( srcVector )[DXB_T];
return Result;
} /* CDXVec::operator- */
template<class TYPE, DXBNDTYPE eBndType>
void CDXV_C::operator=( const CDXV_C& srcVector )
{
memcpy( this, &srcVector, sizeof(CDXVec) );
} /* CDXVec::operator= */
template<class TYPE, DXBNDTYPE eBndType>
BOOL CDXV_C::operator==(const CDXV_C& otherVector) const
{
return !memcmp( this, &otherVector, sizeof(otherVector) );
} /* CDXVec::operator== */
template<class TYPE, DXBNDTYPE eBndType>
BOOL CDXV_C::operator!=(const CDXV_C& otherVector) const
{
return memcmp( this, &otherVector, sizeof(otherVector) );
} /* CDXVec::operator!= */
template<class TYPE, DXBNDTYPE eBndType>
void CDXV_C::operator+=(const CDXV_C& vOther)
{
CDXV_T[DXB_X] += CDXV_O( vOther )[DXB_X];
CDXV_T[DXB_Y] += CDXV_O( vOther )[DXB_Y];
CDXV_T[DXB_Z] += CDXV_O( vOther )[DXB_Z];
CDXV_T[DXB_T] += CDXV_O( vOther )[DXB_T];
} /* CDXVec::operator+= */
template<class TYPE, DXBNDTYPE eBndType>
void CDXV_C::operator-=(const CDXVec& vOther)
{
CDXV_T[DXB_X] -= CDXV_O( vOther )[DXB_X];
CDXV_T[DXB_Y] -= CDXV_O( vOther )[DXB_Y];
CDXV_T[DXB_Z] -= CDXV_O( vOther )[DXB_Z];
CDXV_T[DXB_T] -= CDXV_O( vOther )[DXB_T];
} /* CDXVec::operator-= */
typedef CDXVec<long, DXBT_DISCRETE> CDXDVec;
typedef CDXVec<LONGLONG, DXBT_DISCRETE64> CDXDVec64;
typedef CDXVec<float, DXBT_CONTINUOUS> CDXCVec;
typedef CDXVec<double, DXBT_CONTINUOUS64> CDXCVec64;
/*** CDX2DXForm ************
* This class implements basic matrix operation based on the GDI XFORM
* structure.
*/
//const DX2DXFORM g_DX2DXFORMIdentity = { 1., 0., 0., 1., 0., 0., DX2DXO_IDENTITY };
class CDX2DXForm : public DX2DXFORM
{
/*=== Methods =======*/
public:
/*--- Constructors ---*/
CDX2DXForm() { SetIdentity(); }
CDX2DXForm( const CDX2DXForm& Other ) { memcpy( this, &Other, sizeof(*this) ); }
CDX2DXForm( const DX2DXFORM& Other ) { memcpy( this, &Other, sizeof(*this) ); }
/*--- methods ---*/
void DetermineOp( void );
void Set( const DX2DXFORM& Other ) { memcpy( this, &Other, sizeof(*this) ); DetermineOp(); }
void ZeroMatrix( void ) { memset( this, 0, sizeof( *this ) ); }
void SetIdentity( void ) {
eM11 = 1.;
eM12 = 0.;
eM21 = 0.;
eM22 = 1.;
eDx = 0.;
eDy = 0.;
eOp = DX2DXO_IDENTITY;
}
BOOL IsIdentity() const { return eOp == DX2DXO_IDENTITY; }
void Scale( float sx, float sy );
void Rotate( float Rotation );
void Translate( float dx, float dy );
BOOL Invert();
void TransformBounds( const DXBNDS& Bnds, DXBNDS& ResultBnds ) const;
void TransformPoints( const DXFPOINT InPnts[], DXFPOINT OutPnts[], ULONG ulCount ) const;
void GetMinMaxScales( float& MinScale, float& MaxScale );
/*--- operators ---*/
DXFPOINT operator*( const DXFPOINT& v ) const;
CDX2DXForm operator*( const CDX2DXForm& Other ) const;
};
//=== CDX2DXForm methods ==============================================================
inline void CDX2DXForm::DetermineOp( void )
{
if( ( eM12 == 0. ) && ( eM21 == 0. ) )
{
if( ( eM11 == 1. ) && ( eM22 == 1. ) )
{
eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_IDENTITY):(DX2DXO_TRANSLATE);
}
else
{
eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_SCALE):(DX2DXO_SCALE_AND_TRANS);
}
}
else
{
eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_GENERAL):(DX2DXO_GENERAL_AND_TRANS);
}
} /* CDX2DXForm::DetermineOp */
inline float DXSq( float f ) { return f * f; }
// This function computes the Min and Max scale that a matrix represents.
// In other words, what is the maximum/minimum length that a line of length 1
// could get stretched/shrunk to if the line was transformed by this matrix.
//
// The function uses eigenvalues; and returns two float numbers. Both are
// non-negative; and MaxScale >= MinScale.
//
inline void CDX2DXForm::GetMinMaxScales( float& MinScale, float& MaxScale )
{
if( ( eM12 == 0. ) && ( eM21 == 0. ) )
{
// Let MinScale = abs(eM11)
if (eM11 < 0)
MinScale = -eM11;
else
MinScale = eM11;
// Let MaxScale = abs(eM22)
if (eM22 < 0)
MaxScale = -eM22;
else
MaxScale = eM22;
// Swap Min/Max if necessary
if (MinScale > MaxScale)
{
float flTemp = MinScale;
MinScale = MaxScale;
MaxScale = flTemp;
}
}
else
{
float t1 = DXSq(eM11) + DXSq(eM12) + DXSq(eM21) + DXSq(eM22);
if( t1 == 0. )
{
MinScale = MaxScale = 0;
}
else
{
float t2 = (float)sqrt( (DXSq(eM12 + eM21) + DXSq(eM11 - eM22)) *
(DXSq(eM12 - eM21) + DXSq(eM11 + eM22)) );
// Due to floating point error; t1 may end up less than t2;
// but that would mean that the min scale was small (relative
// to max scale)
if (t1 <= t2)
MinScale = 0;
else
MinScale = (float)sqrt( (t1 - t2) * .5f );
MaxScale = (float)sqrt( (t1 + t2) * .5f );
}
}
} /* CDX2DXForm::GetMinMaxScales */
inline void CDX2DXForm::Rotate( float Rotation )
{
double Angle = Rotation * (3.1415926535/180.0);
float CosZ = (float)cos( Angle );
float SinZ = (float)sin( Angle );
if (CosZ > 0.0F && CosZ < 0.0000005F)
{
CosZ = .0F;
}
if (SinZ > -0.0000005F && SinZ < .0F)
{
SinZ = .0F;
}
float M11 = ( CosZ * eM11 ) + ( SinZ * eM21 );
float M21 = (-SinZ * eM11 ) + ( CosZ * eM21 );
float M12 = ( CosZ * eM12 ) + ( SinZ * eM22 );
float M22 = (-SinZ * eM12 ) + ( CosZ * eM22 );
eM11 = M11; eM21 = M21; eM12 = M12; eM22 = M22;
DetermineOp();
} /* CDX2DXForm::Rotate */
inline void CDX2DXForm::Scale( float sx, float sy )
{
eM11 *= sx;
eM12 *= sx;
eDx *= sx;
eM21 *= sy;
eM22 *= sy;
eDy *= sy;
DetermineOp();
} /* CDX2DXForm::Scale */
inline void CDX2DXForm::Translate( float dx, float dy )
{
eDx += dx;
eDy += dy;
DetermineOp();
} /* CDX2DXForm::Translate */
inline void CDX2DXForm::TransformBounds( const DXBNDS& Bnds, DXBNDS& ResultBnds ) const
{
ResultBnds = Bnds;
if( eOp != DX2DXO_IDENTITY )
{
ResultBnds.u.D[DXB_X].Min = (long)(( eM11 * Bnds.u.D[DXB_X].Min ) + ( eM12 * Bnds.u.D[DXB_Y].Min ) + eDx);
ResultBnds.u.D[DXB_X].Max = (long)(( eM11 * Bnds.u.D[DXB_X].Max ) + ( eM12 * Bnds.u.D[DXB_Y].Max ) + eDx);
ResultBnds.u.D[DXB_Y].Min = (long)(( eM21 * Bnds.u.D[DXB_X].Min ) + ( eM22 * Bnds.u.D[DXB_Y].Min ) + eDy);
ResultBnds.u.D[DXB_Y].Max = (long)(( eM21 * Bnds.u.D[DXB_X].Max ) + ( eM22 * Bnds.u.D[DXB_Y].Max ) + eDy);
}
} /* CDX2DXForm::TransformBounds */
inline void CDX2DXForm::TransformPoints( const DXFPOINT InPnts[], DXFPOINT OutPnts[], ULONG ulCount ) const
{
ULONG i;
switch( eOp )
{
case DX2DXO_IDENTITY:
memcpy( OutPnts, InPnts, ulCount * sizeof( DXFPOINT ) );
break;
case DX2DXO_TRANSLATE:
for( i = 0; i < ulCount; ++i )
{
OutPnts[i].x = InPnts[i].x + eDx;
OutPnts[i].y = InPnts[i].y + eDy;
}
break;
case DX2DXO_SCALE:
for( i = 0; i < ulCount; ++i )
{
OutPnts[i].x = InPnts[i].x * eM11;
OutPnts[i].y = InPnts[i].y * eM22;
}
break;
case DX2DXO_SCALE_AND_TRANS:
for( i = 0; i < ulCount; ++i )
{
OutPnts[i].x = (InPnts[i].x * eM11) + eDx;
OutPnts[i].y = (InPnts[i].y * eM22) + eDy;
}
break;
case DX2DXO_GENERAL:
for( i = 0; i < ulCount; ++i )
{
OutPnts[i].x = ( InPnts[i].x * eM11 ) + ( InPnts[i].y * eM12 );
OutPnts[i].y = ( InPnts[i].x * eM21 ) + ( InPnts[i].y * eM22 );
}
break;
case DX2DXO_GENERAL_AND_TRANS:
for( i = 0; i < ulCount; ++i )
{
OutPnts[i].x = ( InPnts[i].x * eM11 ) + ( InPnts[i].y * eM12 ) + eDx;
OutPnts[i].y = ( InPnts[i].x * eM21 ) + ( InPnts[i].y * eM22 ) + eDy;
}
break;
default:
_ASSERT( 0 ); // invalid operation id
}
} /* CDX2DXForm::TransformPoints */
inline DXFPOINT CDX2DXForm::operator*( const DXFPOINT& v ) const
{
DXFPOINT NewPnt;
NewPnt.x = ( v.x * eM11 ) + ( v.y * eM12 ) + eDx;
NewPnt.y = ( v.x * eM21 ) + ( v.y * eM22 ) + eDy;
return NewPnt;
} /* CDX2DXForm::operator* */
inline CDX2DXForm CDX2DXForm::operator*( const CDX2DXForm& Other ) const
{
DX2DXFORM x;
x.eM11 = ( eM11 * Other.eM11 ) + ( eM12 * Other.eM21 );
x.eM12 = ( eM11 * Other.eM12 ) + ( eM12 * Other.eM22 );
x.eDx = ( eM11 * Other.eDx ) + ( eM12 * Other.eDy ) + eDx;
x.eM21 = ( eM21 * Other.eM11 ) + ( eM22 * Other.eM21 );
x.eM22 = ( eM21 * Other.eM12 ) + ( eM22 * Other.eM22 );
x.eDy = ( eM21 * Other.eDx ) + ( eM22 * Other.eDy ) + eDy;
return x;
} /* CDX2DXForm::operator*= */
inline BOOL CDX2DXForm::Invert()
{
switch( eOp )
{
case DX2DXO_IDENTITY:
break;
case DX2DXO_TRANSLATE:
eDx = -eDx;
eDy = -eDy;
break;
case DX2DXO_SCALE:
if (eM11 == 0.0 || eM22 == 0.0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -