2

I’m learning linear algebra and trying to make a little program with basic linear transformations (rotating, scaling, translating).

## Here is the fully working example:

I wrote functions for generating each matrix for each transformation and functions to calculate them (multiplying matrix with a point, multiplying matrices).

``````export const multiplyMatrixWithPoint = (matrix, point) => {
return point.map((dimension, index) => {
let result = 0;

for (let i = 0; i < 4; i++) {
const matrixIndex = index * 4 + i;
result += dimension * matrix[matrixIndex];
}

return +result.toFixed(2);
})
};

// Just creating 2D array to make it easy to calculate the matrix
export const matrixToPoints = matrix => {
const result = [];

for (let i = 0; i < 4; i++) {
const onePoint = [];

for (let j = 0; j < 4; j++) {
onePoint.push(matrix[4 * i + j]);
}

result.push(onePoint);
}

return result;
};

// Just making 2D array to 1D
export const pointsToMatrix = points => points.reduce((acc, points) => [...acc, ...points], []);

// Transpose function to make the matrix multiplication correct
export const transposeCSSMatrixToTransform = matrix => matrix[0].map((column, index) => matrix.map(row => row[index]));

export const multiplyMatrices = (matrixA, matrixB) => {
const separatePoints = transposeCSSMatrixToTransform(matrixToPoints(matrixB));

return pointsToMatrix(transposeCSSMatrixToTransform(separatePoints.map(point => multiplyMatrixWithPoint(matrixA, point))));
};

export const rotationMatrixGenerator = (matrix, angle) => {

return matrix;
};

export const scaleMatrixGenerator = (matrix, { x, y }) => {
matrix[0] = x;
matrix[5] = y;

return matrix;
};

export const translateMatrixGenerator = (matrix, { x, y }) => {
matrix[12] = x;
matrix[13] = y;

return matrix;
};
``````

For showing the transformations I used CSS’s matrix3d

``````export const matrixToCSSMatrix = matrix => `matrix3d(\${matrix.join(',')})`;
``````

And here are the executing part of the code

``````  ...
const [matrix, setMatrix] = useState(DEFAULT_MATRIX);
const [rotationAngle, setRotationAngle] = useState(0);
const [scale, setScale] = useState(DEFAULT_XY);
const [translate, setTranslate] = useState(DEFAULT_XY);

const classes = useStyles();
const { app } = classes;

// ---------------------- Rotate --------------------- //
const rotate = useCallback(e => {
const { value: angle } = e.target;

const rotationMatrix = rotationMatrixGenerator(matrix, +angle);
const updatedMatrix = multiplyMatrices(matrix, rotationMatrix);

setMatrix(updatedMatrix);
setRotationAngle(angle);
}, [matrix]);

// ---------------------- Scale --------------------- //
const changeScale = useCallback((e, dimension) => {
const { value } = e.target;
const updatedScale = {
...scale,
[dimension]: +value
};

const scaleMatrix = scaleMatrixGenerator(matrix, updatedScale);
const updatedMatrix = multiplyMatrices(matrix, scaleMatrix);

setMatrix(scaleMatrix);
setScale(updatedScale);
}, [matrix, scale]);

// ------------------ Translate --------------------- //
const changeTranslation = useCallback((e, position) => {
const { value } = e.target;
const updatedTranslation = {
...translate,
[position]: +value
};

const translateMatrix = translateMatrixGenerator(matrix, updatedTranslation);
const updatedMatrix = multiplyMatrices(matrix, translateMatrix);

setMatrix(translateMatrix);
setTranslate(updatedTranslation);
}, [matrix, translate]);
...
``````

Firstly I thought it’s because I didn’t transpose the matrix, I tried to transpose it, it helped a little but didn’t fix all bugs. Also, I tried to collect all transformations and apply them at once, but it was a very bad solution and didn’t work well.

I need to have a separate rotation, scaling and transition, but rotation and transition are didn’t work well because they are using the same segments of matrix. Also, I can’t achieve normal rotation against Z-axis.