1 // This is gel/vtol/vtol_two_chain.cxx
2 #include <vector>
3 #include <iostream>
4 #include <algorithm>
5 #include "vtol_two_chain.h"
6 //:
7 // \file
8 // \verbatim
9 // Modifications
10 // 05/13/98 RIH replaced append by insert_after to avoid n^2 behavior
11 // \endverbatim
12
13 #ifdef _MSC_VER
14 # include "vcl_msvc_warnings.h"
15 #endif
16
17 #include <vtol/vtol_list_functions.h>
18 #include <vtol/vtol_face.h>
19 #include <vtol/vtol_edge.h>
20 #include <vtol/vtol_vertex.h>
21 #include <vtol/vtol_block.h>
22 #include <vtol/vtol_macros.h>
23 #include <cassert>
24
25 //***************************************************************************
26 // Initialization
27 //***************************************************************************
28
link_inferior(const vtol_face_sptr & inf)29 void vtol_two_chain::link_inferior(const vtol_face_sptr& inf)
30 {
31 vtol_topology_object::link_inferior(inf->cast_to_topology_object());
32 }
33
unlink_inferior(const vtol_face_sptr & inf)34 void vtol_two_chain::unlink_inferior(const vtol_face_sptr& inf)
35 {
36 vtol_topology_object::unlink_inferior(inf->cast_to_topology_object());
37 }
38
link_chain_inferior(const vtol_two_chain_sptr & chain_inferior)39 void vtol_two_chain::link_chain_inferior(const vtol_two_chain_sptr& chain_inferior)
40 {
41 vtol_chain::link_chain_inferior(chain_inferior->cast_to_chain());
42 }
43
unlink_chain_inferior(const vtol_two_chain_sptr & chain_inferior)44 void vtol_two_chain::unlink_chain_inferior(const vtol_two_chain_sptr& chain_inferior)
45 {
46 vtol_chain::unlink_chain_inferior(chain_inferior->cast_to_chain());
47 }
48
49 //---------------------------------------------------------------------------
50 //: Constructor
51 //---------------------------------------------------------------------------
vtol_two_chain(face_list const & faces,bool new_is_cycle)52 vtol_two_chain::vtol_two_chain(face_list const& faces,
53 bool new_is_cycle)
54 {
55 for (const auto & face : faces)
56 {
57 link_inferior(face);
58 // all face normals point outward.
59 directions_.push_back((signed char)1);
60 }
61 is_cycle_=new_is_cycle;
62 }
63
64 //---------------------------------------------------------------------------
65 //: Constructor
66 //---------------------------------------------------------------------------
vtol_two_chain(face_list const & faces,std::vector<signed char> const & dirs,bool new_is_cycle)67 vtol_two_chain::vtol_two_chain(face_list const& faces,
68 std::vector<signed char> const& dirs,
69 bool new_is_cycle)
70 {
71 std::vector<signed char>::const_iterator di;
72 face_list::const_iterator fi;
73
74 for (di=dirs.begin(),fi=faces.begin();
75 fi!=faces.end()&&di!=dirs.end();
76 ++fi,++di)
77 {
78 if ((*di)<0)
79 (*fi)->reverse_normal();
80 link_inferior(*fi);
81 directions_.push_back(*di);
82 }
83 is_cycle_=new_is_cycle;
84 }
85
86 //---------------------------------------------------------------------------
87 //: Pseudo copy constructor. Deep copy.
88 //---------------------------------------------------------------------------
vtol_two_chain(vtol_two_chain_sptr const & other)89 vtol_two_chain::vtol_two_chain(vtol_two_chain_sptr const& other)
90 {
91 // make a copy of the vertices
92 vertex_list verts; other->vertices(verts);
93 int vlen=verts.size();
94 topology_list newverts(vlen);
95
96 int i=0;
97 for (auto vi=verts.begin();vi!=verts.end();++vi,++i)
98 {
99 vtol_vertex_sptr v = *vi;
100 newverts[i] = v->clone()->cast_to_topology_object();
101 v->set_id(i);
102 }
103
104 // make a copy of the edges
105 edge_list edges; other->edges(edges);
106 int elen=edges.size();
107 topology_list newedges(elen);
108
109 int j=0;
110 for (auto ei=edges.begin();ei!= edges.end();++ei,++j)
111 {
112 vtol_edge_sptr e = *ei;
113 newedges[j] = newverts[e->v1()->get_id()]->cast_to_vertex()->new_edge(
114 newverts[e->v2()->get_id()]->cast_to_vertex())->cast_to_topology_object();
115 e->set_id(j);
116 }
117
118 std::vector<signed char> &dirs=other->directions_;
119 topology_list &infs=other->inferiors_;
120
121 std::vector<signed char>::iterator ddi;
122 topology_list::const_iterator tti;
123 for (ddi=dirs.begin(),tti=infs.begin(); tti!=infs.end()&&ddi!=dirs.end(); ++ddi,++tti)
124 {
125 vtol_face_sptr f=(*tti)->cast_to_face();
126 vtol_face_sptr new_f = f->copy_with_arrays(newverts,newedges);
127 #ifdef DEBUG
128 std::cout << "f\n";
129 f->describe();
130 std::cout << "new f\n";
131 new_f->describe();
132 #endif
133 assert(*new_f == *f);
134
135 link_inferior(new_f);
136 directions_.push_back((*ddi));
137 }
138
139 set_cycle(other->is_cycle());
140 const chain_list *hierarchy_infs=other->chain_inferiors();
141
142 for (const auto & hierarchy_inf : *hierarchy_infs)
143 link_chain_inferior(hierarchy_inf->cast_to_two_chain()->copy_with_arrays(newverts,newedges));
144 }
145
146 vtol_two_chain *
copy_with_arrays(topology_list & newverts,topology_list & newedges) const147 vtol_two_chain::copy_with_arrays(topology_list &newverts,
148 topology_list &newedges) const
149 {
150 const std::vector<signed char> &dirs=directions_;
151 const topology_list &infs=inferiors_;
152
153 auto *result=new vtol_two_chain(infs.size());
154
155 std::vector<signed char>::const_iterator di;
156 topology_list::const_iterator ti;
157 for (di=dirs.begin(),ti=infs.begin();
158 ti!=infs.end()&&di!=dirs.end();
159 ++ti,++di)
160 {
161 vtol_face *f=(*ti)->cast_to_face();
162 result->link_inferior(f->copy_with_arrays(newverts,newedges));
163 result->directions_.push_back((*di));
164 }
165
166 result->set_cycle(is_cycle());
167 const chain_list *hierarchy_infs=chain_inferiors();
168
169 for (const auto & hierarchy_inf : *hierarchy_infs)
170 result->link_chain_inferior(hierarchy_inf->cast_to_two_chain()->copy_with_arrays(newverts,newedges));
171 return result;
172 }
173
174 //---------------------------------------------------------------------------
175 // Destructor
176 //---------------------------------------------------------------------------
~vtol_two_chain()177 vtol_two_chain::~vtol_two_chain()
178 {
179 clear();
180 unlink_all_chain_inferiors();
181 }
182
183 //---------------------------------------------------------------------------
184 //: Clone `this': creation of a new object and initialization
185 // See Prototype pattern
186 //---------------------------------------------------------------------------
clone() const187 vsol_spatial_object_2d* vtol_two_chain::clone() const
188 {
189 return new vtol_two_chain(vtol_two_chain_sptr(const_cast<vtol_two_chain*>(this)));
190 }
191
192 //---------------------------------------------------------------------------
193 //: Shallow copy with no links
194 //---------------------------------------------------------------------------
195 vtol_topology_object *
shallow_copy_with_no_links() const196 vtol_two_chain::shallow_copy_with_no_links() const
197 {
198 auto *result=new vtol_two_chain();
199 result->is_cycle_=is_cycle_;
200 std::vector<signed char>::const_iterator di;
201
202 for (di=directions_.begin();di!=directions_.end();++di)
203 result->directions_.push_back((*di));
204 return result;
205 }
206
207 //***************************************************************************
208 // Editing Functions
209 //***************************************************************************
210
211 //: add the superiors from the parent
212
add_superiors_from_parent(topology_list & sups)213 void vtol_two_chain::add_superiors_from_parent(topology_list &sups)
214 {
215 for (auto & sup : sups)
216 sup->link_inferior(this);
217
218 chain_list::iterator hi;
219 for (hi=chain_inferiors_.begin();hi!=chain_inferiors_.end();++hi)
220 (*hi)->cast_to_two_chain()->add_superiors_from_parent(sups);
221 }
222
remove_superiors_of_parent(topology_list & sups)223 void vtol_two_chain::remove_superiors_of_parent(topology_list &sups)
224 {
225 for (auto & sup : sups)
226 sup->unlink_inferior(this);
227
228 chain_list::iterator hi;
229 for (hi=chain_inferiors_.begin();hi!=chain_inferiors_.end();++hi)
230 (*hi)->cast_to_two_chain()->remove_superiors_of_parent(sups);
231 }
232
remove_superiors()233 void vtol_two_chain::remove_superiors()
234 {
235 superiors_.clear();
236 chain_list::iterator hi;
237 for (hi=chain_inferiors_.begin();hi!=chain_inferiors_.end();++hi)
238 (*hi)->cast_to_two_chain()->remove_superiors();
239 }
240
update_superior_list_p_from_hierarchy_parent()241 void vtol_two_chain::update_superior_list_p_from_hierarchy_parent()
242 {
243 // Check to see if there is a parent node in the tree.
244 const vtol_two_chain *hierarchy_parent=nullptr;
245 if (!chain_superiors_.empty())
246 hierarchy_parent = chain_superiors_.front()->cast_to_two_chain();
247
248 // If vtol_two_chain is a child of another vtol_two_chain...the superiors
249 // lists are updated.
250
251 if (hierarchy_parent!=nullptr)
252 {
253 const std::list<vtol_topology_object*> *parent_superiors = hierarchy_parent->superiors_list();
254
255 // Clear all previous superiors.
256 superiors_.clear();
257 std::list<vtol_topology_object*>::const_iterator ti;
258 for (ti=parent_superiors->begin();ti!= parent_superiors->end();++ti)
259 if (std::find(superiors_.begin(),superiors_.end(),*ti)==superiors_.end())
260 superiors_.push_back(*ti);
261
262 // Recursively update all children.
263 two_chain_list *chains=inferior_two_chains();
264
265 for (auto & chain : *chains)
266 chain->update_superior_list_p_from_hierarchy_parent();
267 delete chains;
268 }
269 }
270
271 bool
break_into_connected_components(topology_list &)272 vtol_two_chain::break_into_connected_components( topology_list& /*components*/ )
273 {
274 std::cerr << "vtol_two_chain::break_into_connected_components() not yet implemented\n";
275 #if 0 // TODO
276 topology_list * tmp = get_inferiors();
277 int numfaces = tmp->size();
278 if ( numfaces == 0 ) return false;
279 std::vector< vtol_face * > faces( numfaces );
280 int i=0;
281 for (topology_list::iterator ti= tmp->begin(); ti!=tmp->end();++ti, ++i )
282 faces[ i ] = (*ti)->cast_to_face();
283
284 // compnum[i] stores the component number of the ith face
285 int * compnum = new int[ numfaces ];
286 assert( compnum );
287
288 // adjslists stores the adjacency lists representation of the face graph
289 std::vector< int > * adjlists = new std::vector< int > [ numfaces ];
290 assert( adjlists );
291
292 // build the adjacency list representation
293 for ( i = 0; i < numfaces; ++i )
294 {
295 compnum[ i ] = -1; // -1 signals it is not part of any component yet
296 for (int j = i+1; j < numfaces; ++j )
297 if ( faces[ i ]->shares_edge_with( faces[ j ] ) )
298 {
299 adjlists[i].push_back( j );
300 adjlists[j].push_back( i );
301 }
302 }
303
304 // use depth first search to find connected components
305 int numcomps = 0;
306 for ( i = 0; i < numfaces; ++i )
307 {
308 if ( compnum[ i ] == -1 ) // unvisited
309 {
310 compnum[ i ] = numcomps;
311 std::vector<int> to_be_explored;
312 to_be_explored.push( i );
313 while ( to_be_explored.size() )
314 {
315 int f = to_be_explored.pop();
316 for ( adjlists[ f ].begin(); adjlists[ f ].end(); )
317 {
318 if ( compnum[ adjlists[ f ].value() ] == -1 )
319 {
320 compnum[ adjlists[ f ].value() ] = numcomps;
321 to_be_explored.push( adjlists[ f ].value() );
322 }
323 }
324 }
325 ++numcomps;
326 }
327 }
328
329 if ( numcomps > 1 )
330 for ( i = 0; i < numcomps; ++i )
331 {
332 std::vector< vtol_face * > component_faces;
333 // gather faces belonging to the ith component
334 for ( j = 0; j < numfaces; ++j )
335 if ( compnum[ j ] == i )
336 component_faces.push_back( faces[ j ] );
337 // create either a two chain or a face out of the component
338 if ( component_faces.size() == 1 )
339 components.push_back( component_faces.get( 0 ) );
340 else
341 {
342 vtol_two_chain * newvtol_two_chain = new vtol_two_chain(component_faces, false);
343 // need to check if it is a cycle??
344 components.push_back( newvtol_two_chain );
345 }
346 component_faces.clear(); // necessary??
347 }
348
349 delete []compnum;
350 delete []adjlists;
351
352 if ( numcomps == 1 ) return false;
353 else return true;
354 #else // 0
355 std::cerr << "vtol_two_chain::break_into_connected_components() not implemented yet\n";
356 return false; // TODO
357 #endif // 0
358 }
359
add_face(vtol_face_sptr const & new_face,signed char dir)360 void vtol_two_chain::add_face(vtol_face_sptr const& new_face,
361 signed char dir)
362 {
363 directions_.push_back(dir);
364 link_inferior(new_face);
365 }
366
367 #if 1 // deprecated
add_face(vtol_face & new_face,signed char dir)368 void vtol_two_chain::add_face(vtol_face &new_face,
369 signed char dir)
370 {
371 std::cerr << "Warning: deprecated form of vtol_face::add_face()\n";
372 directions_.push_back(dir);
373 link_inferior(&new_face);
374 }
375 #endif
376
remove_face(vtol_face_sptr const & doomed_face)377 void vtol_two_chain::remove_face(vtol_face_sptr const& doomed_face)
378 {
379 vtol_topology_object_sptr t=doomed_face->cast_to_topology_object();
380 topology_list::const_iterator i=std::find(inferiors()->begin(),inferiors()->end(),t);
381 topology_list::difference_type index=i-inferiors()->begin();
382
383 if (index>=0 && i!= inferiors()->end())
384 {
385 auto j = directions_.begin() + index;
386 directions_.erase(j);
387 touch();
388 unlink_inferior(doomed_face);
389 }
390 }
391
392 #if 1 // deprecated
remove_face(vtol_face & doomed_face)393 void vtol_two_chain::remove_face(vtol_face &doomed_face)
394 {
395 std::cerr << "Warning: deprecated form of vtol_face::remove_face()\n";
396 vtol_topology_object_sptr t=&doomed_face;
397 topology_list::const_iterator i=std::find(inferiors()->begin(),inferiors()->end(),t);
398 topology_list::difference_type index=i-inferiors()->begin();
399
400 if (index>=0 && i!= inferiors()->end())
401 {
402 auto j = directions_.begin() + index;
403 directions_.erase(j);
404 touch();
405 unlink_inferior(&doomed_face);
406 }
407 }
408 #endif
409
410 //***************************************************************************
411 // Accessor Functions
412 //***************************************************************************
413
face(int i)414 vtol_face_sptr vtol_two_chain::face(int i)
415 {
416 return inferiors_[i]->cast_to_face();
417 }
418
419 //: outside boundary vertices
420
outside_boundary_vertices()421 vertex_list *vtol_two_chain::outside_boundary_vertices()
422 {
423 auto *new_ref_list = new vertex_list;
424 std::vector<vtol_vertex*>* ptr_list = this->outside_boundary_compute_vertices();
425 // copy the lists
426
427 for (auto & ti : *ptr_list)
428 new_ref_list->push_back(ti);
429
430 delete ptr_list;
431
432 return new_ref_list;
433 }
434
435 std::vector<vtol_vertex *> *
outside_boundary_compute_vertices()436 vtol_two_chain::outside_boundary_compute_vertices()
437 {
438 SEL_INF(vtol_vertex,compute_vertices);
439 }
440
441 //: list of vertices
442
compute_vertices()443 std::vector<vtol_vertex *> *vtol_two_chain::compute_vertices()
444 {
445 std::vector<vtol_vertex *> *verts = outside_boundary_compute_vertices();
446
447 // Set current position to the end
448 // verts->set_position(verts->size()-1); - not sure what is supposed to happen here
449
450 SUBCHAIN_INF(verts,two_chain,vtol_vertex,compute_vertices);
451 }
452
453 //: outside boundary zero chains
454
outside_boundary_zero_chains()455 zero_chain_list *vtol_two_chain::outside_boundary_zero_chains()
456 {
457 auto *new_ref_list = new zero_chain_list;
458 std::vector<vtol_zero_chain*>* ptr_list = this->outside_boundary_compute_zero_chains();
459 // copy the lists
460
461 for (auto & ti : *ptr_list)
462 new_ref_list->push_back(ti);
463
464 delete ptr_list;
465
466 return new_ref_list;
467 }
468
outside_boundary_compute_zero_chains()469 std::vector<vtol_zero_chain*> *vtol_two_chain::outside_boundary_compute_zero_chains()
470 {
471 SEL_INF(vtol_zero_chain,compute_zero_chains);
472 }
473
474 //: list of zero chains
compute_zero_chains()475 std::vector<vtol_zero_chain*> *vtol_two_chain::compute_zero_chains()
476 {
477 std::vector<vtol_zero_chain*> *zchs;
478 zchs=outside_boundary_compute_zero_chains();
479
480 SUBCHAIN_INF(zchs,two_chain,vtol_zero_chain,compute_zero_chains);
481 }
482
483 //: outside boundary edges
outside_boundary_edges()484 edge_list *vtol_two_chain::outside_boundary_edges()
485 {
486 auto *new_ref_list = new edge_list;
487 std::vector<vtol_edge*>* ptr_list = this->outside_boundary_compute_edges();
488 // copy the lists
489
490 for (auto & ti : *ptr_list)
491 new_ref_list->push_back(ti);
492
493 delete ptr_list;
494
495 return new_ref_list;
496 }
497
498 //: outside boundary edges
outside_boundary_compute_edges()499 std::vector<vtol_edge*> *vtol_two_chain::outside_boundary_compute_edges()
500 {
501 SEL_INF(vtol_edge,compute_edges);
502 }
503
504 //: list of edges
compute_edges()505 std::vector<vtol_edge*> *vtol_two_chain::compute_edges()
506 {
507 std::vector<vtol_edge*> *edgs;
508 edgs=outside_boundary_compute_edges();
509
510 SUBCHAIN_INF(edgs,two_chain,vtol_edge,compute_edges);
511 }
512
513 //: outside one chains
outside_boundary_one_chains()514 one_chain_list *vtol_two_chain::outside_boundary_one_chains()
515 {
516 std::vector<vtol_one_chain*>* ptr_list= outside_boundary_compute_one_chains();
517 auto *ref_list= new one_chain_list;
518
519 std::vector<vtol_one_chain*>::iterator i;
520 for (i=ptr_list->begin();i!=ptr_list->end();++i)
521 ref_list->push_back(*i);
522
523 delete ptr_list;
524 return ref_list;
525 }
526
outside_boundary_compute_one_chains()527 std::vector<vtol_one_chain*> *vtol_two_chain::outside_boundary_compute_one_chains()
528 {
529 SEL_INF(vtol_one_chain,compute_one_chains);
530 }
531
532 //: one chains
compute_one_chains()533 std::vector<vtol_one_chain*> *vtol_two_chain::compute_one_chains()
534 {
535 std::vector<vtol_one_chain*> *onechs;
536 onechs=outside_boundary_compute_one_chains();
537 SUBCHAIN_INF(onechs,two_chain,vtol_one_chain,compute_one_chains);
538 }
539
540 //: outside faces
outside_boundary_faces()541 face_list *vtol_two_chain::outside_boundary_faces()
542 {
543 std::vector<vtol_face*>* ptr_list= outside_boundary_compute_faces();
544 auto *ref_list= new face_list;
545
546 std::vector<vtol_face*>::iterator i;
547 for (i=ptr_list->begin();i!=ptr_list->end();++i)
548 ref_list->push_back(*i);
549
550 delete ptr_list;
551 return ref_list;
552 }
553
554 // outside faces
outside_boundary_compute_faces()555 std::vector<vtol_face*> *vtol_two_chain::outside_boundary_compute_faces()
556 {
557 COPY_INF(face);
558 }
559
560 //: faces
compute_faces()561 std::vector<vtol_face*> *vtol_two_chain::compute_faces()
562 {
563 std::vector<vtol_face*> *facs;
564 facs=outside_boundary_compute_faces();
565 SUBCHAIN_INF(facs,two_chain,vtol_face,compute_faces);
566 }
567
568 //: list of blocks
compute_blocks()569 std::vector<vtol_block*> *vtol_two_chain::compute_blocks()
570 {
571 if (is_sub_chain())
572 {
573 auto*result=new std::vector<vtol_block*>;
574 std::list<vtol_chain*>::iterator tci;
575 for (tci=chain_superiors_.begin();tci!=chain_superiors_.end();++tci)
576 {
577 std::vector<vtol_block*> *sublist=(*tci)->cast_to_two_chain()->compute_blocks();
578 std::vector<vtol_block*>::iterator si;
579 for (si=sublist->begin();si!=sublist->end();++si)
580 result->push_back(*si);
581 delete sublist;
582 }
583 return tagged_union(result);
584 }
585 else
586 {
587 SEL_SUP(vtol_block,compute_blocks);
588 }
589 }
590
591 //: list of two chains
592
compute_two_chains()593 std::vector<vtol_two_chain*> *vtol_two_chain::compute_two_chains()
594 {
595 std::vector<vtol_two_chain*> *result=outside_boundary_compute_two_chains();
596
597 chain_list::iterator hi;
598 for (hi=chain_inferiors_.begin();hi!=chain_inferiors_.end();++hi )
599 result->push_back((*hi)->cast_to_two_chain());
600 return result;
601 }
602
inferior_two_chains()603 two_chain_list *vtol_two_chain::inferior_two_chains()
604 {
605 auto *result=new two_chain_list;
606 chain_list::iterator hi;
607 for (hi=chain_inferiors_.begin();hi!=chain_inferiors_.end();++hi)
608 result->push_back((*hi)->cast_to_two_chain());
609 return result;
610 }
611
612
superior_two_chains()613 two_chain_list *vtol_two_chain::superior_two_chains()
614 {
615 auto *result=new two_chain_list;
616 std::list<vtol_chain*>::iterator hi;
617 for (hi=chain_superiors_.begin();hi!=chain_superiors_.end();++hi)
618 result->push_back((*hi)->cast_to_two_chain());
619 return result;
620 }
621
outside_boundary_two_chains()622 two_chain_list *vtol_two_chain::outside_boundary_two_chains()
623 {
624 std::vector<vtol_two_chain*>* ptr_list= outside_boundary_compute_two_chains();
625 auto *ref_list= new two_chain_list;
626
627 std::vector<vtol_two_chain*>::iterator i;
628 for (i=ptr_list->begin();i!=ptr_list->end();++i)
629 ref_list->push_back(*i);
630
631 delete ptr_list;
632 return ref_list;
633 }
634
outside_boundary_compute_two_chains()635 std::vector<vtol_two_chain*> *vtol_two_chain::outside_boundary_compute_two_chains()
636 {
637 LIST_SELF(vtol_two_chain);
638 }
639
640 //***************************************************************************
641 // Operator Functions
642 //***************************************************************************
643
644 //: equality operator
645
operator ==(vtol_two_chain const & other) const646 bool vtol_two_chain::operator==(vtol_two_chain const& other) const
647 {
648 if (this==&other)
649 return true;
650
651 if (numinf()!=other.numinf())
652 return false;
653
654 topology_list::const_iterator ti1,ti2;
655 for (ti1=other.inferiors()->begin(),ti2=inferiors()->begin();
656 ti2!=inferiors()->end(); ++ti1,++ti2)
657 {
658 vtol_face *f1=(*ti2)->cast_to_face();
659 vtol_face *f2=(*ti1)->cast_to_face();
660 if (!(*f1==*f2))
661 return false;
662 }
663
664 // check out the directions
665
666 const std::vector<signed char> *dir1=this->directions();
667 const std::vector<signed char> *dir2=other.directions();
668
669 std::vector<signed char>::const_iterator d1;
670 std::vector<signed char>::const_iterator d2;
671 for (d1=dir1->begin(), d2=dir2->begin(); d1 != dir1->end(); ++d1, ++d2)
672 if (!(*d1 == *d2))
673 return false;
674
675 const chain_list &righth=chain_inferiors_;
676 const chain_list &lefth=other.chain_inferiors_;
677 if (righth.size()!=lefth.size())
678 return false;
679
680 chain_list::const_iterator hi1,hi2;
681
682 for (hi1=righth.begin(),hi2=lefth.begin();
683 hi1!=righth.end()&&hi2!=lefth.end();
684 ++hi1,++hi2)
685 if ( !(*(*hi1) == *(*hi2)))
686 return false;
687
688 return true;
689 }
690
691 //: spatial object equality
692
operator ==(vsol_spatial_object_2d const & obj) const693 bool vtol_two_chain::operator==(vsol_spatial_object_2d const& obj) const
694 {
695 return
696 obj.cast_to_topology_object() &&
697 obj.cast_to_topology_object()->cast_to_two_chain() &&
698 *this == *obj.cast_to_topology_object()->cast_to_two_chain();
699 }
700
701 //***************************************************************************
702 // Utility Functions
703 //***************************************************************************
704
705 //: correct the chain directions
correct_chain_directions()706 void vtol_two_chain::correct_chain_directions()
707 {
708 std::cerr << "vtol_two_chain::correct_chain_directions() not yet implemented\n";
709 }
710
711 //***************************************************************************
712 // Print Functions
713 //***************************************************************************
714
print(std::ostream & strm) const715 void vtol_two_chain::print(std::ostream &strm) const
716 {
717 strm << "<vtol_two_chain with " << inferiors()->size() << " faces>\n";
718 }
719
describe_directions(std::ostream & strm,int blanking) const720 void vtol_two_chain::describe_directions(std::ostream &strm,
721 int blanking) const
722 {
723 for (int j=0; j<blanking; ++j) { strm << ' '; }
724 strm << "<Dirs [" << directions_.size() << "]:";
725
726 std::vector<signed char>::const_iterator di;
727 for (di=directions_.begin();di!=directions_.end();++di)
728 {
729 strm << ' ' << (int)(*di);
730 }
731 strm << ">\n";
732 }
733
describe(std::ostream & strm,int blanking) const734 void vtol_two_chain::describe(std::ostream &strm,
735 int blanking) const
736 {
737 for (int j=0; j<blanking; ++j) strm << ' ';
738 print(strm);
739 describe_inferiors(strm,blanking);
740 describe_directions(strm,blanking);
741 describe_superiors(strm,blanking);
742 }
743
direction(vtol_face const & f) const744 signed char vtol_two_chain::direction(vtol_face const& f) const
745 {
746 // return the direction of the face
747
748 std::vector<signed char>::const_iterator dit;
749 topology_list::const_iterator toit;
750
751 dit=directions_.begin();
752 for (toit=inferiors()->begin();toit!=inferiors()->end();++toit)
753 {
754 vtol_face *cf=(*toit)->cast_to_face();
755 if (cf==&f)
756 return *dit;
757 ++dit;
758 }
759 return (signed char)1;
760 }
761