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 }