OSDN Git Service

Make ArcMotion material spec compliant
authorBen Weiss <benweiss@google.com>
Wed, 26 Oct 2016 16:16:41 +0000 (17:16 +0100)
committerBen Weiss <benweiss@google.com>
Thu, 5 Jan 2017 11:43:04 +0000 (11:43 +0000)
Upwards and downwards paths are
now curved in the same direction,
applying "gravity" to objects as they move around.

Test: CTS I40a5df051711fd719806cd88d87eeed68565d73d

Change-Id: I9e5323655dc7901393f90bb1ea2f393ca64b77ff

core/java/android/transition/ArcMotion.java

index 70443ba..da14834 100644 (file)
@@ -199,83 +199,77 @@ public class ArcMotion extends PathMotion {
 
         float ex;
         float ey;
-        if (startY == endY) {
-            ex = (startX + endX) / 2;
-            ey = startY + mMinimumHorizontalTangent * Math.abs(endX - startX) / 2;
-        } else if (startX == endX) {
-            ex = startX + mMinimumVerticalTangent * Math.abs(endY - startY) / 2;
-            ey = (startY + endY) / 2;
-        } else {
-            float deltaX = endX - startX;
-            float deltaY = endY - startY;
-            // hypotenuse squared.
-            float h2 = deltaX * deltaX + deltaY * deltaY;
+        float deltaX = endX - startX;
+        float deltaY = endY - startY;
+
+        // hypotenuse squared.
+        float h2 = deltaX * deltaX + deltaY * deltaY;
 
-            // Midpoint between start and end
-            float dx = (startX + endX) / 2;
-            float dy = (startY + endY) / 2;
+        // Midpoint between start and end
+        float dx = (startX + endX) / 2;
+        float dy = (startY + endY) / 2;
 
-            // Distance squared between end point and mid point is (1/2 hypotenuse)^2
-            float midDist2 = h2 * 0.25f;
+        // Distance squared between end point and mid point is (1/2 hypotenuse)^2
+        float midDist2 = h2 * 0.25f;
 
-            float minimumArcDist2 = 0;
-            boolean isQuadrant1Or3 = (deltaX * deltaY) > 0;
+        float minimumArcDist2 = 0;
 
-            if ((Math.abs(deltaX) < Math.abs(deltaY))) {
-                // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
-                // Therefore, eb = ab * bd / fb
-                // ab = hypotenuse
-                // bd = hypotenuse/2
-                // fb = deltaY
-                float eDistY = h2 / (2 * deltaY);
-                if (isQuadrant1Or3) {
-                    ey = startY + eDistY;
-                    ex = startX;
-                } else {
-                    ey = endY - eDistY;
-                    ex = endX;
-                }
+        boolean isMovingUpwards = startY > endY;
 
-                minimumArcDist2 = midDist2 * mMinimumVerticalTangent
-                        * mMinimumVerticalTangent;
+        if ((Math.abs(deltaX) < Math.abs(deltaY))) {
+            // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
+            // Therefore, eb = ab * bd / fb
+            // ab = hypotenuse
+            // bd = hypotenuse/2
+            // fb = deltaY
+            float eDistY = Math.abs(h2 / (2 * deltaY));
+            if (isMovingUpwards) {
+                ey = endY + eDistY;
+                ex = endX;
             } else {
-                // Same as above, but flip X & Y
-                float eDistX = h2 / (2 * deltaX);
-                if (isQuadrant1Or3) {
-                    ex = endX - eDistX;
-                    ey = endY;
-                } else {
-                    ex = startX + eDistX;
-                    ey = startY;
-                }
+                ey = startY + eDistY;
+                ex = startX;
+            }
 
-                minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
-                        * mMinimumHorizontalTangent;
+            minimumArcDist2 = midDist2 * mMinimumVerticalTangent
+                    * mMinimumVerticalTangent;
+        } else {
+            // Same as above, but flip X & Y and account for negative eDist
+            float eDistX = h2 / (2 * deltaX);
+            if (isMovingUpwards) {
+                ex = startX + eDistX;
+                ey = startY;
+            } else {
+                ex = endX - eDistX;
+                ey = endY;
             }
-            float arcDistX = dx - ex;
-            float arcDistY = dy - ey;
-            float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY;
 
-            float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
+            minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
+                    * mMinimumHorizontalTangent;
+        }
+        float arcDistX = dx - ex;
+        float arcDistY = dy - ey;
+        float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY;
 
-            float newArcDistance2 = 0;
-            if (arcDist2 < minimumArcDist2) {
-                newArcDistance2 = minimumArcDist2;
-            } else if (arcDist2 > maximumArcDist2) {
-                newArcDistance2 = maximumArcDist2;
-            }
-            if (newArcDistance2 != 0) {
-                float ratio2 = newArcDistance2 / arcDist2;
-                float ratio = (float) Math.sqrt(ratio2);
-                ex = dx + (ratio * (ex - dx));
-                ey = dy + (ratio * (ey - dy));
-            }
+        float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
+
+        float newArcDistance2 = 0;
+        if (arcDist2 < minimumArcDist2) {
+            newArcDistance2 = minimumArcDist2;
+        } else if (arcDist2 > maximumArcDist2) {
+            newArcDistance2 = maximumArcDist2;
+        }
+        if (newArcDistance2 != 0) {
+            float ratio2 = newArcDistance2 / arcDist2;
+            float ratio = (float) Math.sqrt(ratio2);
+            ex = dx + (ratio * (ex - dx));
+            ey = dy + (ratio * (ey - dy));
         }
-        float controlX1 = (startX + ex) / 2;
-        float controlY1 = (startY + ey) / 2;
-        float controlX2 = (ex + endX) / 2;
-        float controlY2 = (ey + endY) / 2;
-        path.cubicTo(controlX1, controlY1, controlX2, controlY2, endX, endY);
+        float control1X = (startX + ex) / 2;
+        float control1Y = (startY + ey) / 2;
+        float control2X = (ex + endX) / 2;
+        float control2Y = (ey + endY) / 2;
+        path.cubicTo(control1X, control1Y, control2X, control2Y, endX, endY);
         return path;
     }
 }