UNPKG

react-native-redash

Version:

Utility library for React Native Reanimated

160 lines (148 loc) 4.79 kB
import Animated from "react-native-reanimated"; import { find } from "../Array"; import { acos, approximates } from "../Math"; const { Value, and, cond, divide, add, multiply, block, greaterThan, eq, lessThan, pow, sqrt, set, sub, cos, not } = Animated; const isRootValidForCubicBezier = (root: Animated.Node<number>) => and(greaterThan(root, 0), lessThan(root, 1)); // pomax.github.io/bezierinfo/#extremities const cuberoot = (v: Animated.Adaptable<number>) => cond( lessThan(v, 0), multiply(pow(multiply(v, -1), 1 / 3), -1), pow(v, 1 / 3) ); const cubicBezierSolve = ( pa: Animated.Adaptable<number>, pb: Animated.Adaptable<number>, pc: Animated.Adaptable<number>, pd: Animated.Adaptable<number> ): Animated.Node<number> => { const a: Animated.Value<number> = new Value(); const b: Animated.Value<number> = new Value(); const c: Animated.Value<number> = new Value(); const d: Animated.Value<number> = new Value(); const root1: Animated.Value<number> = new Value(); const root2: Animated.Value<number> = new Value(); const root3: Animated.Value<number> = new Value(); const q: Animated.Value<number> = new Value(); const q2: Animated.Value<number> = new Value(); const p: Animated.Value<number> = new Value(); const p3: Animated.Value<number> = new Value(); const discriminant: Animated.Value<number> = new Value(); const mp3: Animated.Value<number> = new Value(); const mp33: Animated.Value<number> = new Value(); const r: Animated.Value<number> = new Value(); const t: Animated.Value<number> = new Value(); const cosphi: Animated.Value<number> = new Value(); const phi: Animated.Value<number> = new Value(); const crtr: Animated.Value<number> = new Value(); const t1: Animated.Value<number> = new Value(); const u1: Animated.Value<number> = new Value(); const sd: Animated.Value<number> = new Value(); const v1: Animated.Value<number> = new Value(); const sq: Animated.Value<number> = new Value(); return block([ set(a, add(multiply(3, pa), multiply(-6, pb), multiply(3, pc))), set(b, add(multiply(-3, pa), multiply(3, pb))), set(c, pa), set(d, add(multiply(-1, pa), multiply(3, pb), multiply(-3, pc), pd)), cond( approximates(d, 0), cond( approximates(d, 0), cond(not(approximates(b, 0)), set(root1, divide(multiply(-1, c), b)), [ set(q, sqrt(sub(pow(b, 2), multiply(4, a, c)))), set(root1, divide(sub(q, b), multiply(2, a))), set(root2, divide(sub(multiply(b, -1), q), multiply(2, a))) ]) ), [ set(a, divide(a, d)), set(b, divide(b, d)), set(c, divide(c, d)), set(p, divide(sub(multiply(3, b), multiply(a, a)), 3)), set(p3, divide(p, 3)), set( q, divide( add(multiply(2, a, a, a), multiply(-9, a, b), multiply(27, c)), 27 ) ), set(q2, divide(q, 2)), set(discriminant, add(multiply(q2, q2), multiply(p3, p3, p3))), cond( lessThan(discriminant, 0), [ set(mp3, divide(multiply(p, -1), 3)), set(mp33, multiply(mp3, mp3, mp3)), set(r, sqrt(mp33)), set(t, divide(multiply(q, -1), multiply(2, r))), set( cosphi, cond(lessThan(t, -1), -1, cond(greaterThan(t, 1), 1, t)) ), set(phi, acos(cosphi)), set(crtr, cuberoot(r)), set(t1, multiply(2, crtr)), set(root1, sub(multiply(t1, cos(divide(phi, 3))), divide(a, 3))), set( root2, sub( multiply(t1, cos(divide(add(phi, 2 * Math.PI), 3))), divide(a, 3) ) ), set( root3, sub( multiply(t1, cos(divide(add(phi, 4 * Math.PI), 3))), divide(a, 3) ) ) ], cond( eq(discriminant, 0), [ set( u1, cond( lessThan(q2, 0), cuberoot(multiply(q2, -1)), multiply(cuberoot(q2), -1) ) ), set(root1, sub(multiply(2, u1), divide(a, 3))), set(root2, sub(multiply(-1, u1), divide(a, 3))) ], [ set(sd, sqrt(discriminant)), set(u1, cuberoot(sub(sq, q2))), set(v1, cuberoot(add(sq, q2))), set(root1, sub(u1, v1, divide(a, 3))) ] ) ) ] ), find([root1, root2, root3], isRootValidForCubicBezier) ]); }; export default cubicBezierSolve;