1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.animation;
  27 
  28 import com.sun.javafx.animation.TickCalculation;
  29 import com.sun.scenario.animation.shared.InterpolationInterval;
  30 import javafx.animation.Interpolatable;
  31 import javafx.animation.Interpolator;
  32 import javafx.animation.KeyValue;
  33 import javafx.beans.property.Property;
  34 import javafx.beans.property.SimpleLongProperty;
  35 import javafx.util.Duration;
  36 import static org.junit.Assert.assertEquals;
  37 
  38 import org.junit.Test;
  39 
  40 public class InterpolatorTest {
  41 
  42     private static final double EPSILON = 1e-12;
  43     private static final float EPSILON_FLOAT = 1e-6f;
  44     private static final DummyInterpolatable START = new DummyInterpolatable(0);
  45     private static final DummyInterpolatable END   = new DummyInterpolatable(10);
  46     
  47     @Test
  48     public void testInterpolateWithObjects() {
  49         final DummyInterpolatable i1 = new DummyInterpolatable(1);
  50         final DummyInterpolatable i2 = new DummyInterpolatable(4);
  51         final Object o = new Object();
  52         
  53         assertEquals(Double.valueOf(2.5), (Double)Interpolator.LINEAR.interpolate(Double.valueOf(1), Integer.valueOf(4), 0.5), EPSILON);
  54         assertEquals(Double.valueOf(2.5), (Double)Interpolator.LINEAR.interpolate(Integer.valueOf(4), Double.valueOf(1), 0.5), EPSILON);
  55         assertEquals(Float.valueOf(2.5f), (Float)Interpolator.LINEAR.interpolate(Float.valueOf(1), Integer.valueOf(4), 0.5), EPSILON_FLOAT);
  56         assertEquals(Float.valueOf(2.5f), (Float)Interpolator.LINEAR.interpolate(Integer.valueOf(4), Float.valueOf(1), 0.5), EPSILON_FLOAT);
  57         assertEquals(Long.valueOf(3L), Interpolator.LINEAR.interpolate(Long.valueOf(1), Integer.valueOf(4),  0.5));
  58         assertEquals(Long.valueOf(3L), Interpolator.LINEAR.interpolate(Integer.valueOf(4), Long.valueOf(1), 0.5));
  59         assertEquals(Integer.valueOf(3), Interpolator.LINEAR.interpolate(Integer.valueOf(1), Integer.valueOf(4), 0.5));
  60         assertEquals(2.5, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(i1, i2, 0.5)).value, EPSILON);
  61         
  62         assertEquals(o, Interpolator.LINEAR.interpolate(o, Integer.MIN_VALUE, 1.0-2*EPSILON));
  63         assertEquals(Integer.MIN_VALUE, Interpolator.LINEAR.interpolate(o, Integer.MIN_VALUE, 1.0));
  64         
  65         assertEquals(Integer.MIN_VALUE, Interpolator.LINEAR.interpolate(Integer.MIN_VALUE, o, 1.0-2*EPSILON));
  66         assertEquals(o, Interpolator.LINEAR.interpolate(Integer.MIN_VALUE, o, 1.0));
  67         
  68         assertEquals(i1, Interpolator.LINEAR.interpolate(i1, o, 1.0-2*EPSILON));
  69         assertEquals(o, Interpolator.LINEAR.interpolate(i1, o, 1.0));
  70     }
  71 
  72     @Test
  73     public void testDISCRETE() {
  74         assertEquals(false, Interpolator.DISCRETE.interpolate(false, true, 1.0-2*EPSILON));
  75         assertEquals(true, Interpolator.DISCRETE.interpolate(false, true, 1.0));
  76                 
  77         assertEquals(1.0, Interpolator.DISCRETE.interpolate(1.0, 2.0, 1.0-2*EPSILON), EPSILON);
  78         assertEquals(2.0, Interpolator.DISCRETE.interpolate(1.0, 2.0, 1.0), EPSILON);
  79 
  80         assertEquals(-3, Interpolator.DISCRETE.interpolate(-3, 7, 1.0-2*EPSILON));
  81         assertEquals( 7, Interpolator.DISCRETE.interpolate(-3, 7, 1.0));
  82 
  83         assertEquals(  12L, Interpolator.DISCRETE.interpolate(12L, -201L, 1.0-2*EPSILON));
  84         assertEquals(-201L, Interpolator.DISCRETE.interpolate(12L, -201L, 1.0));
  85 
  86         assertEquals( 0, ((DummyInterpolatable)Interpolator.DISCRETE.interpolate(START, END, 1.0-2*EPSILON)).value, EPSILON);
  87         assertEquals(10, ((DummyInterpolatable)Interpolator.DISCRETE.interpolate(START, END, 1.0)).value, EPSILON);
  88     }
  89 
  90     @Test
  91     public void testLINEAR() {
  92         assertEquals(false, Interpolator.LINEAR.interpolate(false, true, 0.0));
  93         assertEquals(false, Interpolator.LINEAR.interpolate(false, true, 0.1));
  94         assertEquals(false, Interpolator.LINEAR.interpolate(false, true, 0.5));
  95         assertEquals(false, Interpolator.LINEAR.interpolate(false, true, 0.9));
  96         assertEquals(true, Interpolator.LINEAR.interpolate(false, true, 1.0));
  97 
  98         assertEquals(1.0, Interpolator.LINEAR.interpolate(1.0, 2.0, 0.0), EPSILON);
  99         assertEquals(1.1, Interpolator.LINEAR.interpolate(1.0, 2.0, 0.1), EPSILON);
 100         assertEquals(1.5, Interpolator.LINEAR.interpolate(1.0, 2.0, 0.5), EPSILON);
 101         assertEquals(1.9, Interpolator.LINEAR.interpolate(1.0, 2.0, 0.9), EPSILON);
 102         assertEquals(2.0, Interpolator.LINEAR.interpolate(1.0, 2.0, 1.0), EPSILON);
 103 
 104         assertEquals(-3, Interpolator.LINEAR.interpolate(-3, 7, 0.0));
 105         assertEquals(-2, Interpolator.LINEAR.interpolate(-3, 7, 0.1));
 106         assertEquals( 2, Interpolator.LINEAR.interpolate(-3, 7, 0.5));
 107         assertEquals( 6, Interpolator.LINEAR.interpolate(-3, 7, 0.9));
 108         assertEquals( 7, Interpolator.LINEAR.interpolate(-3, 7, 1.0));
 109 
 110         assertEquals(-3L, Interpolator.LINEAR.interpolate(-3L, 7L, 0.0));
 111         assertEquals(-2L, Interpolator.LINEAR.interpolate(-3L, 7L, 0.1));
 112         assertEquals( 2L, Interpolator.LINEAR.interpolate(-3L, 7L, 0.5));
 113         assertEquals( 6L, Interpolator.LINEAR.interpolate(-3L, 7L, 0.9));
 114         assertEquals( 7L, Interpolator.LINEAR.interpolate(-3L, 7L, 1.0));
 115 
 116         assertEquals( 0, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(START, END, 0.0)).value, EPSILON);
 117         assertEquals( 1, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(START, END, 0.1)).value, EPSILON);
 118         assertEquals( 5, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(START, END, 0.5)).value, EPSILON);
 119         assertEquals( 9, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(START, END, 0.9)).value, EPSILON);
 120         assertEquals(10, ((DummyInterpolatable)Interpolator.LINEAR.interpolate(START, END, 1.0)).value, EPSILON);
 121     }
 122 
 123     @Test
 124     public void testEASE_BOTH() {
 125         // Expected results calculated with JavaFX SDK 1.3
 126         
 127         assertEquals(false, Interpolator.EASE_BOTH.interpolate(false, true, 0.0));
 128         assertEquals(false, Interpolator.EASE_BOTH.interpolate(false, true, 0.1));
 129         assertEquals(false, Interpolator.EASE_BOTH.interpolate(false, true, 0.5));
 130         assertEquals(false, Interpolator.EASE_BOTH.interpolate(false, true, 0.9));
 131         assertEquals(true, Interpolator.EASE_BOTH.interpolate(false, true, 1.0));
 132         
 133         assertEquals(1.0,   Interpolator.EASE_BOTH.interpolate(1.0, 2.0, 0.0), EPSILON);
 134         assertEquals(1.125, Interpolator.EASE_BOTH.interpolate(1.0, 2.0, 0.2), EPSILON);
 135         assertEquals(1.5,   Interpolator.EASE_BOTH.interpolate(1.0, 2.0, 0.5), EPSILON);
 136         assertEquals(1.875, Interpolator.EASE_BOTH.interpolate(1.0, 2.0, 0.8), EPSILON);
 137         assertEquals(2.0,   Interpolator.EASE_BOTH.interpolate(1.0, 2.0, 1.0), EPSILON);
 138 
 139         assertEquals(-3, Interpolator.EASE_BOTH.interpolate(-3, 7, 0.0));
 140         assertEquals(-2, Interpolator.EASE_BOTH.interpolate(-3, 7, 0.2));
 141         assertEquals( 2, Interpolator.EASE_BOTH.interpolate(-3, 7, 0.5));
 142         assertEquals( 6, Interpolator.EASE_BOTH.interpolate(-3, 7, 0.8));
 143         assertEquals( 7, Interpolator.EASE_BOTH.interpolate(-3, 7, 1.0));
 144 
 145         assertEquals(-3L, Interpolator.EASE_BOTH.interpolate(-3L, 7L, 0.0));
 146         assertEquals(-2L, Interpolator.EASE_BOTH.interpolate(-3L, 7L, 0.2));
 147         assertEquals( 2L, Interpolator.EASE_BOTH.interpolate(-3L, 7L, 0.5));
 148         assertEquals( 6L, Interpolator.EASE_BOTH.interpolate(-3L, 7L, 0.8));
 149         assertEquals( 7L, Interpolator.EASE_BOTH.interpolate(-3L, 7L, 1.0));
 150 
 151         assertEquals( 0,    ((DummyInterpolatable)Interpolator.EASE_BOTH.interpolate(START, END, 0.0)).value, EPSILON);
 152         assertEquals( 1.25, ((DummyInterpolatable)Interpolator.EASE_BOTH.interpolate(START, END, 0.2)).value, EPSILON);
 153         assertEquals( 5,    ((DummyInterpolatable)Interpolator.EASE_BOTH.interpolate(START, END, 0.5)).value, EPSILON);
 154         assertEquals( 8.75, ((DummyInterpolatable)Interpolator.EASE_BOTH.interpolate(START, END, 0.8)).value, EPSILON);
 155         assertEquals(10,    ((DummyInterpolatable)Interpolator.EASE_BOTH.interpolate(START, END, 1.0)).value, EPSILON);
 156     }
 157 
 158     @Test
 159     public void testEASE_IN() {
 160         // Expected results calculated with JavaFX SDK 1.3
 161         
 162         assertEquals(false, Interpolator.EASE_IN.interpolate(false, true, 0.0));
 163         assertEquals(false, Interpolator.EASE_IN.interpolate(false, true, 0.1));
 164         assertEquals(false, Interpolator.EASE_IN.interpolate(false, true, 0.5));
 165         assertEquals(false, Interpolator.EASE_IN.interpolate(false, true, 0.9));
 166         assertEquals(true, Interpolator.EASE_IN.interpolate(false, true, 1.0));
 167         
 168         assertEquals(1.0,      Interpolator.EASE_IN.interpolate(1.0, 2.0, 0.0), EPSILON);
 169         assertEquals(1.1111111111111112, Interpolator.EASE_IN.interpolate(1.0, 2.0, 0.2), EPSILON);
 170         assertEquals(1.4444444444444444, Interpolator.EASE_IN.interpolate(1.0, 2.0, 0.5), EPSILON);
 171         assertEquals(1.777777777777778, Interpolator.EASE_IN.interpolate(1.0, 2.0, 0.8), EPSILON);
 172         assertEquals(2.0,      Interpolator.EASE_IN.interpolate(1.0, 2.0, 1.0), EPSILON);
 173 
 174         assertEquals(-3, Interpolator.EASE_IN.interpolate(-3, 7, 0.0));
 175         assertEquals(-2, Interpolator.EASE_IN.interpolate(-3, 7, 0.2));
 176         assertEquals( 1, Interpolator.EASE_IN.interpolate(-3, 7, 0.5));
 177         assertEquals( 5, Interpolator.EASE_IN.interpolate(-3, 7, 0.8));
 178         assertEquals( 7, Interpolator.EASE_IN.interpolate(-3, 7, 1.0));
 179 
 180         assertEquals(-3L, Interpolator.EASE_IN.interpolate(-3L, 7L, 0.0));
 181         assertEquals(-2L, Interpolator.EASE_IN.interpolate(-3L, 7L, 0.2));
 182         assertEquals( 1L, Interpolator.EASE_IN.interpolate(-3L, 7L, 0.5));
 183         assertEquals( 5L, Interpolator.EASE_IN.interpolate(-3L, 7L, 0.8));
 184         assertEquals( 7L, Interpolator.EASE_IN.interpolate(-3L, 7L, 1.0));
 185 
 186         assertEquals( 0,        ((DummyInterpolatable)Interpolator.EASE_IN.interpolate(START, END, 0.0)).value, EPSILON);
 187         assertEquals( 1.1111111111111114, ((DummyInterpolatable)Interpolator.EASE_IN.interpolate(START, END, 0.2)).value, EPSILON);
 188         assertEquals( 4.444444444444445, ((DummyInterpolatable)Interpolator.EASE_IN.interpolate(START, END, 0.5)).value, EPSILON);
 189         assertEquals( 7.777777777777779, ((DummyInterpolatable)Interpolator.EASE_IN.interpolate(START, END, 0.8)).value, EPSILON);
 190         assertEquals(10,        ((DummyInterpolatable)Interpolator.EASE_IN.interpolate(START, END, 1.0)).value, EPSILON);
 191     }
 192 
 193     @Test
 194     public void testEASE_OUT() {
 195         // Expected results calculated with JavaFX SDK 1.3
 196         
 197         assertEquals(false, Interpolator.EASE_OUT.interpolate(false, true, 0.0));
 198         assertEquals(false, Interpolator.EASE_OUT.interpolate(false, true, 0.1));
 199         assertEquals(false, Interpolator.EASE_OUT.interpolate(false, true, 0.5));
 200         assertEquals(false, Interpolator.EASE_OUT.interpolate(false, true, 0.9));
 201         assertEquals(true, Interpolator.EASE_OUT.interpolate(false, true, 1.0));
 202         
 203         assertEquals(1.0,      Interpolator.EASE_OUT.interpolate(1.0, 2.0, 0.0), EPSILON);
 204         assertEquals(1.2222222222222223, Interpolator.EASE_OUT.interpolate(1.0, 2.0, 0.2), EPSILON);
 205         assertEquals(1.5555555555555556, Interpolator.EASE_OUT.interpolate(1.0, 2.0, 0.5), EPSILON);
 206         assertEquals(1.8888888888888888, Interpolator.EASE_OUT.interpolate(1.0, 2.0, 0.8), EPSILON);
 207         assertEquals(2.0,      Interpolator.EASE_OUT.interpolate(1.0, 2.0, 1.0), EPSILON);
 208 
 209         assertEquals(-3, Interpolator.EASE_OUT.interpolate(-3, 7, 0.0));
 210         assertEquals(-1, Interpolator.EASE_OUT.interpolate(-3, 7, 0.2));
 211         assertEquals( 3, Interpolator.EASE_OUT.interpolate(-3, 7, 0.5));
 212         assertEquals( 6, Interpolator.EASE_OUT.interpolate(-3, 7, 0.8));
 213         assertEquals( 7, Interpolator.EASE_OUT.interpolate(-3, 7, 1.0));
 214 
 215         assertEquals(-3L, Interpolator.EASE_OUT.interpolate(-3L, 7L, 0.0));
 216         assertEquals(-1L, Interpolator.EASE_OUT.interpolate(-3L, 7L, 0.2));
 217         assertEquals( 3L, Interpolator.EASE_OUT.interpolate(-3L, 7L, 0.5));
 218         assertEquals( 6L, Interpolator.EASE_OUT.interpolate(-3L, 7L, 0.8));
 219         assertEquals( 7L, Interpolator.EASE_OUT.interpolate(-3L, 7L, 1.0));
 220 
 221         assertEquals( 0,        ((DummyInterpolatable)Interpolator.EASE_OUT.interpolate(START, END, 0.0)).value, EPSILON);
 222         assertEquals( 2.2222222222222223, ((DummyInterpolatable)Interpolator.EASE_OUT.interpolate(START, END, 0.2)).value, EPSILON);
 223         assertEquals( 5.555555555555555, ((DummyInterpolatable)Interpolator.EASE_OUT.interpolate(START, END, 0.5)).value, EPSILON);
 224         assertEquals( 8.88888888888889, ((DummyInterpolatable)Interpolator.EASE_OUT.interpolate(START, END, 0.8)).value, EPSILON);
 225         assertEquals(10,        ((DummyInterpolatable)Interpolator.EASE_OUT.interpolate(START, END, 1.0)).value, EPSILON);
 226     }
 227 
 228     @Test
 229     public void testSPLINE_Concave() {
 230         Interpolator i = Interpolator.SPLINE(0.0, 0.5, 0.5, 1.0);
 231         assertEquals(1.0, i.interpolate(1.0, 2.0, 0.0), EPSILON);
 232         assertEquals(1.5573742287206063, i.interpolate(1.0, 2.0, 0.2), EPSILON);
 233         assertEquals(1.8400223953585164, i.interpolate(1.0, 2.0, 0.5), EPSILON);
 234         assertEquals(1.9742173260814238, i.interpolate(1.0, 2.0, 0.8), EPSILON);
 235         assertEquals(2.0, i.interpolate(1.0, 2.0, 1.0), EPSILON);
 236     }
 237 
 238     @Test
 239     public void testSPLINE_Convex() {
 240         Interpolator i = Interpolator.SPLINE(0.5, 0.0, 1.0, 0.5);
 241         assertEquals(1.0, i.interpolate(1.0, 2.0, 0.0), EPSILON);
 242         assertEquals(1.0257826739185762, i.interpolate(1.0, 2.0, 0.2), EPSILON);
 243         assertEquals(1.1599776046414838, i.interpolate(1.0, 2.0, 0.5), EPSILON);
 244         assertEquals(1.4426257712793937, i.interpolate(1.0, 2.0, 0.8), EPSILON);
 245         assertEquals(2.0, i.interpolate(1.0, 2.0, 1.0), EPSILON);
 246     }
 247 
 248     @Test
 249     public void testSPLINE_WithInflectionPoint() {
 250         Interpolator i = Interpolator.SPLINE(0.0, 1.0, 1.0, 0.0);
 251 
 252         assertEquals(1.0, i.interpolate(1.0, 2.0, 0.0), EPSILON);
 253         assertEquals(1.4614221762502215, i.interpolate(1.0, 2.0, 0.2), EPSILON);
 254         assertEquals(1.5, i.interpolate(1.0, 2.0, 0.5), EPSILON);
 255         assertEquals(1.5385778237497787, i.interpolate(1.0, 2.0, 0.8), EPSILON);
 256         assertEquals(2.0, i.interpolate(1.0, 2.0, 1.0), EPSILON);
 257     }
 258 
 259     @Test
 260     public void testSPLINE_Linear() {
 261         Interpolator i = Interpolator.SPLINE(1/3, 1/3, 2/3, 2/3);
 262 
 263         assertEquals(1.0, i.interpolate(1.0, 2.0, 0.0), EPSILON);
 264         assertEquals(1.2, i.interpolate(1.0, 2.0, 0.2), EPSILON);
 265         assertEquals(1.5, i.interpolate(1.0, 2.0, 0.5), EPSILON);
 266         assertEquals(1.8, i.interpolate(1.0, 2.0, 0.8), EPSILON);
 267         assertEquals(2.0, i.interpolate(1.0, 2.0, 1.0), EPSILON);
 268     }
 269 
 270     @Test
 271     public void testTANGENT_Linear() {
 272         SimpleLongProperty property = new SimpleLongProperty();
 273 
 274         Interpolator i0 = Interpolator.TANGENT(Duration.seconds(1), 20);
 275         Interpolator i1 = Interpolator.TANGENT(Duration.seconds(1), 40);
 276 
 277         InterpolationInterval interval = InterpolationInterval.create(new KeyValue(property, 60L, i1),
 278                 TickCalculation.fromDuration(Duration.seconds(3)),
 279                 new KeyValue(property, 0L, i0), TickCalculation.fromDuration(Duration.seconds(3)));
 280 
 281         interval.interpolate(1.0/3.0);
 282         assertEquals(20L, (long)property.getValue());
 283         interval.interpolate(1.0/2.0);
 284         assertEquals(30L, (long)property.getValue());
 285         interval.interpolate(2.0/3.0);
 286         assertEquals(40L, (long)property.getValue());
 287     }
 288     
 289     private static class DummyInterpolatable implements Interpolatable<DummyInterpolatable> {
 290 
 291         final double value;
 292 
 293         private DummyInterpolatable(double value) {
 294                 this.value = value;
 295         }
 296 
 297         @Override
 298         public DummyInterpolatable interpolate(DummyInterpolatable endVal, double t) {
 299                 if (Math.abs(t) < EPSILON) {
 300                         return this;
 301                 } else if (Math.abs(t-1.0) < EPSILON) {
 302                         return endVal;
 303                 } else {
 304                         return new DummyInterpolatable(value + t * (endVal.value - value));
 305                 }
 306         }
 307     }
 308 }