1 | // This file is part of Eigen, a lightweight C++ template library
|
---|
2 | // for linear algebra.
|
---|
3 | //
|
---|
4 | // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.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 | typedef typename HyperplaneType::Index Index;
|
---|
22 | const Index dim = _plane.dim();
|
---|
23 | enum { Options = HyperplaneType::Options };
|
---|
24 | typedef typename HyperplaneType::Scalar Scalar;
|
---|
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 = internal::random<Scalar>();
|
---|
40 | Scalar s1 = internal::random<Scalar>();
|
---|
41 |
|
---|
42 | VERIFY_IS_APPROX( n1.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).householderQr().householderQ();
|
---|
53 | DiagonalMatrix<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,Options> hp1f = pl1.template cast<OtherScalar>();
|
---|
74 | VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
|
---|
75 | Hyperplane<Scalar,Dim,Options> hp1d = pl1.template cast<Scalar>();
|
---|
76 | VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
|
---|
77 | }
|
---|
78 |
|
---|
79 | template<typename Scalar> void lines()
|
---|
80 | {
|
---|
81 | using std::abs;
|
---|
82 | typedef Hyperplane<Scalar, 2> HLine;
|
---|
83 | typedef ParametrizedLine<Scalar, 2> PLine;
|
---|
84 | typedef Matrix<Scalar,2,1> Vector;
|
---|
85 | typedef Matrix<Scalar,3,1> CoeffsType;
|
---|
86 |
|
---|
87 | for(int i = 0; i < 10; i++)
|
---|
88 | {
|
---|
89 | Vector center = Vector::Random();
|
---|
90 | Vector u = Vector::Random();
|
---|
91 | Vector v = Vector::Random();
|
---|
92 | Scalar a = internal::random<Scalar>();
|
---|
93 | while (abs(a-1) < 1e-4) a = internal::random<Scalar>();
|
---|
94 | while (u.norm() < 1e-4) u = Vector::Random();
|
---|
95 | while (v.norm() < 1e-4) v = Vector::Random();
|
---|
96 |
|
---|
97 | HLine line_u = HLine::Through(center + u, center + a*u);
|
---|
98 | HLine line_v = HLine::Through(center + v, center + a*v);
|
---|
99 |
|
---|
100 | // the line equations should be normalized so that a^2+b^2=1
|
---|
101 | VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
|
---|
102 | VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
|
---|
103 |
|
---|
104 | Vector result = line_u.intersection(line_v);
|
---|
105 |
|
---|
106 | // the lines should intersect at the point we called "center"
|
---|
107 | VERIFY_IS_APPROX(result, center);
|
---|
108 |
|
---|
109 | // check conversions between two types of lines
|
---|
110 | PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
|
---|
111 | CoeffsType converted_coeffs = HLine(pl).coeffs();
|
---|
112 | converted_coeffs *= (line_u.coeffs()[0])/(converted_coeffs[0]);
|
---|
113 | VERIFY(line_u.coeffs().isApprox(converted_coeffs));
|
---|
114 | }
|
---|
115 | }
|
---|
116 |
|
---|
117 | template<typename Scalar> void planes()
|
---|
118 | {
|
---|
119 | using std::abs;
|
---|
120 | typedef Hyperplane<Scalar, 3> Plane;
|
---|
121 | typedef Matrix<Scalar,3,1> Vector;
|
---|
122 |
|
---|
123 | for(int i = 0; i < 10; i++)
|
---|
124 | {
|
---|
125 | Vector v0 = Vector::Random();
|
---|
126 | Vector v1(v0), v2(v0);
|
---|
127 | if(internal::random<double>(0,1)>0.25)
|
---|
128 | v1 += Vector::Random();
|
---|
129 | if(internal::random<double>(0,1)>0.25)
|
---|
130 | v2 += v1 * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
|
---|
131 | if(internal::random<double>(0,1)>0.25)
|
---|
132 | v2 += Vector::Random() * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
|
---|
133 |
|
---|
134 | Plane p0 = Plane::Through(v0, v1, v2);
|
---|
135 |
|
---|
136 | VERIFY_IS_APPROX(p0.normal().norm(), Scalar(1));
|
---|
137 | VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v0), Scalar(1));
|
---|
138 | VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v1), Scalar(1));
|
---|
139 | VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v2), Scalar(1));
|
---|
140 | }
|
---|
141 | }
|
---|
142 |
|
---|
143 | template<typename Scalar> void hyperplane_alignment()
|
---|
144 | {
|
---|
145 | typedef Hyperplane<Scalar,3,AutoAlign> Plane3a;
|
---|
146 | typedef Hyperplane<Scalar,3,DontAlign> Plane3u;
|
---|
147 |
|
---|
148 | EIGEN_ALIGN16 Scalar array1[4];
|
---|
149 | EIGEN_ALIGN16 Scalar array2[4];
|
---|
150 | EIGEN_ALIGN16 Scalar array3[4+1];
|
---|
151 | Scalar* array3u = array3+1;
|
---|
152 |
|
---|
153 | Plane3a *p1 = ::new(reinterpret_cast<void*>(array1)) Plane3a;
|
---|
154 | Plane3u *p2 = ::new(reinterpret_cast<void*>(array2)) Plane3u;
|
---|
155 | Plane3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Plane3u;
|
---|
156 |
|
---|
157 | p1->coeffs().setRandom();
|
---|
158 | *p2 = *p1;
|
---|
159 | *p3 = *p1;
|
---|
160 |
|
---|
161 | VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
|
---|
162 | VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
|
---|
163 |
|
---|
164 | #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
|
---|
165 | if(internal::packet_traits<Scalar>::Vectorizable)
|
---|
166 | VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a));
|
---|
167 | #endif
|
---|
168 | }
|
---|
169 |
|
---|
170 |
|
---|
171 | void test_geo_hyperplane()
|
---|
172 | {
|
---|
173 | for(int i = 0; i < g_repeat; i++) {
|
---|
174 | CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
|
---|
175 | CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
|
---|
176 | CALL_SUBTEST_2( hyperplane(Hyperplane<float,3,DontAlign>()) );
|
---|
177 | CALL_SUBTEST_2( hyperplane_alignment<float>() );
|
---|
178 | CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
|
---|
179 | CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
|
---|
180 | CALL_SUBTEST_1( lines<float>() );
|
---|
181 | CALL_SUBTEST_3( lines<double>() );
|
---|
182 | CALL_SUBTEST_2( planes<float>() );
|
---|
183 | CALL_SUBTEST_5( planes<double>() );
|
---|
184 | }
|
---|
185 | }
|
---|