1 | // This file is part of Eigen, a lightweight C++ template library
|
---|
2 | // for linear algebra. Eigen itself is part of the KDE project.
|
---|
3 | //
|
---|
4 | // Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
---|
5 | // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
---|
6 | //
|
---|
7 | // This Source Code Form is subject to the terms of the Mozilla
|
---|
8 | // Public License v. 2.0. If a copy of the MPL was not distributed
|
---|
9 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
---|
10 |
|
---|
11 | #include "main.h"
|
---|
12 | #include <Eigen/Geometry>
|
---|
13 | #include <Eigen/LU>
|
---|
14 | #include <Eigen/QR>
|
---|
15 |
|
---|
16 | template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
|
---|
17 | {
|
---|
18 | /* this test covers the following files:
|
---|
19 | Hyperplane.h
|
---|
20 | */
|
---|
21 |
|
---|
22 | const int dim = _plane.dim();
|
---|
23 | typedef typename HyperplaneType::Scalar Scalar;
|
---|
24 | typedef typename NumTraits<Scalar>::Real RealScalar;
|
---|
25 | typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
|
---|
26 | typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
|
---|
27 | HyperplaneType::AmbientDimAtCompileTime> MatrixType;
|
---|
28 |
|
---|
29 | VectorType p0 = VectorType::Random(dim);
|
---|
30 | VectorType p1 = VectorType::Random(dim);
|
---|
31 |
|
---|
32 | VectorType n0 = VectorType::Random(dim).normalized();
|
---|
33 | VectorType n1 = VectorType::Random(dim).normalized();
|
---|
34 |
|
---|
35 | HyperplaneType pl0(n0, p0);
|
---|
36 | HyperplaneType pl1(n1, p1);
|
---|
37 | HyperplaneType pl2 = pl1;
|
---|
38 |
|
---|
39 | Scalar s0 = ei_random<Scalar>();
|
---|
40 | Scalar s1 = ei_random<Scalar>();
|
---|
41 |
|
---|
42 | VERIFY_IS_APPROX( n1.eigen2_dot(n1), Scalar(1) );
|
---|
43 |
|
---|
44 | VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
|
---|
45 | VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
|
---|
46 | VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
|
---|
47 | VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 + pl1.normal().unitOrthogonal() * s1), Scalar(1) );
|
---|
48 |
|
---|
49 | // transform
|
---|
50 | if (!NumTraits<Scalar>::IsComplex)
|
---|
51 | {
|
---|
52 | MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ();
|
---|
53 | Scaling<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
|
---|
54 | Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
|
---|
55 |
|
---|
56 | pl2 = pl1;
|
---|
57 | VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
|
---|
58 | pl2 = pl1;
|
---|
59 | VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
|
---|
60 | pl2 = pl1;
|
---|
61 | VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
|
---|
62 | pl2 = pl1;
|
---|
63 | VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
|
---|
64 | .absDistance((rot*scaling*translation) * p1), Scalar(1) );
|
---|
65 | pl2 = pl1;
|
---|
66 | VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
|
---|
67 | .absDistance((rot*translation) * p1), Scalar(1) );
|
---|
68 | }
|
---|
69 |
|
---|
70 | // casting
|
---|
71 | const int Dim = HyperplaneType::AmbientDimAtCompileTime;
|
---|
72 | typedef typename GetDifferentType<Scalar>::type OtherScalar;
|
---|
73 | Hyperplane<OtherScalar,Dim> hp1f = pl1.template cast<OtherScalar>();
|
---|
74 | VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
|
---|
75 | Hyperplane<Scalar,Dim> hp1d = pl1.template cast<Scalar>();
|
---|
76 | VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
|
---|
77 | }
|
---|
78 |
|
---|
79 | template<typename Scalar> void lines()
|
---|
80 | {
|
---|
81 | typedef Hyperplane<Scalar, 2> HLine;
|
---|
82 | typedef ParametrizedLine<Scalar, 2> PLine;
|
---|
83 | typedef Matrix<Scalar,2,1> Vector;
|
---|
84 | typedef Matrix<Scalar,3,1> CoeffsType;
|
---|
85 |
|
---|
86 | for(int i = 0; i < 10; i++)
|
---|
87 | {
|
---|
88 | Vector center = Vector::Random();
|
---|
89 | Vector u = Vector::Random();
|
---|
90 | Vector v = Vector::Random();
|
---|
91 | Scalar a = ei_random<Scalar>();
|
---|
92 | while (ei_abs(a-1) < 1e-4) a = ei_random<Scalar>();
|
---|
93 | while (u.norm() < 1e-4) u = Vector::Random();
|
---|
94 | while (v.norm() < 1e-4) v = Vector::Random();
|
---|
95 |
|
---|
96 | HLine line_u = HLine::Through(center + u, center + a*u);
|
---|
97 | HLine line_v = HLine::Through(center + v, center + a*v);
|
---|
98 |
|
---|
99 | // the line equations should be normalized so that a^2+b^2=1
|
---|
100 | VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
|
---|
101 | VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
|
---|
102 |
|
---|
103 | Vector result = line_u.intersection(line_v);
|
---|
104 |
|
---|
105 | // the lines should intersect at the point we called "center"
|
---|
106 | VERIFY_IS_APPROX(result, center);
|
---|
107 |
|
---|
108 | // check conversions between two types of lines
|
---|
109 | PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
|
---|
110 | CoeffsType converted_coeffs(HLine(pl).coeffs());
|
---|
111 | converted_coeffs *= line_u.coeffs()(0)/converted_coeffs(0);
|
---|
112 | VERIFY(line_u.coeffs().isApprox(converted_coeffs));
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | void test_eigen2_hyperplane()
|
---|
117 | {
|
---|
118 | for(int i = 0; i < g_repeat; i++) {
|
---|
119 | CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
|
---|
120 | CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
|
---|
121 | CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
|
---|
122 | CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
|
---|
123 | CALL_SUBTEST_5( lines<float>() );
|
---|
124 | CALL_SUBTEST_6( lines<double>() );
|
---|
125 | }
|
---|
126 | }
|
---|