Line data Source code
1 : /*
2 : * Copyright (c) 2010-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 : #ifndef __H__LIB_GRID__SELECTION_UTIL_IMPL__
34 : #define __H__LIB_GRID__SELECTION_UTIL_IMPL__
35 :
36 : #include <vector>
37 : #include <queue>
38 : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
39 : #include "common/util/metaprogramming_util.h"
40 :
41 : namespace ug
42 : {
43 :
44 : ////////////////////////////////////////////////////////////////////////
45 : ////////////////////////////////////////////////////////////////////////
46 : // selection util methods
47 :
48 : ////////////////////////////////////////////////////////////////////////
49 : // CalculateCenter
50 : template <class TAAPosVRT>
51 : bool CalculateCenter(typename TAAPosVRT::ValueType& centerOut,
52 : Selector& sel, TAAPosVRT& aaPos)
53 : {
54 : if(!sel.grid()){
55 : throw(UGError("No grid assigned to selector"));
56 : }
57 :
58 : Grid& grid = *sel.grid();
59 :
60 : // collect all vertices that are adjacent to selected elements
61 : // we have to make sure that each vertex is only counted once.
62 : // we do this by using grid::mark.
63 : grid.begin_marking();
64 :
65 : // std::vector<Vertex*> vrts;
66 : // vrts.assign(sel.vertices_begin(), sel.vertices_end());
67 : // grid.mark(sel.vertices_begin(), sel.vertices_end());
68 :
69 : VecSet(centerOut, 0);
70 : size_t n = 0;
71 : for(VertexIterator iter = sel.vertices_begin();
72 : iter != sel.vertices_end(); ++iter)
73 : {
74 : VecAdd(centerOut, centerOut, aaPos[*iter]);
75 : grid.mark(*iter);
76 : ++n;
77 : }
78 :
79 : for(EdgeIterator iter = sel.edges_begin();
80 : iter != sel.edges_end(); ++iter)
81 : {
82 : Edge::ConstVertexArray vrts = (*iter)->vertices();
83 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
84 : if(!grid.is_marked(vrts[i])){
85 : grid.mark(vrts[i]);
86 : VecAdd(centerOut, centerOut, aaPos[vrts[i]]);
87 : ++n;
88 : }
89 : }
90 : }
91 :
92 : for(FaceIterator iter = sel.faces_begin();
93 : iter != sel.faces_end(); ++iter)
94 : {
95 : Face::ConstVertexArray vrts = (*iter)->vertices();
96 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
97 : if(!grid.is_marked(vrts[i])){
98 : grid.mark(vrts[i]);
99 : VecAdd(centerOut, centerOut, aaPos[vrts[i]]);
100 : ++n;
101 : }
102 : }
103 : }
104 :
105 : for(VolumeIterator iter = sel.volumes_begin();
106 : iter != sel.volumes_end(); ++iter)
107 : {
108 : Volume::ConstVertexArray vrts = (*iter)->vertices();
109 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
110 : if(!grid.is_marked(vrts[i])){
111 : grid.mark(vrts[i]);
112 : VecAdd(centerOut, centerOut, aaPos[vrts[i]]);
113 : ++n;
114 : }
115 : }
116 : }
117 :
118 : grid.end_marking();
119 :
120 : if(n > 0){
121 : VecScale(centerOut, centerOut, 1. / (number)n);
122 : return true;
123 : }
124 : return false;
125 : }
126 :
127 : template <class TAAPosVRT>
128 : void TranslateSelection(Selector& sel, const typename TAAPosVRT::ValueType& offset,
129 : TAAPosVRT& aaPos)
130 : {
131 : if(!sel.grid()){
132 : throw(UGError("No grid assigned to selector"));
133 : }
134 :
135 : Grid& grid = *sel.grid();
136 :
137 : // collect all vertices that are adjacent to selected elements
138 : // we have to make sure that each vertex is only counted once.
139 : // we do this by using grid::mark.
140 : grid.begin_marking();
141 :
142 : for(VertexIterator iter = sel.vertices_begin();
143 : iter != sel.vertices_end(); ++iter)
144 : {
145 : VecAdd(aaPos[*iter], aaPos[*iter], offset);
146 : grid.mark(*iter);
147 : }
148 :
149 : for(EdgeIterator iter = sel.edges_begin();
150 : iter != sel.edges_end(); ++iter)
151 : {
152 : Edge::ConstVertexArray vrts = (*iter)->vertices();
153 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
154 : if(!grid.is_marked(vrts[i])){
155 : grid.mark(vrts[i]);
156 : VecAdd(aaPos[vrts[i]], aaPos[vrts[i]], offset);
157 : }
158 : }
159 : }
160 :
161 : for(FaceIterator iter = sel.faces_begin();
162 : iter != sel.faces_end(); ++iter)
163 : {
164 : Face::ConstVertexArray vrts = (*iter)->vertices();
165 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
166 : if(!grid.is_marked(vrts[i])){
167 : grid.mark(vrts[i]);
168 : VecAdd(aaPos[vrts[i]], aaPos[vrts[i]], offset);
169 : }
170 : }
171 : }
172 :
173 : for(VolumeIterator iter = sel.volumes_begin();
174 : iter != sel.volumes_end(); ++iter)
175 : {
176 : Volume::ConstVertexArray vrts = (*iter)->vertices();
177 : for(size_t i = 0; i < (*iter)->num_vertices(); ++i){
178 : if(!grid.is_marked(vrts[i])){
179 : grid.mark(vrts[i]);
180 : VecAdd(aaPos[vrts[i]], aaPos[vrts[i]], offset);
181 : }
182 : }
183 : }
184 :
185 : grid.end_marking();
186 : }
187 :
188 : ////////////////////////////////////////////////////////////////////////
189 : // InvertSelection
190 : template <class TSelector, class TIterator>
191 0 : void InvertSelection(TSelector& sel, TIterator begin, TIterator end)
192 : {
193 0 : for(TIterator iter = begin; iter != end;){
194 : // be careful - since iterator could be an iterator of the selector,
195 : // we have to make sure, that we will not invalidate it.
196 : typename TIterator::value_type v = *iter;
197 : ++iter;
198 :
199 0 : if(sel.is_selected(v))
200 0 : sel.deselect(v);
201 : else
202 0 : sel.select(v);
203 : }
204 0 : }
205 :
206 : ////////////////////////////////////////////////////////////////////////
207 : template <class TElem, class TIterator>
208 : void
209 0 : SelectAssociated(ISelector& sel, TIterator begin, TIterator end,
210 : ISelector::status_t status)
211 : {
212 : Grid* pGrid = sel.grid();
213 0 : if(!pGrid)
214 0 : return;
215 :
216 : Grid& grid = *pGrid;
217 : std::vector<TElem*> elems;
218 0 : for(TIterator iter = begin; iter != end; ++iter){
219 : CollectAssociated(elems, grid, *iter);
220 0 : for(size_t i = 0; i < elems.size(); ++i){
221 0 : sel.select(elems[i], status);
222 : }
223 : }
224 0 : }
225 :
226 : ////////////////////////////////////////////////////////////////////////
227 : // SelectAssociatedVertices
228 : template <class TSelector, class TElemIterator>
229 0 : void SelectAssociatedVertices(TSelector& sel, TElemIterator elemsBegin,
230 : TElemIterator elemsEnd, ISelector::status_t status)
231 : {
232 0 : while(elemsBegin != elemsEnd)
233 : {
234 0 : uint numVrts = (*elemsBegin)->num_vertices();
235 0 : for(uint i = 0; i < numVrts; ++i)
236 0 : sel.select((*elemsBegin)->vertex(i), status);
237 : elemsBegin++;
238 : }
239 0 : }
240 :
241 : ////////////////////////////////////////////////////////////////////////
242 : // SelectAssociatedEdges
243 : template <class TSelector, class TElemIterator>
244 0 : void SelectAssociatedEdges(TSelector& sel, TElemIterator elemsBegin,
245 : TElemIterator elemsEnd, ISelector::status_t status)
246 : {
247 : Grid* pGrid = sel.grid();
248 0 : if(pGrid)
249 : {
250 : Grid& grid = *pGrid;
251 : std::vector<Edge*> vEdges;
252 0 : while(elemsBegin != elemsEnd)
253 : {
254 0 : CollectEdges(vEdges, grid, *elemsBegin);
255 0 : for(uint i = 0; i < vEdges.size(); ++i)
256 0 : sel.select(vEdges[i], status);
257 : elemsBegin++;
258 : }
259 0 : }
260 0 : }
261 :
262 : ////////////////////////////////////////////////////////////////////////
263 : // SelectAssociatedFaces
264 : template <class TSelector, class TElemIterator>
265 0 : void SelectAssociatedFaces(TSelector& sel, TElemIterator elemsBegin,
266 : TElemIterator elemsEnd, ISelector::status_t status)
267 : {
268 : Grid* pGrid = sel.grid();
269 0 : if(pGrid)
270 : {
271 : Grid& grid = *pGrid;
272 : std::vector<Face*> vFaces;
273 0 : while(elemsBegin != elemsEnd)
274 : {
275 0 : CollectFaces(vFaces, grid, *elemsBegin);
276 0 : for(uint i = 0; i < vFaces.size(); ++i)
277 0 : sel.select(vFaces[i], status);
278 : elemsBegin++;
279 : }
280 0 : }
281 0 : }
282 :
283 : ////////////////////////////////////////////////////////////////////////
284 : // SelectAssociatedFaces
285 : template <class TSelector, class TElemIterator>
286 : void SelectAssociatedVolumes(TSelector& sel, TElemIterator elemsBegin,
287 : TElemIterator elemsEnd, ISelector::status_t status)
288 : {
289 : SelectAssociated<Volume>(sel, elemsBegin, elemsEnd, status);
290 : }
291 :
292 :
293 : template <class TElem, class TSelector>
294 : void AssignSelectionStateToSides(TSelector& sel, bool recursive)
295 : {
296 : typedef typename TSelector::template traits<TElem>::level_iterator TIter;
297 : typedef typename TElem::side TSide;
298 :
299 : UG_ASSERT(sel.grid(), "A selector has to operate on a grid");
300 :
301 : Grid& g = *sel.grid();
302 : typename Grid::traits<TSide>::secure_container sides;
303 :
304 : for(size_t lvl = 0; lvl < sel.num_levels(); ++lvl){
305 : for(TIter iter = sel.template begin<TElem>(lvl);
306 : iter != sel.template end<TElem>(lvl); ++iter)
307 : {
308 : TElem* e = *iter;
309 : ISelector::status_t elemStatus = sel.get_selection_status(e);
310 : g.associated_elements(sides, e);
311 :
312 : for(size_t i = 0; i < sides.size(); ++i){
313 : ISelector::status_t sideStatus = sel.get_selection_status(sides[i]);
314 : sel.select(sides[i], elemStatus | sideStatus);
315 : }
316 : }
317 : }
318 :
319 : if(recursive && TSide::HAS_SIDES){
320 : AssignSelectionStateToSides<TSide>(sel, recursive);
321 : }
322 : }
323 :
324 :
325 : template <class TElemIterator>
326 0 : void SelectBoundaryElements(ISelector& sel, TElemIterator elemsBegin,
327 : TElemIterator elemsEnd)
328 : {
329 : UG_ASSERT(sel.grid(), "A grid has to be associated with the selector");
330 : Grid& grid = *sel.grid();
331 :
332 0 : for(TElemIterator iter = elemsBegin; iter != elemsEnd; ++iter){
333 : typename TElemIterator::value_type e = *iter;
334 0 : if(LiesOnBoundary(grid, e)){
335 : sel.select(e);
336 : }
337 : }
338 0 : }
339 :
340 : template <class TElemIterator>
341 : void SelectInnerElements(ISelector& sel, TElemIterator elemsBegin,
342 : TElemIterator elemsEnd)
343 : {
344 : UG_ASSERT(sel.grid(), "A grid has to be associated with the selector");
345 : Grid& grid = *sel.grid();
346 :
347 : for(TElemIterator iter = elemsBegin; iter != elemsEnd; ++iter){
348 : typename TElemIterator::value_type e = *iter;
349 : if(!LiesOnBoundary(grid, e)){
350 : sel.select(e);
351 : }
352 : }
353 : }
354 :
355 :
356 :
357 : template <class TSelector, class TAAPos>
358 : void ExtendSelectionInDirection(
359 : TSelector& sel,
360 : size_t extSize,
361 : const typename TAAPos::ValueType& dir,
362 : number minAngle,
363 : number maxAngle,
364 : const TAAPos& aaPos,
365 : ISelector::status_t status)
366 : {
367 : if(!sel.grid()){
368 : UG_LOG("ERROR in ExtendSelection: Selector has to be assigned to a grid.\n");
369 : return;
370 : }
371 :
372 : Grid& grid = *sel.grid();
373 :
374 : // first select associated elements of volumes, faces and edges.
375 : // then select associated elements of selected vertices.
376 : // do this extSize times.
377 : // elements that have already been processed are marked.
378 :
379 : grid.begin_marking();
380 :
381 : // perform iteration
382 : for(size_t extIters = 0; extIters < extSize; ++extIters)
383 : {
384 : //TODO: speed-up by only calling SelectAssociatedGridObjects once before the loop.
385 : // During the loop only newly selected elements should be checked for associated elements.
386 :
387 : // select associated elements
388 : SelectAssociatedGridObjects(sel, status);
389 :
390 : // iterate over all selected vertices.
391 : for(size_t lvl = 0; lvl < sel.num_levels(); ++lvl){
392 : for(VertexIterator iter = sel.template begin<Vertex>(lvl);
393 : iter != sel.template end<Vertex>(lvl); ++iter)
394 : {
395 : Vertex* vrt = *iter;
396 : // all marked vertices have already been processed.
397 : if(!grid.is_marked(vrt)){
398 : grid.mark(vrt);
399 :
400 : // select associated volumes, faces and edges.
401 : for(Grid::AssociatedEdgeIterator asIter = grid.associated_edges_begin(vrt);
402 : asIter != grid.associated_edges_end(vrt); ++asIter)
403 : {
404 : if(CheckDirection(vrt, *asIter, aaPos, dir, minAngle, maxAngle))
405 : sel.select(*asIter, status);
406 : }
407 :
408 : for(Grid::AssociatedFaceIterator asIter = grid.associated_faces_begin(vrt);
409 : asIter != grid.associated_faces_end(vrt); ++asIter)
410 : {
411 : if(CheckDirection(vrt, *asIter, aaPos, dir, minAngle, maxAngle))
412 : sel.select(*asIter, status);
413 : }
414 :
415 : for(Grid::AssociatedVolumeIterator asIter = grid.associated_volumes_begin(vrt);
416 : asIter != grid.associated_volumes_end(vrt); ++asIter)
417 : {
418 : if(CheckDirection(vrt, *asIter, aaPos, dir, minAngle, maxAngle))
419 : sel.select(*asIter, status);
420 : }
421 : }
422 : }
423 : }
424 : }
425 :
426 : grid.end_marking();
427 : }
428 :
429 : ////////////////////////////////////////////////////////////////////////
430 : template <class TAAPos>
431 : void SelectEdgesByDirection(
432 : Selector& sel,
433 : TAAPos& aaPos,
434 : const vector3& dir,
435 : number minDeviationAngle,
436 : number maxDeviationAngle,
437 : bool selectFlipped)
438 : {
439 :
440 : UG_COND_THROW(!sel.grid(), "A grid has to be assigned to the given selector");
441 :
442 : Grid& g = *sel.grid();
443 : vector3 n;
444 : VecNormalize(n, dir);
445 :
446 : number maxDot = cos(deg_to_rad(minDeviationAngle));
447 : number minDot = cos(deg_to_rad(maxDeviationAngle));
448 :
449 : lg_for_each(Edge, e, g){
450 : vector3 dir;
451 : VecSubtract(dir, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
452 : VecNormalize(dir, dir);
453 : number d = VecDot(dir, n);
454 : if((d >= minDot - SMALL && d <= maxDot + SMALL) ||
455 : (selectFlipped && (-d >= minDot - SMALL && -d <= maxDot + SMALL)))
456 : {
457 : sel.select(e);
458 : }
459 : }lg_end_for;
460 : }
461 :
462 : ////////////////////////////////////////////////////////////////////////
463 : template <class TAAPos>
464 : void SelectSubsetEdgesByDirection(
465 : Selector& sel,
466 : SubsetHandler& sh,
467 : int subsetIndex,
468 : TAAPos& aaPos,
469 : const vector3& dir,
470 : number minDeviationAngle,
471 : number maxDeviationAngle,
472 : bool selectFlipped)
473 : {
474 :
475 : UG_COND_THROW(!sel.grid(), "A grid has to be assigned to the given selector");
476 :
477 : vector3 n;
478 : VecNormalize(n, dir);
479 :
480 : number maxDot = cos(deg_to_rad(minDeviationAngle));
481 : number minDot = cos(deg_to_rad(maxDeviationAngle));
482 :
483 : lg_for_each_in_subset(Edge, e, sh, subsetIndex){
484 : vector3 dir;
485 : VecSubtract(dir, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
486 : VecNormalize(dir, dir);
487 : number d = VecDot(dir, n);
488 : if((d >= minDot - SMALL && d <= maxDot + SMALL) ||
489 : (selectFlipped && (-d >= minDot - SMALL && -d <= maxDot + SMALL)))
490 : {
491 : sel.select(e);
492 : }
493 : }lg_end_for;
494 : }
495 :
496 :
497 : ////////////////////////////////////////////////////////////////////////
498 : template <class TEdgeIterator>
499 : void SelectCreaseEdges(ISelector& sel, TEdgeIterator edgesBegin, TEdgeIterator edgesEnd,
500 : number minAngle, APosition aPos,
501 : bool ignoreBoundaryEdges, ISelector::status_t state)
502 : {
503 : if(!sel.grid())
504 : return;
505 :
506 : Grid& grid = *sel.grid();
507 :
508 : // get the position accessor
509 : if(!grid.has_vertex_attachment(aPos))
510 : return;
511 :
512 : Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);
513 :
514 : // we'll store face normals in those vectors:
515 : vector3 n[2];
516 :
517 : // associated faces are stored in this array
518 : Face* f[2];
519 :
520 : // all dot-products between normals lower than minDot mark a crease.
521 : number minDot = cos(minAngle * 3.14159265 / 180.f);
522 :
523 : // iterate through the edges
524 : for(TEdgeIterator iter = edgesBegin; iter != edgesEnd; ++iter)
525 : {
526 : Edge* e = *iter;
527 : if(!(ignoreBoundaryEdges && IsBoundaryEdge2D(grid, e))){
528 : // get the associated faces
529 : // all edges that do not have exactly 2 associated edges
530 : // are regarded as crease-edges
531 : if(GetAssociatedFaces(f, grid, e, 2) == 2){
532 : // get the normals of the associated faces
533 : CalculateNormal(n[0], f[0], aaPos);
534 : CalculateNormal(n[1], f[1], aaPos);
535 : // if the dot-product is lower than minDot, then the edge is a crease edge.
536 : if(VecDot(n[0], n[1]) < minDot)
537 : sel.select(e, state);
538 : }
539 : else{
540 : sel.select(e, state);
541 : }
542 : }
543 : }
544 : }
545 :
546 :
547 : ////////////////////////////////////////////////////////////////////////
548 : template <class TIter>
549 0 : void SelectAreaBoundary(ISelector& sel, const TIter begin, const TIter end)
550 : {
551 : typedef typename Pointer2Value<typename TIter::value_type>::type TElem;
552 : typedef typename TElem::side TSide;
553 :
554 0 : if(!sel.grid())
555 0 : return;
556 :
557 : Grid& grid = *sel.grid();
558 :
559 0 : grid.begin_marking();
560 :
561 : std::vector<TSide*> sides;
562 : TIter iter = begin;
563 0 : while(iter != end){
564 : TElem* elem = *iter;
565 : ++iter;
566 : CollectAssociated(sides, grid, elem);
567 0 : for(size_t i = 0; i < sides.size(); ++i){
568 0 : TSide* side = sides[i];
569 0 : if(!grid.is_marked(side)){
570 : // if the side was initially selected, it should stay that way
571 0 : if(!sel.is_selected(side)){
572 : grid.mark(side);
573 : sel.select(side);
574 : }
575 : }
576 : else{
577 : // if the side is marked, then it is an inner side
578 0 : sel.deselect(side);
579 : }
580 : }
581 : }
582 :
583 0 : grid.end_marking();
584 0 : }
585 :
586 : ////////////////////////////////////////////////////////////////////////
587 : template <class TIter>
588 0 : void SelectInterfaceElements(ISelector& sel, ISubsetHandler& sh,
589 : const TIter begin, const TIter end,
590 : bool regardSelectedNbrsOnly)
591 : {
592 : typedef typename Pointer2Value<typename TIter::value_type>::type TElem;
593 : typedef typename TElem::sideof TNbr;
594 :
595 : if(!TElem::CAN_BE_SIDE)
596 0 : return;
597 :
598 0 : if(!sel.grid())
599 : return;
600 :
601 : Grid& grid = *sel.grid();
602 :
603 : std::vector<TNbr*> nbrs;
604 :
605 0 : for(TIter iter = begin; iter != end;){
606 : TElem* elem = *iter;
607 : ++iter;
608 :
609 : CollectAssociated(nbrs, grid, elem);
610 :
611 : int si = -2;
612 0 : for(size_t i = 0; i < nbrs.size(); ++i){
613 0 : if(!regardSelectedNbrsOnly || sel.is_selected(nbrs[i])){
614 0 : if(sh.get_subset_index(nbrs[i]) != si){
615 0 : if(si == -2)
616 0 : si = sh.get_subset_index(nbrs[i]);
617 : else{
618 : // elem is an interface element
619 : sel.select(elem);
620 : break;
621 : }
622 : }
623 : }
624 : }
625 : }
626 0 : }
627 :
628 : template <class TElem>
629 0 : void SelectSubsetElements(ISelector& sel, ISubsetHandler& sh, int subsetIndex,
630 : ISelector::status_t status)
631 : {
632 : typedef typename GridObjectCollection::traits<TElem>::iterator TIter;
633 0 : GridObjectCollection goc = sh.get_grid_objects_in_subset(subsetIndex);
634 :
635 0 : for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){
636 0 : for(TIter iter = goc.begin<TElem>(lvl); iter != goc.end<TElem>(lvl); ++iter)
637 0 : sel.select(*iter, status);
638 : }
639 0 : }
640 :
641 :
642 : template <class TGeomObj, class TAAPos>
643 : bool SelectRegion(Selector& sel, const typename TAAPos::ValueType& p, TAAPos& aaPos,
644 : typename Grid::traits<typename TGeomObj::side>::callback cbRegionBoundary)
645 : {
646 : typedef typename Grid::traits<TGeomObj>::iterator TIter;
647 :
648 : if(!sel.grid())
649 : return false;
650 :
651 : Grid& g = *sel.grid();
652 :
653 : // first try to find the element which contains p
654 : TGeomObj* startElem = NULL;
655 : for(TIter iter = g.begin<TGeomObj>(); iter != g.end<TGeomObj>(); ++iter){
656 : if(ContainsPoint(*iter, p, aaPos)){
657 : startElem = *iter;
658 : break;
659 : }
660 : }
661 :
662 : if(!startElem)
663 : return false;
664 :
665 : sel.clear<TGeomObj>();
666 : sel.select(startElem);
667 : SelectionFill<TGeomObj>(sel, cbRegionBoundary);
668 :
669 : return true;
670 : }
671 :
672 : template <class TAAPos>
673 : void SelectShortPolychains(ISelector& sel, number maxLength, bool closedChainsOnly,
674 : TAAPos aaPos)
675 : {
676 : if(!sel.grid())
677 : return;
678 : Grid& grid = *sel.grid();
679 :
680 : // we'll collect all contained short polychains in this vector before deciding
681 : // to select them or not. If a polychain is already longer than maxLength
682 : // we won't add its edges to the vector
683 : std::vector<Edge*> curChain;
684 : std::queue<Edge*> nextEdges;
685 : Grid::edge_traits::secure_container edges;
686 :
687 : std::vector<Vertex*> junctionPoints;
688 :
689 : grid.begin_marking();
690 :
691 : for(EdgeIterator eiter = grid.begin<Edge>(); eiter != grid.end<Edge>(); ++eiter){
692 : if(grid.is_marked(*eiter))
693 : continue;
694 :
695 : bool curChainIsClosed = true;
696 : number curChainLength = 0;
697 :
698 : curChain.clear();
699 : junctionPoints.clear();
700 :
701 : nextEdges.push(*eiter);
702 : grid.mark(*eiter);
703 :
704 : while(!nextEdges.empty()){
705 : Edge* e = nextEdges.front();
706 : nextEdges.pop();
707 :
708 : curChainLength += EdgeLength(e, aaPos);
709 : if(curChainLength <= maxLength)
710 : curChain.push_back(e);
711 :
712 : for(size_t ivrt = 0; ivrt < 2; ++ivrt){
713 : Vertex* vrt = e->vertex(ivrt);
714 : grid.associated_elements(edges, vrt);
715 : if(edges.size() < 2)
716 : curChainIsClosed = false;
717 : else if(edges.size() == 2){
718 : for(size_t iedge = 0; iedge < 2; ++iedge){
719 : Edge* nextEdge = edges[iedge];
720 : if(!grid.is_marked(nextEdge)){
721 : grid.mark(nextEdge);
722 : nextEdges.push(nextEdge);
723 : }
724 : }
725 : }
726 : else{
727 : junctionPoints.push_back(vrt);
728 : }
729 : }
730 : }
731 :
732 : if((curChainLength <= maxLength)){
733 : if(closedChainsOnly && curChainIsClosed && !junctionPoints.empty()){
734 : // count the number of associated edges of each junction-point
735 : // in curChain. If one is associated with != 2 vertices the chain
736 : // is considered as not closed
737 : for(size_t ivrt = 0; ivrt < junctionPoints.size(); ++ivrt){
738 : Vertex* vrt = junctionPoints[ivrt];
739 : size_t numConnectedEdges = 0;
740 : for(size_t iedge = 0; iedge < curChain.size(); ++iedge){
741 : if(EdgeContains(curChain[iedge], vrt))
742 : ++numConnectedEdges;
743 : }
744 :
745 : if(numConnectedEdges != 2){
746 : curChainIsClosed = false;
747 : break;
748 : }
749 : }
750 :
751 : }
752 :
753 : if(curChainIsClosed || !closedChainsOnly)
754 : sel.select(curChain.begin(), curChain.end());
755 : }
756 : }
757 :
758 : grid.end_marking();
759 : }
760 :
761 : template <class TElem>
762 : void SelectLinkedElements(ISelector& sel,
763 : typename Grid::traits<TElem>::callback cbIsSelectable,
764 : typename Grid::traits<typename TElem::side>::callback cbIsTraversable)
765 : {
766 : using namespace std;
767 : typedef typename Grid::traits<TElem>::iterator ElemIter;
768 : typedef typename TElem::side Side;
769 :
770 : if(!sel.grid())
771 : return;
772 : Grid& grid = *sel.grid();
773 :
774 : queue<TElem*> qElems;
775 :
776 : // add all currently selected elements to the qElems queue
777 : GridObjectCollection goc = sel.get_grid_objects();
778 : for(size_t i = 0; i < goc.num_levels(); ++i){
779 : for(ElemIter iter = goc.begin<TElem>(i); iter != goc.end<TElem>(i); ++iter)
780 : qElems.push(*iter);
781 : }
782 :
783 : typename Grid::traits<TElem>::secure_container nbrs;
784 : typename Grid::traits<Side>::secure_container sides;
785 :
786 : while(!qElems.empty()){
787 : TElem* e = qElems.front();
788 : qElems.pop();
789 :
790 : grid.associated_elements(sides, e);
791 :
792 : for(size_t i_side = 0; i_side < sides.size(); ++i_side){
793 : Side* side = sides[i_side];
794 : // if stopAtSelectedSides is active and if the side is selected,
795 : // we won't traverse it.
796 : if(!cbIsTraversable(side))
797 : continue;
798 :
799 : // get all neighboring elements of side. Check for each unselected,
800 : // whether it lies on a boundary. If it does, select it and push it
801 : // to the queue.
802 : grid.associated_elements(nbrs, side);
803 :
804 : for(size_t i_nbr = 0; i_nbr < nbrs.size(); ++i_nbr){
805 : TElem* nbr = nbrs[i_nbr];
806 : if(sel.is_selected(nbr))
807 : continue;
808 : if(!cbIsSelectable(nbr))
809 : continue;
810 :
811 : // we found a new linked boundary element
812 : sel.select(nbr);
813 : qElems.push(nbr);
814 : }
815 : }
816 : }
817 : }
818 :
819 : template <class TAAPosVRT>
820 : UG_API
821 0 : number FaceArea(ISelector& sel, TAAPosVRT& aaPos)
822 : {
823 : number sum = 0.;
824 :
825 0 : if(!sel.grid()) {
826 : UG_WARNING("A grid has to be associated with the selector!");
827 : return sum;
828 : }
829 :
830 : typedef Grid::traits<Face>::const_iterator FaceIter;
831 0 : GridObjectCollection goc = sel.get_grid_objects();
832 :
833 0 : for(size_t i = 0; i < goc.num_levels(); ++i)
834 0 : for(FaceIter iter = goc.begin<Face>(i); iter != goc.end<Face>(i); ++iter)
835 0 : sum += FaceArea(*iter, aaPos);
836 :
837 : return sum;
838 : }
839 :
840 : }// end of namespace
841 :
842 : #endif
|