ug4
orientation_util_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017: 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__UG_orientation_util_impl
34 #define __H__UG_orientation_util_impl
35 
36 #include "common/math/ugmath.h"
39 
40 #include <stack>
41 #include <vector>
42 
43 
44 namespace ug{
45 
46 
48 // InvertOrientation
49 template <class iter_t>
50 void InvertOrientation(Grid& grid, iter_t elemsBegin,
51  iter_t elemsEnd)
52 {
53  for(iter_t iter = elemsBegin; iter != elemsEnd; ++iter)
54  grid.flip_orientation(*iter);
55 }
56 
57 
59 // FixFaceOrientation
60 template <class TFaceIterator>
61 void FixFaceOrientation(Grid& grid, TFaceIterator facesBegin,
62  TFaceIterator facesEnd)
63 {
64  using namespace std;
65 
66  {
67  // make sure that boundary faces are oriented outwards
69  for(TFaceIterator iter = facesBegin; iter != facesEnd; ++iter){
70  grid.associated_elements(vols, *iter);
71  if(vols.size() == 1 && !OrientationMatches(*iter, vols[0])){
72  grid.flip_orientation(*iter);
73  }
74  }
75  }
76 
77 // the rest only considers manifold faces
78 // we use marks to differentiate between processed and unprocessed faces
79  grid.begin_marking();
80 
81 // we have to mark all faces between facesBegin and facesEnd initially,
82 // to differentiate them from the other faces in the grid.
83  for(TFaceIterator iter = facesBegin; iter != facesEnd; ++iter){
84  if(NumAssociatedVolumes(grid, *iter) == 0)
85  grid.mark(*iter);
86  }
87 
88 // this edge descriptor will be used multiple times
89  EdgeDescriptor ed;
90 
91 // containers to store neighbour elements.
92  vector<Face*> vNeighbours;
93 
94 // stack that stores candidates
95  stack<Face*> stkFaces;
96 
97 // we'll iterate through all faces
98  while(facesBegin != facesEnd)
99  {
100  // candidates are empty at this point.
101  // if the face is unprocessed it is a new candidate
102  if(grid.is_marked(*facesBegin))
103  {
104  // mark it as candidate (by removing the mark)
105  grid.unmark(*facesBegin);
106  stkFaces.push(*facesBegin);
107 
108  // while the stack is not empty
109  while(!stkFaces.empty())
110  {
111  // get the candidate
112  Face* f = stkFaces.top();
113  stkFaces.pop();
114 
115  // get the neighbours for each side
116  for(size_t i = 0; i < f->num_edges(); ++i)
117  {
118  f->edge_desc(i, ed);
119  GetNeighbours(vNeighbours, grid, f, i);
120 
121  // fix orientation of unprocessed neighbours.
122  for(size_t j = 0; j < vNeighbours.size(); ++j)
123  {
124  Face* fn = vNeighbours[j];
125  if(grid.is_marked(fn))
126  {
127  // check whether the orientation of f and fn differs.
128  if(EdgeOrientationMatches(&ed, fn))
129  {
130  // the orientation of ed is the same as the orientation
131  // of an edge in fn.
132  // the faces thus have different orientation.
133  grid.flip_orientation(fn);
134  }
135 
136  // mark the face as processed and add it to the stack
137  grid.unmark(fn);
138  stkFaces.push(fn);
139  }
140  }
141  }
142  }
143  }
144 
145  // check the next face
146  ++facesBegin;
147  }
148 
149  grid.end_marking();
150 }
151 
152 
153 template<class TAAPosVRT>
154 bool
155 CheckOrientation(Volume* vol, TAAPosVRT& aaPosVRT)
156 {
157 // some typedefs
158  typedef typename TAAPosVRT::ValueType vector_t;
159 
160 // First calculate the center of the volume
161  vector_t volCenter = CalculateCenter(vol, aaPosVRT);
162 
163 // now check for each side whether it points away from the center.
164  size_t numFaces = vol->num_faces();
165  FaceDescriptor fd;
166  vector_t normal;
167  for(size_t i = 0; i < numFaces; ++i){
168  vol->face_desc(i, fd);
169  CalculateNormal(normal, &fd, aaPosVRT);
170 
171  // in order to best approximate quadrilateral faces, we'll calculate the
172  // center of the face and compare that to the volCenter.
173  vector_t faceCenter = CalculateCenter(&fd, aaPosVRT);
174 
175  // now compare normal and center
176  vector_t dir;
177  VecSubtract(dir, faceCenter, volCenter);
178  if(VecDot(dir, normal) < 0)
179  return false;
180  }
181 
182 // all center / normal checks succeeded. Orientation is fine.
183  return true;
184 }
185 
186 template<class TVolIterator, class TAAPosVRT>
187 int
188 FixOrientation(Grid& grid, TVolIterator volsBegin, TVolIterator volsEnd,
189  TAAPosVRT& aaPosVRT)
190 {
191  int numFlips = 0;
192 // iterate through all volumes
193  for(TVolIterator iter = volsBegin; iter != volsEnd; ++iter){
194  // check whether the orientation is fine
195  if(!CheckOrientation(*iter, aaPosVRT)){
196  grid.flip_orientation(*iter);
197  ++numFlips;
198  }
199  }
200 
201  return numFlips;
202 }
203 
204 
205 }// end of namespace
206 
207 #endif //__H__UG_orientation_util_impl
Can be used to store information about an edge and to construct an edge.
Definition: grid_base_objects.h:464
Can be queried for the edges and vertices of a face.
Definition: grid_base_objects.h:684
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
virtual EdgeDescriptor edge_desc(int index) const
returns the i-th edge of the face.
Definition: grid_base_objects.h:537
uint num_edges() const
Definition: grid_base_objects.h:545
Manages the elements of a grid and their interconnection.
Definition: grid.h:132
void end_marking()
ends a marking sequence. Call this method when you're done with marking.
Definition: grid.cpp:1285
void unmark(GridObject *obj)
unmarks the object. Calls are only valid between calls to Grid::begin_marking and Grid::end_marking.
Definition: grid_impl.hpp:808
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition: grid_impl.hpp:843
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 flip_orientation(Edge *e)
flips the orientation of an edge.
Definition: grid.cpp:535
void begin_marking()
begin marking.
Definition: grid.cpp:1262
void associated_elements(traits< Vertex >::secure_container &elemsOut, TElem *e)
Puts all elements of type TAss which are contained in 'e' or which contain 'e' into elemsOut.
Definition: grid_impl.hpp:466
Container which holds an array of pointers.
Definition: pointer_const_array.h:84
size_t size() const
returns the size of the associated array.
Definition: pointer_const_array_impl.hpp:106
Volumes are 3-dimensional objects.
Definition: grid_base_objects.h:754
virtual FaceDescriptor face_desc(int index) const
Definition: grid_base_objects.h:784
virtual uint num_faces() const
Definition: grid_base_objects.h:786
int CalculateNormal(vector3 &vNormOut, Grid &grid, Edge *e, Grid::AttachmentAccessor< Vertex, APosition > &aaPos, Grid::AttachmentAccessor< Face, ANormal > *paaNormFACE)
Calculates the normal of the given edge.
Definition: edge_util.cpp:314
int NumAssociatedVolumes(Grid &grid, Face *f)
returns the number of associated volumes of the specified face
Definition: face_util.cpp:147
void GetNeighbours(std::vector< Face * > &vFacesOut, Grid &grid, Face *f, int side, bool clearContainer)
collects neighbours of the given side of a face.
Definition: face_util.cpp:363
void CalculateCenter(vector_t &centerOut, const vector_t *pointSet, size_t numPoints)
calculates the center of a point-set
Definition: math_util_impl.hpp:98
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
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
bool CheckOrientation(Volume *vol, TAAPosVRT &aaPosVRT)
returns true if the volume is oriented so that all sides point to this outside.
Definition: orientation_util_impl.hpp:155
int FixOrientation(Grid &grid, TVolIterator volsBegin, TVolIterator volsEnd, TAAPosVRT &aaPosVRT)
Changes orientation of badly oriented volumes.
Definition: orientation_util_impl.hpp:188
bool OrientationMatches(const EdgeVertices &e1, const EdgeVertices &e2)
Definition: orientation.cpp:60
void InvertOrientation(Grid &grid, iter_t elemsBegin, iter_t elemsEnd)
inverts the orientation of all elements between elemsBegin and elemsEnd
Definition: orientation_util_impl.hpp:50
bool EdgeOrientationMatches(EdgeVertices *ev, Face *f)
checks if the edge-orientation of the edge and the face matches.
Definition: orientation_util.cpp:37
void FixFaceOrientation(Grid &grid, TFaceIterator facesBegin, TFaceIterator facesEnd)
creates uniform orientation of neighboured and boundary faces.
Definition: orientation_util_impl.hpp:61