00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "main.h"
00011 #include <Eigen/StdVector>
00012 #include <Eigen/Geometry>
00013 #include <unsupported/Eigen/BVH>
00014
00015 namespace Eigen {
00016
00017 template<typename Scalar, int Dim> AlignedBox<Scalar, Dim> bounding_box(const Matrix<Scalar, Dim, 1> &v) { return AlignedBox<Scalar, Dim>(v); }
00018
00019 }
00020
00021
00022 template<int Dim>
00023 struct Ball
00024 {
00025 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(double, Dim)
00026
00027 typedef Matrix<double, Dim, 1> VectorType;
00028
00029 Ball() {}
00030 Ball(const VectorType &c, double r) : center(c), radius(r) {}
00031
00032 VectorType center;
00033 double radius;
00034 };
00035 template<int Dim> AlignedBox<double, Dim> bounding_box(const Ball<Dim> &b)
00036 { return AlignedBox<double, Dim>(b.center.array() - b.radius, b.center.array() + b.radius); }
00037
00038 inline double SQR(double x) { return x * x; }
00039
00040 template<int Dim>
00041 struct BallPointStuff
00042 {
00043 typedef double Scalar;
00044 typedef Matrix<double, Dim, 1> VectorType;
00045 typedef Ball<Dim> BallType;
00046 typedef AlignedBox<double, Dim> BoxType;
00047
00048 BallPointStuff() : calls(0), count(0) {}
00049 BallPointStuff(const VectorType &inP) : p(inP), calls(0), count(0) {}
00050
00051
00052 bool intersectVolume(const BoxType &r) { ++calls; return r.contains(p); }
00053 bool intersectObject(const BallType &b) {
00054 ++calls;
00055 if((b.center - p).squaredNorm() < SQR(b.radius))
00056 ++count;
00057 return false;
00058 }
00059
00060 bool intersectVolumeVolume(const BoxType &r1, const BoxType &r2) { ++calls; return !(r1.intersection(r2)).isNull(); }
00061 bool intersectVolumeObject(const BoxType &r, const BallType &b) { ++calls; return r.squaredExteriorDistance(b.center) < SQR(b.radius); }
00062 bool intersectObjectVolume(const BallType &b, const BoxType &r) { ++calls; return r.squaredExteriorDistance(b.center) < SQR(b.radius); }
00063 bool intersectObjectObject(const BallType &b1, const BallType &b2){
00064 ++calls;
00065 if((b1.center - b2.center).norm() < b1.radius + b2.radius)
00066 ++count;
00067 return false;
00068 }
00069 bool intersectVolumeObject(const BoxType &r, const VectorType &v) { ++calls; return r.contains(v); }
00070 bool intersectObjectObject(const BallType &b, const VectorType &v){
00071 ++calls;
00072 if((b.center - v).squaredNorm() < SQR(b.radius))
00073 ++count;
00074 return false;
00075 }
00076
00077 double minimumOnVolume(const BoxType &r) { ++calls; return r.squaredExteriorDistance(p); }
00078 double minimumOnObject(const BallType &b) { ++calls; return (std::max)(0., (b.center - p).squaredNorm() - SQR(b.radius)); }
00079 double minimumOnVolumeVolume(const BoxType &r1, const BoxType &r2) { ++calls; return r1.squaredExteriorDistance(r2); }
00080 double minimumOnVolumeObject(const BoxType &r, const BallType &b) { ++calls; return SQR((std::max)(0., r.exteriorDistance(b.center) - b.radius)); }
00081 double minimumOnObjectVolume(const BallType &b, const BoxType &r) { ++calls; return SQR((std::max)(0., r.exteriorDistance(b.center) - b.radius)); }
00082 double minimumOnObjectObject(const BallType &b1, const BallType &b2){ ++calls; return SQR((std::max)(0., (b1.center - b2.center).norm() - b1.radius - b2.radius)); }
00083 double minimumOnVolumeObject(const BoxType &r, const VectorType &v) { ++calls; return r.squaredExteriorDistance(v); }
00084 double minimumOnObjectObject(const BallType &b, const VectorType &v){ ++calls; return SQR((std::max)(0., (b.center - v).norm() - b.radius)); }
00085
00086 VectorType p;
00087 int calls;
00088 int count;
00089 };
00090
00091
00092 template<int Dim>
00093 struct TreeTest
00094 {
00095 typedef Matrix<double, Dim, 1> VectorType;
00096 typedef std::vector<VectorType, aligned_allocator<VectorType> > VectorTypeList;
00097 typedef Ball<Dim> BallType;
00098 typedef std::vector<BallType, aligned_allocator<BallType> > BallTypeList;
00099 typedef AlignedBox<double, Dim> BoxType;
00100
00101 void testIntersect1()
00102 {
00103 BallTypeList b;
00104 for(int i = 0; i < 500; ++i) {
00105 b.push_back(BallType(VectorType::Random(), 0.5 * internal::random(0., 1.)));
00106 }
00107 KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
00108
00109 VectorType pt = VectorType::Random();
00110 BallPointStuff<Dim> i1(pt), i2(pt);
00111
00112 for(int i = 0; i < (int)b.size(); ++i)
00113 i1.intersectObject(b[i]);
00114
00115 BVIntersect(tree, i2);
00116
00117 VERIFY(i1.count == i2.count);
00118 }
00119
00120 void testMinimize1()
00121 {
00122 BallTypeList b;
00123 for(int i = 0; i < 500; ++i) {
00124 b.push_back(BallType(VectorType::Random(), 0.01 * internal::random(0., 1.)));
00125 }
00126 KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
00127
00128 VectorType pt = VectorType::Random();
00129 BallPointStuff<Dim> i1(pt), i2(pt);
00130
00131 double m1 = (std::numeric_limits<double>::max)(), m2 = m1;
00132
00133 for(int i = 0; i < (int)b.size(); ++i)
00134 m1 = (std::min)(m1, i1.minimumOnObject(b[i]));
00135
00136 m2 = BVMinimize(tree, i2);
00137
00138 VERIFY_IS_APPROX(m1, m2);
00139 }
00140
00141 void testIntersect2()
00142 {
00143 BallTypeList b;
00144 VectorTypeList v;
00145
00146 for(int i = 0; i < 50; ++i) {
00147 b.push_back(BallType(VectorType::Random(), 0.5 * internal::random(0., 1.)));
00148 for(int j = 0; j < 3; ++j)
00149 v.push_back(VectorType::Random());
00150 }
00151
00152 KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
00153 KdBVH<double, Dim, VectorType> vTree(v.begin(), v.end());
00154
00155 BallPointStuff<Dim> i1, i2;
00156
00157 for(int i = 0; i < (int)b.size(); ++i)
00158 for(int j = 0; j < (int)v.size(); ++j)
00159 i1.intersectObjectObject(b[i], v[j]);
00160
00161 BVIntersect(tree, vTree, i2);
00162
00163 VERIFY(i1.count == i2.count);
00164 }
00165
00166 void testMinimize2()
00167 {
00168 BallTypeList b;
00169 VectorTypeList v;
00170
00171 for(int i = 0; i < 50; ++i) {
00172 b.push_back(BallType(VectorType::Random(), 1e-7 + 1e-6 * internal::random(0., 1.)));
00173 for(int j = 0; j < 3; ++j)
00174 v.push_back(VectorType::Random());
00175 }
00176
00177 KdBVH<double, Dim, BallType> tree(b.begin(), b.end());
00178 KdBVH<double, Dim, VectorType> vTree(v.begin(), v.end());
00179
00180 BallPointStuff<Dim> i1, i2;
00181
00182 double m1 = (std::numeric_limits<double>::max)(), m2 = m1;
00183
00184 for(int i = 0; i < (int)b.size(); ++i)
00185 for(int j = 0; j < (int)v.size(); ++j)
00186 m1 = (std::min)(m1, i1.minimumOnObjectObject(b[i], v[j]));
00187
00188 m2 = BVMinimize(tree, vTree, i2);
00189
00190 VERIFY_IS_APPROX(m1, m2);
00191 }
00192 };
00193
00194
00195 void test_BVH()
00196 {
00197 for(int i = 0; i < g_repeat; i++) {
00198 #ifdef EIGEN_TEST_PART_1
00199 TreeTest<2> test2;
00200 CALL_SUBTEST(test2.testIntersect1());
00201 CALL_SUBTEST(test2.testMinimize1());
00202 CALL_SUBTEST(test2.testIntersect2());
00203 CALL_SUBTEST(test2.testMinimize2());
00204 #endif
00205
00206 #ifdef EIGEN_TEST_PART_2
00207 TreeTest<3> test3;
00208 CALL_SUBTEST(test3.testIntersect1());
00209 CALL_SUBTEST(test3.testMinimize1());
00210 CALL_SUBTEST(test3.testIntersect2());
00211 CALL_SUBTEST(test3.testMinimize2());
00212 #endif
00213
00214 #ifdef EIGEN_TEST_PART_3
00215 TreeTest<4> test4;
00216 CALL_SUBTEST(test4.testIntersect1());
00217 CALL_SUBTEST(test4.testMinimize1());
00218 CALL_SUBTEST(test4.testIntersect2());
00219 CALL_SUBTEST(test4.testMinimize2());
00220 #endif
00221 }
00222 }