contrib/brl/bbas/bgrl/bgrl_graph.cxx
Go to the documentation of this file.
00001 // This is brl/bbas/bgrl/bgrl_graph.cxx
00002 #include "bgrl_graph.h"
00003 //:
00004 // \file
00005 #include "bgrl_vertex.h"
00006 #include "bgrl_edge.h"
00007 #include <vbl/io/vbl_io_smart_ptr.h>
00008 #include <vsl/vsl_set_io.h>
00009 #include <vcl_iostream.h>
00010 
00011 //: Constructor
00012 bgrl_graph::bgrl_graph()
00013 {
00014 }
00015 
00016 //: Copy Constructor
00017 // \note this provides a deep copy of the graph
00018 bgrl_graph::bgrl_graph(const bgrl_graph& graph)
00019   : vbl_ref_count()
00020 {
00021   vcl_map<bgrl_vertex_sptr, bgrl_vertex_sptr> old_to_new;
00022 
00023   // copy vertices and outgoing edges
00024   for ( vcl_set<bgrl_vertex_sptr>::const_iterator itr = graph.vertices_.begin();
00025         itr != graph.vertices_.end();  ++itr )
00026   {
00027     bgrl_vertex_sptr vertex_copy((*itr)->clone());
00028     old_to_new[*itr] = vertex_copy;
00029     vertices_.insert(vertex_copy);
00030   }
00031 
00032   // link up new edges to new vertices
00033   for ( vcl_set<bgrl_vertex_sptr>::const_iterator v_itr = vertices_.begin();
00034         v_itr != vertices_.end();  ++v_itr )
00035   {
00036     for ( vcl_set<bgrl_edge_sptr>::const_iterator e_itr = (*v_itr)->out_edges_.begin();
00037           e_itr != (*v_itr)->out_edges_.end();  ++e_itr )
00038     {
00039       vcl_map<bgrl_vertex_sptr, bgrl_vertex_sptr>::iterator find_new = old_to_new.find((*e_itr)->to_);
00040       if ( find_new != old_to_new.end() ){
00041         (*e_itr)->to_ = find_new->second.ptr();
00042         find_new->second->in_edges_.insert(*e_itr);
00043       }
00044       else
00045         vcl_cerr << "Error copying graph: vertex not found in graph\n";
00046     }
00047   }
00048 }
00049 
00050 
00051 //: Adds a new vertex to the graph
00052 bool
00053 bgrl_graph::add_vertex(const bgrl_vertex_sptr& vertex)
00054 {
00055   if (!vertex) return false;
00056 
00057   return vertices_.insert(vertex).second;
00058 }
00059 
00060 
00061 //: Deletes a vertex in the graph
00062 bool
00063 bgrl_graph::remove_vertex(const bgrl_vertex_sptr& vertex)
00064 {
00065   if (!vertex) return false;
00066 
00067   if (vertices_.erase(vertex) == 0) return false;
00068 
00069   vertex->strip();
00070 
00071   return true;
00072 }
00073 
00074 
00075 //: Add an edge between \p v1 and \p v2
00076 bgrl_edge_sptr
00077 bgrl_graph::add_edge( const bgrl_vertex_sptr& v1,
00078                       const bgrl_vertex_sptr& v2,
00079                       const bgrl_edge_sptr& model_edge )
00080 {
00081   if (!v1 || !v2)
00082     return 0;
00083   if ( vertices_.count(v1) == 0 && !this->add_vertex(v1) )
00084     return 0;
00085   if ( vertices_.count(v2) == 0 && !this->add_vertex(v2) )
00086     return 0;
00087 
00088   return v1->add_edge_to(v2, model_edge);
00089 }
00090 
00091 
00092 //: Remove an edge between \p v1 and \p v2
00093 bool
00094 bgrl_graph::remove_edge( const bgrl_vertex_sptr& v1, const bgrl_vertex_sptr& v2 )
00095 {
00096   if (!v1 || !v2) return false;
00097 
00098   return v1->remove_edge_to(v2);
00099 }
00100 
00101 //: Remove all edges to NULL vertices and vertex not found in this graph
00102 bool
00103 bgrl_graph::purge()
00104 {
00105   bool retval = false;
00106 
00107   for ( vertex_iterator v_itr = vertices_.begin();
00108         v_itr != vertices_.end(); ++v_itr )
00109   {
00110     bgrl_vertex_sptr curr_vertex = *v_itr;
00111     // remove the NULL edges
00112     retval = curr_vertex->purge() || retval;
00113     // remove edges to vertices not in this graph
00114     for ( edge_iterator e_itr = curr_vertex->out_edges_.begin();
00115           e_itr != curr_vertex->out_edges_.end(); ++e_itr )
00116     {
00117       if (vertices_.find((*e_itr)->to_) == vertices_.end()) {
00118         curr_vertex->remove_edge_to((*e_itr)->to_);
00119         retval = true;
00120       }
00121     }
00122     // remove edges from vertices not in this graph
00123     for ( edge_iterator e_itr = curr_vertex->in_edges_.begin();
00124           e_itr != curr_vertex->in_edges_.end(); ++e_itr )
00125     {
00126       if (vertices_.find((*e_itr)->from_) == vertices_.end()) {
00127         (*e_itr)->from_->remove_edge_to(curr_vertex);
00128         retval = true;
00129       }
00130     }
00131   }
00132   return retval;
00133 }
00134 
00135 
00136 //: Returns the number of vertices in the graph;
00137 int
00138 bgrl_graph::size() const
00139 {
00140   return vertices_.size();
00141 }
00142 
00143 
00144 //: Return a platform independent string identifying the class
00145 vcl_string
00146 bgrl_graph::is_a() const
00147 {
00148   return "bgrl_graph";
00149 }
00150 
00151 
00152 //: Create a copy of the object on the heap.
00153 // The caller is responsible for deletion
00154 bgrl_graph*
00155 bgrl_graph::clone() const
00156 {
00157   return new bgrl_graph(*this);
00158 }
00159 
00160 
00161 //: Binary save self to stream.
00162 void
00163 bgrl_graph::b_write( vsl_b_ostream& os ) const
00164 {
00165   vsl_b_write(os, version());
00166 
00167   // write the vertices
00168   vsl_b_write(os, vertices_);
00169 }
00170 
00171 
00172 //: Binary load self from stream.
00173 void
00174 bgrl_graph::b_read( vsl_b_istream& is )
00175 {
00176   if (!is) return;
00177 
00178   short ver;
00179   vsl_b_read(is, ver);
00180   switch (ver)
00181   {
00182    case 1:
00183     vsl_b_read(is, vertices_);
00184 
00185     if (this->purge())
00186       vcl_cerr << "I/O WARNING: bgrl_graph::b_read(vsl_b_istream&)\n"
00187                << "             It is likely that the graph object is corrupt.\n"
00188                << "             Invalid edges have been purged.\n";
00189     break;
00190 
00191    default:
00192     vcl_cerr << "I/O ERROR: bgrl_graph::b_read(vsl_b_istream&)\n"
00193              << "           Unknown version number "<< ver << '\n';
00194     is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00195     return;
00196   }
00197 }
00198 
00199 
00200 //: Print an ascii summary to the stream
00201 void
00202 bgrl_graph::print_summary( vcl_ostream& os ) const
00203 {
00204   os << this->size() << " vertices";
00205 }
00206 
00207 
00208 //: Return IO version number;
00209 short
00210 bgrl_graph::version(  ) const
00211 {
00212   return 1;
00213 }
00214 
00215 
00216 //-----------------------------------------------------------------------------------------
00217 // Iterator functions
00218 //-----------------------------------------------------------------------------------------
00219 
00220 //: Constructor
00221 bgrl_graph::iterator::iterator( bgrl_graph* graph, bgrl_search_func_sptr func )
00222  : graph_(graph), search_func_(func),
00223    use_internal_(false), internal_(graph->vertices_.begin())
00224 {
00225   if (!func)
00226     use_internal_ = true;
00227 }
00228 
00229 
00230 //: Constructor - for end iterator
00231 bgrl_graph::iterator::iterator( bgrl_graph* graph )
00232  : graph_(graph),  search_func_(NULL),
00233    use_internal_(true), internal_(graph->vertices_.end())
00234 {
00235 }
00236 
00237 
00238 //: Pre-Increment
00239 bgrl_graph::iterator&
00240 bgrl_graph::iterator::operator++ ()
00241 {
00242   if (use_internal_)
00243     ++internal_;
00244   else
00245     search_func_->next_vertex();
00246 
00247   return *this;
00248 }
00249 
00250 //: Post-Increment
00251 bgrl_graph::iterator
00252 bgrl_graph::iterator::operator++ (int)
00253 {
00254   iterator old(*this);
00255   ++(*this);
00256   return old;
00257 }
00258 
00259 
00260 //: Dereference
00261 bgrl_vertex_sptr
00262 bgrl_graph::iterator::operator -> () const
00263 {
00264   return *(*this);
00265 }
00266 
00267 
00268 //: Dereference
00269 bgrl_vertex_sptr
00270 bgrl_graph::iterator::operator * () const
00271 {
00272   if (use_internal_)
00273     if (internal_ == this->graph_->vertices_.end())
00274       return NULL;
00275     else
00276       return *internal_;
00277   else
00278     return search_func_->curr_vertex();
00279 }
00280 
00281 
00282 //: Equality comparison
00283 bool
00284 bgrl_graph::iterator::operator == (const iterator& rhs) const
00285 {
00286   return *rhs == *(*this);
00287 }
00288 
00289 //: Inequality comparison
00290 bool
00291 bgrl_graph::iterator::operator != (const iterator& rhs) const
00292 {
00293   return !(rhs == *this);
00294 }
00295 
00296 
00297 //-----------------------------------------------------------------------------------------
00298 // External functions
00299 //-----------------------------------------------------------------------------------------
00300 
00301 
00302 //: Binary save bgrl_graph to stream.
00303 void
00304 vsl_b_write(vsl_b_ostream &os, const bgrl_graph* g)
00305 {
00306   if (!g) {
00307     vsl_b_write(os, false); // Indicate null pointer stored
00308   }
00309   else {
00310     vsl_b_write(os,true); // Indicate non-null pointer stored
00311     g->b_write(os);
00312   }
00313 }
00314 
00315 
00316 //: Binary load bgrl_graph from stream.
00317 void
00318 vsl_b_read(vsl_b_istream &is, bgrl_graph* &g)
00319 {
00320   delete g;
00321   bool not_null_ptr;
00322   vsl_b_read(is, not_null_ptr);
00323   if (not_null_ptr) {
00324     g = new bgrl_graph();
00325     g->b_read(is);
00326   }
00327   else
00328     g = 0;
00329 }
00330 
00331 
00332 //: Print an ASCII summary to the stream
00333 void
00334 vsl_print_summary(vcl_ostream &os, const bgrl_graph* g)
00335 {
00336   os << "bgrl_graph{";
00337   g->print_summary(os);
00338   os << '}';
00339 }
00340