contrib/gel/vtol/vtol_edge.cxx
Go to the documentation of this file.
00001 // This is gel/vtol/vtol_edge.cxx
00002 #include "vtol_edge.h"
00003 //:
00004 // \file
00005 #include <vcl_cassert.h>
00006 #include <vtol/vtol_zero_chain.h>
00007 #include <vtol/vtol_one_chain.h>
00008 #include <vtol/vtol_macros.h>
00009 #include <vtol/vtol_list_functions.h>
00010 
00011 //***************************************************************************
00012 // Initialization
00013 //***************************************************************************
00014 
00015 void vtol_edge::link_inferior(vtol_zero_chain_sptr inf)
00016 {
00017   vtol_topology_object::link_inferior(inf->cast_to_topology_object());
00018 }
00019 
00020 void vtol_edge::unlink_inferior(vtol_zero_chain_sptr inf)
00021 {
00022   vtol_topology_object::unlink_inferior(inf->cast_to_topology_object());
00023 }
00024 
00025 //---------------------------------------------------------------------------
00026 //: Return the first non-empty zero-chain of `this'
00027 //---------------------------------------------------------------------------
00028 vtol_zero_chain_sptr vtol_edge::zero_chain(void) const
00029 {
00030   topology_list const& inf = *(inferiors());
00031   for (unsigned int i=0; i<inf.size(); ++i)
00032     if (inf[i]->cast_to_zero_chain()->v0()) // PVr- avoid returning empty chain
00033       return inf[i]->cast_to_zero_chain();
00034   for (unsigned int i=0; i<inf.size(); ++i)
00035     if (inf[i]->cast_to_zero_chain()) // return empty chain if nothing else present
00036       return inf[i]->cast_to_zero_chain();
00037   return 0;
00038 }
00039 
00040 //---------------------------------------------------------------------------
00041 // Destructor
00042 //---------------------------------------------------------------------------
00043 vtol_edge::~vtol_edge()
00044 {
00045   unlink_all_inferiors();
00046 }
00047 
00048 //---------------------------------------------------------------------------
00049 //: Set the first endpoint.
00050 //---------------------------------------------------------------------------
00051 void vtol_edge::set_v1(vtol_vertex_sptr new_v1)
00052 {
00053   if (v1_&&v1_!=v2_)
00054     zero_chain()->unlink_inferior(v1_);
00055   v1_=new_v1;
00056   zero_chain()->link_inferior(v1_);
00057   touch();
00058 }
00059 
00060 //---------------------------------------------------------------------------
00061 //: Set the last endpoint.
00062 //---------------------------------------------------------------------------
00063 void vtol_edge::set_v2(vtol_vertex_sptr new_v2)
00064 {
00065   if (v2_&&v2_!=v1_)
00066     zero_chain()->unlink_inferior(v2_);
00067   v2_=new_v2;
00068   zero_chain()->link_inferior(v2_);
00069   touch();
00070 }
00071 
00072 //---------------------------------------------------------------------------
00073 //: Set the first and last endpoints
00074 // Require: vertex_of_edge(new_v1) and vertex_of_edge(new_v2).
00075 //
00076 //  This function removes curendpt from the edge and replaces it with
00077 //  newendpt.  Both curendpt and newendpt must be non-NULL pointers,
00078 //  curendpt must point to an endpoint of the edge (either v1_ or
00079 //  v2_), and newendpt must be collinear with the edge.  Neither vertex
00080 //  is destroyed in the process; only links are manipulated.
00081 //  (RYF 7-14-98)
00082 //
00083 void vtol_edge::replace_end_point(vtol_vertex &curendpt,
00084                                   vtol_vertex &newendpt)
00085 {
00086   assert(&curendpt==v1_||&curendpt==v2_);
00087 
00088   zero_chain()->unlink_inferior(&curendpt);
00089   zero_chain()->link_inferior(&newendpt);
00090   if (&curendpt==v1_)
00091     v1_=&newendpt;  // update the appropriate endpoint
00092   else // &curendpt == v2_
00093     v2_=&newendpt;
00094 }
00095 
00096 //---------------------------------------------------------------------------
00097 //: Determine the endpoints of an edge from its inferiors
00098 //---------------------------------------------------------------------------
00099 void vtol_edge::set_vertices_from_zero_chains(void)
00100 {
00101   if (numinf()==1) // This is the normal case.
00102   {
00103     // Set v1_ to be the first on the
00104     // vtol_zero_chain. Set v2_ to be the last on
00105     // the vtol_zero_chain.
00106     vtol_topology_object_sptr zc0=inferiors()->front();
00107     switch (zc0->numinf())
00108     {
00109      case 0:
00110       v1_=0;
00111       v2_=0;
00112       break;
00113      case 1:
00114       v1_=v2_=zc0->inferiors()->front()->cast_to_vertex();
00115       break;
00116      default:
00117       topology_list const * v = zc0->inferiors();
00118       v1_=v->front()->cast_to_vertex();
00119       v2_=v->back()->cast_to_vertex();
00120       break;
00121     }
00122   }
00123   else // This is a strange case but we'll take care of it.
00124     // Assuming zero_chains have an ordering,
00125     // Set v1_ to the first vertex and Set v2_
00126     // to be the last vertex.  They will not
00127     // be on the same vtol_zero_chain.
00128   {
00129     vertex_list verts; vertices(verts);
00130     switch (verts.size())
00131     {
00132      case 0:
00133       v1_=0;
00134       v2_=0;
00135       break;
00136      default:
00137       v1_=verts.front();
00138       v2_=verts.back();
00139     }
00140   }
00141   touch();
00142 }
00143 
00144 //:
00145 // This is a utility method that adds new_edge_loop to the vtol_edge's
00146 // superior list.  It returns a boolean value reflecting the success of
00147 // linking.
00148 
00149 void vtol_edge::add_edge_loop(vtol_one_chain_sptr const& new_edge_loop)
00150 {
00151   new_edge_loop->link_inferior(this);
00152 }
00153 
00154 #if 1 // deprecated
00155 void vtol_edge::add_edge_loop(vtol_one_chain &new_edge_loop)
00156 {
00157   vcl_cerr << "Warning: deprecated form of vtol_edge::add_edge_loop()\n";
00158   new_edge_loop.link_inferior(this);
00159 }
00160 #endif
00161 
00162 //:
00163 // This is a utility method that removes doomed_edge_loop from the
00164 // vtol_edge's superior list. It returns a boolean value reflecting the
00165 // success of removing.
00166 
00167 void vtol_edge::remove_edge_loop(vtol_one_chain_sptr const& doomed_edge_loop)
00168 {
00169   doomed_edge_loop->unlink_inferior(this);
00170 }
00171 
00172 #if 1 // deprecated
00173 void vtol_edge::remove_edge_loop(vtol_one_chain &doomed_edge_loop)
00174 {
00175   vcl_cerr << "Warning: deprecated form of vtol_edge::remove_edge_loop()\n";
00176   doomed_edge_loop.unlink_inferior(this);
00177 }
00178 #endif
00179 
00180 // ******************************************************
00181 //
00182 //    Operators
00183 //
00184 
00185 // operators
00186 
00187 bool vtol_edge::operator==(const vtol_edge &other) const
00188 {
00189   if (this==&other) return true;
00190 
00191   if (numinf()!=other.numinf())
00192     return false;
00193 
00194   if (!compare_geometry(other))
00195     return false;
00196 
00197   if (!(*v1_==*(other.v1_)) || !(*v2_==*(other.v2_)))
00198     return false;
00199 
00200   vtol_zero_chain_sptr zc1=zero_chain();
00201   vtol_zero_chain_sptr zc2=other.zero_chain();
00202   if (!zc1||!zc2)
00203     return false;
00204   return *zc1==*zc2;
00205 }
00206 
00207 //: spatial object equality
00208 
00209 bool vtol_edge::operator==(const vsol_spatial_object_2d& obj) const
00210 {
00211   return
00212    obj.cast_to_topology_object() &&
00213    obj.cast_to_topology_object()->cast_to_edge() &&
00214    *this == *obj.cast_to_topology_object()->cast_to_edge();
00215 }
00216 
00217 // ******************************************************
00218 //
00219 //    Inferior/Superior Accessor Functions
00220 //
00221 
00222 //: Returns a list of vertices on the vtol_edge.
00223 
00224 vcl_vector<vtol_vertex *> *vtol_edge::compute_vertices(void)
00225 {
00226   SEL_INF(vtol_vertex,compute_vertices);
00227 }
00228 
00229 //: Returns the vtol_zero_chain list of the vtol_edge. This list is the Inferiors of the edge.
00230 vcl_vector<vtol_zero_chain *> *vtol_edge::compute_zero_chains(void)
00231 {
00232   COPY_INF(zero_chain);
00233 }
00234 
00235 //: Returns a list with itself as the only element. This utility is used in Inferior/Superior accessing methods.
00236 vcl_vector<vtol_edge *> *vtol_edge::compute_edges(void)
00237 {
00238   LIST_SELF(vtol_edge);
00239 }
00240 
00241 //: Returns a list of one_chains which contain the vtol_edge. This list is the Superiors of the edge.
00242 vcl_vector<vtol_one_chain *> *vtol_edge::compute_one_chains(void)
00243 {
00244   SEL_SUP(vtol_one_chain,compute_one_chains);
00245 }
00246 
00247 
00248 //: Returns a list of the faces which contain the vtol_edge.
00249 vcl_vector<vtol_face *> *vtol_edge::compute_faces(void)
00250 {
00251   SEL_SUP(vtol_face,compute_faces);
00252 }
00253 
00254 //: Returns the list of two_chains which contain the vtol_edge.
00255 vcl_vector<vtol_two_chain *> *vtol_edge::compute_two_chains(void)
00256 {
00257   SEL_SUP(vtol_two_chain,compute_two_chains);
00258 }
00259 
00260 //: Returns the list of blocks which contain the vtol_edge.
00261 vcl_vector<vtol_block *> *vtol_edge::compute_blocks(void)
00262 {
00263   SEL_SUP(vtol_block,compute_blocks);
00264 }
00265 
00266 //: Returns a list of vertices containing the endpoints of the edge.
00267 // These vertices are v1_ and v2_ in that order.
00268 vertex_list *vtol_edge::endpoints(void)
00269 {
00270   vertex_list *newl=new vertex_list;
00271   if (v1_)
00272     newl->push_back(v1_);
00273   if (v2_)
00274     newl->push_back(v2_);
00275   return newl;
00276 }
00277 
00278 //:
00279 //  Returns true if the invoking edge has a vertex in common with
00280 //  vtol_edge `other'.  The method determines if the two edges share a vertex
00281 //  by comparing pointer values, not the vertex geometry.
00282 
00283 bool vtol_edge::share_vertex_with(vtol_edge_sptr const& other)
00284 {
00285   vertex_list thisvert; this->vertices(thisvert);
00286   vertex_list everts; other->vertices(everts);
00287   for (vertex_list::const_iterator i1=thisvert.begin();i1!=thisvert.end(); ++i1)
00288     for (vertex_list::const_iterator i2=everts.begin();i2!=everts.end(); ++i2)
00289       if ((*i1)==(*i2))
00290         return true;
00291   return false;
00292 }
00293 
00294 //:
00295 // This method adds newvert to the vtol_edge by linking it to one of the
00296 // zero_chains of the vtol_edge Inferiors. (Method needs work.)
00297 
00298 bool vtol_edge::add_vertex(vtol_vertex_sptr const& newvert)
00299 {
00300   vtol_zero_chain_sptr zc;
00301 
00302   zc=zero_chain();
00303   if (!zc)
00304     link_inferior(zc = new vtol_zero_chain);
00305 
00306   zc->link_inferior(newvert);
00307   return true;
00308 }
00309 
00310 //:
00311 // This method removes uglyvert from the vtol_edge by removing it from the
00312 // inferior zero_chains.  (Method needs work.)
00313 
00314 bool vtol_edge::remove_vertex(vtol_vertex_sptr const& uglyvert)
00315 {
00316   if (uglyvert==v1_)
00317     set_v1(0);
00318   else if (uglyvert==v2_)
00319     set_v2(0);
00320   else
00321     return false;
00322   touch();
00323   return true;
00324 }
00325 
00326 bool vtol_edge::is_endpoint(vtol_vertex_sptr const& v) const
00327 {
00328   return is_endpoint1(v)||is_endpoint2(v);
00329 }
00330 
00331 
00332 //: Returns True if v is equal to the first vtol_edge endpoint,v1_.
00333 bool vtol_edge::is_endpoint1(vtol_vertex_sptr const& v) const
00334 {
00335   return *v1_==*v;
00336 }
00337 
00338 //: Returns True if v is equal to the second vtol_edge endpoint, v2_.
00339 bool vtol_edge::is_endpoint2(vtol_vertex_sptr const& v) const
00340 {
00341   return *v2_ ==*v;
00342 }
00343 
00344 
00345 //: This method works only for ImplicitLine edges.
00346 vtol_vertex_sptr vtol_edge::other_endpoint(const vtol_vertex &overt) const
00347 {
00348   if (overt==*v1_)
00349     return v2_;
00350   else if (overt==*v2_)
00351     return v1_;
00352   else
00353     return 0;
00354 }
00355 
00356 // ******************************************************
00357 //
00358 //    I/O methods
00359 //
00360 
00361 //:
00362 // This method outputs all edge information to the vcl_ostream, strm.  It
00363 // indents various levels of output by the number given in blanking.
00364 void vtol_edge::describe(vcl_ostream &strm,
00365                          int blanking) const
00366 {
00367   for (int i1=0; i1<blanking; ++i1) strm << ' ';
00368   print(strm);
00369   for (int i2=0; i2<blanking; ++i2) strm << ' ';
00370   if (v1_) v1_->print(strm);
00371   else     strm << "Null vertex 1\n";
00372 
00373   for (int i3=0; i3<blanking; ++i3) strm << ' ';
00374   if (v2_) v2_->print(strm);
00375   else     strm << "Null vertex 2\n";
00376 }
00377 
00378 //:
00379 // This method outputs a brief vtol_edge info with vtol_edge object address.
00380 void vtol_edge::print(vcl_ostream &strm) const
00381 {
00382    strm<<"<vtol_edge "<<(void const *)this <<"> with id "<<get_id()<<'\n';
00383 }