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 <cmath>
6#include <limits>
7
8#include "base/basictypes.h"
9#include "testing/gtest/include/gtest/gtest.h"
10#include "ui/gfx/geometry/vector3d_f.h"
11
12namespace gfx {
13
14TEST(Vector3dTest, IsZero) {
15  gfx::Vector3dF float_zero(0, 0, 0);
16  gfx::Vector3dF float_nonzero(0.1f, -0.1f, 0.1f);
17
18  EXPECT_TRUE(float_zero.IsZero());
19  EXPECT_FALSE(float_nonzero.IsZero());
20}
21
22TEST(Vector3dTest, Add) {
23  gfx::Vector3dF f1(3.1f, 5.1f, 2.7f);
24  gfx::Vector3dF f2(4.3f, -1.3f, 8.1f);
25
26  const struct {
27    gfx::Vector3dF expected;
28    gfx::Vector3dF actual;
29  } float_tests[] = {
30    { gfx::Vector3dF(3.1F, 5.1F, 2.7f), f1 + gfx::Vector3dF() },
31    { gfx::Vector3dF(3.1f + 4.3f, 5.1f - 1.3f, 2.7f + 8.1f), f1 + f2 },
32    { gfx::Vector3dF(3.1f - 4.3f, 5.1f + 1.3f, 2.7f - 8.1f), f1 - f2 }
33  };
34
35  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_tests); ++i)
36    EXPECT_EQ(float_tests[i].expected.ToString(),
37              float_tests[i].actual.ToString());
38}
39
40TEST(Vector3dTest, Negative) {
41  const struct {
42    gfx::Vector3dF expected;
43    gfx::Vector3dF actual;
44  } float_tests[] = {
45    { gfx::Vector3dF(-0.0f, -0.0f, -0.0f), -gfx::Vector3dF(0, 0, 0) },
46    { gfx::Vector3dF(-0.3f, -0.3f, -0.3f), -gfx::Vector3dF(0.3f, 0.3f, 0.3f) },
47    { gfx::Vector3dF(0.3f, 0.3f, 0.3f), -gfx::Vector3dF(-0.3f, -0.3f, -0.3f) },
48    { gfx::Vector3dF(-0.3f, 0.3f, -0.3f), -gfx::Vector3dF(0.3f, -0.3f, 0.3f) },
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  };
52
53  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_tests); ++i)
54    EXPECT_EQ(float_tests[i].expected.ToString(),
55              float_tests[i].actual.ToString());
56}
57
58TEST(Vector3dTest, Scale) {
59  float triple_values[][6] = {
60    { 4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
61    { 4.5f, -1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
62    { 4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
63    { 4.5f, -1.2f -1.8f, 3.3f, 5.6f, 4.2f },
64
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    { 4.5f, 1.2f, -1.8f, 3.3f, -5.6f, -4.2f },
68    { 4.5f, 1.2f, -1.8f, -3.3f, -5.6f, -4.2f },
69
70    { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
71    { -4.5f, 1.2f, 1.8f, 0, 5.6f, 4.2f },
72    { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
73    { -4.5f, 1.2f, -1.8f, 0, 5.6f, 4.2f },
74
75    { -4.5f, 1.2f, 1.8f, 3.3f, 0, 4.2f },
76    { 4.5f, 0, 1.8f, 3.3f, 5.6f, 4.2f },
77    { -4.5f, 1.2f, -1.8f, 3.3f, 0, 4.2f },
78    { 4.5f, 0, -1.8f, 3.3f, 5.6f, 4.2f },
79    { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 0 },
80    { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 0 },
81
82    { 0, 1.2f, 0, 3.3f, 5.6f, 4.2f },
83    { 0, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f }
84  };
85
86  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(triple_values); ++i) {
87    gfx::Vector3dF v(triple_values[i][0],
88                     triple_values[i][1],
89                     triple_values[i][2]);
90    v.Scale(triple_values[i][3], triple_values[i][4], triple_values[i][5]);
91    EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v.x());
92    EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v.y());
93    EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v.z());
94
95    Vector3dF v2 = ScaleVector3d(
96        gfx::Vector3dF(triple_values[i][0],
97                       triple_values[i][1],
98                       triple_values[i][2]),
99        triple_values[i][3], triple_values[i][4], triple_values[i][5]);
100    EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v2.x());
101    EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v2.y());
102    EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v2.z());
103  }
104
105  float single_values[][4] = {
106    { 4.5f, 1.2f, 1.8f, 3.3f },
107    { 4.5f, -1.2f, 1.8f, 3.3f },
108    { 4.5f, 1.2f, -1.8f, 3.3f },
109    { 4.5f, -1.2f, -1.8f, 3.3f },
110    { -4.5f, 1.2f, 3.3f },
111    { -4.5f, 1.2f, 0 },
112    { -4.5f, 1.2f, 1.8f, 3.3f },
113    { -4.5f, 1.2f, 1.8f, 0 },
114    { 4.5f, 0, 1.8f, 3.3f },
115    { 0, 1.2f, 1.8f, 3.3f },
116    { 4.5f, 0, 1.8f, 3.3f },
117    { 0, 1.2f, 1.8f, 3.3f },
118    { 4.5f, 1.2f, 0, 3.3f },
119    { 4.5f, 1.2f, 0, 3.3f }
120  };
121
122  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(single_values); ++i) {
123    gfx::Vector3dF v(single_values[i][0],
124                     single_values[i][1],
125                     single_values[i][2]);
126    v.Scale(single_values[i][3]);
127    EXPECT_EQ(single_values[i][0] * single_values[i][3], v.x());
128    EXPECT_EQ(single_values[i][1] * single_values[i][3], v.y());
129    EXPECT_EQ(single_values[i][2] * single_values[i][3], v.z());
130
131    Vector3dF v2 = ScaleVector3d(
132        gfx::Vector3dF(single_values[i][0],
133                       single_values[i][1],
134                       single_values[i][2]),
135        single_values[i][3]);
136    EXPECT_EQ(single_values[i][0] * single_values[i][3], v2.x());
137    EXPECT_EQ(single_values[i][1] * single_values[i][3], v2.y());
138    EXPECT_EQ(single_values[i][2] * single_values[i][3], v2.z());
139  }
140}
141
142TEST(Vector3dTest, Length) {
143  float float_values[][3] = {
144    { 0, 0, 0 },
145    { 10.5f, 20.5f, 8.5f },
146    { 20.5f, 10.5f, 8.5f },
147    { 8.5f, 20.5f, 10.5f },
148    { 10.5f, 8.5f, 20.5f },
149    { -10.5f, -20.5f, -8.5f },
150    { -20.5f, 10.5f, -8.5f },
151    { -8.5f, -20.5f, -10.5f },
152    { -10.5f, -8.5f, -20.5f },
153    { 10.5f, -20.5f, 8.5f },
154    { -10.5f, 20.5f, 8.5f },
155    { 10.5f, -20.5f, -8.5f },
156    { -10.5f, 20.5f, -8.5f },
157    // A large vector that fails if the Length function doesn't use
158    // double precision internally.
159    { 1236278317862780234892374893213178027.12122348904204230f,
160      335890352589839028212313231225425134332.38123f,
161      27861786423846742743236423478236784678.236713617231f }
162  };
163
164  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_values); ++i) {
165    double v0 = float_values[i][0];
166    double v1 = float_values[i][1];
167    double v2 = float_values[i][2];
168    double length_squared =
169        static_cast<double>(v0) * v0 +
170        static_cast<double>(v1) * v1 +
171        static_cast<double>(v2) * v2;
172    double length = std::sqrt(length_squared);
173    gfx::Vector3dF vector(v0, v1, v2);
174    EXPECT_DOUBLE_EQ(length_squared, vector.LengthSquared());
175    EXPECT_FLOAT_EQ(static_cast<float>(length), vector.Length());
176  }
177}
178
179TEST(Vector3dTest, DotProduct) {
180  const struct {
181    float expected;
182    gfx::Vector3dF input1;
183    gfx::Vector3dF input2;
184  } tests[] = {
185    { 0, gfx::Vector3dF(1, 0, 0), gfx::Vector3dF(0, 1, 1) },
186    { 0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(1, 0, 1) },
187    { 0, gfx::Vector3dF(0, 0, 1), gfx::Vector3dF(1, 1, 0) },
188
189    { 3, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1, 1, 1) },
190
191    { 1.2f, gfx::Vector3dF(1.2f, -1.2f, 1.2f), gfx::Vector3dF(1, 1, 1) },
192    { 1.2f, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1.2f, -1.2f, 1.2f) },
193
194    { 38.72f,
195      gfx::Vector3dF(1.1f, 2.2f, 3.3f), gfx::Vector3dF(4.4f, 5.5f, 6.6f) }
196  };
197
198  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
199    float actual = gfx::DotProduct(tests[i].input1, tests[i].input2);
200    EXPECT_EQ(tests[i].expected, actual);
201  }
202}
203
204TEST(Vector3dTest, CrossProduct) {
205  const struct {
206    gfx::Vector3dF expected;
207    gfx::Vector3dF input1;
208    gfx::Vector3dF input2;
209  } tests[] = {
210    { Vector3dF(), Vector3dF(), Vector3dF(1, 1, 1) },
211    { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF() },
212    { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF(1, 1, 1) },
213    { Vector3dF(),
214      Vector3dF(1.6f, 10.6f, -10.6f),
215      Vector3dF(1.6f, 10.6f, -10.6f) },
216
217    { Vector3dF(1, -1, 0), Vector3dF(1, 1, 1), Vector3dF(0, 0, 1) },
218    { Vector3dF(-1, 0, 1), Vector3dF(1, 1, 1), Vector3dF(0, 1, 0) },
219    { Vector3dF(0, 1, -1), Vector3dF(1, 1, 1), Vector3dF(1, 0, 0) },
220
221    { Vector3dF(-1, 1, 0), Vector3dF(0, 0, 1), Vector3dF(1, 1, 1) },
222    { Vector3dF(1, 0, -1), Vector3dF(0, 1, 0), Vector3dF(1, 1, 1) },
223    { Vector3dF(0, -1, 1), Vector3dF(1, 0, 0), Vector3dF(1, 1, 1) }
224  };
225
226  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
227    Vector3dF actual = gfx::CrossProduct(tests[i].input1, tests[i].input2);
228    EXPECT_EQ(tests[i].expected.ToString(), actual.ToString());
229  }
230}
231
232TEST(Vector3dFTest, ClampVector3dF) {
233  Vector3dF a;
234
235  a = Vector3dF(3.5f, 5.5f, 7.5f);
236  EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
237  a.SetToMax(Vector3dF(2, 4.5f, 6.5f));
238  EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
239  a.SetToMax(Vector3dF(3.5f, 5.5f, 7.5f));
240  EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
241  a.SetToMax(Vector3dF(4.5f, 2, 6.5f));
242  EXPECT_EQ(Vector3dF(4.5f, 5.5f, 7.5f).ToString(), a.ToString());
243  a.SetToMax(Vector3dF(3.5f, 6.5f, 6.5f));
244  EXPECT_EQ(Vector3dF(4.5f, 6.5f, 7.5f).ToString(), a.ToString());
245  a.SetToMax(Vector3dF(3.5f, 5.5f, 8.5f));
246  EXPECT_EQ(Vector3dF(4.5f, 6.5f, 8.5f).ToString(), a.ToString());
247  a.SetToMax(Vector3dF(8.5f, 10.5f, 12.5f));
248  EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
249
250  a.SetToMin(Vector3dF(9.5f, 11.5f, 13.5f));
251  EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
252  a.SetToMin(Vector3dF(8.5f, 10.5f, 12.5f));
253  EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
254  a.SetToMin(Vector3dF(7.5f, 11.5f, 13.5f));
255  EXPECT_EQ(Vector3dF(7.5f, 10.5f, 12.5f).ToString(), a.ToString());
256  a.SetToMin(Vector3dF(9.5f, 9.5f, 13.5f));
257  EXPECT_EQ(Vector3dF(7.5f, 9.5f, 12.5f).ToString(), a.ToString());
258  a.SetToMin(Vector3dF(9.5f, 11.5f, 11.5f));
259  EXPECT_EQ(Vector3dF(7.5f, 9.5f, 11.5f).ToString(), a.ToString());
260  a.SetToMin(Vector3dF(3.5f, 5.5f, 7.5f));
261  EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
262}
263
264}  // namespace gfx
265