blob: f3d9804240db36f82e59d4340fdf8cf5809722f5 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/transforms/rotation.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
const double kAxisTolerance = 1e-6;
const double kAngleTolerance = 1e-4;
#define EXPECT_AXIS(expected, actual) \
do { \
EXPECT_NEAR(expected.X(), actual.X(), kAxisTolerance); \
EXPECT_NEAR(expected.Y(), actual.Y(), kAxisTolerance); \
EXPECT_NEAR(expected.Z(), actual.Z(), kAxisTolerance); \
} while (false)
#define EXPECT_ANGLE(expected, actual) \
EXPECT_NEAR(expected, actual, kAngleTolerance)
TEST(RotationTest, GetCommonAxisTest) {
FloatPoint3D axis;
double angle_a;
double angle_b;
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(0, 0, 0), 0),
Rotation(FloatPoint3D(1, 2, 3), 100),
axis, angle_a, angle_b));
FloatPoint3D expected_axis = FloatPoint3D(1, 2, 3);
expected_axis.Normalize();
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(0, angle_a);
EXPECT_EQ(100, angle_b);
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(1, 2, 3), 100),
Rotation(FloatPoint3D(0, 0, 0), 0), axis,
angle_a, angle_b));
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(100, angle_a);
EXPECT_EQ(0, angle_b);
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(0, 0, 0), 100),
Rotation(FloatPoint3D(1, 2, 3), 100),
axis, angle_a, angle_b));
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(0, angle_a);
EXPECT_EQ(100, angle_b);
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(3, 2, 1), 0),
Rotation(FloatPoint3D(1, 2, 3), 100),
axis, angle_a, angle_b));
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(0, angle_a);
EXPECT_EQ(100, angle_b);
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(1, 2, 3), 50),
Rotation(FloatPoint3D(1, 2, 3), 100),
axis, angle_a, angle_b));
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(50, angle_a);
EXPECT_EQ(100, angle_b);
EXPECT_TRUE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(1, 2, 3), 50),
Rotation(FloatPoint3D(2, 4, 6), 100),
axis, angle_a, angle_b));
EXPECT_AXIS(expected_axis, axis);
EXPECT_EQ(50, angle_a);
EXPECT_EQ(100, angle_b);
EXPECT_FALSE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(1, 2, 3), 50),
Rotation(FloatPoint3D(3, 2, 1), 100),
axis, angle_a, angle_b));
EXPECT_FALSE(Rotation::GetCommonAxis(Rotation(FloatPoint3D(1, 2, 3), 50),
Rotation(FloatPoint3D(-1, -2, -3), 100),
axis, angle_a, angle_b));
}
TEST(RotationTest, AddTest) {
// Test accumulation around common axis.
Rotation x_rotation = Rotation::Add(Rotation(FloatPoint3D(1, 0, 0), 60),
Rotation(FloatPoint3D(1, 0, 0), 30));
EXPECT_AXIS(FloatPoint3D(1, 0, 0), x_rotation.axis);
EXPECT_ANGLE(90, x_rotation.angle);
Rotation y_rotation = Rotation::Add(Rotation(FloatPoint3D(0, 1, 0), 60),
Rotation(FloatPoint3D(0, 1, 0), 30));
EXPECT_AXIS(FloatPoint3D(0, 1, 0), y_rotation.axis);
EXPECT_ANGLE(90, y_rotation.angle);
Rotation z_rotation = Rotation::Add(Rotation(FloatPoint3D(0, 0, 1), 60),
Rotation(FloatPoint3D(0, 0, 1), 30));
EXPECT_AXIS(FloatPoint3D(0, 0, 1), z_rotation.axis);
EXPECT_ANGLE(90, z_rotation.angle);
// Test axis pairs
Rotation xy_rotation = Rotation::Add(Rotation(FloatPoint3D(1, 0, 0), 90),
Rotation(FloatPoint3D(0, 1, 0), 90));
double root3_inv = 1 / std::sqrt(3);
FloatPoint3D expected_axis = FloatPoint3D(root3_inv, root3_inv, root3_inv);
EXPECT_AXIS(expected_axis, xy_rotation.axis);
EXPECT_ANGLE(120, xy_rotation.angle);
Rotation yz_rotation = Rotation::Add(Rotation(FloatPoint3D(0, 1, 0), 90),
Rotation(FloatPoint3D(0, 0, 1), 90));
EXPECT_AXIS(expected_axis, yz_rotation.axis);
EXPECT_ANGLE(120, yz_rotation.angle);
Rotation zx_rotation = Rotation::Add(Rotation(FloatPoint3D(0, 0, 1), 90),
Rotation(FloatPoint3D(1, 0, 0), 90));
EXPECT_AXIS(expected_axis, zx_rotation.axis);
EXPECT_ANGLE(120, zx_rotation.angle);
}
TEST(RotationTest, SlerpTest) {
// Common axis case.
Rotation x_rotation =
Rotation::Slerp(Rotation(FloatPoint3D(1, 0, 0), 30),
Rotation(FloatPoint3D(1, 0, 0), 60), 0.5);
EXPECT_AXIS(FloatPoint3D(1, 0, 0), x_rotation.axis);
EXPECT_ANGLE(45, x_rotation.angle);
// General case without a common rotation axis.
Rotation xy_rotation =
Rotation::Slerp(Rotation(FloatPoint3D(1, 0, 0), 90),
Rotation(FloatPoint3D(0, 1, 0), 90), 0.5);
double root2_inv = 1 / std::sqrt(2); // half angle is 60 degrees
EXPECT_AXIS(FloatPoint3D(root2_inv, root2_inv, 0), xy_rotation.axis);
double expected_angle = rad2deg(std::acos(1.0 / 3.0));
EXPECT_ANGLE(expected_angle, xy_rotation.angle);
}
} // namespace blink