www.pudn.com > ZFXMath-latest.zip > SHRotateMatrix.h
/// \file
///
/// \if DE
/// @brief SphericalHarmonics::TRotateMatrix
///
/// TRotateMatrix: führt die Rotation der SH-Koeffizienten durch
/// \else
/// @brief SphericalHarmonics::TRotateMatrix
///
/// TRotateMatrix: performs the rotation of the SH-Coefficients
/// \endif
#ifndef _ZFXMATH_INCLUDE_SH_ROTATEMATRIX_H_
#define _ZFXMATH_INCLUDE_SH_ROTATEMATRIX_H_
namespace ZFXMath
{
namespace SphericalHarmonics
{
/// \if DE
/// @brief Rotationsmatrix zum transformieren von SH Koeffizienten.
/// \else
/// @brief Rotation Matrix, to transform SH Coefficients.
/// \endif
template
class TRotateMatrix
{
public:
TRotateMatrix(const int nb_bands) :
m_NbBands(nb_bands),
m_Matrices(0),
m_Elements(0)
{
/// Allocate the sub-matrix array
m_Matrices = (SubMatrix*)operator new (m_NbBands * sizeof(SubMatrix));
int size = 0;
for (int i = 0; i < m_NbBands; i++)
size += (i * 2 + 1) * (i * 2 + 1);
/// Allocate the entire element array
m_Elements = new PrecisionType[size];
/// Construct each sub-matrix
for (int i = 0, j = 0; i < m_NbBands; i++)
{
int w = i * 2 + 1;
m_Matrices[i] = *new SubMatrix(m_Elements + j, w);
j += (w * w);
}
// The first 1x1 sub-matrix is always 1 and so doesn't need to be stored in the rotation matrix
// It's stored simply to make the indexing logic as easy as possible
m_Elements[0] = 1;
}
~TRotateMatrix(void)
{
if (m_Elements)
delete [] m_Elements;
if (m_Matrices)
delete [] m_Matrices;
}
// Element accessors which take the band index and (+,-) index relative to the centre of the sub-matrix
PrecisionType& operator () (const int l, const int m, const int n)
{
return (m_Matrices[l](m, n));
}
PrecisionType operator () (const int l, const int m, const int n) const
{
return (m_Matrices[l](m, n));
}
int GetNbBands(void) const
{
return (m_NbBands);
}
/// \if DE
/// @brief Rotiert die gegebenen Koeffizienten
/// \else
/// @brief Rotates the given coefficients
/// \endif
void Transform(const TCoeffs& source, TCoeffs& dest) const
{
// Check number of bands match
int nb_bands = source.GetNbBands();
assert(nb_bands == dest.GetNbBands());
// Band 0 is always multiplied by 1 so it stays untouched
dest(0) = source(0);
// Loop through each band
for (int l = 1; l < nb_bands; l++)
{
SubMatrix& M = m_Matrices[l];
// Calculate band offset into coeff list
int band_offset = l * (l + 1);
// Now through each argument of the destination coeff-list
for (int mo = -l; mo <= l; mo++)
{
// Clear destination
FuncValueType& d = dest(band_offset + mo);
d = 0;
// Pre-calculate of mo's lookup in the sub-matrix, plus mi's shift
int p_mo = (mo + M.GetShift()) * M.GetWidth() + M.GetShift();
// Multiply-add with each argument of the source coeff-list
for (int mi = -l; mi <= l; mi++)
d += source(band_offset + mi) * FuncValueType( M(p_mo + mi) );
}
}
}
private:
class SubMatrix;
// Number of bands stored
int m_NbBands;
// Sub-matrix for each band
SubMatrix* m_Matrices;
// Element array for each sub-matrix
PrecisionType* m_Elements;
class SubMatrix
{
public:
// Construct that needs previously allocated element array
SubMatrix(PrecisionType* elements, const int width) :
m_Elements(elements),
m_Width(width),
m_Size(width * width),
m_Shift((width - 1) / 2)
{
}
// Element accessors with (+,-) lookup
PrecisionType& operator () (const int m, const int n)
{
return (m_Elements[Index(m, n)]);
}
PrecisionType operator () (const int m, const int n) const
{
return (m_Elements[Index(m, n)]);
}
// Linear element accessors
PrecisionType& operator () (const int i)
{
return (m_Elements[Index(i)]);
}
PrecisionType operator () (const int i) const
{
return (m_Elements[Index(i)]);
}
int GetWidth(void) const
{
return (m_Width);
}
int GetShift(void) const
{
return (m_Shift);
}
private:
int Index(const int m, const int n) const
{
// Check bounds in debug build
assert(m >= -m_Shift && m <= m_Shift);
assert(n >= -m_Shift && n <= m_Shift);
return ((m + m_Shift) * m_Width + (n + m_Shift));
}
int Index(const int i) const
{
// Check bounds in debug build
assert(i >= 0 && i < m_Size);
return (i);
}
// Element array
PrecisionType* m_Elements;
// Width of the sub-matrix
int m_Width;
// Total size of the sub-matrix in multiples of PrecisionType
int m_Size;
// Value to shift incoming matrix indices by
int m_Shift;
};
}; // class TRotateMatrix
}; // namespace SphericalHarmonics
}; // namespace ZFXMath
#endif //_ZFXMATH_INCLUDE_SH_ROTATEMATRIX_H_