Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
element_angles.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2018: G-CSC, Goethe University Frankfurt
3 * Author: Martin Stepniewski
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__UG_ELEMENT_ANGLES
34#define __H__UG_ELEMENT_ANGLES
35
36#ifdef UG_PARALLEL
38#endif
39
40/* system includes */
41#include <stddef.h>
42#include <cmath>
43#include <stdlib.h>
44#include <stdio.h>
45#include <string.h>
46#include <fstream>
47#include <vector>
48#include <string>
49#include <algorithm>
50
51#include "lib_grid/lib_grid.h"
52
53
54using namespace std;
55
56
57namespace ug {
58
59
60
62// CollectAssociatedSides
64
66
68inline void CollectAssociatedSides(Edge* sidesOut[2], Grid& grid, Face* f, Vertex* vrt)
69{
70 //PROFILE_BEGIN(CollectAssociatedSides_VERTEX);
71 sidesOut[0] = NULL;
72 sidesOut[1] = NULL;
73
74 grid.begin_marking();
75 for(size_t i = 0; i < f->num_vertices(); ++i){
76 grid.mark(f->vertex(i));
77 }
78
79 //vector<Edge*> vNeighbourEdgesToVertex;
80 //CollectAssociated(vNeighbourEdgesToVertex, grid, vrt, true);
81
83 //Grid::AssociatedEdgeIterator iterEnd = vNeighbourEdgesToVertex.end();
84 for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(vrt); iter != iterEnd; ++iter)
85 //for(Grid::AssociatedEdgeIterator iter = vNeighbourEdgesToVertex.begin(); iter != iterEnd; ++iter)
86 {
87 Edge* e = *iter;
88 if(grid.is_marked(e->vertex(0)) && grid.is_marked(e->vertex(1))){
89 UG_ASSERT( sidesOut[1] == NULL,
90 "Only two edges may be adjacent to a vertex in a face element.");
91
92 if(sidesOut[0] == NULL)
93 sidesOut[0] = e;
94 else
95 sidesOut[1] = e;
96 }
97 }
98
99 grid.end_marking();
100 UG_ASSERT( sidesOut[1] != NULL,
101 "Exactly two edges should be adjacent to a vertex in a face element.")
102}
103
105
106UG_API
107inline void CollectAssociatedSides(Face* sidesOut[2], Grid& grid, Volume* v, Edge* e)
108{
109 //PROFILE_BEGIN(CollectAssociatedSides_EDGE);
110 sidesOut[0] = NULL;
111 sidesOut[1] = NULL;
112
113 grid.begin_marking();
114
115 for(size_t i = 0; i < v->num_vertices(); ++i)
116 grid.mark(v->vertex(i));
117
118 vector<Face*> vNeighbourFacesToEdge;
119 CollectAssociated(vNeighbourFacesToEdge, grid, e, true);
120
121 //Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(e);
122 Grid::AssociatedFaceIterator iterEnd = vNeighbourFacesToEdge.end();
123 //for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(e); iter != iterEnd; ++iter)
124 for(Grid::AssociatedFaceIterator iter = vNeighbourFacesToEdge.begin(); iter != iterEnd; ++iter)
125 {
126 Face* f = *iter;
127
128 // check whether all vertices of f are marked
129 bool allMarked = true;
130 for(size_t i = 0; i < f->num_vertices(); ++i){
131 if(!grid.is_marked(f->vertex(i))){
132 allMarked = false;
133 break;
134 }
135 }
136
137 if(allMarked){
138 if(FaceContains(f, e)){
139 UG_ASSERT( sidesOut[1] == NULL,
140 "Only two faces may be adjacent to an edge in a volume element.")
141
142 if(sidesOut[0] == NULL)
143 sidesOut[0] = f;
144 else
145 sidesOut[1] = f;
146 }
147 }
148 }
149
150 grid.end_marking();
151
152 UG_ASSERT( sidesOut[1] != NULL,
153 "Exactly two faces should be adjacent to an edge in a volume element.")
154}
155
156
158// CalculateMinAngle
160
162template <class TElem, class TAAPosVRT>
163number CalculateMinAngle(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
164
166template <class TAAPosVRT>
167number CalculateMinAngle(Grid& grid, Face* f, TAAPosVRT& aaPos)
168{
169 //PROFILE_FUNC();
170
178 {
179 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
181 }
182
183// Get type of vertex attachment in aaPos and define it as ValueType
184 typedef typename TAAPosVRT::ValueType ValueType;
185
186// Initialization
187 uint numFaceVrts = f->num_vertices();
188 ValueType vNorm1, vNorm2;
189 ValueType vDir1, vDir2;
190 number minAngle = 180.0;
191 number tmpAngle;
192 Edge* vNeighbourEdgesToVertex[2];
193 Vertex* adjacentVrt1;
194 Vertex* adjacentVrt2;
195
196// Iterate over all face vertices
197 for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
198 {
199 Vertex* vrt = f->vertex(vrtIter);
200
201 // Get adjacent edges at the current vertex and calculate the angle between their normals
202 CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
203
204 // Calculate vDir vectors of the current two adjacent edges
205 // !!! Beware of the correct order of the vertices to get correct angle value !!!
206 if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
207 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
208 else
209 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
210
211 if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
212 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
213 else
214 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
215
216 VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
217 VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
218
219 // Normalize
220 VecNormalize(vDir1, vDir1);
221 VecNormalize(vDir2, vDir2);
222
223 // Calculate current angle
224 tmpAngle = acos(VecDot(vDir1, vDir2));
225
226 // Check for minimality
227 if(tmpAngle < minAngle)
228 {
229 minAngle = tmpAngle;
230 }
231 }
232
233// Transform minAngle from RAD to DEG
234 minAngle = 180/PI * minAngle;
235
236 return minAngle;
237}
238
240// INFO: For volume elements the minimal angle corresponds to the smallest dihedral
242
244template <class TAAPosVRT>
245number CalculateMinAngle(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
246{
247 return CalculateMinDihedral(grid, static_cast<Volume*>(tet), aaPos);
248}
249
251template <class TAAPosVRT>
252number CalculateMinAngle(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
253{
254 return CalculateMinDihedral(grid, static_cast<Volume*>(prism), aaPos);
255}
256
258template <class TAAPosVRT>
259number CalculateMinAngle(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
260{
261 return CalculateMinDihedral(grid, static_cast<Volume*>(pyr), aaPos);
262}
263
265template <class TAAPosVRT>
266number CalculateMinAngle(Grid& grid, Hexahedron* hex, TAAPosVRT& aaPos)
267{
268 return CalculateMinDihedral(grid, static_cast<Volume*>(hex), aaPos);
269}
270
272template <class TAAPosVRT>
273number CalculateMinAngle(Grid& grid, Volume* vol, TAAPosVRT& aaPos)
274{
275 return CalculateMinDihedral(grid, vol, aaPos);
276}
277
278
280// CalculateMinDihedral
282
284template <class TElem, class TAAPosVRT>
285number CalculateMinDihedral(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
286
288template <class TAAPosVRT>
289number CalculateMinDihedral(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
290{
291 return CalculateMinDihedral(grid, static_cast<Volume*>(tet), aaPos);
292}
293
295template <class TAAPosVRT>
296number CalculateMinDihedral(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
297{
298 return CalculateMinDihedral(grid, static_cast<Volume*>(prism), aaPos);
299}
300
302template <class TAAPosVRT>
303number CalculateMinDihedral(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
304{
305 return CalculateMinDihedral(grid, static_cast<Volume*>(pyr), aaPos);
306}
307
309template <class TAAPosVRT>
310number CalculateMinDihedral(Grid& grid, Hexahedron* hex, TAAPosVRT& aaPos)
311{
312 return CalculateMinDihedral(grid, static_cast<Volume*>(hex), aaPos);
313}
314
316template <class TAAPosVRT>
317number CalculateMinDihedral(Grid& grid, Volume* v, TAAPosVRT& aaPos)
318{
319 //PROFILE_FUNC();
320
328 {
329 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
331 }
332
333// Initialization
334 uint numElementEdges = v->num_edges();
335 vector3 vNorm1, vNorm2;
336 number minDihedral = 360.0;
337 number tmpAngle;
338 Face* vNeighbourFacesToEdge[2];
339
340// Iterate over all element edges
341 for(uint eIter = 0; eIter < numElementEdges; ++eIter)
342 {
343 Edge* e = grid.get_edge(v, eIter);
344
345 // Get adjacent faces at the current edge and calculate the angle between their normals
346 // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
347 CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
348
349 Vertex* adjacentVrt1;
350 Vertex* adjacentVrt2;
351 vector3 vDir1;
352 vector3 vDir2;
353 vector3 vDir3;
354
355 // Get vertex of each associated face, which is not part of the given edge
356 for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
357 {
358 if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
359 adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
360 }
361
362 for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
363 {
364 if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
365 adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
366 }
367
368 VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
369 VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
370 VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
371
372 VecCross(vNorm1, vDir1, vDir2);
373 VecCross(vNorm2, vDir1, vDir3);
374
375 VecNormalize(vNorm1, vNorm1);
376 VecNormalize(vNorm2, vNorm2);
377
378 tmpAngle = acos(VecDot(vNorm1, vNorm2));
379 tmpAngle = PI - tmpAngle;
380
381 // Check for minimality
382 if(tmpAngle < minDihedral)
383 {
384 minDihedral = tmpAngle;
385 }
386 }
387
388// Transform minAngle from RAD to DEG
389 minDihedral = 180/PI * minDihedral;
390
391 return minDihedral;
392}
393
394
396// CalculateMaxAngle
398
400template <class TElem, class TAAPosVRT>
401number CalculateMaxAngle(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
402
404template <class TAAPosVRT>
405number CalculateMaxAngle(Grid& grid, Face* f, TAAPosVRT& aaPos)
406{
407 //PROFILE_FUNC();
408
416 {
417 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
419 }
420
421// Get type of vertex attachment in aaPos and define it as ValueType
422 typedef typename TAAPosVRT::ValueType ValueType;
423
424// Initialization
425 uint numFaceVrts = f->num_vertices();
426 ValueType vNorm1, vNorm2;
427 ValueType vDir1, vDir2;
428 number maxAngle = 0;
429 number tmpAngle;
430 Edge* vNeighbourEdgesToVertex[2];
431 Vertex* adjacentVrt1;
432 Vertex* adjacentVrt2;
433
434// Iterate over all face vertices
435 for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
436 {
437 Vertex* vrt = f->vertex(vrtIter);
438
439 // Get adjacent edges at the current vertex and calculate the angle between their normals
440 CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
441
442 // Calculate vExtrDir vectors of the current two adjacent edges
443 // !!! Beware of the correct order of the vertices to get correct angle value !!!
444 if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
445 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
446 else
447 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
448
449 if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
450 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
451 else
452 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
453
454 VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
455 VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
456
457 // Normalize
458 VecNormalize(vDir1, vDir1);
459 VecNormalize(vDir2, vDir2);
460
461 // Calculate current angle
462 tmpAngle = acos(VecDot(vDir1, vDir2));
463
464 // Check for maximality
465 if(tmpAngle > maxAngle)
466 {
467 maxAngle = tmpAngle;
468 }
469 }
470
471// Transform maxAngle from RAD to DEG
472 maxAngle = 180/PI * maxAngle;
473
474 return maxAngle;
475}
476
478// INFO: For volume elements the maxAngle corresponds to the largest dihedral
480
482template <class TAAPosVRT>
483number CalculateMaxAngle(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
484{
485 return CalculateMaxDihedral(grid, static_cast<Volume*>(tet), aaPos);
486}
487
489template <class TAAPosVRT>
490number CalculateMaxAngle(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
491{
492 return CalculateMaxDihedral(grid, static_cast<Volume*>(prism), aaPos);
493}
494
496template <class TAAPosVRT>
497number CalculateMaxAngle(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
498{
499 return CalculateMaxDihedral(grid, static_cast<Volume*>(pyr), aaPos);
500}
501
503template <class TAAPosVRT>
504number CalculateMaxAngle(Grid& grid, Volume* vol, TAAPosVRT& aaPos)
505{
506 return CalculateMaxDihedral(grid, vol, aaPos);
507}
508
509
511// CalculateMaxDihedral
513
515template <class TElem, class TAAPosVRT>
516number CalculateMaxDihedral(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
517
519template <class TAAPosVRT>
520number CalculateMaxDihedral(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
521{
522 return CalculateMaxDihedral(grid, static_cast<Volume*>(tet), aaPos);
523}
524
526template <class TAAPosVRT>
527number CalculateMaxDihedral(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
528{
529 return CalculateMaxDihedral(grid, static_cast<Volume*>(prism), aaPos);
530}
531
533template <class TAAPosVRT>
534number CalculateMaxDihedral(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
535{
536 return CalculateMaxDihedral(grid, static_cast<Volume*>(pyr), aaPos);
537}
538
540template <class TAAPosVRT>
541number CalculateMaxDihedral(Grid& grid, Volume* v, TAAPosVRT& aaPos)
542{
543 //PROFILE_FUNC();
544
552 {
553 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
555 }
556
557// Initialization
558 uint numElementEdges = v->num_edges();
559 vector3 vNorm1, vNorm2;
560 number maxDihedral = 0;
561 number tmpAngle;
562 Face* vNeighbourFacesToEdge[2];
563
564// Iterate over all element edges
565 for(uint eIter = 0; eIter < numElementEdges; ++eIter)
566 {
567 Edge* e = grid.get_edge(v, eIter);
568
569 // Get adjacent faces at the current edge and calculate the angle between their normals
570 // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
571 CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
572
573 Vertex* adjacentVrt1;
574 Vertex* adjacentVrt2;
575 vector3 vDir1;
576 vector3 vDir2;
577 vector3 vDir3;
578
579 for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
580 {
581 if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
582 adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
583 }
584
585 for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
586 {
587 if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
588 adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
589 }
590
591 VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
592 VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
593 VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
594
595 VecCross(vNorm1, vDir1, vDir2);
596 VecCross(vNorm2, vDir1, vDir3);
597
598 VecNormalize(vNorm1, vNorm1);
599 VecNormalize(vNorm2, vNorm2);
600
601 tmpAngle = acos(VecDot(vNorm1, vNorm2));
602 tmpAngle = PI - tmpAngle;
603
604 // Check for maximality
605 if(tmpAngle > maxDihedral)
606 {
607 maxDihedral = tmpAngle;
608 }
609 }
610
611// Transform maxDihedral from RAD to DEG
612 maxDihedral = 180/PI * maxDihedral;
613
614 return maxDihedral;
615}
616
617
619// CalculateAngles
621
623template <class TElem, class TAAPosVRT>
624number CalculateAngles(vector<number>& vAnglesOut, Grid& grid, TElem* elem, TAAPosVRT& aaPos);
625
627template <class TAAPosVRT>
628void CalculateAngles(vector<number>& vAnglesOut, Grid& grid, Face* f, TAAPosVRT& aaPos)
629{
630 //PROFILE_FUNC();
631
639 {
640 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
642 }
643
644// Get type of vertex attachment in aaPos and define it as ValueType
645 typedef typename TAAPosVRT::ValueType ValueType;
646
647// Initialization
648 uint numFaceVrts = f->num_vertices();
649 ValueType vNorm1, vNorm2;
650 ValueType vDir1, vDir2;
651 number tmpAngle;
652 Edge* vNeighbourEdgesToVertex[2];
653 Vertex* adjacentVrt1;
654 Vertex* adjacentVrt2;
655
656// Iterate over all face vertices
657 for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
658 {
659 Vertex* vrt = f->vertex(vrtIter);
660
661 // Get adjacent edges at the current vertex and calculate the angle between their normals
662 CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
663
664 // Calculate vDir vectors of the current two adjacent edges
665 // !!! Beware of the correct order of the vertices to get correct angle value !!!
666 if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
667 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
668 else
669 adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
670
671 if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
672 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
673 else
674 adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
675
676 VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
677 VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
678
679 // Normalize
680 VecNormalize(vDir1, vDir1);
681 VecNormalize(vDir2, vDir2);
682
683 // Calculate current angle
684 tmpAngle = acos(VecDot(vDir1, vDir2));
685
686 // Transform minAngle from RAD to DEG
687 tmpAngle = 180/PI * tmpAngle;
688
689 vAnglesOut.push_back(tmpAngle);
690 }
691}
692
694template <class TAAPosVRT>
695void CalculateAngles(vector<number>& vAnglesOut, Grid& grid, Volume* v, TAAPosVRT& aaPos)
696{
697 //PROFILE_FUNC();
698
706 {
707 LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
709 }
710
711// Initialization
712 uint numElementEdges = v->num_edges();
713 vector3 vNorm1, vNorm2;
714 number tmpAngle;
715 Face* vNeighbourFacesToEdge[2];
716
717// Iterate over all element edges
718 for(uint eIter = 0; eIter < numElementEdges; ++eIter)
719 {
720 Edge* e = grid.get_edge(v, eIter);
721
722 // Get adjacent faces at the current edge and calculate the angle between their normals
723 // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
724 CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
725
726 Vertex* adjacentVrt1;
727 Vertex* adjacentVrt2;
728 vector3 vDir1;
729 vector3 vDir2;
730 vector3 vDir3;
731
732 for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
733 {
734 if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
735 adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
736 }
737
738 for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
739 {
740 if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
741 adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
742 }
743
744 VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
745 VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
746 VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
747
748 VecCross(vNorm1, vDir1, vDir2);
749 VecCross(vNorm2, vDir1, vDir3);
750
751 VecNormalize(vNorm1, vNorm1);
752 VecNormalize(vNorm2, vNorm2);
753
754 tmpAngle = acos(VecDot(vNorm1, vNorm2));
755 tmpAngle = PI - tmpAngle;
756
757 // Transform maxDihedral from RAD to DEG
758 tmpAngle = 180.0/PI * tmpAngle;
759
760 vAnglesOut.push_back(tmpAngle);
761 }
762}
763
764
766// FindElementWithSmallestMinAngle
767template <class TIterator, class TAAPosVRT>
768typename TIterator::value_type
769FindElementWithSmallestMinAngle(Grid& grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT& aaPos)
770{
771 //PROFILE_FUNC();
772// if volumesBegin equals volumesBegin, then the list is empty and we can
773// immediately return NULL
774 if(elementsBegin == elementsEnd)
775 return NULL;
776
777// Initializations
778 typename TIterator::value_type elementWithSmallestMinAngle = *elementsBegin;
779 number smallestMinAngle = CalculateMinAngle(grid, elementWithSmallestMinAngle, aaPos);
780 ++elementsBegin;
781
782// compare all volumes and find that one with smallest minAngle
783 for(; elementsBegin != elementsEnd; ++elementsBegin)
784 {
785 typename TIterator::value_type curElement = *elementsBegin;
786 number curSmallestMinAngle = CalculateMinAngle(grid, curElement, aaPos);
787
788 if(curSmallestMinAngle < smallestMinAngle)
789 {
790 elementWithSmallestMinAngle = curElement;
791 smallestMinAngle = curSmallestMinAngle;
792 }
793 }
794
795 return elementWithSmallestMinAngle;
796}
797
798
800// FindElementWithLargestMaxAngle
801template <class TIterator, class TAAPosVRT>
802typename TIterator::value_type
803FindElementWithLargestMaxAngle(Grid& grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT& aaPos)
804{
805 //PROFILE_FUNC();
806// if volumesBegin equals volumesBegin, then the list is empty and we can
807// immediately return NULL
808 if(elementsBegin == elementsEnd)
809 return NULL;
810
811// Initializations
812 typename TIterator::value_type elementWithLargestMaxAngle = *elementsBegin;
813 number largestMaxAngle = CalculateMaxAngle(grid, elementWithLargestMaxAngle, aaPos);
814 ++elementsBegin;
815
816// compare all volumes and find that one with largest maxAngle
817 for(; elementsBegin != elementsEnd; ++elementsBegin)
818 {
819 typename TIterator::value_type curElement = *elementsBegin;
820 number curLargestMaxAngle = CalculateMaxAngle(grid, curElement, aaPos);
821
822 if(curLargestMaxAngle > largestMaxAngle)
823 {
824 elementWithLargestMaxAngle = curElement;
825 largestMaxAngle = curLargestMaxAngle;
826 }
827 }
828
829 return elementWithLargestMaxAngle;
830}
831
832
833}
834#endif
Base-class for edges.
Definition grid_base_objects.h:397
virtual Vertex * vertex(size_t index) const
Definition grid_base_objects.h:366
Faces are 2-dimensional objects.
Definition grid_base_objects.h:510
virtual size_t num_vertices() const
Definition grid_base_objects.h:488
virtual Vertex * vertex(size_t index) const
Definition grid_base_objects.h:486
Manages the elements of a grid and their interconnection.
Definition grid.h:132
EdgeContainer::iterator AssociatedEdgeIterator
used to iterate over associated edges of vertices, faces and volumes
Definition grid.h:249
void end_marking()
ends a marking sequence. Call this method when you're done with marking.
Definition grid.cpp:1285
AssociatedEdgeIterator associated_edges_begin(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition grid.cpp:882
bool option_is_enabled(uint option) const
see set_options for a description of valid parameters.
Definition grid.cpp:721
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition grid_impl.hpp:843
AssociatedEdgeIterator associated_edges_end(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition grid.cpp:892
Edge * get_edge(Vertex *v1, Vertex *v2)
returns the edge between v1 and v2, if it exists. Returns NULL if not.
Definition grid.cpp:1069
void mark(GridObject *obj)
marks the object. Calls are only valid between calls to Grid::begin_marking and Grid::end_marking.
Definition grid_impl.hpp:773
void begin_marking()
begin marking.
Definition grid.cpp:1262
FaceContainer::iterator AssociatedFaceIterator
used to iterate over associated faces of vertices, edges and volumes
Definition grid.h:251
void enable_options(uint options)
see set_options for a description of valid parameters.
Definition grid.cpp:711
A volume element with 6 quadrilateral sides.
Definition grid_objects_3d.h:227
A volume element with 2 triangle and 3 quadrilateral sides.
Definition grid_objects_3d.h:360
A volume element with 4 triangle and 1 quadrilateral sides.
Definition grid_objects_3d.h:493
the most simple volume-element.
Definition grid_objects_3d.h:91
Base-class for all vertex-types.
Definition grid_base_objects.h:231
Volumes are 3-dimensional objects.
Definition grid_base_objects.h:754
virtual uint num_edges() const
Definition grid_base_objects.h:782
virtual Vertex * vertex(size_t index) const
Definition grid_base_objects.h:727
virtual size_t num_vertices() const
Definition grid_base_objects.h:729
bool FaceContains(Face *f, EdgeVertices *ev)
returns true if the given face contains the two given vertices
Definition grid_util.cpp:561
UG_API void CollectAssociated(std::vector< Vertex * > &vVertexOut, Grid &grid, GridObject *obj, bool clearContainer=true)
Definition grid_util_impl.hpp:169
@ GRIDOPT_AUTOGENERATE_SIDES
sides are automatically created
Definition grid_constants.h:102
#define UG_ASSERT(expr, msg)
Definition assert.h:70
#define LOG(msg)
Definition common.h:60
#define UG_API
Definition ug_config.h:65
unsigned int uint
Definition types.h:114
double number
Definition types.h:124
void VecNormalize(vector_t &vOut, const vector_t &v)
scales a vector_t to unit length
Definition math_vector_functions_common_impl.hpp:501
void VecSubtract(vector_t &vOut, const vector_t &v1, const vector_t &v2)
subtracts v2 from v1 and stores the result in a vOut
Definition math_vector_functions_common_impl.hpp:226
void VecCross(vector_t &vOut, const vector_t &v1, const vector_t &v2)
calculates the cross product of two Vectors of dimension 3. It makes no sense to use VecCross for vec...
Definition math_vector_functions_common_impl.hpp:437
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
returns the dot-product of two vector_ts
Definition math_vector_functions_common_impl.hpp:385
Definition smart_pointer.h:814
the ug namespace
const number PI
Definition math_constants.h:45
number CalculateMaxDihedral(Grid &grid, TElem *elem, TAAPosVRT &aaPos)
An unimplemented version, so that a compile error occurs if no overload exists.
number CalculateMinDihedral(Grid &grid, TElem *elem, TAAPosVRT &aaPos)
An unimplemented version, so that a compile error occurs if no overload exists.
TIterator::value_type FindElementWithSmallestMinAngle(Grid &grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT &aaPos)
Definition element_angles.h:769
UG_API void CollectAssociatedSides(Edge *sidesOut[2], Grid &grid, Face *f, Vertex *vrt)
Collects all edges (= 2) which exist in the given face and which share the given vertex.
Definition element_angles.h:68
number CalculateMinAngle(Grid &grid, TElem *elem, TAAPosVRT &aaPos)
An unimplemented version, so that a compile error occurs if no overload exists.
number CalculateMaxAngle(Grid &grid, TElem *elem, TAAPosVRT &aaPos)
An unimplemented version, so that a compile error occurs if no overload exists.
number CalculateAngles(vector< number > &vAnglesOut, Grid &grid, TElem *elem, TAAPosVRT &aaPos)
An unimplemented version, so that a compile error occurs if no overload exists.
TIterator::value_type FindElementWithLargestMaxAngle(Grid &grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT &aaPos)
Definition element_angles.h:803