Line data Source code
1 : /*
2 : * Copyright (c) 2009-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : ////////////////////////////////////////////////////////////////////////
34 : ////////////////////////////////////////////////////////////////////////
35 : /*
36 : * In this file the the grids connectivity-management is implemented.
37 : * The methods change_vertex_options(...), change_edge_options, ...
38 : * attach and detach Containers to vertices, edges, ... in order to
39 : * store associated elements, as specified in the passed options.
40 : * The generated data can be accessed through Grids
41 : * get_associated_edges, get_associated_faces, ... methods later on.
42 : *
43 : * New edges, faces and volumes have to be registered with other objects
44 : * directly after creation. For this task the methods
45 : * register_edge, register_face, ... are supplied.
46 : * On the other hand Grid has to update connectivity information, as
47 : * soon as grid-elements are removed. for these tasks the methods
48 : * unregister_edge, unregister_face, ... are supplied.
49 : */
50 : ////////////////////////////////////////////////////////////////////////
51 : ////////////////////////////////////////////////////////////////////////
52 :
53 :
54 : #include <algorithm>
55 : #include "grid.h"
56 : #include "grid_util.h"
57 : #include "common/common.h"
58 : #include "common/profiler/profiler.h"
59 :
60 : using namespace std;
61 :
62 : ////////////////////////////////////////////////////////////////////////
63 : //define PROFILE_GRID_CONNECTION_MANAGMENT if you want to profile
64 : //the code below.
65 : //#define PROFILE_GRID_CONNECTION_MANAGMENT
66 : #ifdef PROFILE_GRID_CONNECTION_MANAGMENT
67 : #define GCM_PROFILE_FUNC() PROFILE_FUNC()
68 : #define GCM_PROFILE(name) PROFILE_BEGIN(name)
69 : #define GCM_PROFILE_END() PROFILE_END()
70 : #else
71 : #define GCM_PROFILE_FUNC()
72 : #define GCM_PROFILE(name)
73 : #define GCM_PROFILE_END()
74 : #endif
75 :
76 :
77 : ////////////////////////////////////////////////////////////////////////
78 : /// this macro helps calling callbacks of different observers.
79 : /**
80 : * Be sure that callback is a complete function call - including parameters.
81 : */
82 : #define NOTIFY_OBSERVERS(observerContainer, callback) {for(Grid::ObserverContainer::iterator iter = observerContainer.begin(); iter != observerContainer.end(); iter++) (*iter)->callback;}
83 : #define NOTIFY_OBSERVERS_REVERSE(observerContainer, callback) {for(Grid::ObserverContainer::reverse_iterator iter = observerContainer.rbegin(); iter != observerContainer.rend(); iter++) (*iter)->callback;}
84 :
85 : ////////////////////////////////////////////////////////////////////////
86 : /// a useful macro that checks if a set of options contains the specified option.
87 : #define OPTIONS_CONTAIN_OPTION(options, option) (((options) & (option)) == (option))
88 :
89 :
90 : namespace ug
91 : {
92 :
93 : ////////////////////////////////////////////////////////////////////////
94 : ////////////////////////////////////////////////////////////////////////
95 : // VERTICES
96 : /// creates and removes connectivity data, as specified in optsNew.
97 3 : void Grid::register_vertex(Vertex* v, GridObject* pParent)
98 : {
99 : GCM_PROFILE_FUNC();
100 :
101 : // store the element and register it at the pipe.
102 3 : m_vertexElementStorage.m_attachmentPipe.register_element(v);
103 3 : m_vertexElementStorage.m_sectionContainer.insert(v, v->container_section());
104 :
105 : // assign the hash-value
106 : assign_hash_value(v);
107 :
108 : GCM_PROFILE(GCM_notify_vertex_observers);
109 : // inform observers about the creation
110 3 : NOTIFY_OBSERVERS(m_vertexObservers, vertex_created(this, v, pParent));
111 : GCM_PROFILE_END();
112 3 : }
113 :
114 0 : void Grid::register_and_replace_element(Vertex* v, Vertex* pReplaceMe)
115 : {
116 0 : m_vertexElementStorage.m_attachmentPipe.register_element(v);
117 0 : m_vertexElementStorage.m_sectionContainer.insert(v, v->container_section());
118 :
119 : // assign the hash-value
120 : assign_hash_value(v);
121 :
122 : // pass on values
123 0 : pass_on_values(pReplaceMe, v);
124 :
125 : // inform observers about the creation
126 0 : NOTIFY_OBSERVERS(m_vertexObservers, vertex_created(this, v, pReplaceMe, true));
127 : // inform observers about the deletion
128 0 : NOTIFY_OBSERVERS_REVERSE(m_vertexObservers,
129 : vertex_to_be_erased(this, pReplaceMe, v));
130 :
131 : // all edges, faces and volumes associated with pReplaceMe have to be updated.
132 : // the options in GRIDOPT_VERTEXCENTRIC_INTERCONNECTION have to be enabled.
133 : // we do this per element only, to avoid unnecessary memory overhead.
134 :
135 : // update edges
136 0 : if(num_edges()){
137 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES)){
138 : LOG("WARNING in Grid::register_and_replace_element(...) - Vertex: autoenabling grid-option VRTOPT_STORE_ASSOCIATED_EDGES.");
139 0 : enable_options(VRTOPT_STORE_ASSOCIATED_EDGES);
140 : }
141 :
142 0 : for(AssociatedEdgeIterator iter = associated_edges_begin(pReplaceMe);
143 0 : iter != associated_edges_end(pReplaceMe); ++iter)
144 : {
145 0 : Edge* e = *iter;
146 : // replace the vertex and push e into v's associated edges.
147 0 : for(uint i = 0; i < 2; ++i)
148 : {
149 0 : if(e->vertex(i) == pReplaceMe)
150 : e->set_vertex(i, v);
151 : }
152 :
153 0 : m_aaEdgeContainerVERTEX[v].push_back(e);
154 : }
155 : }
156 :
157 : // update faces
158 0 : if(num_faces()){
159 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES)){
160 : LOG("WARNING in Grid::register_and_replace_element(...) - Vertex: autoenabling grid-option VRTOPT_STORE_ASSOCIATED_FACES.");
161 0 : enable_options(VRTOPT_STORE_ASSOCIATED_FACES);
162 : }
163 :
164 0 : for(AssociatedFaceIterator iter = associated_faces_begin(pReplaceMe);
165 0 : iter != associated_faces_end(pReplaceMe); ++iter)
166 : {
167 0 : Face* f = *iter;
168 : // replace the vertex and push f into v's associated faces.
169 0 : uint numVrts = f->num_vertices();
170 0 : Face::ConstVertexArray vrts = f->vertices();
171 0 : for(uint i = 0; i < numVrts; ++i)
172 : {
173 0 : if(vrts[i] == pReplaceMe)
174 0 : f->set_vertex(i, v);
175 : }
176 :
177 0 : m_aaFaceContainerVERTEX[v].push_back(f);
178 : }
179 : }
180 :
181 : // update volumes
182 0 : if(num_volumes()){
183 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES)){
184 : LOG("WARNING in Grid::register_and_replace_element(...) - Vertex: autoenabling grid-option VRTOPT_STORE_ASSOCIATED_VOLUMES.");
185 0 : enable_options(VRTOPT_STORE_ASSOCIATED_VOLUMES);
186 : }
187 :
188 0 : for(AssociatedVolumeIterator iter = associated_volumes_begin(pReplaceMe);
189 0 : iter != associated_volumes_end(pReplaceMe); ++iter)
190 : {
191 0 : Volume* vol = *iter;
192 : // replace the vertex and push vol into v's associated volumes.
193 0 : uint numVrts = vol->num_vertices();
194 0 : Volume::ConstVertexArray vrts = vol->vertices();
195 0 : for(uint i = 0; i < numVrts; ++i)
196 : {
197 0 : if(vrts[i] == pReplaceMe)
198 0 : vol->set_vertex(i, v);
199 : }
200 :
201 0 : m_aaVolumeContainerVERTEX[v].push_back(vol);
202 : }
203 : }
204 :
205 : // clear the containers of pReplaceMe
206 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
207 : m_aaEdgeContainerVERTEX[pReplaceMe].clear();
208 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
209 : m_aaFaceContainerVERTEX[pReplaceMe].clear();
210 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
211 : m_aaVolumeContainerVERTEX[pReplaceMe].clear();
212 :
213 : // remove pReplaceMe
214 0 : m_vertexElementStorage.m_attachmentPipe.unregister_element(pReplaceMe);
215 0 : m_vertexElementStorage.m_sectionContainer.erase(get_iterator(pReplaceMe), pReplaceMe->container_section());
216 0 : delete pReplaceMe;
217 0 : }
218 :
219 3 : void Grid::unregister_vertex(Vertex* v)
220 : {
221 : // notify observers that the vertex is being erased
222 3 : NOTIFY_OBSERVERS_REVERSE(m_vertexObservers, vertex_to_be_erased(this, v));
223 :
224 : // perform some checks in order to assert grid consistency.
225 : // all edges, faces and volume referencing this vertex have to be erased.
226 :
227 3 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
228 : {
229 : // if there are edges this option has to be enabled!
230 3 : if(num_edges() > 0)
231 : {
232 : LOG("WARNING in Grid::unregister_vertex(...): auto-enabling VRTOPT_STORE_ASSOCIATED_EDGES." << std::endl);
233 0 : vertex_store_associated_edges(true);
234 : }
235 : }
236 :
237 3 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
238 : {
239 : // if there are faces we have to consider the following
240 3 : if(num_faces() > 0)
241 : {
242 : // if edges store associated faces and if faces auto-generate edges, then
243 : // nothing has to be performed here.
244 0 : if(!(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES)
245 0 : && option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)))
246 : {
247 : // since adjacent faces have to be removed, we have to enable VRTOPT_STORE_ASSOCIATED_FACES
248 : LOG("WARNING in Grid::unregister_vertex(...): auto-enabling VRTOPT_STORE_ASSOCIATED_FACES." << std::endl);
249 0 : vertex_store_associated_faces(true);
250 : }
251 : }
252 : }
253 :
254 3 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
255 : {
256 : // if there are volumes we have to consider the following
257 3 : if(num_volumes() > 0)
258 : {
259 : // if edges store associated volumes and volumes auto-generate edges or
260 : // if faces store associated volumes and volumes auto-generate faces then
261 : // nothing has to be performed here.
262 0 : bool cond1 = option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES) &&
263 0 : option_is_enabled(VOLOPT_AUTOGENERATE_EDGES);
264 0 : bool cond2 = option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES) &&
265 0 : option_is_enabled(VOLOPT_AUTOGENERATE_FACES);
266 :
267 0 : if(!(cond1 || cond2))
268 : {
269 : // since we have to remove adjacent volumes we have to enable VRTOPT_STORE_ASSOCIATED_VOLUMES
270 : LOG("WARNING in Grid::unregister_vertex(...): auto-enabling VRTOPT_STORE_ASSOCIATED_VOLUMES." << std::endl);
271 0 : vertex_store_associated_volumes(true);
272 : }
273 : }
274 : }
275 :
276 : // remove associated volumes
277 3 : if(num_volumes() > 0)
278 : {
279 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
280 : {
281 : // remove associated volumes. Make sure that there are no problems
282 : // when volumes try to unregister from the vertex.
283 : VolumeContainer vols;
284 0 : vols.swap(m_aaVolumeContainerVERTEX[v]);
285 :
286 0 : for(VolumeContainer::iterator iter = vols.begin(); iter != vols.end();)
287 : {
288 0 : Volume* eraseVol = *iter;
289 : ++iter;
290 0 : erase(eraseVol);
291 : }
292 0 : }
293 : }
294 :
295 : // remove associated faces
296 3 : if(num_faces() > 0)
297 : {
298 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
299 : {
300 : // remove all associated faces. Make sure that there are no problems
301 : // when faces try to unregister from the vertex.
302 : FaceContainer faces;
303 0 : faces.swap(m_aaFaceContainerVERTEX[v]);
304 0 : for(FaceContainer::iterator iter = faces.begin(); iter != faces.end();)
305 : {
306 0 : Face* eraseFace = *iter;
307 : ++iter;
308 0 : erase(eraseFace);
309 : }
310 0 : }
311 : }
312 :
313 : // remove associated edges
314 3 : if(num_edges() > 0)
315 : {
316 : assert(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES) && "unexpected internal error in Grid::unregister_vertex - rae.");
317 : // remove all associated edges. Make sure that there are no problems
318 : // when edges try to unregister from the vertex.
319 : EdgeContainer edges;
320 0 : edges.swap(m_aaEdgeContainerVERTEX[v]);
321 0 : for(EdgeContainer::iterator iter = edges.begin(); iter != edges.end();)
322 : {
323 0 : Edge* eraseEdge = *iter;
324 : ++iter;
325 0 : erase(eraseEdge);
326 : }
327 0 : }
328 :
329 : // remove the element from the storage
330 3 : m_vertexElementStorage.m_sectionContainer.erase(get_iterator(v), v->container_section());
331 3 : m_vertexElementStorage.m_attachmentPipe.unregister_element(v);
332 3 : }
333 :
334 3 : void Grid::change_vertex_options(uint optsNew)
335 : {
336 : // check if associated edge information has to be created or removed.
337 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VRTOPT_STORE_ASSOCIATED_EDGES))
338 : {
339 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES)){
340 2 : vertex_store_associated_edges(true);
341 : }
342 : }
343 : else
344 : {
345 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES)){
346 1 : vertex_store_associated_edges(false);
347 : }
348 : }
349 :
350 : // check if associated face information has to be created or removed.
351 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VRTOPT_STORE_ASSOCIATED_FACES))
352 : {
353 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
354 2 : vertex_store_associated_faces(true);
355 : }
356 : else
357 : {
358 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
359 1 : vertex_store_associated_faces(false);
360 : }
361 :
362 : // check if associated volume information has to be created or removed.
363 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VRTOPT_STORE_ASSOCIATED_VOLUMES))
364 : {
365 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
366 2 : vertex_store_associated_volumes(true);
367 : }
368 : else
369 : {
370 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
371 1 : vertex_store_associated_volumes(false);
372 : }
373 3 : }
374 :
375 3 : void Grid::vertex_store_associated_edges(bool bStoreIt)
376 : {
377 3 : if(bStoreIt)
378 : {
379 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
380 : {
381 : // store associated edges
382 2 : attach_to_vertices(m_aEdgeContainer);
383 2 : m_aaEdgeContainerVERTEX.access(*this, m_aEdgeContainer);
384 :
385 : // iterate through all edges and store them in the associated vertices
386 2 : for(EdgeIterator iter = this->edges_begin(); iter != this->edges_end(); iter++)
387 : {
388 0 : Edge* e = *iter;
389 0 : m_aaEdgeContainerVERTEX[e->vertex(0)].push_back(e);
390 0 : m_aaEdgeContainerVERTEX[e->vertex(1)].push_back(e);
391 : }
392 :
393 2 : m_options |= VRTOPT_STORE_ASSOCIATED_EDGES;
394 : }
395 : }
396 : else
397 : {
398 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
399 : {
400 1 : detach_from_vertices(m_aEdgeContainer);
401 1 : m_options &= (~VRTOPT_STORE_ASSOCIATED_EDGES);
402 : }
403 : }
404 3 : }
405 :
406 3 : void Grid::vertex_store_associated_faces(bool bStoreIt)
407 : {
408 3 : if(bStoreIt)
409 : {
410 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
411 : {
412 : // store associated faces
413 2 : attach_to_vertices(m_aFaceContainer);
414 2 : m_aaFaceContainerVERTEX.access(*this, m_aFaceContainer);
415 :
416 : // iterator through all faces and store them in the referenced vertices
417 2 : for(FaceIterator iter = this->faces_begin(); iter != this->faces_end(); iter++)
418 : {
419 0 : Face* f = *iter;
420 0 : int numVrts = f->num_vertices();
421 0 : Face::ConstVertexArray vrts = f->vertices();
422 0 : for(int i = 0; i < numVrts; i++)
423 0 : m_aaFaceContainerVERTEX[vrts[i]].push_back(f);
424 : }
425 :
426 : // store the option
427 2 : m_options |= VRTOPT_STORE_ASSOCIATED_FACES;
428 : }
429 : }
430 : else
431 : {
432 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
433 : {
434 1 : detach_from_vertices(m_aFaceContainer);
435 1 : m_options &= (~VRTOPT_STORE_ASSOCIATED_FACES);
436 : }
437 : }
438 3 : }
439 :
440 3 : void Grid::vertex_store_associated_volumes(bool bStoreIt)
441 : {
442 3 : if(bStoreIt)
443 : {
444 2 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
445 : {
446 : // store associated volumes
447 2 : attach_to_vertices(m_aVolumeContainer);
448 2 : m_aaVolumeContainerVERTEX.access(*this, m_aVolumeContainer);
449 :
450 : // iterator through all faces and store them in the referenced vertices
451 2 : for(VolumeIterator iter = this->volumes_begin(); iter != this->volumes_end(); iter++)
452 : {
453 0 : Volume* v = *iter;
454 0 : int numVrts = v->num_vertices();
455 0 : Volume::ConstVertexArray vrts = v->vertices();
456 0 : for(int i = 0; i < numVrts; i++)
457 0 : m_aaVolumeContainerVERTEX[vrts[i]].push_back(v);
458 : }
459 :
460 : // store the option
461 2 : m_options |= VRTOPT_STORE_ASSOCIATED_VOLUMES;
462 : }
463 : }
464 : else
465 : {
466 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
467 : {
468 1 : detach_from_vertices(m_aVolumeContainer);
469 1 : m_options &= (~VRTOPT_STORE_ASSOCIATED_VOLUMES);
470 : }
471 : }
472 3 : }
473 :
474 : ////////////////////////////////////////////////////////////////////////
475 : ////////////////////////////////////////////////////////////////////////
476 : // EDGES
477 : /// creates and removes connectivity data, as specified in optsNew.
478 3 : void Grid::register_edge(Edge* e, GridObject* pParent,
479 : Face* createdByFace, Volume* createdByVol)
480 : {
481 : GCM_PROFILE_FUNC();
482 :
483 : // store the element and register it at the pipe.
484 3 : m_edgeElementStorage.m_attachmentPipe.register_element(e);
485 3 : m_edgeElementStorage.m_sectionContainer.insert(e, e->container_section());
486 :
487 : // register edge at vertices, faces and volumes, if the according options are enabled.
488 3 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
489 : {
490 3 : m_aaEdgeContainerVERTEX[e->vertex(0)].push_back(e);
491 3 : m_aaEdgeContainerVERTEX[e->vertex(1)].push_back(e);
492 : }
493 :
494 : // register edges at faces and vice versa
495 : // this is only necessary, if faces do not autogenerate edges
496 3 : if(createdByFace != NULL){
497 : // e has been autogenerated by f. We thus have don't have to check
498 : // for other faces. e is already contained in f's edge-container.
499 3 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
500 0 : m_aaFaceContainerEDGE[e].push_back(createdByFace);
501 : }
502 : else
503 : {
504 0 : if(!option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){
505 : GCM_PROFILE(GCM_reg_edge_processing_faces);
506 : int switchVar = 0; // this var will be used to determine what to register where.
507 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
508 : switchVar = 1;
509 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
510 0 : switchVar += 2;
511 :
512 0 : if(switchVar > 0)
513 : {
514 : // find the faces that contain the edge. search the associated vertices for connected faces.
515 0 : AssociatedFaceIterator iterStart = associated_faces_begin(e->vertex(0));
516 0 : AssociatedFaceIterator iterEnd = associated_faces_end(e->vertex(0));
517 :
518 0 : EdgeDescriptor ed;
519 0 : for(AssociatedFaceIterator iter = iterStart; iter != iterEnd; iter++)
520 : {
521 0 : Face* f = *iter;
522 : uint numEdges = f->num_edges();
523 0 : for(uint i = 0; i < numEdges; ++i)
524 : {
525 0 : f->edge_desc(i, ed);
526 0 : if(CompareVertices(e, &ed))
527 : {
528 : // f contains e
529 0 : switch(switchVar)
530 : {
531 0 : case 1: m_aaFaceContainerEDGE[e].push_back(f);
532 : break;
533 0 : case 2: m_aaEdgeContainerFACE[f].push_back(e);
534 : break;
535 0 : case 3: m_aaFaceContainerEDGE[e].push_back(f);
536 0 : m_aaEdgeContainerFACE[f].push_back(e);
537 : break;
538 : }
539 : }
540 : }
541 : }
542 : }
543 : }
544 : }
545 :
546 : // register edges at volumes and vice versa
547 3 : if(createdByVol != NULL){
548 : // e was at least indirectly created by a volume.
549 : // We thus do not have to check for other volumes.
550 : // e is already registered in v's edge-container.
551 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
552 0 : m_aaVolumeContainerEDGE[e].push_back(createdByVol);
553 : }
554 : else
555 : {
556 3 : bool ignoreVolumes = option_is_enabled(VOLOPT_AUTOGENERATE_EDGES)
557 3 : || (option_is_enabled(VOLOPT_AUTOGENERATE_FACES)
558 3 : && option_is_enabled(FACEOPT_AUTOGENERATE_EDGES));
559 :
560 : if(!ignoreVolumes){
561 : GCM_PROFILE(GCM_reg_edge_processing_volumes);
562 : int switchVar = 0; // this var will be used to determine what to register where.
563 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
564 : switchVar = 1;
565 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
566 0 : switchVar += 2;
567 :
568 0 : if(switchVar > 0)
569 : {
570 : // find the volumes that contain the edge.
571 0 : AssociatedVolumeIterator iterStart = associated_volumes_begin(e->vertex(0));
572 0 : AssociatedVolumeIterator iterEnd = associated_volumes_end(e->vertex(0));
573 :
574 0 : for(AssociatedVolumeIterator iter = iterStart; iter != iterEnd; iter++)
575 : {
576 0 : Volume* v = *iter;
577 0 : uint numEdges = v->num_edges();
578 0 : for(uint i = 0; i < numEdges; ++i)
579 : {
580 0 : EdgeDescriptor ed;
581 0 : v->edge_desc(i, ed);
582 0 : if(CompareVertices(e, &ed))
583 : {
584 : // f contains e
585 0 : switch(switchVar)
586 : {
587 0 : case 1: m_aaVolumeContainerEDGE[e].push_back(v);
588 : break;
589 0 : case 2: m_aaEdgeContainerVOLUME[v].push_back(e);
590 : break;
591 0 : case 3: m_aaVolumeContainerEDGE[e].push_back(v);
592 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
593 : break;
594 : }
595 : }
596 : }
597 : }
598 : }
599 : }
600 : }
601 :
602 : GCM_PROFILE(GCM_notify_edge_observers);
603 : // inform observers about the creation
604 3 : NOTIFY_OBSERVERS(m_edgeObservers, edge_created(this, e, pParent));
605 : GCM_PROFILE_END();
606 3 : }
607 :
608 0 : void Grid::register_and_replace_element(Edge* e, Edge* pReplaceMe)
609 : {
610 : // store the element and register it at the pipe.
611 0 : m_edgeElementStorage.m_attachmentPipe.register_element(e);
612 0 : m_edgeElementStorage.m_sectionContainer.insert(e, e->container_section());
613 :
614 0 : pass_on_values(pReplaceMe, e);
615 :
616 : // assign vertices
617 0 : e->set_vertex(0, pReplaceMe->vertex(0));
618 0 : e->set_vertex(1, pReplaceMe->vertex(1));
619 :
620 : // inform observers about the creation
621 0 : NOTIFY_OBSERVERS(m_edgeObservers, edge_created(this, e, pReplaceMe, true));
622 : // inform observers about the deletion
623 0 : NOTIFY_OBSERVERS_REVERSE(m_edgeObservers, edge_to_be_erased(this, pReplaceMe, e));
624 :
625 : // check if vertices, faces and volumes reference pReplaceMe.
626 : // if so, correct those references.
627 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
628 : {
629 0 : for(uint i = 0; i < 2; ++i)
630 0 : replace(associated_edges_begin(e->vertex(i)),
631 0 : associated_edges_end(e->vertex(i)),
632 : pReplaceMe, e);
633 : }
634 :
635 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
636 : {
637 : // collect all faces that are associated with pReplaceMe
638 : vector<Face*> vFaces;
639 0 : CollectFaces(vFaces, *this, pReplaceMe);
640 0 : for(uint i = 0; i < vFaces.size(); ++i)
641 0 : replace(associated_edges_begin(vFaces[i]),
642 : associated_edges_end(vFaces[i]),
643 : pReplaceMe, e);
644 0 : }
645 :
646 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
647 : {
648 : // collect all volumes that are associated with pReplaceMe
649 : vector<Volume*> vVolumes;
650 0 : CollectVolumes(vVolumes, *this, pReplaceMe);
651 0 : for(uint i = 0; i < vVolumes.size(); ++i)
652 0 : replace(associated_edges_begin(vVolumes[i]),
653 : associated_edges_end(vVolumes[i]),
654 : pReplaceMe, e);
655 0 : }
656 :
657 : // now we have to copy all associated elements of pReplaceMe to e
658 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
659 : {
660 0 : m_aaFaceContainerEDGE[e].assign(associated_faces_begin(pReplaceMe),
661 : associated_faces_end(pReplaceMe));
662 : m_aaFaceContainerEDGE[pReplaceMe].clear();
663 : }
664 :
665 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
666 : {
667 0 : m_aaVolumeContainerEDGE[e].assign(associated_volumes_begin(pReplaceMe),
668 : associated_volumes_end(pReplaceMe));
669 : m_aaVolumeContainerEDGE[pReplaceMe].clear();
670 : }
671 :
672 : // remove the element from the storage and delete it.
673 0 : m_edgeElementStorage.m_sectionContainer.erase(get_iterator(pReplaceMe), pReplaceMe->container_section());
674 0 : m_edgeElementStorage.m_attachmentPipe.unregister_element(pReplaceMe);
675 0 : delete pReplaceMe;
676 0 : }
677 :
678 3 : void Grid::unregister_edge(Edge* e)
679 : {
680 : // notify observers that the edge is being erased
681 3 : NOTIFY_OBSERVERS_REVERSE(m_edgeObservers, edge_to_be_erased(this, e));
682 :
683 : // delete associated faces or unregister from associated faces
684 3 : if(num_volumes() > 0)
685 : {
686 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_EDGES) ||
687 0 : option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
688 : {
689 : // check if anything has to be performed at all.
690 0 : if(!(option_is_enabled(VOLOPT_AUTOGENERATE_FACES) &&
691 0 : option_is_enabled(FACEOPT_AUTOGENERATE_EDGES) &&
692 0 : option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES) &&
693 0 : option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES)))
694 : {
695 : // we have to perform something...
696 : vector<Volume*> vVolumes;
697 0 : CollectVolumes(vVolumes, *this, e);
698 : vector<Volume*>::iterator vIter = vVolumes.begin();
699 :
700 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_EDGES))
701 : {
702 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
703 0 : m_aaVolumeContainerEDGE[e].clear();
704 :
705 : // erase the collected volumes
706 0 : while(vIter != vVolumes.end())
707 : {
708 0 : Volume* eraseVol = *vIter;
709 : ++vIter;
710 0 : erase(eraseVol);
711 : }
712 : }
713 : else
714 : {
715 : // unlink from the collected volumes
716 0 : for(; vIter != vVolumes.end(); ++vIter)
717 : {
718 0 : Volume* v = *vIter;
719 : // find the edge and remove the corresponding entry
720 0 : EdgeContainer::iterator iter = find(m_aaEdgeContainerVOLUME[v].begin(),
721 : m_aaEdgeContainerVOLUME[v].end(), e);
722 0 : if(iter != m_aaEdgeContainerVOLUME[v].end())
723 : m_aaEdgeContainerVOLUME[v].erase(iter);
724 : }
725 : }
726 0 : }
727 : }
728 : }
729 :
730 : // delete associated faces or unregister from associated faces
731 3 : if(num_faces() > 0)
732 : {
733 0 : if(option_is_enabled(FACEOPT_AUTOGENERATE_EDGES) ||
734 0 : option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
735 : {
736 : vector<Face*> vFaces;
737 0 : CollectFaces(vFaces, *this, e);
738 : vector<Face*>::iterator fIter = vFaces.begin();
739 :
740 0 : if(option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
741 : {
742 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
743 0 : m_aaFaceContainerEDGE[e].clear();
744 :
745 : // erase the collected faces.
746 0 : while(fIter != vFaces.end())
747 : {
748 0 : Face* eraseFace = *fIter;
749 : ++fIter;
750 0 : erase(eraseFace);
751 : }
752 : }
753 : else
754 : {
755 : // unlink
756 0 : for(; fIter != vFaces.end(); ++fIter)
757 : {
758 0 : Face* f = *fIter;
759 : // find the matching entry and remove it
760 0 : EdgeContainer::iterator iter = find(m_aaEdgeContainerFACE[f].begin(),
761 : m_aaEdgeContainerFACE[f].end(), e);
762 0 : if(iter != m_aaEdgeContainerFACE[f].end())
763 : m_aaEdgeContainerFACE[f].erase(iter);
764 : }
765 : }
766 0 : }
767 : }
768 :
769 : // unregister from vertices
770 3 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
771 : {
772 : // iterate through the associated vertices and remove the edge from their edge-list.
773 0 : for(int i = 0; i < 2; ++i)
774 : {
775 0 : Vertex* vrt = e->vertex(i);
776 0 : EdgeContainer::iterator iter = find(m_aaEdgeContainerVERTEX[vrt].begin(),
777 : m_aaEdgeContainerVERTEX[vrt].end(), e);
778 0 : if(iter != m_aaEdgeContainerVERTEX[vrt].end())
779 0 : m_aaEdgeContainerVERTEX[e->vertex(i)].erase(iter);
780 : }
781 : }
782 :
783 : // remove the element from the storage
784 3 : m_edgeElementStorage.m_sectionContainer.erase(get_iterator(e), e->container_section());
785 3 : m_edgeElementStorage.m_attachmentPipe.unregister_element(e);
786 3 : }
787 :
788 3 : void Grid::change_edge_options(uint optsNew)
789 : {
790 : // check if associated face information has to be created or removed.
791 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, EDGEOPT_STORE_ASSOCIATED_FACES))
792 : {
793 0 : if(!option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
794 0 : edge_store_associated_faces(true);
795 : }
796 : else
797 : {
798 3 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
799 0 : edge_store_associated_faces(false);
800 : }
801 :
802 : // check if associated volume information has to be created or removed.
803 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, EDGEOPT_STORE_ASSOCIATED_VOLUMES))
804 : {
805 0 : if(!option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
806 0 : edge_store_associated_volumes(true);
807 : }
808 : else
809 : {
810 3 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
811 0 : edge_store_associated_volumes(false);
812 : }
813 3 : }
814 :
815 0 : void Grid::edge_store_associated_faces(bool bStoreIt)
816 : {
817 0 : if(bStoreIt)
818 : {
819 0 : if(!option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
820 : {
821 : // store associated faces
822 0 : attach_to_edges(m_aFaceContainer);
823 0 : m_aaFaceContainerEDGE.access(*this, m_aFaceContainer);
824 :
825 : // iterate through the faces and store them at each of their edges.
826 : // in order to perform this task at acceptable speed,
827 : // the option VRTOPT_STORE_ASSOCIATED_EDGES has to be enabled.
828 : // (This is due to the use of GetEdge(...))
829 : // if it is disabled here, we'll enable it.
830 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
831 : {
832 : LOG("WARNING in edge_store_associated_faces(...): auto-enabling VRTOPT_STORE_ASSOCIATED_EDGES." << endl);
833 0 : vertex_store_associated_edges(true);
834 : }
835 :
836 0 : for(FaceIterator iter = faces_begin(); iter != faces_end(); iter++)
837 : {
838 0 : Face* f = *iter;
839 : // iterate through the edges of the face
840 0 : int numEdges = f->num_edges();
841 0 : for(int i = 0; i < numEdges; ++i)
842 : {
843 : // get the i-th edge
844 0 : Edge* e = get_edge(f, i);
845 0 : if(e != NULL)
846 0 : m_aaFaceContainerEDGE[e].push_back(f);
847 : }
848 : }
849 : // store the option
850 0 : m_options |= EDGEOPT_STORE_ASSOCIATED_FACES;
851 : }
852 : }
853 : else
854 : {
855 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
856 : {
857 : // detach edge-face connections
858 0 : detach_from_edges(m_aFaceContainer);
859 0 : m_options &= (~EDGEOPT_STORE_ASSOCIATED_FACES);
860 : }
861 : }
862 0 : }
863 :
864 0 : void Grid::edge_store_associated_volumes(bool bStoreIt)
865 : {
866 0 : if(bStoreIt)
867 : {
868 0 : if(!option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
869 : {
870 : // store associated faces
871 0 : attach_to_edges(m_aVolumeContainer);
872 0 : m_aaVolumeContainerEDGE.access(*this, m_aVolumeContainer);
873 :
874 : // iterate through the volumes and store them at each of their edges.
875 : // in order to perform this task at acceptable speed,
876 : // the option VRTOPT_STORE_ASSOCIATED_VOLUMES has to be enabled.
877 : // (This is due to the use of GetEdge(...))
878 : // if it is disabled here, we'll enable it.
879 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
880 : {
881 : LOG("WARNING in Grid::edge_store_associated_volumes(...): auto-enabling VRTOPT_STORE_ASSOCIATED_VOLUMES." << endl);
882 0 : vertex_store_associated_volumes(true);
883 : }
884 :
885 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
886 : {
887 0 : Volume* v = *iter;
888 : // iterate through the edges of the volume
889 0 : int numEdges = v->num_edges();
890 0 : for(int i = 0; i < numEdges; ++i)
891 : {
892 : // get the edge-descriptor
893 0 : EdgeDescriptor ed;
894 0 : v->edge_desc(i, ed);
895 : // get the edge that is described by the EdgeDescriptor - if it exists at all.
896 0 : Edge* e = get_edge(ed);
897 0 : if(e != NULL)
898 0 : m_aaVolumeContainerEDGE[e].push_back(v);
899 : }
900 : }
901 :
902 : // store the option
903 0 : m_options |= EDGEOPT_STORE_ASSOCIATED_VOLUMES;
904 : }
905 : }
906 : else
907 : {
908 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
909 : {
910 : // detach edge-volume connections
911 0 : detach_from_edges(m_aVolumeContainer);
912 0 : m_options &= (~EDGEOPT_STORE_ASSOCIATED_VOLUMES);
913 : }
914 : }
915 0 : }
916 :
917 :
918 : ////////////////////////////////////////////////////////////////////////////////
919 : ////////////////////////////////////////////////////////////////////////////////
920 : // FACES
921 : /// creates and removes connectivity data, as specified in optsNew.
922 1 : void Grid::register_face(Face* f, GridObject* pParent, Volume* createdByVol)
923 : {
924 : GCM_PROFILE_FUNC();
925 :
926 : // store the element and register it at the pipe.
927 1 : m_faceElementStorage.m_attachmentPipe.register_element(f);
928 1 : m_faceElementStorage.m_sectionContainer.insert(f, f->container_section());
929 :
930 : // register face at vertices
931 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
932 : {
933 1 : uint numVrts = f->num_vertices();
934 1 : Face::ConstVertexArray vrts = f->vertices();
935 4 : for(uint i = 0; i < numVrts; ++i)
936 3 : m_aaFaceContainerVERTEX[vrts[i]].push_back(f);
937 : }
938 :
939 1 : bool createEdges = option_is_enabled(FACEOPT_AUTOGENERATE_EDGES);;
940 1 : const bool edgesStoreFaces = option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES);
941 1 : const bool facesStoreEdges = option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES);
942 :
943 : // make sure that the edge container is big enough to hold all edges
944 1 : if(facesStoreEdges)
945 0 : m_aaEdgeContainerFACE[f].reserve(f->num_edges());
946 :
947 : // create edges if FACEOPT_AUTOGENERATE_EDGES is enabled.
948 : // register face at associated vertices and edges if the according options are set.
949 1 : if(createEdges
950 1 : || edgesStoreFaces
951 0 : || facesStoreEdges)
952 : {
953 : GCM_PROFILE(GCM_reg_face_processing_edges);
954 : // loop through the edges of the face and check if they already exist in the grid.
955 1 : int numEdges = f->num_edges();
956 1 : EdgeDescriptor ed;
957 4 : for(int i = 0; i < numEdges; ++i)
958 : {
959 3 : f->edge_desc(i, ed);
960 3 : Edge* e = find_edge_in_associated_edges(ed.vertex(0), ed);
961 :
962 3 : if(e == NULL)
963 : {
964 3 : if(createEdges)
965 : {
966 : // create the edge - regard the parent of f as the parent of the new edge, too.
967 3 : e = f->create_edge(i);
968 :
969 3 : if(facesStoreEdges)
970 0 : m_aaEdgeContainerFACE[f].push_back(e);
971 :
972 : // register the edge
973 3 : register_edge(e, pParent, f, createdByVol);
974 : }
975 : }
976 : else
977 : {
978 : // register the face at the edge
979 0 : if(edgesStoreFaces)
980 0 : m_aaFaceContainerEDGE[e].push_back(f);
981 : // register the edge at the face.
982 0 : if(facesStoreEdges)
983 0 : m_aaEdgeContainerFACE[f].push_back(e);
984 : }
985 : }
986 : }
987 :
988 : // register face at existing volumes. find all volumes that contain face
989 : // if the option VOLOPT_AUTOGENERATE_FACES is enabled, we can ignore volumes
990 : // here anyways, since they would be associated with volumes in register_volume
991 1 : if(createdByVol != NULL){
992 : // This means that the face was autogenerated by a volume.
993 : // In this case the face is already registered in the volumes container.
994 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
995 0 : m_aaVolumeContainerFACE[f].push_back(createdByVol);
996 : }
997 : else
998 : {
999 1 : if(!option_is_enabled(VOLOPT_AUTOGENERATE_FACES)){
1000 : GCM_PROFILE(GCM_reg_face_processing_volumes);
1001 :
1002 : int switchVar = 0;
1003 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1004 : switchVar = 1;
1005 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1006 0 : switchVar += 2;
1007 :
1008 0 : if(switchVar > 0)
1009 : {
1010 : // find associated volumes of f. Don't use get_associated, since it
1011 : // may lookup m_aaVolumeContainerFACE, which we just want to update...
1012 : vector<Volume*> vVols;
1013 0 : vVols.reserve(2);
1014 :
1015 0 : CollectVolumes(vVols, *this, f, false, true);
1016 :
1017 :
1018 :
1019 0 : for(vector<Volume*>::iterator iter = vVols.begin(); iter != vVols.end(); ++iter)
1020 : {
1021 0 : Volume* v = *iter;
1022 : // v contains f
1023 0 : switch(switchVar)
1024 : {
1025 0 : case 1: m_aaVolumeContainerFACE[f].push_back(v);
1026 : break;
1027 0 : case 2: m_aaFaceContainerVOLUME[v].push_back(f);
1028 : break;
1029 0 : case 3: m_aaVolumeContainerFACE[f].push_back(v);
1030 0 : m_aaFaceContainerVOLUME[v].push_back(f);
1031 : break;
1032 : }
1033 : }
1034 0 : }
1035 : }
1036 : }
1037 :
1038 : GCM_PROFILE(GCM_notify_face_observers);
1039 : // inform observers about the creation
1040 1 : NOTIFY_OBSERVERS(m_faceObservers, face_created(this, f, pParent));
1041 : GCM_PROFILE_END();
1042 1 : }
1043 :
1044 0 : void Grid::register_and_replace_element(Face* f, Face* pReplaceMe)
1045 : {
1046 : // check that f and pReplaceMe have the same amount of vertices.
1047 0 : if(f->num_vertices() != pReplaceMe->num_vertices())
1048 : {
1049 : LOG("WARNING in Grid::register_and_replace_element(Face* f, Face* pReplaceMe): f and pReplaceMe have different numbers of vertices.");
1050 : LOG(" f has not been registered. pReplaceMe has not been replaced.");
1051 : assert(!"ERROR in Grid::register_and_replace_element(Face* f, Face* pReplaceMe): f and pReplaceMe have different numbers of vertices.");
1052 0 : return;
1053 : }
1054 :
1055 : // store the element and register it at the pipe.
1056 0 : m_faceElementStorage.m_attachmentPipe.register_element(f);
1057 0 : m_faceElementStorage.m_sectionContainer.insert(f, f->container_section());
1058 :
1059 0 : pass_on_values(pReplaceMe, f);
1060 :
1061 0 : Face::ConstVertexArray vrts = pReplaceMe->vertices();
1062 :
1063 : // assign vertices
1064 0 : uint numVrts = f->num_vertices();
1065 : {
1066 0 : for(uint i = 0; i < numVrts; ++i)
1067 0 : f->set_vertex(i, vrts[i]);
1068 : }
1069 :
1070 : // inform observers about the creation
1071 0 : NOTIFY_OBSERVERS(m_faceObservers, face_created(this, f, pReplaceMe, true));
1072 : // inform observers about the deletion
1073 0 : NOTIFY_OBSERVERS_REVERSE(m_faceObservers, face_to_be_erased(this, pReplaceMe, f));
1074 :
1075 : // check if vertices, edges and volumes reference pReplaceMe.
1076 : // if so, correct those references.
1077 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
1078 : {
1079 0 : for(uint i = 0; i < numVrts; ++i)
1080 0 : replace(associated_faces_begin(vrts[i]),
1081 0 : associated_faces_end(vrts[i]),
1082 : pReplaceMe, f);
1083 : }
1084 :
1085 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
1086 : {
1087 : // collect all edges that are associated with pReplaceMe
1088 : vector<Edge*> vEdges;
1089 0 : CollectEdges(vEdges, *this, pReplaceMe);
1090 0 : for(uint i = 0; i < vEdges.size(); ++i)
1091 0 : replace(associated_faces_begin(vEdges[i]),
1092 : associated_faces_end(vEdges[i]),
1093 : pReplaceMe, f);
1094 0 : }
1095 :
1096 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1097 : {
1098 : // collect all volumes that are associated with pReplaceMe
1099 : vector<Volume*> vVolumes;
1100 0 : CollectVolumes(vVolumes, *this, pReplaceMe);
1101 0 : for(uint i = 0; i < vVolumes.size(); ++i)
1102 0 : replace(associated_faces_begin(vVolumes[i]),
1103 : associated_faces_end(vVolumes[i]),
1104 : pReplaceMe, f);
1105 0 : }
1106 :
1107 : // now we have to copy all associated elements of pReplaceMe to f
1108 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
1109 : {
1110 0 : m_aaEdgeContainerFACE[f].assign(associated_edges_begin(pReplaceMe),
1111 : associated_edges_end(pReplaceMe));
1112 : m_aaEdgeContainerFACE[pReplaceMe].clear();
1113 : }
1114 :
1115 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1116 : {
1117 0 : m_aaVolumeContainerFACE[f].assign(associated_volumes_begin(pReplaceMe),
1118 : associated_volumes_end(pReplaceMe));
1119 : m_aaVolumeContainerFACE[pReplaceMe].clear();
1120 : }
1121 :
1122 : // remove the element from the storage and delete it.
1123 0 : m_faceElementStorage.m_sectionContainer.erase(get_iterator(pReplaceMe), pReplaceMe->container_section());
1124 0 : m_faceElementStorage.m_attachmentPipe.unregister_element(pReplaceMe);
1125 0 : delete pReplaceMe;
1126 : }
1127 :
1128 1 : void Grid::unregister_face(Face* f)
1129 : {
1130 : // notify observers that the face is being erased
1131 1 : NOTIFY_OBSERVERS_REVERSE(m_faceObservers, face_to_be_erased(this, f));
1132 :
1133 : // remove or disconnect from volumes
1134 1 : if(num_volumes() > 0)
1135 : {
1136 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_FACES) ||
1137 0 : option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1138 : {
1139 : vector<Volume*> vVolumes;
1140 0 : CollectVolumes(vVolumes, *this, f, true);
1141 : vector<Volume*>::iterator vIter= vVolumes.begin();
1142 :
1143 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_FACES))
1144 : {
1145 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1146 0 : m_aaVolumeContainerFACE[f].clear();
1147 :
1148 : // delete the collected volumes
1149 0 : while(vIter != vVolumes.end())
1150 : {
1151 0 : Volume* eraseVol = *vIter;
1152 : ++vIter;
1153 0 : erase(eraseVol);
1154 : }
1155 : }
1156 : else
1157 : {
1158 : // unregister from the collected volumes.
1159 0 : for(;vIter != vVolumes.end(); ++vIter)
1160 : {
1161 0 : Volume* vol = *vIter;
1162 0 : FaceContainer::iterator iter = find(m_aaFaceContainerVOLUME[vol].begin(),
1163 : m_aaFaceContainerVOLUME[vol].end(), f);
1164 0 : if(iter != m_aaFaceContainerVOLUME[vol].end())
1165 : m_aaFaceContainerVOLUME[vol].erase(iter);
1166 : }
1167 : }
1168 0 : }
1169 : }
1170 :
1171 : // disconnect from edges
1172 1 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
1173 : {
1174 : // iterate through all edges of the face
1175 0 : uint numEdges = f->num_edges();
1176 0 : for(uint i = 0; i < numEdges; ++i)
1177 : {
1178 0 : Edge* e = get_edge(f, i);
1179 0 : if(e != NULL)
1180 : {
1181 0 : FaceContainer::iterator iter = find(m_aaFaceContainerEDGE[e].begin(),
1182 : m_aaFaceContainerEDGE[e].end(), f);
1183 0 : if(iter != m_aaFaceContainerEDGE[e].end())
1184 : m_aaFaceContainerEDGE[e].erase(iter);
1185 : }
1186 : }
1187 : }
1188 :
1189 : // disconnect from vertices
1190 1 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
1191 : {
1192 0 : size_t numVrts = f->num_vertices();
1193 0 : Face::ConstVertexArray vrts = f->vertices();
1194 0 : for(uint i = 0; i < numVrts; ++i)
1195 : {
1196 0 : Vertex* vrt = vrts[i];
1197 0 : FaceContainer::iterator iter = find(m_aaFaceContainerVERTEX[vrt].begin(),
1198 : m_aaFaceContainerVERTEX[vrt].end(), f);
1199 0 : if(iter != m_aaFaceContainerVERTEX[vrt].end())
1200 : m_aaFaceContainerVERTEX[vrt].erase(iter);
1201 : }
1202 : }
1203 :
1204 : // remove the element from the storage
1205 1 : m_faceElementStorage.m_sectionContainer.erase(get_iterator(f), f->container_section());
1206 1 : m_faceElementStorage.m_attachmentPipe.unregister_element(f);
1207 1 : }
1208 :
1209 3 : void Grid::change_face_options(uint optsNew)
1210 : {
1211 : // check if associated edge information has to be created or removed.
1212 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, FACEOPT_STORE_ASSOCIATED_EDGES))
1213 : {
1214 0 : if(!option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
1215 0 : face_store_associated_edges(true);
1216 : }
1217 : else
1218 : {
1219 3 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
1220 0 : face_store_associated_edges(false);
1221 : }
1222 :
1223 : // check if associated volume information has to be created or removed.
1224 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, FACEOPT_STORE_ASSOCIATED_VOLUMES))
1225 : {
1226 0 : if(!option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1227 0 : face_store_associated_volumes(true);
1228 : }
1229 : else
1230 : {
1231 3 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1232 0 : face_store_associated_volumes(false);
1233 : }
1234 :
1235 : // turn auto-generation of edges on and of
1236 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, FACEOPT_AUTOGENERATE_EDGES))
1237 : {
1238 2 : if(!option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
1239 2 : face_autogenerate_edges(true);
1240 : }
1241 : else
1242 : {
1243 1 : if(option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
1244 1 : face_autogenerate_edges(false);
1245 : }
1246 3 : }
1247 :
1248 0 : void Grid::face_store_associated_edges(bool bStoreIt)
1249 : {
1250 0 : if(bStoreIt)
1251 : {
1252 0 : if(!option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
1253 : {
1254 : // store associated edges
1255 0 : attach_to_faces(m_aEdgeContainer);
1256 0 : m_aaEdgeContainerFACE.access(*this, m_aEdgeContainer);
1257 :
1258 0 : bool createEdges = option_is_enabled(FACEOPT_AUTOGENERATE_EDGES);
1259 :
1260 : // if EDGEOPT_STORE_ASSOCIATED_FACES is enabled, this is as simple
1261 : // as to iterate through all edges and store them at their
1262 : // associated faces.
1263 : // if not we have to iterate through the faces and store
1264 : // each of their edges..
1265 : // If createEdges == true, we want to store the edges sorted.
1266 : // The else branch thus has to be executed.
1267 : if(!createEdges
1268 0 : && option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
1269 : {
1270 : // iterate through the edges
1271 0 : for(EdgeIterator iter = edges_begin(); iter != edges_end(); iter++)
1272 : {
1273 0 : Edge* e = *iter;
1274 : // iterate through the edges associated faces
1275 0 : for(AssociatedFaceIterator fIter = associated_faces_begin(e);
1276 0 : fIter != associated_faces_end(e); fIter++)
1277 : {
1278 0 : m_aaEdgeContainerFACE[*fIter].push_back(e);
1279 : }
1280 : }
1281 : }
1282 : else
1283 : {
1284 : // we have to find the edges by hand using GetEdge(...)
1285 0 : for(FaceIterator iter = faces_begin(); iter != faces_end(); iter++)
1286 : {
1287 : Face* f = *iter;
1288 : uint numEdges = f->num_edges();
1289 :
1290 0 : if(createEdges){
1291 0 : m_aaEdgeContainerFACE[f].resize(numEdges);
1292 0 : for(uint i = 0; i < numEdges; ++i)
1293 0 : m_aaEdgeContainerFACE[f][i] = get_edge(f, i);
1294 : }
1295 : else{
1296 0 : for(uint i = 0; i < numEdges; ++i)
1297 : {
1298 : // get the i-th edge that is described by the EdgeDescriptor - if it exists at all.
1299 0 : Edge* e = get_edge(f, i);
1300 0 : if(e != NULL)
1301 0 : m_aaEdgeContainerFACE[f].push_back(e);
1302 : }
1303 : }
1304 : }
1305 : }
1306 :
1307 : // store the options
1308 0 : m_options |= FACEOPT_STORE_ASSOCIATED_EDGES;
1309 : }
1310 : }
1311 : else
1312 : {
1313 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
1314 : {
1315 : // remove face-edge connections
1316 0 : detach_from_faces(m_aEdgeContainer);
1317 0 : m_options &= (~FACEOPT_STORE_ASSOCIATED_EDGES);
1318 : }
1319 : }
1320 0 : }
1321 :
1322 0 : void Grid::face_store_associated_volumes(bool bStoreIt)
1323 : {
1324 0 : if(bStoreIt)
1325 : {
1326 0 : if(!option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1327 : {
1328 : // store associated faces
1329 0 : attach_to_faces(m_aVolumeContainer);
1330 0 : m_aaVolumeContainerFACE.access(*this, m_aVolumeContainer);
1331 :
1332 : // iterate through the volumes and store each of their faces...
1333 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
1334 : {
1335 0 : Volume* v = *iter;
1336 :
1337 : // if faces are already stored at their associated volumes, we iterate over them.
1338 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1339 : {
1340 0 : AssociatedFaceIterator iterEnd = associated_faces_end(v);
1341 0 : for(AssociatedFaceIterator iter = associated_faces_begin(v); iter != iterEnd; iter++)
1342 0 : m_aaVolumeContainerFACE[*iter].push_back(v);
1343 : }
1344 : else
1345 : {
1346 0 : uint numFaces = v->num_faces();
1347 0 : for(uint i = 0; i < numFaces; ++i)
1348 : {
1349 0 : Face* f = get_face(v, i);
1350 :
1351 0 : if(f)
1352 0 : m_aaVolumeContainerFACE[f].push_back(v);
1353 : }
1354 : }
1355 : }
1356 :
1357 : // store options
1358 0 : m_options |= FACEOPT_STORE_ASSOCIATED_VOLUMES;
1359 : }
1360 : }
1361 : else
1362 : {
1363 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1364 : {
1365 : // remove face-edge connections
1366 0 : detach_from_faces(m_aVolumeContainer);
1367 0 : m_options &= (~FACEOPT_STORE_ASSOCIATED_VOLUMES);
1368 : }
1369 : }
1370 0 : }
1371 :
1372 3 : void Grid::face_autogenerate_edges(bool bAutogen)
1373 : {
1374 3 : if(bAutogen)
1375 : {
1376 2 : if(!option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
1377 : {
1378 2 : bool storeEdges = option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES);
1379 2 : EdgeDescriptor ed;
1380 :
1381 : // generate all missing edges now!
1382 2 : for(FaceIterator iter = faces_begin(); iter != faces_end(); iter++)
1383 : {
1384 : Face* f = *iter;
1385 : // check for each edge of the face if it exists. if not create it and link it to the face.
1386 : uint numEdges = f->num_edges();
1387 :
1388 : // reserve memory for neighbors
1389 0 : if(storeEdges){
1390 : m_aaEdgeContainerFACE[f].clear();
1391 0 : m_aaEdgeContainerFACE[f].reserve(numEdges);
1392 : }
1393 :
1394 0 : for(uint i = 0; i < numEdges; ++i)
1395 : {
1396 : // we can't use get_edge here, since we're manipulating m_aaEdgeContainerFACE on the fly.
1397 0 : f->edge_desc(i, ed);
1398 0 : Edge* e = find_edge_in_associated_edges(ed.vertex(0), ed);
1399 :
1400 0 : if(e == NULL)
1401 : {
1402 : // create the edge
1403 0 : e = f->create_edge(i);
1404 0 : if(storeEdges)
1405 0 : m_aaEdgeContainerFACE[f].push_back(e);
1406 0 : register_edge(e, f, f, NULL);
1407 : }
1408 0 : else if(storeEdges)
1409 0 : m_aaEdgeContainerFACE[f].push_back(e);
1410 : }
1411 : }
1412 :
1413 : // store the option
1414 2 : m_options |= FACEOPT_AUTOGENERATE_EDGES;
1415 :
1416 : // if VOLOPT_AUTOGENERATE_FACES is active, too, then all volume-edges exist.
1417 : // Now, if VOLOPT_STORE_ASSOCIATED_EDGES is active but
1418 : // VOLOPT_AUTOGENERATE_EDGES is inactive, then we'll sort the associated-edges
1419 : // of volumes.
1420 2 : if(option_is_enabled(VOLOPT_AUTOGENERATE_FACES)
1421 0 : && option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES)
1422 2 : && (!option_is_enabled(VOLOPT_AUTOGENERATE_EDGES)))
1423 : {
1424 0 : volume_sort_associated_edge_container();
1425 : }
1426 : }
1427 : }
1428 : else
1429 : {
1430 : // stop auto-generation
1431 1 : m_options &= (~FACEOPT_AUTOGENERATE_EDGES);
1432 : }
1433 3 : }
1434 :
1435 :
1436 : ////////////////////////////////////////////////////////////////////////////////////////////////
1437 : ////////////////////////////////////////////////////////////////////////////////////////////////
1438 : // VOLUMES
1439 : /// creates and removes connectivity data, as specified in optsNew.
1440 0 : void Grid::register_volume(Volume* v, GridObject* pParent)
1441 : {
1442 : GCM_PROFILE_FUNC();
1443 :
1444 : // store the element and register it at the pipe.
1445 0 : m_volumeElementStorage.m_attachmentPipe.register_element(v);
1446 0 : m_volumeElementStorage.m_sectionContainer.insert(v, v->container_section());
1447 :
1448 : // create edges and faces if the according options are enabled.
1449 : // register the volume at the associated vertices, edges and faces, if the according options are enabled.
1450 :
1451 : // register volume at vertices
1452 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
1453 : {
1454 0 : uint numVrts = v->num_vertices();
1455 0 : Volume::ConstVertexArray vrts = v->vertices();
1456 0 : for(uint i = 0; i < numVrts; ++i)
1457 0 : m_aaVolumeContainerVERTEX[vrts[i]].push_back(v);
1458 : }
1459 :
1460 0 : const bool createEdges = option_is_enabled(VOLOPT_AUTOGENERATE_EDGES);
1461 0 : const bool createFaces = option_is_enabled(VOLOPT_AUTOGENERATE_FACES);
1462 0 : const bool createEdgesIndirect = option_is_enabled(VOLOPT_AUTOGENERATE_FACES
1463 : | FACEOPT_AUTOGENERATE_EDGES);
1464 :
1465 0 : const bool edgesStoreVols = option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES);
1466 0 : const bool volsStoreEdges = option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES);
1467 :
1468 0 : const bool facesStoreVols = option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES);
1469 0 : const bool volsStoreFaces = option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES);
1470 :
1471 :
1472 : // if elements are automatically created, then we can directly reserve memory
1473 : // to store neighborhood relations
1474 0 : if(volsStoreEdges && (createEdges || createEdgesIndirect))
1475 0 : m_aaEdgeContainerVOLUME[v].reserve(v->num_edges());
1476 0 : if(volsStoreFaces && createFaces)
1477 0 : m_aaFaceContainerVOLUME[v].reserve(v->num_faces());
1478 :
1479 : // create faces first. This makes sense, since faces thus get a chance to
1480 : // generate associated edges. This has the benefit, that the option
1481 : // VOLOPT_AUTOGENERATE_EDGES has no effect in this case.
1482 :
1483 : // register with faces. autogenerate them if they do not already exist.
1484 0 : if(createFaces
1485 0 : || facesStoreVols
1486 0 : || volsStoreFaces)
1487 : {
1488 : GCM_PROFILE(GCM_vol_handle_faces);
1489 : // iterate through the faces of the volume. create them if demanded.
1490 : // register faces at the volume and vice versa.
1491 0 : uint numFaces = v->num_faces();
1492 0 : FaceDescriptor fd;
1493 0 : for(uint i = 0; i < numFaces; ++i)
1494 : {
1495 0 : v->face_desc(i, fd);
1496 0 : Face* f = find_face_in_associated_faces(fd.vertex(0), fd);
1497 :
1498 0 : if(f == NULL)
1499 : {
1500 0 : if(createFaces)
1501 : {
1502 0 : f = v->create_face(i);
1503 :
1504 0 : if(volsStoreFaces)
1505 0 : m_aaFaceContainerVOLUME[v].push_back(f);
1506 :
1507 : // register the face. By passing v, we speed up the process.
1508 0 : register_face(f, pParent, v);
1509 : }
1510 : }
1511 : else
1512 : {
1513 0 : if(facesStoreVols)
1514 0 : m_aaVolumeContainerFACE[f].push_back(v);
1515 :
1516 0 : if(volsStoreFaces)
1517 0 : m_aaFaceContainerVOLUME[v].push_back(f);
1518 : }
1519 : }
1520 : }
1521 :
1522 : // register with edges. autogenerate missing edges if option is set
1523 0 : if(createEdges
1524 0 : || edgesStoreVols
1525 0 : || volsStoreEdges)
1526 : {
1527 : GCM_PROFILE(GCM_vol_handle_edges);
1528 : // loop through all edges of the volume. check if we have to create it.
1529 : // register the volume with the edges and vice versa after that.
1530 0 : uint numEdges = v->num_edges();
1531 0 : EdgeDescriptor ed;
1532 0 : for(uint i = 0; i < numEdges; ++i)
1533 : {
1534 0 : v->edge_desc(i, ed);
1535 0 : Edge* e = find_edge_in_associated_edges(ed.vertex(0), ed);
1536 :
1537 0 : if(e == NULL)
1538 : {
1539 0 : if(createEdges)
1540 : {
1541 : // create the edge
1542 0 : e = v->create_edge(i);
1543 :
1544 : // store a reference to the edge, if required
1545 0 : if(volsStoreEdges)
1546 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
1547 :
1548 : // register the edge.
1549 0 : register_edge(e, pParent, NULL, v);
1550 : }
1551 : }
1552 : else
1553 : {
1554 0 : if(edgesStoreVols){
1555 : // if the edge was indirectly created during creation of
1556 : // a side-face above, it already has v in its associated-
1557 : // volume container. v is the first element in this container
1558 : // in that case and doesn't have to be added again.
1559 : VolumeContainer& assVols = m_aaVolumeContainerEDGE[e];
1560 0 : if((assVols.size() == 0) || (assVols.front() != v))
1561 0 : assVols.push_back(v);
1562 : }
1563 :
1564 0 : if(volsStoreEdges)
1565 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
1566 : }
1567 : }
1568 : }
1569 :
1570 : GCM_PROFILE(GCM_notify_volume_observers);
1571 : // inform observers about the creation
1572 0 : NOTIFY_OBSERVERS(m_volumeObservers, volume_created(this, v, pParent));
1573 : GCM_PROFILE_END();
1574 0 : }
1575 :
1576 0 : void Grid::register_and_replace_element(Volume* v, Volume* pReplaceMe)
1577 : {
1578 : // check that v and pReplaceMe have the same number of vertices.
1579 0 : if(v->num_vertices() != pReplaceMe->num_vertices())
1580 : {
1581 : LOG("WARNING in Grid::register_and_replace_element(Volume* v, Volume* pReplaceMe): v and pReplaceMe have different numbers of vertices.");
1582 : LOG(" v has not been registered. pReplaceMe has not been replaced.");
1583 : assert(!"ERROR in Grid::register_and_replace_element(Volume* v, Volume* pReplaceMe): v and pReplaceMe have different numbers of vertices.");
1584 0 : return;
1585 : }
1586 :
1587 : // store the element and register it at the pipe.
1588 0 : m_volumeElementStorage.m_attachmentPipe.register_element(v);
1589 0 : m_volumeElementStorage.m_sectionContainer.insert(v, v->container_section());
1590 :
1591 0 : pass_on_values(pReplaceMe, v);
1592 :
1593 : // assign vertices
1594 0 : uint numVrts = v->num_vertices();
1595 0 : Volume::ConstVertexArray vrts = pReplaceMe->vertices();
1596 0 : for(uint i = 0; i < numVrts; ++i)
1597 0 : v->set_vertex(i, vrts[i]);
1598 :
1599 : // inform observers about the creation
1600 0 : NOTIFY_OBSERVERS(m_volumeObservers, volume_created(this, v, pReplaceMe, true));
1601 : // inform observers about the deletion
1602 0 : NOTIFY_OBSERVERS_REVERSE(m_volumeObservers, volume_to_be_erased(this, pReplaceMe, v));
1603 :
1604 : // check if vertices, edges and faces reference pReplaceMe.
1605 : // if so, correct those references.
1606 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
1607 : {
1608 0 : for(uint i = 0; i < numVrts; ++i)
1609 0 : replace(associated_volumes_begin(vrts[i]),
1610 0 : associated_volumes_end(vrts[i]),
1611 : pReplaceMe, v);
1612 : }
1613 :
1614 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
1615 : {
1616 : // collect all edges that are associated with pReplaceMe
1617 : vector<Edge*> vEdges;
1618 0 : CollectEdges(vEdges, *this, pReplaceMe);
1619 0 : for(uint i = 0; i < vEdges.size(); ++i)
1620 0 : replace(associated_volumes_begin(vEdges[i]),
1621 : associated_volumes_end(vEdges[i]),
1622 : pReplaceMe, v);
1623 0 : }
1624 :
1625 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1626 : {
1627 : // collect all faces that are associated with pReplaceMe
1628 : vector<Face*> vFaces;
1629 0 : CollectFaces(vFaces, *this, pReplaceMe);
1630 0 : for(uint i = 0; i < vFaces.size(); ++i)
1631 0 : replace(associated_volumes_begin(vFaces[i]),
1632 : associated_volumes_end(vFaces[i]),
1633 : pReplaceMe, v);
1634 0 : }
1635 :
1636 : // now we have to copy all associated elements of pReplaceMe to v
1637 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
1638 : {
1639 0 : m_aaEdgeContainerVOLUME[v].assign(associated_edges_begin(pReplaceMe),
1640 : associated_edges_end(pReplaceMe));
1641 : m_aaEdgeContainerVOLUME[pReplaceMe].clear();
1642 : }
1643 :
1644 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1645 : {
1646 0 : m_aaFaceContainerVOLUME[v].assign(associated_faces_begin(pReplaceMe),
1647 : associated_faces_end(pReplaceMe));
1648 : m_aaFaceContainerVOLUME[pReplaceMe].clear();
1649 : }
1650 :
1651 : // remove the element from the storage and delete it.
1652 0 : m_volumeElementStorage.m_sectionContainer.erase(get_iterator(pReplaceMe), pReplaceMe->container_section());
1653 0 : m_volumeElementStorage.m_attachmentPipe.unregister_element(pReplaceMe);
1654 0 : delete pReplaceMe;
1655 : }
1656 :
1657 0 : void Grid::unregister_volume(Volume* v)
1658 : {
1659 : // notify observers that the face is being erased
1660 0 : NOTIFY_OBSERVERS_REVERSE(m_volumeObservers, volume_to_be_erased(this, v));
1661 :
1662 : // disconnect from faces
1663 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1664 : {
1665 0 : uint numFaces = v->num_faces();
1666 : vector<Face*> vFaces;
1667 0 : vFaces.reserve(numFaces);
1668 0 : CollectFaces(vFaces, *this, v, false);
1669 0 : numFaces = vFaces.size();
1670 0 : for(uint i = 0; i < numFaces; ++i)
1671 : {
1672 0 : Face* f = vFaces[i];
1673 :
1674 0 : if(f != NULL)
1675 : {
1676 0 : VolumeContainer::iterator iter = find(m_aaVolumeContainerFACE[f].begin(),
1677 : m_aaVolumeContainerFACE[f].end(), v);
1678 0 : if(iter != m_aaVolumeContainerFACE[f].end())
1679 : m_aaVolumeContainerFACE[f].erase(iter);
1680 : }
1681 : }
1682 0 : }
1683 :
1684 : // disconnect from edges
1685 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
1686 : {
1687 0 : uint numEdges = v->num_edges();
1688 0 : for(uint i = 0; i < numEdges; ++i)
1689 : {
1690 : // find the correct entry
1691 0 : Edge* e = get_edge(v, i);
1692 0 : if(e != NULL)
1693 : {
1694 0 : VolumeContainer::iterator iter = find(m_aaVolumeContainerEDGE[e].begin(),
1695 : m_aaVolumeContainerEDGE[e].end(), v);
1696 0 : if(iter != m_aaVolumeContainerEDGE[e].end())
1697 : m_aaVolumeContainerEDGE[e].erase(iter);
1698 : }
1699 : }
1700 : }
1701 :
1702 : // disconnect from vertices
1703 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
1704 : {
1705 : // iterate through all associated vertices and update their connection-info
1706 0 : uint numVertices = v->num_vertices();
1707 0 : Volume::ConstVertexArray vrts = v->vertices();
1708 0 : for(uint i = 0; i < numVertices; ++i)
1709 : {
1710 : // find the correct entry
1711 0 : Vertex* vrt = vrts[i];
1712 0 : VolumeContainer::iterator iter = find(m_aaVolumeContainerVERTEX[vrt].begin(),
1713 : m_aaVolumeContainerVERTEX[vrt].end(), v);
1714 0 : if(iter != m_aaVolumeContainerVERTEX[vrt].end())
1715 : m_aaVolumeContainerVERTEX[vrt].erase(iter);
1716 : }
1717 : }
1718 :
1719 : // remove the element from the storage
1720 0 : m_volumeElementStorage.m_sectionContainer.erase(get_iterator(v), v->container_section());
1721 0 : m_volumeElementStorage.m_attachmentPipe.unregister_element(v);
1722 0 : }
1723 :
1724 3 : void Grid::change_volume_options(uint optsNew)
1725 : {
1726 : // check if associated edge information has to be created or removed.
1727 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VOLOPT_STORE_ASSOCIATED_EDGES))
1728 : {
1729 0 : if(!option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
1730 0 : volume_store_associated_edges(true);
1731 : }
1732 : else
1733 : {
1734 3 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
1735 0 : volume_store_associated_edges(false);
1736 : }
1737 :
1738 : // check if associated face information has to be created or removed.
1739 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VOLOPT_STORE_ASSOCIATED_FACES))
1740 : {
1741 0 : if(!option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1742 0 : volume_store_associated_faces(true);
1743 : }
1744 : else
1745 : {
1746 3 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1747 0 : volume_store_associated_faces(false);
1748 : }
1749 :
1750 : // enable or disable edge-auto-generation
1751 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VOLOPT_AUTOGENERATE_EDGES))
1752 : {
1753 0 : if(!option_is_enabled(VOLOPT_AUTOGENERATE_EDGES))
1754 0 : volume_autogenerate_edges(true);
1755 : }
1756 : else
1757 : {
1758 3 : if(option_is_enabled(VOLOPT_AUTOGENERATE_EDGES))
1759 0 : volume_autogenerate_edges(false);
1760 : }
1761 :
1762 : // enable or disable face-auto-generation
1763 3 : if(OPTIONS_CONTAIN_OPTION(optsNew, VOLOPT_AUTOGENERATE_FACES))
1764 : {
1765 2 : if(!option_is_enabled(VOLOPT_AUTOGENERATE_FACES))
1766 2 : volume_autogenerate_faces(true);
1767 : }
1768 : else
1769 : {
1770 1 : if(option_is_enabled(VOLOPT_AUTOGENERATE_FACES))
1771 1 : volume_autogenerate_faces(false);
1772 : }
1773 3 : }
1774 :
1775 0 : void Grid::volume_store_associated_edges(bool bStoreIt)
1776 : {
1777 0 : if(bStoreIt)
1778 : {
1779 0 : if(!option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
1780 : {
1781 : // store associated edges
1782 0 : attach_to_volumes(m_aEdgeContainer);
1783 0 : m_aaEdgeContainerVOLUME.access(*this, m_aEdgeContainer);
1784 :
1785 0 : bool createEdges = option_is_enabled(VOLOPT_AUTOGENERATE_EDGES)
1786 0 : || option_is_enabled(GRIDOPT_AUTOGENERATE_SIDES);
1787 : // if EDGEOPT_STORE_ASSOCIATED_VOLUMES is enabled, this is as simple
1788 : // as to iterate through all edges and store them at their
1789 : // associated volumes.
1790 : // if not we have to iterate through the volumes and store
1791 : // each of their edges..
1792 : // If createEdges == true, we want to store the edges sorted.
1793 : // The else branch thus has to be executed.
1794 : if(!createEdges
1795 0 : && option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
1796 : {
1797 : // iterate through the edges
1798 0 : for(EdgeIterator iter = edges_begin(); iter != edges_end(); iter++)
1799 : {
1800 0 : Edge* e = *iter;
1801 : // iterate through the edges associated faces
1802 0 : for(AssociatedVolumeIterator vIter = associated_volumes_begin(e);
1803 0 : vIter != associated_volumes_end(e); vIter++)
1804 : {
1805 0 : m_aaEdgeContainerVOLUME[*vIter].push_back(e);
1806 : }
1807 : }
1808 : }
1809 : else
1810 : {
1811 : // we have to find the edges by hand using GetEdge(...)
1812 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
1813 : {
1814 : Volume* v = *iter;
1815 0 : int numEdges = v->num_edges();
1816 :
1817 0 : if(createEdges){
1818 : // all edges exist. We can insert them sorted.
1819 0 : m_aaEdgeContainerVOLUME[v].resize(numEdges);
1820 0 : for(int i = 0; i < numEdges; ++i)
1821 0 : m_aaEdgeContainerVOLUME[v][i] = get_edge(v, i);
1822 : }
1823 : else{
1824 : // iterate through the edges of the volume
1825 0 : for(int i = 0; i < numEdges; ++i)
1826 : {
1827 : // get the edge-descriptor
1828 0 : Edge* e = get_edge(v, i);
1829 0 : if(e != NULL)
1830 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
1831 : }
1832 : }
1833 : }
1834 : }
1835 :
1836 : // store the option
1837 0 : m_options |= VOLOPT_STORE_ASSOCIATED_EDGES;
1838 : }
1839 : }
1840 : else
1841 : {
1842 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
1843 : {
1844 : // remove vol-edge connection
1845 0 : detach_from_volumes(m_aEdgeContainer);
1846 0 : m_options &= (~VOLOPT_STORE_ASSOCIATED_EDGES);
1847 : }
1848 : }
1849 0 : }
1850 :
1851 0 : void Grid::volume_store_associated_faces(bool bStoreIt)
1852 : {
1853 0 : if(bStoreIt)
1854 : {
1855 0 : if(!option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1856 : {
1857 : // store associated faces
1858 0 : attach_to_volumes(m_aFaceContainer);
1859 0 : m_aaFaceContainerVOLUME.access(*this, m_aFaceContainer);
1860 :
1861 0 : bool createFaces = option_is_enabled(VOLOPT_AUTOGENERATE_FACES);
1862 :
1863 : // if FACEOPT_STORE_ASSOCIATED_VOLUMES is enabled, this is as simple
1864 : // as to iterate through all faces and store them at their
1865 : // associated volumes.
1866 : // if not we have to iterate through the volumes and store
1867 : // each of their faces..
1868 : // if createFaces == true then we want to store the faces sorted.
1869 : if(!createFaces
1870 0 : && option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
1871 : {
1872 : // iterate through the edges
1873 0 : for(FaceIterator iter = faces_begin(); iter != faces_end(); iter++)
1874 : {
1875 0 : Face* f = *iter;
1876 : // iterate through the faces associated volumes
1877 0 : for(AssociatedVolumeIterator vIter = associated_volumes_begin(f);
1878 0 : vIter != associated_volumes_end(f); vIter++)
1879 : {
1880 0 : m_aaFaceContainerVOLUME[*vIter].push_back(f);
1881 : }
1882 : }
1883 : }
1884 : else
1885 : {
1886 : // we have to find the edges by hand using GetEdge(...)
1887 0 : FaceDescriptor fd;
1888 :
1889 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
1890 : {
1891 : Volume* v = *iter;
1892 : // iterate through the faces of the volume and get the corresponding face from the grid.
1893 0 : int numFaces = v->num_faces();
1894 :
1895 0 : if(createFaces){
1896 0 : m_aaFaceContainerVOLUME[v].resize(numFaces);
1897 0 : for(int i = 0; i < numFaces; ++i)
1898 0 : m_aaFaceContainerVOLUME[v][i] = get_face(v, i);
1899 :
1900 : }
1901 : else{
1902 0 : for(int i = 0; i < numFaces; ++i)
1903 : {
1904 0 : v->face_desc(i, fd);
1905 0 : Face* f = find_face_in_associated_faces(fd.vertex(0), fd);
1906 :
1907 0 : if(f)
1908 0 : m_aaFaceContainerVOLUME[v].push_back(f);
1909 : }
1910 : }
1911 : }
1912 : }
1913 :
1914 : // store options
1915 0 : m_options |= VOLOPT_STORE_ASSOCIATED_FACES;
1916 : }
1917 : }
1918 : else
1919 : {
1920 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
1921 : {
1922 : // remove vol-edge connection
1923 0 : detach_from_volumes(m_aFaceContainer);
1924 0 : m_options &= (~VOLOPT_STORE_ASSOCIATED_FACES);
1925 : }
1926 : }
1927 0 : }
1928 :
1929 0 : void Grid::volume_autogenerate_edges(bool bAutogen)
1930 : {
1931 0 : if(bAutogen)
1932 : {
1933 0 : if(!option_is_enabled(VOLOPT_AUTOGENERATE_EDGES))
1934 : {
1935 0 : bool volsStoreEdges = option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES);
1936 0 : EdgeDescriptor ed;
1937 :
1938 : // generate all missing edges now!
1939 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
1940 : {
1941 : Volume* v = *iter;
1942 :
1943 : // check for each edge of the volume if it exists. if not create it and link it to the edge.
1944 0 : uint numEdges = v->num_edges();
1945 :
1946 : // reserve memory for neighbors
1947 0 : if(volsStoreEdges){
1948 : m_aaEdgeContainerVOLUME[v].clear();
1949 0 : m_aaEdgeContainerVOLUME[v].reserve(numEdges);
1950 : }
1951 :
1952 0 : for(uint i = 0; i < numEdges; ++i)
1953 : {
1954 : // we can't use get_edge here, since we modify m_aaEdgeContainerVOLUME on the fly.
1955 0 : v->edge_desc(i, ed);
1956 0 : Edge* e = find_edge_in_associated_edges(ed.vertex(0), ed);
1957 :
1958 0 : if(e == NULL)
1959 : {
1960 : // create the edge
1961 0 : e = v->create_edge(i);
1962 0 : if(volsStoreEdges) // has to be performed before register_edge
1963 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
1964 0 : register_edge(e, v, NULL, v);
1965 : }
1966 0 : else if(volsStoreEdges)
1967 0 : m_aaEdgeContainerVOLUME[v].push_back(e);
1968 : }
1969 : }
1970 :
1971 : // store the option
1972 0 : m_options |= VOLOPT_AUTOGENERATE_EDGES;
1973 : }
1974 : }
1975 : else
1976 : {
1977 : // stop auto-generation
1978 0 : m_options &= (~VOLOPT_AUTOGENERATE_EDGES);
1979 : }
1980 0 : }
1981 :
1982 3 : void Grid::volume_autogenerate_faces(bool bAutogen)
1983 : {
1984 3 : if(bAutogen)
1985 : {
1986 2 : if(!option_is_enabled(VOLOPT_AUTOGENERATE_FACES))
1987 : {
1988 2 : bool volsStoreFaces = option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES);
1989 2 : FaceDescriptor fd;
1990 :
1991 : // generate all missing faces now!
1992 2 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
1993 : {
1994 : Volume* v = *iter;
1995 : // check for each face of the volume if it exists. if not create it and link it to the face.
1996 0 : uint numFaces = v->num_faces();
1997 :
1998 : // reserve memory for neighbors
1999 0 : if(volsStoreFaces){
2000 : m_aaFaceContainerVOLUME[v].clear();
2001 0 : m_aaFaceContainerVOLUME[v].reserve(numFaces);
2002 : }
2003 :
2004 0 : for(uint i = 0; i < numFaces; ++i)
2005 : {
2006 : // we can't use get_face here, since we modify m_aaEdgeContainerVOLUME on the fly.
2007 0 : v->face_desc(i, fd);
2008 0 : Face* f = find_face_in_associated_faces(fd.vertex(0), fd);
2009 :
2010 0 : if(f == NULL)
2011 : {
2012 : // create the face
2013 0 : f = v->create_face(i);
2014 0 : if(volsStoreFaces) // has to be performed before register_face
2015 0 : m_aaFaceContainerVOLUME[v].push_back(f);
2016 0 : register_face(f, v, v);
2017 : }
2018 0 : else if(volsStoreFaces)
2019 0 : m_aaFaceContainerVOLUME[v].push_back(f);
2020 : }
2021 : }
2022 :
2023 : // store the option
2024 2 : m_options |= VOLOPT_AUTOGENERATE_FACES;
2025 :
2026 : // if FACEOPT_AUTOGENERATE_EDGES is active, too, then all volume-edges exist.
2027 : // Now, if VOLOPT_STORE_ASSOCIATED_EDGES is active but
2028 : // VOLOPT_AUTOGENERATE_EDGES is inactive, then we'll sort the associated-edges
2029 : // of volumes.
2030 2 : if(option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)
2031 2 : && option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES)
2032 2 : && (!option_is_enabled(VOLOPT_AUTOGENERATE_EDGES)))
2033 : {
2034 0 : volume_sort_associated_edge_container();
2035 : }
2036 : }
2037 : }
2038 : else
2039 : {
2040 : // stop auto-generation
2041 1 : m_options &= (~VOLOPT_AUTOGENERATE_FACES);
2042 : }
2043 3 : }
2044 :
2045 :
2046 0 : void Grid::volume_sort_associated_edge_container()
2047 : {
2048 0 : if(!option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
2049 0 : return;
2050 :
2051 : EdgeContainer tmpCon;
2052 0 : for(VolumeIterator iter = volumes_begin(); iter != volumes_end(); iter++)
2053 : {
2054 : Volume* v = *iter;
2055 0 : uint numEdges = v->num_edges();
2056 :
2057 : // since we already have a container of associated edges, we will search it
2058 : // for matching edges...
2059 : // to reduce memory allocation, we'll first copy the values to tmpCon
2060 : EdgeContainer& edges = m_aaEdgeContainerVOLUME[v];
2061 : tmpCon.clear();
2062 0 : for(size_t i = 0; i < edges.size(); ++i)
2063 0 : tmpCon.push_back(edges[i]);
2064 :
2065 : edges.clear();
2066 :
2067 : // check for each edge-desc, whether a matching edge is contained in edges.
2068 : // if so push it back to edgesSorted.
2069 0 : EdgeDescriptor ed;
2070 0 : for(uint i = 0; i < numEdges; ++i){
2071 0 : v->edge_desc(i, ed);
2072 0 : for(size_t j = 0; j < tmpCon.size(); ++j){
2073 0 : if(tmpCon[j] && CompareVertices(&ed, tmpCon[j])){
2074 0 : edges.push_back(tmpCon[j]);
2075 0 : tmpCon[j] = NULL;
2076 0 : break;
2077 : }
2078 : }
2079 : }
2080 : }
2081 0 : }
2082 :
2083 : ////////////////////////////////////////////////////////////////////////
2084 : ////////////////////////////////////////////////////////////////////////
2085 : // replace_vertex
2086 0 : bool Grid::replace_vertex(Vertex* vrtOld, Vertex* vrtNew)
2087 : {
2088 : // this bool should be a parameter. However one first would have
2089 : // to add connectivity updates for double-elements in this method,
2090 : // to handle the case when eraseDoubleElements is set to false.
2091 : bool eraseDoubleElements = true;
2092 :
2093 : // iterate through associated objects of vrtOld.
2094 : // replace in each vrtOld by vrtNew.
2095 : // Delete objects that would be doubled if eraseDoubleElements is set to true.
2096 : // Update connectivity information.
2097 : // erase vrtOld
2098 : // all elements that will be erased, during this method will be
2099 : // unregistered manually on the fly.
2100 :
2101 : // containers for object collection
2102 : vector<Edge*> vEdges;
2103 : vector<Face*> vFaces;
2104 : vector<Volume*> vVolumes;
2105 :
2106 0 : EdgeDescriptor ed;
2107 0 : FaceDescriptor fd;
2108 0 : VolumeDescriptor vd;
2109 :
2110 : // since vrtOld will be erased, we will notify all observers
2111 0 : NOTIFY_OBSERVERS_REVERSE(m_vertexObservers, vertex_to_be_erased(this, vrtOld));
2112 :
2113 : // EDGES
2114 0 : if(num_edges() > 0)
2115 : {
2116 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_EDGES,
2117 : "Grid::replace_vertex(...)",
2118 : "VRTOPT_STORE_ASSOCIATED_EDGES");
2119 :
2120 0 : AssociatedEdgeIterator iter = associated_edges_begin(vrtOld);
2121 0 : AssociatedEdgeIterator iterEnd = associated_edges_end(vrtOld);
2122 0 : while(iter != iterEnd)
2123 : {
2124 0 : Edge* e = *iter;
2125 : ++iter;
2126 :
2127 : // if eraseDoubleElementes is enabled and the new edge would
2128 : // already exist, we wont replace the vertex in it.
2129 : bool bReplaceVertex = true;
2130 :
2131 : if(eraseDoubleElements)
2132 : {
2133 : // create an edge-descriptor of the edge that will be created.
2134 0 : if(e->vertex(0) == vrtOld)
2135 0 : ed.set_vertices(e->vertex(1), vrtNew);
2136 : else
2137 0 : ed.set_vertices(e->vertex(0), vrtNew);
2138 :
2139 : // check if this edge already exists.
2140 0 : Edge* eNew = get_edge(ed);
2141 0 : if(eNew)
2142 : {
2143 : // The edge will be removed. Notify observers.
2144 0 : NOTIFY_OBSERVERS_REVERSE(m_edgeObservers, edge_to_be_erased(this, e));
2145 :
2146 : // Since we want to avoid deletion of associated elements
2147 : // we have to handle the erasure of e by our self.
2148 : bReplaceVertex = false;
2149 :
2150 : // before the removal we will replace its entry in associated-
2151 : // element-lists with the pointer to the existing edge.
2152 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
2153 : {
2154 : // unregister e from the vertex with which e connects vrtOld.
2155 : EdgeContainer& ec = m_aaEdgeContainerVERTEX[ed.vertex(0)];
2156 0 : EdgeContainer::iterator tmpI = find(ec.begin(), ec.end(), e);
2157 0 : if(tmpI != ec.end())
2158 : ec.erase(tmpI);
2159 : }
2160 :
2161 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES)
2162 0 : && num_faces() > 0)
2163 : {
2164 : // unregister the edge from all adjacent faces
2165 0 : CollectFaces(vFaces, *this, e);
2166 0 : for(uint i = 0; i < vFaces.size(); ++i)
2167 : {
2168 0 : Face* f = vFaces[i];
2169 0 : replace(associated_edges_begin(f),
2170 : associated_edges_end(f), e, eNew);
2171 : }
2172 : }
2173 :
2174 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES)
2175 0 : && num_volumes() > 0)
2176 : {
2177 : // unregister the edge from all adjacent volumes
2178 0 : CollectVolumes(vVolumes, *this, e);
2179 0 : for(uint i = 0; i < vVolumes.size(); ++i)
2180 : {
2181 0 : Volume* v = vVolumes[i];
2182 0 : replace(associated_edges_begin(v),
2183 : associated_edges_end(v), e, eNew);
2184 : }
2185 : }
2186 :
2187 : // we can now remove e from the storage.
2188 0 : m_edgeElementStorage.m_sectionContainer.erase(get_iterator(e), e->container_section());
2189 0 : m_edgeElementStorage.m_attachmentPipe.unregister_element(e);
2190 0 : delete e;
2191 : }
2192 : }
2193 :
2194 : // perform the replace
2195 : if(bReplaceVertex)
2196 : {
2197 : // replace the vertex
2198 0 : if(e->vertex(0) == vrtOld)
2199 0 : e->set_vertex(0, vrtNew);
2200 : else
2201 0 : e->set_vertex(1, vrtNew);
2202 :
2203 : // register e at vrtNew
2204 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
2205 : {
2206 0 : m_aaEdgeContainerVERTEX[vrtNew].push_back(e);
2207 : }
2208 : }
2209 : }
2210 :
2211 : // we will now clear the associated edges array of vrtOld.
2212 : m_aaEdgeContainerVERTEX[vrtOld].clear();
2213 : }
2214 :
2215 : // FACES
2216 0 : if(num_faces() > 0)
2217 : {
2218 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_FACES,
2219 : "Grid::replace_vertex(...)",
2220 : "VRTOPT_STORE_ASSOCIATED_FACES");
2221 :
2222 0 : AssociatedFaceIterator iter = associated_faces_begin(vrtOld);
2223 0 : AssociatedFaceIterator iterEnd = associated_faces_end(vrtOld);
2224 0 : while(iter != iterEnd)
2225 : {
2226 0 : Face* f = *iter;
2227 0 : uint numVrts = f->num_vertices();
2228 0 : Face::ConstVertexArray vrts = f->vertices();
2229 :
2230 : ++iter;
2231 :
2232 : // if eraseDoubleElementes is enabled and the new face would
2233 : // already exist, we wont replace the vertex in it.
2234 : bool bReplaceVertex = true;
2235 :
2236 : if(eraseDoubleElements)
2237 : {
2238 : // create a face-descriptor of the face that will be created.
2239 : fd.set_num_vertices(numVrts);
2240 0 : for(uint i = 0; i < numVrts; ++i)
2241 : {
2242 0 : if(vrts[i] == vrtOld)
2243 : fd.set_vertex(i, vrtNew);
2244 : else
2245 : fd.set_vertex(i, vrts[i]);
2246 : }
2247 :
2248 : // check if this face already exists.
2249 0 : Face* fNew = get_face(fd);
2250 0 : if(fNew)
2251 : {
2252 : // The face will be removed. Notify observers.
2253 0 : NOTIFY_OBSERVERS_REVERSE(m_faceObservers, face_to_be_erased(this, f));
2254 :
2255 : // Since we want to avoid deletion of associated elements
2256 : // we have to handle the erasure of f by our self.
2257 : bReplaceVertex = false;
2258 :
2259 : // before the removal we will replace its entry in associated-
2260 : // element-lists with the pointer to the existing face.
2261 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
2262 : {
2263 : // unregister f from the vertices with which f connects vrtOld.
2264 0 : for(uint i = 0; i < numVrts; ++i)
2265 : {
2266 0 : if(vrts[i] != vrtOld)
2267 : {
2268 : FaceContainer& fc = m_aaFaceContainerVERTEX[vrts[i]];
2269 0 : FaceContainer::iterator tmpI = find(fc.begin(), fc.end(), f);
2270 0 : if(tmpI != fc.end())
2271 : fc.erase(tmpI);
2272 : }
2273 : }
2274 : }
2275 :
2276 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES)
2277 0 : && num_edges() > 0)
2278 : {
2279 : // unregister f from adjacent edges.
2280 0 : CollectEdges(vEdges, *this, f);
2281 0 : for(uint i = 0; i < vEdges.size(); ++i)
2282 : {
2283 0 : FaceContainer& fc = m_aaFaceContainerEDGE[vEdges[i]];
2284 0 : FaceContainer::iterator tmpI = find(fc.begin(), fc.end(), f);
2285 0 : if(tmpI != fc.end())
2286 : fc.erase(tmpI);
2287 : }
2288 : }
2289 :
2290 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES)
2291 0 : && num_volumes() > 0)
2292 : {
2293 : // unregister the face from all adjacent volumes
2294 0 : CollectVolumes(vVolumes, *this, f);
2295 0 : for(uint i = 0; i < vVolumes.size(); ++i)
2296 : {
2297 0 : Volume* v = vVolumes[i];
2298 0 : replace(associated_faces_begin(v),
2299 : associated_faces_end(v), f, fNew);
2300 : }
2301 : }
2302 :
2303 : // we can now remove f from the storage.
2304 0 : m_faceElementStorage.m_sectionContainer.erase(get_iterator(f), f->container_section());
2305 0 : m_faceElementStorage.m_attachmentPipe.unregister_element(f);
2306 0 : delete f;
2307 : }
2308 : }
2309 :
2310 : // perform the replace
2311 : if(bReplaceVertex)
2312 : {
2313 : // replace the vertex
2314 0 : uint numVrts = f->num_vertices();
2315 0 : for(uint i = 0; i < numVrts; ++i)
2316 : {
2317 0 : if(vrts[i] == vrtOld)
2318 0 : f->set_vertex(i, vrtNew);
2319 : }
2320 :
2321 : // register f at vrtNew
2322 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
2323 : {
2324 0 : m_aaFaceContainerVERTEX[vrtNew].push_back(f);
2325 : }
2326 :
2327 : // register f at existing edges
2328 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES))
2329 : {
2330 : // only edges which contain vrtNew are relevant.
2331 0 : uint numEdges = f->num_edges();
2332 0 : for(uint i = 0; i < numEdges; ++i)
2333 : {
2334 0 : f->edge_desc(i, ed);
2335 0 : if(ed.vertex(0) == vrtNew || ed.vertex(1) == vrtNew)
2336 : {
2337 0 : Edge* tEdge = get_edge(ed);
2338 0 : if(tEdge)
2339 : {
2340 : FaceContainer& fc = m_aaFaceContainerEDGE[tEdge];
2341 0 : FaceContainer::iterator tmpI = find(fc.begin(), fc.end(), f);
2342 0 : if(tmpI == fc.end())
2343 0 : fc.push_back(f);
2344 : }
2345 : }
2346 : }
2347 : }
2348 : }
2349 : }
2350 : // clear associated faces list of vrtOld
2351 : m_aaFaceContainerVERTEX[vrtOld].clear();
2352 : }
2353 :
2354 : // VOLUMES
2355 0 : if(num_volumes() > 0)
2356 : {
2357 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_VOLUMES,
2358 : "Grid::replace_vertex(...)",
2359 : "VRTOPT_STORE_ASSOCIATED_VOLUMES");
2360 :
2361 0 : AssociatedVolumeIterator iter = associated_volumes_begin(vrtOld);
2362 0 : AssociatedVolumeIterator iterEnd = associated_volumes_end(vrtOld);
2363 0 : while(iter != iterEnd)
2364 : {
2365 0 : Volume* v = *iter;
2366 0 : uint numVrts = v->num_vertices();
2367 0 : Volume::ConstVertexArray vrts = v->vertices();
2368 : ++iter;
2369 :
2370 : // if eraseDoubleElementes is enabled and the new face would
2371 : // already exist, we wont replace the vertex in it.
2372 : bool bReplaceVertex = true;
2373 :
2374 : if(eraseDoubleElements)
2375 : {
2376 : // create a volume-descriptor of the volume that will be created.
2377 : vd.set_num_vertices(numVrts);
2378 :
2379 0 : for(uint i = 0; i < numVrts; ++i)
2380 : {
2381 0 : if(vrts[i] == vrtOld)
2382 : vd.set_vertex(i, vrtNew);
2383 : else
2384 : vd.set_vertex(i, vrts[i]);
2385 : }
2386 :
2387 : // check if this volume already exists.
2388 0 : Volume* vNew = get_volume(vd);
2389 0 : if(vNew)
2390 : {
2391 : // The volume will be removed. Notify observers.
2392 0 : NOTIFY_OBSERVERS_REVERSE(m_volumeObservers, volume_to_be_erased(this, v));
2393 :
2394 : // Since we want to avoid deletion of associated elements
2395 : // we have to handle the erasure of v by our self.
2396 : bReplaceVertex = false;
2397 :
2398 : // before the removal we will replace its entry in associated-
2399 : // element-lists with the pointer to the existing volume.
2400 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
2401 : {
2402 : // unregister v from the vertices with which v connects vrtOld.
2403 0 : for(uint i = 0; i < numVrts; ++i)
2404 : {
2405 0 : if(vrts[i] != vrtOld)
2406 : {
2407 : VolumeContainer& vc = m_aaVolumeContainerVERTEX[vrts[i]];
2408 0 : VolumeContainer::iterator tmpI = find(vc.begin(), vc.end(), v);
2409 0 : if(tmpI != vc.end())
2410 : vc.erase(tmpI);
2411 : }
2412 : }
2413 : }
2414 :
2415 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES)
2416 0 : && num_edges() > 0)
2417 : {
2418 : // unregister v from adjacent edges.
2419 0 : CollectEdges(vEdges, *this, v);
2420 0 : for(uint i = 0; i < vEdges.size(); ++i)
2421 : {
2422 0 : VolumeContainer& vc = m_aaVolumeContainerEDGE[vEdges[i]];
2423 0 : VolumeContainer::iterator tmpI = find(vc.begin(), vc.end(), v);
2424 0 : if(tmpI != vc.end())
2425 : vc.erase(tmpI);
2426 : }
2427 : }
2428 :
2429 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES)
2430 0 : && num_faces() > 0)
2431 : {
2432 : // unregister v from adjacent faces.
2433 0 : CollectFaces(vFaces, *this, v);
2434 0 : for(uint i = 0; i < vFaces.size(); ++i)
2435 : {
2436 0 : VolumeContainer& vc = m_aaVolumeContainerFACE[vFaces[i]];
2437 0 : VolumeContainer::iterator tmpI = find(vc.begin(), vc.end(), v);
2438 0 : if(tmpI != vc.end())
2439 : vc.erase(tmpI);
2440 : }
2441 : }
2442 :
2443 :
2444 : // we can now remove v from the storage.
2445 0 : m_volumeElementStorage.m_sectionContainer.erase(get_iterator(v), v->container_section());
2446 0 : m_volumeElementStorage.m_attachmentPipe.unregister_element(v);
2447 0 : delete v;
2448 : }
2449 : }
2450 :
2451 : // perform the replace
2452 : if(bReplaceVertex)
2453 : {
2454 : // replace the vertex
2455 0 : uint numVrts = v->num_vertices();
2456 0 : for(uint i = 0; i < numVrts; ++i)
2457 : {
2458 0 : if(vrts[i] == vrtOld)
2459 0 : v->set_vertex(i, vrtNew);
2460 : }
2461 :
2462 : // register v at vrtNew
2463 0 : if(option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))
2464 : {
2465 0 : m_aaVolumeContainerVERTEX[vrtNew].push_back(v);
2466 : }
2467 :
2468 : // register v at existing edges
2469 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES))
2470 : {
2471 : // only edges which contain vrtNew are relevant.
2472 0 : uint numEdges = v->num_edges();
2473 0 : for(uint i = 0; i < numEdges; ++i)
2474 : {
2475 0 : v->edge_desc(i, ed);
2476 0 : if(ed.vertex(0) == vrtNew || ed.vertex(1) == vrtNew)
2477 : {
2478 0 : Edge* tEdge = get_edge(ed);
2479 0 : if(tEdge)
2480 : {
2481 : VolumeContainer& vc = m_aaVolumeContainerEDGE[tEdge];
2482 0 : VolumeContainer::iterator tmpI = find(vc.begin(), vc.end(), v);
2483 0 : if(tmpI == vc.end())
2484 0 : vc.push_back(v);
2485 : }
2486 : }
2487 : }
2488 : }
2489 :
2490 : // register v at existing faces
2491 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
2492 : {
2493 : // only faces which contain vrtNew are relevant.
2494 0 : uint numFaces = v->num_faces();
2495 0 : for(uint i = 0; i < numFaces; ++i)
2496 : {
2497 0 : v->face_desc(i, fd);
2498 : // check whether fd contains vrtNew
2499 : bool bContainsVrtNew = false;
2500 : size_t numFaceVrts = fd.num_vertices();
2501 : Face::ConstVertexArray fvrts = fd.vertices();
2502 0 : for(uint j = 0; j < numFaceVrts; ++j)
2503 : {
2504 0 : if(fvrts[j] == vrtNew)
2505 : {
2506 : bContainsVrtNew = true;
2507 : break;
2508 : }
2509 : }
2510 :
2511 0 : if(bContainsVrtNew)
2512 : {
2513 0 : Face* tFace = get_face(fd);
2514 0 : if(tFace)
2515 : {
2516 : VolumeContainer& vc = m_aaVolumeContainerFACE[tFace];
2517 0 : VolumeContainer::iterator tmpI = find(vc.begin(), vc.end(), v);
2518 0 : if(tmpI == vc.end())
2519 0 : vc.push_back(v);
2520 : }
2521 : }
2522 : }
2523 : }
2524 : }
2525 : }
2526 : }
2527 :
2528 : // finally erase vrtOld.
2529 0 : m_vertexElementStorage.m_sectionContainer.erase(get_iterator(vrtOld), vrtOld->container_section());
2530 0 : m_vertexElementStorage.m_attachmentPipe.unregister_element(vrtOld);
2531 0 : delete vrtOld;
2532 :
2533 0 : return true;
2534 0 : }
2535 :
2536 : ////////////////////////////////////////////////////////////////////////
2537 : // replace_vertex_is_valid
2538 0 : bool Grid::replace_vertex_is_valid(Vertex* vrtOld, Vertex* vrtNew)
2539 : {
2540 : // iterate through all geometric objects connected to vrtOld and check
2541 : // if they contain vrtNew too. If not return true, else return false.
2542 :
2543 : // check edges
2544 0 : if(num_edges() > 0)
2545 : {
2546 : // we need vertex-edge connectivity
2547 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_EDGES,
2548 : "Grid::replace_vertex_is_valid(...)",
2549 : "VRTOPT_STORE_ASSOCIATED_EDGES");
2550 :
2551 0 : AssociatedEdgeIterator iterEnd = associated_edges_end(vrtOld);
2552 0 : for(AssociatedEdgeIterator iter = associated_edges_begin(vrtOld);
2553 0 : iter != iterEnd; ++iter)
2554 : {
2555 : // check whether vrtNew is contained in the edge.
2556 0 : if((*iter)->vertex(0) == vrtNew)
2557 : return false;
2558 0 : if((*iter)->vertex(1) == vrtNew)
2559 : return false;
2560 : }
2561 : }
2562 :
2563 : // check faces
2564 0 : if(num_faces() > 0)
2565 : {
2566 : // we need vertex-face connectivity
2567 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_FACES,
2568 : "Grid::replace_vertex_is_valid(...)",
2569 : "VRTOPT_STORE_ASSOCIATED_FACES");
2570 :
2571 0 : AssociatedFaceIterator iterEnd = associated_faces_end(vrtOld);
2572 0 : for(AssociatedFaceIterator iter = associated_faces_begin(vrtOld);
2573 0 : iter != iterEnd; ++iter)
2574 : {
2575 0 : if(FaceContains(*iter, vrtNew))
2576 : return false;
2577 : }
2578 : }
2579 :
2580 : // check volumes
2581 0 : if(num_volumes() > 0)
2582 : {
2583 : // we need vertex-face connectivity
2584 0 : autoenable_option(VRTOPT_STORE_ASSOCIATED_VOLUMES,
2585 : "Grid::replace_vertex_is_valid(...)",
2586 : "VRTOPT_STORE_ASSOCIATED_VOLUMES");
2587 :
2588 0 : AssociatedVolumeIterator iterEnd = associated_volumes_end(vrtOld);
2589 0 : for(AssociatedVolumeIterator iter = associated_volumes_begin(vrtOld);
2590 0 : iter != iterEnd; ++iter)
2591 : {
2592 0 : if(VolumeContains(*iter, vrtNew))
2593 : return false;
2594 : }
2595 : }
2596 :
2597 : return true;
2598 : }
2599 :
2600 :
2601 :
2602 : ////////////////////////////////////////////////////////////////////////////////
2603 : // ASSOCIATED ELEMENTS
2604 : ////////////////////////////////////////////////////////////////////////////////
2605 :
2606 : ////////////////////////////////////////////////////////////////////////////////
2607 : // ASSOCIATED VERTICES
2608 0 : void Grid::get_associated(SecureVertexContainer& vrts, Edge* e)
2609 : {
2610 0 : vrts.set_external_array(e->vertices(), e->num_vertices());
2611 0 : }
2612 :
2613 0 : void Grid::get_associated(SecureVertexContainer& vrts, Face* f)
2614 : {
2615 0 : vrts.set_external_array(f->vertices(), f->num_vertices());
2616 0 : }
2617 :
2618 0 : void Grid::get_associated(SecureVertexContainer& vrts, Volume* v)
2619 : {
2620 0 : vrts.set_external_array(v->vertices(), v->num_vertices());
2621 0 : }
2622 :
2623 :
2624 : ////////////////////////////////////////////////////////////////////////////////
2625 : // ASSOCIATED EDGES
2626 0 : void Grid::get_associated(SecureEdgeContainer& edges, Vertex* v)
2627 : {
2628 : // Without the VRTOPT_STORE_ASSOCIATED_... option, this operation would have
2629 : // complexity O(n). This has to be avoided! We thus simply enable the option.
2630 : // This takes some time, however, later queries will greatly benefit.
2631 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES)){
2632 : // only enable the option if edges exist at all
2633 0 : if(num<Edge>() == 0){
2634 : edges.clear();
2635 0 : return;
2636 : }
2637 :
2638 : LOG("WARNING in get_associated(edges, vrt): auto-enabling VRTOPT_STORE_ASSOCIATED_EDGES." << endl);
2639 0 : vertex_store_associated_edges(true);
2640 : }
2641 :
2642 : EdgeContainer& assEdges = m_aaEdgeContainerVERTEX[v];
2643 0 : if(assEdges.empty())
2644 : edges.clear();
2645 : else
2646 0 : edges.set_external_array(&assEdges.front(), assEdges.size());
2647 : }
2648 :
2649 0 : void Grid::get_associated(SecureEdgeContainer& edges, Face* f)
2650 : {
2651 : // to improve performance, we first check the grid options.
2652 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_EDGES))
2653 : {
2654 : // we can output the associated array directly
2655 : EdgeContainer& assEdges = m_aaEdgeContainerFACE[f];
2656 0 : if(assEdges.empty())
2657 : edges.clear();
2658 : else
2659 0 : edges.set_external_array(&assEdges.front(), assEdges.size());
2660 : }
2661 : else{
2662 : // clear the container
2663 : edges.clear();
2664 :
2665 : // if no edges are present, we can leave immediately
2666 0 : if(num<Edge>() == 0)
2667 : return;
2668 :
2669 : // get the edges one by one
2670 : uint numEdges = f->num_edges();
2671 0 : for(uint i = 0; i < numEdges; ++i){
2672 0 : Edge* e = get_edge(f, i);
2673 0 : if(e != NULL)
2674 0 : edges.push_back(e);
2675 : }
2676 : }
2677 : }
2678 :
2679 0 : void Grid::get_associated(SecureEdgeContainer& edges, Volume* v)
2680 : {
2681 : // to improve performance, we first check the grid options.
2682 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_EDGES))
2683 : {
2684 : // we can output the associated array directly
2685 : EdgeContainer& assEdges = m_aaEdgeContainerVOLUME[v];
2686 0 : if(assEdges.empty())
2687 : edges.clear();
2688 : else
2689 0 : edges.set_external_array(&assEdges.front(), assEdges.size());
2690 : }
2691 : else{
2692 : // clear the container
2693 : edges.clear();
2694 :
2695 : // if no edges are present, we can leave immediately
2696 0 : if(num<Edge>() == 0)
2697 : return;
2698 :
2699 : // get the edges one by one
2700 0 : uint numEdges = v->num_edges();
2701 0 : for(uint i = 0; i < numEdges; ++i){
2702 0 : Edge* e = get_edge(v, i);
2703 0 : if(e != NULL)
2704 0 : edges.push_back(e);
2705 : }
2706 : }
2707 : }
2708 :
2709 :
2710 : ////////////////////////////////////////////////////////////////////////////////
2711 : // ASSOCIATED FACES
2712 0 : void Grid::get_associated(SecureFaceContainer& faces, Vertex* v)
2713 : {
2714 : // Without the VRTOPT_STORE_ASSOCIATED_... option, this operation would have
2715 : // complexity O(n). This has to be avoided! We thus simply enable the option.
2716 : // This takes some time, however, later queries will greatly benefit.
2717 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES)){
2718 : // only enable the option if faces exist at all
2719 0 : if(num<Face>() == 0){
2720 : faces.clear();
2721 0 : return;
2722 : }
2723 :
2724 : LOG("WARNING in get_associated(faces, vrt): auto-enabling VRTOPT_STORE_ASSOCIATED_FACES." << endl);
2725 0 : vertex_store_associated_faces(true);
2726 : }
2727 :
2728 : FaceContainer& assFaces = m_aaFaceContainerVERTEX[v];
2729 0 : if(assFaces.empty())
2730 : faces.clear();
2731 : else
2732 0 : faces.set_external_array(&assFaces.front(), assFaces.size());
2733 : }
2734 :
2735 0 : void Grid::get_associated(SecureFaceContainer& faces, Edge* e)
2736 : {
2737 : // best option: EDGEOPT_STORE_ASSOCIATED_FACES
2738 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES)){
2739 : // we can output the associated array directly
2740 : FaceContainer& assFaces = m_aaFaceContainerEDGE[e];
2741 0 : if(assFaces.empty())
2742 : faces.clear();
2743 : else
2744 0 : faces.set_external_array(&assFaces.front(), assFaces.size());
2745 : }
2746 : else{
2747 : // second best: iterate through all faces associated with the first end-point of e
2748 : // and check for each if it contains e. If so push it into the container.
2749 : // VRTOPT_STORE_ASSOCIATED_FACES has to be enabled for this. Only continue,
2750 : // if faces exist at all
2751 : faces.clear();
2752 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES)){
2753 : // only enable the option if faces exist at all
2754 0 : if(num<Face>() == 0){
2755 : return;
2756 : }
2757 :
2758 : LOG("WARNING in get_associated(faces, edge): auto-enabling VRTOPT_STORE_ASSOCIATED_FACES." << endl);
2759 0 : vertex_store_associated_faces(true);
2760 : }
2761 :
2762 : // check as few faces as possible
2763 0 : Vertex* vrt = e->vertex(0);
2764 : /* // This check could be beneficial - however, it probably introduces unnecessary overhead.
2765 : if(m_aaFaceContainerVERTEX[vrt].size() >
2766 : m_aaFaceContainerVERTEX[e->vertex(1)].size())
2767 : {
2768 : vrt = e->vertex(1);
2769 : }
2770 : */
2771 :
2772 : FaceContainer& assFaces = m_aaFaceContainerVERTEX[vrt];
2773 0 : for(size_t i = 0; i < assFaces.size(); ++i){
2774 0 : if(FaceContains(assFaces[i], e))
2775 0 : faces.push_back(assFaces[i]);
2776 : }
2777 : }
2778 : }
2779 :
2780 0 : void Grid::get_associated(SecureFaceContainer& faces, Volume* v)
2781 : {
2782 : // to improve performance, we first check the grid options.
2783 0 : if(option_is_enabled(VOLOPT_STORE_ASSOCIATED_FACES))
2784 : {
2785 : // we can output the associated array directly
2786 : FaceContainer& assFaces = m_aaFaceContainerVOLUME[v];
2787 0 : if(assFaces.empty())
2788 : faces.clear();
2789 : else
2790 0 : faces.set_external_array(&assFaces.front(), assFaces.size());
2791 : }
2792 : else{
2793 : // clear the container
2794 : faces.clear();
2795 :
2796 : // if no faces are present, we can leave immediately
2797 0 : if(num<Face>() == 0)
2798 : return;
2799 :
2800 : // get the faces one by one
2801 0 : uint numFaces = v->num_faces();
2802 0 : for(uint i = 0; i < numFaces; ++i){
2803 0 : Face* f = get_face(v, i);
2804 0 : if(f != NULL)
2805 0 : faces.push_back(f);
2806 : }
2807 : }
2808 : }
2809 :
2810 :
2811 : ////////////////////////////////////////////////////////////////////////////////
2812 : // ASSOCIATED VOLUMES
2813 0 : void Grid::get_associated(SecureVolumeContainer& vols, Vertex* v)
2814 : {
2815 : // Without the VRTOPT_STORE_ASSOCIATED_... option, this operation would have
2816 : // complexity O(n). This has to be avoided! We thus simply enable the option.
2817 : // This takes some time, however, later queries will greatly benefit.
2818 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES)){
2819 : // only enable the option if volumes exist at all
2820 0 : if(num<Volume>() == 0){
2821 : vols.clear();
2822 0 : return;
2823 : }
2824 :
2825 : LOG("WARNING in get_associated(volumes, vrt): auto-enabling VRTOPT_STORE_ASSOCIATED_VOLUMES." << endl);
2826 0 : vertex_store_associated_volumes(true);
2827 : }
2828 :
2829 : VolumeContainer& assVols = m_aaVolumeContainerVERTEX[v];
2830 0 : if(assVols.empty())
2831 : vols.clear();
2832 : else
2833 0 : vols.set_external_array(&assVols.front(), assVols.size());
2834 : }
2835 :
2836 0 : void Grid::get_associated(SecureVolumeContainer& vols, Edge* e)
2837 : {
2838 : // best option: EDGEOPT_STORE_ASSOCIATED_VOLUMES
2839 0 : if(option_is_enabled(EDGEOPT_STORE_ASSOCIATED_VOLUMES)){
2840 : // we can output the associated array directly
2841 : VolumeContainer& assVols = m_aaVolumeContainerEDGE[e];
2842 0 : if(assVols.empty())
2843 : vols.clear();
2844 : else
2845 0 : vols.set_external_array(&assVols.front(), assVols.size());
2846 : }
2847 : else{
2848 : // second best: iterate through all volumes associated with the first end-point of e
2849 : // and check for each if it contains e. If so push it into the container.
2850 : // VRTOPT_STORE_ASSOCIATED_VOLUMES has to be enabled for this. Only continue,
2851 : // if volumes exist at all
2852 : vols.clear();
2853 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES)){
2854 : // only enable the option if volumes exist at all
2855 0 : if(num<Volume>() == 0){
2856 : return;
2857 : }
2858 :
2859 : LOG("WARNING in get_associated(volumes, edge): auto-enabling VRTOPT_STORE_ASSOCIATED_VOLUMES." << endl);
2860 0 : vertex_store_associated_volumes(true);
2861 : }
2862 :
2863 : // check as few faces as possible
2864 0 : Vertex* vrt = e->vertex(0);
2865 : /* // This check could be beneficial - however, it probably introduces unnecessary overhead.
2866 : if(m_aaVolumeContainerVERTEX[vrt].size() >
2867 : m_aaVolumeContainerVERTEX[e->vertex(1)].size())
2868 : {
2869 : vrt = e->vertex(1);
2870 : }
2871 : */
2872 :
2873 : VolumeContainer& assVols = m_aaVolumeContainerVERTEX[vrt];
2874 0 : for(size_t i = 0; i < assVols.size(); ++i){
2875 0 : if(VolumeContains(assVols[i], e))
2876 0 : vols.push_back(assVols[i]);
2877 : }
2878 : }
2879 : }
2880 :
2881 0 : void Grid::get_associated(SecureVolumeContainer& vols, Face* f)
2882 : {
2883 : // best option: FACEOPT_STORE_ASSOCIATED_VOLUMES
2884 0 : if(option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES)){
2885 : // we can output the associated array directly
2886 : VolumeContainer& assVols = m_aaVolumeContainerFACE[f];
2887 0 : if(assVols.empty())
2888 : vols.clear();
2889 : else
2890 0 : vols.set_external_array(&assVols.front(), assVols.size());
2891 : }
2892 : else
2893 0 : get_associated_vols_raw(vols, f);
2894 0 : }
2895 :
2896 0 : void Grid::get_associated_vols_raw(SecureVolumeContainer& vols, Face* f)
2897 : {
2898 :
2899 : // iterate through all volumes associated with the first corner of f
2900 : // and check for each if it contains f. If so push it into the container.
2901 : // VRTOPT_STORE_ASSOCIATED_VOLUMES has to be enabled for this. Only continue,
2902 : // if volumes exist at all
2903 : vols.clear();
2904 0 : if(!option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES)){
2905 : // only enable the option if volumes exist at all
2906 0 : if(num<Volume>() == 0){
2907 : return;
2908 : }
2909 :
2910 : LOG("WARNING in get_associated_vols_raw(volumes, face): auto-enabling VRTOPT_STORE_ASSOCIATED_VOLUMES." << endl);
2911 0 : vertex_store_associated_volumes(true);
2912 : }
2913 :
2914 : // check as few faces as possible
2915 0 : Vertex* vrt = f->vertex(0);
2916 :
2917 : VolumeContainer& assVols = m_aaVolumeContainerVERTEX[vrt];
2918 0 : for(size_t i = 0; i < assVols.size(); ++i){
2919 0 : Volume* v = assVols[i];
2920 0 : if(VolumeContains(v, f->vertex(1))){
2921 0 : if(VolumeContains(v, f->vertex(2))){
2922 0 : if(VolumeContains(v, f))
2923 0 : vols.push_back(v);
2924 : }
2925 : }
2926 : }
2927 : }
2928 :
2929 :
2930 : ////////////////////////////////////////////////////////////////////////////////
2931 : // ASSOCIATED SORTED
2932 0 : void Grid::get_associated_sorted(SecureVertexContainer& vrts, Edge* e) const
2933 : {
2934 0 : vrts.set_external_array(e->vertices(), e->num_vertices());
2935 0 : }
2936 :
2937 0 : void Grid::get_associated_sorted(SecureVertexContainer& vrts, Face* f) const
2938 : {
2939 0 : vrts.set_external_array(f->vertices(), f->num_vertices());
2940 0 : }
2941 :
2942 0 : void Grid::get_associated_sorted(SecureVertexContainer& vrts, Volume* v) const
2943 : {
2944 0 : vrts.set_external_array(v->vertices(), v->num_vertices());
2945 0 : }
2946 :
2947 :
2948 0 : void Grid::get_associated_sorted(SecureEdgeContainer& edges, Vertex*)
2949 : {
2950 0 : edges.set_external_array(NULL, 0);
2951 0 : }
2952 :
2953 0 : void Grid::get_associated_sorted(SecureEdgeContainer& edges, Face* f)
2954 : {
2955 : // to improve performance, we first check the grid options.
2956 0 : if(option_is_enabled(FACEOPT_AUTOGENERATE_EDGES
2957 : | FACEOPT_STORE_ASSOCIATED_EDGES))
2958 : {
2959 : // we can output the associated array directly
2960 : EdgeContainer& assEdges = m_aaEdgeContainerFACE[f];
2961 0 : edges.set_external_array(&assEdges.front(), assEdges.size());
2962 : }
2963 : else{
2964 : // clear the container
2965 : edges.clear();
2966 :
2967 : // if no edges are present, we can leave immediately
2968 0 : if(num<Edge>() == 0)
2969 : return;
2970 :
2971 : // get the edges one by one
2972 : uint numEdges = f->num_edges();
2973 0 : for(uint i = 0; i < numEdges; ++i){
2974 0 : Edge* e = get_edge(f, i);
2975 0 : if(e != NULL)
2976 0 : edges.push_back(e);
2977 : }
2978 : }
2979 : }
2980 :
2981 0 : void Grid::get_associated_sorted(SecureEdgeContainer& edges, Volume* v)
2982 : {
2983 : // to improve performance, we first check the grid options.
2984 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_EDGES
2985 : | VOLOPT_STORE_ASSOCIATED_EDGES)
2986 0 : || option_is_enabled(VOLOPT_AUTOGENERATE_FACES
2987 : | FACEOPT_AUTOGENERATE_EDGES
2988 : | VOLOPT_STORE_ASSOCIATED_EDGES))
2989 : {
2990 : // we can output the associated array directly
2991 : EdgeContainer& assEdges = m_aaEdgeContainerVOLUME[v];
2992 0 : edges.set_external_array(&assEdges.front(), assEdges.size());
2993 : }
2994 : else{
2995 : // clear the container
2996 : edges.clear();
2997 :
2998 : // if no edges are present, we can leave immediately
2999 0 : if(num<Edge>() == 0)
3000 : return;
3001 :
3002 : // get the edges one by one
3003 0 : uint numEdges = v->num_edges();
3004 0 : for(uint i = 0; i < numEdges; ++i){
3005 0 : Edge* e = get_edge(v, i);
3006 0 : if(e != NULL)
3007 0 : edges.push_back(e);
3008 : }
3009 : }
3010 : }
3011 :
3012 0 : void Grid::get_associated_sorted(SecureFaceContainer& faces, Vertex*)
3013 : {
3014 0 : faces.set_external_array(NULL, 0);
3015 0 : }
3016 :
3017 0 : void Grid::get_associated_sorted(SecureFaceContainer& faces, Edge*)
3018 : {
3019 0 : faces.set_external_array(NULL, 0);
3020 0 : }
3021 :
3022 0 : void Grid::get_associated_sorted(SecureFaceContainer& faces, Volume* v)
3023 : {
3024 : // to improve performance, we first check the grid options.
3025 0 : if(option_is_enabled(VOLOPT_AUTOGENERATE_FACES
3026 : | VOLOPT_STORE_ASSOCIATED_FACES))
3027 : {
3028 : // we can output the associated array directly
3029 : FaceContainer& assFaces = m_aaFaceContainerVOLUME[v];
3030 0 : faces.set_external_array(&assFaces.front(), assFaces.size());
3031 : }
3032 : else{
3033 : // clear the container
3034 : faces.clear();
3035 :
3036 : // if no edges are present, we can leave immediately
3037 0 : if(num<Face>() == 0)
3038 : return;
3039 :
3040 : // get the edges one by one
3041 0 : uint numFaces = v->num_faces();
3042 0 : for(uint i = 0; i < numFaces; ++i){
3043 0 : Face* f = get_face(v, i);
3044 0 : if(f != NULL)
3045 0 : faces.push_back(f);
3046 : }
3047 : }
3048 : }
3049 :
3050 0 : void Grid::get_associated_sorted(SecureVolumeContainer& vols, Vertex*)
3051 : {
3052 0 : vols.set_external_array(NULL, 0);
3053 0 : }
3054 :
3055 0 : void Grid::get_associated_sorted(SecureVolumeContainer& vols, Edge*)
3056 : {
3057 0 : vols.set_external_array(NULL, 0);
3058 0 : }
3059 :
3060 0 : void Grid::get_associated_sorted(SecureVolumeContainer& vols, Face*)
3061 : {
3062 0 : vols.set_external_array(NULL, 0);
3063 0 : }
3064 :
3065 : } // end of namespace
|