UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

95 lines (73 loc) 2.69 kB
import { assert } from "../../assert.js"; import { max2 } from "../max2.js"; import { min2 } from "../min2.js"; import { spline_hermite3 } from "./spline_hermite3.js"; /** * Compute bounds of a 3-rd degree hermite curve * Note that this is a 1d case solver * Lower bound will be written into result[offset], upper bounds will be written into result[offset+result_stride] * Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve * Differentiation of hermite polynomial is done in WolframAlpha * 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0 * @param {number[]|Float32Array} result * @param {number} result_offset offset into the result array * @param {number} result_stride * @param {number} p0 * @param {number} p1 * @param {number} m0 * @param {number} m1 */ export function spline_hermite3_bounds( result, result_offset, result_stride, p0, p1, m0, m1) { assert.greaterThan(result_stride, 0, 'result_stride must be greater than 0'); assert.isInteger(result_stride, 'result_stride'); const a = 3 * (m0 + m1 + 2 * p0 - 2 * p1); const b = -2 * (2 * m0 + m1 + 3 * p0 - 3 * p1); const c = m0; let min = min2(p0, p1); let max = max2(p0, p1); if (Math.abs(a) < 1e-12) { if (Math.abs(b) >= 1e-12) { const t = -c / b; if (0 < t && t < 1) { const value = spline_hermite3(t, p0, p1, m0, m1); if (value < min) { min = value; } if (value > max) { max = value; } } } } else { const b2ac = b * b - 4 * c * a; const sqrtb2ac = Math.sqrt(b2ac); if (b2ac >= 0) { const t1 = (-b + sqrtb2ac) / (2 * a); if (0 < t1 && t1 < 1) { const value = spline_hermite3(t1, p0, p1, m0, m1); if (value < min) { min = value; } if (value > max) { max = value; } } const t2 = (-b - sqrtb2ac) / (2 * a); if (0 < t2 && t2 < 1) { const value = spline_hermite3(t2, p0, p1, m0, m1); if (value < min) { min = value; } if (value > max) { max = value; } } } } result[result_offset] = min; result[result_offset + result_stride] = max; }