1 // This is gel/vtol/vtol_face.cxx
2 #include "vtol_face.h"
3 //:
4 // \file
5
6 #include <cassert>
7 #ifdef _MSC_VER
8 # include "vcl_msvc_warnings.h"
9 #endif
10 #include <vtol/vtol_macros.h>
11 #include <vtol/vtol_two_chain.h>
12 #include <vtol/vtol_vertex.h>
13 #include <vtol/vtol_edge.h>
14 #include <vtol/vtol_one_chain.h>
15 #include <vtol/vtol_list_functions.h>
16
link_inferior(const vtol_one_chain_sptr & inf)17 void vtol_face::link_inferior(const vtol_one_chain_sptr& inf)
18 {
19 vtol_topology_object::link_inferior(inf->cast_to_topology_object());
20 }
21
unlink_inferior(const vtol_one_chain_sptr & inf)22 void vtol_face::unlink_inferior(const vtol_one_chain_sptr& inf)
23 {
24 vtol_topology_object::unlink_inferior(inf->cast_to_topology_object());
25 }
26
27 //---------------------------------------------------------------------------
28 // Destructor
29 //---------------------------------------------------------------------------
~vtol_face()30 vtol_face::~vtol_face()
31 {
32 unlink_all_inferiors();
33 }
34
35 //:
36 // Returns an ordered list of vertices of the outside boundary of the
37 // face. All vertices on any holes of the face are \e not included.
38 // This vertex list is ordered such that a positive normal is
39 // computing using the Right Hand rule in the direction of the vertex
40 // list.
41
outside_boundary_vertices()42 vertex_list *vtol_face::outside_boundary_vertices() {
43 auto *new_ref_list = new vertex_list;
44 std::vector<vtol_vertex*>* ptr_list = this->outside_boundary_compute_vertices();
45
46 // copy the lists
47 for (std::vector<vtol_vertex*>::const_iterator ti = ptr_list->begin();
48 ti != ptr_list->end(); ++ti)
49 new_ref_list->push_back(*ti);
50
51 delete ptr_list;
52 return new_ref_list;
53 }
54
outside_boundary_compute_vertices()55 std::vector<vtol_vertex *> *vtol_face::outside_boundary_compute_vertices() {
56 OUTSIDE_BOUNDARY(vtol_vertex,one_chain,compute_vertices);
57 }
58
59 //:
60 // Returns a vtol_vertex list of all the vertices on the face.
61 // If the face does not have any holes, this vertex list is ordered
62 // in the direction of a positive normal using the Right Hand rule.
63
compute_vertices()64 std::vector<vtol_vertex *> *vtol_face::compute_vertices() {
65 SEL_INF(vtol_vertex,compute_vertices);
66 }
67
68 //:
69 // Returns a list of the zero_chains on the outside boundary of the face.
70 // All zero_chains on any hole boundaries of the face are \e not included.
71
72 std::vector<vtol_zero_chain *> *
outside_boundary_compute_zero_chains()73 vtol_face::outside_boundary_compute_zero_chains() {
74 OUTSIDE_BOUNDARY(vtol_zero_chain,one_chain,compute_zero_chains);
75 }
76
77 //:
78 // Returns a list of the zero_chains on the outside boundary of the face.
79 // All zero_chains on any hole boundaries of the face are \e not included.
80
outside_boundary_zero_chains()81 zero_chain_list *vtol_face::outside_boundary_zero_chains() {
82 auto *new_ref_list = new zero_chain_list;
83 std::vector<vtol_zero_chain*>* ptr_list = this->outside_boundary_compute_zero_chains();
84
85 // copy the lists
86 for (std::vector<vtol_zero_chain*>::const_iterator ti = ptr_list->begin();
87 ti != ptr_list->end(); ++ti)
88 new_ref_list->push_back(*ti);
89
90 delete ptr_list;
91 return new_ref_list;
92 }
93
94 //: Returns a list of zero_chains of the face.
95
compute_zero_chains()96 std::vector<vtol_zero_chain *> *vtol_face::compute_zero_chains() {
97 SEL_INF(vtol_zero_chain,compute_zero_chains);
98 }
99
100 //:
101 // Returns a list of edges that make up the outside boundary of the
102 // face. All edges on any hole boundaries are \e not included.
103
outside_boundary_compute_edges()104 std::vector<vtol_edge *> *vtol_face::outside_boundary_compute_edges() {
105 OUTSIDE_BOUNDARY(vtol_edge,one_chain,compute_edges);
106 }
107
108 //---------------------------------------------------------------------------
109 //: Get the outside boundary edges
110 //---------------------------------------------------------------------------
outside_boundary_edges()111 edge_list *vtol_face::outside_boundary_edges() {
112 auto *new_ref_list = new edge_list;
113 std::vector<vtol_edge*>* ptr_list = this->outside_boundary_compute_edges();
114
115 // copy the lists
116 for (std::vector<vtol_edge*>::const_iterator ti = ptr_list->begin();
117 ti != ptr_list->end(); ++ti)
118 new_ref_list->push_back(*ti);
119
120 delete ptr_list;
121 return new_ref_list;
122 }
123
124 //: Returns a list of edges on the face.
compute_edges()125 std::vector<vtol_edge *> *vtol_face::compute_edges() {
126 SEL_INF(vtol_edge,compute_edges);
127 }
128
129 //: Returns a list of one_chains that make up the outside boundary of the face.
130
outside_boundary_one_chains()131 one_chain_list *vtol_face::outside_boundary_one_chains() {
132 std::vector<vtol_one_chain*>* ptr_list= outside_boundary_compute_one_chains();
133 auto *ref_list= new one_chain_list;
134
135 for (std::vector<vtol_one_chain*>::const_iterator i=ptr_list->begin();
136 i!=ptr_list->end(); ++i)
137 ref_list->push_back(*i);
138
139 delete ptr_list;
140 return ref_list;
141 }
142
143 std::vector<vtol_one_chain *> *
outside_boundary_compute_one_chains()144 vtol_face::outside_boundary_compute_one_chains() {
145 COPY_INF(one_chain);
146 }
147
148 //: Returns a list of all Onechains of the face.
149
compute_one_chains()150 std::vector<vtol_one_chain *> *vtol_face::compute_one_chains() {
151 SEL_INF(vtol_one_chain,compute_one_chains);
152 }
153
154 //:
155 // Returns a list of that has itself as the only element. This method
156 // is needed for traversing the model hierarchy consistently.
157
compute_faces()158 std::vector<vtol_face *> *vtol_face::compute_faces() { LIST_SELF(vtol_face); }
159
160 //: Returns a list of all the two_chains which contain the vtol_face.
compute_two_chains()161 std::vector<vtol_two_chain *> *vtol_face::compute_two_chains() {
162 SEL_SUP(vtol_two_chain,compute_two_chains);
163 }
164
165 //: Returns a list of all the blocks that contain the vtol_face.
166
compute_blocks()167 std::vector<vtol_block *> *vtol_face::compute_blocks() {
168 SEL_SUP(vtol_block,compute_blocks);
169 }
170
171 //---------------------------------------------------------------------------
172 //: Does `this' share an edge with `f' ?
173 // Comparison of edge pointers, not geometric values
174 //---------------------------------------------------------------------------
shares_edge_with(vtol_face_sptr const & f)175 bool vtol_face::shares_edge_with(vtol_face_sptr const& f)
176 {
177 edge_list thised; this->edges(thised);
178 edge_list fedges; f->edges(fedges);
179 for (edge_list::const_iterator ei1=thised.begin(); ei1!=thised.end(); ++ei1)
180 for (edge_list::const_iterator ei2=fedges.begin(); ei2!=fedges.end(); ++ei2)
181 if ((*ei1)==(*ei2)) return true;
182 return false;
183 }
184
185 //:
186 // Links new_vtol_one_chain as an inferior of the vtol_face and returns True if
187 // successful. This method will be replacing all calls to add_edge_loop().
188
add_one_chain(vtol_one_chain_sptr const & new_vtol_one_chain)189 void vtol_face::add_one_chain(vtol_one_chain_sptr const& new_vtol_one_chain)
190 {
191 // require
192 assert(new_vtol_one_chain->contains_sub_chains());
193
194 link_inferior(new_vtol_one_chain);
195 }
196
197 #if 1 // deprecated
add_one_chain(vtol_one_chain & new_vtol_one_chain)198 void vtol_face::add_one_chain(vtol_one_chain &new_vtol_one_chain)
199 {
200 std::cerr << "Warning: deprecated form of vtol_face::add_one_chain()\n";
201 assert(new_vtol_one_chain.contains_sub_chains());
202
203 link_inferior(&new_vtol_one_chain);
204 }
205 #endif
206
207 //: deep equality check on faces. uses fuzzy equal on vertices.
208 //
209
operator ==(const vtol_face & other) const210 bool vtol_face::operator==(const vtol_face &other) const
211 {
212 if (this==&other) return true;
213
214 if (numinf()!=other.numinf())
215 return false;
216
217 if (!compare_geometry(other))
218 return false;
219
220 topology_list::const_iterator ti1;
221 topology_list::const_iterator ti2;
222
223 for (ti1=inferiors()->begin(),ti2=other.inferiors()->begin(); ti1!=inferiors()->end(); ++ti1,++ti2)
224 if (!(*(*ti1)== *(*ti2)))
225 return false;
226
227 return true;
228 }
229
230 //---------------------------------------------------------------------------
231 //: Spatial object equality
232 //---------------------------------------------------------------------------
operator ==(const vsol_spatial_object_2d & obj) const233 bool vtol_face::operator==(const vsol_spatial_object_2d& obj) const
234 {
235 return
236 obj.cast_to_topology_object() &&
237 obj.cast_to_topology_object()->cast_to_face() &&
238 *this == *obj.cast_to_topology_object()->cast_to_face();
239 }
240
241 //: Returns the ith inferior vtol_one_chain of the vtol_face.
242
get_one_chain(int which)243 vtol_one_chain_sptr vtol_face::get_one_chain(int which)
244 {
245 assert((unsigned int)which < inferiors()->size());
246 if ((unsigned int)which < inferiors()->size())
247 return (inferiors_[which])->cast_to_one_chain();
248 else
249 {
250 std::cerr << "Tried to get bad edge_loop from face\n";
251 return nullptr;
252 }
253 }
254
255 //: Returns the first inferior vtol_one_chain of the vtol_face (the boundary onechain).
256
get_boundary_cycle()257 vtol_one_chain_sptr vtol_face::get_boundary_cycle() {
258 // The outside boundary vtol_one_chain will *always*
259 // be the first one chain in the inferiors
260 // list.
261 return get_one_chain(0);
262 }
263
264 //---------------------------------------------------------------------------
265 //: Adds a new hole to the face
266 //---------------------------------------------------------------------------
add_hole_cycle(vtol_one_chain_sptr new_hole)267 bool vtol_face::add_hole_cycle(vtol_one_chain_sptr new_hole)
268 {
269 vtol_one_chain_sptr onech=get_boundary_cycle();
270
271 if (onech)
272 {
273 onech->link_chain_inferior(new_hole);
274 return true;
275 }
276 else
277 return false;
278 }
279
280 // Returns a list of the one_chains that make up the holes of the vtol_face.
281
get_hole_cycles()282 one_chain_list *vtol_face::get_hole_cycles() {
283 auto * result=new one_chain_list;
284
285 topology_list::const_iterator ii;
286 for (ii=inferiors()->begin();ii!=inferiors()->end();++ii)
287 {
288 one_chain_list* templist=(*ii)->cast_to_one_chain()->inferior_one_chains();
289
290 for (one_chain_list::const_iterator oi=templist->begin();oi!=templist->end();++oi)
291 result->push_back(*oi);
292 delete templist;
293 }
294
295 return result;
296 }
297
298 //: Returns the number of edges on the vtol_face.
299 //
300
get_num_edges() const301 int vtol_face::get_num_edges() const {
302 int result=0;
303 topology_list::const_iterator ii;
304 for (ii=inferiors()->begin();ii!=inferiors()->end();++ii)
305 result+=((*ii)->cast_to_one_chain())->numinf();
306 return result;
307 }
308
309 //---------------------------------------------------------------------------
310 //: Reverse the direction of the face
311 //---------------------------------------------------------------------------
reverse_normal()312 void vtol_face::reverse_normal() {
313 topology_list::const_iterator ti;
314 for (ti=inferiors()->begin();ti!=inferiors()->end();++ti)
315 (*ti)->cast_to_one_chain()->reverse_directions();
316 // compute_normal();
317 }
318
319 //:
320 // This method describes the data members of the vtol_face including the
321 // Inferiors. The blanking argument is used to indent the output in
322 // a clear fashion.
323
describe(std::ostream & strm,int blanking) const324 void vtol_face::describe(std::ostream &strm,
325 int blanking) const
326 {
327 for (int j=0; j<blanking; ++j) strm << ' ';
328 print();
329 for (unsigned int i=0;i<inferiors()->size();++i)
330 {
331 if ((inferiors_[i])->cast_to_one_chain()!=nullptr)
332 (inferiors_[i])->cast_to_one_chain()->describe(strm,blanking);
333 else
334 std::cout << "*** Odd inferior for a face\n";
335 }
336 }
337
338 //:
339 // This method prints out a simple text representation for the vtol_face which
340 // includes its address in memory.
print(std::ostream & strm) const341 void vtol_face::print(std::ostream &strm) const
342 {
343 strm << "<vtol_face ";
344
345 topology_list::const_iterator ii;
346 for (ii=inferiors()->begin();ii!= inferiors()->end();++ii)
347 {
348 strm << ' ' << (*ii)->inferiors()->size();
349 }
350 strm << " " << (void const *) this << ">\n";
351 }
352
353 //-------------------------------------------------------------
354 //: Update the bounding box, a member of vsol_spatial_object_2d.
355 // The algorithm uses the bounding boxes of the vtol_edge(s) forming
356 // the boundary of the face.
compute_bounding_box() const357 void vtol_face::compute_bounding_box() const
358 {
359 this->empty_bounding_box();
360 edge_list edges; this->edges(edges);
361 for (auto & edge : edges)
362 this->add_to_bounding_box(edge->get_bounding_box());
363 }
364
365 //: This method determines if a vtol_face is a hole of another vtol_face.
IsHoleP() const366 bool vtol_face::IsHoleP() const
367 {
368 edge_list* edges = const_cast<vtol_face*>(this)->outside_boundary_edges();
369 if (edges->empty()) {
370 delete edges;
371 return false;
372 }
373 vtol_edge_sptr e = edges->front();
374 delete edges;
375 std::list<vtol_topology_object*> const* chains = e->superiors_list();
376 for (auto chain : *chains)
377 if (chain->cast_to_one_chain()->numsup() > 0)
378 return true;
379 return false;
380 }
381