1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2009 Ilya Baran <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li
10*bf2c3715SXin Li #include "main.h"
11*bf2c3715SXin Li #include <Eigen/StdVector>
12*bf2c3715SXin Li #include <Eigen/Geometry>
13*bf2c3715SXin Li #include <unsupported/Eigen/BVH>
14*bf2c3715SXin Li
15*bf2c3715SXin Li namespace Eigen {
16*bf2c3715SXin Li
bounding_box(const Matrix<Scalar,Dim,1> & v)17*bf2c3715SXin Li template<typename Scalar, int Dim> AlignedBox<Scalar, Dim> bounding_box(const Matrix<Scalar, Dim, 1> &v) { return AlignedBox<Scalar, Dim>(v); }
18*bf2c3715SXin Li
19*bf2c3715SXin Li }
20*bf2c3715SXin Li
21*bf2c3715SXin Li
22*bf2c3715SXin Li template<int Dim>
23*bf2c3715SXin Li struct Ball
24*bf2c3715SXin Li {
25*bf2c3715SXin Li EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(double, Dim)
26*bf2c3715SXin Li
27*bf2c3715SXin Li typedef Matrix<double, Dim, 1> VectorType;
28*bf2c3715SXin Li
BallBall29*bf2c3715SXin Li Ball() {}
BallBall30*bf2c3715SXin Li Ball(const VectorType &c, double r) : center(c), radius(r) {}
31*bf2c3715SXin Li
32*bf2c3715SXin Li VectorType center;
33*bf2c3715SXin Li double radius;
34*bf2c3715SXin Li };
bounding_box(const Ball<Dim> & b)35*bf2c3715SXin Li template<int Dim> AlignedBox<double, Dim> bounding_box(const Ball<Dim> &b)
36*bf2c3715SXin Li { return AlignedBox<double, Dim>(b.center.array() - b.radius, b.center.array() + b.radius); }
37*bf2c3715SXin Li
SQR(double x)38*bf2c3715SXin Li inline double SQR(double x) { return x * x; }
39*bf2c3715SXin Li
40*bf2c3715SXin Li template<int Dim>
41*bf2c3715SXin Li struct BallPointStuff //this class provides functions to be both an intersector and a minimizer, both for a ball and a point and for two trees
42*bf2c3715SXin Li {
43*bf2c3715SXin Li typedef double Scalar;
44*bf2c3715SXin Li typedef Matrix<double, Dim, 1> VectorType;
45*bf2c3715SXin Li typedef Ball<Dim> BallType;
46*bf2c3715SXin Li typedef AlignedBox<double, Dim> BoxType;
47*bf2c3715SXin Li
BallPointStuffBallPointStuff48*bf2c3715SXin Li BallPointStuff() : calls(0), count(0) {}
BallPointStuffBallPointStuff49*bf2c3715SXin Li BallPointStuff(const VectorType &inP) : p(inP), calls(0), count(0) {}
50*bf2c3715SXin Li
51*bf2c3715SXin Li
intersectVolumeBallPointStuff52*bf2c3715SXin Li bool intersectVolume(const BoxType &r) { ++calls; return r.contains(p); }
intersectObjectBallPointStuff53*bf2c3715SXin Li bool intersectObject(const BallType &b) {
54*bf2c3715SXin Li ++calls;
55*bf2c3715SXin Li if((b.center - p).squaredNorm() < SQR(b.radius))
56*bf2c3715SXin Li ++count;
57*bf2c3715SXin Li return false; //continue
58*bf2c3715SXin Li }
59*bf2c3715SXin Li
intersectVolumeVolumeBallPointStuff60*bf2c3715SXin Li bool intersectVolumeVolume(const BoxType &r1, const BoxType &r2) { ++calls; return !(r1.intersection(r2)).isNull(); }
intersectVolumeObjectBallPointStuff61*bf2c3715SXin Li bool intersectVolumeObject(const BoxType &r, const BallType &b) { ++calls; return r.squaredExteriorDistance(b.center) < SQR(b.radius); }
intersectObjectVolumeBallPointStuff62*bf2c3715SXin Li bool intersectObjectVolume(const BallType &b, const BoxType &r) { ++calls; return r.squaredExteriorDistance(b.center) < SQR(b.radius); }
intersectObjectObjectBallPointStuff63*bf2c3715SXin Li bool intersectObjectObject(const BallType &b1, const BallType &b2){
64*bf2c3715SXin Li ++calls;
65*bf2c3715SXin Li if((b1.center - b2.center).norm() < b1.radius + b2.radius)
66*bf2c3715SXin Li ++count;
67*bf2c3715SXin Li return false;
68*bf2c3715SXin Li }
intersectVolumeObjectBallPointStuff69*bf2c3715SXin Li bool intersectVolumeObject(const BoxType &r, const VectorType &v) { ++calls; return r.contains(v); }
intersectObjectObjectBallPointStuff70*bf2c3715SXin Li bool intersectObjectObject(const BallType &b, const VectorType &v){
71*bf2c3715SXin Li ++calls;
72*bf2c3715SXin Li if((b.center - v).squaredNorm() < SQR(b.radius))
73*bf2c3715SXin Li ++count;
74*bf2c3715SXin Li return false;
75*bf2c3715SXin Li }
76*bf2c3715SXin Li
minimumOnVolumeBallPointStuff77*bf2c3715SXin Li double minimumOnVolume(const BoxType &r) { ++calls; return r.squaredExteriorDistance(p); }
minimumOnObjectBallPointStuff78*bf2c3715SXin Li double minimumOnObject(const BallType &b) { ++calls; return (std::max)(0., (b.center - p).squaredNorm() - SQR(b.radius)); }
minimumOnVolumeVolumeBallPointStuff79*bf2c3715SXin Li double minimumOnVolumeVolume(const BoxType &r1, const BoxType &r2) { ++calls; return r1.squaredExteriorDistance(r2); }
minimumOnVolumeObjectBallPointStuff80*bf2c3715SXin Li double minimumOnVolumeObject(const BoxType &r, const BallType &b) { ++calls; return SQR((std::max)(0., r.exteriorDistance(b.center) - b.radius)); }
minimumOnObjectVolumeBallPointStuff81*bf2c3715SXin Li double minimumOnObjectVolume(const BallType &b, const BoxType &r) { ++calls; return SQR((std::max)(0., r.exteriorDistance(b.center) - b.radius)); }
minimumOnObjectObjectBallPointStuff82*bf2c3715SXin Li double minimumOnObjectObject(const BallType &b1, const BallType &b2){ ++calls; return SQR((std::max)(0., (b1.center - b2.center).norm() - b1.radius - b2.radius)); }
minimumOnVolumeObjectBallPointStuff83*bf2c3715SXin Li double minimumOnVolumeObject(const BoxType &r, const VectorType &v) { ++calls; return r.squaredExteriorDistance(v); }
minimumOnObjectObjectBallPointStuff84*bf2c3715SXin Li double minimumOnObjectObject(const BallType &b, const VectorType &v){ ++calls; return SQR((std::max)(0., (b.center - v).norm() - b.radius)); }
85*bf2c3715SXin Li
86*bf2c3715SXin Li VectorType p;
87*bf2c3715SXin Li int calls;
88*bf2c3715SXin Li int count;
89*bf2c3715SXin Li };
90*bf2c3715SXin Li
91*bf2c3715SXin Li
92*bf2c3715SXin Li template<int Dim>
93*bf2c3715SXin Li struct TreeTest
94*bf2c3715SXin Li {
95*bf2c3715SXin Li typedef Matrix<double, Dim, 1> VectorType;
96*bf2c3715SXin Li typedef std::vector<VectorType, aligned_allocator<VectorType> > VectorTypeList;
97*bf2c3715SXin Li typedef Ball<Dim> BallType;
98*bf2c3715SXin Li typedef std::vector<BallType, aligned_allocator<BallType> > BallTypeList;
99*bf2c3715SXin Li typedef AlignedBox<double, Dim> BoxType;
100*bf2c3715SXin Li
testIntersect1TreeTest101*bf2c3715SXin Li void testIntersect1()
102*bf2c3715SXin Li {
103*bf2c3715SXin Li BallTypeList b;
104*bf2c3715SXin Li for(int i = 0; i < 500; ++i) {
105*bf2c3715SXin Li b.push_back(BallType(VectorType::Random(), 0.5 * internal::random(0., 1.)));
106*bf2c3715SXin Li }
107*bf2c3715SXin Li KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
108*bf2c3715SXin Li
109*bf2c3715SXin Li VectorType pt = VectorType::Random();
110*bf2c3715SXin Li BallPointStuff<Dim> i1(pt), i2(pt);
111*bf2c3715SXin Li
112*bf2c3715SXin Li for(int i = 0; i < (int)b.size(); ++i)
113*bf2c3715SXin Li i1.intersectObject(b[i]);
114*bf2c3715SXin Li
115*bf2c3715SXin Li BVIntersect(tree, i2);
116*bf2c3715SXin Li
117*bf2c3715SXin Li VERIFY(i1.count == i2.count);
118*bf2c3715SXin Li }
119*bf2c3715SXin Li
testMinimize1TreeTest120*bf2c3715SXin Li void testMinimize1()
121*bf2c3715SXin Li {
122*bf2c3715SXin Li BallTypeList b;
123*bf2c3715SXin Li for(int i = 0; i < 500; ++i) {
124*bf2c3715SXin Li b.push_back(BallType(VectorType::Random(), 0.01 * internal::random(0., 1.)));
125*bf2c3715SXin Li }
126*bf2c3715SXin Li KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
127*bf2c3715SXin Li
128*bf2c3715SXin Li VectorType pt = VectorType::Random();
129*bf2c3715SXin Li BallPointStuff<Dim> i1(pt), i2(pt);
130*bf2c3715SXin Li
131*bf2c3715SXin Li double m1 = (std::numeric_limits<double>::max)(), m2 = m1;
132*bf2c3715SXin Li
133*bf2c3715SXin Li for(int i = 0; i < (int)b.size(); ++i)
134*bf2c3715SXin Li m1 = (std::min)(m1, i1.minimumOnObject(b[i]));
135*bf2c3715SXin Li
136*bf2c3715SXin Li m2 = BVMinimize(tree, i2);
137*bf2c3715SXin Li
138*bf2c3715SXin Li VERIFY_IS_APPROX(m1, m2);
139*bf2c3715SXin Li }
140*bf2c3715SXin Li
testIntersect2TreeTest141*bf2c3715SXin Li void testIntersect2()
142*bf2c3715SXin Li {
143*bf2c3715SXin Li BallTypeList b;
144*bf2c3715SXin Li VectorTypeList v;
145*bf2c3715SXin Li
146*bf2c3715SXin Li for(int i = 0; i < 50; ++i) {
147*bf2c3715SXin Li b.push_back(BallType(VectorType::Random(), 0.5 * internal::random(0., 1.)));
148*bf2c3715SXin Li for(int j = 0; j < 3; ++j)
149*bf2c3715SXin Li v.push_back(VectorType::Random());
150*bf2c3715SXin Li }
151*bf2c3715SXin Li
152*bf2c3715SXin Li KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
153*bf2c3715SXin Li KdBVH<double, Dim, VectorType> vTree(v.begin(), v.end());
154*bf2c3715SXin Li
155*bf2c3715SXin Li BallPointStuff<Dim> i1, i2;
156*bf2c3715SXin Li
157*bf2c3715SXin Li for(int i = 0; i < (int)b.size(); ++i)
158*bf2c3715SXin Li for(int j = 0; j < (int)v.size(); ++j)
159*bf2c3715SXin Li i1.intersectObjectObject(b[i], v[j]);
160*bf2c3715SXin Li
161*bf2c3715SXin Li BVIntersect(tree, vTree, i2);
162*bf2c3715SXin Li
163*bf2c3715SXin Li VERIFY(i1.count == i2.count);
164*bf2c3715SXin Li }
165*bf2c3715SXin Li
testMinimize2TreeTest166*bf2c3715SXin Li void testMinimize2()
167*bf2c3715SXin Li {
168*bf2c3715SXin Li BallTypeList b;
169*bf2c3715SXin Li VectorTypeList v;
170*bf2c3715SXin Li
171*bf2c3715SXin Li for(int i = 0; i < 50; ++i) {
172*bf2c3715SXin Li b.push_back(BallType(VectorType::Random(), 1e-7 + 1e-6 * internal::random(0., 1.)));
173*bf2c3715SXin Li for(int j = 0; j < 3; ++j)
174*bf2c3715SXin Li v.push_back(VectorType::Random());
175*bf2c3715SXin Li }
176*bf2c3715SXin Li
177*bf2c3715SXin Li KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
178*bf2c3715SXin Li KdBVH<double, Dim, VectorType> vTree(v.begin(), v.end());
179*bf2c3715SXin Li
180*bf2c3715SXin Li BallPointStuff<Dim> i1, i2;
181*bf2c3715SXin Li
182*bf2c3715SXin Li double m1 = (std::numeric_limits<double>::max)(), m2 = m1;
183*bf2c3715SXin Li
184*bf2c3715SXin Li for(int i = 0; i < (int)b.size(); ++i)
185*bf2c3715SXin Li for(int j = 0; j < (int)v.size(); ++j)
186*bf2c3715SXin Li m1 = (std::min)(m1, i1.minimumOnObjectObject(b[i], v[j]));
187*bf2c3715SXin Li
188*bf2c3715SXin Li m2 = BVMinimize(tree, vTree, i2);
189*bf2c3715SXin Li
190*bf2c3715SXin Li VERIFY_IS_APPROX(m1, m2);
191*bf2c3715SXin Li }
192*bf2c3715SXin Li };
193*bf2c3715SXin Li
194*bf2c3715SXin Li
EIGEN_DECLARE_TEST(BVH)195*bf2c3715SXin Li EIGEN_DECLARE_TEST(BVH)
196*bf2c3715SXin Li {
197*bf2c3715SXin Li for(int i = 0; i < g_repeat; i++) {
198*bf2c3715SXin Li #ifdef EIGEN_TEST_PART_1
199*bf2c3715SXin Li TreeTest<2> test2;
200*bf2c3715SXin Li CALL_SUBTEST(test2.testIntersect1());
201*bf2c3715SXin Li CALL_SUBTEST(test2.testMinimize1());
202*bf2c3715SXin Li CALL_SUBTEST(test2.testIntersect2());
203*bf2c3715SXin Li CALL_SUBTEST(test2.testMinimize2());
204*bf2c3715SXin Li #endif
205*bf2c3715SXin Li
206*bf2c3715SXin Li #ifdef EIGEN_TEST_PART_2
207*bf2c3715SXin Li TreeTest<3> test3;
208*bf2c3715SXin Li CALL_SUBTEST(test3.testIntersect1());
209*bf2c3715SXin Li CALL_SUBTEST(test3.testMinimize1());
210*bf2c3715SXin Li CALL_SUBTEST(test3.testIntersect2());
211*bf2c3715SXin Li CALL_SUBTEST(test3.testMinimize2());
212*bf2c3715SXin Li #endif
213*bf2c3715SXin Li
214*bf2c3715SXin Li #ifdef EIGEN_TEST_PART_3
215*bf2c3715SXin Li TreeTest<4> test4;
216*bf2c3715SXin Li CALL_SUBTEST(test4.testIntersect1());
217*bf2c3715SXin Li CALL_SUBTEST(test4.testMinimize1());
218*bf2c3715SXin Li CALL_SUBTEST(test4.testIntersect2());
219*bf2c3715SXin Li CALL_SUBTEST(test4.testMinimize2());
220*bf2c3715SXin Li #endif
221*bf2c3715SXin Li }
222*bf2c3715SXin Li }
223