Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
vertex_util_impl.hpp
Go to the documentation of this file.
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__VERTEX_UTIL_IMPL__
34#define __H__LIB_GRID__VERTEX_UTIL_IMPL__
35
36#include "vertex_util.h"
37#include "edge_util.h"
38#include "face_util.h"
39#include "../trees/kd_tree_static.h"
40#include "misc_util.h"
41
42namespace ug
43{
44
46template <class TAAPos>
47number VertexDistanceSq(Vertex* v0, Vertex* v1, TAAPos& aaPos)
48{
49 return VecDistanceSq(aaPos[v0], aaPos[v1]);
50}
51
53template <class TAAPos>
54number VertexDistance(Vertex* v0, Vertex* v1, TAAPos& aaPos)
55{
56 return VecDistance(aaPos[v0], aaPos[v1]);
57}
58
60template <class TAAPosVRT>
61void CalculateVertexNormal(vector3& nOut, Grid& grid, Vertex* vrt, TAAPosVRT& aaPos)
62{
63// set all normal to zero
64 nOut = vector3(0, 0, 0);
65
66// loop through all associated faces, calculate their normal and add them to thee normal
69 iter != iterEnd; iter++)
70 {
71 vector3 vN;
72 CalculateNormal(vN, *iter, aaPos);
73 VecAdd(nOut, nOut, vN);
74 }
75
76 VecNormalize(nOut, nOut);
77}
78
80template <class TAAPosVRT>
81void CalculateBoundaryVertexNormal2D(typename TAAPosVRT::ValueType& nOut,
82 Grid& grid, Vertex* vrt,
83 TAAPosVRT& aaPos)
84{
85// The algorithm is a little cumbersome. However, through this setup, we
86// make sure that the orientation of the normal indeed points outwards,
87// based only on the topology.
88
89// set nOut to 0
90 VecSet(nOut, 0);
91
92// iterate over associated faces
93 std::vector<Face*> faces;
94 CollectAssociated(faces, grid, vrt);
95
97 for(size_t i_face = 0; i_face < faces.size(); ++i_face){
98 Face* f = faces[i_face];
99 // check for each side of f whether it is a boundary edge
100 for(size_t i_side = 0; i_side < f->num_sides(); ++i_side){
101 if(IsBoundaryEdge2D(grid, grid.get_edge(f, i_side))){
102 f->edge_desc(i_side, ed);
103 // make sure that e contains the specified vertex
104 if(!EdgeContains(&ed, vrt))
105 continue;
106
107 // the normal pointing outwards is clearly defined from the
108 // orientation of the edge descriptor
109 nOut.x() += aaPos[ed.vertex(1)].y() - aaPos[ed.vertex(0)].y();
110 nOut.y() += aaPos[ed.vertex(0)].x() - aaPos[ed.vertex(1)].x();
111 }
112 }
113 }
114
115 VecNormalize(nOut, nOut);
116}
117
119template <class TAAPosVRT>
121 TAAPosVRT& aaPos)
122{
123// The algorithm is a little cumbersome. However, through this setup, we
124// make sure that the orientation of the normal indeed points outwards,
125// based only on the topology.
126
127// set nOut to 0
128 VecSet(nOut, 0);
129
130// iterate over associated volumes
131 std::vector<Volume*> vols;
132 CollectAssociated(vols, grid, vrt);
133
135 for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){
136 Volume* v = vols[i_vol];
137 // check for each side of f whether it is a boundary edge
138 for(size_t i_side = 0; i_side < v->num_sides(); ++i_side){
139 if(IsBoundaryFace3D(grid, grid.get_face(v, i_side))){
140 v->face_desc(i_side, fd);
141
142 // make sure that fd contains the given vertex
143 if(!FaceContains(&fd, vrt))
144 continue;
145
146 // the normal pointing outwards is clearly defined from the
147 // orientation of the face descriptor
148 vector3 n;
149 CalculateNormal(n, &fd, aaPos);
150 VecAdd(nOut, nOut, n);
151 }
152 }
153 }
154
155 VecNormalize(nOut, nOut);
156}
157
159template <class TVrtIter, class TAPosition>
160void
161CalculateBoundingBox(typename TAPosition::ValueType& vMinOut,
162 typename TAPosition::ValueType& vMaxOut,
163 TVrtIter vrtsBegin, TVrtIter vrtsEnd,
165{
166 size_t dim = TAPosition::ValueType::Size;
167
168 if(vrtsBegin != vrtsEnd)
169 {
170 vMinOut = aaPos[*vrtsBegin];
171 vMaxOut = vMinOut;
172
173 for(TVrtIter iter = vrtsBegin; iter != vrtsEnd; ++iter)
174 {
175 for(size_t i = 0; i < dim; ++i){
176 vMinOut[i] = std::min(vMinOut[i], aaPos[*iter][i]);
177 vMaxOut[i] = std::max(vMaxOut[i], aaPos[*iter][i]);
178 }
179 }
180 }
181}
182
184template<class TVertexPositionAttachmentAccessor>
185inline
186typename TVertexPositionAttachmentAccessor::ValueType
187CalculateCenter(const Vertex* v, TVertexPositionAttachmentAccessor& aaPosVRT)
188{
189 return aaPosVRT[v];
190}
191
192template<class TAAPosVRT, class TAAWeightVRT>
193UG_API
194typename TAAPosVRT::ValueType
195CalculateCenter(const Vertex* v, TAAPosVRT& aaPosVRT, TAAWeightVRT&)
196{
197 return aaPosVRT[v];
198}
199
201template <class TVrtIter, class TAPosition>
202typename TAPosition::ValueType
203CalculateCenter(TVrtIter vrtsBegin, TVrtIter vrtsEnd,
205{
206 typename TAPosition::ValueType vMin, vMax;
207 CalculateBoundingBox(vMin, vMax, vrtsBegin, vrtsEnd, aaPos);
208 typename TAPosition::ValueType vRet;
209 VecScaleAdd(vRet, 0.5, vMin, 0.5, vMax);
210 return vRet;
211}
212
214template <class TVrtIter, class TAPosition>
215typename TAPosition::ValueType
216CalculateBarycenter(TVrtIter vrtsBegin, TVrtIter vrtsEnd,
218{
219 typename TAPosition::ValueType v;
220 VecSet(v, 0);
221 int counter = 0;
222 for(TVrtIter iter = vrtsBegin; iter != vrtsEnd; ++iter)
223 {
224 VecAdd(v,v,aaPos[*iter]);
225 counter++;
226 }
227
228 if(counter>0)
229 VecScale(v,v,1.f/counter);
230 return v;
231}
232
234template <class TVrtIterator>
235Vertex* MergeMultipleVertices(Grid& grid, TVrtIterator vrtsBegin,
236 TVrtIterator vrtsEnd)
237{
238 if(vrtsBegin == vrtsEnd)
239 return NULL;
240
241 Vertex* v = *vrtsBegin;
242 ++vrtsBegin;
243 while(vrtsBegin != vrtsEnd){
244 Vertex* v2 = *vrtsBegin;
245 ++vrtsBegin;
246 MergeVertices(grid, v, v2);
247 }
248 return v;
249}
250
252//TODO: replace KDTreeStatic by a dynamic kd-tree.
253//TODO: Better support for various iterators.
254template <int dim, class TVrtIterator>
255void RemoveDoubles(Grid& grid, const TVrtIterator& iterBegin,
256 const TVrtIterator& iterEnd, Attachment<MathVector<dim> >& aPos,
257 number threshold)
258{
259 if(!grid.has_vertex_attachment(aPos))
260 return;
261
262 typedef Attachment<MathVector<dim> > attachment_type;
264
265 RemoveDoubles<dim>(grid, iterBegin, iterEnd, aaPos, threshold);
266}
267
268template <int dim, class TVrtIterator, class TAAPos>
269void RemoveDoubles(Grid& grid, const TVrtIterator& iterBegin,
270 const TVrtIterator& iterEnd,
271 TAAPos aaPos,
272 number threshold)
273{
274 typedef Attachment<MathVector<dim> > attachment_type;
276 kdTree.create_from_grid(grid, iterBegin, iterEnd, aaPos, 20, 10, KDSD_LARGEST);
277
278// we need temporary attachments:
279// a vector<Vertex*> attachment, that stores for each vertex all other vertices
280// closer than threshold, which have higher attachment data index.
281 typedef Attachment<std::list<Vertex*> > AVertexList;
282 AVertexList aVertexList;
283 grid.attach_to_vertices(aVertexList);
284 Grid::VertexAttachmentAccessor<AVertexList> aaVL(grid, aVertexList);
285
286// we'll store in this attachment whether a vertex will be merged or not.
287 AInt aInt;
288 grid.attach_to_vertices(aInt);
289 Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt);
290 {
291 for(TVrtIterator iter = iterBegin; iter != iterEnd; ++iter)
292 aaInt[*iter] = 0;
293 }
294
295// compare squares.
296 threshold *= threshold;
297 std::vector<Vertex*> neighbours;
298// iterate over all vertices and collect all that have aInt == 0 and are within range.
299 for(TVrtIterator iter = iterBegin; iter != iterEnd; ++iter)
300 {
301 Vertex* v = *iter;
302 if(aaInt[v] == 0)
303 {// the vertex will not be removed during merge
304 // find all vertices closer than threshold
305 uint numClosest = 3;
306 while(numClosest < grid.num_vertices())
307 {
308 neighbours.clear();
309 kdTree.get_neighbourhood(neighbours, aaPos[v], numClosest);
310
311 if(VecDistanceSq(aaPos[neighbours.back()], aaPos[v]) < threshold)
312 numClosest *= 2;
313 else
314 break;
315 }
316
317 // store them in the vertexVec attachment
318 if(!neighbours.empty())
319 {
320 for(std::vector<Vertex*>::iterator nIter = neighbours.begin();
321 nIter != neighbours.end(); ++nIter)
322 {
323 Vertex* nv = *nIter;
324 if(aaInt[nv] == 0)
325 {
326 if(nv != v)
327 {
328 if(VecDistanceSq(aaPos[v], aaPos[nv]) < threshold)
329 {
330 aaVL[v].push_back(nv);
331 aaInt[nv] = 1;
332 }
333 else
334 break;
335 }
336 }
337 }
338 }
339 }
340 }
341
342// iterate over all vertices again and merge collected ones
343// This iteration only works, if the iterators stem from a class
344// like Selector or SubsetHandler or Grid etc, which automatically
345// handle removed elements.
346//TODO: This should be improved somehow!
347 {
348 TVrtIterator iter = iterBegin;
349 while(iter != iterEnd)
350 {
351 Vertex* v = *iter;
352 if(!aaVL[v].empty())
353 {
354 std::list<Vertex*>::iterator nIter = aaVL[v].begin();
355 while(nIter != aaVL[v].end())
356 {
357 Vertex* delVrt = *nIter;
358 nIter++;
359 MergeVertices(grid, v, delVrt);
360 }
361 }
362
363 ++iter;
364 }
365 }
366
367 grid.detach_from_vertices(aVertexList);
368 grid.detach_from_vertices(aInt);
369}
370
371
373template<class TAAPos> inline
374void TransformVertex(Vertex* vrt, matrix33& m, TAAPos& aaPos)
375{
376// todo: avoid unnecessary copy
377 vector3 oldPos = aaPos[vrt];
378 MatVecMult(aaPos[vrt], m, oldPos);
379}
380
382template<class TIterator, class TAAPos>
383void TransformVertices(TIterator vrtsBegin, TIterator vrtsEnd,
384 matrix33& m, TAAPos& aaPos)
385{
386 for(TIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
387 TransformVertex(*iter, m, aaPos);
388}
389
391template<class TIterator, class TAAPos> inline
392void MoveVertices(TIterator vrtsBegin, TIterator vrtsEnd, TAAPos aaPos,
393 const typename TAAPos::ValueType& offset)
394{
395 for(TIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
396 aaPos[*iter] += offset;
397}
398
400template <class vector_t, class TAAPos>
401UG_API bool
402ContainsPoint(const Vertex* v, const vector_t& p, TAAPos aaPos)
403{
404 const vector_t& pv = aaPos[v];
405 for(size_t i = 0; i < vector_t::Size; ++i){
406 if(pv[i] != p[i])
407 return false;
408 }
409 return true;
410}
411
412template <size_t dim>
413int FindVertexByCoordinate(const MathVector<dim>& coord, size_t ncoords, const MathVector<dim> vCoords[])
414{
415
416 if (ncoords <= 0) return -1;
417
418 size_t bestVrt = 0;
419 number bestDistSq = VecDistanceSq(coord, vCoords[0]);
420
421 for (size_t i=1; i<ncoords; ++i)
422 {
423 number distSq = VecDistance(coord, vCoords[i]);
424 if(distSq < bestDistSq)
425 {
426 bestDistSq = distSq;
427 bestVrt = i;
428 }
429 }
430 return bestVrt;
431}
432
433}// end of namespace
434
435#endif
parameterString p
A generic specialization of IAttachment.
Definition attachment_pipe.h:263
Can be used to store information about an edge and to construct an edge.
Definition grid_base_objects.h:464
virtual Vertex * vertex(size_t index) const
Definition grid_base_objects.h:366
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_sides() const
Definition grid_base_objects.h:546
the generic attachment-accessor for access to grids attachment pipes.
Definition grid.h:182
Manages the elements of a grid and their interconnection.
Definition grid.h:132
AssociatedFaceIterator associated_faces_begin(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition grid.cpp:944
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
Face * get_face(const FaceVertices &fv)
returns the face that is described by fv.
Definition grid.cpp:1135
size_t num_vertices() const
Definition grid.h:551
void detach_from_vertices(IAttachment &attachment)
Definition grid.h:787
AssociatedFaceIterator associated_faces_end(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition grid.cpp:954
bool has_vertex_attachment(IAttachment &attachment)
Definition grid.h:798
void attach_to_vertices(IAttachment &attachment, bool passOnValues)
Definition grid.h:728
FaceContainer::iterator AssociatedFaceIterator
used to iterate over associated faces of vertices, edges and volumes
Definition grid.h:251
organizes vertices in a binary-tree structure. Only for static use!
Definition kd_tree_static.h:85
bool get_neighbourhood(std::vector< Vertex * > &vrtsOut, typename TPositionAttachment::ValueType &pos, int numClosest)
Definition kd_tree_static_impl.hpp:104
bool create_from_grid(Grid &grid, TVrtIterator vrtsBegin, TVrtIterator vrtsEnd, TPositionAttachment &aPos, int maxTreeDepth, int splitThreshold, KDSplitDimension splitDimension=KDSD_LARGEST)
Definition kd_tree_static_impl.hpp:75
A class for fixed size, dense matrices.
Definition math_matrix.h:63
Base-class for all vertex-types.
Definition grid_base_objects.h:231
Volumes are 3-dimensional objects.
Definition grid_base_objects.h:754
virtual FaceDescriptor face_desc(int index) const
Definition grid_base_objects.h:784
uint num_sides() const
Definition grid_base_objects.h:787
bool EdgeContains(EdgeVertices *e, Vertex *vrt)
Definition grid_util_impl.hpp:45
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
bool IsBoundaryEdge2D(Grid &grid, Edge *e)
returns whether an edge lies on the boundary of a 2D grid.
Definition edge_util.cpp:112
UG_API bool ContainsPoint(const EdgeVertices *e, const vector_t &p, TAAPos aaPos)
Returns true if the given point lies on the given edge.
Definition edge_util_impl.hpp:513
UG_API bool IsBoundaryFace3D(Grid &grid, TFace *f)
A wrapper for IsVolumeBoundaryFace.
Definition face_util.h:151
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
@ KDSD_LARGEST
Definition kd_tree_static.h:64
UG_API void TransformVertices(TIterator vrtsBegin, TIterator vrtsEnd, matrix33 &m, TAAPos &aaPos)
transforms all given vertices by a given matrix
Definition vertex_util_impl.hpp:383
UG_API void RemoveDoubles(Grid &grid, const TVrtIterator &iterBegin, const TVrtIterator &iterEnd, Attachment< MathVector< dim > > &aPos, number threshold)
merges all vertices that are closer to each other than the specified threshold.
Definition vertex_util_impl.hpp:255
UG_API number VertexDistance(Vertex *v0, Vertex *v1, TAAPos &aaPos)
Returns the distance between two vertices.
Definition vertex_util_impl.hpp:54
UG_API void CalculateBoundaryVertexNormal3D(vector3 &nOut, Grid &grid, Vertex *vrt, TAAPosVRT &aaPos)
calculates the normal of a boundary vertex using associated volumes
Definition vertex_util_impl.hpp:120
void MoveVertices(TIterator vrtsBegin, TIterator vrtsEnd, TAAPos aaPos, const typename TAAPos::ValueType &offset)
moves vertices by the specified offset
Definition vertex_util_impl.hpp:392
void MergeVertices(Grid &grid, Vertex *v1, Vertex *v2)
merges two vertices and restructures the adjacent elements.
Definition vertex_util.cpp:395
UG_API Vertex * MergeMultipleVertices(Grid &grid, TVrtIterator vrtsBegin, TVrtIterator vrtsEnd)
Merges all vertices between the given iterators into a single vertex.
Definition vertex_util_impl.hpp:235
UG_API void CalculateVertexNormal(vector3 &nOut, Grid &grid, Vertex *vrt, TAAPosVRT &aaPos)
calculates the normal of a vertex using associated faces
Definition vertex_util_impl.hpp:61
UG_API void TransformVertex(Vertex *vrt, matrix33 &m, TAAPos &aaPos)
transforms a vertex by a given matrix
Definition vertex_util_impl.hpp:374
UG_API TAPosition::ValueType CalculateBarycenter(TVrtIter vrtsBegin, TVrtIter vrtsEnd, Grid::VertexAttachmentAccessor< TAPosition > &aaPos)
calculates the barycenter of a set of vertices
Definition vertex_util_impl.hpp:216
UG_API number VertexDistanceSq(Vertex *v0, Vertex *v1, TAAPos &aaPos)
Returns the squared distance between two vertices.
Definition vertex_util_impl.hpp:47
int FindVertexByCoordinate(const MathVector< dim > &coord, size_t ncoords, const MathVector< dim > vCoords[])
returns (non-unique?) index of closest vertex
Definition vertex_util_impl.hpp:413
UG_API void CalculateBoundaryVertexNormal2D(typename TAAPosVRT::ValueType &nOut, Grid &grid, Vertex *vrt, TAAPosVRT &aaPos)
calculates the normal of a boundary vertex using associated faces
Definition vertex_util_impl.hpp:81
#define UG_API
Definition ug_config.h:65
unsigned int uint
Definition types.h:114
double number
Definition types.h:124
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
Matrix - Vector Multiplication.
Definition math_matrix_vector_functions_common_impl.hpp:49
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 VecSet(vector_t &vInOut, typename vector_t::value_type s)
Set each vector component to scalar (componentwise)
Definition math_vector_functions_common_impl.hpp:539
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition math_vector_functions_common_impl.hpp:265
void VecNormalize(vector_t &vOut, const vector_t &v)
scales a vector_t to unit length
Definition math_vector_functions_common_impl.hpp:501
vector_t::value_type VecDistanceSq(const vector_t &v1, const vector_t &v2)
returns the squared distance of two vector_ts.
Definition math_vector_functions_common_impl.hpp:351
MathVector< 3, number > vector3
a 3d vector
Definition ugmath_types.h:72
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
returns the distance of two vector_ts.
Definition math_vector_functions_common_impl.hpp:375
void VecAdd(vector_t &vOut, const vector_t &v1, const vector_t &v2)
adds two MathVector<N>s and stores the result in a third one
Definition math_vector_functions_common_impl.hpp:185
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
scales a MathVector<N>
Definition math_vector_functions_common_impl.hpp:252
the ug namespace
AABox< typename TAAPos::ValueType > CalculateBoundingBox(Vertex *e, TAAPos aaPos)
calculates the smallest axis aligned box that contains the given vertex
Definition bounding_box_util.h:43