Public
Edited
Sep 7, 2023
Importers
14 stars
Also listed in…
Geo
Projections
Algorithms
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function solve2d(f, MAX_ITERATIONS = 40, eps = 1e-12) {
const abs = Math.abs; // import {abs} from "math"
return function(x, y, a = 0, b = 0) {
let err2, da, db;
for (let i = 0; i < MAX_ITERATIONS; i++) {
const p = f(a, b),
tx = p[0] - x,
ty = p[1] - y;
if (abs(tx) < eps && abs(ty) < eps) break; // we're there!

// backtrack if we overshot
const h = tx * tx + ty * ty;
if (h > err2) {
a -= da /= 2;
b -= db /= 2;
continue;
}
err2 = h;

// partial derivatives
const ea = (a > 0 ? -1 : 1) * eps,
eb = (b > 0 ? -1 : 1) * eps,
pa = f(a + ea, b),
pb = f(a, b + eb),
dxa = (pa[0] - p[0]) / ea,
dya = (pa[1] - p[1]) / ea,
dxb = (pb[0] - p[0]) / eb,
dyb = (pb[1] - p[1]) / eb,
// determinant
D = dyb * dxa - dya * dxb,
// newton step
l = (abs(D) < 0.5 ? 0.5 : 1) / D;
da = (ty * dxb - tx * dyb) * l;
db = (tx * dya - ty * dxa) * l;
a += da;
b += db;

if (abs(da) < eps && abs(db) < eps) break; // we're crawling
}
return [a, b];
};
}
Insert cell
Insert cell
littrow = (a, b) => [Math.sin(a) / Math.cos(b), Math.tan(b) * Math.cos(a)]
Insert cell
inverse = solve2d(littrow)
Insert cell
xy = [2, 1] // our target point
Insert cell
solution = inverse(...xy)
Insert cell
littrow(...solution) // should be reasonably close to xy
Insert cell
Insert cell
littrow(...inverse(1, 3000)) // starting from (a,b)=(0,0), the algorithm has clearly failed to converge
Insert cell
Insert cell
littrow(...inverse(1, 3000, 1500, 3000)) // starting from (1500, 3000), it converges
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