contrib/gel/vtol/vtol_face.cxx
Go to the documentation of this file.
00001 // This is gel/vtol/vtol_face.cxx
00002 #include "vtol_face.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_cassert.h>
00007 #include <vtol/vtol_macros.h>
00008 #include <vtol/vtol_two_chain.h>
00009 #include <vtol/vtol_vertex.h>
00010 #include <vtol/vtol_edge.h>
00011 #include <vtol/vtol_one_chain.h>
00012 #include <vtol/vtol_list_functions.h>
00013 
00014 void vtol_face::link_inferior(vtol_one_chain_sptr inf)
00015 {
00016   vtol_topology_object::link_inferior(inf->cast_to_topology_object());
00017 }
00018 
00019 void vtol_face::unlink_inferior(vtol_one_chain_sptr inf)
00020 {
00021   vtol_topology_object::unlink_inferior(inf->cast_to_topology_object());
00022 }
00023 
00024 //---------------------------------------------------------------------------
00025 // Destructor
00026 //---------------------------------------------------------------------------
00027 vtol_face::~vtol_face()
00028 {
00029   unlink_all_inferiors();
00030 }
00031 
00032 //:
00033 // Returns an ordered list of vertices of the outside boundary of the
00034 // face.  All vertices on any holes of the face are \e not included.
00035 // This vertex list is ordered such that a positive normal is
00036 // computing using the Right Hand rule in the direction of the vertex
00037 // list.
00038 
00039 vertex_list *vtol_face::outside_boundary_vertices(void)
00040 {
00041   vertex_list *new_ref_list = new vertex_list;
00042   vcl_vector<vtol_vertex*>* ptr_list = this->outside_boundary_compute_vertices();
00043 
00044   // copy the lists
00045   for (vcl_vector<vtol_vertex*>::const_iterator ti = ptr_list->begin();
00046        ti != ptr_list->end(); ++ti)
00047     new_ref_list->push_back(*ti);
00048 
00049   delete ptr_list;
00050   return new_ref_list;
00051 }
00052 
00053 vcl_vector<vtol_vertex*> *vtol_face::outside_boundary_compute_vertices(void)
00054 {
00055   OUTSIDE_BOUNDARY(vtol_vertex,one_chain,compute_vertices);
00056 }
00057 
00058 //:
00059 // Returns a vtol_vertex list of all the vertices on the face.
00060 // If the face does not have any holes, this vertex list is ordered
00061 // in the direction of a positive normal using the Right Hand rule.
00062 
00063 vcl_vector<vtol_vertex*> *vtol_face::compute_vertices(void)
00064 {
00065   SEL_INF(vtol_vertex,compute_vertices);
00066 }
00067 
00068 //:
00069 // Returns a list of the zero_chains on the outside boundary of the face.
00070 // All zero_chains on any hole boundaries of the face are \e not included.
00071 
00072 vcl_vector<vtol_zero_chain*> *vtol_face::outside_boundary_compute_zero_chains(void)
00073 {
00074   OUTSIDE_BOUNDARY(vtol_zero_chain,one_chain,compute_zero_chains);
00075 }
00076 
00077 
00078 //:
00079 // Returns a list of the zero_chains on the outside boundary of the face.
00080 // All zero_chains on any hole boundaries of the face are \e not included.
00081 
00082 zero_chain_list *vtol_face::outside_boundary_zero_chains(void)
00083 {
00084   zero_chain_list *new_ref_list = new zero_chain_list;
00085   vcl_vector<vtol_zero_chain*>* ptr_list = this->outside_boundary_compute_zero_chains();
00086 
00087   // copy the lists
00088   for (vcl_vector<vtol_zero_chain*>::const_iterator ti = ptr_list->begin();
00089        ti != ptr_list->end(); ++ti)
00090     new_ref_list->push_back(*ti);
00091 
00092   delete ptr_list;
00093   return new_ref_list;
00094 }
00095 
00096 
00097 //: Returns a list of zero_chains of the face.
00098 
00099 vcl_vector<vtol_zero_chain*> *vtol_face::compute_zero_chains(void)
00100 {
00101   SEL_INF(vtol_zero_chain,compute_zero_chains);
00102 }
00103 
00104 //:
00105 // Returns a list of edges that make up the outside boundary of the
00106 // face. All edges on any hole boundaries are \e not included.
00107 
00108 vcl_vector<vtol_edge*> *vtol_face::outside_boundary_compute_edges(void)
00109 {
00110   OUTSIDE_BOUNDARY(vtol_edge,one_chain,compute_edges);
00111 }
00112 
00113 //---------------------------------------------------------------------------
00114 //: Get the outside boundary edges
00115 //---------------------------------------------------------------------------
00116 edge_list *vtol_face::outside_boundary_edges(void)
00117 {
00118   edge_list *new_ref_list = new edge_list;
00119   vcl_vector<vtol_edge*>* ptr_list = this->outside_boundary_compute_edges();
00120 
00121   // copy the lists
00122   for (vcl_vector<vtol_edge*>::const_iterator ti = ptr_list->begin();
00123        ti != ptr_list->end(); ++ti)
00124     new_ref_list->push_back(*ti);
00125 
00126   delete ptr_list;
00127   return new_ref_list;
00128 }
00129 
00130 //: Returns a list of edges on the face.
00131 vcl_vector<vtol_edge*> *vtol_face::compute_edges(void)
00132 {
00133   SEL_INF(vtol_edge,compute_edges);
00134 }
00135 
00136 //: Returns a list of one_chains that make up the outside boundary of the face.
00137 
00138 one_chain_list *vtol_face::outside_boundary_one_chains(void)
00139 {
00140   vcl_vector<vtol_one_chain*>* ptr_list= outside_boundary_compute_one_chains();
00141   one_chain_list *ref_list= new one_chain_list;
00142 
00143   for (vcl_vector<vtol_one_chain*>::const_iterator i=ptr_list->begin();
00144        i!=ptr_list->end(); ++i)
00145     ref_list->push_back(*i);
00146 
00147   delete ptr_list;
00148   return ref_list;
00149 }
00150 
00151 
00152 vcl_vector<vtol_one_chain*> *vtol_face::outside_boundary_compute_one_chains(void)
00153 {
00154   COPY_INF(one_chain);
00155 }
00156 
00157 
00158 //: Returns a list of all Onechains of the face.
00159 
00160 vcl_vector<vtol_one_chain*> *vtol_face::compute_one_chains(void)
00161 {
00162   SEL_INF(vtol_one_chain,compute_one_chains);
00163 }
00164 
00165 //:
00166 // Returns a list of that has itself as the only element.  This method
00167 // is needed for traversing the model hierarchy consistently.
00168 
00169 vcl_vector<vtol_face*>  *vtol_face::compute_faces(void)
00170 {
00171   LIST_SELF(vtol_face);
00172 }
00173 
00174 //: Returns a list of all the two_chains which contain the vtol_face.
00175 vcl_vector<vtol_two_chain*>  *vtol_face::compute_two_chains(void)
00176 {
00177   SEL_SUP(vtol_two_chain,compute_two_chains);
00178 }
00179 
00180 //: Returns a list of all the blocks that contain the vtol_face.
00181 
00182 vcl_vector<vtol_block*> *vtol_face::compute_blocks(void)
00183 {
00184   SEL_SUP(vtol_block,compute_blocks);
00185 }
00186 
00187 //---------------------------------------------------------------------------
00188 //: Does `this' share an edge with `f' ?
00189 //  Comparison of edge pointers, not geometric values
00190 //---------------------------------------------------------------------------
00191 bool vtol_face::shares_edge_with(vtol_face_sptr const& f)
00192 {
00193   edge_list thised; this->edges(thised);
00194   edge_list fedges; f->edges(fedges);
00195   for (edge_list::const_iterator ei1=thised.begin(); ei1!=thised.end(); ++ei1)
00196     for (edge_list::const_iterator ei2=fedges.begin(); ei2!=fedges.end(); ++ei2)
00197       if ((*ei1)==(*ei2)) return true;
00198   return false;
00199 }
00200 
00201 //:
00202 // Links new_vtol_one_chain as an inferior of the vtol_face and returns True if
00203 // successful. This method will be replacing all calls to add_edge_loop().
00204 
00205 void vtol_face::add_one_chain(vtol_one_chain_sptr const& new_vtol_one_chain)
00206 {
00207   // require
00208   assert(new_vtol_one_chain->contains_sub_chains());
00209 
00210   link_inferior(new_vtol_one_chain);
00211 }
00212 
00213 #if 1 // deprecated
00214 void vtol_face::add_one_chain(vtol_one_chain &new_vtol_one_chain)
00215 {
00216   vcl_cerr << "Warning: deprecated form of vtol_face::add_one_chain()\n";
00217   assert(new_vtol_one_chain.contains_sub_chains());
00218 
00219   link_inferior(&new_vtol_one_chain);
00220 }
00221 #endif
00222 
00223 //: deep equality check on faces.  uses fuzzy equal on vertices.
00224 //
00225 
00226 bool vtol_face::operator==(const vtol_face &other) const
00227 {
00228   if (this==&other) return true;
00229 
00230   if (numinf()!=other.numinf())
00231     return false;
00232 
00233   if (!compare_geometry(other))
00234     return false;
00235 
00236   topology_list::const_iterator ti1;
00237   topology_list::const_iterator ti2;
00238 
00239   for (ti1=inferiors()->begin(),ti2=other.inferiors()->begin(); ti1!=inferiors()->end(); ++ti1,++ti2)
00240       if (!(*(*ti1)== *(*ti2)))
00241         return false;
00242 
00243   return true;
00244 }
00245 
00246 //---------------------------------------------------------------------------
00247 //: Spatial object equality
00248 //---------------------------------------------------------------------------
00249 bool vtol_face::operator==(const vsol_spatial_object_2d& obj) const
00250 {
00251   return
00252    obj.cast_to_topology_object() &&
00253    obj.cast_to_topology_object()->cast_to_face() &&
00254    *this == *obj.cast_to_topology_object()->cast_to_face();
00255 }
00256 
00257 //: Returns the ith inferior vtol_one_chain of the vtol_face.
00258 
00259 vtol_one_chain_sptr vtol_face::get_one_chain(int which)
00260 {
00261   assert((unsigned int)which < inferiors()->size());
00262   if ((unsigned int)which < inferiors()->size())
00263     return (inferiors_[which])->cast_to_one_chain();
00264   else
00265   {
00266     vcl_cerr << "Tried to get bad edge_loop from face\n";
00267     return NULL;
00268   }
00269 }
00270 
00271 //: Returns the first inferior vtol_one_chain of the vtol_face (the boundary onechain).
00272 
00273 vtol_one_chain_sptr vtol_face::get_boundary_cycle(void)
00274 {
00275   // The outside boundary vtol_one_chain will *always*
00276   // be the first one chain in the inferiors
00277   // list.
00278   return get_one_chain(0);
00279 }
00280 
00281 //---------------------------------------------------------------------------
00282 //: Adds a new hole to the face
00283 //---------------------------------------------------------------------------
00284 bool vtol_face::add_hole_cycle(vtol_one_chain_sptr new_hole)
00285 {
00286   vtol_one_chain_sptr onech=get_boundary_cycle();
00287 
00288   if (onech)
00289   {
00290     onech->link_chain_inferior(new_hole);
00291     return true;
00292   }
00293   else
00294     return false;
00295 }
00296 
00297 // Returns a list of the one_chains that make up the holes of the vtol_face.
00298 
00299 one_chain_list *vtol_face::get_hole_cycles(void)
00300 {
00301   one_chain_list * result=new one_chain_list;
00302 
00303   topology_list::const_iterator ii;
00304   for (ii=inferiors()->begin();ii!=inferiors()->end();++ii)
00305   {
00306     one_chain_list* templist=(*ii)->cast_to_one_chain()->inferior_one_chains();
00307 
00308     for (one_chain_list::const_iterator oi=templist->begin();oi!=templist->end();++oi)
00309       result->push_back(*oi);
00310     delete templist;
00311   }
00312 
00313   return result;
00314 }
00315 
00316 //: Returns the number of edges on the vtol_face.
00317 //
00318 
00319 int vtol_face::get_num_edges(void) const
00320 {
00321   int result=0;
00322   topology_list::const_iterator ii;
00323   for (ii=inferiors()->begin();ii!=inferiors()->end();++ii)
00324     result+=((*ii)->cast_to_one_chain())->numinf();
00325   return result;
00326 }
00327 
00328 //---------------------------------------------------------------------------
00329 //: Reverse the direction of the face
00330 //---------------------------------------------------------------------------
00331 void vtol_face::reverse_normal(void)
00332 {
00333   topology_list::const_iterator ti;
00334   for (ti=inferiors()->begin();ti!=inferiors()->end();++ti)
00335     (*ti)->cast_to_one_chain()->reverse_directions();
00336   // compute_normal();
00337 }
00338 
00339 //:
00340 //  This method describes the data members of the vtol_face including the
00341 // Inferiors.  The blanking argument is used to indent the output in
00342 // a clear fashion.
00343 
00344 void vtol_face::describe(vcl_ostream &strm,
00345                          int blanking) const
00346 {
00347   for (int j=0; j<blanking; ++j) strm << ' ';
00348   print();
00349   for (unsigned int i=0;i<inferiors()->size();++i)
00350   {
00351     if ((inferiors_[i])->cast_to_one_chain()!=0)
00352       (inferiors_[i])->cast_to_one_chain()->describe(strm,blanking);
00353     else
00354       vcl_cout << "*** Odd inferior for a face\n";
00355   }
00356 }
00357 
00358 //:
00359 // This method prints out a simple text representation for the vtol_face which
00360 // includes its address in memory.
00361 void vtol_face::print(vcl_ostream &strm) const
00362 {
00363   strm << "<vtol_face ";
00364 
00365   topology_list::const_iterator ii;
00366   for (ii=inferiors()->begin();ii!= inferiors()->end();++ii)
00367   {
00368     strm << ' ' << (*ii)->inferiors()->size();
00369   }
00370   strm << "   " << (void const *) this << ">\n";
00371 }
00372 
00373 //-------------------------------------------------------------
00374 //: Update the bounding box, a member of vsol_spatial_object_2d.
00375 //  The algorithm uses the bounding boxes of the vtol_edge(s) forming
00376 //  the boundary of the face.
00377 void vtol_face::compute_bounding_box() const
00378 {
00379   this->empty_bounding_box();
00380   edge_list edges; this->edges(edges);
00381   for (edge_list::iterator eit = edges.begin();eit != edges.end(); ++eit)
00382     this->add_to_bounding_box((*eit)->get_bounding_box());
00383 }
00384 
00385 //: This method determines if a vtol_face is a hole of another vtol_face.
00386 bool vtol_face::IsHoleP() const
00387 {
00388   edge_list* edges = const_cast<vtol_face*>(this)->outside_boundary_edges();
00389   if (edges->size() == 0) { delete edges; return false; }
00390   vtol_edge_sptr e = edges->front();
00391   delete edges;
00392   vcl_list<vtol_topology_object*> const* chains = e->superiors_list();
00393   for (vcl_list<vtol_topology_object*>::const_iterator i=chains->begin(); i!=chains->end(); ++i)
00394     if ((*i)->cast_to_one_chain()->numsup() > 0)
00395       return true;
00396   return false;
00397 }