contrib/gel/vtol/vtol_one_chain.cxx
Go to the documentation of this file.
00001 // This is gel/vtol/vtol_one_chain.cxx
00002 #include "vtol_one_chain.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_cassert.h>
00007 #include <vcl_algorithm.h>
00008 #include <vtol/vtol_edge.h>
00009 #include <vtol/vtol_edge_2d.h>
00010 #include <vtol/vtol_macros.h>
00011 #include <vtol/vtol_list_functions.h>
00012 
00013 vtol_edge_sptr vtol_one_chain::edge(int i) const
00014 {
00015   assert (i>=0);
00016   assert (i<numinf());
00017   return inferiors_[i]->cast_to_edge();
00018 }
00019 
00020 //***************************************************************************
00021 // Initialization
00022 //***************************************************************************
00023 
00024 void vtol_one_chain::link_inferior(vtol_edge_sptr inf)
00025 {
00026   vtol_topology_object::link_inferior(inf->cast_to_topology_object());
00027 }
00028 
00029 void vtol_one_chain::unlink_inferior(vtol_edge_sptr inf)
00030 {
00031   vtol_topology_object::unlink_inferior(inf->cast_to_topology_object());
00032 }
00033 
00034 void vtol_one_chain::link_chain_inferior(vtol_one_chain_sptr chain_inferior)
00035 {
00036   vtol_chain::link_chain_inferior(chain_inferior->cast_to_chain());
00037 }
00038 
00039 void vtol_one_chain::unlink_chain_inferior(vtol_one_chain_sptr chain_inferior)
00040 {
00041   vtol_chain::unlink_chain_inferior(chain_inferior->cast_to_chain());
00042 }
00043 
00044 //---------------------------------------------------------------------------
00045 //: Constructor from an array of edges
00046 //---------------------------------------------------------------------------
00047 vtol_one_chain::vtol_one_chain(edge_list const& edgs,
00048                                bool new_is_cycle)
00049 {
00050   set_cycle(new_is_cycle);
00051 
00052   for (edge_list::const_iterator i=edgs.begin(); i!=edgs.end(); ++i)
00053   {
00054     link_inferior(*i);
00055     directions_.push_back((signed char)1);
00056   }
00057 
00058   if (is_cycle())
00059     determine_edge_directions();
00060 }
00061 
00062 //---------------------------------------------------------------------------
00063 //: Constructor from an array of edges and an array of directions
00064 //---------------------------------------------------------------------------
00065 vtol_one_chain::vtol_one_chain(edge_list const& edgs,
00066                                vcl_vector<signed char> const& dirs,
00067                                bool new_is_cycle)
00068 {
00069   set_cycle(new_is_cycle);
00070 
00071   for (edge_list::const_iterator i=edgs.begin(); i!=edgs.end(); ++i)
00072     link_inferior(*i);
00073 
00074   for (vcl_vector<signed char>::const_iterator j=dirs.begin();j!=dirs.end();++j)
00075     directions_.push_back(*j);
00076 }
00077 
00078 //---------------------------------------------------------------------------
00079 //: Pseudo copy constructor.  Deep copy.
00080 //---------------------------------------------------------------------------
00081 vtol_one_chain::vtol_one_chain(vtol_one_chain_sptr const& other)
00082 {
00083   vertex_list verts; other->vertices(verts);
00084   topology_list newverts(verts.size());
00085 
00086   int i=0;
00087   for (vertex_list::iterator v=verts.begin();v!=verts.end();++v,++i)
00088   {
00089     vtol_vertex_sptr ve=*v;
00090     newverts[i]=ve->clone()->cast_to_topology_object();
00091     ve->set_id(i);
00092   }
00093 
00094   vcl_vector<signed char>::iterator dir=other->directions_.begin();
00095   topology_list::iterator inf=other->inferiors()->begin();
00096   for (; dir!=other->directions_.end(); ++dir,++inf)
00097   {
00098     vtol_edge_sptr e=(*inf)->cast_to_edge();
00099     vtol_edge_sptr newedge = newverts[e->v1()->get_id()]->cast_to_vertex()->new_edge(
00100                              newverts[e->v2()->get_id()]->cast_to_vertex());
00101     link_inferior(newedge);
00102     directions_.push_back(*dir);
00103   }
00104   set_cycle(other->is_cycle());
00105   const chain_list *hierarchy_infs=other->chain_inferiors();
00106 
00107   for (chain_list::const_iterator h=hierarchy_infs->begin();h!=hierarchy_infs->end();++h)
00108     link_chain_inferior((*h)->clone()->cast_to_topology_object()->cast_to_one_chain());
00109 }
00110 
00111 //---------------------------------------------------------------------------
00112 // Destructor
00113 //---------------------------------------------------------------------------
00114 vtol_one_chain::~vtol_one_chain()
00115 {
00116   unlink_all_chain_inferiors();
00117   unlink_all_inferiors();
00118 }
00119 
00120 //---------------------------------------------------------------------------
00121 //: Clone `this': creation of a new object and initialization.
00122 // See Prototype pattern
00123 //---------------------------------------------------------------------------
00124 vsol_spatial_object_2d* vtol_one_chain::clone() const
00125 {
00126   return new vtol_one_chain(vtol_one_chain_sptr(const_cast<vtol_one_chain*>(this)));
00127 }
00128 
00129 vtol_one_chain *
00130 vtol_one_chain::copy_with_arrays(topology_list &verts,
00131                                  topology_list &edges) const
00132 {
00133   vtol_one_chain *result=new vtol_one_chain();
00134 
00135   vcl_vector<signed char>::const_iterator di=directions_.begin();
00136   topology_list::const_iterator ti=inferiors()->begin();
00137   for (; ti!=inferiors()->end(); ++ti,++di)
00138   {
00139     vtol_edge *e=(*ti)->cast_to_edge();
00140     vtol_edge *newedge=edges[e->get_id()]->cast_to_edge();
00141 
00142     assert(*e == *newedge);
00143 
00144     result->link_inferior(newedge);
00145     result->directions_.push_back((*di));
00146   }
00147   result->set_cycle(is_cycle());
00148   const chain_list *hierarchy_infs=chain_inferiors();
00149 
00150   for (chain_list::const_iterator hi=hierarchy_infs->begin();hi!=hierarchy_infs->end();++hi)
00151   {
00152     vtol_one_chain_sptr tch = (*hi)->cast_to_one_chain();
00153     int n = tch->num_edges();
00154     vsol_spatial_object_2d_sptr so = (*hi)->clone();
00155     vtol_one_chain *temp = so->cast_to_topology_object()->cast_to_one_chain();
00156     // we have to set the ids here because the clone operation does not
00157     // copy the id field on vsol_spatial_object_2d
00158     for (int i=0; i<n; ++i)
00159     {
00160       vtol_edge_sptr e = temp->edge(i);
00161       e->set_id(tch->edge(i)->get_id());
00162     }
00163     result->link_chain_inferior(temp->copy_with_arrays(verts,edges));
00164   }
00165 
00166   assert(*result == *this);
00167 
00168   return result;
00169 }
00170 
00171 // ***********************************
00172 //         Accessors
00173 //
00174 // **********************************
00175 
00176 //: Get the direction of the edge "e" in the onechain.
00177 signed char vtol_one_chain::direction(vtol_edge const &e) const
00178 {
00179   vcl_vector<signed char>::const_iterator dit=directions_.begin();
00180   topology_list::const_iterator toit;
00181   for (toit=inferiors()->begin();toit!=inferiors()->end();++toit)
00182   {
00183     vtol_edge *ce=(*toit)->cast_to_edge();
00184     if (ce==&e)
00185       return *dit;
00186     ++dit;
00187   }
00188   return (signed char)1;
00189 }
00190 
00191 //---------------------------------------------------------------------------
00192 //: Get the outside boundary vertices
00193 //---------------------------------------------------------------------------
00194 vcl_vector<vtol_vertex*> *
00195 vtol_one_chain::outside_boundary_compute_vertices()
00196 {
00197   vcl_vector<vtol_vertex*> *result=new vcl_vector<vtol_vertex*>;
00198 
00199   topology_list::iterator inf=inferiors()->begin();
00200   vcl_vector<signed char>::iterator dir=directions_.begin();
00201   for (; inf!=inferiors()->end(); ++inf,++dir)
00202   {
00203     vtol_edge_sptr e=(*inf)->cast_to_edge();
00204     if ((*dir)< 0)
00205     {
00206       result->push_back(e->v2()->cast_to_vertex());
00207       result->push_back(e->v1()->cast_to_vertex());
00208     }
00209     else
00210     {
00211       result->push_back(e->v1()->cast_to_vertex());
00212       result->push_back(e->v2()->cast_to_vertex());
00213     }
00214   }
00215   return tagged_union(result);
00216 }
00217 
00218 //---------------------------------------------------------------------------
00219 //: Get the outside boundary vertices
00220 //---------------------------------------------------------------------------
00221 vertex_list *vtol_one_chain::outside_boundary_vertices()
00222 {
00223   vcl_vector<vtol_vertex*> *tmp_list=outside_boundary_compute_vertices();
00224   vertex_list *result=new vertex_list;
00225   result->reserve(tmp_list->size());
00226   vcl_vector<vtol_vertex*>::iterator i;
00227   for (i=tmp_list->begin();i!=tmp_list->end();++i)
00228     result->push_back(*i);
00229   delete tmp_list;
00230   return result;
00231 }
00232 
00233 //---------------------------------------------------------------------------
00234 //: Get the vertices of this object
00235 //---------------------------------------------------------------------------
00236 vcl_vector<vtol_vertex*> *vtol_one_chain::compute_vertices()
00237 {
00238   // We must collect vertices from subchains as well as
00239   // from direct Inferiors...so this function only has
00240   // an ordering if there are no subchains.
00241 
00242   vcl_vector<vtol_vertex*> *verts=outside_boundary_compute_vertices();
00243 
00244   // This macro adds the subchain vertices to the verts list.
00245 
00246   SUBCHAIN_INF(verts,one_chain,vtol_vertex,compute_vertices);
00247 }
00248 
00249 
00250 //---------------------------------------------------------------------------
00251 //: Get the outside boundary zero chains
00252 //---------------------------------------------------------------------------
00253 vcl_vector<vtol_zero_chain *> *
00254 vtol_one_chain::outside_boundary_compute_zero_chains()
00255 {
00256   SEL_INF(vtol_zero_chain,compute_zero_chains);
00257 }
00258 
00259 //---------------------------------------------------------------------------
00260 //: Get the outside boundary zero chains
00261 //---------------------------------------------------------------------------
00262 zero_chain_list *vtol_one_chain::outside_boundary_zero_chains()
00263 {
00264   zero_chain_list *result=new zero_chain_list;
00265   vcl_vector<vtol_zero_chain *> *ptr_list=outside_boundary_compute_zero_chains();
00266 
00267   // copy the lists
00268   vcl_vector<vtol_zero_chain *>::iterator i;
00269   for (i=ptr_list->begin();i!=ptr_list->end();++i)
00270     if ((*i)->v0()) // PVr- added this condition so no empty chains are returned
00271       result->push_back(*i);
00272   delete ptr_list;
00273 
00274   return result;
00275 }
00276 
00277 
00278 //---------------------------------------------------------------------------
00279 //: Get the zero chains of this object
00280 //---------------------------------------------------------------------------
00281 vcl_vector<vtol_zero_chain*> *vtol_one_chain::compute_zero_chains()
00282 {
00283   vcl_vector<vtol_zero_chain*> *zchs;
00284   zchs=outside_boundary_compute_zero_chains();
00285 
00286   // This macro adds the subchain zerochains to the zchs list.
00287 
00288   SUBCHAIN_INF(zchs,one_chain,vtol_zero_chain,compute_zero_chains);
00289 }
00290 
00291 //---------------------------------------------------------------------------
00292 //: Get the outside boundary edges
00293 //---------------------------------------------------------------------------
00294 vcl_vector<vtol_edge*> *vtol_one_chain::outside_boundary_compute_edges()
00295 {
00296   COPY_INF(edge);
00297 }
00298 
00299 
00300 //---------------------------------------------------------------------------
00301 //: Get the outside boundary edges
00302 //---------------------------------------------------------------------------
00303 edge_list *vtol_one_chain::outside_boundary_edges()
00304 {
00305   edge_list *new_ref_list = new edge_list;
00306   vcl_vector<vtol_edge*>* ptr_list = this->outside_boundary_compute_edges();
00307   // copy the lists
00308 
00309   for (vcl_vector<vtol_edge*>::iterator ti = ptr_list->begin(); ti != ptr_list->end(); ++ti)
00310     new_ref_list->push_back(*ti);
00311 
00312   delete ptr_list;
00313   return new_ref_list;
00314 }
00315 
00316 //---------------------------------------------------------------------------
00317 //: Get the edges
00318 //---------------------------------------------------------------------------
00319 vcl_vector<vtol_edge*> *vtol_one_chain::compute_edges()
00320 {
00321   vcl_vector<vtol_edge*> *edges;
00322   edges=outside_boundary_compute_edges();
00323 
00324   // This macro adds the subchain zerochains to the zchs list.
00325 
00326   SUBCHAIN_INF(edges,one_chain,vtol_edge,compute_edges);
00327 }
00328 
00329 //---------------------------------------------------------------------------
00330 //: Get the one chains
00331 //---------------------------------------------------------------------------
00332 vcl_vector<vtol_one_chain*> *vtol_one_chain::compute_one_chains()
00333 {
00334   vcl_vector<vtol_one_chain*> *result=outside_boundary_compute_one_chains();
00335 
00336   for (chain_list::iterator i=chain_inferiors_.begin();
00337        i!=chain_inferiors_.end();++i)
00338   {
00339     vsol_spatial_object_2d_sptr so = (*i)->clone();
00340     //==============================================================
00341     //compensate for leaving scope.  The clone method returns a smart
00342     //pointer, but the output in this method is a bare pointer.  Thus
00343     //so will be deleted when the routine leaves scope.  The calling
00344     //routine for compute_one_chains will push these one_chains on a list
00345     //of smart pointers so there should be no leak.  This routine never
00346     //worked -- JLM
00347     so->ref();
00348     //===============================================================
00349     vtol_one_chain* sub_chain = so->cast_to_topology_object()->
00350       cast_to_one_chain();
00351     result->push_back(sub_chain);
00352   }
00353   return result;
00354 }
00355 
00356 //---------------------------------------------------------------------------
00357 //: Get the inferior one chains
00358 //---------------------------------------------------------------------------
00359 one_chain_list *vtol_one_chain::inferior_one_chains()
00360 {
00361   one_chain_list *result=new one_chain_list;
00362 
00363   for (chain_list::iterator i=chain_inferiors_.begin();i!=chain_inferiors_.end();++i)
00364     result->push_back((*i)->clone()->cast_to_topology_object()->cast_to_one_chain());
00365 
00366   return result;
00367 }
00368 
00369 //---------------------------------------------------------------------------
00370 //: Get the superior one chains
00371 //---------------------------------------------------------------------------
00372 one_chain_list *vtol_one_chain::superior_one_chains()
00373 {
00374   one_chain_list *result=new one_chain_list;
00375 
00376   vcl_list<vtol_chain*>::iterator i;
00377   for (i=chain_superiors_.begin();i!=chain_superiors_.end();++i)
00378     result->push_back((*i)->clone()->cast_to_topology_object()->cast_to_one_chain());
00379 
00380   return result;
00381 }
00382 
00383 //---------------------------------------------------------------------------
00384 //: Get the outside boundary one chains
00385 //---------------------------------------------------------------------------
00386 one_chain_list *vtol_one_chain::outside_boundary_one_chains()
00387 {
00388   vcl_vector<vtol_one_chain*>* ptr_list= outside_boundary_compute_one_chains();
00389   one_chain_list *ref_list= new one_chain_list;
00390 
00391   vcl_vector<vtol_one_chain*>::iterator i;
00392   for (i=ptr_list->begin();i!=ptr_list->end();++i)
00393   {
00394     ref_list->push_back(*i);
00395   }
00396   delete ptr_list;
00397   return ref_list;
00398 }
00399 
00400 
00401 //---------------------------------------------------------------------------
00402 //: Get the outside boundary one chains
00403 //---------------------------------------------------------------------------
00404 vcl_vector<vtol_one_chain*> *vtol_one_chain::outside_boundary_compute_one_chains()
00405 {
00406   LIST_SELF(vtol_one_chain);
00407 }
00408 
00409 //---------------------------------------------------------------------------
00410 //: Get the faces
00411 //---------------------------------------------------------------------------
00412 vcl_vector<vtol_face*> *vtol_one_chain::compute_faces()
00413 {
00414   if (is_sub_chain())
00415   {
00416     vcl_vector<vtol_face*> *result=new vcl_vector<vtol_face*>();
00417     one_chain_list *onech=superior_one_chains();
00418 
00419     for (one_chain_list::iterator i=onech->begin();i!=onech->end();++i)
00420     {
00421       vcl_vector<vtol_face*> *sublist=(*i)->compute_faces();
00422       vcl_vector<vtol_face*>::iterator ii;
00423       for (ii=sublist->begin();ii!=sublist->end();++ii)
00424         result->push_back(*ii);
00425       delete sublist;
00426     }
00427     delete onech;
00428     return tagged_union(result);
00429   }
00430   else
00431   {
00432     SEL_SUP(vtol_face, compute_faces);
00433   }
00434 }
00435 
00436 //---------------------------------------------------------------------------
00437 //: Get the two chains
00438 //---------------------------------------------------------------------------
00439 vcl_vector<vtol_two_chain*> *vtol_one_chain::compute_two_chains()
00440 {
00441   if (is_sub_chain())
00442   {
00443     vcl_vector<vtol_two_chain*> *result=new vcl_vector<vtol_two_chain*>;
00444     one_chain_list *onech=superior_one_chains();
00445 
00446     for (one_chain_list::iterator i=onech->begin();i!=onech->end();++i)
00447     {
00448       vcl_vector<vtol_two_chain*> *sublist=(*i)->compute_two_chains();
00449       vcl_vector<vtol_two_chain*>::iterator ii;
00450       for (ii=sublist->begin();ii!=sublist->end();++ii)
00451         result->push_back(*ii);
00452       delete sublist;
00453     }
00454     delete onech;
00455     return tagged_union(result);
00456   }
00457   else
00458   {
00459     SEL_SUP(vtol_two_chain, compute_two_chains);
00460   }
00461 }
00462 
00463 //---------------------------------------------------------------------------
00464 //: Get the blocks
00465 //---------------------------------------------------------------------------
00466 vcl_vector<vtol_block*> *vtol_one_chain::compute_blocks()
00467 {
00468   if (is_sub_chain())
00469   {
00470     vcl_vector<vtol_block*> *result=new vcl_vector<vtol_block*>;
00471     one_chain_list *onech=superior_one_chains();
00472     for (one_chain_list::iterator i=onech->begin();i!=onech->end();++i)
00473     {
00474       vcl_vector<vtol_block*> *sublist=(*i)->compute_blocks();
00475       vcl_vector<vtol_block*>::iterator ii;
00476       for (ii=sublist->begin();ii!=sublist->end();++ii)
00477         result->push_back(*ii);
00478       delete sublist;
00479     }
00480     delete onech;
00481     return tagged_union(result);
00482   }
00483   else
00484   {
00485     SEL_SUP(vtol_block, compute_blocks);
00486   }
00487 }
00488 
00489 //---------------------------------------------------------------------------
00490 //: Computes the bounding box of a vtol_one_chain from the edges.
00491 //  Just get the bounding box for each edge and update this's box accordingly.
00492 //  Note that the computation is done independently of dimension.
00493 //---------------------------------------------------------------------------
00494 
00495 void vtol_one_chain::compute_bounding_box() const
00496 {
00497   // we need to clear the bounds of the box to correctly reflect edge bounds
00498   this->empty_bounding_box();
00499 
00500   edge_list edgs; this->edges(edgs);
00501   for (edge_list::iterator eit = edgs.begin(); eit != edgs.end(); eit++)
00502   {
00503     if (!(*eit)->get_bounding_box())
00504     {
00505       vcl_cout << "In vtol_one_chain::compute_bounding_box() -"
00506                << " edge has null bounding box\n";
00507       continue;
00508     }
00509     this->add_to_bounding_box((*eit)->get_bounding_box());
00510   }
00511 }
00512 
00513 //---------------------------------------------------------------------------
00514 //: Redetermining the directions of all edges in the onechain.
00515 // Require: is_cycle()
00516 //---------------------------------------------------------------------------
00517 void vtol_one_chain::determine_edge_directions()
00518 {
00519   // require
00520   assert(is_cycle());
00521 
00522   int num_edges;
00523   vtol_edge_sptr first_edge;
00524   vtol_edge_sptr second_edge;
00525   vtol_vertex_sptr tweeney;
00526 
00527   // Clear out any old info...
00528   directions_.clear();
00529   num_edges=numinf();
00530   if (num_edges>=2)
00531   {
00532     // Determining the cycle direction
00533     // with reference to the first edge.
00534 
00535     topology_list::iterator i=inferiors()->begin();
00536     first_edge=(*i)->cast_to_edge();
00537     ++i;
00538 
00539     second_edge=(*i)->cast_to_edge();
00540 
00541     if (second_edge->is_endpoint1(first_edge->v1()))
00542     {
00543       directions_.push_back((signed char)(-1));
00544       tweeney=second_edge->v2();
00545       directions_.push_back((signed char)1);
00546     }
00547     else if (second_edge->is_endpoint2(first_edge->v1()))
00548     {
00549       directions_.push_back((signed char)(-1));
00550       directions_.push_back((signed char)(-1));
00551       tweeney=second_edge->v1();
00552     }
00553     else
00554     {
00555       directions_.push_back((signed char)1);
00556       if (second_edge->is_endpoint1(first_edge->v2()))
00557       {
00558         tweeney=second_edge->v2();
00559         directions_.push_back((signed char)1);
00560       }
00561       else
00562       {
00563         tweeney=second_edge->v1();
00564         directions_.push_back((signed char)(-1));
00565       }
00566     }
00567     if (num_edges>2)
00568     {
00569       vtol_edge *cur_edge;
00570       ++i;
00571       while (i!=inferiors()->end())
00572       {
00573         cur_edge=(*i)->cast_to_edge();
00574         if (cur_edge->is_endpoint1(tweeney))
00575         {
00576           tweeney=cur_edge->v2();
00577           directions_.push_back((signed char)1);
00578         }
00579         else
00580         {
00581           tweeney=cur_edge->v1();
00582           directions_.push_back((signed char)(-1));
00583         }
00584         ++i;
00585       }
00586     }
00587   }
00588   else if (num_edges==1)
00589     directions_.push_back((signed char)1);
00590 }
00591 
00592 //---------------------------------------------------------------------------
00593 //: Add an edge
00594 //---------------------------------------------------------------------------
00595 void vtol_one_chain::add_edge(vtol_edge_sptr const& new_edge,
00596                               bool dir)
00597 {
00598   if (dir)
00599     directions_.push_back((signed char)1);
00600   else
00601     directions_.push_back((signed char)(-1));
00602   link_inferior(new_edge);
00603 }
00604 
00605 void vtol_one_chain::add_edge(vtol_edge_2d_sptr const& new_edge,
00606                               bool dir)
00607 {
00608   if (dir)
00609     directions_.push_back((signed char)1);
00610   else
00611     directions_.push_back((signed char)(-1));
00612   link_inferior(new_edge->cast_to_edge());
00613 }
00614 
00615 #if 1 // deprecated
00616 void vtol_one_chain::add_edge(vtol_edge &new_edge,
00617                               bool dir)
00618 {
00619   vcl_cerr << "Warning: deprecated form of vtol_one_chain::add_edge()\n";
00620   if (dir)
00621     directions_.push_back((signed char)1);
00622   else
00623     directions_.push_back((signed char)(-1));
00624   link_inferior(&new_edge);
00625 }
00626 #endif // 1
00627 
00628 //---------------------------------------------------------------------------
00629 //: Remove an edge
00630 //---------------------------------------------------------------------------
00631 void vtol_one_chain::remove_edge(vtol_edge_sptr const& doomed_edge,
00632                                  bool force_it)
00633 {
00634   // require
00635   assert(force_it||!is_cycle());
00636 
00637   vtol_topology_object_sptr t=doomed_edge->cast_to_topology_object();
00638   topology_list::const_iterator i=vcl_find(inferiors()->begin(),inferiors()->end(),t);
00639   topology_list::difference_type index=i-inferiors()->begin();
00640 
00641   if (index>=0 && i!= inferiors()->end())
00642   {
00643     vcl_vector<signed char>::iterator j = directions_.begin() + index;
00644     directions_.erase(j);// get rid of the direction associated with the edge
00645     touch();
00646     unlink_inferior(doomed_edge);
00647   }
00648 }
00649 
00650 void vtol_one_chain::remove_edge(vtol_edge_2d_sptr const& doomed_edge,
00651                                  bool force_it)
00652 {
00653   // require
00654   assert(force_it||!is_cycle());
00655 
00656   vtol_topology_object_sptr t=doomed_edge->cast_to_topology_object();
00657   topology_list::const_iterator i=vcl_find(inferiors()->begin(),inferiors()->end(),t);
00658   topology_list::difference_type index=i-inferiors()->begin();
00659 
00660   if (index>=0 && i!= inferiors()->end())
00661   {
00662     vcl_vector<signed char>::iterator j = directions_.begin() + index;
00663     directions_.erase(j);// get rid of the direction associated with the edge
00664     touch();
00665     unlink_inferior(doomed_edge->cast_to_edge());
00666   }
00667 }
00668 
00669 #if 1 // deprecated
00670 void vtol_one_chain::remove_edge(vtol_edge &doomed_edge,
00671                                  bool force_it)
00672 {
00673   vcl_cerr << "Warning: deprecated form of vtol_one_chain::remove_edge()\n";
00674   assert(force_it||!is_cycle());
00675 
00676   vtol_topology_object_sptr t=&doomed_edge;
00677   topology_list::const_iterator i=vcl_find(inferiors()->begin(),inferiors()->end(),t);
00678   topology_list::difference_type index=i-inferiors()->begin();
00679 
00680   if (index>=0 && i!= inferiors()->end())
00681   {
00682     vcl_vector<signed char>::iterator j = directions_.begin() + index;
00683     directions_.erase(j);// get rid of the direction associated with the edge
00684     touch();
00685     unlink_inferior(&doomed_edge);
00686   }
00687 }
00688 #endif // 1
00689 
00690 //---------------------------------------------------------------------------
00691 //: Comparison operator
00692 //---------------------------------------------------------------------------
00693 bool vtol_one_chain::operator==(vtol_one_chain const &other) const
00694 {
00695   if (this==&other) return true;
00696 
00697   // Check to see if the number of edges is the same
00698   if (numinf()!=other.numinf())
00699     return false;
00700 
00701   const topology_list *inf1=inferiors();
00702   const topology_list *inf2=other.inferiors();
00703 
00704   topology_list::const_iterator i1;
00705   topology_list::const_iterator i2;
00706   for (i1=inf1->begin() , i2 = inf2->begin(); i1 != inf1->end(); ++i1 , ++i2)
00707   {
00708     if (!( *(*i1) == *(*i2) ))
00709       return false;
00710 
00711     // Comparing the directions_
00712     const vcl_vector<signed char> *dir1=directions();
00713     const vcl_vector<signed char> *dir2=other.directions();
00714 
00715     if ((dir1->size()!=dir2->size())||(is_cycle()!=other.is_cycle()))
00716       return false;
00717 
00718     vcl_vector<signed char>::const_iterator d1;
00719     vcl_vector<signed char>::const_iterator d2;
00720     for (d1=dir1->begin(), d2=dir2->begin(); d1 != dir1->end(); ++d1, ++d2)
00721       if (!(*d1 == *d2))
00722     return false;
00723 
00724     // compare onechains that make up any holes
00725     const chain_list &righth=chain_inferiors_;
00726     const chain_list &lefth=other.chain_inferiors_;
00727     if (righth.size() != lefth.size())
00728       return false;
00729 
00730     chain_list::const_iterator r;
00731     chain_list::const_iterator l;
00732     for (r=righth.begin(), l=lefth.begin(); r!=righth.end(); ++r, ++l)
00733       if ( !(*(*r) == *(*l)) ) // ( *(*r) != *(*l))
00734         return false;
00735   }
00736   return true;
00737 }
00738 
00739 //---------------------------------------------------------------------------
00740 //: Reverse the direction of the one chain
00741 //---------------------------------------------------------------------------
00742 void vtol_one_chain::reverse_directions()
00743 {
00744   // This function reverses the direction
00745   // array in the list.
00746 
00747   for (vcl_vector<signed char>::iterator di=directions_.begin();
00748        di !=directions_.end();++di)
00749     (*di) = - (*di);
00750 
00751   // reverse the inferiors
00752 
00753   topology_list inf_tmp(inferiors()->size());
00754 
00755   // vcl_reverse_copy(inferiors()->begin(),inferiors()->end(),inf_tmp.begin());
00756   // reverse copy does not seem to work do this the hard way
00757   int s= inferiors()->size();
00758   for (int i=0;i<s;++i)
00759     inf_tmp[i]=inferiors_[s-1-i];
00760 
00761   inferiors()->clear();
00762   //  vcl_copy(inf_tmp.begin(),inf_tmp.end(),inferiors()->begin());
00763 
00764   for (topology_list::iterator ti=inf_tmp.begin();ti!=inf_tmp.end();ti++)
00765     inferiors()->push_back(*ti);
00766 
00767   vcl_vector<signed char> dir_tmp(directions_.size());
00768 
00769   // vcl_reverse_copy(directions_.begin(),directions_.end(),dir_tmp.begin());
00770   s=directions_.size();
00771 
00772   for (int i=0;i<s;++i)
00773     dir_tmp[i]=directions_[s-1-i];
00774 
00775   directions_.clear();
00776   // vcl_copy(dir_tmp.begin(),dir_tmp.end(),directions_.begin());
00777 
00778   for (vcl_vector<signed char>::iterator di=dir_tmp.begin();di!=dir_tmp.end();++di)
00779     directions_.push_back(*di);
00780 
00781   for (chain_list::iterator hi=chain_inferiors_.begin();
00782        hi!=chain_inferiors_.end();++hi)
00783     (*hi)->cast_to_one_chain()->reverse_directions();
00784 }
00785 
00786 //---------------------------------------------------------------------------
00787 //: Spatial object equality
00788 //---------------------------------------------------------------------------
00789 bool vtol_one_chain::operator==(vsol_spatial_object_2d const& obj) const
00790 {
00791   return
00792    obj.cast_to_topology_object() &&
00793    obj.cast_to_topology_object()->cast_to_one_chain() &&
00794    *this == *obj.cast_to_topology_object()->cast_to_one_chain();
00795 }
00796 
00797 //---------------------------------------------------------------------------
00798 //: Print Methods
00799 //---------------------------------------------------------------------------
00800 void vtol_one_chain::print(vcl_ostream &strm) const
00801 {
00802   strm << "<one_chain " << inferiors()->size() << "  "
00803        << (void const *) this << ">\n";
00804 }
00805 
00806 //---------------------------------------------------------------------------
00807 //: Describe the directions
00808 //---------------------------------------------------------------------------
00809 void vtol_one_chain::describe_directions(vcl_ostream &strm, int blanking) const
00810 {
00811   for (int j=0; j<blanking; ++j) { strm << ' '; }
00812   strm << "<Dirs [" << directions_.size() << "]:";
00813 
00814   vcl_vector<signed char>::const_iterator d1;
00815   for (d1=directions_.begin();d1!=directions_.end();++d1)
00816   {
00817     strm << ' ' << (int)(*d1);
00818   }
00819   strm << ">\n";
00820 }
00821 
00822 //---------------------------------------------------------------------------
00823 //: Describe the one chain
00824 //---------------------------------------------------------------------------
00825 void vtol_one_chain::describe(vcl_ostream &strm, int blanking) const
00826 {
00827   for (int j=0; j<blanking; ++j) strm << ' ';
00828   print(strm);
00829   describe_inferiors(strm, blanking);
00830   describe_directions(strm, blanking);
00831   describe_superiors(strm, blanking);
00832 }