# Affine Decomposition

All that's left to do is to implement the actual `AffineDecompose` function. This page is mostly just a code-dump of how to put everything together. Let's start with the structures and function signatures of what we have already written. The only decomposition method that isn't needed here is `QRDecompositon`, because it is only used as a helper function for `SpectralDecompositon`.

```struct FactorTranslationResult {
Matrix T; // Translation
Matrix X; // Linear transformation
}

struct PolarDecompResult {
Matrix Q; // Q is a rotation, or the negative of a rotation
Matrix S; // Scale and skew matrix
}

struct FactorRotationResult {
Matrix F; // Positive or negative identity (flip if negative)
Matrix R; // Rotation matrix
}

struct SpectralDecompositionResult {
Matrix U; // Each basis vector is an eigenvector
Matrix K; // Contains eigenvalues on main diagonal
Matrix Ut; // Transpose of U
}

Matrix U; // Each basis vector is an eigenvector
Matrix K; // Contains eigenvalues on main diagonal
Matrix Ut; // Transpose of U
}

FactorTranslationResult FactorTranslation(Matrix M);
PolarDecompResult PolarDecomposition(Matrix X);
FactorRotationResult FactorRotation(Matrix Q);
SpectralDecompositionResult SpectralDecomposition(Matrix S);

Having already written all of the above functions, implementing `AffineDecomposition` becomes a matter of calling the helper functions in the appropriate order, like so:

```struct AffineDecompositionResult {
Matrix T; // Holds translation of the matrix
Matrix F; // Flip data (positive or negative identity)
Matrix R; // Holds rotation of the matrix
Matrix U; // Holds eigenvectors of the matrix
Matrix K; // Holds eigenvalues (scale) of the matrix
Matrix Ut;// Transpose of U
}

AffineDecompositionResult AffineDecomposition(Matrix M) {
FactorTranslationResult factorTranslation = FactorTranslation(M);
PolarDecompResult polarDecomposition = PolarDecomposition(factorTranslation.X);
FactorRotationResult factorRotation = FactorRotation(polarDecomposition.Q);
SpectralDecompositionResult spectralDecomp = SpectralDecomposition(factorRotation.R);

AffineDecompositionResult result;
result.T = factorTranslation.T;
result.F = factorRotation.F;
result.R = factorRotation.R;

return result;
}```

We might want to re-format the output to match shoemake's reference code a bit more. For the most part this is just a matter of converting some matrices to quaternions, like so:

```struct ShoemakeResult {
Vector3 T; // Translation
float F; // Sign of determinant
Quaternion R; // Rotation (q in shoemake's code)
Quaternion U; //Stretch matrix
Vector3 K; // Scale info
}

ShoemakeResult ConvertResultToShoemakeFormat(AffineDecompositionResult affine) {
ShoemakeResult result;

result.T = Vector3(affine.T[12], affine.T[13], affine.T[14]);
result.F = affine.F[0];
result.R = ToQuaternion(affine.R);
result.U = ToQuaternion(affine.U);
result.K = Vector3(affine.K[0], affine.K[5], affine.K[10]);

return result;
}```