00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BB_H_
00009 #define BB_H_
00010
00011 #include <pcl/common/pca.h>
00012
00013 namespace BoundingBox {
00014 struct TransformedFoVBB
00015 {
00016 struct Plane {
00017 Eigen::Vector3f normal_x_,normal_y_, offs_;
00018 Eigen::Vector2f boundary_[4];
00019
00020 int pnpoly(float x, float y) const
00021 {
00022 int i, j, c = 0;
00023 for (i = 0, j = 4-1; i < 4; j = i++) {
00024 if ((((boundary_[i](1) <= y) && (y < boundary_[j](1))) ||
00025 ((boundary_[j](1) <= y) && (y < boundary_[i](1)))) &&
00026 (x < (boundary_[j](0) - boundary_[i](0)) * (y - boundary_[i](1)) / (boundary_[j](1) - boundary_[i](1)) + boundary_[i](0)))
00027 c = !c;
00028 }
00029 return c;
00030 }
00031
00032 bool intersectRay(const Eigen::Vector3f &a, const Eigen::Vector3f &b) const
00033 {
00034 Eigen::Matrix3f M;
00035 Eigen::Vector3f v;
00036 M.col(0) = a-b;
00037 M.col(1) = normal_x_;
00038 M.col(2) = normal_y_;
00039
00040 v = M.inverse()*(a-offs_);
00041
00042
00043
00044 if(std::abs(v(0))<=1)
00045 {
00046
00047
00048
00049 return pnpoly(v(1),v(2));
00050 }
00051 return false;
00052 }
00053
00054 bool sidePt(const Eigen::Vector3f &a) const
00055 {
00056
00057
00058
00059
00060
00061
00062 return (a-offs_).dot(normal_x_.cross(normal_y_))>0;
00063 }
00064
00065 };
00066
00067 Plane planes_[6];
00068 Eigen::Vector3f p_[8];
00069
00070 bool check(const TransformedFoVBB &o) const {
00071 for(int j=0; j<6; j++)
00072 for(int i=0; i<4; i++)
00073 {
00074 if(planes_[j].intersectRay(o.p_[i],o.p_[(i+1)%4]))
00075 return true;
00076 if(planes_[j].intersectRay(o.p_[i+4],o.p_[(i+1)%4+4]))
00077 return true;
00078 if(planes_[j].intersectRay(o.p_[i+4],o.p_[i]))
00079 return true;
00080 }
00081 return false;
00082 }
00083
00084 bool operator&(const TransformedFoVBB &o) const
00085 {
00086 return check(o) || o.check(*this);
00087 }
00088
00089 bool operator&(const Eigen::Vector3f &o) const
00090 {
00091 if(planes_[0].sidePt(o)!=planes_[1].sidePt(o)) return false;
00092 if(planes_[2].sidePt(o)!=planes_[4].sidePt(o)) return false;
00093 if(planes_[3].sidePt(o)!=planes_[5].sidePt(o)) return false;
00094 return true;
00095 }
00096 };
00097
00098
00099
00100 template<typename _TYPE>
00101 class FoVBB
00102 {
00103 public:
00104 typedef _TYPE TYPE;
00105
00106 protected:
00107 TYPE min_dist_, max_dist_;
00108 TYPE min_x_, min_y_, max_x_, max_y_;
00109
00110 public:
00111
00112
00113 void update(const Eigen::Vector3f &mi, const Eigen::Vector3f &ma) {
00114 min_dist_ = min_x_ = min_y_ = std::numeric_limits<float>::max();
00115 max_dist_ = max_x_ = max_y_ = -std::numeric_limits<float>::max();
00116
00117 min_dist_ = std::min(min_dist_, mi(2));
00118 min_x_ = std::min(min_x_, mi(0)/mi(2));
00119 min_y_ = std::min(min_y_, mi(1)/mi(2));
00120 max_dist_ = std::max(max_dist_, ma(2));
00121 max_x_ = std::max(max_x_, ma(0)/ma(2));
00122 max_y_ = std::max(max_y_, ma(1)/ma(2));
00123 }
00124
00125 TransformedFoVBB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f t) const {
00126 TransformedFoVBB r;
00127 r.p_[0](0) = min_x_;
00128 r.p_[0](1) = min_y_;
00129 r.p_[1](0) = max_x_;
00130 r.p_[1](1) = min_y_;
00131 r.p_[2](0) = max_x_;
00132 r.p_[2](1) = max_y_;
00133 r.p_[3](0) = min_x_;
00134 r.p_[3](1) = max_y_;
00135
00136 Eigen::Vector3f p[8];
00137 for(int i=0; i<4; i++)
00138 r.p_[i+4] = r.p_[i];
00139 for(int i=0; i<8; i++)
00140 {
00141 r.p_[i](2) = 1;
00142 r.p_[i] *= i<4 ? min_dist_:max_dist_;
00143 p[i] = r.p_[i];
00144 r.p_[i] = R*r.p_[i] + t;
00145 }
00146
00147 Eigen::Vector3f x,y,z;
00148 x=y=z=Eigen::Vector3f::Zero();
00149 x(0)=1;
00150 y(1)=1;
00151 z(2)=1;
00152
00153 r.planes_[0].offs_ = R*min_dist_*z+t;
00154 r.planes_[1].offs_ = R*max_dist_*z+t;
00155 r.planes_[0].normal_x_ = R*x;
00156 r.planes_[0].normal_y_ = R*y;
00157 r.planes_[1].normal_x_ = -R*x;
00158 r.planes_[1].normal_y_ = R*y;
00159 for(int i=0; i<4; i++)
00160 {
00161 r.planes_[0].boundary_[i] = (p[i].head(2));
00162 r.planes_[1].boundary_[i] = (p[i+4].head(2));
00163 }
00164
00165
00166
00167
00168
00169
00170 for(int i=0; i<4; i++)
00171 {
00172 r.planes_[2+i].normal_x_ = r.p_[i+4]+r.p_[(i+1)%4+4]-r.p_[i]-r.p_[(i+1)%4];
00173 r.planes_[2+i].normal_x_.normalize();
00174 r.planes_[2+i].normal_y_ = r.p_[(i+1)%4]-r.p_[i];
00175 r.planes_[2+i].normal_y_.normalize();
00176
00177 r.planes_[2+i].boundary_[0](0) = p[i](2);
00178 r.planes_[2+i].boundary_[1](0) = p[(i+1)%4](2);
00179 r.planes_[2+i].boundary_[2](0) = p[(i+1)%4](2);
00180 r.planes_[2+i].boundary_[3](0) = p[i+4](2);
00181
00182 r.planes_[2+i].boundary_[0](1) = p[i](i%2);
00183 r.planes_[2+i].boundary_[1](1) = p[(i+1)%4](i%2);
00184 r.planes_[2+i].boundary_[2](1) = p[(i+1)%4](i%2);
00185 r.planes_[2+i].boundary_[3](1) = p[i+4](i%2);
00186
00187 r.planes_[2+i].offs_ = t;
00188 }
00189
00190 return r;
00191 }
00192
00193 void get8Edges(Eigen::Vector3f *edges) const {
00194 for(int i=0; i<4; i++) {
00195 edges[i+4](0) = edges[i](0) = (i&1?min_x_:max_x_);
00196 edges[i+4](1) = edges[i](1) = (i&2?min_y_:max_y_);
00197 edges[i+4](2) = edges[i](2) = 1;
00198 edges[i+4] *= max_dist_;
00199 edges[i] *= min_dist_;
00200 }
00201 }
00202
00203 };
00204
00205
00206 class AABB {
00207 Eigen::Vector3f mi_, ma_;
00208 public:
00209 AABB() {}
00210 AABB(const Eigen::Vector3f &v):mi_(v),ma_(v) {}
00211
00212 bool operator&(const AABB &o) const {
00213 return mi_(0)<=o.ma_(0) && ma_(0)>=o.mi_(0) &&
00214 mi_(1)<=o.ma_(1) && ma_(1)>=o.mi_(1) &&
00215 mi_(2)<=o.ma_(2) && ma_(2)>=o.mi_(2) ;
00216 }
00217
00218 AABB increaseIfNec(const float rot, const float tr) const {
00219 AABB r = *this;
00220 return r;
00221 }
00222
00223 AABB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f &tr) const {
00224 AABB r = *this;
00225 r.mi_ = R*mi_ + tr;
00226 r.ma_ = R*ma_ + tr;
00227 return r;
00228 }
00229
00230 void get8Edges(Eigen::Vector3f *edges) const {
00231 for(int i=0; i<8; i++) {
00232 edges[i](0) = (i&1?mi_(0):ma_(0));
00233 edges[i](1) = (i&2?mi_(1):ma_(1));
00234 edges[i](2) = (i&4?mi_(2):ma_(2));
00235 }
00236 }
00237
00238 float extension() const {
00239 return (ma_-mi_).norm();
00240 }
00241
00242 void minmax(Eigen::Vector3f &mi, Eigen::Vector3f &ma) const {
00243 mi = mi_;
00244 ma = ma_;
00245 }
00246 };
00247
00248 class OOBB {
00249 Eigen::Vector3f m_, e_;
00250 Eigen::Matrix3f axis_;
00251 public:
00252 void debug() const {
00253 std::cout<<"mid\n"<<m_<<"\n";
00254 std::cout<<"ex\n"<<e_<<"\n";
00255 std::cout<<"axis\n"<<axis_<<"\n";
00256 }
00257
00258 OOBB() {}
00259
00260 OOBB(const Eigen::Vector3f &v):axis_(Eigen::Matrix3f::Identity()), m_(v) {for(int i=0; i<3; i++) e_(i)=0.001f;}
00261
00262 void set(const pcl::PointCloud<pcl::PointXYZ> &pc) {
00263 pcl::PCA<pcl::PointXYZ> pca;
00264 pca.compute(pc);
00265
00266 m_ = pca.getMean().head<3>();
00267 axis_ = pca.getEigenVectors();
00268 e_ = Eigen::Vector3f::Zero();
00269
00270 Eigen::Vector3f t;
00271 for(size_t i=0; i<pc.size(); i++) {
00272 t = axis_.transpose()*(pc[i].getVector3fMap()-m_);
00273 t(0)=std::abs(t(0));t(1)=std::abs(t(1));t(2)=std::abs(t(2));
00274 if(t(0)>e_(0))
00275 e_(0)=t(0);
00276 if(t(1)>e_(1))
00277 e_(1)=t(1);
00278 if(t(2)>e_(2))
00279 e_(2)=t(2);
00280 }
00281
00282 for(int i=0; i<3; i++) e_(i)=std::max(e_(i),0.001f);
00283 }
00284
00285 Eigen::Vector3f getCenter() const {return m_;}
00286 Eigen::Vector3f getExtension() const {return e_;}
00287 Eigen::Matrix3f getAxis() const {return axis_;}
00288
00289 float preassumption(const OOBB &o) const {
00290
00291 int m1=0;
00292 if(e_(1)<e_(m1)) m1=1;
00293 if(e_(2)<e_(m1)) m1=2;
00294 int m2=0;
00295 if(o.e_(1)<o.e_(m2)) m2=1;
00296 if(o.e_(2)<o.e_(m2)) m2=2;
00297 return std::abs(axis_.col(m1).dot(o.axis_.col(m2)));
00298 }
00299
00300 bool operator&(const OOBB &o) const {
00301 float ra, rb;
00302 Eigen::Matrix3f R, AbsR;
00303
00304 for (int i = 0; i < 3; i++)
00305 for (int j = 0; j < 3; j++)
00306 R(i,j) = axis_.col(i).dot(o.axis_.col(j));
00307
00308 Eigen::Vector3f t2 = o.m_-m_, t;
00309
00310 t(0) = t2.dot(axis_.col(0));
00311 t(1) = t2.dot(axis_.col(1));
00312 t(2) = t2.dot(axis_.col(2));
00313
00314
00315
00316 for (int i = 0; i < 3; i++)
00317 for (int j = 0; j < 3; j++)
00318 AbsR(i,j) = std::abs(R(i,j)) + 0.00001f;
00319
00320 for (int i = 0; i < 3; i++) {
00321 ra = e_(i);
00322 rb = o.e_(0) * AbsR(i,0) + o.e_(1) * AbsR(i,1) + o.e_(2) * AbsR(i,2);
00323
00324 if (std::abs(t(i)) > ra + rb) return false;
00325 }
00326
00327 for (int i = 0; i < 3; i++) {
00328 ra = e_(0) * AbsR(0,i) + e_(1) * AbsR(1,i) + e_(2) * AbsR(2,i);
00329 rb = o.e_(i);
00330
00331 if (std::abs(t(0)*R(0,i)+t(1)*R(1,i)+t(2)*R(2,i)) > ra + rb) return false;
00332 }
00333
00334 ra = e_(1) * AbsR(2,0) + e_(2) * AbsR(1,0);
00335 rb = o.e_(1) * AbsR(0,2) + o.e_(2) * AbsR(0,1);
00336 if (std::abs(t(2) * R(1,0) - t(1) * R(2,0)) > ra + rb) return false;
00337
00338 ra = e_(1) * AbsR(2,1) + e_(2) * AbsR(1,1);
00339 rb = o.e_(0) * AbsR(0,2) + o.e_(2) * AbsR(0,0);
00340 if (std::abs(t(2) * R(1,1) - t(1) * R(2,1)) > ra + rb) return false;
00341
00342 ra = e_(1) * AbsR(2,2) + e_(2) * AbsR(1,2);
00343 rb = o.e_(0) * AbsR(0,1) + o.e_(1) * AbsR(0,0);
00344 if (std::abs(t(2) * R(1,2) - t(1) * R(2,2)) > ra + rb) return false;
00345
00346 ra = e_(0) * AbsR(2,0) + e_(2) * AbsR(0,0);
00347 rb = o.e_(1) * AbsR(1,2) + o.e_(2) * AbsR(1,1);
00348 if (std::abs(t(0) * R(2,0) - t(2) * R(0,0)) > ra + rb) return false;
00349
00350 ra = e_(0) * AbsR(2,1) + e_(2) * AbsR(0,1);
00351 rb = o.e_(0) * AbsR(1,2) + o.e_(2) * AbsR(1,0);
00352 if (std::abs(t(0) * R(2,1) - t(2) * R(0,1)) > ra + rb) return false;
00353
00354 ra = e_(0) * AbsR(2,2) + e_(2) * AbsR(0,2);
00355 rb = o.e_(0) * AbsR(1,1) + o.e_(1) * AbsR(1,0);
00356 if (std::abs(t(0) * R(2,2) - t(2) * R(0,2)) > ra + rb) return false;
00357
00358 ra = e_(0) * AbsR(1,0) + e_(1) * AbsR(0,0);
00359 rb = o.e_(1) * AbsR(2,2) + o.e_(2) * AbsR(2,1);
00360 if (std::abs(t(1) * R(0,0) - t(0) * R(1,0)) > ra + rb) return false;
00361
00362 ra = e_(0) * AbsR(1,1) + e_(1) * AbsR(0,1);
00363 rb = o.e_(0) * AbsR(2,2) + o.e_(2) * AbsR(2,0);
00364 if (std::abs(t(1) * R(0,1) - t(0) * R(1,1)) > ra + rb) return false;
00365
00366 ra = e_(0) * AbsR(1,2) + e_(1) * AbsR(0,2);
00367 rb = o.e_(0) * AbsR(2,1) + o.e_(1) * AbsR(2,0);
00368 if (std::abs(t(1) * R(0,2) - t(0) * R(1,2)) > ra + rb) return false;
00369
00370 return true;
00371 }
00372
00373 OOBB changeSize(const float fact) const {
00374 OOBB r = *this;
00375 for(int i=0; i<3; i++)
00376 r.e_(i) *= fact;
00377 return r;
00378 }
00379
00380 OOBB setMinSize(const float s) const {
00381 OOBB r = *this;
00382 for(int i=0; i<3; i++)
00383 r.e_(i) = std::max(s,r.e_(i));
00384 return r;
00385 }
00386
00387 OOBB increaseIfNec(const float rot, const float tr) const {
00388 OOBB r = *this;
00389 Eigen::Vector3f z;
00390 z(0)=z(1)=0;
00391 z(2)=1;
00392 const float a = r.m_.norm()*rot;
00393 const float l = a + tr;
00394 for(int i=0; i<3; i++)
00395 r.e_(i) = std::max(l-a*r.axis_.col(i).dot(z),r.e_(i));
00396 return r;
00397 }
00398
00399 OOBB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f &tr) const {
00400 OOBB r = *this;
00401 r.m_ = R*r.m_ + tr;
00402 r.axis_ = R*r.axis_;
00403 return r;
00404 }
00405
00406 void get8Edges(Eigen::Vector3f *edges) const {
00407 for(int i=0; i<8; i++)
00408 edges[i] = m_ + (i&1?1:-1)*e_(0)*axis_.col(0) + (i&2?1:-1)*e_(1)*axis_.col(1) + (i&4?1:-1)*e_(2)*axis_.col(2);
00409 }
00410
00411 float extension() const {
00412 return std::max(e_(0),std::max(e_(1),e_(2)));
00413 }
00414
00415 void minmax(Eigen::Vector3f &mi, Eigen::Vector3f &ma) const {
00416 Eigen::Vector3f e[8];
00417 get8Edges(e);
00418 ma = mi = e[0];
00419 for(size_t i=1; i<8; i++)
00420 {
00421 if(e[i](2)>ma(2)) ma = e[i];
00422 if(e[i](2)<mi(2)) mi = e[i];
00423 }
00424 }
00425
00426 float ratio() const {
00427 int m1=0;
00428 if(e_(1)<e_(m1)) m1=1;
00429 if(e_(2)<e_(m1)) m1=2;
00430 int m2=(m1+1)%3;
00431 for(int i=0; i<3; i++) {
00432 if(i==m1) continue;
00433 if(e_(i)<e_(m2)) m2=i;
00434 }
00435
00436 return e_(m1)/e_(m2);
00437 }
00438
00439 };
00440
00441 }
00442
00443 #endif