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 : #include "vertex_util.h"
34 : #include "edge_util.h"
35 : #include "../trees/kd_tree_static.h"
36 : #include "misc_util.h"
37 :
38 : using namespace std;
39 :
40 : namespace ug
41 : {
42 :
43 : ////////////////////////////////////////////////////////////////////////
44 0 : int GetVertexIndex(EdgeVertices* e, Vertex* v)
45 : {
46 0 : if(e->vertex(0) == v)
47 : return 0;
48 0 : else if(e->vertex(1) == v)
49 0 : return 1;
50 : return -1;
51 : }
52 :
53 : ////////////////////////////////////////////////////////////////////////
54 0 : int GetVertexIndex(FaceVertices* f, Vertex* v)
55 : {
56 0 : uint numVrts = f->num_vertices();
57 0 : for(uint i = 0; i < numVrts; ++i)
58 : {
59 0 : if(f->vertex(i) == v)
60 0 : return i;
61 : }
62 : return -1;
63 : }
64 :
65 : ////////////////////////////////////////////////////////////////////////
66 0 : int GetVertexIndex(VolumeVertices* vol, Vertex* v)
67 : {
68 0 : uint numVrts = vol->num_vertices();
69 0 : for(uint i = 0; i < numVrts; ++i)
70 : {
71 0 : if(vol->vertex(i) == v)
72 0 : return i;
73 : }
74 : return -1;
75 : }
76 :
77 : ////////////////////////////////////////////////////////////////////////
78 0 : Vertex* GetConnectedVertex(Edge* e, Vertex* v)
79 : {
80 0 : if(e->vertex(0) == v)
81 0 : return e->vertex(1);
82 0 : else if(e->vertex(1) == v)
83 0 : return e->vertex(0);
84 : return NULL;
85 : }
86 :
87 : ////////////////////////////////////////////////////////////////////////
88 : // GetConnectedVertex
89 0 : Vertex* GetConnectedVertex(EdgeVertices* e, Face* f)
90 : {
91 0 : uint numVrts = f->num_vertices();
92 0 : for(uint i = 0; i < numVrts; ++i){
93 0 : if((f->vertex(i) != e->vertex(0)) &&
94 0 : (f->vertex(i) != e->vertex(1)))
95 0 : return f->vertex(i);
96 : }
97 : return NULL;
98 : }
99 :
100 : ////////////////////////////////////////////////////////////////////////
101 0 : int GetConnectedVertexIndex(Face* f, const EdgeDescriptor& ed)
102 : {
103 0 : return GetConnectedVertexIndex(f, &ed);
104 : }
105 :
106 0 : int GetConnectedVertexIndex(Face* f, const EdgeVertices* e)
107 : {
108 0 : uint numVrts = f->num_vertices();
109 0 : for(uint i = 0; i < numVrts; ++i)
110 : {
111 0 : if((f->vertex(i) != e->vertex(0)) &&
112 0 : (f->vertex(i) != e->vertex(1)))
113 : {
114 0 : return i;
115 : }
116 : }
117 : return -1;
118 : }
119 :
120 : ////////////////////////////////////////////////////////////////////////
121 0 : Edge* GetConnectedEdge(Grid& g, Vertex* vrt, Face* tri)
122 : {
123 : size_t numEdges = tri->num_edges();
124 0 : EdgeDescriptor ed;
125 0 : for(size_t i = 0; i < numEdges; ++i){
126 0 : tri->edge_desc(i, ed);
127 0 : if(!EdgeContains(&ed, vrt))
128 0 : return g.get_edge(ed);
129 : }
130 : return NULL;
131 : }
132 :
133 : ////////////////////////////////////////////////////////////////////////
134 0 : Vertex* GetSharedVertex(IVertexGroup* vrts0, IVertexGroup* vrts1)
135 : {
136 : const size_t num0 = vrts0->size();
137 : const size_t num1 = vrts1->size();
138 :
139 0 : IVertexGroup::ConstVertexArray v0 = vrts0->vertices();
140 0 : IVertexGroup::ConstVertexArray v1 = vrts1->vertices();
141 :
142 0 : for(size_t i0 = 0; i0 < num0; ++i0){
143 0 : Vertex* v = v0[i0];
144 0 : for(size_t i1 = 0; i1 < num1; ++i1){
145 0 : if(v == v1[i1])
146 0 : return v;
147 : }
148 : }
149 :
150 : return 0;
151 : }
152 :
153 : ////////////////////////////////////////////////////////////////////////
154 0 : size_t GetSharedVertices(
155 : std::vector<Vertex*>& vrtsOut,
156 : IVertexGroup* vrts0,
157 : IVertexGroup* vrts1)
158 : {
159 : vrtsOut.clear();
160 :
161 : const size_t num0 = vrts0->size();
162 : const size_t num1 = vrts1->size();
163 :
164 0 : IVertexGroup::ConstVertexArray v0 = vrts0->vertices();
165 0 : IVertexGroup::ConstVertexArray v1 = vrts1->vertices();
166 :
167 0 : for(size_t i0 = 0; i0 < num0; ++i0){
168 0 : Vertex* v = v0[i0];
169 0 : for(size_t i1 = 0; i1 < num1; ++i1){
170 0 : if(v == v1[i1])
171 0 : vrtsOut.push_back(v);
172 : }
173 : }
174 :
175 0 : return vrtsOut.size();
176 : }
177 :
178 : ////////////////////////////////////////////////////////////////////////
179 0 : size_t NumSharedVertices(IVertexGroup* vrts0, IVertexGroup* vrts1)
180 : {
181 : const size_t num0 = vrts0->size();
182 : const size_t num1 = vrts1->size();
183 :
184 0 : IVertexGroup::ConstVertexArray v0 = vrts0->vertices();
185 0 : IVertexGroup::ConstVertexArray v1 = vrts1->vertices();
186 :
187 : size_t numShared = 0;
188 0 : for(size_t i0 = 0; i0 < num0; ++i0){
189 0 : Vertex* v = v0[i0];
190 0 : for(size_t i1 = 0; i1 < num1; ++i1){
191 0 : if(v == v1[i1])
192 0 : ++numShared;
193 : }
194 : }
195 :
196 0 : return numShared;
197 : }
198 :
199 : ////////////////////////////////////////////////////////////////////////
200 0 : int NumAssociatedEdges(Grid& grid, Vertex* v)
201 : {
202 : Grid::edge_traits::secure_container edges;
203 : grid.associated_elements(edges, v);
204 0 : return (int)edges.size();
205 : }
206 :
207 : ////////////////////////////////////////////////////////////////////////
208 0 : int NumAssociatedFaces(Grid& grid, Vertex* v)
209 : {
210 : Grid::face_traits::secure_container faces;
211 : grid.associated_elements(faces, v);
212 0 : return (int)faces.size();
213 : }
214 :
215 : ////////////////////////////////////////////////////////////////////////
216 : // CollectSurfaceNeighborsSorted
217 0 : bool CollectSurfaceNeighborsSorted(std::vector<Vertex*>& vNeighborsOut,
218 : Grid& grid, Vertex* v)
219 : {
220 : vNeighborsOut.clear();
221 :
222 : // the algorithm won't work if volumes are connected
223 0 : if(grid.num_volumes() > 0){
224 0 : if(grid.associated_volumes_begin(v) != grid.associated_volumes_end(v))
225 : return false;
226 : }
227 :
228 : // the algorithm won't work if no faces are connected
229 0 : if(grid.associated_faces_begin(v) == grid.associated_faces_end(v))
230 : return false;
231 :
232 0 : grid.begin_marking();
233 :
234 0 : if(grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)
235 0 : && grid.option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES)){
236 : // collect edges in this vector
237 : vector<Edge*> edges;
238 : // start with an arbitrary edge
239 0 : Edge* curEdge = *grid.associated_edges_begin(v);
240 :
241 0 : while(curEdge){
242 0 : vNeighborsOut.push_back(GetConnectedVertex(curEdge, v));
243 : grid.mark(curEdge);
244 :
245 : // get associated faces
246 : Face* f[2];
247 0 : if(GetAssociatedFaces(f, grid, curEdge, 2) != 2)
248 0 : return false;
249 :
250 : curEdge = NULL;
251 0 : for(int i = 0; i < 2; ++i){
252 0 : if(!grid.is_marked(f[i])){
253 0 : CollectEdges(edges, grid, f[i]);
254 0 : for(size_t j = 0; j < edges.size(); ++j){
255 0 : if(!grid.is_marked(edges[j])){
256 0 : if(EdgeContains(edges[j], v)){
257 0 : curEdge = edges[j];
258 0 : break;
259 : }
260 : }
261 : }
262 : }
263 : }
264 : }
265 0 : }
266 : else{
267 : // we can't use GetAssociatedFaces here, since it uses Grid::mark itself if
268 : // EDGEOPT_STORE_ASSOCIATED_FACES is not enabled.
269 : // Start with an arbitrary face
270 0 : Face* f = *grid.associated_faces_begin(v);
271 : grid.mark(v);
272 :
273 0 : while(f){
274 : grid.mark(f);
275 :
276 : // mark one of the edges that is connected to v by marking
277 : // the edges endpoints. Make sure that it was not already marked.
278 0 : size_t numVrts = f->num_vertices();
279 0 : int vind = GetVertexIndex(f, v);
280 0 : Vertex* tvrt = f->vertex((vind + 1)%numVrts);
281 0 : if(grid.is_marked(tvrt))
282 0 : tvrt = f->vertex((vind + numVrts - 1)%numVrts);
283 0 : if(grid.is_marked(tvrt))
284 0 : throw(UGError("CollectSurfaceNeighborsSorted: unexpected exit."));
285 :
286 0 : vNeighborsOut.push_back(tvrt);
287 : grid.mark(tvrt);
288 :
289 : // iterate through the faces associated with v and find an unmarked one that
290 : // contains two marked vertices
291 : f = NULL;
292 0 : Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(v);
293 0 : for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v);
294 0 : iter != iterEnd; ++iter)
295 : {
296 0 : if(!grid.is_marked(*iter)){
297 : f = *iter;
298 : size_t numMarked = 0;
299 0 : for(size_t i = 0; i < f->num_vertices(); ++i){
300 0 : if(grid.is_marked(f->vertex(i)))
301 0 : ++numMarked;
302 : }
303 0 : if(numMarked == 2)
304 : break;
305 : else
306 : f = NULL;
307 : }
308 : }
309 : }
310 : }
311 :
312 0 : grid.end_marking();
313 0 : return true;
314 : }
315 :
316 : ////////////////////////////////////////////////////////////////////////
317 0 : Vertex* FindVertexByCoordiante(vector3& coord, VertexIterator iterBegin, VertexIterator iterEnd,
318 : Grid::VertexAttachmentAccessor<APosition>& aaPos)
319 : {
320 0 : if(iterBegin == iterEnd)
321 : return NULL;
322 :
323 : Vertex* bestVrt = *iterBegin;
324 0 : number bestDistSq = VecDistanceSq(coord, aaPos[bestVrt]);
325 :
326 : VertexIterator iter = iterBegin;
327 : iter++;
328 0 : while(iter != iterEnd)
329 : {
330 0 : number distSq = VecDistanceSq(coord, aaPos[*iter]);
331 0 : if(distSq < bestDistSq)
332 : {
333 : bestDistSq = distSq;
334 : bestVrt = *iter;
335 : }
336 :
337 : ++iter;
338 : }
339 :
340 : return bestVrt;
341 : }
342 :
343 : ////////////////////////////////////////////////////////////////////////
344 : // CalculateVertexNormals
345 0 : bool CalculateVertexNormals(Grid& grid,
346 : Grid::AttachmentAccessor<Vertex, APosition>& aaPos,
347 : Grid::AttachmentAccessor<Vertex, ANormal>& aaNorm)
348 : {
349 : // set all normals to zero
350 : {
351 : for(VertexIterator iter = grid.begin<Vertex>();
352 0 : iter != grid.end<Vertex>(); iter++)
353 : aaNorm[*iter] = vector3(0, 0, 0);
354 : }
355 : // loop through all the faces, calculate their normal and add them to their connected points
356 : {
357 0 : for(FaceIterator iter = grid.begin<Face>(); iter != grid.end<Face>(); iter++)
358 : {
359 : Face* f = *iter;
360 : vector3 vN;
361 :
362 0 : CalculateNormal(vN, f, aaPos);
363 :
364 0 : for(size_t i = 0; i < f->num_vertices(); ++i)
365 0 : VecAdd(aaNorm[f->vertex(i)], aaNorm[f->vertex(i)], vN);
366 : }
367 : }
368 : // loop through all the points and normalize their normals
369 : {
370 : for(VertexIterator iter = grid.begin<Vertex>();
371 0 : iter != grid.end<Vertex>(); iter++)
372 0 : VecNormalize(aaNorm[*iter], aaNorm[*iter]);
373 : }
374 : // done
375 0 : return true;
376 : }
377 :
378 0 : bool CalculateVertexNormals(Grid& grid, APosition& aPos, ANormal& aNorm)
379 : {
380 0 : if(!grid.has_attachment<Vertex>(aPos))
381 : return false;
382 0 : if(!grid.has_attachment<Vertex>(aNorm))
383 0 : grid.attach_to<Vertex>(aNorm);
384 :
385 : Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);
386 : Grid::VertexAttachmentAccessor<ANormal> aaNorm(grid, aNorm);
387 :
388 0 : return CalculateVertexNormals(grid, aaPos, aaNorm);
389 : }
390 :
391 :
392 : ////////////////////////////////////////////////////////////////////////
393 : // MergeVertices
394 : /// merges two vertices and restructures the adjacent elements.
395 0 : void MergeVertices(Grid& grid, Vertex* v1, Vertex* v2)
396 : {
397 : // make sure that GRIDOPT_VERTEXCENTRIC_INTERCONNECTION is enabled
398 0 : if(grid.num_edges() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))){
399 : LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_EDGES\n");
400 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_EDGES);
401 : }
402 0 : if(grid.num_faces() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))){
403 : LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_FACES\n");
404 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_FACES);
405 : }
406 0 : if(grid.num_volumes() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))){
407 : LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_VOLUMES\n");
408 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_VOLUMES);
409 : }
410 :
411 :
412 0 : Edge* conEdge = grid.get_edge(v1, v2);
413 0 : if(conEdge){
414 : // perform an edge-collapse on conEdge
415 0 : CollapseEdge(grid, conEdge, v1);
416 : }
417 : else{
418 : // notify the grid, that the two vertices will be merged
419 : grid.objects_will_be_merged(v1, v1, v2);
420 :
421 : // we have to check if there are elements that connect the vertices.
422 : // We have to delete those.
423 0 : EraseConnectingElements(grid, v1, v2);
424 :
425 : // create new edges for each edge that is connected with v2.
426 : // avoid double edges
427 0 : if(grid.num_edges() > 0)
428 : {
429 0 : EdgeDescriptor ed;
430 0 : Grid::AssociatedEdgeIterator iterEnd = grid.associated_edges_end(v2);
431 0 : for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v2); iter != iterEnd; ++iter)
432 : {
433 0 : Edge* e = *iter;
434 0 : if(e->vertex(0) == v2)
435 0 : ed.set_vertices(v1, e->vertex(1));
436 : else
437 0 : ed.set_vertices(e->vertex(0), v1);
438 :
439 0 : Edge* existingEdge = grid.get_edge(ed);
440 0 : if(!existingEdge)
441 0 : grid.create_by_cloning(e, ed, e);
442 : else
443 : grid.objects_will_be_merged(existingEdge, existingEdge, e);
444 : }
445 : }
446 :
447 : // create new faces for each face that is connected to v2
448 : // avoid double faces.
449 0 : if(grid.num_faces() > 0)
450 : {
451 0 : FaceDescriptor fd;
452 0 : Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(v2);
453 0 : for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v2); iter != iterEnd; ++iter)
454 : {
455 0 : Face* f = *iter;
456 0 : uint numVrts = f->num_vertices();
457 : fd.set_num_vertices(numVrts);
458 0 : for(uint i = 0; i < numVrts; ++i)
459 : {
460 0 : if(f->vertex(i) == v2)
461 : fd.set_vertex(i, v1);
462 : else
463 0 : fd.set_vertex(i, f->vertex(i));
464 : }
465 :
466 0 : Face* existingFace = grid.get_face(fd);
467 0 : if(!existingFace)
468 0 : grid.create_by_cloning(f, fd, f);
469 : else
470 : grid.objects_will_be_merged(existingFace, existingFace, f);
471 : }
472 : }
473 :
474 : // create new volumes for each volume that is connected to v2
475 0 : if(grid.num_volumes() > 0)
476 : {
477 0 : VolumeDescriptor vd;
478 0 : Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(v2);
479 0 : for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(v2); iter != iterEnd; ++iter)
480 : {
481 0 : Volume* v = *iter;
482 0 : uint numVrts = v->num_vertices();
483 : vd.set_num_vertices(numVrts);
484 0 : for(uint i = 0; i < numVrts; ++i)
485 : {
486 0 : if(v->vertex(i) == v2)
487 : vd.set_vertex(i, v1);
488 : else
489 0 : vd.set_vertex(i, v->vertex(i));
490 : }
491 :
492 : //assert(!"avoid double volumes! implement FindVolume and use it here.");
493 0 : grid.create_by_cloning(v, vd, v);
494 : }
495 : }
496 :
497 : // new elements have been created. remove the old ones.
498 : // it is sufficient to simply erase v2.
499 0 : grid.erase(v2);
500 : }
501 0 : }
502 :
503 : ////////////////////////////////////////////////////////////////////////
504 0 : bool IsBoundaryVertex1D(Grid& grid, Vertex* v,
505 : Grid::edge_traits::callback cbConsiderEdge)
506 : {
507 0 : if(!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
508 : {
509 : // we have to enable this option, since nothing works without it in reasonable time.
510 : LOG("WARNING in IsBoundaryVertex1D(...): auto-enabling VRTOPT_STORE_ASSOCIATED_EDGES.\n");
511 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_EDGES);
512 : }
513 :
514 : // iterate over associated edges and return true if only one of them
515 : // should be considered for the polygonal chain
516 : size_t counter = 0;
517 0 : for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v);
518 0 : iter != grid.associated_edges_end(v); ++iter)
519 : {
520 0 : if(cbConsiderEdge(*iter)){
521 0 : ++counter;
522 0 : if(counter > 1)
523 : return false;
524 : }
525 : }
526 :
527 : return true;
528 : }
529 :
530 : ////////////////////////////////////////////////////////////////////////
531 0 : bool IsBoundaryVertex2D(Grid& grid, Vertex* v)
532 : {
533 : // check whether one of the associated edges is a boundary edge.
534 : // if so return true.
535 0 : if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
536 : {
537 : // we have to enable this option, since we need edges in order to detect boundary vertices.
538 : LOG("WARNING in IsBoundaryVertex2D(...): auto-enabling FACEOPT_AUTOGENERATE_EDGES.\n");
539 0 : grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
540 : }
541 0 : if(!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))
542 : {
543 : // we have to enable this option, since nothing works without it in reasonable time.
544 : LOG("WARNING in IsBoundaryVertex2D(...): auto-enabling VRTOPT_STORE_ASSOCIATED_EDGES.\n");
545 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_EDGES);
546 : }
547 :
548 0 : for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v);
549 0 : iter != grid.associated_edges_end(v); ++iter)
550 : {
551 0 : if(IsBoundaryEdge2D(grid, *iter))
552 : return true;
553 : }
554 :
555 : return false;
556 : }
557 :
558 0 : bool IsBoundaryVertex3D(Grid& grid, Vertex* v)
559 : {
560 : // check whether one of the associated edges is a boundary edge.
561 : // if so return true.
562 0 : if(!grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES))
563 : {
564 : // we have to enable this option, since we need edges in order to detect boundary vertices.
565 : LOG(" WARNING in IsBoundaryVertex2D(...): auto-enabling VOLOPT_AUTOGENERATE_FACES.\n");
566 0 : grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
567 : }
568 0 : if(!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))
569 : {
570 : // we have to enable this option, since nothing works without it in reasonable time.
571 : LOG(" WARNING in IsBoundaryVertex2D(...): auto-enabling VRTOPT_STORE_ASSOCIATED_FACES.\n");
572 0 : grid.enable_options(VRTOPT_STORE_ASSOCIATED_FACES);
573 : }
574 :
575 0 : for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v);
576 0 : iter != grid.associated_faces_end(v); ++iter)
577 : {
578 0 : if(IsVolumeBoundaryFace(grid, *iter))
579 : return true;
580 : }
581 :
582 : return false;
583 : }
584 :
585 0 : bool LiesOnBoundary(Grid& grid, Vertex* v)
586 : {
587 0 : if(IsBoundaryVertex1D(grid, v))
588 : return true;
589 :
590 0 : if((grid.num<Face>() > 0) && IsBoundaryVertex2D(grid, v))
591 : return true;
592 :
593 0 : if((grid.num<Volume>() > 0) && IsBoundaryVertex3D(grid, v))
594 : return true;
595 :
596 : return false;
597 : }
598 :
599 :
600 : ////////////////////////////////////////////////////////////////////////
601 0 : bool IsRegularSurfaceVertex(Grid& grid, Vertex* v)
602 : {
603 : // check how many faces each associated edge has
604 0 : Grid::AssociatedEdgeIterator edgesEnd = grid.associated_edges_end(v);
605 0 : for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v);
606 0 : iter != edgesEnd; ++iter)
607 : {
608 0 : if(NumAssociatedFaces(grid, *iter) != 2)
609 : return false;
610 : }
611 : return true;
612 : }
613 :
614 : ////////////////////////////////////////////////////////////////////////
615 0 : void MarkFixedCreaseVertices(Grid& grid, SubsetHandler& sh,
616 : int creaseSI, int fixedSI)
617 : {
618 : // if there are no crease-edges then there is nothing to do.
619 0 : if((int)sh.num_subsets() <= creaseSI)
620 : return;
621 0 : if(sh.num<Edge>(creaseSI) == 0)
622 : return;
623 :
624 : // begin marking
625 0 : grid.begin_marking();
626 : // iterate over all crease-edges
627 : for(EdgeIterator iter = sh.begin<Edge>(creaseSI);
628 0 : iter != sh.end<Edge>(creaseSI); ++iter)
629 : {
630 : // check for both vertices whether they are fixed-vertices
631 0 : for(int i = 0; i < 2; ++i)
632 : {
633 0 : Vertex* v = (*iter)->vertex(i);
634 : // if the vertex is not marked (has not been checked yet)
635 0 : if(!grid.is_marked(v))
636 : {
637 : // mark it
638 : grid.mark(v);
639 : // count associated crease edges
640 : int counter = 0;
641 0 : Grid::AssociatedEdgeIterator aeIterEnd = grid.associated_edges_end(v);
642 0 : for(Grid::AssociatedEdgeIterator aeIter = grid.associated_edges_begin(v);
643 0 : aeIter != aeIterEnd; ++aeIter)
644 : {
645 0 : if(sh.get_subset_index(*aeIter) == creaseSI)
646 : {
647 : // the edge is a crease-edge. Increase the counter.
648 0 : ++counter;
649 : // if the counter is higher than 2, the vertex is a fixed vertex.
650 0 : if(counter > 2)
651 : {
652 0 : sh.assign_subset(v, fixedSI);
653 : break;
654 : }
655 : }
656 : }
657 : }
658 : }
659 : }
660 :
661 : // end marking
662 0 : grid.end_marking();
663 : }
664 :
665 : }// end of namespace
|