diff --git a/src/v1/AnimationRunners.ts b/src/v1/AnimationRunners.ts deleted file mode 100644 index f148c96..0000000 --- a/src/v1/AnimationRunners.ts +++ /dev/null @@ -1,257 +0,0 @@ -import Animated, { add } from "react-native-reanimated"; - -import type { SpringConfig } from "./Animations"; - -const { - Clock, - Value, - block, - cond, - stopClock, - set, - startClock, - clockRunning, - not, - and, - timing: reTiming, - decay: reDecay, - spring: reSpring, - SpringUtils, -} = Animated; - -const defaultSpringConfig = SpringUtils.makeDefaultConfig(); - -interface AnimateParams { - clock: Animated.Clock; - fn: ( - clock: Animated.Clock, - state: S, - config: C - ) => Animated.Adaptable; - state: S; - config: C; - from: Animated.Adaptable; -} - -interface TimingAnimation { - state: Animated.TimingState; - config: Animated.TimingConfig; -} - -interface SpringAnimation { - state: Animated.SpringState; - config: Animated.SpringConfig; -} - -interface DecayAnimation { - state: Animated.DecayState; - config: Animated.DecayConfig; -} - -type Animation = SpringAnimation | DecayAnimation | TimingAnimation; - -const animate = ({ - fn, - clock, - state, - config, - from, -}: AnimateParams) => - block([ - cond(not(clockRunning(clock)), [ - set(state.finished, 0), - set(state.time, 0), - set(state.position, from), - startClock(clock), - ]), - fn(clock, state, config), - cond(state.finished, stopClock(clock)), - state.position, - ]); - -export interface TimingParams { - clock?: Animated.Clock; - from?: Animated.Adaptable; - to?: Animated.Adaptable; - duration?: Animated.Adaptable; - easing?: (v: Animated.Adaptable) => Animated.Node; -} - -export const timing = (params: TimingParams) => { - const { clock, easing, duration, from, to } = { - clock: new Clock(), - duration: 250, - from: 0, - to: 1, - easing: (v: Animated.Adaptable) => add(v, 0), - ...params, - }; - - const state: Animated.TimingState = { - finished: new Value(0), - position: new Value(0), - time: new Value(0), - frameTime: new Value(0), - }; - - const config = { - toValue: new Value(0), - duration, - easing, - }; - - return block([ - cond(not(clockRunning(clock)), [ - set(config.toValue, to), - set(state.frameTime, 0), - ]), - animate({ - clock, - fn: reTiming, - state, - config, - from, - }), - ]); -}; - -export interface DecayParams { - clock?: Animated.Clock; - from?: Animated.Adaptable; - velocity?: Animated.Adaptable; - deceleration?: Animated.Adaptable; -} - -export const decay = (params: DecayParams) => { - const { clock, from, velocity, deceleration } = { - clock: new Clock(), - velocity: new Value(0), - deceleration: 0.998, - from: 0, - ...params, - }; - - const state: Animated.DecayState = { - finished: new Value(0), - position: new Value(0), - time: new Value(0), - velocity: new Value(0), - }; - - const config: Animated.DecayConfig = { - deceleration, - }; - - return block([ - cond(not(clockRunning(clock)), [set(state.velocity, velocity)]), - animate({ - clock, - fn: reDecay, - state, - config, - from, - }), - ] as ReadonlyArray>); -}; - -export interface SpringParams { - clock?: Animated.Clock; - from?: Animated.Adaptable; - to: Animated.Adaptable; - velocity?: Animated.Adaptable; - config?: SpringConfig; -} - -export const spring = (params: SpringParams) => { - const { - clock, - from, - velocity, - config: springConfig, - to, - } = { - clock: new Clock(), - velocity: new Value(0), - from: 0, - ...params, - }; - - const state: Animated.SpringState = { - finished: new Value(0), - position: new Value(0), - time: new Value(0), - velocity: new Value(0), - }; - - const config = { - ...defaultSpringConfig, - toValue: new Value(0), - ...springConfig, - }; - - return block([ - cond(not(clockRunning(clock)), [ - set(config.toValue, to), - set(state.velocity, velocity), - ]), - animate({ - clock, - fn: reSpring, - state, - config, - from, - }), - ] as ReadonlyArray>); -}; - -export const delay = (node: Animated.Node, duration: number) => { - const clock = new Clock(); - return block([ - timing({ clock, from: 0, to: 1, duration }), - cond(not(clockRunning(clock)), node), - ]); -}; - -export interface LoopProps { - clock?: Animated.Clock; - easing?: (v: Animated.Adaptable) => Animated.Node; - duration?: number; - boomerang?: boolean; - autoStart?: boolean; -} - -export const loop = (loopConfig: LoopProps) => { - const { clock, easing, duration, boomerang, autoStart } = { - clock: new Clock(), - duration: 250, - boomerang: false, - autoStart: true, - easing: (v: Animated.Adaptable) => add(v, 0), - ...loopConfig, - }; - const state = { - finished: new Value(0), - position: new Value(0), - time: new Value(0), - frameTime: new Value(0), - }; - const config = { - toValue: new Value(1), - duration, - easing, - }; - - return block([ - cond(and(not(clockRunning(clock)), autoStart ? 1 : 0), startClock(clock)), - reTiming(clock, state, config), - cond(state.finished, [ - set(state.finished, 0), - set(state.time, 0), - set(state.frameTime, 0), - boomerang - ? set(config.toValue, cond(config.toValue, 0, 1)) - : set(state.position, 0), - ]), - state.position, - ]); -}; diff --git a/src/v1/Animations.ts b/src/v1/Animations.ts deleted file mode 100644 index 1dc0ebd..0000000 --- a/src/v1/Animations.ts +++ /dev/null @@ -1,152 +0,0 @@ -import Animated, { block, defined } from "react-native-reanimated"; - -import { clamp, max, min } from "./Math"; -import type { Matrix3, Transforms2d } from "./Matrix3"; -import { decompose2d } from "./Matrix3"; - -const { - Value, - set, - add, - multiply, - cond, - eq, - abs, - sub, - not, - lessThan, - greaterThan, - divide, - modulo, - proc, -} = Animated; - -export type SpringConfig = Partial>; -export type TimingConfig = Partial>; - -export const mix = proc( - ( - value: Animated.Adaptable, - x: Animated.Adaptable, - y: Animated.Adaptable - ) => add(x, multiply(value, sub(y, x))) -); - -export const step = proc( - (value: Animated.Adaptable, edge: Animated.Adaptable) => - lessThan(value, edge) -); - -export const smoothstep = proc( - ( - value: Animated.Adaptable, - edge0: Animated.Adaptable, - edge1: Animated.Adaptable - ) => { - const t = clamp(divide(sub(value, edge0), sub(edge1, edge0)), 0, 1); - return multiply(t, t, sub(3, multiply(2, t))); - } -); - -export const tween2d = ( - value: Animated.Node, - t1: Matrix3 | Transforms2d, - t2: Matrix3 | Transforms2d -) => { - const d1 = decompose2d(t1); - const d2 = decompose2d(t2); - const translateX = mix(value, d1[0].translateX, d2[0].translateX); - const translateY = mix(value, d1[1].translateY, d2[1].translateY); - const skewX = mix(value, d1[2].rotateZ, d2[2].rotateZ); - const scaleX = mix(value, d1[3].scaleX, d2[3].scaleX); - const scaleY = mix(value, d1[4].scaleY, d2[4].scaleY); - const rotateZ = mix(value, d1[5].rotateZ, d2[5].rotateZ); - return [ - { translateX }, - { translateY }, - { rotateZ: skewX }, - { scaleX }, - { scaleY }, - { rotateZ }, - ] as const; -}; - -// currently diffClamp() from reanimated seems currently buggy because of proc() -export const diff = (v: Animated.Node) => { - const stash = new Value(0); - const prev = new Value(); - return block([ - set(stash, cond(defined(prev), sub(v, prev), 0)), - set(prev, v), - stash, - ]); -}; - -export const diffClamp = ( - a: Animated.Node, - minVal: Animated.Adaptable, - maxVal: Animated.Adaptable -) => { - const value = new Value(); - return set( - value, - min(max(add(cond(defined(value), value, a), diff(a)), minVal), maxVal) - ); -}; - -export const moving = ( - position: Animated.Node, - minPositionDelta = 1e-3, - emptyFrameThreshold = 5 -) => { - const delta = diff(position); - const noMovementFrames = new Value(0); - return cond( - lessThan(abs(delta), minPositionDelta), - [ - set(noMovementFrames, add(noMovementFrames, 1)), - not(greaterThan(noMovementFrames, emptyFrameThreshold)), - ], - [set(noMovementFrames, 0), 1] - ); -}; - -export const snapPoint = ( - value: Animated.Adaptable, - velocity: Animated.Adaptable, - points: Animated.Adaptable[] -) => { - const point = add(value, multiply(0.2, velocity)); - const diffPoint = (p: Animated.Adaptable) => abs(sub(point, p)); - const deltas = points.map((p) => diffPoint(p)); - const minDelta = min(...deltas); - return points.reduce( - (acc, p) => cond(eq(diffPoint(p), minDelta), p, acc), - new Value() - ) as Animated.Node; -}; - -export const addTo = proc( - (value: Animated.Value, node: Animated.Adaptable) => - set(value, add(value, node)) -); - -export const subTo = proc( - (value: Animated.Value, node: Animated.Adaptable) => - set(value, sub(value, node)) -); - -export const multiplyTo = proc( - (value: Animated.Value, node: Animated.Adaptable) => - set(value, multiply(value, node)) -); - -export const divideTo = proc( - (value: Animated.Value, node: Animated.Adaptable) => - set(value, divide(value, node)) -); - -export const moduloTo = proc( - (value: Animated.Value, node: Animated.Adaptable) => - set(value, modulo(value, node)) -); diff --git a/src/v1/Array.ts b/src/v1/Array.ts deleted file mode 100644 index ec6eaae..0000000 --- a/src/v1/Array.ts +++ /dev/null @@ -1,28 +0,0 @@ -import Animated from "react-native-reanimated"; - -const { Value, cond, eq, or } = Animated; - -export const get = ( - array: Animated.Adaptable[], - index: Animated.Adaptable, - notFound: Animated.Node = new Value() -): Animated.Node => - array.reduce( - (acc, v, i) => cond(eq(i, index), v, acc), - notFound - ) as Animated.Node; - -export const contains = ( - values: Animated.Adaptable[], - value: Animated.Adaptable -): Animated.Node<0 | 1> => - values.reduce( - (acc, v) => or(acc, eq(value, v)), - new Value(0) - ) as Animated.Node<0 | 1>; - -export const find = ( - values: Animated.Node[], - fn: (v: Animated.Node) => Animated.Node, - notFound: Animated.Node = new Value() -) => values.reduce((acc, v) => cond(fn(v), v, acc), notFound); diff --git a/src/v1/Colors.ts b/src/v1/Colors.ts deleted file mode 100644 index 98c0508..0000000 --- a/src/v1/Colors.ts +++ /dev/null @@ -1,202 +0,0 @@ -import Animated, { - interpolateNode, - Extrapolate, -} from "react-native-reanimated"; -import { processColor } from "react-native"; - -import { mix } from "./Animations"; -import { clamp, fract } from "./Math"; - -const { add, multiply, abs, round, sub, proc, color, greaterThan, cond } = - Animated; - -// type Color = Animated.Adaptable | Animated.Adaptable; -type StaticColor = string | number; - -export const opacity = (c: number) => ((c >> 24) & 255) / 255; -export const red = (c: number) => (c >> 16) & 255; -export const green = (c: number) => (c >> 8) & 255; -export const blue = (c: number) => c & 255; - -export const hsv2rgb = ( - h: Animated.Adaptable, - s: Animated.Adaptable, - v: Animated.Adaptable -) => { - // vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - const K = { - x: 1, - y: 2 / 3, - z: 1 / 3, - w: 3, - }; - // vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - const p = { - x: abs(sub(multiply(fract(add(h, K.x)), 6), K.w)), - y: abs(sub(multiply(fract(add(h, K.y)), 6), K.w)), - z: abs(sub(multiply(fract(add(h, K.z)), 6), K.w)), - }; - // return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); - const rgb = { - x: multiply(v, mix(s, K.x, clamp(sub(p.x, K.x), 0, 1))), - y: multiply(v, mix(s, K.x, clamp(sub(p.y, K.x), 0, 1))), - z: multiply(v, mix(s, K.x, clamp(sub(p.z, K.x), 0, 1))), - }; - return { - r: round(multiply(rgb.x, 255)), - g: round(multiply(rgb.y, 255)), - b: round(multiply(rgb.z, 255)), - }; -}; - -export const hsv2color = proc( - ( - h: Animated.Adaptable, - s: Animated.Adaptable, - v: Animated.Adaptable - ) => { - const { r, g, b } = hsv2rgb(h, s, v); - return color(r, g, b) as Animated.Node; - } -); - -export const colorForBackground = proc( - ( - r: Animated.Adaptable, - g: Animated.Adaptable, - b: Animated.Adaptable - ) => { - const L = add(multiply(0.299, r), multiply(0.587, g), multiply(0.114, b)); - return cond( - greaterThan(L, 186), - color(0, 0, 0) as Animated.Node, - color(255, 255, 255) as Animated.Node - ); - } -); - -const rgbToHsv = (c: number) => { - const r = red(c) / 255; - const g = green(c) / 255; - const b = blue(c) / 255; - - const ma = Math.max(r, g, b); - const mi = Math.min(r, g, b); - let h = 0; - const v = ma; - - const d = ma - mi; - const s = ma === 0 ? 0 : d / ma; - if (ma === mi) { - h = 0; // achromatic - } else { - switch (ma) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - default: // do nothing - } - h /= 6; - } - return { h, s, v }; -}; - -const interpolateColorsHSV = ( - animationValue: Animated.Adaptable, - inputRange: readonly Animated.Adaptable[], - colors: number[] -): Animated.Node => { - const colorsAsHSV = colors.map((c) => rgbToHsv(c)); - const h = interpolateNode(animationValue, { - inputRange, - outputRange: colorsAsHSV.map((c) => c.h), - extrapolate: Extrapolate.CLAMP, - }); - const s = interpolateNode(animationValue, { - inputRange, - outputRange: colorsAsHSV.map((c) => c.s), - extrapolate: Extrapolate.CLAMP, - }); - const v = interpolateNode(animationValue, { - inputRange, - outputRange: colorsAsHSV.map((c) => c.v), - extrapolate: Extrapolate.CLAMP, - }); - return hsv2color(h, s, v); -}; - -const interpolateColorsRGB = ( - animationValue: Animated.Adaptable, - inputRange: readonly Animated.Adaptable[], - colors: number[] -) => { - const r = round( - interpolateNode(animationValue, { - inputRange, - outputRange: colors.map((c) => red(c)), - extrapolate: Extrapolate.CLAMP, - }) - ); - const g = round( - interpolateNode(animationValue, { - inputRange, - outputRange: colors.map((c) => green(c)), - extrapolate: Extrapolate.CLAMP, - }) - ); - const b = round( - interpolateNode(animationValue, { - inputRange, - outputRange: colors.map((c) => blue(c)), - extrapolate: Extrapolate.CLAMP, - }) - ); - const a = interpolateNode(animationValue, { - inputRange, - outputRange: colors.map((c) => opacity(c)), - extrapolate: Extrapolate.CLAMP, - }); - - return color(r, g, b, a) as Animated.Node; -}; - -interface ColorInterpolationConfig { - inputRange: readonly Animated.Adaptable[]; - outputRange: StaticColor[]; -} - -export const interpolateColor = ( - value: Animated.Adaptable, - config: ColorInterpolationConfig, - colorSpace: "hsv" | "rgb" = "rgb" -): Animated.Node => { - const { inputRange } = config; - const outputRange = config.outputRange.map((c) => - typeof c === "number" ? c : (processColor(c) as number) - ); - if (colorSpace === "hsv") { - return interpolateColorsHSV(value, inputRange, outputRange); - } - return interpolateColorsRGB(value, inputRange, outputRange); -}; - -export const mixColor = ( - value: Animated.Adaptable, - color1: StaticColor, - color2: StaticColor, - colorSpace: "hsv" | "rgb" = "rgb" -) => - interpolateColor( - value, - { - inputRange: [0, 1], - outputRange: [color1, color2], - }, - colorSpace - ); diff --git a/src/v1/Coordinates.ts b/src/v1/Coordinates.ts deleted file mode 100644 index 7f11f36..0000000 --- a/src/v1/Coordinates.ts +++ /dev/null @@ -1,41 +0,0 @@ -import Animated from "react-native-reanimated"; - -import { atan2 } from "./Math"; -import type { Vector } from "./Vectors"; - -const { sub, multiply, add, cos, sin, pow, sqrt } = Animated; - -export interface PolarPoint { - theta: Animated.Adaptable; - radius: Animated.Adaptable; -} - -export const canvas2Cartesian = ({ x, y }: Vector, center: Vector) => { - return { - x: sub(x, center.x), - y: multiply(sub(y, center.y), -1), - }; -}; - -export const cartesian2Canvas = ({ x, y }: Vector, center: Vector) => ({ - x: add(x, center.x), - y: add(multiply(y, -1), center.y), -}); - -export const cartesian2Polar = ({ x, y }: Vector) => { - return { - theta: atan2(y, x), - radius: sqrt(add(pow(x, 2), pow(y, 2))), - }; -}; - -export const polar2Cartesian = ({ theta, radius }: PolarPoint) => ({ - x: multiply(radius, cos(theta)), - y: multiply(radius, sin(theta)), -}); - -export const polar2Canvas = ({ theta, radius }: PolarPoint, center: Vector) => - cartesian2Canvas(polar2Cartesian({ theta, radius }), center); - -export const canvas2Polar = ({ x, y }: Vector, center: Vector) => - cartesian2Polar(canvas2Cartesian({ x, y }, center)); diff --git a/src/v1/Gesture.ts b/src/v1/Gesture.ts deleted file mode 100644 index 47c83ab..0000000 --- a/src/v1/Gesture.ts +++ /dev/null @@ -1,372 +0,0 @@ -import Animated, { diff, lessThan, or } from "react-native-reanimated"; -import type { - FlingGestureHandlerEventExtra, - ForceTouchGestureHandlerEventExtra, - GestureHandlerStateChangeNativeEvent, - LongPressGestureHandlerEventExtra, - PanGestureHandlerEventExtra, - PinchGestureHandlerEventExtra, - RotationGestureHandlerEventExtra, - TapGestureHandlerEventExtra, -} from "react-native-gesture-handler"; -import { State } from "react-native-gesture-handler"; -import { Platform } from "react-native"; - -import { snapPoint } from "./Animations"; -import { vec } from "./Vectors"; - -const { - proc, - Clock, - Value, - event, - add, - block, - cond, - eq, - multiply, - set, - stopClock, - and, - not, - clockRunning, - startClock, - neq, - call, - decay: reDecay, - spring: reSpring, - onChange, - debug, -} = Animated; - -// See: https://github.com/kmagiera/react-native-gesture-handler/issues/553 -export const pinchBegan = proc((state: Animated.Node) => - Platform.OS === "android" - ? cond(eq(diff(state), State.ACTIVE - State.BEGAN), eq(state, State.ACTIVE)) - : eq(state, State.BEGAN) -); - -export const pinchActive = proc( - (state: Animated.Node, numberOfPointers: Animated.Node) => - and( - eq(state, State.ACTIVE), - eq(numberOfPointers, 2), - Platform.OS === "android" ? not(pinchBegan(state)) : 1 - ) -); - -export const pinchEnd = proc( - (state: Animated.Node, numberOfPointers: Animated.Node) => - Platform.OS === "android" - ? or(eq(state, State.END), lessThan(numberOfPointers, 2)) - : eq(state, State.END) -); - -export const withScaleOffset = ( - value: Animated.Node, - state: Animated.Node, - offset: Animated.Value = new Value(1) -) => - cond( - eq(state, State.END), - [set(offset, multiply(offset, value)), offset], - multiply(offset, value) - ); - -export const withOffset = ( - value: Animated.Node, - state: Animated.Node, - offset: Animated.Value = new Value(0) -) => - cond( - eq(state, State.END), - [set(offset, add(offset, value)), offset], - add(offset, value) - ); - -interface PrivateSpringConfig extends Animated.SpringConfig { - toValue: Animated.Value; -} - -type SpringConfig = Omit; - -export interface WithSpringParams { - value: Animated.Adaptable; - velocity: Animated.Adaptable; - state: Animated.Node; - snapPoints: Animated.Adaptable[]; - offset?: Animated.Value; - config?: SpringConfig; - onSnap?: (value: readonly number[]) => void; -} - -export const withSpring = (props: WithSpringParams) => { - const { - value, - velocity, - state, - snapPoints, - offset, - config: springConfig, - onSnap, - } = { - offset: new Value(0), - ...props, - }; - const clock = new Clock(); - const springState: Animated.SpringState = { - finished: new Value(0), - velocity: new Value(0), - position: new Value(0), - time: new Value(0), - }; - - const config: PrivateSpringConfig = { - toValue: new Value(0), - damping: 6, - mass: 1, - stiffness: 64, - overshootClamping: false, - restSpeedThreshold: 0.01, - restDisplacementThreshold: 0.01, - ...springConfig, - }; - - const gestureAndAnimationIsOver = new Value(1); - const isSpringInterrupted = and(eq(state, State.BEGAN), clockRunning(clock)); - const finishSpring = [ - set(offset, springState.position), - stopClock(clock), - set(gestureAndAnimationIsOver, 1), - ]; - const snap = onSnap - ? [cond(clockRunning(clock), call([springState.position], onSnap))] - : []; - return block([ - cond(isSpringInterrupted, finishSpring), - cond(gestureAndAnimationIsOver, set(springState.position, offset)), - cond(neq(state, State.END), [ - set(gestureAndAnimationIsOver, 0), - set(springState.finished, 0), - set(springState.position, add(offset, value)), - ]), - cond(and(eq(state, State.END), not(gestureAndAnimationIsOver)), [ - cond(and(not(clockRunning(clock)), not(springState.finished)), [ - set(springState.velocity, velocity), - set(springState.time, 0), - set( - config.toValue, - snapPoint(springState.position, velocity, snapPoints) - ), - startClock(clock), - ]), - reSpring(clock, springState, config), - cond(springState.finished, [...snap, ...finishSpring]), - ]), - springState.position, - ]); -}; - -interface WithDecayParams { - value: Animated.Adaptable; - velocity: Animated.Adaptable; - state: Animated.Node; - offset?: Animated.Value; - deceleration?: number; -} - -export const withDecay = (config: WithDecayParams) => { - const { value, velocity, state, offset, deceleration } = { - offset: new Value(0), - deceleration: 0.998, - ...config, - }; - const clock = new Clock(); - const decayState = { - finished: new Value(0), - velocity: new Value(0), - position: new Value(0), - time: new Value(0), - }; - - const isDecayInterrupted = and(eq(state, State.BEGAN), clockRunning(clock)); - const finishDecay = [set(offset, decayState.position), stopClock(clock)]; - - return block([ - cond(isDecayInterrupted, finishDecay), - cond(neq(state, State.END), [ - set(decayState.finished, 0), - set(decayState.position, add(offset, value)), - ]), - cond(eq(state, State.END), [ - cond(and(not(clockRunning(clock)), not(decayState.finished)), [ - set(decayState.velocity, velocity), - set(decayState.time, 0), - startClock(clock), - ]), - reDecay(clock, decayState, { deceleration }), - cond(decayState.finished, finishDecay), - ]), - decayState.position, - ]); -}; - -export const onScrollEvent = (contentOffset: { - x?: Animated.Node; - y?: Animated.Node; -}) => - event([ - { - nativeEvent: { - contentOffset, - }, - }, - ]); - -type NativeEvent = GestureHandlerStateChangeNativeEvent & - ( - | PanGestureHandlerEventExtra - | TapGestureHandlerEventExtra - | LongPressGestureHandlerEventExtra - | RotationGestureHandlerEventExtra - | FlingGestureHandlerEventExtra - | PinchGestureHandlerEventExtra - | ForceTouchGestureHandlerEventExtra - ); - -type Adaptable = { [P in keyof T]: Animated.Adaptable }; - -export const onGestureEvent = ( - nativeEvent: Partial> -) => { - const gestureEvent = event([{ nativeEvent }]); - return { - onHandlerStateChange: gestureEvent, - onGestureEvent: gestureEvent, - }; -}; - -export const tapGestureHandler = () => { - const state = new Value(State.UNDETERMINED); - const position = vec.createValue(0); - const absolutePosition = vec.createValue(0); - const gestureHandler = onGestureEvent({ - state, - x: position.x, - y: position.y, - absoluteX: absolutePosition.x, - absoluteY: absolutePosition.y, - }); - return { - gestureHandler, - position, - absolutePosition, - state, - }; -}; - -export const panGestureHandler = () => { - const position = vec.createValue(0); - const translation = vec.createValue(0); - const velocity = vec.createValue(0); - const state = new Value(State.UNDETERMINED); - const gestureHandler = onGestureEvent({ - x: position.x, - translationX: translation.x, - velocityX: velocity.x, - y: position.y, - translationY: translation.y, - velocityY: velocity.y, - state, - }); - return { - position, - translation, - velocity, - state, - gestureHandler, - }; -}; - -export const pinchGestureHandler = () => { - const focal = vec.createValue(0, 0); - const scale = new Value(1); - const numberOfPointers = new Value(0); - const state = new Value(State.UNDETERMINED); - const gestureHandler = onGestureEvent({ - numberOfPointers, - focalX: focal.x, - focalY: focal.y, - scale, - state, - }); - return { - numberOfPointers, - scale, - state, - gestureHandler, - focal, - }; -}; - -export const rotationGestureHandler = () => { - const anchor = vec.createValue(0, 0); - const rotation = new Value(0); - const state = new Value(State.UNDETERMINED); - const gestureHandler = onGestureEvent({ - anchorX: anchor.x, - anchorY: anchor.y, - rotation, - state, - }); - return { - rotation, - state, - gestureHandler, - anchor, - }; -}; - -export const scrollHandler = () => { - const x = new Value(0); - const y = new Value(0); - const onScroll = onScrollEvent({ x, y }); - return { - x, - y, - scrollHandler: { - onScroll, - scrollEventThrottle: 1, - }, - }; -}; - -export const debugGestureState = ( - label: string, - state: Animated.Node -) => { - const d = (value: string): Animated.Node => - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - debug(label, new Value(value)); - return onChange( - state, - cond( - eq(state, State.UNDETERMINED), - d("UNDETERMINED"), - cond( - eq(state, State.BEGAN), - d("BEGAN"), - cond( - eq(state, State.ACTIVE), - d("ACTIVE"), - cond( - eq(state, State.END), - d("END"), - cond(eq(state, State.CANCELLED), d("CANCELLED"), d("FAILED")) - ) - ) - ) - ) - ); -}; diff --git a/src/v1/Hooks.ts b/src/v1/Hooks.ts deleted file mode 100644 index ed9fa12..0000000 --- a/src/v1/Hooks.ts +++ /dev/null @@ -1,164 +0,0 @@ -import Animated from "react-native-reanimated"; -import { useRef } from "react"; - -import { - onGestureEvent, - panGestureHandler, - pinchGestureHandler, - rotationGestureHandler, - tapGestureHandler, - scrollHandler, -} from "./Gesture"; -import type { Vector } from "./Vectors"; -import { vec } from "./Vectors"; -import { loop } from "./AnimationRunners"; - -const { Clock, Value, diff, set, useCode, debug, block } = Animated; - -export function useConst(initialValue: T | (() => T)): T { - const ref = useRef<{ value: T }>(); - if (ref.current === undefined) { - // Box the value in an object so we can tell if it's initialized even if the initializer - // returns/is undefined - ref.current = { - value: - typeof initialValue === "function" - ? // eslint-disable-next-line @typescript-eslint/ban-types - (initialValue as Function)() - : initialValue, - }; - } - return ref.current.value; -} - -export const useGestureHandler = ( - nativeEvent: Parameters[0] -) => useConst(() => onGestureEvent(nativeEvent)); - -export const usePanGestureHandler = () => useConst(() => panGestureHandler()); -export const useRotationGestureHandler = () => - useConst(() => rotationGestureHandler()); -export const usePinchGestureHandler = () => - useConst(() => pinchGestureHandler()); -export const useTapGestureHandler = () => useConst(() => tapGestureHandler()); -export const useScrollHandler = () => useConst(() => scrollHandler()); - -type Atomic = string | number | boolean; - -export const useVector = ( - ...defaultValues: Parameters -) => useConst(() => vec.createValue(...defaultValues)); - -type P = Parameters; -type R = Vector>; -type UseVectors = { - (...v: [P]): [R]; - (...v: [P, P]): [R, R]; - (...v: [P, P, P]): [R, R, R]; - (...v: [P, P, P, P]): [R, R, R, R]; - (...v: [P, P, P, P, P]): [R, R, R, R, R]; - (...v: [P, P, P, P, P, P]): [R, R, R, R, R, R]; - (...v: P[]): R[]; -}; - -export const useVectors = (( - ...defaultValues: Parameters[] -) => - useConst(() => - defaultValues.map((values) => vec.createValue(...values)) - )) as unknown as UseVectors; - -export const useClock = () => useConst(() => new Clock()); - -export const useValue = (value: V) => - useConst(() => new Value(value)); - -export const usePhysicsState = () => ({ - time: useValue(0), - position: useValue(0), - velocity: useValue(0), - finished: useValue(0), -}); - -export const useSpringConfig = ( - config: Partial> -) => ({ - toValue: useValue(0), - damping: 15, - mass: 1, - stiffness: 150, - overshootClamping: false, - restSpeedThreshold: 1, - restDisplacementThreshold: 1, - ...config, -}); - -export const useLoop = (duration = 1000, boomerang = true) => { - const progress = useValue(0); - useCode(() => set(progress, loop({ duration, boomerang })), [progress]); - return progress; -}; - -type UseValues = { - (v: V): [Animated.Value]; - (v1: V1, v2: V2): [ - Animated.Value, - Animated.Value - ]; - ( - v1: V1, - v2: V2, - v3: V3 - ): [Animated.Value, Animated.Value, Animated.Value]; - ( - v1: V1, - v2: V2, - v3: V3, - v4: V4 - ): [ - Animated.Value, - Animated.Value, - Animated.Value, - Animated.Value - ]; - < - V1 extends Atomic, - V2 extends Atomic, - V3 extends Atomic, - V4 extends Atomic, - V5 extends Atomic - >( - v1: V1, - v2: V2, - v3: V3, - v4: V4, - v5: V5 - ): [ - Animated.Value, - Animated.Value, - Animated.Value, - Animated.Value, - Animated.Value - ]; - (...values: V[]): Animated.Value[]; -}; - -export const useValues = ((...values: [V, ...V[]]) => - useConst(() => values.map((v) => new Value(v)))) as unknown as UseValues; - -export const useClocks = (numberOfClocks: number): Animated.Clock[] => - useConst(() => new Array(numberOfClocks).fill(0).map(() => new Clock())); - -export const useDiff = (node: Animated.Node) => { - const dDiff = useValue(0); - useCode(() => set(dDiff, diff(node)), [dDiff, node]); - return dDiff; -}; - -export const useDebug = (values: { [key: string]: Animated.Node }) => { - const keys = Object.keys(values); - useCode( - () => block(keys.map((name) => debug(name, values[name]))), - [keys, values] - ); -}; diff --git a/src/v1/Math.ts b/src/v1/Math.ts deleted file mode 100644 index f1d9b03..0000000 --- a/src/v1/Math.ts +++ /dev/null @@ -1,148 +0,0 @@ -import Animated from "react-native-reanimated"; - -const { - eq, - set, - cond, - atan, - add, - multiply, - lessThan, - abs, - divide, - sub, - min: min2, - max: max2, - round: reRound, - greaterThan, - pow, - and, - greaterOrEq, - lessOrEq, - proc, - floor, -} = Animated; - -export const bin = (value: boolean): 0 | 1 => (value ? 1 : 0); - -export const fract = (x: Animated.Adaptable) => sub(x, floor(x)); - -export const sign = (x: Animated.Adaptable) => - cond(lessThan(x, 0), -1, cond(eq(x, 0), 0, 1)); - -export const min = (...args: Animated.Adaptable[]) => - args.reduce((acc, arg) => min2(acc, arg)); - -export const max = (...args: Animated.Adaptable[]) => - args.reduce((acc, arg) => max2(acc, arg)); - -export const minus = (x: Animated.Node) => multiply(-1, x); - -export const avg = ( - ...v: [ - Animated.Adaptable, - Animated.Adaptable, - ...Animated.Adaptable[] - ] -) => divide(add(...v), v.length); - -export const clamp = proc( - ( - value: Animated.Adaptable, - lowerBound: Animated.Adaptable, - upperBound: Animated.Adaptable - ): Animated.Node => min2(max2(lowerBound, value), upperBound) -); - -export const between = ( - value: Animated.Node, - lowerBound: Animated.Adaptable, - upperBound: Animated.Adaptable, - inclusive = true -) => { - if (inclusive) { - return and(greaterOrEq(value, lowerBound), lessOrEq(value, upperBound)); - } - return and(greaterThan(value, lowerBound), lessThan(value, upperBound)); -}; - -export const approximates = proc( - ( - a: Animated.Adaptable, - b: Animated.Adaptable, - precision: Animated.Adaptable = 0.001 - ) => lessThan(abs(sub(a, b)), precision) -); - -export const toRad = proc( - (deg: Animated.Adaptable): Animated.Node => - multiply(deg, Math.PI / 180) -); - -export const toDeg = proc( - (rad: Animated.Adaptable): Animated.Node => - multiply(rad, 180 / Math.PI) -); - -// https://en.wikipedia.org/wiki/Atan2 -// https://www.gamedev.net/forums/topic/441464-manually-implementing-atan2-or-atan/ -// https://developer.download.nvidia.com/cg/atan2.html -// https://www.medcalc.org/manual/atan2_function.php -export const atan2 = proc( - (y: Animated.Adaptable, x: Animated.Adaptable) => { - const a = atan(divide(y, x)); - const { PI } = Math; - return cond( - greaterThan(x, 0), - a, - cond( - and(lessThan(x, 0), greaterOrEq(y, 0)), - add(a, PI), - cond( - and(lessThan(x, 0), lessThan(y, 0)), - sub(a, PI), - cond( - and(eq(x, 0), greaterThan(y, 0)), - PI / 2, - cond(and(eq(x, 0), lessThan(y, 0)), -PI / 2, 0) - ) - ) - ) - ); - } -); - -export const cubicBezier = proc( - ( - t: Animated.Adaptable, - p0: Animated.Adaptable, - p1: Animated.Adaptable, - p2: Animated.Adaptable, - p3: Animated.Adaptable - ): Animated.Node => { - const term = sub(1, t); - const a = multiply(1, pow(term, 3), pow(t, 0), p0); - const b = multiply(3, pow(term, 2), pow(t, 1), p1); - const c = multiply(3, pow(term, 1), pow(t, 2), p2); - const d = multiply(1, pow(term, 0), pow(t, 3), p3); - return add(a, b, c, d); - } -); - -export const round = proc( - ( - value: Animated.Adaptable, - precision: Animated.Adaptable = 0 - ) => { - const p = pow(10, precision); - return divide(reRound(multiply(value, p)), p); - } -); - -export const inc = proc((value: Animated.Value) => - set(value, add(value, 1)) -); - -export const dec = proc((value: Animated.Value) => - set(value, sub(value, 1)) -); diff --git a/src/v1/Matrix3.ts b/src/v1/Matrix3.ts deleted file mode 100644 index 37d7e22..0000000 --- a/src/v1/Matrix3.ts +++ /dev/null @@ -1,252 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import Animated from "react-native-reanimated"; - -import { atan2 } from "./Math"; -import type { Vector } from "./Vectors"; - -const { add, multiply, sqrt, cos, sin, sub, divide, pow, tan } = Animated; - -export type Vec3 = readonly [ - Animated.Adaptable, - Animated.Adaptable, - Animated.Adaptable -]; - -export type Matrix3 = readonly [Vec3, Vec3, Vec3]; - -type Transform2dName = - | "translateX" - | "translateY" - | "scale" - | "skewX" - | "skewY" - | "scaleX" - | "scaleY" - | "rotateZ" - | "rotate"; -type Transformations = { - [Name in Transform2dName]: Animated.Adaptable; -}; -export type Transforms2d = ( - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick -)[]; - -const exhaustiveCheck = (a: never): never => { - throw new Error(`Unexhaustive handling for ${a}`); -}; - -const identityMatrix: Matrix3 = [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], -]; - -const translateXMatrix = (x: Animated.Adaptable): Matrix3 => [ - [1, 0, x], - [0, 1, 0], - [0, 0, 1], -]; - -const translateYMatrix = (y: Animated.Adaptable): Matrix3 => [ - [1, 0, 0], - [0, 1, y], - [0, 0, 1], -]; - -const scaleMatrix = (s: Animated.Adaptable): Matrix3 => [ - [s, 0, 0], - [0, s, 0], - [0, 0, 1], -]; - -const scaleXMatrix = (s: Animated.Adaptable): Matrix3 => [ - [s, 0, 0], - [0, 1, 0], - [0, 0, 1], -]; - -const scaleYMatrix = (s: Animated.Adaptable): Matrix3 => [ - [1, 0, 0], - [0, s, 0], - [0, 0, 1], -]; - -const skewXMatrix = (s: Animated.Adaptable): Matrix3 => [ - [1, tan(s), 0], - [0, 1, 0], - [0, 0, 1], -]; - -const skewYMatrix = (s: Animated.Adaptable): Matrix3 => [ - [1, 0, 0], - [tan(s), 1, 0], - [0, 0, 1], -]; - -const rotateZMatrix = (r: Animated.Adaptable): Matrix3 => [ - [cos(r), multiply(-1, sin(r)), 0], - [sin(r), cos(r), 0], - [0, 0, 1], -]; - -export const dot3 = (row: Vec3, col: Vec3) => - add( - multiply(row[0], col[0]), - multiply(row[1], col[1]), - multiply(row[2], col[2]) - ); - -export const matrixVecMul3 = (m: Matrix3, v: Vec3) => - [dot3(m[0], v), dot3(m[1], v), dot3(m[2], v)] as const; - -export const multiply3 = (m1: Matrix3, m2: Matrix3) => { - const col0 = [m2[0][0], m2[1][0], m2[2][0]] as const; - const col1 = [m2[0][1], m2[1][1], m2[2][1]] as const; - const col2 = [m2[0][2], m2[1][2], m2[2][2]] as const; - return [ - [dot3(m1[0], col0), dot3(m1[0], col1), dot3(m1[0], col2)], - [dot3(m1[1], col0), dot3(m1[1], col1), dot3(m1[1], col2)], - [dot3(m1[2], col0), dot3(m1[2], col1), dot3(m1[2], col2)], - ] as const; -}; - -export const processTransform2d = (transforms: Transforms2d) => - transforms.reduce((acc, transform) => { - const key = Object.keys(transform)[0] as Transform2dName; - const value = (transform as Pick)[key]; - if (key === "translateX") { - return multiply3(acc, translateXMatrix(value)); - } - if (key === "translateY") { - return multiply3(acc, translateYMatrix(value)); - } - if (key === "scale") { - return multiply3(acc, scaleMatrix(value)); - } - if (key === "scaleX") { - return multiply3(acc, scaleXMatrix(value)); - } - if (key === "scaleY") { - return multiply3(acc, scaleYMatrix(value)); - } - if (key === "skewX") { - return multiply3(acc, skewXMatrix(value)); - } - if (key === "skewY") { - return multiply3(acc, skewYMatrix(value)); - } - if (key === "rotate" || key === "rotateZ") { - return multiply3(acc, rotateZMatrix(value)); - } - return exhaustiveCheck(key); - }, identityMatrix); - -const isMatrix3 = (arg: Matrix3 | Transforms2d): arg is Matrix3 => - arg.length === 3 && arg[0] instanceof Array; - -// https://math.stackexchange.com/questions/13150/extracting-rotation-scale-values-from-2d-transformation-matrix -export const decompose2d = (arg: Matrix3 | Transforms2d) => { - const m = isMatrix3(arg) ? arg : processTransform2d(arg); - const a = m[0][0]; - const b = m[1][0]; - const c = m[0][1]; - const d = m[1][1]; - const translateX = m[0][2] as Animated.Node; - const translateY = m[1][2] as Animated.Node; - const E = divide(add(a, d), 2); - const F = divide(sub(a, d), 2); - const G = divide(add(c, b), 2); - const H = divide(sub(c, b), 2); - const Q = sqrt(add(pow(E, 2), pow(H, 2))); - const R = sqrt(add(pow(F, 2), pow(G, 2))); - const scaleX = add(Q, R); - const scaleY = sub(Q, R); - const a1 = atan2(G, F); - const a2 = atan2(H, E); - const theta = divide(sub(a2, a1), 2); - const phi = divide(add(a2, a1), 2); - return [ - { translateX }, - { translateY }, - { rotateZ: multiply(-1, theta) }, - { scaleX }, - { scaleY }, - { rotateZ: multiply(-1, phi) }, - ] as const; -}; - -const adjugate = (m: Matrix3) => { - return [ - [ - sub(multiply(m[1][1], m[2][2]), multiply(m[1][2], m[2][1])), - sub(multiply(m[0][2], m[2][1]), multiply(m[0][1], m[2][2])), - sub(multiply(m[0][1], m[1][2]), multiply(m[0][2], m[1][1])), - ], - [ - sub(multiply(m[1][2], m[2][0]), multiply(m[1][0], m[2][2])), - sub(multiply(m[0][0], m[2][2]), multiply(m[0][2], m[2][0])), - sub(multiply(m[0][2], m[1][0]), multiply(m[0][0], m[1][2])), - ], - [ - sub(multiply(m[1][0], m[2][1]), multiply(m[1][1], m[2][0])), - sub(multiply(m[0][1], m[2][0]), multiply(m[0][0], m[2][1])), - sub(multiply(m[0][0], m[1][1]), multiply(m[0][1], m[1][0])), - ], - ] as const; -}; - -interface Quadrilateral { - p1: Vector; - p2: Vector; - p3: Vector; - p4: Vector; -} - -interface Parameters { - canvas: Quadrilateral; - projected: Quadrilateral; -} - -const basisToPoints = ({ p1, p2, p3, p4 }: Quadrilateral) => { - const m = [ - [p1.x, p2.x, p3.x], - [p1.y, p2.y, p3.y], - [1, 1, 1], - ] as const; - const v = matrixVecMul3(adjugate(m), [p4.x, p4.y, 1]); - return multiply3(m, [ - [v[0], 0, 0], - [0, v[1], 0], - [0, 0, v[2]], - ]); -}; - -// https://math.stackexchange.com/questions/296794/finding-the-transform-matrix-from-4-projected-points-with-javascript -// https://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/ -// http://jsfiddle.net/dFrHS/1/ -export const transform2d = (params: Parameters) => { - const s = basisToPoints(params.canvas); - const d = basisToPoints(params.projected); - const t = multiply3(d, adjugate(s)); - return [ - [ - divide(t[0][0], t[2][2]), - divide(t[0][1], t[2][2]), - divide(t[0][2], t[2][2]), - ], - [ - divide(t[1][0], t[2][2]), - divide(t[1][1], t[2][2]), - divide(t[1][2], t[2][2]), - ], - [divide(t[2][0], t[2][2]), divide(t[2][1], t[2][2]), 1], - ] as const; -}; diff --git a/src/v1/Matrix4.ts b/src/v1/Matrix4.ts deleted file mode 100644 index 04c683e..0000000 --- a/src/v1/Matrix4.ts +++ /dev/null @@ -1,248 +0,0 @@ -import Animated, { tan } from "react-native-reanimated"; - -const { add, multiply, cos, sin, divide } = Animated; - -export type Vec4 = readonly [ - Animated.Adaptable, - Animated.Adaptable, - Animated.Adaptable, - Animated.Adaptable -]; - -export type Matrix4 = readonly [Vec4, Vec4, Vec4, Vec4]; - -type Transform3dName = - | "translateX" - | "translateY" - | "translateZ" - | "scale" - | "scaleX" - | "scaleY" - | "skewX" - | "skewY" - | "rotateZ" - | "rotate" - | "perspective" - | "rotateX" - | "rotateY" - | "rotateZ" - | "matrix"; -type Transformations = { - [Name in Transform3dName]: Name extends "matrix" - ? Matrix4 - : Animated.Adaptable; -}; -export type Transforms3d = ( - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick - | Pick -)[]; - -const exhaustiveCheck = (a: never): never => { - throw new Error(`Unexhaustive handling for ${a}`); -}; - -export const identityMatrix4: Matrix4 = [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const translateXMatrix = (x: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, x], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const translateYMatrix = (y: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [0, 1, 0, y], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const translateZMatrix = (z: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, z], - [0, 0, 0, 1], -]; - -const scaleMatrix = (s: Animated.Adaptable): Matrix4 => [ - [s, 0, 0, 0], - [0, s, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const scaleXMatrix = (s: Animated.Adaptable): Matrix4 => [ - [s, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const skewXMatrix = (s: Animated.Adaptable): Matrix4 => [ - [1, tan(s), 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const skewYMatrix = (s: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [tan(s), 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const scaleYMatrix = (s: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [0, s, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -const perspectiveMatrix = (p: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, divide(-1, p), 1], -]; - -const rotateXMatrix = (r: Animated.Adaptable): Matrix4 => [ - [1, 0, 0, 0], - [0, cos(r), multiply(-1, sin(r)), 0], - [0, sin(r), cos(r), 0], - [0, 0, 0, 1], -]; - -const rotateYMatrix = (r: Animated.Adaptable): Matrix4 => [ - [cos(r), 0, sin(r), 0], - [0, 1, 0, 0], - [multiply(-1, sin(r)), 0, cos(r), 0], - [0, 0, 0, 1], -]; - -const rotateZMatrix = (r: Animated.Adaptable): Matrix4 => [ - [cos(r), multiply(-1, sin(r)), 0, 0], - [sin(r), cos(r), 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], -]; - -export const dot4 = (row: Vec4, col: Vec4) => { - return add( - multiply(row[0], col[0]), - multiply(row[1], col[1]), - multiply(row[2], col[2]), - multiply(row[3], col[3]) - ); -}; - -export const matrixVecMul4 = (m: Matrix4, v: Vec4) => - [dot4(m[0], v), dot4(m[1], v), dot4(m[2], v), dot4(m[3], v)] as const; - -export const multiply4 = (m1: Matrix4, m2: Matrix4) => { - const col0 = [m2[0][0], m2[1][0], m2[2][0], m2[3][0]] as const; - const col1 = [m2[0][1], m2[1][1], m2[2][1], m2[3][1]] as const; - const col2 = [m2[0][2], m2[1][2], m2[2][2], m2[3][2]] as const; - const col3 = [m2[0][3], m2[1][3], m2[2][3], m2[3][3]] as const; - return [ - [ - dot4(m1[0], col0), - dot4(m1[0], col1), - dot4(m1[0], col2), - dot4(m1[0], col3), - ], - [ - dot4(m1[1], col0), - dot4(m1[1], col1), - dot4(m1[1], col2), - dot4(m1[1], col3), - ], - [ - dot4(m1[2], col0), - dot4(m1[2], col1), - dot4(m1[2], col2), - dot4(m1[2], col3), - ], - [ - dot4(m1[3], col0), - dot4(m1[3], col1), - dot4(m1[3], col2), - dot4(m1[3], col3), - ], - ] as const; -}; - -export const processTransform3d = (transforms: Transforms3d) => - transforms.reduce((acc, transform) => { - const key = Object.keys(transform)[0] as Transform3dName; - if (key === "translateX") { - const value = (transform as Pick)[key]; - return multiply4(acc, translateXMatrix(value)); - } - if (key === "translateY") { - const value = (transform as Pick)[key]; - return multiply4(acc, translateYMatrix(value)); - } - if (key === "translateZ") { - const value = (transform as Pick)[key]; - return multiply4(acc, translateZMatrix(value)); - } - if (key === "scale") { - const value = (transform as Pick)[key]; - return multiply4(acc, scaleMatrix(value)); - } - if (key === "scaleX") { - const value = (transform as Pick)[key]; - return multiply4(acc, scaleXMatrix(value)); - } - if (key === "scaleY") { - const value = (transform as Pick)[key]; - return multiply4(acc, scaleYMatrix(value)); - } - if (key === "skewX") { - const value = (transform as Pick)[key]; - return multiply4(acc, skewXMatrix(value)); - } - if (key === "skewY") { - const value = (transform as Pick)[key]; - return multiply4(acc, skewYMatrix(value)); - } - if (key === "rotateX") { - const value = (transform as Pick)[key]; - return multiply4(acc, rotateXMatrix(value)); - } - if (key === "rotateY") { - const value = (transform as Pick)[key]; - return multiply4(acc, rotateYMatrix(value)); - } - if (key === "perspective") { - const value = (transform as Pick)[key]; - return multiply4(acc, perspectiveMatrix(value)); - } - if (key === "rotate" || key === "rotateZ") { - const value = (transform as Pick)[key]; - return multiply4(acc, rotateZMatrix(value)); - } - if (key === "matrix") { - const matrix = (transform as Pick)[key]; - return multiply4(acc, matrix); - } - return exhaustiveCheck(key); - }, identityMatrix4); diff --git a/src/v1/ReText.tsx b/src/v1/ReText.tsx deleted file mode 100644 index c395935..0000000 --- a/src/v1/ReText.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import type { TextStyle, StyleProp } from "react-native"; -import { TextInput } from "react-native"; -import Animated from "react-native-reanimated"; - -const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); - -interface TextProps { - text: Animated.Node; - style?: StyleProp>; -} - -const ReText = (props: TextProps) => { - const { text, style } = { style: {}, ...props }; - return ( - - ); -}; - -export default ReText; diff --git a/src/v1/SVG.ts b/src/v1/SVG.ts deleted file mode 100644 index 9751193..0000000 --- a/src/v1/SVG.ts +++ /dev/null @@ -1,236 +0,0 @@ -import Animated, { interpolateNode } from "react-native-reanimated"; -import parseSVG from "parse-svg-path"; -import absSVG from "abs-svg-path"; -import normalizeSVG from "normalize-svg-path"; - -import { get } from "./Array"; -import { string } from "./String"; -import { cubicBezier } from "./Math"; -import cubicBezierLength from "./bezier/CubicBezierLength"; -import cubicBezierSolve from "./bezier/CubicBezierSolve"; - -const { - Value, - lessOrEq, - greaterOrEq, - and, - cond, - multiply, - lessThan, - concat, - add, -} = Animated; - -// const COMMAND = 0; -const MX = 1; -const MY = 2; -const CX1 = 1; -const CY1 = 2; -const CX2 = 3; -const CY2 = 4; -const CX = 5; -const CY = 6; - -type SVGMoveCommand = ["M", number, number]; -type SVGCurveCommand = ["C", number, number, number, number, number, number]; -type SVGNormalizedCommands = [SVGMoveCommand, ...SVGCurveCommand[]]; -type BezierPoint = - | "p0x" - | "p0y" - | "p1x" - | "p1y" - | "p2x" - | "p2y" - | "p3x" - | "p3y"; - -interface Point { - x: number; - y: number; -} - -interface BezierCubicCurve { - length: number; - p0: Point; - p1: Point; - p2: Point; - p3: Point; -} - -export interface PathInterpolationConfig { - inputRange: readonly Animated.Adaptable[]; - outputRange: readonly (ReanimatedPath | string)[]; - extrapolate?: Animated.Extrapolate; - extrapolateLeft?: Animated.Extrapolate; - extrapolateRight?: Animated.Extrapolate; -} - -export interface ReanimatedPath { - totalLength: number; - segments: { start: number; end: number; p0x: number; p3x: number }[]; - length: number[]; - start: number[]; - end: number[]; - p0x: number[]; - p0y: number[]; - p1x: number[]; - p1y: number[]; - p2x: number[]; - p2y: number[]; - p3x: number[]; - p3y: number[]; -} - -export const parsePath = (d: string): ReanimatedPath => { - const [move, ...curves]: SVGNormalizedCommands = normalizeSVG( - absSVG(parseSVG(d)) - ); - const parts: BezierCubicCurve[] = curves.map((curve, index) => { - const prevCurve = curves[index - 1]; - const p0 = - index === 0 - ? { x: move[MX], y: move[MY] } - : { x: prevCurve[CX], y: prevCurve[CY] }; - const p1 = { x: curve[CX1], y: curve[CY1] }; - const p2 = { x: curve[CX2], y: curve[CY2] }; - const p3 = { x: curve[CX], y: curve[CY] }; - const length = cubicBezierLength(p0, p1, p2, p3); - return { - p0, - p1, - p2, - p3, - length, - }; - }); - const segments = parts.map((part, index) => { - const start = parts.slice(0, index).reduce((acc, p) => acc + p.length, 0); - const end = start + part.length; - return { - start, - end, - p0x: part.p0.x, - p3x: part.p3.x, - }; - }); - return { - segments, - totalLength: parts.reduce((acc, part) => acc + part.length, 0), - length: parts.map((part) => part.length), - start: segments.map((segment) => segment.start), - end: segments.map((segment) => segment.end), - p0x: parts.map((part) => part.p0.x), - p0y: parts.map((part) => part.p0.y), - p1x: parts.map((part) => part.p1.x), - p1y: parts.map((part) => part.p1.y), - p2x: parts.map((part) => part.p2.x), - p2y: parts.map((part) => part.p2.y), - p3x: parts.map((part) => part.p3.x), - p3y: parts.map((part) => part.p3.y), - }; -}; - -export const getPointAtLength = ( - path: ReanimatedPath, - length: Animated.Adaptable -): { x: Animated.Node; y: Animated.Node } => { - const notFound: Animated.Node = new Value(-1); - const index = path.segments.reduce( - (acc, p, i) => - cond(and(greaterOrEq(length, p.start), lessOrEq(length, p.end)), i, acc), - notFound - ); - const start = get(path.start, index); - const end = get(path.end, index); - - const p0x = get(path.p0x, index); - const p1x = get(path.p1x, index); - const p2x = get(path.p2x, index); - const p3x = get(path.p3x, index); - - const p0y = get(path.p0y, index); - const p1y = get(path.p1y, index); - const p2y = get(path.p2y, index); - const p3y = get(path.p3y, index); - const t = interpolateNode(length, { - inputRange: [start, end], - outputRange: [0, 1], - }); - return { - x: cubicBezier(t, p0x, p1x, p2x, p3x), - y: cubicBezier(t, p0y, p1y, p2y, p3y), - }; -}; - -export const interpolatePath = ( - value: Animated.Adaptable, - { inputRange, outputRange, ...config }: PathInterpolationConfig -): Animated.Node => { - const paths = outputRange.map((path) => - typeof path === "string" ? parsePath(path) : path - ); - const [path] = paths; - const commands = path.segments.map((_, index) => { - const interpolatePoint = (point: BezierPoint) => - interpolateNode(value, { - inputRange, - outputRange: paths.map((p) => p[point][index]), - ...config, - }); - - const mx = interpolatePoint("p0x"); - const my = interpolatePoint("p0y"); - - const p1x = interpolatePoint("p1x"); - const p1y = interpolatePoint("p1y"); - - const p2x = interpolatePoint("p2x"); - const p2y = interpolatePoint("p2y"); - - const p3x = interpolatePoint("p3x"); - const p3y = interpolatePoint("p3y"); - - return string`${ - index === 0 ? string`M${mx},${my} ` : "" - }C${p1x},${p1y} ${p2x},${p2y} ${p3x},${p3y}`; - }); - return concat(...commands); -}; - -export const bInterpolatePath = ( - value: Animated.Value, - path1: ReanimatedPath | string, - path2: ReanimatedPath | string -): Animated.Node => - interpolatePath(value, { - inputRange: [0, 1], - outputRange: [path1, path2], - }); - -// https://pomax.github.io/bezierinfo/#yforx -export const getLengthAtX = ( - path: ReanimatedPath, - x: Animated.Adaptable -): Animated.Node => { - const notFound: Animated.Node = new Value(-1); - const index = path.segments.reduce( - (acc, p, i) => cond(and(greaterOrEq(x, p.p0x), lessOrEq(x, p.p3x)), i, acc), - notFound - ); - const p0 = get(path.p0x, index); - const p1 = get(path.p1x, index); - const p2 = get(path.p2x, index); - const p3 = get(path.p3x, index); - const t = cubicBezierSolve(p0, p1, p2, p3); - const length = get(path.length, index); - /* eslint-disable @typescript-eslint/no-explicit-any */ - const start = add( - ...(path.length.map((l, i) => cond(lessThan(i, index), l, 0)) as [ - any, - any, - ...any[] - ]) - ); - /* eslint-enable @typescript-eslint/no-explicit-any */ - return add(start, multiply(t, length)); -}; diff --git a/src/v1/String.tsx b/src/v1/String.tsx deleted file mode 100644 index 0182e4a..0000000 --- a/src/v1/String.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Animated from "react-native-reanimated"; - -const { concat } = Animated; - -export type Concatable = - | Animated.Adaptable - | Animated.Adaptable; - -export const string = ( - strings: readonly string[], - ...values: readonly Concatable[] -) => { - if (values.length === 0) { - return concat(strings[0]); - } - const result = values.reduce( - (acc, v, idx) => [...acc, strings[idx], v], - [] - ); - result.push(strings[strings.length - 1]); - return concat(...result); -}; diff --git a/src/v1/Transformations.ts b/src/v1/Transformations.ts deleted file mode 100644 index 27b0f7b..0000000 --- a/src/v1/Transformations.ts +++ /dev/null @@ -1,41 +0,0 @@ -import Animated from "react-native-reanimated"; - -import type { Vector } from "./Vectors"; -import { vec } from "./Vectors"; -import type { Transforms2d } from "./Matrix3"; - -const { divide, sub, multiply, add, cos, sin } = Animated; - -export const translateZ = ( - perspective: Animated.Adaptable, - z: Animated.Adaptable -) => ({ scale: divide(perspective, sub(perspective, z)) }); - -export const translate = ({ x: translateX, y: translateY }: Vector) => [ - { translateX }, - { translateY }, -]; - -export const transformOrigin = ( - { x, y }: Vector, - ...transformations: Transforms2d -): Transforms2d => [ - { translateX: x }, - { translateY: y }, - ...transformations, - { translateX: multiply(x, -1) }, - { translateY: multiply(y, -1) }, -]; - -export const rotateTranslation = ( - tr: Vector, - rotate: Animated.Adaptable -) => ({ - x: sub(multiply(tr.x, cos(rotate)), multiply(tr.y, sin(rotate))), - y: add(multiply(tr.x, sin(rotate)), multiply(tr.y, cos(rotate))), -}); - -export const scaleTranslation = ( - tr: Vector, - scale: Animated.Adaptable -) => vec.multiply(tr, scale); diff --git a/src/v1/Transitions.ts b/src/v1/Transitions.ts deleted file mode 100644 index 4a1db00..0000000 --- a/src/v1/Transitions.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* eslint-disable no-nested-ternary */ -import { useEffect } from "react"; -import Animated, { not, add } from "react-native-reanimated"; - -import type { SpringConfig, TimingConfig } from "./Animations"; -import { useConst } from "./Hooks"; - -const { - Value, - cond, - block, - set, - Clock, - spring, - startClock, - stopClock, - timing, - neq, - SpringUtils, -} = Animated; - -const defaultSpringConfig = SpringUtils.makeDefaultConfig(); - -export const withTransition = ( - value: Animated.Node, - timingConfig: TimingConfig = {} -) => { - const init = new Value(0); - const clock = new Clock(); - const state = { - finished: new Value(0), - frameTime: new Value(0), - position: new Value(0), - time: new Value(0), - }; - const config = { - toValue: new Value(0), - duration: 150, - easing: (v: Animated.Adaptable) => add(v, 0), - ...timingConfig, - }; - return block([ - cond(not(init), [set(init, 1), set(state.position, value)]), - cond(neq(config.toValue, value), [ - set(state.frameTime, 0), - set(state.time, 0), - set(state.finished, 0), - set(config.toValue, value), - startClock(clock), - ]), - timing(clock, state, config), - cond(state.finished, stopClock(clock)), - state.position, - ]); -}; - -export const withSpringTransition = ( - value: Animated.Node, - springConfig: SpringConfig = defaultSpringConfig, - velocity: Animated.Adaptable = 0 -) => { - const init = new Value(0); - const clock = new Clock(); - const state = { - finished: new Value(0), - velocity: new Value(0), - position: new Value(0), - time: new Value(0), - }; - const config = { - toValue: new Value(0), - damping: 15, - mass: 1, - stiffness: 150, - overshootClamping: false, - restSpeedThreshold: 1, - restDisplacementThreshold: 1, - ...springConfig, - }; - return block([ - cond(not(init), [set(init, 1), set(state.position, value)]), - cond(neq(config.toValue, value), [ - set(state.velocity, velocity), - set(state.time, 0), - set(state.finished, 0), - set(config.toValue, value), - startClock(clock), - ]), - spring(clock, state, config), - cond(state.finished, stopClock(clock)), - state.position, - ]); -}; - -export const withTimingTransition = withTransition; - -export const useTransition = ( - state: boolean | number, - config: TimingConfig = {} -) => { - const value: Animated.Value = useConst(() => new Value(0)); - useEffect(() => { - value.setValue(typeof state === "boolean" ? (state ? 1 : 0) : state); - }, [value, state]); - const transition = useConst(() => withTransition(value, config)); - return transition; -}; - -export const useSpringTransition = ( - state: boolean | number, - config: SpringConfig = defaultSpringConfig -) => { - const value: Animated.Value = useConst(() => new Value(0)); - - useEffect(() => { - value.setValue(typeof state === "boolean" ? (state ? 1 : 0) : state); - }, [value, state]); - - const transition = useConst(() => withSpringTransition(value, config)); - return transition; -}; - -export const useTimingTransition = useTransition; diff --git a/src/v1/Vectors.ts b/src/v1/Vectors.ts deleted file mode 100644 index cab5160..0000000 --- a/src/v1/Vectors.ts +++ /dev/null @@ -1,103 +0,0 @@ -import Animated from "react-native-reanimated"; - -import { clamp as clamp1 } from "./Math"; - -const { Value, block } = Animated; -type Dimension = "x" | "y"; -type Fn = (...args: Animated.Adaptable[]) => Animated.Node; -type Adaptable = Vector | Animated.Adaptable; -type SingleArgOp = [T]; -type BinArgOp = [T, T, ...T[]]; - -export interface Vector< - T extends Animated.Adaptable = Animated.Adaptable -> { - x: T; - y: T; -} - -type Create = { - (): Vector<0>; - >(x: T, y?: T): Vector; -}; - -const create: Create = >( - x?: T, - y?: T -) => ({ - x: x ?? 0, - y: y ?? x ?? 0, -}); - -const createValue = (x = 0, y?: number) => - create(new Value(x), new Value(y ?? x)); - -const isAdaptable = (value: Adaptable): value is Animated.Adaptable => - typeof value === "number" || - value instanceof Animated.Node || - value instanceof Animated.Value; - -const get = (vectors: Adaptable[], dimension: Dimension) => - vectors.map((vector) => (isAdaptable(vector) ? vector : vector[dimension])); - -const apply = (fn: Fn, ...vectors: Adaptable[]) => ({ - x: fn(...get(vectors, "x")), - y: fn(...get(vectors, "y")), -}); - -const add = (...vectors: BinArgOp) => apply(Animated.add, ...vectors); -const sub = (...vectors: BinArgOp) => apply(Animated.sub, ...vectors); -const div = (...vectors: BinArgOp) => apply(Animated.divide, ...vectors); -const mul = (...vectors: BinArgOp) => apply(Animated.multiply, ...vectors); -const pow = (...vectors: [Adaptable, number]) => - apply(Animated.pow, ...vectors); -const sqrt = (...vectors: SingleArgOp) => apply(Animated.sqrt, ...vectors); -const cos = (...vectors: SingleArgOp) => apply(Animated.cos, ...vectors); -const sin = (...vectors: SingleArgOp) => apply(Animated.sin, ...vectors); -const min = (vector: Adaptable, value: Animated.Adaptable) => - apply(Animated.min, vector, value); -const max = (vector: Adaptable, value: Animated.Adaptable) => - apply(Animated.max, vector, value); -const clamp = (value: Adaptable, minVec: Adaptable, maxVec: Adaptable) => - apply(clamp1, value, minVec, maxVec); - -const minus = (a: Adaptable) => mul(-1, a); - -const set = (a: Vector>, b: Adaptable) => - block([ - Animated.set(a.x, isAdaptable(b) ? b : b.x), - Animated.set(a.y, isAdaptable(b) ? b : b.y), - ]); - -const length = (v: Vector) => - Animated.sqrt(Animated.add(Animated.pow(v.x, 2), Animated.pow(v.y, 2))); -const normalize = (v: Vector) => div(v, length(v)); -const dot = (v1: Vector, v2: Vector) => - add(Animated.multiply(v1.x, v2.x), Animated.multiply(v1.y, v2.y)); -const cross = (v1: Vector, v2: Vector) => - sub(Animated.multiply(v1.x, v2.y), Animated.multiply(v1.y, v2.x)); - -export const vec = { - create, - createValue, - minus, - add, - sub, - dot, - div, - mul, - multiply: mul, - divide: div, - pow, - sqrt, - set, - clamp, - apply, - min, - max, - cos, - sin, - length, - normalize, - cross, -}; diff --git a/src/v1/bezier/CubicBezierLength.ts b/src/v1/bezier/CubicBezierLength.ts deleted file mode 100644 index 30f7973..0000000 --- a/src/v1/bezier/CubicBezierLength.ts +++ /dev/null @@ -1,764 +0,0 @@ -interface Point { - x: number; - y: number; -} - -type CtrlPoint = [number, number, number, number]; - -// Cubic bezier curve length from http://bl.ocks.org/hnakamur/e7efd0602bfc15f66fc5 -// Legendre-Gauss abscissae (xi values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x)) -const tValues = [ - [], - [], - [ - -0.5773502691896257645091487805019574556476, - 0.5773502691896257645091487805019574556476, - ], - [ - 0, -0.7745966692414833770358530799564799221665, - 0.7745966692414833770358530799564799221665, - ], - [ - -0.3399810435848562648026657591032446872005, - 0.3399810435848562648026657591032446872005, - -0.8611363115940525752239464888928095050957, - 0.8611363115940525752239464888928095050957, - ], - [ - 0, -0.5384693101056830910363144207002088049672, - 0.5384693101056830910363144207002088049672, - -0.9061798459386639927976268782993929651256, - 0.9061798459386639927976268782993929651256, - ], - [ - 0.6612093864662645136613995950199053470064, - -0.6612093864662645136613995950199053470064, - -0.2386191860831969086305017216807119354186, - 0.2386191860831969086305017216807119354186, - -0.9324695142031520278123015544939946091347, - 0.9324695142031520278123015544939946091347, - ], - [ - 0, 0.4058451513773971669066064120769614633473, - -0.4058451513773971669066064120769614633473, - -0.7415311855993944398638647732807884070741, - 0.7415311855993944398638647732807884070741, - -0.9491079123427585245261896840478512624007, - 0.9491079123427585245261896840478512624007, - ], - [ - -0.1834346424956498049394761423601839806667, - 0.1834346424956498049394761423601839806667, - -0.5255324099163289858177390491892463490419, - 0.5255324099163289858177390491892463490419, - -0.7966664774136267395915539364758304368371, - 0.7966664774136267395915539364758304368371, - -0.9602898564975362316835608685694729904282, - 0.9602898564975362316835608685694729904282, - ], - [ - 0, -0.8360311073266357942994297880697348765441, - 0.8360311073266357942994297880697348765441, - -0.9681602395076260898355762029036728700494, - 0.9681602395076260898355762029036728700494, - -0.3242534234038089290385380146433366085719, - 0.3242534234038089290385380146433366085719, - -0.6133714327005903973087020393414741847857, - 0.6133714327005903973087020393414741847857, - ], - [ - -0.1488743389816312108848260011297199846175, - 0.1488743389816312108848260011297199846175, - -0.4333953941292471907992659431657841622, - 0.4333953941292471907992659431657841622, - -0.6794095682990244062343273651148735757692, - 0.6794095682990244062343273651148735757692, - -0.8650633666889845107320966884234930485275, - 0.8650633666889845107320966884234930485275, - -0.9739065285171717200779640120844520534282, - 0.9739065285171717200779640120844520534282, - ], - [ - 0, -0.2695431559523449723315319854008615246796, - 0.2695431559523449723315319854008615246796, - -0.5190961292068118159257256694586095544802, - 0.5190961292068118159257256694586095544802, - -0.7301520055740493240934162520311534580496, - 0.7301520055740493240934162520311534580496, - -0.8870625997680952990751577693039272666316, - 0.8870625997680952990751577693039272666316, - -0.9782286581460569928039380011228573907714, - 0.9782286581460569928039380011228573907714, - ], - [ - -0.1252334085114689154724413694638531299833, - 0.1252334085114689154724413694638531299833, - -0.3678314989981801937526915366437175612563, - 0.3678314989981801937526915366437175612563, - -0.587317954286617447296702418940534280369, - 0.587317954286617447296702418940534280369, - -0.7699026741943046870368938332128180759849, - 0.7699026741943046870368938332128180759849, - -0.9041172563704748566784658661190961925375, - 0.9041172563704748566784658661190961925375, - -0.9815606342467192506905490901492808229601, - 0.9815606342467192506905490901492808229601, - ], - [ - 0, -0.2304583159551347940655281210979888352115, - 0.2304583159551347940655281210979888352115, - -0.4484927510364468528779128521276398678019, - 0.4484927510364468528779128521276398678019, - -0.6423493394403402206439846069955156500716, - 0.6423493394403402206439846069955156500716, - -0.8015780907333099127942064895828598903056, - 0.8015780907333099127942064895828598903056, - -0.9175983992229779652065478365007195123904, - 0.9175983992229779652065478365007195123904, - -0.9841830547185881494728294488071096110649, - 0.9841830547185881494728294488071096110649, - ], - [ - -0.1080549487073436620662446502198347476119, - 0.1080549487073436620662446502198347476119, - -0.3191123689278897604356718241684754668342, - 0.3191123689278897604356718241684754668342, - -0.5152486363581540919652907185511886623088, - 0.5152486363581540919652907185511886623088, - -0.6872929048116854701480198030193341375384, - 0.6872929048116854701480198030193341375384, - -0.8272013150697649931897947426503949610397, - 0.8272013150697649931897947426503949610397, - -0.928434883663573517336391139377874264477, - 0.928434883663573517336391139377874264477, - -0.986283808696812338841597266704052801676, - 0.986283808696812338841597266704052801676, - ], - [ - 0, -0.2011940939974345223006283033945962078128, - 0.2011940939974345223006283033945962078128, - -0.3941513470775633698972073709810454683627, - 0.3941513470775633698972073709810454683627, - -0.5709721726085388475372267372539106412383, - 0.5709721726085388475372267372539106412383, - -0.7244177313601700474161860546139380096308, - 0.7244177313601700474161860546139380096308, - -0.8482065834104272162006483207742168513662, - 0.8482065834104272162006483207742168513662, - -0.9372733924007059043077589477102094712439, - 0.9372733924007059043077589477102094712439, - -0.9879925180204854284895657185866125811469, - 0.9879925180204854284895657185866125811469, - ], - [ - -0.0950125098376374401853193354249580631303, - 0.0950125098376374401853193354249580631303, - -0.281603550779258913230460501460496106486, - 0.281603550779258913230460501460496106486, - -0.45801677765722738634241944298357757354, - 0.45801677765722738634241944298357757354, - -0.6178762444026437484466717640487910189918, - 0.6178762444026437484466717640487910189918, - -0.7554044083550030338951011948474422683538, - 0.7554044083550030338951011948474422683538, - -0.8656312023878317438804678977123931323873, - 0.8656312023878317438804678977123931323873, - -0.9445750230732325760779884155346083450911, - 0.9445750230732325760779884155346083450911, - -0.9894009349916499325961541734503326274262, - 0.9894009349916499325961541734503326274262, - ], - [ - 0, -0.1784841814958478558506774936540655574754, - 0.1784841814958478558506774936540655574754, - -0.3512317634538763152971855170953460050405, - 0.3512317634538763152971855170953460050405, - -0.5126905370864769678862465686295518745829, - 0.5126905370864769678862465686295518745829, - -0.6576711592166907658503022166430023351478, - 0.6576711592166907658503022166430023351478, - -0.7815140038968014069252300555204760502239, - 0.7815140038968014069252300555204760502239, - -0.8802391537269859021229556944881556926234, - 0.8802391537269859021229556944881556926234, - -0.9506755217687677612227169578958030214433, - 0.9506755217687677612227169578958030214433, - -0.9905754753144173356754340199406652765077, - 0.9905754753144173356754340199406652765077, - ], - [ - -0.0847750130417353012422618529357838117333, - 0.0847750130417353012422618529357838117333, - -0.2518862256915055095889728548779112301628, - 0.2518862256915055095889728548779112301628, - -0.4117511614628426460359317938330516370789, - 0.4117511614628426460359317938330516370789, - -0.5597708310739475346078715485253291369276, - 0.5597708310739475346078715485253291369276, - -0.6916870430603532078748910812888483894522, - 0.6916870430603532078748910812888483894522, - -0.8037049589725231156824174550145907971032, - 0.8037049589725231156824174550145907971032, - -0.8926024664975557392060605911271455154078, - 0.8926024664975557392060605911271455154078, - -0.9558239495713977551811958929297763099728, - 0.9558239495713977551811958929297763099728, - -0.9915651684209309467300160047061507702525, - 0.9915651684209309467300160047061507702525, - ], - [ - 0, -0.1603586456402253758680961157407435495048, - 0.1603586456402253758680961157407435495048, - -0.3165640999636298319901173288498449178922, - 0.3165640999636298319901173288498449178922, - -0.4645707413759609457172671481041023679762, - 0.4645707413759609457172671481041023679762, - -0.6005453046616810234696381649462392798683, - 0.6005453046616810234696381649462392798683, - -0.7209661773352293786170958608237816296571, - 0.7209661773352293786170958608237816296571, - -0.8227146565371428249789224867127139017745, - 0.8227146565371428249789224867127139017745, - -0.9031559036148179016426609285323124878093, - 0.9031559036148179016426609285323124878093, - -0.960208152134830030852778840687651526615, - 0.960208152134830030852778840687651526615, - -0.9924068438435844031890176702532604935893, - 0.9924068438435844031890176702532604935893, - ], - [ - -0.0765265211334973337546404093988382110047, - 0.0765265211334973337546404093988382110047, - -0.227785851141645078080496195368574624743, - 0.227785851141645078080496195368574624743, - -0.3737060887154195606725481770249272373957, - 0.3737060887154195606725481770249272373957, - -0.5108670019508270980043640509552509984254, - 0.5108670019508270980043640509552509984254, - -0.6360536807265150254528366962262859367433, - 0.6360536807265150254528366962262859367433, - -0.7463319064601507926143050703556415903107, - 0.7463319064601507926143050703556415903107, - -0.8391169718222188233945290617015206853296, - 0.8391169718222188233945290617015206853296, - -0.9122344282513259058677524412032981130491, - 0.9122344282513259058677524412032981130491, - -0.963971927277913791267666131197277221912, - 0.963971927277913791267666131197277221912, - -0.9931285991850949247861223884713202782226, - 0.9931285991850949247861223884713202782226, - ], - [ - 0, -0.1455618541608950909370309823386863301163, - 0.1455618541608950909370309823386863301163, - -0.288021316802401096600792516064600319909, - 0.288021316802401096600792516064600319909, - -0.4243421202074387835736688885437880520964, - 0.4243421202074387835736688885437880520964, - -0.551618835887219807059018796724313286622, - 0.551618835887219807059018796724313286622, - -0.667138804197412319305966669990339162597, - 0.667138804197412319305966669990339162597, - -0.7684399634756779086158778513062280348209, - 0.7684399634756779086158778513062280348209, - -0.8533633645833172836472506385875676702761, - 0.8533633645833172836472506385875676702761, - -0.9200993341504008287901871337149688941591, - 0.9200993341504008287901871337149688941591, - -0.9672268385663062943166222149076951614246, - 0.9672268385663062943166222149076951614246, - -0.9937521706203895002602420359379409291933, - 0.9937521706203895002602420359379409291933, - ], - [ - -0.0697392733197222212138417961186280818222, - 0.0697392733197222212138417961186280818222, - -0.2078604266882212854788465339195457342156, - 0.2078604266882212854788465339195457342156, - -0.3419358208920842251581474204273796195591, - 0.3419358208920842251581474204273796195591, - -0.4693558379867570264063307109664063460953, - 0.4693558379867570264063307109664063460953, - -0.5876404035069115929588769276386473488776, - 0.5876404035069115929588769276386473488776, - -0.6944872631866827800506898357622567712673, - 0.6944872631866827800506898357622567712673, - -0.7878168059792081620042779554083515213881, - 0.7878168059792081620042779554083515213881, - -0.8658125777203001365364256370193787290847, - 0.8658125777203001365364256370193787290847, - -0.9269567721871740005206929392590531966353, - 0.9269567721871740005206929392590531966353, - -0.9700604978354287271239509867652687108059, - 0.9700604978354287271239509867652687108059, - -0.994294585482399292073031421161298980393, - 0.994294585482399292073031421161298980393, - ], - [ - 0, -0.1332568242984661109317426822417661370104, - 0.1332568242984661109317426822417661370104, - -0.264135680970344930533869538283309602979, - 0.264135680970344930533869538283309602979, - -0.390301038030290831421488872880605458578, - 0.390301038030290831421488872880605458578, - -0.5095014778460075496897930478668464305448, - 0.5095014778460075496897930478668464305448, - -0.6196098757636461563850973116495956533871, - 0.6196098757636461563850973116495956533871, - -0.7186613631319501944616244837486188483299, - 0.7186613631319501944616244837486188483299, - -0.8048884016188398921511184069967785579414, - 0.8048884016188398921511184069967785579414, - -0.8767523582704416673781568859341456716389, - 0.8767523582704416673781568859341456716389, - -0.9329710868260161023491969890384229782357, - 0.9329710868260161023491969890384229782357, - -0.9725424712181152319560240768207773751816, - 0.9725424712181152319560240768207773751816, - -0.9947693349975521235239257154455743605736, - 0.9947693349975521235239257154455743605736, - ], - [ - -0.0640568928626056260850430826247450385909, - 0.0640568928626056260850430826247450385909, - -0.1911188674736163091586398207570696318404, - 0.1911188674736163091586398207570696318404, - -0.3150426796961633743867932913198102407864, - 0.3150426796961633743867932913198102407864, - -0.4337935076260451384870842319133497124524, - 0.4337935076260451384870842319133497124524, - -0.5454214713888395356583756172183723700107, - 0.5454214713888395356583756172183723700107, - -0.6480936519369755692524957869107476266696, - 0.6480936519369755692524957869107476266696, - -0.7401241915785543642438281030999784255232, - 0.7401241915785543642438281030999784255232, - -0.8200019859739029219539498726697452080761, - 0.8200019859739029219539498726697452080761, - -0.8864155270044010342131543419821967550873, - 0.8864155270044010342131543419821967550873, - -0.9382745520027327585236490017087214496548, - 0.9382745520027327585236490017087214496548, - -0.9747285559713094981983919930081690617411, - 0.9747285559713094981983919930081690617411, - -0.9951872199970213601799974097007368118745, - 0.9951872199970213601799974097007368118745, - ], -]; - -// Legendre-Gauss weights (wi values, defined by a function linked to in the Bezier primer article) -const cValues = [ - [], - [], - [1.0, 1.0], - [ - 0.8888888888888888888888888888888888888888, - 0.5555555555555555555555555555555555555555, - 0.5555555555555555555555555555555555555555, - ], - [ - 0.6521451548625461426269360507780005927646, - 0.6521451548625461426269360507780005927646, - 0.3478548451374538573730639492219994072353, - 0.3478548451374538573730639492219994072353, - ], - [ - 0.5688888888888888888888888888888888888888, - 0.4786286704993664680412915148356381929122, - 0.4786286704993664680412915148356381929122, - 0.2369268850561890875142640407199173626432, - 0.2369268850561890875142640407199173626432, - ], - [ - 0.3607615730481386075698335138377161116615, - 0.3607615730481386075698335138377161116615, - 0.4679139345726910473898703439895509948116, - 0.4679139345726910473898703439895509948116, - 0.1713244923791703450402961421727328935268, - 0.1713244923791703450402961421727328935268, - ], - [ - 0.4179591836734693877551020408163265306122, - 0.3818300505051189449503697754889751338783, - 0.3818300505051189449503697754889751338783, - 0.2797053914892766679014677714237795824869, - 0.2797053914892766679014677714237795824869, - 0.1294849661688696932706114326790820183285, - 0.1294849661688696932706114326790820183285, - ], - [ - 0.3626837833783619829651504492771956121941, - 0.3626837833783619829651504492771956121941, - 0.3137066458778872873379622019866013132603, - 0.3137066458778872873379622019866013132603, - 0.2223810344533744705443559944262408844301, - 0.2223810344533744705443559944262408844301, - 0.1012285362903762591525313543099621901153, - 0.1012285362903762591525313543099621901153, - ], - [ - 0.3302393550012597631645250692869740488788, - 0.1806481606948574040584720312429128095143, - 0.1806481606948574040584720312429128095143, - 0.0812743883615744119718921581105236506756, - 0.0812743883615744119718921581105236506756, - 0.3123470770400028400686304065844436655987, - 0.3123470770400028400686304065844436655987, - 0.2606106964029354623187428694186328497718, - 0.2606106964029354623187428694186328497718, - ], - [ - 0.295524224714752870173892994651338329421, - 0.295524224714752870173892994651338329421, - 0.2692667193099963550912269215694693528597, - 0.2692667193099963550912269215694693528597, - 0.2190863625159820439955349342281631924587, - 0.2190863625159820439955349342281631924587, - 0.1494513491505805931457763396576973324025, - 0.1494513491505805931457763396576973324025, - 0.0666713443086881375935688098933317928578, - 0.0666713443086881375935688098933317928578, - ], - [ - 0.272925086777900630714483528336342189156, - 0.2628045445102466621806888698905091953727, - 0.2628045445102466621806888698905091953727, - 0.2331937645919904799185237048431751394317, - 0.2331937645919904799185237048431751394317, - 0.1862902109277342514260976414316558916912, - 0.1862902109277342514260976414316558916912, - 0.1255803694649046246346942992239401001976, - 0.1255803694649046246346942992239401001976, - 0.0556685671161736664827537204425485787285, - 0.0556685671161736664827537204425485787285, - ], - [ - 0.2491470458134027850005624360429512108304, - 0.2491470458134027850005624360429512108304, - 0.2334925365383548087608498989248780562594, - 0.2334925365383548087608498989248780562594, - 0.2031674267230659217490644558097983765065, - 0.2031674267230659217490644558097983765065, - 0.160078328543346226334652529543359071872, - 0.160078328543346226334652529543359071872, - 0.1069393259953184309602547181939962242145, - 0.1069393259953184309602547181939962242145, - 0.047175336386511827194615961485017060317, - 0.047175336386511827194615961485017060317, - ], - [ - 0.2325515532308739101945895152688359481566, - 0.2262831802628972384120901860397766184347, - 0.2262831802628972384120901860397766184347, - 0.2078160475368885023125232193060527633865, - 0.2078160475368885023125232193060527633865, - 0.1781459807619457382800466919960979955128, - 0.1781459807619457382800466919960979955128, - 0.1388735102197872384636017768688714676218, - 0.1388735102197872384636017768688714676218, - 0.0921214998377284479144217759537971209236, - 0.0921214998377284479144217759537971209236, - 0.0404840047653158795200215922009860600419, - 0.0404840047653158795200215922009860600419, - ], - [ - 0.2152638534631577901958764433162600352749, - 0.2152638534631577901958764433162600352749, - 0.2051984637212956039659240656612180557103, - 0.2051984637212956039659240656612180557103, - 0.1855383974779378137417165901251570362489, - 0.1855383974779378137417165901251570362489, - 0.1572031671581935345696019386238421566056, - 0.1572031671581935345696019386238421566056, - 0.1215185706879031846894148090724766259566, - 0.1215185706879031846894148090724766259566, - 0.0801580871597602098056332770628543095836, - 0.0801580871597602098056332770628543095836, - 0.0351194603317518630318328761381917806197, - 0.0351194603317518630318328761381917806197, - ], - [ - 0.2025782419255612728806201999675193148386, - 0.1984314853271115764561183264438393248186, - 0.1984314853271115764561183264438393248186, - 0.1861610000155622110268005618664228245062, - 0.1861610000155622110268005618664228245062, - 0.1662692058169939335532008604812088111309, - 0.1662692058169939335532008604812088111309, - 0.1395706779261543144478047945110283225208, - 0.1395706779261543144478047945110283225208, - 0.1071592204671719350118695466858693034155, - 0.1071592204671719350118695466858693034155, - 0.0703660474881081247092674164506673384667, - 0.0703660474881081247092674164506673384667, - 0.0307532419961172683546283935772044177217, - 0.0307532419961172683546283935772044177217, - ], - [ - 0.1894506104550684962853967232082831051469, - 0.1894506104550684962853967232082831051469, - 0.1826034150449235888667636679692199393835, - 0.1826034150449235888667636679692199393835, - 0.1691565193950025381893120790303599622116, - 0.1691565193950025381893120790303599622116, - 0.1495959888165767320815017305474785489704, - 0.1495959888165767320815017305474785489704, - 0.1246289712555338720524762821920164201448, - 0.1246289712555338720524762821920164201448, - 0.0951585116824927848099251076022462263552, - 0.0951585116824927848099251076022462263552, - 0.0622535239386478928628438369943776942749, - 0.0622535239386478928628438369943776942749, - 0.0271524594117540948517805724560181035122, - 0.0271524594117540948517805724560181035122, - ], - [ - 0.1794464703562065254582656442618856214487, - 0.1765627053669926463252709901131972391509, - 0.1765627053669926463252709901131972391509, - 0.1680041021564500445099706637883231550211, - 0.1680041021564500445099706637883231550211, - 0.1540457610768102880814315948019586119404, - 0.1540457610768102880814315948019586119404, - 0.1351363684685254732863199817023501973721, - 0.1351363684685254732863199817023501973721, - 0.1118838471934039710947883856263559267358, - 0.1118838471934039710947883856263559267358, - 0.0850361483171791808835353701910620738504, - 0.0850361483171791808835353701910620738504, - 0.0554595293739872011294401653582446605128, - 0.0554595293739872011294401653582446605128, - 0.0241483028685479319601100262875653246916, - 0.0241483028685479319601100262875653246916, - ], - [ - 0.1691423829631435918406564701349866103341, - 0.1691423829631435918406564701349866103341, - 0.1642764837458327229860537764659275904123, - 0.1642764837458327229860537764659275904123, - 0.1546846751262652449254180038363747721932, - 0.1546846751262652449254180038363747721932, - 0.1406429146706506512047313037519472280955, - 0.1406429146706506512047313037519472280955, - 0.1225552067114784601845191268002015552281, - 0.1225552067114784601845191268002015552281, - 0.1009420441062871655628139849248346070628, - 0.1009420441062871655628139849248346070628, - 0.0764257302548890565291296776166365256053, - 0.0764257302548890565291296776166365256053, - 0.0497145488949697964533349462026386416808, - 0.0497145488949697964533349462026386416808, - 0.0216160135264833103133427102664524693876, - 0.0216160135264833103133427102664524693876, - ], - [ - 0.1610544498487836959791636253209167350399, - 0.1589688433939543476499564394650472016787, - 0.1589688433939543476499564394650472016787, - 0.152766042065859666778855400897662998461, - 0.152766042065859666778855400897662998461, - 0.1426067021736066117757461094419029724756, - 0.1426067021736066117757461094419029724756, - 0.1287539625393362276755157848568771170558, - 0.1287539625393362276755157848568771170558, - 0.1115666455473339947160239016817659974813, - 0.1115666455473339947160239016817659974813, - 0.0914900216224499994644620941238396526609, - 0.0914900216224499994644620941238396526609, - 0.0690445427376412265807082580060130449618, - 0.0690445427376412265807082580060130449618, - 0.0448142267656996003328381574019942119517, - 0.0448142267656996003328381574019942119517, - 0.0194617882297264770363120414644384357529, - 0.0194617882297264770363120414644384357529, - ], - [ - 0.1527533871307258506980843319550975934919, - 0.1527533871307258506980843319550975934919, - 0.1491729864726037467878287370019694366926, - 0.1491729864726037467878287370019694366926, - 0.1420961093183820513292983250671649330345, - 0.1420961093183820513292983250671649330345, - 0.1316886384491766268984944997481631349161, - 0.1316886384491766268984944997481631349161, - 0.118194531961518417312377377711382287005, - 0.118194531961518417312377377711382287005, - 0.1019301198172404350367501354803498761666, - 0.1019301198172404350367501354803498761666, - 0.0832767415767047487247581432220462061001, - 0.0832767415767047487247581432220462061001, - 0.0626720483341090635695065351870416063516, - 0.0626720483341090635695065351870416063516, - 0.040601429800386941331039952274932109879, - 0.040601429800386941331039952274932109879, - 0.0176140071391521183118619623518528163621, - 0.0176140071391521183118619623518528163621, - ], - [ - 0.1460811336496904271919851476833711882448, - 0.1445244039899700590638271665537525436099, - 0.1445244039899700590638271665537525436099, - 0.1398873947910731547221334238675831108927, - 0.1398873947910731547221334238675831108927, - 0.132268938633337461781052574496775604329, - 0.132268938633337461781052574496775604329, - 0.1218314160537285341953671771257335983563, - 0.1218314160537285341953671771257335983563, - 0.1087972991671483776634745780701056420336, - 0.1087972991671483776634745780701056420336, - 0.0934444234560338615532897411139320884835, - 0.0934444234560338615532897411139320884835, - 0.0761001136283793020170516533001831792261, - 0.0761001136283793020170516533001831792261, - 0.0571344254268572082836358264724479574912, - 0.0571344254268572082836358264724479574912, - 0.0369537897708524937999506682993296661889, - 0.0369537897708524937999506682993296661889, - 0.0160172282577743333242246168584710152658, - 0.0160172282577743333242246168584710152658, - ], - [ - 0.1392518728556319933754102483418099578739, - 0.1392518728556319933754102483418099578739, - 0.1365414983460151713525738312315173965863, - 0.1365414983460151713525738312315173965863, - 0.1311735047870623707329649925303074458757, - 0.1311735047870623707329649925303074458757, - 0.1232523768105124242855609861548144719594, - 0.1232523768105124242855609861548144719594, - 0.1129322960805392183934006074217843191142, - 0.1129322960805392183934006074217843191142, - 0.1004141444428809649320788378305362823508, - 0.1004141444428809649320788378305362823508, - 0.0859416062170677274144436813727028661891, - 0.0859416062170677274144436813727028661891, - 0.0697964684245204880949614189302176573987, - 0.0697964684245204880949614189302176573987, - 0.0522933351526832859403120512732112561121, - 0.0522933351526832859403120512732112561121, - 0.0337749015848141547933022468659129013491, - 0.0337749015848141547933022468659129013491, - 0.0146279952982722006849910980471854451902, - 0.0146279952982722006849910980471854451902, - ], - [ - 0.1336545721861061753514571105458443385831, - 0.132462039404696617371642464703316925805, - 0.132462039404696617371642464703316925805, - 0.1289057221880821499785953393997936532597, - 0.1289057221880821499785953393997936532597, - 0.1230490843067295304675784006720096548158, - 0.1230490843067295304675784006720096548158, - 0.1149966402224113649416435129339613014914, - 0.1149966402224113649416435129339613014914, - 0.1048920914645414100740861850147438548584, - 0.1048920914645414100740861850147438548584, - 0.0929157660600351474770186173697646486034, - 0.0929157660600351474770186173697646486034, - 0.0792814117767189549228925247420432269137, - 0.0792814117767189549228925247420432269137, - 0.0642324214085258521271696151589109980391, - 0.0642324214085258521271696151589109980391, - 0.0480376717310846685716410716320339965612, - 0.0480376717310846685716410716320339965612, - 0.0309880058569794443106942196418845053837, - 0.0309880058569794443106942196418845053837, - 0.0134118594871417720813094934586150649766, - 0.0134118594871417720813094934586150649766, - ], - [ - 0.1279381953467521569740561652246953718517, - 0.1279381953467521569740561652246953718517, - 0.1258374563468282961213753825111836887264, - 0.1258374563468282961213753825111836887264, - 0.121670472927803391204463153476262425607, - 0.121670472927803391204463153476262425607, - 0.1155056680537256013533444839067835598622, - 0.1155056680537256013533444839067835598622, - 0.1074442701159656347825773424466062227946, - 0.1074442701159656347825773424466062227946, - 0.0976186521041138882698806644642471544279, - 0.0976186521041138882698806644642471544279, - 0.086190161531953275917185202983742667185, - 0.086190161531953275917185202983742667185, - 0.0733464814110803057340336152531165181193, - 0.0733464814110803057340336152531165181193, - 0.0592985849154367807463677585001085845412, - 0.0592985849154367807463677585001085845412, - 0.0442774388174198061686027482113382288593, - 0.0442774388174198061686027482113382288593, - 0.0285313886289336631813078159518782864491, - 0.0285313886289336631813078159518782864491, - 0.0123412297999871995468056670700372915759, - 0.0123412297999871995468056670700372915759, - ], -]; - -// LUT for binomial coefficient arrays per curve order 'n' -const binomialCoefficients = [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]; - -// Look up what the binomial coefficient is for pair {n,k} -const binomials = (n: number, k: number) => binomialCoefficients[n][k]; - -/** - * Compute the curve derivative (hodograph) at t. - */ -const getDerivative = (derivative: number, t: number, vs: number[]): number => { - // the derivative of any 't'-less function is zero. - const n = vs.length - 1; - let value; - let k; - if (n === 0) { - return 0; - } - - // direct values? compute! - if (derivative === 0) { - value = 0; - for (k = 0; k <= n; k += 1) { - value += binomials(n, k) * (1 - t ** n - k) * t ** k * vs[k]; - } - return value; - } - // Still some derivative? go down one order, then try - // for the lower order curve's. - const vs1 = new Array(n); - for (k = 0; k < n; k += 1) { - vs1[k] = n * (vs[k + 1] - vs[k]); - } - return getDerivative(derivative - 1, t, vs1); -}; - -function B(xs: CtrlPoint, ys: CtrlPoint, t: number) { - const xbase = getDerivative(1, t, xs); - const ybase = getDerivative(1, t, ys); - const combined = xbase * xbase + ybase * ybase; - return Math.sqrt(combined); -} - -const getArcLength = (xs: CtrlPoint, ys: CtrlPoint, t = 1, n = 20) => { - if (xs.length >= tValues.length) { - throw new Error("too high n bezier"); - } - const z = t / 2; - let sum = 0; - let i; - for (i = 0; i < n; i += 1) { - const correctedT = z * tValues[n][i] + z; - sum += cValues[n][i] * B(xs, ys, correctedT); - } - return z * sum; -}; - -const cubicBezierLength = ( - p0: Point, - p1: Point, - p2: Point, - p3: Point -): number => { - const xs: CtrlPoint = [p0.x, p1.x, p2.x, p3.x]; - const ys: CtrlPoint = [p0.y, p1.y, p2.y, p3.y]; - return getArcLength(xs, ys); -}; - -export default cubicBezierLength; diff --git a/src/v1/bezier/CubicBezierSolve.ts b/src/v1/bezier/CubicBezierSolve.ts deleted file mode 100644 index a92b835..0000000 --- a/src/v1/bezier/CubicBezierSolve.ts +++ /dev/null @@ -1,164 +0,0 @@ -import Animated from "react-native-reanimated"; - -import { find } from "../Array"; -import { approximates } from "../Math"; - -const { - Value, - and, - cond, - divide, - add, - multiply, - block, - greaterThan, - eq, - lessThan, - pow, - sqrt, - set, - sub, - cos, - not, - acos, -} = Animated; - -const isRootValidForCubicBezier = (root: Animated.Node) => - and(greaterThan(root, 0), lessThan(root, 1)); - -// pomax.github.io/bezierinfo/#extremities -const cuberoot = (v: Animated.Adaptable) => - cond( - lessThan(v, 0), - multiply(pow(multiply(v, -1), 1 / 3), -1), - pow(v, 1 / 3) - ); - -const cubicBezierSolve = ( - pa: Animated.Adaptable, - pb: Animated.Adaptable, - pc: Animated.Adaptable, - pd: Animated.Adaptable -): Animated.Node => { - const a: Animated.Value = new Value(); - const b: Animated.Value = new Value(); - const c: Animated.Value = new Value(); - const d: Animated.Value = new Value(); - const root1: Animated.Value = new Value(); - const root2: Animated.Value = new Value(); - const root3: Animated.Value = new Value(); - - const q: Animated.Value = new Value(); - const q2: Animated.Value = new Value(); - const p: Animated.Value = new Value(); - const p3: Animated.Value = new Value(); - const discriminant: Animated.Value = new Value(); - - const mp3: Animated.Value = new Value(); - const mp33: Animated.Value = new Value(); - const r: Animated.Value = new Value(); - const t: Animated.Value = new Value(); - const cosphi: Animated.Value = new Value(); - const phi: Animated.Value = new Value(); - const crtr: Animated.Value = new Value(); - const t1: Animated.Value = new Value(); - - const u1: Animated.Value = new Value(); - - const sd: Animated.Value = new Value(); - const v1: Animated.Value = new Value(); - const sq: Animated.Value = 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, 0.001), - cond( - approximates(d, 0, 0.001), - cond( - not(approximates(b, 0, 0.001)), - 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; diff --git a/src/v1/index.ts b/src/v1/index.ts deleted file mode 100644 index 2bddf3e..0000000 --- a/src/v1/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export { default as ReText } from "./ReText"; -export * from "./Math"; -export * from "./Coordinates"; -export * from "./Colors"; -export * from "./AnimationRunners"; -export * from "./Gesture"; -export * from "./Array"; -export * from "./String"; -export * from "./SVG"; -export * from "./Animations"; -export * from "./Transitions"; -export * from "./Transformations"; -export * from "./Matrix3"; -export * from "./Matrix4"; -export * from "./Vectors"; -export * from "./Hooks"; diff --git a/tsconfig.json b/tsconfig.json index 7cbe634..38abd04 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,6 @@ "types": ["react", "react-native", "jest"], "skipLibCheck": true }, - "files": ["src/index.d.ts", "src/__tests__/index.ts", "src/v1/index.ts"], + "files": ["src/index.d.ts", "src/__tests__/index.ts"], "include": ["src/index.ts", "node_modules/@types/jest"] }