OLD | NEW |
| (Empty) |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/base/math_util.h" | |
6 | |
7 #include <cmath> | |
8 | |
9 #include "cc/test/geometry_test_utils.h" | |
10 #include "testing/gmock/include/gmock/gmock.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 #include "ui/gfx/geometry/rect.h" | |
13 #include "ui/gfx/geometry/rect_f.h" | |
14 #include "ui/gfx/transform.h" | |
15 | |
16 namespace cc { | |
17 namespace { | |
18 | |
19 TEST(MathUtilTest, ProjectionOfPerpendicularPlane) { | |
20 // In this case, the m33() element of the transform becomes zero, which could | |
21 // cause a divide-by-zero when projecting points/quads. | |
22 | |
23 gfx::Transform transform; | |
24 transform.MakeIdentity(); | |
25 transform.matrix().set(2, 2, 0); | |
26 | |
27 gfx::RectF rect = gfx::RectF(0, 0, 1, 1); | |
28 gfx::RectF projected_rect = MathUtil::ProjectClippedRect(transform, rect); | |
29 | |
30 EXPECT_EQ(0, projected_rect.x()); | |
31 EXPECT_EQ(0, projected_rect.y()); | |
32 EXPECT_TRUE(projected_rect.IsEmpty()); | |
33 } | |
34 | |
35 TEST(MathUtilTest, EnclosingClippedRectUsesCorrectInitialBounds) { | |
36 HomogeneousCoordinate h1(-100, -100, 0, 1); | |
37 HomogeneousCoordinate h2(-10, -10, 0, 1); | |
38 HomogeneousCoordinate h3(10, 10, 0, -1); | |
39 HomogeneousCoordinate h4(100, 100, 0, -1); | |
40 | |
41 // The bounds of the enclosing clipped rect should be -100 to -10 for both x | |
42 // and y. However, if there is a bug where the initial xmin/xmax/ymin/ymax are | |
43 // initialized to numeric_limits<float>::min() (which is zero, not -flt_max) | |
44 // then the enclosing clipped rect will be computed incorrectly. | |
45 gfx::RectF result = MathUtil::ComputeEnclosingClippedRect(h1, h2, h3, h4); | |
46 | |
47 // Due to floating point math in ComputeClippedPointForEdge this result | |
48 // is fairly imprecise. 0.15f was empirically determined. | |
49 EXPECT_RECT_NEAR( | |
50 gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result, 0.15f); | |
51 } | |
52 | |
53 TEST(MathUtilTest, EnclosingRectOfVerticesUsesCorrectInitialBounds) { | |
54 gfx::PointF vertices[3]; | |
55 int num_vertices = 3; | |
56 | |
57 vertices[0] = gfx::PointF(-10, -100); | |
58 vertices[1] = gfx::PointF(-100, -10); | |
59 vertices[2] = gfx::PointF(-30, -30); | |
60 | |
61 // The bounds of the enclosing rect should be -100 to -10 for both x and y. | |
62 // However, if there is a bug where the initial xmin/xmax/ymin/ymax are | |
63 // initialized to numeric_limits<float>::min() (which is zero, not -flt_max) | |
64 // then the enclosing clipped rect will be computed incorrectly. | |
65 gfx::RectF result = | |
66 MathUtil::ComputeEnclosingRectOfVertices(vertices, num_vertices); | |
67 | |
68 EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), | |
69 result); | |
70 } | |
71 | |
72 TEST(MathUtilTest, SmallestAngleBetweenVectors) { | |
73 gfx::Vector2dF x(1, 0); | |
74 gfx::Vector2dF y(0, 1); | |
75 gfx::Vector2dF test_vector(0.5, 0.5); | |
76 | |
77 // Orthogonal vectors are at an angle of 90 degress. | |
78 EXPECT_EQ(90, MathUtil::SmallestAngleBetweenVectors(x, y)); | |
79 | |
80 // A vector makes a zero angle with itself. | |
81 EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(x, x)); | |
82 EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(y, y)); | |
83 EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(test_vector, test_vector)); | |
84 | |
85 // Parallel but reversed vectors are at 180 degrees. | |
86 EXPECT_FLOAT_EQ(180, MathUtil::SmallestAngleBetweenVectors(x, -x)); | |
87 EXPECT_FLOAT_EQ(180, MathUtil::SmallestAngleBetweenVectors(y, -y)); | |
88 EXPECT_FLOAT_EQ( | |
89 180, MathUtil::SmallestAngleBetweenVectors(test_vector, -test_vector)); | |
90 | |
91 // The test vector is at a known angle. | |
92 EXPECT_FLOAT_EQ( | |
93 45, std::floor(MathUtil::SmallestAngleBetweenVectors(test_vector, x))); | |
94 EXPECT_FLOAT_EQ( | |
95 45, std::floor(MathUtil::SmallestAngleBetweenVectors(test_vector, y))); | |
96 } | |
97 | |
98 TEST(MathUtilTest, VectorProjection) { | |
99 gfx::Vector2dF x(1, 0); | |
100 gfx::Vector2dF y(0, 1); | |
101 gfx::Vector2dF test_vector(0.3f, 0.7f); | |
102 | |
103 // Orthogonal vectors project to a zero vector. | |
104 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(x, y)); | |
105 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(y, x)); | |
106 | |
107 // Projecting a vector onto the orthonormal basis gives the corresponding | |
108 // component of the vector. | |
109 EXPECT_VECTOR_EQ(gfx::Vector2dF(test_vector.x(), 0), | |
110 MathUtil::ProjectVector(test_vector, x)); | |
111 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, test_vector.y()), | |
112 MathUtil::ProjectVector(test_vector, y)); | |
113 | |
114 // Finally check than an arbitrary vector projected to another one gives a | |
115 // vector parallel to the second vector. | |
116 gfx::Vector2dF target_vector(0.5, 0.2f); | |
117 gfx::Vector2dF projected_vector = | |
118 MathUtil::ProjectVector(test_vector, target_vector); | |
119 EXPECT_EQ(projected_vector.x() / target_vector.x(), | |
120 projected_vector.y() / target_vector.y()); | |
121 } | |
122 | |
123 TEST(MathUtilTest, MapEnclosedRectWith2dAxisAlignedTransform) { | |
124 gfx::Rect input(1, 2, 3, 4); | |
125 gfx::Rect output; | |
126 gfx::Transform transform; | |
127 | |
128 // Identity. | |
129 output = | |
130 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
131 EXPECT_EQ(input, output); | |
132 | |
133 // Integer translate. | |
134 transform.Translate(2.0, 3.0); | |
135 output = | |
136 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
137 EXPECT_EQ(gfx::Rect(3, 5, 3, 4), output); | |
138 | |
139 // Non-integer translate. | |
140 transform.Translate(0.5, 0.5); | |
141 output = | |
142 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
143 EXPECT_EQ(gfx::Rect(4, 6, 2, 3), output); | |
144 | |
145 // Scale. | |
146 transform = gfx::Transform(); | |
147 transform.Scale(2.0, 3.0); | |
148 output = | |
149 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
150 EXPECT_EQ(gfx::Rect(2, 6, 6, 12), output); | |
151 | |
152 // Rotate Z. | |
153 transform = gfx::Transform(); | |
154 transform.Translate(1.0, 2.0); | |
155 transform.RotateAboutZAxis(90.0); | |
156 transform.Translate(-1.0, -2.0); | |
157 output = | |
158 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
159 EXPECT_EQ(gfx::Rect(-3, 2, 4, 3), output); | |
160 | |
161 // Rotate X. | |
162 transform = gfx::Transform(); | |
163 transform.RotateAboutXAxis(90.0); | |
164 output = | |
165 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
166 EXPECT_TRUE(output.IsEmpty()); | |
167 | |
168 transform = gfx::Transform(); | |
169 transform.RotateAboutXAxis(180.0); | |
170 output = | |
171 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
172 EXPECT_EQ(gfx::Rect(1, -6, 3, 4), output); | |
173 | |
174 // Rotate Y. | |
175 transform = gfx::Transform(); | |
176 transform.RotateAboutYAxis(90.0); | |
177 output = | |
178 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
179 EXPECT_TRUE(output.IsEmpty()); | |
180 | |
181 transform = gfx::Transform(); | |
182 transform.RotateAboutYAxis(180.0); | |
183 output = | |
184 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
185 EXPECT_EQ(gfx::Rect(-4, 2, 3, 4), output); | |
186 | |
187 // Translate Z. | |
188 transform = gfx::Transform(); | |
189 transform.ApplyPerspectiveDepth(10.0); | |
190 transform.Translate3d(0.0, 0.0, 5.0); | |
191 output = | |
192 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input); | |
193 EXPECT_EQ(gfx::Rect(2, 4, 6, 8), output); | |
194 } | |
195 | |
196 } // namespace | |
197 } // namespace cc | |
OLD | NEW |