core/vgl/vgl_box_2d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_box_2d.txx
00002 #ifndef vgl_box_2d_txx_
00003 #define vgl_box_2d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_box_2d.h"
00008 #include <vcl_iostream.h>
00009 #include <vcl_algorithm.h>
00010 #include <vcl_cassert.h>
00011 #include <vcl_cmath.h>
00012 #include <vgl/vgl_point_2d.h>
00013 
00014 // Constructors/Destructor---------------------------------------------------
00015 
00016 template <class Type>
00017 vgl_box_2d<Type>::vgl_box_2d()
00018 {
00019   min_pos_[0]=min_pos_[1]=(Type)1;
00020   max_pos_[0]=max_pos_[1]=(Type)0; // empty box
00021 }
00022 
00023 template <class Type>
00024 vgl_box_2d<Type>::vgl_box_2d(Type const corner1[2],
00025                              Type const corner2[2])
00026 {
00027   min_pos_[0]=max_pos_[0]=corner1[0];
00028   min_pos_[1]=max_pos_[1]=corner1[1];
00029   this->add(corner2);
00030 }
00031 
00032 template <class Type>
00033 vgl_box_2d<Type>::vgl_box_2d(vgl_point_2d<Type> const& corner1,
00034                              vgl_point_2d<Type> const& corner2)
00035 {
00036   min_pos_[0]=max_pos_[0]=corner1.x();
00037   min_pos_[1]=max_pos_[1]=corner1.y();
00038   this->add(corner2);
00039 }
00040 
00041 template <class Type>
00042 vgl_box_2d<Type>::vgl_box_2d(Type xmin, Type xmax, Type ymin, Type ymax)
00043 {
00044   min_pos_[0]=max_pos_[0]=xmin;
00045   min_pos_[1]=max_pos_[1]=ymin;
00046   this->add(vgl_point_2d<Type>(xmax,ymax));
00047   if (xmin > xmax || ymin > ymax) this->empty();
00048 }
00049 
00050 template <class Type>
00051 vgl_box_2d<Type>::vgl_box_2d(Type const ref_point[2],
00052                              Type w, Type h,
00053                              typename vgl_box_2d<Type>::point_type t)
00054 {
00055   if (t == vgl_box_2d<Type>::centre)
00056   {
00057     min_pos_[0]=Type(ref_point[0]-0.5*w);
00058     min_pos_[1]=Type(ref_point[1]-0.5*h);
00059     max_pos_[0]=Type(ref_point[0]+0.5*w);
00060     max_pos_[1]=Type(ref_point[1]+0.5*h);
00061   }
00062   else if (t == vgl_box_2d<Type>::min_pos)
00063   {
00064     min_pos_[0]=ref_point[0];
00065     min_pos_[1]=ref_point[1];
00066     max_pos_[0]=ref_point[0]+w;
00067     max_pos_[1]=ref_point[1]+h;
00068   }
00069   else if (t == vgl_box_2d<Type>::max_pos)
00070   {
00071     min_pos_[0]=ref_point[0]-w;
00072     min_pos_[1]=ref_point[1]-h;
00073     max_pos_[0]=ref_point[0];
00074     max_pos_[1]=ref_point[1];
00075   }
00076   else
00077     assert(!"point_type should be one of: centre, min_pos, max_pos");
00078 }
00079 
00080 template <class Type>
00081 vgl_box_2d<Type>::vgl_box_2d(vgl_point_2d<Type> const& ref_point,
00082                              Type w, Type h,
00083                              typename vgl_box_2d<Type>::point_type t)
00084 {
00085   if (t == vgl_box_2d<Type>::centre)
00086   {
00087     min_pos_[0]=Type(ref_point.x()-0.5*w);
00088     min_pos_[1]=Type(ref_point.y()-0.5*h);
00089     max_pos_[0]=Type(ref_point.x()+0.5*w);
00090     max_pos_[1]=Type(ref_point.y()+0.5*h);
00091   }
00092   else if (t == vgl_box_2d<Type>::min_pos)
00093   {
00094     min_pos_[0]=ref_point.x();
00095     min_pos_[1]=ref_point.y();
00096     max_pos_[0]=ref_point.x()+w;
00097     max_pos_[1]=ref_point.y()+h;
00098   }
00099   else if (t == vgl_box_2d<Type>::max_pos)
00100   {
00101     min_pos_[0]=ref_point.x()-w;
00102     min_pos_[1]=ref_point.y()-h;
00103     max_pos_[0]=ref_point.x();
00104     max_pos_[1]=ref_point.y();
00105   }
00106   else
00107     assert(!"point_type should be one of: centre, min_pos, max_pos");
00108 }
00109 
00110 template <class Type>
00111 Type vgl_box_2d<Type>::centroid_x() const
00112 {
00113   assert(!is_empty());
00114   return Type(0.5*(min_pos_[0] + max_pos_[0]));
00115 }
00116 
00117 template <class Type>
00118 Type vgl_box_2d<Type>::centroid_y() const
00119 {
00120   assert(!is_empty());
00121   return Type(0.5*(min_pos_[1] + max_pos_[1]));
00122 }
00123 
00124 template <class Type>
00125 Type vgl_box_2d<Type>::width() const
00126 {
00127   return (max_pos_[0] > min_pos_[0]) ? max_pos_[0] - min_pos_[0] : 0;
00128 }
00129 
00130 template <class Type>
00131 Type vgl_box_2d<Type>::height() const
00132 {
00133   return (max_pos_[1] > min_pos_[1]) ? max_pos_[1] - min_pos_[1] : 0;
00134 }
00135 
00136 template <class Type>
00137 vgl_point_2d<Type> vgl_box_2d<Type>::min_point() const
00138 {
00139   assert(!is_empty());
00140   return vgl_point_2d<Type>(min_pos_[0],min_pos_[1]);
00141 }
00142 
00143 template <class Type>
00144 vgl_point_2d<Type> vgl_box_2d<Type>::max_point() const
00145 {
00146   assert(!is_empty());
00147   return vgl_point_2d<Type>(max_pos_[0],max_pos_[1]);
00148 }
00149 
00150 template <class Type>
00151 vgl_point_2d<Type> vgl_box_2d<Type>::centroid() const
00152 {
00153   assert(!is_empty());
00154   return vgl_point_2d<Type>(centroid_x(),centroid_y());
00155 }
00156 
00157 template <class Type>
00158 void vgl_box_2d<Type>::set_centroid_x(Type cent_x)
00159 {
00160   assert(!is_empty());
00161   Type delta = cent_x - centroid_x();
00162   min_pos_[0]= min_pos_[0] + delta;
00163   max_pos_[0]= max_pos_[0] + delta;
00164 }
00165 
00166 template <class Type>
00167 void vgl_box_2d<Type>::set_centroid_y(Type cent_y)
00168 {
00169   assert(!is_empty());
00170   Type delta = cent_y - centroid_y();
00171   min_pos_[1]= min_pos_[1] + delta;
00172   max_pos_[1]= max_pos_[1] + delta;
00173 }
00174 
00175 template <class T>
00176 inline void set_dim_2d(T & minv, T& maxv, T spread);
00177 
00178 // All this code is to avoid drift in the centroid.
00179 VCL_DEFINE_SPECIALIZATION
00180 inline void set_dim_2d(int & minv, int& maxv, int spread)
00181 {
00182   int sum = minv + maxv;
00183   sum = sum | (spread&1); // if width is odd, then make sum odd
00184   minv = int(vcl_floor((sum-spread)/2.0));
00185   maxv = minv+spread;
00186 }
00187 
00188 template <class T>
00189 inline void set_dim_2d(T & minv, T& maxv, T spread)
00190 {
00191   T x = minv + maxv;
00192   minv = T( (x-spread)*0.5 );
00193   maxv = minv + spread;
00194 }
00195 
00196 //: Modify width, retaining centroid at current position
00197 // For integer types, centroid might change slightly, but
00198 // repeat calls to set_height will not cause centroid drift.
00199 template <class Type>
00200 void vgl_box_2d<Type>::set_width(Type w)
00201 {
00202   assert(!is_empty());
00203   set_dim_2d(min_pos_[0], max_pos_[0], w);
00204 }
00205 
00206 //: Modify height, retaining centroid at current position
00207 // For integer types, centroid might change slightly, but
00208 // repeat calls to set_height will not cause centroid drift.
00209 template <class Type>
00210 void vgl_box_2d<Type>::set_height(Type h)
00211 {
00212   assert(!is_empty());
00213   set_dim_2d(min_pos_[1], max_pos_[1], h);
00214 }
00215 
00216 
00217 //: Add to width and height, centroid unchanged.
00218 // Will move each side by \p expand / 2.
00219 template <class Type>
00220 void vgl_box_2d<Type>::expand_about_centroid(Type expand)
00221 {
00222   assert(!is_empty());
00223   set_dim_2d(min_pos_[0], max_pos_[0], width() + expand );
00224   set_dim_2d(min_pos_[1], max_pos_[1], height() + expand );
00225 }
00226 
00227 //: Scale width and height, centroid unchanged.
00228 template <class Type>
00229 void vgl_box_2d<Type>::scale_about_centroid(double s)
00230 {
00231   assert(!is_empty());
00232   set_dim_2d(min_pos_[0], max_pos_[0], static_cast<Type>(width()*s));
00233   set_dim_2d(min_pos_[1], max_pos_[1], static_cast<Type>(height()*s));
00234 }
00235 
00236 
00237 //: Scale width and height, keeping scaled position of origin unchanged.
00238 template <class Type>
00239 void vgl_box_2d<Type>::scale_about_origin(double s)
00240 {
00241   min_pos_[0] = static_cast<Type>(min_pos_[0] * s);
00242   min_pos_[1] = static_cast<Type>(min_pos_[1] * s);
00243   max_pos_[0] = static_cast<Type>(max_pos_[0] * s);
00244   max_pos_[1] = static_cast<Type>(max_pos_[1] * s);
00245 }
00246 
00247 template <class Type>
00248 void vgl_box_2d<Type>::setmin_position(Type const min_position[2])
00249 {
00250   min_pos_[0]=min_position[0];
00251   min_pos_[1]=min_position[1];
00252   if (max_pos_[0] < min_pos_[0]) {
00253     max_pos_[0]=min_pos_[0];
00254   }
00255   if (max_pos_[1] < min_pos_[1]) {
00256     max_pos_[1]=min_pos_[1];
00257   }
00258 }
00259 
00260 template <class Type>
00261 void vgl_box_2d<Type>::setmax_position(Type const max_position[2])
00262 {
00263   max_pos_[0]=max_position[0];
00264   max_pos_[1]=max_position[1];
00265   if (max_pos_[0] < min_pos_[0])
00266     min_pos_[0]=max_pos_[0];
00267   if (max_pos_[1] < min_pos_[1])
00268     min_pos_[1]=max_pos_[1];
00269 }
00270 
00271 template <class Type>
00272 void vgl_box_2d<Type>::set_min_point(vgl_point_2d<Type> const& min_pt)
00273 {
00274   min_pos_[0]=min_pt.x(); if (max_pos_[0]<min_pos_[0]) max_pos_[0]=min_pos_[0];
00275   min_pos_[1]=min_pt.y(); if (max_pos_[1]<min_pos_[1]) max_pos_[1]=min_pos_[1];
00276 }
00277 
00278 template <class Type>
00279 void vgl_box_2d<Type>::set_max_point(vgl_point_2d<Type> const& max_pt)
00280 {
00281   max_pos_[0]=max_pt.x(); if (max_pos_[0]<min_pos_[0]) min_pos_[0]=max_pos_[0];
00282   max_pos_[1]=max_pt.y(); if (max_pos_[1]<min_pos_[1]) min_pos_[1]=max_pos_[1];
00283 }
00284 
00285 template <class Type>
00286 vcl_ostream& vgl_box_2d<Type>::print(vcl_ostream& s) const
00287 {
00288   if (is_empty())
00289     return s << "<vgl_box_2d (empty)>";
00290   else
00291     return s << "<vgl_box_2d "
00292              << min_pos_[0] << ',' << min_pos_[1] << " to "
00293              << max_pos_[0] << ',' << max_pos_[1] << '>';
00294 }
00295 
00296 template <class Type>
00297 vcl_ostream& vgl_box_2d<Type>::write(vcl_ostream& s) const
00298 {
00299   return s << min_pos_[0] << ' ' << min_pos_[1] << ' '
00300            << max_pos_[0] << ' ' << max_pos_[1] << '\n';
00301 }
00302 
00303 template <class Type>
00304 vcl_istream& vgl_box_2d<Type>::read(vcl_istream& s)
00305 {
00306   return s >> min_pos_[0] >> min_pos_[1]
00307            >> max_pos_[0] >> max_pos_[1];
00308 }
00309 
00310 //: Add a point to this box.
00311 // Do this by possibly enlarging the box so that the point just falls within the box.
00312 // Adding a point to an empty box makes it a size zero box only containing p.
00313 template <class Type>
00314 void vgl_box_2d<Type>::add(vgl_point_2d<Type> const& p)
00315 {
00316   if (is_empty())
00317   {
00318     min_pos_[0] = max_pos_[0] = p.x();
00319     min_pos_[1] = max_pos_[1] = p.y();
00320   }
00321   else
00322   {
00323     if (p.x() > max_pos_[0]) max_pos_[0] = p.x();
00324     if (p.x() < min_pos_[0]) min_pos_[0] = p.x();
00325     if (p.y() > max_pos_[1]) max_pos_[1] = p.y();
00326     if (p.y() < min_pos_[1]) min_pos_[1] = p.y();
00327   }
00328 }
00329 
00330 //: Make the convex union of two boxes
00331 // Do this by possibly enlarging this box so that the corner points of the
00332 // given box just fall within the box.
00333 // Adding an empty box does not change the current box.
00334 template <class Type>
00335 void vgl_box_2d<Type>::add(vgl_box_2d<Type> const& b)
00336 {
00337   if (b.is_empty()) return;
00338   add(b.min_point());
00339   add(b.max_point());
00340 }
00341 
00342 //: Return true iff the point p is inside this box
00343 template <class Type>
00344 bool vgl_box_2d<Type>::contains(vgl_point_2d<Type> const& p) const
00345 {
00346   return contains(p.x(), p.y());
00347 }
00348 
00349 //: Return true iff the corner points of b are inside this box
00350 template <class Type>
00351 bool vgl_box_2d<Type>::contains(vgl_box_2d<Type> const& b) const
00352 {
00353   return
00354     contains(b.min_x(), b.min_y()) &&
00355     contains(b.max_x(), b.max_y());
00356 }
00357 
00358 //: Make the box empty
00359 template <class Type>
00360 void vgl_box_2d<Type>::empty()
00361 {
00362   min_pos_[0]=min_pos_[1]=(Type)1;
00363   max_pos_[0]=max_pos_[1]=(Type)0;
00364 }
00365 
00366 //: Print to stream
00367 template <class Type>
00368 vcl_ostream& operator<<(vcl_ostream& s, vgl_box_2d<Type> const& p)
00369 {
00370   return p.print(s);
00371 }
00372 
00373 //: Read from stream
00374 template <class Type>
00375 vcl_istream& operator>>(vcl_istream& is, vgl_box_2d<Type>& p)
00376 {
00377   return p.read(is);
00378 }
00379 
00380 #undef VGL_BOX_2D_INSTANTIATE
00381 #define VGL_BOX_2D_INSTANTIATE(Type) \
00382 template class vgl_box_2d<Type >;\
00383 template vcl_istream& operator>>(vcl_istream&, vgl_box_2d<Type >&);\
00384 template vcl_ostream& operator<<(vcl_ostream&, vgl_box_2d<Type > const&)
00385 
00386 #endif // vgl_box_2d_txx_