From 4540521988bda4f69ddbf1b1f2942c712ec5162d Mon Sep 17 00:00:00 2001 From: facelessuser Date: Wed, 5 Feb 2025 00:20:02 -0700 Subject: [PATCH] Easing changes - Use Ostrowski Method in easing - More precise inverse easing for RYB Biased --- coloraide/algebra.py | 6 ++++-- coloraide/easing.py | 6 ++++-- coloraide/spaces/ryb.py | 4 ++-- docs/src/markdown/about/changelog.md | 1 + tests/test_easing.py | 24 ++++++++++++------------ 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/coloraide/algebra.py b/coloraide/algebra.py index b553ddeb..149aafa6 100644 --- a/coloraide/algebra.py +++ b/coloraide/algebra.py @@ -243,6 +243,8 @@ def solve_newton( yn = xn - f(xn) / f'(xn) ostrowski = yn - f(xn) / (f(xn) - 2 * f(yn)) * (f(yn) / f'(xn)) ``` + + Return result along with True if converged, False if did not converge, None if could not converge. """ for _ in range(maxiter): @@ -281,9 +283,9 @@ def solve_newton( return x0, True fy_x2 = 2 * fy if fy_x2 == fx: - return x0, False + return x0, None x1 = x0 - fx / (fx - fy_x2) * (fy / d1) - if abs(x1 - x0) < epsilon: + if abs(x1 - prev) < epsilon: return x1, True x0 = x1 diff --git a/coloraide/easing.py b/coloraide/easing.py index 441fe14c..d24dc70e 100644 --- a/coloraide/easing.py +++ b/coloraide/easing.py @@ -43,7 +43,7 @@ from . import algebra as alg from typing import Callable -EPSILON = 1e-6 +EPSILON = 1e-12 MAX_ITER = 8 @@ -87,7 +87,9 @@ def _solve_bezier( t, f0, _bezier_derivative(a, b, c), - maxiter=maxiter + maxiter=maxiter, + epsilon=eps, + ostrowski=True ) # We converged or we are close enough diff --git a/coloraide/spaces/ryb.py b/coloraide/spaces/ryb.py index 52045d6e..1e15930a 100644 --- a/coloraide/spaces/ryb.py +++ b/coloraide/spaces/ryb.py @@ -11,7 +11,7 @@ from ..channels import Channel from ..cat import WHITES from ..types import Vector, Matrix -from ..easing import _bezier, _solve_bezier +from ..easing import _bezier # In terms of RGB GOSSET_CHEN_CUBE = [ @@ -32,7 +32,7 @@ def srgb_to_ryb(rgb: Vector, cube_t: Matrix, cube: Matrix, biased: bool) -> Vect # Calculate the RYB value ryb = alg.ilerp3d(cube_t, rgb, vertices_t=cube) # Remove smoothstep easing if "biased" is enabled. - return [_solve_bezier(t, -2.0, 3.0, 0.0) if 0 <= t <= 1 else t for t in ryb] if biased else ryb + return [_bezier(2, -3, 2)(t) if 0 <= t <= 1 else t for t in ryb] if biased else ryb def ryb_to_srgb(ryb: Vector, cube_t: Matrix, biased: bool) -> Vector: diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md index 4364eadc..44242720 100644 --- a/docs/src/markdown/about/changelog.md +++ b/docs/src/markdown/about/changelog.md @@ -2,6 +2,7 @@ ## 4.2.2 +- **FIX**: More precise inverse of RYB Biased. - **FIX**: Speed up solving of cubic bezier for easing functions. - **FIX**: Protect against possible divide by zero in HCT reverse transform. diff --git a/tests/test_easing.py b/tests/test_easing.py index 94b75e17..b49b6663 100644 --- a/tests/test_easing.py +++ b/tests/test_easing.py @@ -32,7 +32,7 @@ def test_bisect(self): """ ease_in_out_expo = cubic_bezier(1.000, 0.000, 0.000, 1.000) - self.assertEqual(ease_in_out_expo(0.43), 0.14556343840627634) + self.assertEqual(ease_in_out_expo(0.43), 0.14556294236066833) class TestEasingMethods(unittest.TestCase): @@ -90,7 +90,7 @@ def test_ease(self): -0.08000000000000002, -0.040000000000000015, -1.1102230246251566e-17, - 0.09479630571604325, + 0.09479630571604322, 0.2952443342678225, 0.5133151609733584, 0.6825405059781395, @@ -120,15 +120,15 @@ def test_ease_in(self): 0.0, 0.0, 0.0, - 0.01702660965156293, + 0.017026609651562934, 0.06228200013673226, 0.12957676084535252, 0.21486093875289342, 0.3153568125725393, - 0.4291197692963171, + 0.42911976929631723, 0.5548140325286628, 0.6916339333193129, - 0.8394278457624664, + 0.8394278457624662, 0.9999999999999998, 1.172413793103448, 1.3448275862068964, @@ -152,14 +152,14 @@ def test_ease_out(self): -4.785444071660158e-17, 0.16057215423753346, 0.3083660666806869, - 0.445185967471337, + 0.44518596747133715, 0.5708802307036829, 0.6846431874274606, 0.7851390612471065, 0.8704232391546475, 0.9377179998632681, - 0.982973390348437, - 0.9999999999999998, + 0.9829733903484374, + 1.0, 1.0, 1.0, 1.0, @@ -183,13 +183,13 @@ def test_ease_in_out(self): 0.01972245354831119, 0.08165985626589745, 0.18739590670531256, - 0.33188387009764614, + 0.3318838700976461, 0.5, 0.668116129902354, - 0.8126040932946875, + 0.8126040932946876, 0.9183401437341026, - 0.9802775464516886, - 1.0, + 0.9802775464516889, + 0.9999999999999998, 1.0, 1.0, 1.0,