Public
Edited
Mar 24, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function computeRbf() {
let anchors = [
[-gridSize * 10, -gridSize * 10],
[-gridSize * 10, gridSize * 10],
[gridSize * 10, gridSize * 10],
[gridSize * 10, -gridSize * 10]
];
let src = controlPoints.src.concat(anchors);
let dst = controlPoints.dst.concat(anchors);
return RBF(src, dst, distanceFunction.fn, euclideanNorm);
}
Insert cell
rbf = computeRbf()
Insert cell
rbf([1, 2])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
/**
* This is essentially the rbf module by Thibaut Séguy, but modified to use a selectable norm
* See https://github.com/thibauts/rbf
**/
RBF = {
function RBF(points, values, distanceFunction, normFunction, epsilon) {
let epsilon_ = epsilon;

// `identity` here serves as a shorthand to allocate
// the matrix nested array.
const M = numeric.identity(points.length);
const M_ = Matrix.eye(points.length);

// First compute the point to point distance matrix
// to allow computing epsilon if it's not provided
for (let j = 0; j < points.length; j++) {
for (let i = 0; i < points.length; i++) {
M[j][i] = normFunction(points[i], points[j]);
M_.set(j, i, normFunction(points[i], points[j]));
}
}

// if needed, compute espilon as the average distance between points
if (epsilon === undefined) {
epsilon = numeric.sum(M) / (Math.pow(points.length, 2) - points.length);
epsilon_ = sumM(M_) / (Math.pow(points.length, 2) - points.length);
}

// console.log(epsilon, epsilon_);

// update the matrix to reflect the requested distance function
for (let j = 0; j < points.length; j++) {
for (let i = 0; i < points.length; i++) {
M[j][i] = distanceFunction(M[j][i], epsilon);
M_.set(j, i, distanceFunction(M_.get(j, i), epsilon_));
}
}

// reshape values by dimension/component
let valuesByDimension = new Array(2);
for (let i = 0; i < 2; i++) {
valuesByDimension[i] = values.map((value) => value[i]);
}

// Compute basis functions weights by solving
// the linear system of equations for each target component
let w = new Array(2);
let w_ = new Array(2);
const LU = numeric.LU(M);
for (let i = 0; i < 2; i++) {
w[i] = numeric.LUsolve(LU, valuesByDimension[i]);
w_[i] = mlMatrix.solve(M_, Matrix.columnVector(valuesByDimension[i]));
}

// console.log(w, w_);

// The returned interpolant will compute the value at any point
// by summing the weighted contributions of the input points
function interpolant(p) {
let distances = new Array(points.length);
for (let i = 0; i < points.length; i++) {
distances[i] = distanceFunction(normFunction(p, points[i]), epsilon);
}

const distances_ = new Matrix(distances.map((d) => [d]));

let sums = new Array(2);
let sums_ = new Array(2);

for (let i = 0; i < 2; i++) {
sums[i] = numeric.sum(numeric.mul(distances, w[i]));

// console.log(distances, "x", w[i]);
// console.log(distances_, "xx", w_[i]);

sums_[i] = sumM(mulM(distances_, w_[i]));
// sums_[i] = sumM(w_[i].mmul(distances_));
}

// console.log(sums, sums_);

return sums_;
}

interpolant.weights = w_;
return interpolant;
}

return RBF;
}
Insert cell
Insert cell
Insert cell
gcpRbf = {
let src = gcps2.map((gcp) => gcp.image);
let dst = gcps2.map((gcp) => gcp.world);
return RBF(src, dst, distanceFunction.fn, euclideanNorm);
}
Insert cell
gcpRbf([518, 991])
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more