1 // Copyright (c) 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 <stddef.h>
6
7 #include <cmath>
8 #include <limits>
9
10 #include "base/macros.h"
11 #include "build/build_config.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gfx/geometry/vector3d_f.h"
14
15 namespace gfx {
16
TEST(Vector3dTest,IsZero)17 TEST(Vector3dTest, IsZero) {
18 gfx::Vector3dF float_zero(0, 0, 0);
19 gfx::Vector3dF float_nonzero(0.1f, -0.1f, 0.1f);
20
21 EXPECT_TRUE(float_zero.IsZero());
22 EXPECT_FALSE(float_nonzero.IsZero());
23 }
24
TEST(Vector3dTest,Add)25 TEST(Vector3dTest, Add) {
26 gfx::Vector3dF f1(3.1f, 5.1f, 2.7f);
27 gfx::Vector3dF f2(4.3f, -1.3f, 8.1f);
28
29 const struct {
30 gfx::Vector3dF expected;
31 gfx::Vector3dF actual;
32 } float_tests[] = {
33 { gfx::Vector3dF(3.1F, 5.1F, 2.7f), f1 + gfx::Vector3dF() },
34 { gfx::Vector3dF(3.1f + 4.3f, 5.1f - 1.3f, 2.7f + 8.1f), f1 + f2 },
35 { gfx::Vector3dF(3.1f - 4.3f, 5.1f + 1.3f, 2.7f - 8.1f), f1 - f2 }
36 };
37
38 for (size_t i = 0; i < arraysize(float_tests); ++i)
39 EXPECT_EQ(float_tests[i].expected.ToString(),
40 float_tests[i].actual.ToString());
41 }
42
TEST(Vector3dTest,Negative)43 TEST(Vector3dTest, Negative) {
44 const struct {
45 gfx::Vector3dF expected;
46 gfx::Vector3dF actual;
47 } float_tests[] = {
48 { gfx::Vector3dF(-0.0f, -0.0f, -0.0f), -gfx::Vector3dF(0, 0, 0) },
49 { gfx::Vector3dF(-0.3f, -0.3f, -0.3f), -gfx::Vector3dF(0.3f, 0.3f, 0.3f) },
50 { gfx::Vector3dF(0.3f, 0.3f, 0.3f), -gfx::Vector3dF(-0.3f, -0.3f, -0.3f) },
51 { gfx::Vector3dF(-0.3f, 0.3f, -0.3f), -gfx::Vector3dF(0.3f, -0.3f, 0.3f) },
52 { gfx::Vector3dF(0.3f, -0.3f, -0.3f), -gfx::Vector3dF(-0.3f, 0.3f, 0.3f) },
53 { gfx::Vector3dF(-0.3f, -0.3f, 0.3f), -gfx::Vector3dF(0.3f, 0.3f, -0.3f) }
54 };
55
56 for (size_t i = 0; i < arraysize(float_tests); ++i)
57 EXPECT_EQ(float_tests[i].expected.ToString(),
58 float_tests[i].actual.ToString());
59 }
60
TEST(Vector3dTest,Scale)61 TEST(Vector3dTest, Scale) {
62 float triple_values[][6] = {
63 { 4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
64 { 4.5f, -1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
65 { 4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
66 { 4.5f, -1.2f -1.8f, 3.3f, 5.6f, 4.2f },
67
68 { 4.5f, 1.2f, 1.8f, 3.3f, -5.6f, -4.2f },
69 { 4.5f, 1.2f, 1.8f, -3.3f, -5.6f, -4.2f },
70 { 4.5f, 1.2f, -1.8f, 3.3f, -5.6f, -4.2f },
71 { 4.5f, 1.2f, -1.8f, -3.3f, -5.6f, -4.2f },
72
73 { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
74 { -4.5f, 1.2f, 1.8f, 0, 5.6f, 4.2f },
75 { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
76 { -4.5f, 1.2f, -1.8f, 0, 5.6f, 4.2f },
77
78 { -4.5f, 1.2f, 1.8f, 3.3f, 0, 4.2f },
79 { 4.5f, 0, 1.8f, 3.3f, 5.6f, 4.2f },
80 { -4.5f, 1.2f, -1.8f, 3.3f, 0, 4.2f },
81 { 4.5f, 0, -1.8f, 3.3f, 5.6f, 4.2f },
82 { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 0 },
83 { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 0 },
84
85 { 0, 1.2f, 0, 3.3f, 5.6f, 4.2f },
86 { 0, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f }
87 };
88
89 for (size_t i = 0; i < arraysize(triple_values); ++i) {
90 gfx::Vector3dF v(triple_values[i][0],
91 triple_values[i][1],
92 triple_values[i][2]);
93 v.Scale(triple_values[i][3], triple_values[i][4], triple_values[i][5]);
94 EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v.x());
95 EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v.y());
96 EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v.z());
97
98 Vector3dF v2 = ScaleVector3d(
99 gfx::Vector3dF(triple_values[i][0],
100 triple_values[i][1],
101 triple_values[i][2]),
102 triple_values[i][3], triple_values[i][4], triple_values[i][5]);
103 EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v2.x());
104 EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v2.y());
105 EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v2.z());
106 }
107
108 float single_values[][4] = {
109 { 4.5f, 1.2f, 1.8f, 3.3f },
110 { 4.5f, -1.2f, 1.8f, 3.3f },
111 { 4.5f, 1.2f, -1.8f, 3.3f },
112 { 4.5f, -1.2f, -1.8f, 3.3f },
113 { -4.5f, 1.2f, 3.3f },
114 { -4.5f, 1.2f, 0 },
115 { -4.5f, 1.2f, 1.8f, 3.3f },
116 { -4.5f, 1.2f, 1.8f, 0 },
117 { 4.5f, 0, 1.8f, 3.3f },
118 { 0, 1.2f, 1.8f, 3.3f },
119 { 4.5f, 0, 1.8f, 3.3f },
120 { 0, 1.2f, 1.8f, 3.3f },
121 { 4.5f, 1.2f, 0, 3.3f },
122 { 4.5f, 1.2f, 0, 3.3f }
123 };
124
125 for (size_t i = 0; i < arraysize(single_values); ++i) {
126 gfx::Vector3dF v(single_values[i][0],
127 single_values[i][1],
128 single_values[i][2]);
129 v.Scale(single_values[i][3]);
130 EXPECT_EQ(single_values[i][0] * single_values[i][3], v.x());
131 EXPECT_EQ(single_values[i][1] * single_values[i][3], v.y());
132 EXPECT_EQ(single_values[i][2] * single_values[i][3], v.z());
133
134 Vector3dF v2 = ScaleVector3d(
135 gfx::Vector3dF(single_values[i][0],
136 single_values[i][1],
137 single_values[i][2]),
138 single_values[i][3]);
139 EXPECT_EQ(single_values[i][0] * single_values[i][3], v2.x());
140 EXPECT_EQ(single_values[i][1] * single_values[i][3], v2.y());
141 EXPECT_EQ(single_values[i][2] * single_values[i][3], v2.z());
142 }
143 }
144
TEST(Vector3dTest,Length)145 TEST(Vector3dTest, Length) {
146 float float_values[][3] = {
147 { 0, 0, 0 },
148 { 10.5f, 20.5f, 8.5f },
149 { 20.5f, 10.5f, 8.5f },
150 { 8.5f, 20.5f, 10.5f },
151 { 10.5f, 8.5f, 20.5f },
152 { -10.5f, -20.5f, -8.5f },
153 { -20.5f, 10.5f, -8.5f },
154 { -8.5f, -20.5f, -10.5f },
155 { -10.5f, -8.5f, -20.5f },
156 { 10.5f, -20.5f, 8.5f },
157 { -10.5f, 20.5f, 8.5f },
158 { 10.5f, -20.5f, -8.5f },
159 { -10.5f, 20.5f, -8.5f },
160 // A large vector that fails if the Length function doesn't use
161 // double precision internally.
162 { 1236278317862780234892374893213178027.12122348904204230f,
163 335890352589839028212313231225425134332.38123f,
164 27861786423846742743236423478236784678.236713617231f }
165 };
166
167 for (size_t i = 0; i < arraysize(float_values); ++i) {
168 double v0 = float_values[i][0];
169 double v1 = float_values[i][1];
170 double v2 = float_values[i][2];
171 double length_squared =
172 static_cast<double>(v0) * v0 +
173 static_cast<double>(v1) * v1 +
174 static_cast<double>(v2) * v2;
175 double length = std::sqrt(length_squared);
176 gfx::Vector3dF vector(v0, v1, v2);
177 EXPECT_DOUBLE_EQ(length_squared, vector.LengthSquared());
178 EXPECT_FLOAT_EQ(static_cast<float>(length), vector.Length());
179 }
180 }
181
TEST(Vector3dTest,DotProduct)182 TEST(Vector3dTest, DotProduct) {
183 const struct {
184 float expected;
185 gfx::Vector3dF input1;
186 gfx::Vector3dF input2;
187 } tests[] = {
188 { 0, gfx::Vector3dF(1, 0, 0), gfx::Vector3dF(0, 1, 1) },
189 { 0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(1, 0, 1) },
190 { 0, gfx::Vector3dF(0, 0, 1), gfx::Vector3dF(1, 1, 0) },
191
192 { 3, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1, 1, 1) },
193
194 { 1.2f, gfx::Vector3dF(1.2f, -1.2f, 1.2f), gfx::Vector3dF(1, 1, 1) },
195 { 1.2f, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1.2f, -1.2f, 1.2f) },
196
197 { 38.72f,
198 gfx::Vector3dF(1.1f, 2.2f, 3.3f), gfx::Vector3dF(4.4f, 5.5f, 6.6f) }
199 };
200
201 for (size_t i = 0; i < arraysize(tests); ++i) {
202 float actual = gfx::DotProduct(tests[i].input1, tests[i].input2);
203 EXPECT_EQ(tests[i].expected, actual);
204 }
205 }
206
TEST(Vector3dTest,CrossProduct)207 TEST(Vector3dTest, CrossProduct) {
208 const struct {
209 gfx::Vector3dF expected;
210 gfx::Vector3dF input1;
211 gfx::Vector3dF input2;
212 } tests[] = {
213 { Vector3dF(), Vector3dF(), Vector3dF(1, 1, 1) },
214 { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF() },
215 { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF(1, 1, 1) },
216 { Vector3dF(),
217 Vector3dF(1.6f, 10.6f, -10.6f),
218 Vector3dF(1.6f, 10.6f, -10.6f) },
219
220 { Vector3dF(1, -1, 0), Vector3dF(1, 1, 1), Vector3dF(0, 0, 1) },
221 { Vector3dF(-1, 0, 1), Vector3dF(1, 1, 1), Vector3dF(0, 1, 0) },
222 { Vector3dF(0, 1, -1), Vector3dF(1, 1, 1), Vector3dF(1, 0, 0) },
223
224 { Vector3dF(-1, 1, 0), Vector3dF(0, 0, 1), Vector3dF(1, 1, 1) },
225 { Vector3dF(1, 0, -1), Vector3dF(0, 1, 0), Vector3dF(1, 1, 1) },
226 { Vector3dF(0, -1, 1), Vector3dF(1, 0, 0), Vector3dF(1, 1, 1) }
227 };
228
229 for (size_t i = 0; i < arraysize(tests); ++i) {
230 SCOPED_TRACE(i);
231 Vector3dF actual = gfx::CrossProduct(tests[i].input1, tests[i].input2);
232 EXPECT_EQ(tests[i].expected.ToString(), actual.ToString());
233 }
234 }
235
TEST(Vector3dFTest,ClampVector3dF)236 TEST(Vector3dFTest, ClampVector3dF) {
237 Vector3dF a;
238
239 a = Vector3dF(3.5f, 5.5f, 7.5f);
240 EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
241 a.SetToMax(Vector3dF(2, 4.5f, 6.5f));
242 EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
243 a.SetToMax(Vector3dF(3.5f, 5.5f, 7.5f));
244 EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
245 a.SetToMax(Vector3dF(4.5f, 2, 6.5f));
246 EXPECT_EQ(Vector3dF(4.5f, 5.5f, 7.5f).ToString(), a.ToString());
247 a.SetToMax(Vector3dF(3.5f, 6.5f, 6.5f));
248 EXPECT_EQ(Vector3dF(4.5f, 6.5f, 7.5f).ToString(), a.ToString());
249 a.SetToMax(Vector3dF(3.5f, 5.5f, 8.5f));
250 EXPECT_EQ(Vector3dF(4.5f, 6.5f, 8.5f).ToString(), a.ToString());
251 a.SetToMax(Vector3dF(8.5f, 10.5f, 12.5f));
252 EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
253
254 a.SetToMin(Vector3dF(9.5f, 11.5f, 13.5f));
255 EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
256 a.SetToMin(Vector3dF(8.5f, 10.5f, 12.5f));
257 EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
258 a.SetToMin(Vector3dF(7.5f, 11.5f, 13.5f));
259 EXPECT_EQ(Vector3dF(7.5f, 10.5f, 12.5f).ToString(), a.ToString());
260 a.SetToMin(Vector3dF(9.5f, 9.5f, 13.5f));
261 EXPECT_EQ(Vector3dF(7.5f, 9.5f, 12.5f).ToString(), a.ToString());
262 a.SetToMin(Vector3dF(9.5f, 11.5f, 11.5f));
263 EXPECT_EQ(Vector3dF(7.5f, 9.5f, 11.5f).ToString(), a.ToString());
264 a.SetToMin(Vector3dF(3.5f, 5.5f, 7.5f));
265 EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
266 }
267
TEST(Vector3dTest,AngleBetweenVectorsInDegress)268 TEST(Vector3dTest, AngleBetweenVectorsInDegress) {
269 const struct {
270 float expected;
271 gfx::Vector3dF input1;
272 gfx::Vector3dF input2;
273 } tests[] = {
274 {0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)},
275 {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)},
276 {45,
277 gfx::Vector3dF(0, 1, 0),
278 gfx::Vector3dF(0, 0.70710678188f, 0.70710678188f)},
279 {180, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, -1, 0)},
280 };
281
282 for (size_t i = 0; i < arraysize(tests); ++i) {
283 float actual =
284 gfx::AngleBetweenVectorsInDegrees(tests[i].input1, tests[i].input2);
285 EXPECT_FLOAT_EQ(tests[i].expected, actual);
286 actual =
287 gfx::AngleBetweenVectorsInDegrees(tests[i].input2, tests[i].input1);
288 EXPECT_FLOAT_EQ(tests[i].expected, actual);
289 }
290 }
291
TEST(Vector3dTest,ClockwiseAngleBetweenVectorsInDegress)292 TEST(Vector3dTest, ClockwiseAngleBetweenVectorsInDegress) {
293 const struct {
294 float expected;
295 gfx::Vector3dF input1;
296 gfx::Vector3dF input2;
297 } tests[] = {
298 {0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)},
299 {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, -1)},
300 {45,
301 gfx::Vector3dF(0, -1, 0),
302 gfx::Vector3dF(0, -0.70710678188f, 0.70710678188f)},
303 {180, gfx::Vector3dF(0, -1, 0), gfx::Vector3dF(0, 1, 0)},
304 {270, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)},
305 };
306
307 const gfx::Vector3dF normal_vector(1.0f, 0.0f, 0.0f);
308
309 for (size_t i = 0; i < arraysize(tests); ++i) {
310 float actual = gfx::ClockwiseAngleBetweenVectorsInDegrees(
311 tests[i].input1, tests[i].input2, normal_vector);
312 EXPECT_FLOAT_EQ(tests[i].expected, actual);
313 actual = -gfx::ClockwiseAngleBetweenVectorsInDegrees(
314 tests[i].input2, tests[i].input1, normal_vector);
315 if (actual < 0.0f)
316 actual += 360.0f;
317 EXPECT_FLOAT_EQ(tests[i].expected, actual);
318 }
319 }
320
TEST(Vector3dTest,GetNormalized)321 TEST(Vector3dTest, GetNormalized) {
322 const struct {
323 bool expected;
324 gfx::Vector3dF v;
325 gfx::Vector3dF normalized;
326 } tests[] = {
327 {false, gfx::Vector3dF(0, 0, 0), gfx::Vector3dF(0, 0, 0)},
328 {false,
329 gfx::Vector3dF(std::numeric_limits<float>::min(),
330 std::numeric_limits<float>::min(),
331 std::numeric_limits<float>::min()),
332 gfx::Vector3dF(std::numeric_limits<float>::min(),
333 std::numeric_limits<float>::min(),
334 std::numeric_limits<float>::min())},
335 {true, gfx::Vector3dF(1, 0, 0), gfx::Vector3dF(1, 0, 0)},
336 {true, gfx::Vector3dF(std::numeric_limits<float>::max(), 0, 0),
337 gfx::Vector3dF(1, 0, 0)},
338 };
339
340 for (size_t i = 0; i < arraysize(tests); ++i) {
341 gfx::Vector3dF n;
342 EXPECT_EQ(tests[i].expected, tests[i].v.GetNormalized(&n));
343 EXPECT_EQ(tests[i].normalized.ToString(), n.ToString());
344 }
345 }
346
347 } // namespace gfx
348