This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new b583328d64 feat(Math): add easing methods
b583328d64 is described below

commit b583328d64edbbe893e94e2e9fa8c5ea0f6a02a9
Author: jsorel <[email protected]>
AuthorDate: Sat May 2 23:48:39 2026 +0200

    feat(Math): add easing methods
---
 .../apache/sis/geometries/math/EasingMethod.java   | 302 +++++++++++++++++++++
 .../sis/geometries/math/EasingMethodTest.java      |  46 ++++
 2 files changed, 348 insertions(+)

diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/EasingMethod.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/EasingMethod.java
new file mode 100644
index 0000000000..68b11a6d35
--- /dev/null
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/EasingMethod.java
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometries.math;
+
+import java.util.function.DoubleUnaryOperator;
+
+/**
+ * Interpolation methods. The next methods provide non linear interpolation
+ * between zero and one. Such methods are often use for animations.
+ *
+ * Resources :
+ * 
http://iphonedevelopment.blogspot.fr/2010/12/more-animation-curves-than-you-can.html
+ * 
https://web.archive.org/web/20161020230122/http://iphonedevelopment.blogspot.com/2010/12/more-animation-curves-than-you-can.html
+ *
+ * quote : 'I've decided to release my animation curve functions as public
+ * domain (no attribute required, no rights reserved)'
+ *
+ * @author Jeff LaMarche (original source code in C)
+ * @author Johann Sorel (Java port in Unlicense-lib)
+ */
+public final class EasingMethod implements DoubleUnaryOperator {
+
+    public static enum Method {
+        LINEAR,
+        QUADRATIC_EASE_OUT,
+        QUADRATIC_EASE_IN,
+        QUADRATIC_EASE_IN_OUT,
+        CUBIC_EASE_OUT,
+        CUBIC_EASE_IN,
+        CUBIC_EASE_IN_OUT,
+        QUARTIC_EASE_OUT,
+        QUARTIC_EASE_IN,
+        QUARTIC_EASE_IN_OUT,
+        QUINTIC_EASE_OUT,
+        QUINTIC_EASE_IN,
+        QUINTIC_EASE_IN_OUT,
+        SINUSOIDAL_EASE_OUT,
+        SINUSOIDAL_EASE_IN,
+        SINUSOIDAL_EASE_IN_OUT,
+        EXPONENTIAL_EASE_OUT,
+        EXPONENTIAL_EASE_IN,
+        EXPONENTIAL_EASE_IN_OUT,
+        CIRCULAR_EASE_OUT,
+        CIRCULAR_EASE_IN,
+        CIRCULAR_EASE_IN_OUT
+    }
+
+    private final Method method;
+    private final double start;
+    private final double end;
+
+    public EasingMethod(Method method) {
+        this(method, 0.0, 1.0);
+    }
+
+    public EasingMethod(Method method, double start, double end) {
+        this.method = method;
+        this.start = start;
+        this.end = end;
+    }
+
+    /**
+     * Interpolation between start and end.
+     *
+     * @param t time between 0 and 1
+     * @return interpolated value.
+     */
+    @Override
+    public double applyAsDouble(double t) {
+        switch(method){
+            case LINEAR :                    return linear(t, start, end);
+            case QUADRATIC_EASE_OUT :        return quadraticEaseOut(t, start, 
end);
+            case QUADRATIC_EASE_IN :         return quadraticEaseIn(t, start, 
end);
+            case QUADRATIC_EASE_IN_OUT :     return quadraticEaseInOut(t, 
start, end);
+            case CUBIC_EASE_OUT :            return cubicEaseOut(t, start, 
end);
+            case CUBIC_EASE_IN :             return cubicEaseIn(t, start, end);
+            case CUBIC_EASE_IN_OUT :         return cubicEaseInOut(t, start, 
end);
+            case QUARTIC_EASE_OUT :          return quarticEaseOut(t, start, 
end);
+            case QUARTIC_EASE_IN :           return quarticEaseIn(t, start, 
end);
+            case QUARTIC_EASE_IN_OUT :       return quarticEaseInOut(t, start, 
end);
+            case QUINTIC_EASE_OUT :          return quinticEaseOut(t, start, 
end);
+            case QUINTIC_EASE_IN :           return quinticEaseIn(t, start, 
end);
+            case QUINTIC_EASE_IN_OUT :       return quinticEaseInOut(t, start, 
end);
+            case SINUSOIDAL_EASE_OUT :       return sinusoidalEaseOut(t, 
start, end);
+            case SINUSOIDAL_EASE_IN :        return sinusoidalEaseIn(t, start, 
end);
+            case SINUSOIDAL_EASE_IN_OUT :    return sinusoidalEaseInOut(t, 
start, end);
+            case EXPONENTIAL_EASE_OUT :      return exponentialEaseOut(t, 
start, end);
+            case EXPONENTIAL_EASE_IN :       return exponentialEaseIn(t, 
start, end);
+            case EXPONENTIAL_EASE_IN_OUT :   return exponentialEaseInOut(t, 
start, end);
+            case CIRCULAR_EASE_OUT :         return circularEaseOut(t, start, 
end);
+            case CIRCULAR_EASE_IN :          return circularEaseIn(t, start, 
end);
+            case CIRCULAR_EASE_IN_OUT :      return circularEaseInOut(t, 
start, end);
+            default: throw new IllegalArgumentException("Unknown method : " + 
method);
+        }
+    }
+
+    public static double linear(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return t * end + (1.0 - t) * start;
+    }
+
+    public static double cubic(double[] points, double x) {
+        return points[1] + 0.5 * x * (points[2] - points[0] + x * 
(2.0*points[0] - 5.0*points[1] + 4.0*points[2] - points[3] + x*(3.0*(points[1] 
- points[2]) + points[3] - points[0])));
+    }
+
+    public static double quadraticEaseOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return -end * t * (t - 2.0) - 1.0;
+    }
+
+    public static double quadraticEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * t * t + start - 1.0;
+    }
+
+    public static double quadraticEaseInOut(double t, double start, double 
end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return end / 2.0 * t * t + start - 1.0;
+        }
+        t--;
+        return -end / 2.0 * (t * (t - 2) - 1.0) + start - 1.0;
+    }
+
+    public static double cubicEaseOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t--;
+        return end * (t * t * t + 1.0) + start - 1.0;
+    }
+
+    public static double cubicEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * t * t * t + start - 1.0;
+    }
+
+    public static double cubicEaseInOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return end / 2.0 * t * t * t + start - 1.0;
+        }
+        t -= 2.0;
+        return end / 2.0 * (t * t * t + 2.0) + start - 1.0;
+    }
+
+    public static double quarticEaseOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t--;
+        return -end * (t * t * t * t - 1.0) + start - 1.0;
+    }
+
+    public static double quarticEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * t * t * t * t + start;
+    }
+
+    public static double quarticEaseInOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return end / 2.0 * t * t * t * t + start - 1.0;
+        }
+        t -= 2.0;
+        return -end / 2.0 * (t * t * t * t - 2.0) + start - 1.0;
+    }
+
+    public static double quinticEaseOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t--;
+        return end * (t * t * t * t * t + 1) + start - 1.0;
+    }
+
+    public static double quinticEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * t * t * t * t * t + start - 1.0;
+    }
+
+    public static double quinticEaseInOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return end / 2.0 * t * t * t * t * t + start - 1.0;
+        }
+        t -= 2.0;
+        return end / 2.0 * (t * t * t * t * t + 2.0) + start - 1.0;
+    }
+
+    public static double sinusoidalEaseOut(double t, double start, double end) 
{
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * Math.sin(t * (Math.PI / 2.0)) + start - 1.0;
+    }
+
+    public static double sinusoidalEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return -end * Math.cos(t * (Math.PI / 2.0)) + end + start - 1.0;
+    }
+
+    public static double sinusoidalEaseInOut(double t, double start, double 
end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return -end / 2.0 * (Math.cos(Math.PI * t) - 1.0) + start - 1.0;
+    }
+
+    public static double exponentialEaseOut(double t, double start, double 
end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * (-Math.pow(2.0, -10.0 * t) + 1.0) + start - 1.0;
+    }
+
+    public static double exponentialEaseIn(double t, double start, double end) 
{
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return end * Math.pow(2.0, 10.0 * (t - 1.0)) + start - 1.0;
+    }
+
+    public static double exponentialEaseInOut(double t, double start, double 
end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return end / 2.0 * Math.pow(2.0, 10.0 * (t - 1.0)) + start - 1.0;
+        }
+        t--;
+        return end / 2.0 * (-Math.pow(2.0, -10.0 * t) + 2.0) + start - 1.0;
+    }
+
+    public static double circularEaseOut(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t--;
+        return end * Math.sqrt(1.0 - t * t) + start - 1.0;
+    }
+
+    public static double circularEaseIn(double t, double start, double end) {
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        return -end * (Math.sqrt(1.0 - t * t) - 1.0) + start - 1.0;
+    }
+
+    public static double circularEaseInOut(double t, double start, double end) 
{
+        if (t<=0.0) return start;
+        if (t>=1.0) return end;
+
+        t *= 2.0;
+        if (t < 1.0) {
+            return -end / 2.0 * (Math.sqrt(1.0 - t * t) - 1.0) + start - 1.0;
+        }
+        t -= 2.0;
+        return end / 2.0 * (Math.sqrt(1.0 - t * t) + 1.0) + start - 1.0;
+    }
+}
diff --git 
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/EasingMethodTest.java
 
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/EasingMethodTest.java
new file mode 100644
index 0000000000..7d2e729c4b
--- /dev/null
+++ 
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/EasingMethodTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometries.math;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Easing method tests.
+ *
+ * @author Johann Sorel
+ */
+public class EasingMethodTest {
+    protected static final double TOLERANCE = 0.0000001;
+
+    public EasingMethodTest(){}
+
+    @Test
+    public void testStartEndValues() {
+
+        for (EasingMethod.Method method : EasingMethod.Method.values()) {
+            final EasingMethod increasing = new EasingMethod(method, 10.0, 
20.0);
+            assertEquals(10.0, increasing.applyAsDouble(-1.0));
+            assertEquals(10.0, increasing.applyAsDouble( 0.0));
+            assertEquals(20.0, increasing.applyAsDouble( 1.0));
+            assertEquals(20.0, increasing.applyAsDouble( 2.0));
+
+        }
+
+    }
+
+}

Reply via email to