1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.transition.cts;
17 
18 import static org.junit.Assert.assertEquals;
19 
20 import android.graphics.Path;
21 import android.transition.ArcMotion;
22 
23 import androidx.test.filters.SmallTest;
24 import androidx.test.runner.AndroidJUnit4;
25 
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 
29 @SmallTest
30 @RunWith(AndroidJUnit4.class)
31 public class ArcMotionTest extends PathMotionTest {
32     @Test
test90Quadrants()33     public void test90Quadrants() {
34         ArcMotion arcMotion = new ArcMotion();
35         arcMotion.setMaximumAngle(90);
36 
37         Path expected = arcWithPoint(0, 100, 100, 0, 100, 100);
38         Path path = arcMotion.getPath(0, 100, 100, 0);
39         assertPathMatches(expected, path);
40 
41         expected = arcWithPoint(100, 0, 0, -100, 0, 0);
42         path = arcMotion.getPath(100, 0, 0, -100);
43         assertPathMatches(expected, path);
44 
45         expected = arcWithPoint(0, -100, -100, 0, 0, 0);
46         path = arcMotion.getPath(0, -100, -100, 0);
47         assertPathMatches(expected, path);
48 
49         expected = arcWithPoint(-100, 0, 0, 100, -100, 100);
50         path = arcMotion.getPath(-100, 0, 0, 100);
51         assertPathMatches(expected, path);
52     }
53 
54     @Test
test345Triangles()55     public void test345Triangles() {
56         // 3-4-5 triangles are easy to calculate the control points
57         ArcMotion arcMotion = new ArcMotion();
58         arcMotion.setMaximumAngle(90);
59         Path expected;
60         Path path;
61 
62         expected = arcWithPoint(0, 120, 160, 0, 125, 120);
63         path = arcMotion.getPath(0, 120, 160, 0);
64         assertPathMatches(expected, path);
65 
66         expected = arcWithPoint(0, 160, 120, 0, 120, 125);
67         path = arcMotion.getPath(0, 160, 120, 0);
68         assertPathMatches(expected, path);
69 
70         expected = arcWithPoint(-120, 0, 0, 160, -120, 125);
71         path = arcMotion.getPath(-120, 0, 0, 160);
72         assertPathMatches(expected, path);
73 
74         expected = arcWithPoint(-160, 0, 0, 120, -125, 120);
75         path = arcMotion.getPath(-160, 0, 0, 120);
76         assertPathMatches(expected, path);
77 
78         expected = arcWithPoint(0, -120, -160, 0, -35, 0);
79         path = arcMotion.getPath(0, -120, -160, 0);
80         assertPathMatches(expected, path);
81 
82         expected = arcWithPoint(0, -160, -120, 0, 0, -35);
83         path = arcMotion.getPath(0, -160, -120, 0);
84         assertPathMatches(expected, path);
85 
86         expected = arcWithPoint(120, 0, 0, -160, 0, -35);
87         path = arcMotion.getPath(120, 0, 0, -160);
88         assertPathMatches(expected, path);
89 
90         expected = arcWithPoint(160, 0, 0, -120, 35, 0);
91         path = arcMotion.getPath(160, 0, 0, -120);
92         assertPathMatches(expected, path);
93     }
94 
arcWithPoint(float startX, float startY, float endX, float endY, float eX, float eY)95     private static Path arcWithPoint(float startX, float startY, float endX, float endY,
96             float eX, float eY) {
97         float c1x = (eX + startX) / 2;
98         float c1y = (eY + startY) / 2;
99         float c2x = (eX + endX) / 2;
100         float c2y = (eY + endY) / 2;
101         Path path = new Path();
102         path.moveTo(startX, startY);
103         path.cubicTo(c1x, c1y, c2x, c2y, endX, endY);
104         return path;
105     }
106 
107     @Test
testMaximumAngle()108     public void testMaximumAngle() {
109         ArcMotion arcMotion = new ArcMotion();
110         arcMotion.setMaximumAngle(45f);
111         assertEquals(45f, arcMotion.getMaximumAngle(), 0.0f);
112 
113         float ratio = (float) Math.tan(Math.PI / 8);
114         float ex = 50 + (50 * ratio);
115         float ey = ex;
116 
117         Path expected = arcWithPoint(0, 100, 100, 0, ex, ey);
118         Path path = arcMotion.getPath(0, 100, 100, 0);
119         assertPathMatches(expected, path);
120     }
121 
122     @Test
testMinimumHorizontalAngle()123     public void testMinimumHorizontalAngle() {
124         ArcMotion arcMotion = new ArcMotion();
125         arcMotion.setMinimumHorizontalAngle(45);
126         assertEquals(45, arcMotion.getMinimumHorizontalAngle(), 0.0f);
127 
128         float ex = 37.5f;
129         float ey = (float) (Math.tan(Math.PI / 4) * 50);
130         Path expected = arcWithPoint(0, 0, 100, 50, ex, ey);
131         Path path = arcMotion.getPath(0, 0, 100, 50);
132         assertPathMatches(expected, path);
133 
134         // Pretty much the same, but follows a different path.
135         expected = arcWithPoint(0, 0, 100.001f, 50, ex, ey);
136         path = arcMotion.getPath(0, 0, 100.001f, 50);
137         assertPathMatches(expected, path);
138 
139         // Moving in the opposite direction.
140         expected = arcWithPoint(100, 50, 0, 0, ex, ey);
141         path = arcMotion.getPath(100, 50, 0, 0);
142         assertPathMatches(expected, path);
143 
144         // With x < y.
145         ex = 0;
146         ey =  (float) (Math.tan(Math.PI / 4) * 62.5f);
147         expected = arcWithPoint(0, 0, 50, 100, ex, ey);
148         path = arcMotion.getPath(0, 0, 50, 100);
149         assertPathMatches(expected, path);
150 
151         // Pretty much the same, but follows a different path.
152         expected = arcWithPoint(0, 0, 50, 100.001f, ex, ey);
153         path = arcMotion.getPath(0, 0, 50, 100.001f);
154         assertPathMatches(expected, path);
155 
156         // Moving in the opposite direction.
157         expected = arcWithPoint(50, 100, 0, 0, ex, ey);
158         path = arcMotion.getPath(50, 100, 0, 0);
159         assertPathMatches(expected, path);
160     }
161 
162     @Test
testMinimumVerticalAngle()163     public void testMinimumVerticalAngle() {
164         ArcMotion arcMotion = new ArcMotion();
165         arcMotion.setMinimumVerticalAngle(45);
166         assertEquals(45, arcMotion.getMinimumVerticalAngle(), 0.0f);
167 
168         float ex = 0;
169         float ey = 62.5f;
170         Path expected = arcWithPoint(0, 0, 50, 100, ex, ey);
171         Path path = arcMotion.getPath(0, 0, 50, 100);
172         assertPathMatches(expected, path);
173 
174         // Pretty much the same, but follows a different path.
175         expected = arcWithPoint(0, 0, 50, 100.001f, ex, ey);
176         path = arcMotion.getPath(0, 0, 50, 100.001f);
177         assertPathMatches(expected, path);
178 
179         // Moving in opposite direction.
180         expected = arcWithPoint(50, 100, 0, 0, ex, ey);
181         path = arcMotion.getPath(50, 100, 0, 0);
182         assertPathMatches(expected, path);
183 
184         // With x > y.
185         ex = (float) (Math.tan(Math.PI / 4) * 37.5f);
186         ey = 50;
187         expected = arcWithPoint(0, 0, 100, 50, ex, ey);
188         path = arcMotion.getPath(0, 0, 100, 50);
189         assertPathMatches(expected, path);
190 
191         // Pretty much the same, but follows a different path.
192         expected = arcWithPoint(0, 0, 100.001f, 50, ex, ey);
193         path = arcMotion.getPath(0, 0, 100.001f, 50);
194         assertPathMatches(expected, path);
195 
196         // Moving in opposite direction.
197         expected = arcWithPoint(100, 50, 0, 0, ex, ey);
198         path = arcMotion.getPath(100, 50, 0, 0);
199         assertPathMatches(expected, path);
200     }
201 
202     @Test
horizontalAndVerticalMotion()203     public void horizontalAndVerticalMotion() {
204         ArcMotion arcMotion = new ArcMotion();
205         arcMotion.setMinimumHorizontalAngle(80);
206         arcMotion.setMaximumAngle(90);
207 
208         float ex = 50;
209         float ey = (float) (50 * Math.tan(Math.toRadians(40)));
210         Path expected = arcWithPoint(0, 0, 100, 0, ex, ey);
211         Path path = arcMotion.getPath(0, 0, 100, 0);
212         assertPathMatches(expected, path);
213 
214         // Now move it in the opposite direction
215         expected = arcWithPoint(100, 0, 0, 0, ex, ey);
216         path = arcMotion.getPath(100, 0, 0, 0);
217         assertPathMatches(expected, path);
218 
219         // Now try vertical path
220         arcMotion.setMinimumVerticalAngle(45);
221         ex = (float) (50 * Math.tan(Math.toRadians(22.5)));
222         ey = 50f;
223         expected = arcWithPoint(0, 0, 0, 100f, ex, ey);
224         path = arcMotion.getPath(0, 0, 0, 100f);
225         assertPathMatches(expected, path);
226 
227         // Now move it in the opposite direction
228         arcMotion.setMinimumVerticalAngle(45);
229         expected = arcWithPoint(0, 100, 0, 0f, ex, ey);
230         path = arcMotion.getPath(0, 100, 0, 0f);
231         assertPathMatches(expected, path);
232     }
233 }
234 
235