contrib/gel/vsol/vsol_poly_set_2d.cxx
Go to the documentation of this file.
00001 // This is gel/vsol/vsol_poly_set_2d.cxx
00002 #include "vsol_poly_set_2d.h"
00003 //:
00004 // \file
00005 #include <vsl/vsl_vector_io.h>
00006 #include <vcl_iostream.h>
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h>
00009 #include <vsol/vsol_polygon_2d.h>
00010 
00011 //***************************************************************************
00012 // Initialization
00013 //***************************************************************************
00014 
00015 //---------------------------------------------------------------------------
00016 //: Constructor from a vcl_vector (not a geometric vector but a list of points)
00017 // Require: new_vertices.size()>=3
00018 //---------------------------------------------------------------------------
00019 vsol_poly_set_2d::vsol_poly_set_2d(const vcl_vector<vsol_polygon_2d_sptr> &new_polys)
00020   : vsol_region_2d()
00021 {
00022   storage_=new vcl_vector<vsol_polygon_2d_sptr>(new_polys);
00023 }
00024 
00025 //---------------------------------------------------------------------------
00026 // Copy constructor
00027 //---------------------------------------------------------------------------
00028 vsol_poly_set_2d::vsol_poly_set_2d(const vsol_poly_set_2d &other)
00029   : vsol_region_2d(other)
00030 {
00031   //vsol_point_2d_sptr p;
00032   storage_=new vcl_vector<vsol_polygon_2d_sptr>(*other.storage_);
00033   for (unsigned int i=0;i<storage_->size();++i)
00034     (*storage_)[i]=new vsol_polygon_2d(*((*other.storage_)[i]));
00035 }
00036 
00037 //---------------------------------------------------------------------------
00038 // Destructor
00039 //---------------------------------------------------------------------------
00040 vsol_poly_set_2d::~vsol_poly_set_2d()
00041 {
00042   for (unsigned i = 0; i < storage_->size(); i++)
00043    (*storage_)[i] = 0;
00044   delete storage_;
00045 }
00046 
00047 //---------------------------------------------------------------------------
00048 //: Clone `this': creation of a new object and initialization
00049 // See Prototype pattern
00050 //---------------------------------------------------------------------------
00051 vsol_spatial_object_2d* vsol_poly_set_2d::clone(void) const
00052 {
00053   return new vsol_poly_set_2d(*this);
00054 }
00055 
00056 //***************************************************************************
00057 // Safe casting
00058 //***************************************************************************
00059 
00060 #if 0
00061 vsol_poly_set_2d* vsol_poly_set_2d::cast_to_poly_set(void)
00062 {
00063   if (!cast_to_triangle()||!cast_to_rectangle())
00064     return this;
00065   else
00066     return 0;
00067 }
00068 
00069 const vsol_poly_set_2d* vsol_poly_set_2d::cast_to_poly_set(void) const
00070 {
00071   if (!cast_to_triangle()||!cast_to_rectangle())
00072     return this;
00073   else
00074     return 0;
00075 }
00076 
00077 vsol_triangle_2d* vsol_poly_set_2d::cast_to_triangle(void){return 0;}
00078 const vsol_triangle_2d* vsol_poly_set_2d::cast_to_triangle(void) const{return 0;}
00079 
00080 vsol_rectangle_2d* vsol_poly_set_2d::cast_to_rectangle(void){return 0;}
00081 const vsol_rectangle_2d* vsol_poly_set_2d::cast_to_rectangle(void) const{return 0;}
00082 
00083 #endif // 0
00084 
00085 //***************************************************************************
00086 // Access
00087 //***************************************************************************
00088 
00089 //---------------------------------------------------------------------------
00090 //: Return vertex `i'
00091 // Require: valid_index(i)
00092 //---------------------------------------------------------------------------
00093 vsol_polygon_2d_sptr vsol_poly_set_2d::poly(const int i) const
00094 {
00095   // require
00096   assert(valid_index(i));
00097 
00098   return (*storage_)[i];
00099 }
00100 
00101 //***************************************************************************
00102 // Comparison
00103 //***************************************************************************
00104 
00105 //---------------------------------------------------------------------------
00106 //: Has `this' the same points than `other' in the same order ?
00107 //---------------------------------------------------------------------------
00108 bool vsol_poly_set_2d::operator==(const vsol_poly_set_2d &other) const
00109 {
00110   bool result = (this==&other);
00111 
00112   if (!result)
00113   {
00114     result = (storage_->size()==other.storage_->size());
00115     if (result)
00116     {
00117       vsol_polygon_2d_sptr p=(*storage_)[0];
00118 
00119       unsigned int i=0;
00120       for (result=false;i<storage_->size()&&!result;++i)
00121         result = (*p==*(*other.storage_)[i]);
00122       if (result)
00123       {
00124         for (unsigned int j=1;j<size()&&result;++i,++j)
00125         {
00126           if (i>=storage_->size()) i=0;
00127           result = ((*storage_)[i]==(*storage_)[j]);
00128         }
00129       }
00130     }
00131   }
00132   return result;
00133 }
00134 
00135 //: spatial object equality
00136 
00137 bool vsol_poly_set_2d::operator==(const vsol_spatial_object_2d& obj) const
00138 {
00139   return
00140     obj.cast_to_region() && obj.cast_to_region()->cast_to_poly_set() &&
00141     *this == *obj.cast_to_region()->cast_to_poly_set();
00142 }
00143 
00144 
00145 //---------------------------------------------------------------------------
00146 //: Compute the bounding box of `this'
00147 //---------------------------------------------------------------------------
00148 void vsol_poly_set_2d::compute_bounding_box(void) const
00149 {
00150   set_bounding_box((*storage_)[0]->get_bounding_box());
00151   for (unsigned int i=1;i<storage_->size();++i)
00152     add_to_bounding_box((*storage_)[i]->get_bounding_box());
00153 }
00154 
00155 //---------------------------------------------------------------------------
00156 //: Return the area of `this'
00157 //---------------------------------------------------------------------------
00158 double vsol_poly_set_2d::area(void) const
00159 {
00160   double area = 0.0;
00161   unsigned int last = storage_->size()-1;
00162 
00163   for (unsigned int i=0; i<last; ++i)
00164     area += ((*storage_)[i]->area());;
00165 
00166   return vcl_abs(area / 2.0);
00167 }
00168 
00169 //---------------------------------------------------------------------------
00170 //: Return the centroid of `this'
00171 //---------------------------------------------------------------------------
00172 // The centroid is computed by using Green's theorem to compute the
00173 // area-weighted 1st moments of the poly_set.
00174 //  Green's theorem relates the surface integral to the line integral around
00175 //  the boundary as:
00176 //     Int(surface) x dxdy = 0.5 * Int(boundary) x*x dy
00177 //     Int(surface) y dxdy = 0.5 * Int(boundary) y*y dx
00178 //  The centroid is given by
00179 //     xc = Int(surface) x dxdy / Int(surface) dxdy  = Int(surface) x dxdy/area
00180 //     yc = Int(surface) y dxdy / Int(surface) dxdy  = Int(surface) y dxdy/area
00181 //
00182 //  For a poly_set: with vertices x[i], y[i]
00183 //   0.5 * Int(boundary) x*x dy =
00184 //   1/6 * Sum(i)( x[i+1] + x[i] ) * ( x[i] * y[i+1] - x[i+1] * y[i] )
00185 //
00186 //   0.5 * Int(boundary) y*y dx =
00187 //   1/6 * Sum(i)( y[i+1] + y[i] ) * ( x[i] * y[i+1] - x[i+1] * y[i] )
00188 //
00189 //  In the case of degenerate poly_sets, where area == 0, return the average of
00190 //  the vertex locations.
00191 //
00192 vsol_point_2d_sptr vsol_poly_set_2d::centroid(void) const
00193 {
00194   vcl_vector<vsol_point_2d_sptr> p;
00195   for (unsigned int i=0; i<storage_->size(); ++i)
00196   {
00197     vsol_point_2d_sptr c = (*storage_)[i]->centroid();
00198     p.push_back(c);
00199   }
00200   vsol_polygon_2d poly(p);
00201   return poly.centroid();
00202 }
00203 
00204 //---------------------------------------------------------------------------
00205 //: Is `this' convex ?
00206 // A poly_set is convex if the direction of "turning" at every vertex is
00207 // the same.  This is checked by calculating the cross product of two
00208 // consecutive edges and verifying that these all have the same sign.
00209 //---------------------------------------------------------------------------
00210 bool vsol_poly_set_2d::is_convex(void) const
00211 {
00212   // First find a non-zero cross product.  This is certainly present,
00213   // unless the poly_set collapses to a line segment.
00214   // Note that cross-product=0 means that two edges are parallel, which
00215   // is perfectly valid, but the other "turnings" should still all be in
00216   // the same direction.  An earlier implementation allowed for turning
00217   // in the other direction after a cross-product=0.
00218 
00219   for (unsigned int i=0; i<storage_->size(); ++i)
00220   {
00221     if ((*storage_)[i]->is_convex())
00222       return true;
00223   }
00224   return false;
00225 }
00226 
00227 //----------------------------------------------------------------
00228 // ================   Binary I/O Methods ========================
00229 //----------------------------------------------------------------
00230 
00231 //: Binary save self to stream.
00232 void vsol_poly_set_2d::b_write(vsl_b_ostream &os) const
00233 {
00234   vsl_b_write(os, version());
00235   vsol_spatial_object_2d::b_write(os);
00236   if (!storage_)
00237     vsl_b_write(os, false); // Indicate null pointer stored
00238   else
00239   {
00240     vsl_b_write(os, true); // Indicate non-null pointer stored
00241     vsl_b_write(os, *storage_);
00242   }
00243 }
00244 
00245 //: Binary load self from stream (not typically used)
00246 void vsol_poly_set_2d::b_read(vsl_b_istream &is)
00247 {
00248   short ver;
00249   vsl_b_read(is, ver);
00250   switch (ver)
00251   {
00252    case 1:
00253     vsol_spatial_object_2d::b_read(is);
00254 
00255     delete storage_;
00256     storage_ = new vcl_vector<vsol_polygon_2d_sptr>();
00257     bool null_ptr;
00258     vsl_b_read(is, null_ptr);
00259     if (!null_ptr)
00260       return;
00261     vsl_b_read(is, *storage_);
00262     break;
00263    default:
00264     vcl_cerr << "vsol_poly_set_2d: unknown I/O version " << ver << '\n';
00265   }
00266 }
00267 
00268 //: Return IO version number;
00269 short vsol_poly_set_2d::version() const
00270 {
00271   return 1;
00272 }
00273 
00274 //: Print an ascii summary to the stream
00275 void vsol_poly_set_2d::print_summary(vcl_ostream &os) const
00276 {
00277   os << *this;
00278 }
00279 
00280 //***************************************************************************
00281 // Implementation
00282 //***************************************************************************
00283 
00284 //---------------------------------------------------------------------------
00285 //: Default constructor.
00286 //---------------------------------------------------------------------------
00287 vsol_poly_set_2d::vsol_poly_set_2d(void)
00288 {
00289   storage_=new vcl_vector<vsol_polygon_2d_sptr>();
00290 }
00291 
00292 
00293 //: Binary save vsol_poly_set_2d to stream.
00294 void
00295 vsl_b_write(vsl_b_ostream &os, const vsol_poly_set_2d* p)
00296 {
00297   if (p==0) {
00298     vsl_b_write(os, false); // Indicate null pointer stored
00299   }
00300   else{
00301     vsl_b_write(os,true); // Indicate non-null pointer stored
00302     p->b_write(os);
00303   }
00304 }
00305 
00306 
00307 //: Binary load vsol_poly_set_2d from stream.
00308 void
00309 vsl_b_read(vsl_b_istream &is, vsol_poly_set_2d* &p)
00310 {
00311   delete p;
00312   bool not_null_ptr;
00313   vsl_b_read(is, not_null_ptr);
00314   if (not_null_ptr) {
00315     p = new vsol_poly_set_2d();
00316     p->b_read(is);
00317   }
00318   else
00319     p = 0;
00320 }
00321 
00322 
00323 inline void vsol_poly_set_2d::describe(vcl_ostream &strm, int blanking) const
00324 {
00325   if (blanking < 0) blanking = 0; while (blanking--) strm << ' ';
00326   if (size() == 0)
00327     strm << "[null]";
00328   else {
00329     strm << "[Nverts=" << size()
00330          << " Area=" << area();
00331     for (unsigned int i=0; i<size(); ++i)
00332       strm << " p" << i << ':' << *(poly(i));
00333     strm << ']';
00334   }
00335   strm << vcl_endl;
00336 }