00001
00002 #ifndef vgl_box_3d_txx_
00003 #define vgl_box_3d_txx_
00004
00005
00006
00007 #include "vgl_box_3d.h"
00008 #include <vgl/vgl_point_3d.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_algorithm.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_cmath.h>
00013
00014
00015
00016 template <class Type>
00017 vgl_box_3d<Type>::vgl_box_3d()
00018 {
00019 min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
00020 max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0;
00021 }
00022
00023 template <class Type>
00024 vgl_box_3d<Type>::vgl_box_3d(Type const corner1[3],
00025 Type const corner2[3])
00026 {
00027 min_pos_[0]=max_pos_[0]=corner1[0];
00028 min_pos_[1]=max_pos_[1]=corner1[1];
00029 min_pos_[2]=max_pos_[2]=corner1[2];
00030 this->add(corner2);
00031 }
00032
00033 template <class Type>
00034 vgl_box_3d<Type>::vgl_box_3d(vgl_point_3d<Type> const& corner1,
00035 vgl_point_3d<Type> const& corner2)
00036 {
00037 min_pos_[0]=max_pos_[0]=corner1.x();
00038 min_pos_[1]=max_pos_[1]=corner1.y();
00039 min_pos_[2]=max_pos_[2]=corner1.z();
00040 this->add(corner2);
00041 }
00042
00043 template <class Type>
00044 vgl_box_3d<Type>::vgl_box_3d(Type xmin, Type ymin, Type zmin,
00045 Type xmax, Type ymax, Type zmax)
00046 {
00047 min_pos_[0]=max_pos_[0]=xmin;
00048 min_pos_[1]=max_pos_[1]=ymin;
00049 min_pos_[2]=max_pos_[2]=zmin;
00050 this->add(vgl_point_3d<Type>(xmax,ymax,zmax));
00051 if (xmin > xmax || ymin > ymax || zmin > zmax) this->empty();
00052 }
00053
00054 template <class Type>
00055 vgl_box_3d<Type>::vgl_box_3d(Type const ref_point[3],
00056 Type w, Type h, Type d,
00057 typename vgl_box_3d<Type>::point_type t)
00058 {
00059 if (t == vgl_box_3d<Type>::centre)
00060 {
00061 min_pos_[0]=Type(ref_point[0]-0.5*w);
00062 min_pos_[1]=Type(ref_point[1]-0.5*h);
00063 min_pos_[2]=Type(ref_point[2]-0.5*d);
00064 max_pos_[0]=Type(ref_point[0]+0.5*w);
00065 max_pos_[1]=Type(ref_point[1]+0.5*h);
00066 max_pos_[2]=Type(ref_point[2]+0.5*d);
00067 }
00068 else if (t == vgl_box_3d<Type>::min_pos)
00069 {
00070 min_pos_[0]=ref_point[0];
00071 min_pos_[1]=ref_point[1];
00072 min_pos_[2]=ref_point[2];
00073 max_pos_[0]=ref_point[0]+w;
00074 max_pos_[1]=ref_point[1]+h;
00075 max_pos_[2]=ref_point[2]+d;
00076 }
00077 else if (t == vgl_box_3d<Type>::max_pos)
00078 {
00079 min_pos_[0]=ref_point[0]-w;
00080 min_pos_[1]=ref_point[1]-h;
00081 min_pos_[2]=ref_point[2]-d;
00082 max_pos_[0]=ref_point[0];
00083 max_pos_[1]=ref_point[1];
00084 max_pos_[2]=ref_point[2];
00085 }
00086 else
00087 assert(!"point_type should be one of: centre, min_pos, max_pos");
00088 }
00089
00090 template <class Type>
00091 vgl_box_3d<Type>::vgl_box_3d(vgl_point_3d<Type> const& ref_point,
00092 Type w, Type h, Type d,
00093 typename vgl_box_3d<Type>::point_type t)
00094 {
00095 if (t == vgl_box_3d<Type>::centre)
00096 {
00097 min_pos_[0]=Type(ref_point.x()-0.5*w);
00098 min_pos_[1]=Type(ref_point.y()-0.5*h);
00099 min_pos_[2]=Type(ref_point.z()-0.5*d);
00100 max_pos_[0]=Type(ref_point.x()+0.5*w);
00101 max_pos_[1]=Type(ref_point.y()+0.5*h);
00102 max_pos_[2]=Type(ref_point.z()+0.5*d);
00103 }
00104 else if (t == vgl_box_3d<Type>::min_pos)
00105 {
00106 min_pos_[0]=ref_point.x();
00107 min_pos_[1]=ref_point.y();
00108 min_pos_[2]=ref_point.z();
00109 max_pos_[0]=ref_point.x()+w;
00110 max_pos_[1]=ref_point.y()+h;
00111 max_pos_[2]=ref_point.z()+d;
00112 }
00113 else if (t == vgl_box_3d<Type>::max_pos)
00114 {
00115 min_pos_[0]=ref_point.x()-w;
00116 min_pos_[1]=ref_point.y()-h;
00117 min_pos_[2]=ref_point.z()-d;
00118 max_pos_[0]=ref_point.x();
00119 max_pos_[1]=ref_point.y();
00120 max_pos_[2]=ref_point.z();
00121 }
00122 else
00123 assert(!"point_type should be one of: centre, min_pos, max_pos");
00124 }
00125
00126 template <class Type>
00127 Type vgl_box_3d<Type>::width() const
00128 {
00129 return (max_pos_[0] > min_pos_[0]) ? max_pos_[0] - min_pos_[0] : 0;
00130 }
00131
00132 template <class Type>
00133 Type vgl_box_3d<Type>::height() const
00134 {
00135 return (max_pos_[1] > min_pos_[1]) ? max_pos_[1] - min_pos_[1] : 0;
00136 }
00137
00138 template <class Type>
00139 Type vgl_box_3d<Type>::depth() const
00140 {
00141 return (max_pos_[2] > min_pos_[2]) ? max_pos_[2] - min_pos_[2] : 0;
00142 }
00143
00144 template <class Type>
00145 vgl_point_3d<Type> vgl_box_3d<Type>::centroid() const
00146 {
00147 return vgl_point_3d<Type>(centroid_x(),centroid_y(),centroid_z());
00148 }
00149
00150 template <class Type>
00151 Type vgl_box_3d<Type>::centroid_x() const
00152 {
00153 assert(!is_empty());
00154 return Type(0.5*(min_pos_[0]+max_pos_[0]));
00155 }
00156
00157 template <class Type>
00158 Type vgl_box_3d<Type>::centroid_y() const
00159 {
00160 assert(!is_empty());
00161 return Type(0.5*(min_pos_[1]+max_pos_[1]));
00162 }
00163
00164 template <class Type>
00165 Type vgl_box_3d<Type>::centroid_z() const
00166 {
00167 assert(!is_empty());
00168 return Type(0.5*(min_pos_[2]+max_pos_[2]));
00169 }
00170
00171 template <class Type>
00172 void vgl_box_3d<Type>::set_centroid_x(Type cx)
00173 {
00174 assert(!is_empty());
00175 Type delta = cx - centroid_x();
00176 min_pos_[0]= min_pos_[0] + delta;
00177 max_pos_[0]= max_pos_[0] + delta;
00178 }
00179
00180 template <class Type>
00181 void vgl_box_3d<Type>::set_centroid_y(Type cy)
00182 {
00183 assert(!is_empty());
00184 Type delta = cy - centroid_y();
00185 min_pos_[1]= min_pos_[1] + delta;
00186 max_pos_[1]= max_pos_[1] + delta;
00187 }
00188
00189 template <class Type>
00190 void vgl_box_3d<Type>::set_centroid_z(Type cz)
00191 {
00192 assert(!is_empty());
00193 Type delta = cz - centroid_z();
00194 min_pos_[2]= min_pos_[2] + delta;
00195 max_pos_[2]= max_pos_[2] + delta;
00196 }
00197
00198 template <class T>
00199 inline void set_dim_3d(T& minv, T& maxv, T spread);
00200
00201
00202 VCL_DEFINE_SPECIALIZATION
00203 inline void set_dim_3d(int& minv, int& maxv, int spread)
00204 {
00205 int sum = minv + maxv;
00206 sum = sum | (spread&1);
00207 minv = int(vcl_floor((sum-spread)/2.0));
00208 maxv = minv+spread;
00209 }
00210
00211 template <class T>
00212 inline void set_dim_3d(T& minv, T& maxv, T spread)
00213 {
00214 T x = minv + maxv;
00215 minv = T( (x-spread)*0.5 );
00216 maxv = minv + spread;
00217 }
00218
00219 template <class Type>
00220 void vgl_box_3d<Type>::set_width(Type w)
00221 {
00222 assert(!is_empty());
00223 set_dim_3d(min_pos_[0], max_pos_[0], w);
00224 }
00225
00226 template <class Type>
00227 void vgl_box_3d<Type>::set_height(Type h)
00228 {
00229 assert(!is_empty());
00230 set_dim_3d(min_pos_[1], max_pos_[1], h);
00231 }
00232
00233 template <class Type>
00234 void vgl_box_3d<Type>::set_depth(Type d)
00235 {
00236 assert(!is_empty());
00237 set_dim_3d(min_pos_[2], max_pos_[2], d);
00238 }
00239
00240
00241
00242 template <class Type>
00243 void vgl_box_3d<Type>::expand_about_centroid(Type expand)
00244 {
00245 assert(!is_empty());
00246 set_dim_3d(min_pos_[0], max_pos_[0], width() + expand );
00247 set_dim_3d(min_pos_[1], max_pos_[1], height() + expand );
00248 set_dim_3d(min_pos_[2], max_pos_[2], depth() + expand );
00249 }
00250
00251
00252 template <class Type>
00253 void vgl_box_3d<Type>::scale_about_centroid(double s)
00254 {
00255 assert(!is_empty());
00256 set_dim_3d(min_pos_[0], max_pos_[0], static_cast<Type>(width()*s));
00257 set_dim_3d(min_pos_[1], max_pos_[1], static_cast<Type>(height()*s));
00258 set_dim_3d(min_pos_[2], max_pos_[2], static_cast<Type>(depth()*s));
00259 }
00260
00261
00262 template <class Type>
00263 void vgl_box_3d<Type>::scale_about_origin(double s)
00264 {
00265 min_pos_[0] = static_cast<Type>(min_pos_[0] * s);
00266 min_pos_[1] = static_cast<Type>(min_pos_[1] * s);
00267 min_pos_[2] = static_cast<Type>(min_pos_[2] * s);
00268 max_pos_[0] = static_cast<Type>(max_pos_[0] * s);
00269 max_pos_[1] = static_cast<Type>(max_pos_[1] * s);
00270 max_pos_[2] = static_cast<Type>(max_pos_[2] * s);
00271 }
00272
00273 template <class Type>
00274 void vgl_box_3d<Type>::set_min_position(Type const min_position[3])
00275 {
00276 min_pos_[0]=min_position[0];
00277 min_pos_[1]=min_position[1];
00278 min_pos_[2]=min_position[2];
00279 if (max_pos_[0] < min_pos_[0]) max_pos_[0]=min_pos_[0];
00280 if (max_pos_[1] < min_pos_[1]) max_pos_[1]=min_pos_[1];
00281 if (max_pos_[2] < min_pos_[2]) max_pos_[2]=min_pos_[2];
00282 }
00283
00284 template <class Type>
00285 void vgl_box_3d<Type>::set_max_position(Type const max_position[3])
00286 {
00287 max_pos_[0]=max_position[0];
00288 max_pos_[1]=max_position[1];
00289 max_pos_[2]=max_position[2];
00290 if (max_pos_[0] < min_pos_[0]) min_pos_[0]=max_pos_[0];
00291 if (max_pos_[1] < min_pos_[1]) min_pos_[1]=max_pos_[1];
00292 if (max_pos_[2] < min_pos_[2]) min_pos_[2]=max_pos_[2];
00293 }
00294
00295 template <class Type>
00296 void vgl_box_3d<Type>::set_min_point(vgl_point_3d<Type> const& min_pt)
00297 {
00298 min_pos_[0]=min_pt.x(); if (max_pos_[0]<min_pos_[0]) max_pos_[0]=min_pos_[0];
00299 min_pos_[1]=min_pt.y(); if (max_pos_[1]<min_pos_[1]) max_pos_[1]=min_pos_[1];
00300 min_pos_[2]=min_pt.z(); if (max_pos_[2]<min_pos_[2]) max_pos_[2]=min_pos_[2];
00301 }
00302
00303 template <class Type>
00304 void vgl_box_3d<Type>::set_max_point(vgl_point_3d<Type> const& max_pt)
00305 {
00306 max_pos_[0]=max_pt.x(); if (max_pos_[0]<min_pos_[0]) min_pos_[0]=max_pos_[0];
00307 max_pos_[1]=max_pt.y(); if (max_pos_[1]<min_pos_[1]) min_pos_[1]=max_pos_[1];
00308 max_pos_[2]=max_pt.z(); if (max_pos_[2]<min_pos_[2]) min_pos_[2]=max_pos_[2];
00309 }
00310
00311 template <class Type>
00312 vcl_ostream& vgl_box_3d<Type>::print(vcl_ostream& s) const
00313 {
00314 if (is_empty())
00315 return s << "<vgl_box_3d (empty)>";
00316 else
00317 return s<< "<vgl_box_3d "
00318 << min_pos_[0] << ',' << min_pos_[1] << ',' << min_pos_[2] << " to "
00319 << max_pos_[0] << ',' << max_pos_[1] << ',' << max_pos_[2] << '>';
00320 }
00321
00322 template <class Type>
00323 vgl_point_3d<Type> vgl_box_3d<Type>::min_point() const
00324 {
00325 assert(!is_empty());
00326 return vgl_point_3d<Type>(min_pos_[0],min_pos_[1],min_pos_[2]);
00327 }
00328
00329 template <class Type>
00330 vgl_point_3d<Type> vgl_box_3d<Type>::max_point() const
00331 {
00332 assert(!is_empty());
00333 return vgl_point_3d<Type>(max_pos_[0],max_pos_[1],max_pos_[2]);
00334 }
00335
00336 template <class Type>
00337 vcl_vector<vgl_point_3d<Type> > vgl_box_3d<Type>::vertices() const
00338 {
00339 assert(!is_empty());
00340 vcl_vector<vgl_point_3d<Type> > vertices;
00341 vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], min_pos_[2]));
00342 vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], min_pos_[2]));
00343 vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], min_pos_[2]));
00344 vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], min_pos_[2]));
00345 vertices.push_back(vgl_point_3d<Type>(min_pos_[0], min_pos_[1], max_pos_[2]));
00346 vertices.push_back(vgl_point_3d<Type>(max_pos_[0], min_pos_[1], max_pos_[2]));
00347 vertices.push_back(vgl_point_3d<Type>(max_pos_[0], max_pos_[1], max_pos_[2]));
00348 vertices.push_back(vgl_point_3d<Type>(min_pos_[0], max_pos_[1], max_pos_[2]));
00349 return vertices;
00350 }
00351
00352 template <class Type>
00353 vcl_ostream& vgl_box_3d<Type>::write(vcl_ostream& s) const
00354 {
00355 return s << min_pos_[0] << ' ' << min_pos_[1] << ' ' << min_pos_[2] << ' '
00356 << max_pos_[0] << ' ' << max_pos_[1] << ' ' << max_pos_[2] << '\n';
00357 }
00358
00359 template <class Type>
00360 vcl_istream& vgl_box_3d<Type>::read(vcl_istream& s)
00361 {
00362 return s >> min_pos_[0] >> min_pos_[1] >> min_pos_[2]
00363 >> max_pos_[0] >> max_pos_[1] >> max_pos_[2];
00364 }
00365
00366
00367
00368
00369 template <class Type>
00370 void vgl_box_3d<Type>::add(vgl_point_3d<Type> const& p)
00371 {
00372 if (is_empty())
00373 {
00374 min_pos_[0] = max_pos_[0] = p.x();
00375 min_pos_[1] = max_pos_[1] = p.y();
00376 min_pos_[2] = max_pos_[2] = p.z();
00377 }
00378 else
00379 {
00380 if (p.x() > max_pos_[0]) max_pos_[0] = p.x();
00381 if (p.x() < min_pos_[0]) min_pos_[0] = p.x();
00382 if (p.y() > max_pos_[1]) max_pos_[1] = p.y();
00383 if (p.y() < min_pos_[1]) min_pos_[1] = p.y();
00384 if (p.z() > max_pos_[2]) max_pos_[2] = p.z();
00385 if (p.z() < min_pos_[2]) min_pos_[2] = p.z();
00386 }
00387 }
00388
00389
00390
00391
00392
00393 template <class Type>
00394 void vgl_box_3d<Type>::add(vgl_box_3d<Type> const& b)
00395 {
00396 if (b.is_empty()) return;
00397 add(b.min_point());
00398 add(b.max_point());
00399 }
00400
00401
00402 template <class Type>
00403 bool vgl_box_3d<Type>::contains(vgl_point_3d<Type> const& p) const
00404 {
00405 return contains(p.x(), p.y(), p.z());
00406 }
00407
00408
00409 template <class Type>
00410 bool vgl_box_3d<Type>::contains(vgl_box_3d<Type> const& b) const
00411 {
00412 return
00413 contains(b.min_x(), b.min_y(), b.min_z()) &&
00414 contains(b.max_x(), b.max_y(), b.max_z());
00415 }
00416
00417
00418 template <class Type>
00419 void vgl_box_3d<Type>::empty()
00420 {
00421 min_pos_[0]=min_pos_[1]=min_pos_[2]=(Type)1;
00422 max_pos_[0]=max_pos_[1]=max_pos_[2]=(Type)0;
00423 }
00424
00425
00426 template <class Type>
00427 vcl_ostream& operator<<(vcl_ostream& s, vgl_box_3d<Type> const& p)
00428 {
00429 return p.print(s);
00430 }
00431
00432
00433 template <class Type>
00434 vcl_istream& operator>>(vcl_istream& is, vgl_box_3d<Type>& p)
00435 {
00436 return p.read(is);
00437 }
00438
00439 #undef VGL_BOX_3D_INSTANTIATE
00440 #define VGL_BOX_3D_INSTANTIATE(Type) \
00441 template class vgl_box_3d<Type >;\
00442 template vcl_ostream& operator<<(vcl_ostream&, vgl_box_3d<Type > const& p);\
00443 template vcl_istream& operator>>(vcl_istream&, vgl_box_3d<Type >& p)
00444
00445 #endif // vgl_box_3d_txx_