xref: /aosp_15_r20/external/libchrome/ui/gfx/geometry/vector3d_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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