Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_BOX2
00025 #define __VCGLIB_BOX2
00026
00027 #include <assert.h>
00028 #include <algorithm>
00029 #include <vcg/math/base.h>
00030 #include <vcg/space/point2.h>
00031
00032 namespace vcg {
00033
00034
00035
00036 template <class SegScalarType> class Segment2;
00037
00044 template <class BoxScalarType>
00045 class Box2
00046 {
00047 public:
00049 typedef BoxScalarType ScalarType;
00050 typedef Point2<BoxScalarType> PointType ;
00051
00053 PointType min;
00055 PointType max;
00057 inline Box2() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; }
00059 inline Box2( const Box2 & b ) { min=b.min; max=b.max; }
00061 inline Box2( const Point2<BoxScalarType> & mi, const Point2<BoxScalarType> & ma ) { min = mi; max = ma; }
00062
00063 inline Box2(const Point2<BoxScalarType> & center, const BoxScalarType & radius) {
00064 min = center-Point2<BoxScalarType>(radius,radius);
00065 max = center+Point2<BoxScalarType>(radius,radius);
00066 }
00067
00069 inline ~Box2() { }
00071 inline bool operator == ( Box2 const & p ) const
00072 {
00073 return min==p.min && max==p.max;
00074 }
00076 void Set( const PointType & p )
00077 {
00078 min = max = p;
00079 }
00080
00081 Point2<BoxScalarType> P(const int & i) const
00082 {
00083 return Point2<BoxScalarType>(
00084 min[0]+ (i%2) * DimX(),
00085 min[1]+ ((i / 2)%2) * DimY());
00086 }
00087
00088
00089 inline void Set( ScalarType minx, ScalarType miny, ScalarType maxx, ScalarType maxy )
00090 {
00091 min[0] = minx;
00092 min[1] = miny;
00093 max[0] = maxx;
00094 max[1] = maxy;
00095 }
00097 void SetNull()
00098 {
00099 min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1;
00100 }
00105 void Add( Box2 const & b )
00106 {
00107 if(IsNull())
00108 {
00109 min=b.min;
00110 max=b.max;
00111 }
00112 else
00113 {
00114 if(min.X() > b.min.X()) min.X() = b.min.X();
00115 if(min.Y() > b.min.Y()) min.Y() = b.min.Y();
00116
00117 if(max.X() < b.max.X()) max.X() = b.max.X();
00118 if(max.Y() < b.max.Y()) max.Y() = b.max.Y();
00119 }
00120 }
00125 void Add( const PointType & p )
00126 {
00127 if(IsNull()) Set(p);
00128 else
00129 {
00130 if(min.X() > p.X()) min.X() = p.X();
00131 if(min.Y() > p.Y()) min.Y() = p.Y();
00132
00133 if(max.X() < p.X()) max.X() = p.X();
00134 if(max.Y() < p.Y()) max.Y() = p.Y();
00135 }
00136 }
00137
00141 void Offset(const ScalarType s)
00142 {
00143 Offset(PointType(s, s));
00144 }
00145
00149 void Offset(const PointType & delta)
00150 {
00151 min -= delta;
00152 max += delta;
00153 }
00154
00158 void Intersect( const Box2 & b )
00159 {
00160 if(min.X() < b.min.X()) min.X() = b.min.X();
00161 if(min.Y() < b.min.Y()) min.Y() = b.min.Y();
00162
00163 if(max.X() > b.max.X()) max.X() = b.max.X();
00164 if(max.Y() > b.max.Y()) max.Y() = b.max.Y();
00165
00166 if(min.X()>max.X() || min.Y()>max.Y()) SetNull();
00167 }
00168
00172 void Translate( const PointType & p )
00173 {
00174 min += p;
00175 max += p;
00176 }
00181 bool IsIn( PointType const & p ) const
00182 {
00183 return (
00184 min.X() <= p.X() && p.X() <= max.X() &&
00185 min.Y() <= p.Y() && p.Y() <= max.Y()
00186 );
00187 }
00192 bool IsInEx( PointType const & p ) const
00193 {
00194 return (
00195 min.X() <= p.X() && p.X() < max.X() &&
00196 min.Y() <= p.Y() && p.Y() < max.Y()
00197 );
00198 }
00204 bool Collide( Box2 const &b )
00205 {
00206 Box2 bb=*this;
00207 bb.Intersect(b);
00208 return bb.IsValid();
00209 }
00213 inline bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y(); }
00214
00218 inline bool IsValid() const { return min.X()<max.X() && min.Y()<max.Y(); }
00219
00223 inline bool IsEmpty() const { return min==max; }
00224
00226 ScalarType Diag() const
00227 {
00228 return Distance(min,max);
00229 }
00231 PointType Center() const
00232 {
00233 return (min+max)/2;
00234 }
00236 inline ScalarType Area() const
00237 {
00238 return (max[0]-min[0])*(max[1]-min[1]);
00239 }
00241 inline ScalarType DimX() const { return max.X()-min.X(); }
00243 inline ScalarType DimY() const { return max.Y()-min.Y(); }
00244
00246 inline PointType Dim() const { return max-min; }
00247
00249 inline void Normalize( PointType & p )
00250 {
00251 p -= min;
00252 p[0] /= max[0]-min[0];
00253 p[1] /= max[1]-min[1];
00254 }
00255
00257 PointType LocalToGlobal(PointType const & p) const{
00258 return PointType(
00259 min[0] + p[0]*(max[0]-min[0]),
00260 min[1] + p[1]*(max[1]-min[1]));
00261 }
00263 PointType GlobalToLocal(PointType const & p) const{
00264 return PointType(
00265 (p[0]-min[0])/(max[0]-min[0]),
00266 (p[1]-min[1])/(max[1]-min[1])
00267 );
00268 }
00269
00271 void MakeSquare(){
00272 ScalarType radius = max( DimX(), DimY() ) / 2;
00273 PointType c = Center();
00274 max = c + PointType(radius, radius);
00275 min = c - PointType(radius, radius);
00276 }
00277
00278 };
00279
00280 template <class ScalarType>
00281 ScalarType DistancePoint2Box2(const Point2<ScalarType> &test,
00282 const Box2<ScalarType> &bbox)
00283 {
00285 if (!bbox.IsIn(test)){
00286 if ((test.X()<=bbox.min.X())&&(test.Y()<=bbox.min.Y()))
00287 return ((test-bbox.min).Norm());
00288 else
00289 if ((test.X()>=bbox.min.X())&&
00290 (test.X()<=bbox.max.X())&&
00291 (test.Y()<=bbox.min.Y()))
00292 return (bbox.min.Y()-test.Y());
00293 else
00294 if ((test.X()>=bbox.max.X())&&
00295 (test.Y()<=bbox.min.Y()))
00296 return ((test-vcg::Point2<ScalarType>(bbox.max.X(),bbox.min.Y())).Norm());
00297 else
00298 if ((test.Y()>=bbox.min.Y())&&
00299 (test.Y()<=bbox.max.Y())&&
00300 (test.X()>=bbox.max.X()))
00301 return (test.X()-bbox.max.X());
00302 else
00303 if ((test.X()>=bbox.max.X())&&(test.Y()>=bbox.max.Y()))
00304 return ((test-bbox.max).Norm());
00305 else
00306 if ((test.X()>=bbox.min.X())&&
00307 (test.X()<=bbox.max.X())&&
00308 (test.Y()>=bbox.max.Y()))
00309 return (test.Y()-bbox.max.Y());
00310 else
00311 if ((test.X()<=bbox.min.X())&&
00312 (test.Y()>=bbox.max.Y()))
00313 return ((test-vcg::Point2<ScalarType>(bbox.min.X(),bbox.max.Y())).Norm());
00314 else
00315 if ((test.X()<=bbox.min.X())&&
00316 (test.Y()<=bbox.max.Y())&&
00317 (test.Y()>=bbox.min.Y()))
00318 return (bbox.min.X()-test.X());
00319 }
00320 else
00321 {
00322
00323 ScalarType dx=std::min<ScalarType>(fabs(test.X()-bbox.min.X()),fabs(bbox.max.X()-test.X()));
00324 ScalarType dy=std::min<ScalarType>(fabs(test.Y()-bbox.min.Y()),fabs(bbox.max.Y()-test.Y()));
00325 return(std::min<ScalarType>(dx,dy));
00326 }
00327 }
00328
00329 template <class ScalarType>
00330 Point2<ScalarType> ClosestPoint2Box2(const Point2<ScalarType> &test,
00331 const Box2<ScalarType> &bbox)
00332 {
00333 Segment2<ScalarType> Segs[4];
00334 Segs[0].P0() = bbox.min;
00335 Segs[0].P1() = vcg::Point2<ScalarType>(bbox.max.X(), bbox.min.Y());
00336
00337 Segs[1].P0() = Segs[0].P1();
00338 Segs[1].P1() = bbox.max;
00339
00340 Segs[2].P0() = Segs[1].P1();
00341 Segs[2].P1() = vcg::Point2<ScalarType>(bbox.min.X(), bbox.max.Y());
00342
00343 Segs[3].P0() = Segs[2].P1();
00344 Segs[3].P1() = bbox.min;
00345
00346 Point2<ScalarType> closest = ClosestPoint(Segs[0], test);
00347 ScalarType minDist = (closest-test).Norm();
00348 for (int i = 1; i < 4; i++)
00349 {
00350 Point2<ScalarType> point = ClosestPoint(Segs[i], test);
00351 ScalarType dist = (test - point).Norm();
00352 if (dist < minDist)
00353 {
00354 minDist = dist;
00355 closest = point;
00356 }
00357 }
00358 return closest;
00359 }
00360
00362 typedef Box2<short> Box2s;
00364 typedef Box2<int> Box2i;
00366 typedef Box2<float> Box2f;
00368 typedef Box2<double> Box2d;
00369
00371 }
00372
00373
00374 #endif