apollo_spline = function apollo_spline(knots, correction) {
const npts = knots.length;
const astart = [], aend = [];
const kstart = [], kend = [];
const dinv = [];
for (let i = npts-1; i >= 0; i--) {
const pm1 = knots[mod(i-1, npts)], p0 = knots[i],
p1 = knots[mod(i+1, npts)], p2 = knots[mod(i+2, npts)];
const inv_dist = dinv[i] = 1 / cabs(csub(p1, p0));
const [a0, a1] = [astart[i], aend[i]] = angles(pm1, p0, p1, p2);
kstart[i] = inv_dist * (Math.sin(a0) - (a1 - a0));
kend[i] = inv_dist * (Math.sin(a1) + (a1 - a0));
}
const segments = [];
for (let i = npts-1; i >= 0; i--) {
const im1 = mod(i-1, npts), ip1 = mod(i+1, npts);
const a0 = astart[i], a1 = aend[i];
let kc0, kc1;
if (+correction == 1) {
const k0m = kend[im1], k0p = kstart[i],
k1m = kend[i], k1p = kstart[ip1],
dm1 = dinv[im1], d0 = dinv[i], d1 = dinv[ip1];
kc0 = (k0p - k0m) / (dm1 + d0);
kc1 = (k1p - k1m) / (d0 + d1);
} else if (+correction == 2) {
kc0 = (a0 - a1), kc1 = (a0 - a1);
} else {
kc0 = kc1 = 0;
}
segments[i] = apollo_segment_adjusted(
knots[i], knots[mod(i+1, npts)], a0, a1, kc0, kc1);
}
return segments;
}