README
CGA-SVD
A simple Javascript library for a number of Linear Algebra algorithms that rely on SVD.
https://github.com/WilliamLiu-1997/cga-svd
Description
Procrustes: A multi-dimentioanl vector alignment algorithm (known as Constrained Orthogonal Procrustes Problem or Kabsch algorithm). Return a matrix(presenting the rotation (Scale and/or Reflection on demand)) and a vector(presenting the translation) that that align a set of n dimentional vectors to their corresponding targets.
VectorFitting: SVD vector fitting algorithm. Simulate a n dimentional plane that fits a set of n dimentional vectors. Return a n dimentional vectors('normal') presenting the direction of the plane and a n dimentional vectors('center') presenting its center position.
SVD: Singular Value Decomposition. Code from https://github.com/danilosalvati/svd-js
MatrixRotationAroundVectorPoint3D: Produce a rotation matrix and translation vector that performs a rotation around a rotation axis that pass a specific point (default is the origin) in space with a certain angle. (3D Space)
MatrixMultiply: Multiply two matrices.
Transform: Apply a Transform on a list of vectors.
Translate: Apply a Translation on a list of vectors.
MatrixInverse: Invert a matrix
MatrixTranspose: Transpose a matrix.
Determinant: Determinant of a squared matrix.
Install
npm install cga-svd
Usage
Procrustes(source, target, withTranslation, withScale, withReflection) => { transform, translation }
@param {Array} source: an list of n dimentional vectors, will be aligned to target
@param {Array} target: an list of n dimentional vectors
@param {Boolean} withTranslation: whether move to target positions, default is true
@param {Boolean} withScale: whether contain scaling, default is true
@param {Boolean} withReflection: whether contain reflection, default is false
@returns {Object} An object containing:
transform: a matrix presenting the rotation (Scale and/or Reflection on demand)
translation: a vector presenting the translation
VectorFitting(vectors) => { normal, center }
@param {Array} vectors: A list of n dimentional vector
@returns {Object} An object containing:
normal: n dimentional vectors presenting the direction of the n dimentional plane
center: n dimentional vectors presenting the n dimentional plane center position
SVD(a, withu, withv, eps, tol) => { u, q, v}
See: https://github.com/danilosalvati/svd-js
MatrixRotationAroundVectorPoint3D(normal, angle, point) => { transform, translation }
@param {Array} normal The direction of rotation axis
@param {Number} angle The angle in radian to rotate
@param {Array} point A point on the rotation axis (optional, if not provided, assume the rotation axis will cross the origin)
@returns {Object} An object containing:
transform: a matrix presenting the rotation
translation: a vector presenting the translation
MatrixMultiply(A, B) => results
Transform(Matrix, Vectors) => transformed vectors
Translate(Translation, Vectors) => translated vectors
MatrixInverse(A) => inverse of A
MatrixTranspose(A) => transpose of A
Determinant(A) => determinant of A
Examples
Procrustes
import { Procrustes } from 'cga-svd'
const source = [
[5520256.7770074, 336354.37003699713, 3167002.52261562],
[5520303.125007548, 336553.002625376, 3166783.194184834],
[5520310.842973152, 336705.55202601955, 3167007.8452485506],
[5520191.48555612, 336523.0133727255, 3166900.0472742445],
];
const target = [
[5520446.76569624, 336367.3208137894, 3166268.4262278015],
[5520524.811239348, 336385.0079539137, 3166133.338472933],
[5520497.071423062, 336518.70720680256, 3166171.1038762117],
[5520446.59762856, 336401.7774899081, 3166164.846668752],
];
const transform = Procrustes(source, target);
console.log(transform);
Output
{
transform: [
[0.48342920386037325, 0.0708119504810417, -0.1895852609563988],
[0.06177151645240301, 0.4158938316122264, 0.3128534788522917],
[0.19272047960195052, -0.3109319654584928, 0.3752876606631539],
],
translation: [3428392.5996840945, -1135322.3833147655, 1018448.1011024625],
}
VectorFitting
import { VectorFitting } from 'cga-svd'
const vectors = [
[5520446.76569624, 336367.3208137894, 3166268.4262278015],
[5520524.811239348, 336385.0079539137, 3166133.338472933],
[5520497.071423062, 336518.70720680256, 3166171.1038762117],
[5520446.59762856, 336401.7774899081, 3166164.846668752],
[5520256.7770074, 336354.37003699713, 3167002.52261562],
[5520303.125007548, 336553.002625376, 3166783.194184834],
[5520310.842973152, 336705.55202601955, 3167007.8452485506],
[5520191.48555612, 336523.0133727255, 3166900.0472742445],
];
const plane = VectorFitting(vectors);
console.log(plane);
Output
{
normal: [-0.9438538172977762, 0.15522796333103916, -0.29162347465955824],
center: [5520372.184566429, 336476.0939406915, 3166553.9155711182],
}
Demo
A 3D web demo that uses these functions: https://cesium-tool.vercel.app/
Procrustes: Calibration -> Alignment(Better) (Click 4 points on grey model and click 4 points(should be the same position) on the other model, then click "Apply")
VectorFitting: Calibration -> Leveling (Click n point on a plane on grey model that is supposed to be horizontal, then click "Apply")