ug4
resolve_intersections_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-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__UG__resolve_intersections_impl__
34 #define __H__UG__resolve_intersections_impl__
35 
36 #include <map>
37 #include <limits>
38 #include "resolve_intersections.h"
47 
48 namespace ug{
49 
50 namespace grid_intersection_impl {
51 // static int fileCounter = 1;
52 // string filenamePrefix = "/home/sreiter/Desktop/failed_sweeplines/failed_sweepline_";
53 // stringstream ss2d, ss3d;
54 // ss2d << filenamePrefix << "2d_" << fileCounter << ".lgb";
55 // ss3d << filenamePrefix << "3d_" << fileCounter << ".lgb";
56 // ++fileCounter;
57 // UG_LOG("TriangleFill_SweepLine failed!\n");
58 // SaveGridToFile(tgrid, ss3d.str().c_str(), aPos);
59 // // perform transformation to 2d and save that too.
60 // std::vector<vector3> vrts;
61 // for(VertexIterator iter = tgrid.vertices_begin();
62 // iter != tgrid.vertices_end(); ++iter)
63 // {
64 // vrts.push_back(taaPos[*iter]);
65 // }
66 // std::vector<vector2> vrts2d(vrts.size());
67 // TransformPointSetTo2D(&vrts2d.front(), &vrts.front(),
68 // vrts.size());
69 
70 // size_t counter = 0;
71 // for(VertexIterator iter = tgrid.vertices_begin();
72 // iter != tgrid.vertices_end(); ++iter, ++counter)
73 // {
74 // taaPos[*iter] = vector3(vrts2d[counter].x(), vrts2d[counter].y(), 0);
75 // }
76 
77 // SaveGridToFile(tgrid, ss2d.str().c_str(), aPos);
78 
79  template <class TAPos>
80  void DebugSave(Grid& grid, const char* filePrefix, TAPos aPos)
81  {
82  #ifdef UG_INTERSECTION_DEBUG_PATH
83  static int fileCounter = 0;
84  ++fileCounter;
85  std::string pathName = UG_INTERSECTION_DEBUG_PATH;
86  std::string filename =
87  mkstr(pathName << "/" << filePrefix
88  << "-" << fileCounter << ".ugx");
89  UG_LOG("Saving intersection debug geometry to " << filename << std::endl);
90  SaveGridToFile(grid, filename.c_str(), aPos);
91  #endif
92  }
93 
94  template <class TAPos>
95  void DebugSave2d(Grid& grid, const char* filePrefix, TAPos aPos)
96  {
97  #ifdef UG_INTERSECTION_DEBUG_PATH
98  static int fileCounter = 0;
99  ++fileCounter;
100  std::string pathName = UG_INTERSECTION_DEBUG_PATH;
101  std::string filename =
102  mkstr(pathName << "/" << filePrefix
103  << "-" << fileCounter << ".ugx");
104  UG_LOG("Saving 2d intersection debug geometry to " << filename << std::endl);
105 
106  Grid::VertexAttachmentAccessor<TAPos> aaPos(grid, aPos);
107  std::vector<vector3> vrts;
108  for(VertexIterator iter = grid.vertices_begin();
109  iter != grid.vertices_end(); ++iter)
110  {
111  vrts.push_back(aaPos[*iter]);
112  }
113  std::vector<vector2> vrts2d(vrts.size());
114  TransformPointSetTo2D(&vrts2d.front(), &vrts.front(),
115  vrts.size());
116 
117  size_t counter = 0;
118  for(VertexIterator iter = grid.vertices_begin();
119  iter != grid.vertices_end(); ++iter, ++counter)
120  {
121  aaPos[*iter] = vector3(vrts2d[counter].x(), vrts2d[counter].y(), 0);
122  }
123 
124  SaveGridToFile(grid, filename.c_str(), aPos);
125 
126  for(VertexIterator iter = grid.vertices_begin();
127  iter != grid.vertices_end(); ++iter, ++counter)
128  {
129  aaPos[*iter] = vrts[counter];
130  }
131 
132  #endif
133  }
134 }
135 
136 template <class TAAPosVRT>
138  Edge* e, TAAPosVRT& aaPos,
139  number snapThreshold)
140 {
141  typedef typename TAAPosVRT::ValueType vector_t;
142 
143  number snapThresholdSq = snapThreshold * snapThreshold;
144 
145 // make sure that the vertex is not an endpoint of e
146  if(EdgeContains(e, v))
147  return NULL;
148 
149 // we have to make sure that v and e are not connected by a face.
150 // This could lead to infinite recursion
151 /*
152  vector<Face*> faces;
153  CollectFaces(faces, grid, e);
154  for(size_t i = 0; i < faces.size(); ++i){
155  if(FaceContains(faces[i], v))
156  return NULL;
157  }
158 */
159 // project the vertex to the line defined by the edge
160  vector_t p;
161  number t = DropAPerpendicular(p, aaPos[v], aaPos[e->vertex(0)],
162  aaPos[e->vertex(1)]);
163 
164  if((t >= 0) && (t <= 1.)){
165  if(VecDistanceSq(p, aaPos[v]) < snapThresholdSq){
166  // to make sure that no double edges may occur, we'll use MergeVertices
167  RegularVertex* nVrt = SplitEdge<RegularVertex>(grid, grid, e);
168  aaPos[v] = p;
169  MergeVertices(grid, v, nVrt);
170  return v;
171 /*
172  // insert the vertex into the edge
173  CreateEdgeSplitGeometry(grid, grid, e, v);
174  grid.erase(e);
175  return v;
176 */
177  }
178  }
179  return NULL;
180 }
181 
187  template <class TAAPosVRT>
189  Face* f, TAAPosVRT& aaPos,
190  number snapThreshold,
191  std::vector<Face*>* pNewFacesOut)
192 {
193  using namespace std;
194  typedef typename TAAPosVRT::ValueType vector_t;
195 
196  if(pNewFacesOut)
197  pNewFacesOut->clear();
198 
199  number snapThresholdSq = snapThreshold * snapThreshold;
200 
201 // make sure that the vertex is not a corner of f
202  if(FaceContains(f, v))
203  return false;
204 
205 // calculate the normal
206  vector_t n;
207  CalculateNormal(n, f, aaPos);
208 
209 // project the vertex to the plane defined by the face
210  vector_t p;
211  ProjectPointToPlane(p, aaPos[v], aaPos[f->vertex(0)], n);
212 
213 // check whether the distance is fine
214  if(VecDistanceSq(p, aaPos[v]) < snapThresholdSq){
215  // now we have to check whether the projection lies in the face
216  vector_t pi;
217  bool refined = false;
218  if(f->num_vertices() == 3){
219  if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
220  aaPos[f->vertex(2)], p, n))
221  {
222  refined = true;
223  }
224  }
225  else if(f->num_vertices() == 4){
226  if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
227  aaPos[f->vertex(2)], p, n))
228  {
229  refined = true;
230  }
231  else if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(2)],
232  aaPos[f->vertex(3)], p, n))
233  {
234  refined = true;
235  }
236  }
237 
238  if(!refined)
239  return false;
240 
241  // check whether the projection is too close to one of the corners.
242  // if this is the case, we'll set the position to that corner, so that
243  // a call to remove-doubles will resolve the intersection
244  for(size_t i = 0; i < f->num_vertices(); ++i){
245  if(VecDistanceSq(p, aaPos[f->vertex(i)]) < snapThresholdSq){
246  // aaPos[v] = aaPos[f->vertex(i)];
247  return false;
248  }
249  }
250 
251  // adjust position
252  //aaPos[v] = p;
253 
254  // check whether the vertex is close to one of the edges of the face.
255  // if so, we'll only split the edge locally...
256  // this leads to T-junctions, which may be resolved later on
257  // through a call to ProjectVerticesToCloseEdges
258  EdgeDescriptor ed;
259  for(size_t i = 0; i < f->num_edges(); ++i){
260  f->edge_desc(i, ed);
261  vector_t pl;
262  ProjectPointToLine(pl, p, aaPos[ed.vertex(0)], aaPos[ed.vertex(1)]);
263  if(VecDistanceSq(pl, p) < snapThresholdSq){
264  // we have to locally split the edge
265  Vertex* newEdgeVrts[4] = {NULL, NULL, NULL, NULL};
266  newEdgeVrts[i] = v;
267  Vertex* newFaceVrt = NULL;
268  vector<Face*> newFaces;
269  if(f->refine(newFaces, &newFaceVrt, newEdgeVrts, NULL)){
270  if(newFaceVrt)
271  grid.register_element(newFaceVrt);
272  // split the edge to make sure that properties are passed on to children
273  Edge* e = grid.get_edge(f, i);
274  if(e){
275  EdgeDescriptor ne1(ed.vertex(0), v);
276  EdgeDescriptor ne2(v, ed.vertex(1));
277  if(!grid.get_element(ne1))
278  grid.create<RegularEdge>(ne1, e);
279  if(!grid.get_element(ne2))
280  grid.create<RegularEdge>(ne2, e);
281  }
282  // insert the newly created faces into the grid
283  for(size_t j = 0; j < newFaces.size(); ++j){
284  if(!grid.get_face(*newFaces[j])){
285  grid.register_element(newFaces[j], f);
286  if(pNewFacesOut)
287  pNewFacesOut->push_back(newFaces[j]);
288  }
289  else
290  delete newFaces[j];
291  }
292  // if f is the only connected face, we have to erase e
293  if(e && NumAssociatedFaces(grid, e) == 1){
294  grid.erase(f);
295  grid.erase(e);
296  }
297  else
298  grid.erase(f);
299  return true;
300  }
301  else
302  return false;
303 
304  }
305  }
306 
307  // if we reach this point we have to actually split the face.
308  // we do this by creating a new triangle connecting 'v' with each edge of f
309  FaceDescriptor fd(3);
310  for(size_t i = 0; i < f->num_edges(); ++i){
311  f->edge_desc(i, ed);
312  fd.set_vertex(0, ed.vertex(0));
313  fd.set_vertex(1, ed.vertex(1));
314  fd.set_vertex(2, v);
315  if(!grid.get_element(fd)){
316  Face* nf = *grid.create<Triangle>(TriangleDescriptor(fd.vertex(0),
317  fd.vertex(1), fd.vertex(2)),
318  f);
319  if(pNewFacesOut)
320  pNewFacesOut->push_back(nf);
321  }
322  }
323  grid.erase(f);
324  return true;
325  }
326 
327  return false;
328 }
329 // template <class TAAPosVRT>
330 // bool ResolveVertexFaceIntersection(Grid& grid, Vertex* v,
331 // Face* f, TAAPosVRT& aaPos,
332 // number snapThreshold,
333 // std::vector<Face*>* pNewFacesOut)
334 // {
335 // using namespace std;
336 // typedef typename TAAPosVRT::ValueType vector_t;
337 
338 // if(pNewFacesOut)
339 // pNewFacesOut->clear();
340 
341 // number snapThresholdSq = snapThreshold * snapThreshold;
342 
343 // // make sure that the vertex is not a corner of f
344 // if(FaceContains(f, v))
345 // return false;
346 
347 // // calculate the normal
348 // vector_t n;
349 // CalculateNormal(n, f, aaPos);
350 
351 // // project the vertex to the plane defined by the face
352 // vector_t p;
353 // ProjectPointToPlane(p, aaPos[v], aaPos[f->vertex(0)], n);
354 
355 // // check whether the distance is fine
356 // if(VecDistanceSq(p, aaPos[v]) < snapThresholdSq){
357 // bool refined = false;
358 // vector<Face*> newFaces;
359 // Vertex* newFaceVrt = NULL;
360 // // Vertex* nVrt = NULL;
361 // vector_t pi;
362 // // now we have to check whether the projection lies in the face
363 // if(f->num_vertices() == 3){
364 // if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
365 // aaPos[f->vertex(2)], p, n))
366 // {
367 // Vertex* newEdgeVrts[3] = {NULL, NULL, NULL};
368 // refined = f->refine(newFaces, &newFaceVrt, newEdgeVrts, v);
369 // }
370 // }
371 // else if(f->num_vertices() == 4){
372 // bool success = false;
373 // if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
374 // aaPos[f->vertex(2)], p, n))
375 // {
376 // success = true;
377 // }
378 // else if(RayTriangleIntersection(pi, aaPos[f->vertex(0)], aaPos[f->vertex(2)],
379 // aaPos[f->vertex(3)], p, n))
380 // {
381 // success = true;
382 // }
383 
384 // if(success){
385 // Vertex* newEdgeVrts[4] = {NULL, NULL, NULL, NULL};
386 // refined = f->refine(newFaces, &newFaceVrt, newEdgeVrts, v);
387 // }
388 // }
389 
390 // if(refined){
391 // // adjust position
392 // aaPos[v] = pi;
393 // // register the new faces and erase the old one
394 // for(size_t i = 0; i < newFaces.size(); ++i){
395 // if(!grid.get_face(*newFaces[i])){
396 // grid.register_element(newFaces[i], f);
397 // if(pNewFacesOut)
398 // pNewFacesOut->push_back(newFaces[i]);
399 // }
400 // else
401 // delete newFaces[i];
402 // }
403 // grid.erase(f);
404 // return true;
405 // }
406 // }
407 
408 // return false;
409 // }
410 
416 template <class TAAPosVRT>
418  TAAPosVRT& aaPos, number snapThreshold)
419 {
420  typedef typename TAAPosVRT::ValueType vector_t;
421 
422 // check whether one edge contains a vertex of another edge
423  if(EdgeContains(e1, e2->vertex(0)) || EdgeContains(e1, e2->vertex(1)))
424  return NULL;
425 
426  number snapThresholdSq = snapThreshold * snapThreshold;
427 
428  number t1, t2;
429  if(LineLineProjection(t1, t2, aaPos[e1->vertex(0)], aaPos[e1->vertex(1)],
430  aaPos[e2->vertex(0)], aaPos[e2->vertex(1)]))
431  {
432  // calculate the positions
433  vector_t v1, v2;
434  VecScaleAdd(v1, (1. - t1), aaPos[e1->vertex(0)], t1, aaPos[e1->vertex(1)]);
435  VecScaleAdd(v2, (1. - t2), aaPos[e2->vertex(0)], t2, aaPos[e2->vertex(1)]);
436 
437  // check whether the points are close to each other
438  if(VecDistanceSq(v1, v2) < snapThresholdSq){
439  // calculate center
440  vector_t p;
441  VecScaleAdd(p, 0.5, v1, 0.5, v2);
442 
443  // to make sure that no double edges may occur, we'll use MergeVertices
444  RegularVertex* nVrt1 = SplitEdge<RegularVertex>(grid, grid, e1);
445  RegularVertex* nVrt2 = SplitEdge<RegularVertex>(grid, grid, e2);
446  aaPos[nVrt1] = p;
447  MergeVertices(grid, nVrt1, nVrt2);
448 
449  return nVrt1;
450  /*
451  // create a new vertex and split both edges using it
452  RegularVertex* vrt = *grid.create<RegularVertex>();
453  aaPos[vrt] = p;
454  CreateEdgeSplitGeometry(grid, grid, e1, vrt);
455  CreateEdgeSplitGeometry(grid, grid, e2, vrt);
456  grid.erase(e1);
457  grid.erase(e2);
458  */
459  }
460  else{
461  /*
462  LOG("distance check failed at: " << v1 << ", " << v2 << endl);
463  UG_LOG("edges with vertices: " << aaPos[e1->vertex(0)] << aaPos[e1->vertex(1)] << endl);
464  UG_LOG(" " << aaPos[e2->vertex(0)] << aaPos[e2->vertex(1)]);
465  */
466  }
467  }
468  return NULL;
469 }
470 
476 template <class TAAPosVRT>
478  TAAPosVRT& aaPos, number snapThreshold)
479 {
480  using namespace std;
481  typedef typename TAAPosVRT::ValueType vector_t;
482 
483 // check whether one edge contains a vertex of another edge
484  if(FaceContains(f, e->vertex(0)) || FaceContains(f, e->vertex(1)))
485  return false;
486 
487  vector_t dir;
488  VecSubtract(dir, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
489 
490  vector_t p;
491  number t1, t2, s;
492  bool refined = false;
493  vector<Face*> newFaces;
494  Vertex* newFaceVrt = NULL;
495  Vertex* vrt = NULL;
496  if(f->num_vertices() == 3){
497  if(RayTriangleIntersection(p, t1, t2, s, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
498  aaPos[f->vertex(2)], aaPos[e->vertex(0)], dir))
499  {
500  if((s >= 0) && (s <= 1.)){
501  // split the face
502  vrt = *grid.create<RegularVertex>();
503  Vertex* newEdgeVrts[3] = {NULL, NULL, NULL};
504  refined = f->refine(newFaces, &newFaceVrt, newEdgeVrts, vrt);
505  }
506  }
507  }
508  else if(f->num_vertices() == 4){
509  bool intersecting = false;
510  if(RayTriangleIntersection(p, t1, t2, s, aaPos[f->vertex(0)], aaPos[f->vertex(1)],
511  aaPos[f->vertex(2)], aaPos[e->vertex(0)], dir))
512  {
513  intersecting = true;
514  }
515  else if(RayTriangleIntersection(p, t1, t2, s, aaPos[f->vertex(0)], aaPos[f->vertex(2)],
516  aaPos[f->vertex(3)], aaPos[e->vertex(0)], dir))
517  {
518  intersecting = true;
519  }
520 
521  if(intersecting && (s >= 0) && (s <= 1.))
522  {
523  // split the face
524  vrt = *grid.create<RegularVertex>();
525  Vertex* newEdgeVrts[4] = {NULL, NULL, NULL, NULL};
526  refined = f->refine(newFaces, &newFaceVrt, newEdgeVrts, vrt);
527  }
528  }
529 
530  if(refined && vrt){
531  // create a new vertex and adjust position
532  aaPos[vrt] = p;
533 
534  // register the new faces and erase the old one
535  for(size_t i = 0; i < newFaces.size(); ++i)
536  grid.register_element(newFaces[i], f);
537  grid.erase(f);
538 
539  // to make sure that no double edges may occur, we'll use MergeVertices
540  // and SplitEdge
541  RegularVertex* nVrt = SplitEdge<RegularVertex>(grid, grid, e);
542  MergeVertices(grid, vrt, nVrt);
543 
544 /*
545  // split the edge with the new vertex and erase the old one
546  CreateEdgeSplitGeometry(grid, grid, e, vrt);
547  grid.erase(e);
548 */
549 
550  return true;
551  }
552 
553  return false;
554 }
555 
556 
558 
562 template <class TVrtIter, class TAAPos>
563 void SpacialVertexSort(std::multimap<number, Vertex*>& vrtsOut,
564  const TVrtIter vrtsBegin, const TVrtIter vrtsEnd,
565  const typename TAAPos::ValueType& rayFrom,
566  const typename TAAPos::ValueType& rayDir,
567  TAAPos aaPos,
568  bool clearContainer = true)
569 {
570  typedef typename TAAPos::ValueType vector_t;
571 
572  if(clearContainer)
573  vrtsOut.clear();
574 
575  for(TVrtIter i_vrt = vrtsBegin; i_vrt != vrtsEnd; ++i_vrt){
576  vector_t p;
577  number t = ProjectPointToRay(p, aaPos[*i_vrt], rayFrom, rayDir);
578  vrtsOut.insert(std::pair<number, Vertex*>(t, *i_vrt));
579  }
580 }
581 
582 
584 
587 template <class TVrtIter, class TAAPos>
588 void MultiEdgeSplit(Grid& grid, Edge* edge,
589  TVrtIter vrtsBegin, TVrtIter vrtsEnd,
590  TAAPos aaPos)
591 {
592  if(vrtsBegin == vrtsEnd)
593  return;
594 
595  typedef typename TAAPos::ValueType vector_t;
596  vector_t dir;
597  VecSubtract(dir, aaPos[edge->vertex(1)], aaPos[edge->vertex(0)]);
598 
599  std::multimap<number, Vertex*> vrtMap;
600  SpacialVertexSort(vrtMap, vrtsBegin, vrtsEnd, aaPos[edge->vertex(0)], dir, aaPos);
601 
602 // all associated faces have to be converted to triangles first
603 // since we may alter faces, we'll collect them in a std::vector
604  std::vector<Face*> faces;
605  CollectFaces(faces, grid, edge);
606  for(size_t i = 0; i < faces.size(); ++i){
607  if(faces[i]->num_vertices() > 3){
608  Quadrilateral* q = dynamic_cast<Quadrilateral*>(faces[i]);
609  if(q)
610  Triangulate(grid, q, &aaPos);
611  }
612  }
613 
614 // now collect associated faces again and find the connected vertices
615 // also store for each associated face whether the orientation matches.
616  CollectFaces(faces, grid, edge);
617  std::vector<Vertex*> conVrts(faces.size());
618  std::vector<bool> orientations(faces.size());
619  for(size_t i = 0; i < faces.size(); ++i){
620  orientations[i] = EdgeOrientationMatches(edge, faces[i]);
621  conVrts[i] = GetConnectedVertex(edge, faces[i]);
622  UG_COND_THROW(conVrts[i] == NULL,
623  " no connected vertex found to edge: " << ElementDebugInfo(grid, edge)
624  << " and face " << ElementDebugInfo(grid, faces[i]));
625  }
626 
627  FaceDescriptor fd(3);
629 
630  std::multimap<number, Vertex*>::iterator iter = vrtMap.begin();
631  Vertex* curVrt = edge->vertex(0);
632  Vertex* nextVrt = iter->second;
633  while(nextVrt){
634  // create a new edge
635  if(curVrt != nextVrt){
636  EdgeDescriptor ed(curVrt, nextVrt);
637  if(!grid.get_element(ed))
638  grid.create<RegularEdge>(ed, edge);
639 
640  // create new triangles for all connected vertices
641  for(size_t i = 0; i < faces.size(); ++i){
642  if(conVrts[i] == curVrt || conVrts[i] == nextVrt)
643  continue;
644 
645  if(orientations[i]){
646  fd.set_vertex(0, curVrt);
647  fd.set_vertex(1, nextVrt);
648  fd.set_vertex(2, conVrts[i]);
649  }
650  else{
651  fd.set_vertex(0, nextVrt);
652  fd.set_vertex(1, curVrt);
653  fd.set_vertex(2, conVrts[i]);
654  }
655  if(!grid.get_element(fd)){
656  grid.create<Triangle>(TriangleDescriptor(fd.vertex(0), fd.vertex(1), fd.vertex(2)),
657  faces[i]);
658  }
659  }
660  }
661 
662  // pick next vertex pair
663  if(nextVrt == edge->vertex(1))
664  break;
665  else{
666  curVrt = nextVrt;
667  ++iter;
668  if(iter != vrtMap.end())
669  nextVrt = iter->second;
670  else
671  nextVrt = edge->vertex(1);
672  }
673  }
674 
675 // erase the old edge and associated faces
676  grid.erase(edge);
677 }
678 
679 
686 namespace impl{
688  struct Record{
689  Record() : closestEdge(-1), distanceSq(std::numeric_limits<number>::max()) {}
692  };
693 }}
694 
695 template <class TAPos>
697  GridObjectCollection elems,
698  TAPos& aPos,
699  number snapThreshold)
700 {
701 // to speed things up we'll use an octree!
702  typedef lg_ntree<3, 3, Vertex> octree_t;
703  typedef octree_t::box_t box_t;
704  typedef typename TAPos::ValueType vector_t;
705 
706  Grid::VertexAttachmentAccessor<TAPos> aaPos(grid, aPos);
707  number snapThresholdSq = sq(snapThreshold);
708 
709  size_t numVrts = elems.num<Vertex>();
710  size_t numEdges = elems.num<Edge>();
711 
712 // we'll only use an octree if there is a high number of vertices and edges...
713  bool useOctree = (numVrts > 10 && numEdges > 10);
714  octree_t octree(grid, aPos);
715  if(useOctree)
716  octree.create_tree(elems.begin<Vertex>(), elems.end<Vertex>());
717 
718 // we'll now iterate over all edges and search for close vertices.
719  vector_t offset;
720  VecSet(offset, snapThreshold);
721  std::vector<Vertex*> closeVrts;
722  std::vector<Vertex*> insertVrts;
723 
724  if(!useOctree){
725  closeVrts.reserve(elems.num<Vertex>());
726  for(VertexIterator iter = elems.begin<Vertex>();
727  iter != elems.end<Vertex>(); ++iter)
728  {
729  closeVrts.push_back(*iter);
730  }
731  }
732 
734  std::map<Vertex*, Record> snapVrtMap;
735  std::vector<Edge*> edges;
736  edges.reserve(elems.num<Edge>());
737  for(EdgeIterator eIter = elems.begin<Edge>(); eIter != elems.end<Edge>(); ++eIter)
738  edges.push_back(*eIter);
739 
740 // find the closest edge for each vertex first and store it in snapVrtMap
741  for(size_t iEdge = 0; iEdge < edges.size(); ++iEdge){
742  Edge* e = edges[iEdge];
743 
744  vector_t corner[2];
745  corner[0] = aaPos[e->vertex(0)];
746  corner[1] = aaPos[e->vertex(1)];
747 
748  // get all close vertices from the tree and do the projection
749  if(useOctree){
750  box_t bbox(corner, 2);
751  bbox.min -= offset;
752  bbox.max += offset;
753  FindElementsInIntersectingNodes(closeVrts, octree, bbox);
754  }
755 
756  // find all vertices which have to be inserted by traversing closeVrts
757  for(size_t i = 0; i < closeVrts.size(); ++i){
758  Vertex* vrt = closeVrts[i];
759  if(EdgeContains(e, vrt))
760  continue;
761 
762  vector_t p;
763  number s = ProjectPointToLine(p, aaPos[vrt], corner[0], corner[1]);
764  // we do an exact comparision here, since all other matches should be
765  // handled by a remove-doubles anyways
766  if(s > 0 && s < 1.){
767  const number distSq = VecDistanceSq(p, aaPos[vrt]);
768  if(distSq <= snapThresholdSq){
769  Record& rec = snapVrtMap[vrt];
770  if(distSq < rec.distanceSq){
771  rec.closestEdge = (int)iEdge;
772  rec.distanceSq = distSq;
773  }
774  }
775  }
776  }
777  }
778 
779 // split edges by finding associated vertices in snapVrtMap
780  for(size_t iEdge = 0; iEdge < edges.size(); ++iEdge){
781  Edge* e = edges[iEdge];
782 
783  vector_t corner[2];
784  corner[0] = aaPos[e->vertex(0)];
785  corner[1] = aaPos[e->vertex(1)];
786 
787  // get all close vertices from the tree and do the projection
788  if(useOctree){
789  box_t bbox(corner, 2);
790  bbox.min -= offset;
791  bbox.max += offset;
792  FindElementsInIntersectingNodes(closeVrts, octree, bbox);
793  }
794 
795  // find all vertices which have to be inserted by traversing closeVrts
796  insertVrts.clear();
797  for(size_t i = 0; i < closeVrts.size(); ++i){
798  Vertex* vrt = closeVrts[i];
799  if(EdgeContains(e, vrt))
800  continue;
801 
802  std::map<Vertex*, Record>::iterator imap = snapVrtMap.find(vrt);
803  if(imap != snapVrtMap.end()){
804  Record& rec = imap->second;
805  if(rec.closestEdge == (int)iEdge)
806  insertVrts.push_back(vrt);
807  }
808  }
809 
810  if(!insertVrts.empty()){
811  MultiEdgeSplit(grid, e, insertVrts.begin(), insertVrts.end(), aaPos);
812  }
813  }
814 
815  return true;
816 }
817 
825 template <class TObjectCollection, class TAPos>
827  TObjectCollection& elems,
828  TAPos& aPos,
829  number snapThreshold)
830 {
831 // to speed things up we'll use an octree!
832  typedef lg_ntree<3, 3, Vertex> octree_t;
833  typedef octree_t::box_t box_t;
834  typedef typename TAPos::ValueType vector_t;
835 
836  Grid::VertexAttachmentAccessor<TAPos> aaPos(grid, aPos);
837  number snapThresholdSq = sq(snapThreshold);
838 
839  size_t numVrts = elems.template num<Vertex>();
840  size_t numFaces = elems.template num<Face>();
841 
842 // we'll only use an octree if there is a high number of vertices and edges...
843  bool useOctree = (numVrts > 10 && numFaces > 10);
844  octree_t octree(grid, aPos);
845  if(useOctree)
846  octree.create_tree(elems.template begin<Vertex>(), elems.template end<Vertex>());
847 
848  vector_t offset;
849  VecSet(offset, snapThreshold);
850 
851  std::vector<Vertex*> closeVrts;
852  std::vector<Vertex*> insertVrts;
853 
854  if(!useOctree){
855  closeVrts.reserve(elems.template num<Vertex>());
856  for(VertexIterator iter = elems.template begin<Vertex>();
857  iter != elems.template end<Vertex>(); ++iter)
858  {
859  closeVrts.push_back(*iter);
860  }
861  }
862 
863  std::queue<Face*> qFaces;
864 
865  for(FaceIterator iter = elems.template begin<Face>();
866  iter != elems.template end<Face>(); ++iter)
867  {
868  qFaces.push(*iter);
869  }
870 
871  std::vector<Face*> newFaces;
872  // int maxIters = 1;
873  while(!qFaces.empty()){
874  // if(maxIters <= 0)
875  // break;
876 
877  Face* f = qFaces.front();
878  qFaces.pop();
879  if(useOctree){
880  box_t bbox(aaPos[f->vertex(0)], aaPos[f->vertex(0)]);
881  for(size_t i = 1; i < f->num_vertices(); ++i){
882  bbox = box_t(bbox, aaPos[f->vertex(i)]);
883  }
884  bbox.min -= offset;
885  bbox.max += offset;
886  FindElementsInIntersectingNodes(closeVrts, octree, bbox);
887  }
888 
889  for(size_t i = 0; i < closeVrts.size(); ++i){
890  Vertex* vrt = closeVrts[i];
891  if(!FaceContains(f, vrt)){
892  // if the vertex is too close to a corner, we'll skip the insertion
893  bool skip = false;
894  for(size_t j = 0; j < f->num_vertices(); ++j){
895  Vertex* corner = f->vertex(j);
896  if(VecDistanceSq(aaPos[vrt], aaPos[corner]) <= snapThresholdSq){
897  skip = true;
898  break;
899  }
900  }
901 
902  if(skip)
903  continue;
904 
905  if(ResolveVertexFaceIntersection(grid, vrt, f, aaPos, snapThresholdSq,
906  &newFaces))
907  {
908  // UG_LOG("resolved intersection of vertex at: " << aaPos[vrt] << std::endl);
909  // --maxIters;
910  for(size_t j = 0; j < newFaces.size(); ++j){
911  qFaces.push(newFaces[j]);
912  }
913  break;
914  }
915  }
916  }
917  }
918 
919  return true;
920 }
921 
931 template <class TObjectCollection, class TAAPosVRT>
933  TObjectCollection& elems,
934  TAAPosVRT& aaPos,
935  number snapThreshold)
936 {
937 // we'll first mark all elements in elems to make sure that
938 // only edges which were initially marked are intersected.
939  grid.begin_marking();
940  for(EdgeIterator iter = elems.template begin<Edge>();
941  iter != elems.template end<Edge>(); ++iter)
942  {
943  grid.mark(*iter);
944  }
945 
946 // perform edge/edge and edge/face intersections
948 // if faces exist, more intersections may be necessary...
949  const size_t maxIntersections = sq(elems.template num<Edge>());
950  size_t numIntersections = 0;
951 
952  for(EdgeIterator mainIter = elems.template begin<Edge>();
953  mainIter != elems.template end<Edge>();)
954  {
955  if(numIntersections > maxIntersections){
956  UG_LOG("Intersection threshold reached in IntersectCloseEdges. "
957  " Not all intersections may have been resolved.\n");
958  UG_LOG(" num-initial-edges: " << sqrt(maxIntersections) << "\n");
959  grid.end_marking();
960  return false;
961  }
962 
963  Edge* e = *mainIter;
964  ++mainIter;
965 
966  // only consider marked edges
967  if(!grid.is_marked(e))
968  continue;
969 
970  // check all other edges up to e.
971  for(EdgeIterator iter = elems.template begin<Edge>(); *iter != e;)
972  {
973  Edge* e2 = *iter;
974  ++iter;
975  if(!grid.is_marked(e2))
976  continue;
977 
978  // if an intersection occured, we have to move on to the next edge in the queue,
979  // since the old edge no longer exists.
980  Vertex* nVrt = ResolveEdgeEdgeIntersection(grid, e, e2, aaPos, snapThreshold);
981  if(nVrt){
982  ++numIntersections;
983  // all edges connected to nVrt have to be marked, since they are new candidates!
984  grid.associated_elements(edges, nVrt);
985  for(size_t i = 0; i < edges.size(); ++i){
986  grid.mark(edges[i]);
987  }
988  break;
989  }
990  }
991  }
992  grid.end_marking();
993  return true;
994 }
995 
996 
998 
999 template <class TAAPosVRT>
1000 int FindCloseVertexInArray(std::vector<Vertex*>& array,
1001  const typename TAAPosVRT::ValueType& p,
1002  TAAPosVRT& aaPos, number snapThreshold)
1003 {
1004  number snapThrSq = snapThreshold * snapThreshold;
1005 // iterate over the array and check whether a vertex close to vrt already exists.
1006  for(size_t i = 0; i < array.size(); ++i){
1007  if(VecDistanceSq(aaPos[array[i]], p) < snapThrSq){
1008  // we got one. return the index
1009  return (int)i;
1010  }
1011  }
1012  return -1;
1013 }
1014 
1016 
1017 template <class TAAPosVRT>
1018 int FindClosestVertexInArray(std::vector<Vertex*>& array, const Vertex* p,
1019  TAAPosVRT& aaPos, number snapThreshold)
1020 {
1021  number snapThrSq = snapThreshold * snapThreshold;
1022 
1023  number bestDistance = VecDistanceSq(aaPos[array[0]], aaPos[p]);
1024  int bestElem = 0;
1025 
1026  for (size_t i = 1; i < array.size(); ++i) {
1027  number dist = VecDistanceSq(aaPos[array[i]], aaPos[p]);
1028  if (dist < bestDistance) {
1029  bestDistance = dist;
1030  bestElem = i;
1031  }
1032  }
1033  return (bestDistance < snapThrSq) ? bestElem : -1;
1034 }
1035 
1037 
1038 template <class TAAPosVRT, class vector_t>
1039 int FindClosestVertexInPointSet(const vector_t* pointSet, const Vertex* p,
1040  TAAPosVRT& aaPos, number snapThreshold,
1041  size_t numPoints) {
1042  std::vector<Vertex*> vertices;
1043  vertices.resize(numPoints);
1044  for (size_t i = 0; i < numPoints; ++i) {
1045  vertices[i] = pointSet[i];
1046  }
1047  return FindClosestVertexInArray(vertices, p, aaPos, snapThreshold);
1048 }
1049 
1050 
1053 
1059 inline bool IntersectCoplanarTriangles(std::vector<vector2>& edgesOut,
1060  const vector2& p00, const vector2& p01, const vector2& p02,
1061  const vector2& p10, const vector2& p11, const vector2& p12)
1062 {
1063  // UG_LOG("intersecting...\n");
1064 
1065  edgesOut.clear();
1066 
1067  vector2 t0_ARR[] = {p00, p01, p02};
1068  vector2 t1_ARR[] = {p10, p11, p12};
1069  vector2* t0 = t0_ARR;
1070  vector2* t1 = t1_ARR;
1071 
1072 // to avoid rounding issues we search for the largest node-value and scale SMALL by that value
1073  number maxLenSq = 0;
1074  for(size_t i = 0; i < 3; ++i){
1075  maxLenSq = std::max(maxLenSq, VecLengthSq(t0[i]));
1076  maxLenSq = std::max(maxLenSq, VecLengthSq(t1[i]));
1077  }
1078  const number sml = SMALL * sqrt(maxLenSq);
1079  const number smlSq = sq(sml);
1080  // UG_LOG("sml: " << sml << ", smlSq: " << smlSq << "\n");
1081 
1082  // UG_LOG(" 2d-coords-t1: " << p00 << ", " << p01 << ", " << p02 << std::endl);
1083  // UG_LOG(" 2d-coords-t2: " << p10 << ", " << p11 << ", " << p12 << std::endl);
1084  // for(size_t i = 0; i < 3; ++i){
1085  // for(size_t j = 0; j < 3; ++j){
1086  // UG_LOG("VertexDistance " << i << "-" << j << ": " << VecDistance(t0[i], t1[j]) << std::endl);
1087  // }
1088  // }
1089 
1090 // first we check whether the two triangles are separable
1091 // note that t0 and t1 are switched twice, so that both are checked
1092  for(int i_tri = 0; i_tri < 2; ++i_tri){
1093  for(int i0 = 0; i0 < 3; ++i0){
1094  int i1 = (i0+1)%3;
1095  int i2 = (i0+2)%3;
1096  vector2 d;
1097  VecSubtract(d, t0[i1], t0[i0]);
1098  number refLen = VecLength(d);
1099  if(refLen < SMALL)
1100  continue;
1101  //vector2 n(d.y() / refLen, -d.x() / refLen);
1102  vector2 n(d.y(), -d.x());
1103  VecScale(n, n, (number) 1 / refLen);
1104  vector2 v;
1105  VecSubtract(v, t0[i2], t0[i0]);
1106  number refDot = VecDot(v, n);
1107  // UG_LOG("refDot: " << refDot << std::endl);
1108  bool separable = true;
1109  for(int j = 0; j < 3; ++j){
1110  VecSubtract(v, t1[j], t0[i0]);
1111  // UG_LOG(" first-pass:\n");
1112  // UG_LOG(" checkedDot: " << VecDot(v, n) << std::endl);
1113  // UG_LOG(" product: " << VecDot(v, n) * refDot << std::endl);
1114  // UG_LOG(" refLen*SMALL: " << refLen * SMALL << std::endl);
1115  //if(VecDot(v, n) * refDot > refLen * SMALL){
1116  if(VecDot(v, n) * refDot > sml){
1117  // UG_LOG("not separable\n");
1118  // not separable along this edge
1119  separable = false;
1120  break;
1121  }
1122  }
1123 
1124  if(separable)
1125  return false;
1126  }
1127  std::swap(t0, t1);
1128  }
1129 
1130  bool isInside[3];
1131  int matchingCorner[] = {-1, -1, -1};// matching corner in t0 for i-th point of t1
1132 
1133  for(int i = 0; i < 3; ++i){
1134  isInside[i] = PointIsInsideTriangle(t1[i], p00, p01, p02);
1135  //if(isInside[i]){
1136  for(int j = 0; j < 3; ++j){
1137  if(VecDistanceSq(t0[j], t1[i]) < smlSq){
1138  matchingCorner[i] = j;
1139  isInside[i] = true;
1140  // UG_LOG("matching corners: " << i << ", " << j << "\n");
1141  break;
1142  }
1143  }
1144  //}
1145  }
1146 
1147  for(int i0 = 0; i0 < 3; ++i0){
1148  int i1 = (i0+1)%3;
1149  if(isInside[i0]){
1150  if(isInside[i1]){
1151  if((matchingCorner[i0] == -1) || (matchingCorner[i1] == -1)){
1152  // both points do lie in the triangle and thus the whole edge does
1153  edgesOut.push_back(t1[i0]);
1154  edgesOut.push_back(t1[i1]);
1155  }
1156  }
1157  else{
1158  // an intersection with one of the other edges has to exist
1159  bool gotOne = false;
1160  for(int j0 = 0; j0 < 3; ++j0){
1161  int j1 = (j0+1)%3;
1162  vector2 vi;
1163  number s0, s1;
1164  if(LineLineIntersection2d(vi, s0, s1, t1[i0], t1[i1],
1165  t0[j0], t0[j1], sml))
1166  {
1167  // got our two points
1168  if(VecDistanceSq(t1[i0], vi) > smlSq){
1169  edgesOut.push_back(t1[i0]);
1170  edgesOut.push_back(vi);
1171  gotOne = true;
1172  break;
1173  }
1174  }
1175  }
1176  UG_COND_THROW(!gotOne && (matchingCorner[i0] == -1),
1177  "An intersection has to exist if one point is "
1178  "inside and one point is outside!\n"
1179  << " checked line: " << t1[i0] << " - " << t1[i1]
1180  << "\nchecked tri: " << t0[0] << ", " << t0[1] << ", " << t0[2]);
1181  }
1182  }
1183  else if(isInside[i1]){
1184  // an intersection with one of the other edges has to exist
1185  bool gotOne = false;
1186  for(int j0 = 0; j0 < 3; ++j0){
1187  int j1 = (j0+1)%3;
1188  vector2 vi;
1189  number s0, s1;
1190  if(LineLineIntersection2d(vi, s0, s1, t1[i0], t1[i1],
1191  t0[j0], t0[j1], sml))
1192  {
1193  // got our two points
1194  if(VecDistanceSq(vi, t1[i1]) > smlSq){
1195  edgesOut.push_back(vi);
1196  edgesOut.push_back(t1[i1]);
1197  gotOne = true;
1198  break;
1199  }
1200  }
1201  }
1202  UG_COND_THROW(!gotOne && (matchingCorner[i1] == -1),
1203  "An intersection has to exist if one point is "
1204  "inside and one point is outside!\n"
1205  << " checked line: " << t1[i0] << " - " << t1[i1]
1206  << "\nchecked tri: " << t0[0] << ", " << t0[1] << ", " << t0[2]);
1207  }
1208  else{
1209  // both points lie outside. An intersection may still exist. In this case
1210  // however, the edge should intersect two other edges
1211  int numInts = 0;
1212  vector2 ints[2];
1213  for(int j0 = 0; j0 < 3; ++j0){
1214  int j1 = (j0+1)%3;
1215  number s0, s1;
1216  if(LineLineIntersection2d(ints[numInts], s0, s1, t1[i0], t1[i1],
1217  t0[j0], t0[j1], sml))
1218  {
1219  ++numInts;
1220  if(numInts > 1)
1221  break;
1222  }
1223  }
1224  UG_COND_THROW(numInts == 1, "Either 0 or 2 intersections have to exist!\n"
1225  << " checked line: " << t1[i0] << " - " << t1[i1]
1226  << "\nchecked tri: " << t0[0] << ", " << t0[1] << ", " << t0[2]);
1227  if(numInts == 2){
1228  edgesOut.push_back(ints[0]);
1229  edgesOut.push_back(ints[1]);
1230  }
1231  }
1232  }
1233  return !edgesOut.empty();
1234 }
1235 
1238 
1248 inline bool IntersectCoplanarTriangles(std::vector<vector3>& edgesOut,
1249  const vector3& p00, const vector3& p01, const vector3& p02,
1250  const vector3& p10, const vector3& p11, const vector3& p12)
1251 {
1252  edgesOut.clear();
1253 
1254 // we have to project all points into the 2d space.
1255 // The transformation taken from the first triangle
1256  vector3 n;
1257  CalculateTriangleNormal(n, p00, p01, p02);
1258  matrix33 m;
1259  if(!ConstructOrthonormalSystem(m, n, 2)){
1260  UG_LOG("Construction of local orthonormal system failed...\n");
1261  return false;
1262  }
1263 
1264 // in order to make the transformation more robust, we'll rotate the triangles
1265 // around the center of tri-0
1266  vector3 c = p00;
1267  c += p01;
1268  c += p02;
1269  c *= (1./3.);
1270 
1271  // UG_LOG(" 3d-coords-t1: " << p00 << ", " << p01 << ", " << p02 << std::endl);
1272  // UG_LOG(" 3d-coords-t2: " << p10 << ", " << p11 << ", " << p12 << std::endl);
1273  // UG_LOG(" n: " << n << ", c: " << c << std::endl);
1274 
1275  vector3 v, vp0, vp1, vp2, vp3, vp4, vp5;
1276  VecSubtract(v, p00, c);
1277  TransposedMatVecMult(vp0, m, v);
1278  VecSubtract(v, p01, c);
1279  TransposedMatVecMult(vp1, m, v);
1280  VecSubtract(v, p02, c);
1281  TransposedMatVecMult(vp2, m, v);
1282  VecSubtract(v, p10, c);
1283  TransposedMatVecMult(vp3, m, v);
1284  VecSubtract(v, p11, c);
1285  TransposedMatVecMult(vp4, m, v);
1286  VecSubtract(v, p12, c);
1287  TransposedMatVecMult(vp5, m, v);
1288 
1289  std::vector<vector2> edges2d;
1290  if(IntersectCoplanarTriangles(edges2d,
1291  vector2(vp0.x(), vp0.y()), vector2(vp1.x(), vp1.y()), vector2(vp2.x(), vp2.y()),
1292  vector2(vp3.x(), vp3.y()), vector2(vp4.x(), vp4.y()), vector2(vp5.x(), vp5.y())))
1293  {
1294  edgesOut.resize(edges2d.size());
1295  for(size_t i = 0; i < edges2d.size(); ++i){
1296  vector3 v;
1297  VecCopy(v, edges2d[i], 0);
1298  MatVecMult(edgesOut[i], m, v);
1299  edgesOut[i] += c;
1300  }
1301  return true;
1302  }
1303  return false;
1304 }
1305 
1308 
1310 template <class TAAPos>
1311 bool IntersectCoplanarTriangles(std::vector<typename TAAPos::ValueType>& edgesOut,
1312  FaceVertices* tri1, FaceVertices* tri2,
1313  TAAPos aaPos)
1314 {
1315  try{
1316  // UG_LOG("checking tris: " << CalculateCenter(tri1, aaPos)
1317  // << ", " << CalculateCenter(tri2, aaPos) << std::endl);
1318  if((tri1->num_vertices() == 3) && (tri2->num_vertices() == 3)){
1319 
1320  return IntersectCoplanarTriangles(edgesOut,
1321  aaPos[tri1->vertex(0)], aaPos[tri1->vertex(1)], aaPos[tri1->vertex(2)],
1322  aaPos[tri2->vertex(0)], aaPos[tri2->vertex(1)], aaPos[tri2->vertex(2)]);
1323  }
1324  }
1325  catch(UGError& err){
1326  UG_THROW(err.get_msg() << "\n"
1327  << "centers of involved triangles: " << CalculateCenter(tri1, aaPos)
1328  << ", " << CalculateCenter(tri2, aaPos));
1329  }
1330  // UG_CATCH_THROW("centers of involved triangles: " << CalculateCenter(tri1, aaPos)
1331  // << ", " << CalculateCenter(tri2, aaPos));
1332  return false;
1333 }
1334 
1335 template <class TAAPos>
1336 Sphere<typename TAAPos::ValueType>
1338 {
1340  s.center = CalculateCenter(face, aaPos);
1341  number maxDistSq = 0;
1342  for(size_t i = 0; i < face->num_vertices(); ++i){
1343  maxDistSq = std::max<number>(maxDistSq,
1344  VecDistanceSq(s.center, aaPos[face->vertex(i)]));
1345  }
1346  s.radius = sqrt(maxDistSq);
1347  return s;
1348 }
1350 
1352 template <class TAPos>
1354  TriangleIterator trisEnd, number snapThreshold,
1355  TAPos& aPos)
1356 {
1357  using namespace std;
1358  // number snapThresholdSq = sq(snapThreshold);
1359 //todo: add octree
1360 // we use a selector to select elements that shall be merged and
1361 // triangles that are to be processed and deleted.
1362  Selector sel(grid);
1363  sel.enable_autoselection(false);
1364 
1365  sel.select(trisBegin, trisEnd);
1366 // we first select all associated vertices and perform a merge on them
1367  SelectAssociatedVertices(sel, trisBegin, trisEnd);
1368  // SelectAssociatedEdges(sel, trisBegin, trisEnd);
1369  RemoveDoubles<3>(grid, sel.vertices_begin(), sel.vertices_end(),
1370  aPos, snapThreshold);
1371 
1373 // PERFORM AND RESOLVE TRIANGLE - TRIANGLE INTERSECTIONS
1374  Grid::VertexAttachmentAccessor<TAPos> aaPos(grid, aPos);
1375 
1376 // to speed things up we'll use an octree!
1377  typedef lg_ntree<3, 3, Face> octree_t;
1378  typedef octree_t::box_t box_t;
1379 
1380  octree_t octree(grid, aPos);
1381  octree.create_tree(trisBegin, trisEnd);
1382 
1383 // clear edges and vertices from the selector. faces have to stay, since we will
1384 // operate on them now.
1385  sel.clear<Vertex>();
1386  sel.clear<Edge>();
1387 
1388 // enable selection inheritance, since we want new elements to be
1389 // selected in this selector
1390  sel.enable_selection_inheritance(true);
1391 
1392 // we need some attachments in order to store new vertices and edges for
1393 // each face.
1394  typedef Attachment<vector<Vertex*> > AVrtVec;
1395  typedef Attachment<vector<pair<int, int> > > AEdgeDescVec;
1396  AVrtVec aVrtVec;
1397  AEdgeDescVec aEdgeDescVec;
1398  grid.attach_to_faces(aVrtVec);
1399  grid.attach_to_faces(aEdgeDescVec);
1400  Grid::FaceAttachmentAccessor<AVrtVec> aaVrtVec(grid, aVrtVec);
1401  Grid::FaceAttachmentAccessor<AEdgeDescVec> aaEdgeDescVec(grid, aEdgeDescVec);
1402 
1403  std::vector<vector3> planarIntersections;
1404 
1405 // this vector will be used to find close triangles
1406  vector<Face*> closeTris;
1408 
1409 // iterate over all triangles and perform intersection with other triangles
1410  size_t triCounter = 0;
1411  for(TriangleIterator triIter1 = sel.begin<Triangle>();
1412  triIter1 != sel.end<Triangle>(); ++triIter1, ++triCounter)
1413  {
1414  Face* t1 = *triIter1;
1415 
1416  box_t bbox;
1417  bbox.min = bbox.max = aaPos[t1->vertex(0)];
1418  for(size_t i = 1; i < t1->num_vertices(); ++i)
1419  bbox = box_t(bbox, aaPos[t1->vertex(i)]);
1420  bbox.min -= vector3(snapThreshold, snapThreshold, snapThreshold);
1421  bbox.max += vector3(snapThreshold, snapThreshold, snapThreshold);
1422 
1423  // find close triangles
1424  FindElementsInIntersectingNodes(closeTris, octree, bbox);
1425 
1426  // iterate over the rest of the triangles
1427  for(size_t i_close = 0; i_close < closeTris.size(); ++i_close){
1428  Face* t2 = closeTris[i_close];
1429  Face* t[2]; t[0] = t1; t[1] = t2;
1430 
1431  // the attachments have a fixed order throughout the whole iteration...
1432  // we want to make sure that each pair of triangles is checked only once.
1433  // at the same time we avoid that t1 is intersected with t1...
1434  if(grid.get_attachment_data_index(t1) >= grid.get_attachment_data_index(t2))
1435  continue;
1436 
1437  // check is obsolete, since only close elements are considered.
1438  // Sphere<vector3> s1 = CalculateBoundingSphere(t1, aaPos);
1439  // Sphere<vector3> s2 = CalculateBoundingSphere(t2, aaPos);
1440  // if(VecDistance(s1.center, s2.center)
1441  // > (s1.radius + s2.radius + snapThreshold + SMALL))
1442  // {
1443  // continue;
1444  // }
1445 
1446  //todo: Move both triangles closer to the origin to minimize rounding issues...
1447 
1448  // perform normal comparision to handle coplanar triangles
1449  vector3 n1, n2;
1450  CalculateNormal(n1, t1, aaPos);
1451  CalculateNormal(n2, t2, aaPos);
1452  number d = VecDot(n1, n2);
1453  if(fabs(d) > 1. - snapThreshold){
1454  // if the two triangles aren't in the same plane, there's nothing to do...
1455  if(DistancePointToPlane(aaPos[t2->vertex(0)], aaPos[t1->vertex(0)], n1) > snapThreshold)
1456  continue;
1457  // perform coplanar triangle intersection for tri1 and tri2
1458  // note that t1 and t2 are swapped twice - once at the end of each i_tri iteration.
1459  for(int i_tri = 0; i_tri < 2; ++i_tri){
1460  if(IntersectCoplanarTriangles(planarIntersections, t1, t2, aaPos)){
1461  // if(triCounter == dbgTriInd){
1462  // UG_LOG("<dbg> Coplanar Triangles Intersected\n");
1463  // }
1464 
1465  // we have to make sure that the corners of both triangles are
1466  // contained in aVrtVec if an intersection occurs.
1467  for(int j_tri = 0; j_tri < 2; ++j_tri){
1468  vector<Vertex*>& vrts = aaVrtVec[t[j_tri]];
1469  if(vrts.empty()){
1470  for(size_t i = 0; i < t[j_tri]->num_vertices(); ++i)
1471  vrts.push_back(t[j_tri]->vertex(i));
1472  }
1473  }
1474 
1475  vector<Vertex*>& vrts = aaVrtVec[t1];
1476 
1477  for(size_t i = 0; i < planarIntersections.size(); i+=2){
1478  int inds[2];
1479  for(int j = 0; j < 2; ++j){
1480  inds[j] = FindCloseVertexInArray(vrts,
1481  planarIntersections[i+j],
1482  aaPos, snapThreshold);
1483  if(inds[j] == -1){
1484  // check if the vertex is contained in the other tri...
1485  vector<Vertex*>& vrts2 = aaVrtVec[t2];
1486  int ind = FindCloseVertexInArray(vrts2,
1487  planarIntersections[i+j],
1488  aaPos, snapThreshold);
1489  if(ind != -1){
1490  // insert the vertex into t1's list of vertices
1491  inds[j] = (int)vrts.size();
1492  vrts.push_back(vrts2[ind]);
1493  }
1494  }
1495  if(inds[j] == -1){
1496  // we have to create a new vertex
1497  Vertex* vrt = *grid.create<RegularVertex>();
1498  aaPos[vrt] = planarIntersections[i+j];
1499  inds[j] = (int)vrts.size();
1500  vrts.push_back(vrt);
1501  }
1502  }
1503  if(inds[0] != inds[1])
1504  aaEdgeDescVec[t1].push_back(make_pair(inds[0], inds[1]));
1505  }
1506  }
1507  // swap tris
1508  std::swap(t1, t2);
1509  }
1510  continue;
1511  }
1512 
1513  // since the faces are not coplanar, we have to make sure
1514  // that t1 and t2 do not share an edge (two vertices)
1515  size_t numShared = NumSharedVertices(grid, t1, t2);
1516  if(numShared > 1)
1517  continue;
1518 
1519  vector3 ip[2];
1520  if(TriangleTriangleIntersection(aaPos[t1->vertex(0)], aaPos[t1->vertex(1)],
1521  aaPos[t1->vertex(2)], aaPos[t2->vertex(0)],
1522  aaPos[t2->vertex(1)], aaPos[t2->vertex(2)],
1523  &ip[0], &ip[1], SMALL) == 1)
1524  {
1525  // if(triCounter == dbgTriInd){
1526  // UG_LOG("<dbg> tri " << dbgTriInd << " Intersection points: " << ip[0] << ", " << ip[1] << endl);
1527  // UG_LOG("involved triangles: " << ElementDebugInfo(grid, t1) << std::endl);
1528  // UG_LOG(" and: " << ElementDebugInfo(grid, t2) << std::endl);
1529  // }
1530  // add an edge between the two points
1531  // to avoid insertion of double points, we first check whether the point
1532  // already exists in the triangle. Do this for both triangles.
1533 
1534  // prepare both triangles.
1535  //todo: think about performance optimizations.
1536  // insertion of corner points could be avoided by bloating the code a little.
1537  // this could increase performance.
1538  for(size_t i_tri = 0; i_tri < 2; ++i_tri){
1539  // If it is encountered for the first time,
1540  // we'll add its corner-vertices to its list of vertices.
1541  Face* tri = t[i_tri];
1542  vector<Vertex*>& vrts = aaVrtVec[tri];
1543  if(vrts.empty()){
1544  for(size_t i = 0; i < tri->num_vertices(); ++i)
1545  vrts.push_back(tri->vertex(i));
1546  }
1547 
1548  // (a) this version only checks for close vertices in the list
1549  // of vertices of the currently processed triangle. This
1550  // version will introduce more (and possibly very close)
1551  // vertices, but should be more robust.
1552  // todo: only create vertices for each point once, for both tris!
1553 
1554  // int edgeInd[2] = {-1, -1};
1555  // for(size_t i_point = 0; i_point < 2; ++i_point){
1556  // const vector3& point = ip[i_point];
1557  // int closeInd = FindCloseVertexInArray(aaVrtVec[tri], point,
1558  // aaPos, snapThreshold);
1559 
1560  // if(closeInd == -1){
1561  // Vertex* vrt = *grid.create<RegularVertex>();
1562  // aaPos[vrt] = point;
1563  // closeInd = (int)aaVrtVec[tri].size();
1564  // aaVrtVec[tri].push_back(vrt);
1565  // }
1566 
1567  // edgeInd[i_point] = closeInd;
1568  // }
1569 
1570  // if(edgeInd[0] != edgeInd[1])
1571  // aaEdgeDescVec[tri].push_back(
1572  // make_pair(edgeInd[0], edgeInd[1]));
1573  }
1574 
1575  // (b) the version below also checks for existing vertices in other tris.
1576  // however, this can lead to vertices which do not lie in the plane
1577  // of an intersecting triangle. This in turn may lead to problems
1578  // during triangulation.
1579 
1580  int inds1[2];
1581  int inds2[2];
1582  for(size_t i = 0; i < 2; ++i){
1583  int tind1 = FindCloseVertexInArray(aaVrtVec[t[0]], ip[i],
1584  aaPos, snapThreshold);
1585  int tind2 = FindCloseVertexInArray(aaVrtVec[t[1]], ip[i],
1586  aaPos, snapThreshold);
1587  if(tind1 == -1){
1588  if(tind2 == -1){
1589  // UG_LOG("<dbg> Creating a new vertex in tri intersection at " << ip[i] << std::endl);
1590  // UG_LOG("involved triangles: " << ElementDebugInfo(grid, t[0]) << std::endl);
1591  // UG_LOG(" and: " << ElementDebugInfo(grid, t[1]) << std::endl);
1592  // we have to create a new vertex
1593  Vertex* vrt = *grid.create<RegularVertex>();
1594  aaPos[vrt] = ip[i];
1595  tind1 = (int)aaVrtVec[t[0]].size();
1596  tind2 = (int)aaVrtVec[t[1]].size();
1597  aaVrtVec[t[0]].push_back(vrt);
1598  aaVrtVec[t[1]].push_back(vrt);
1599  }
1600  else{
1601  // the vertex already exists in t[1]
1602  tind1 = (int)aaVrtVec[t[0]].size();
1603  aaVrtVec[t[0]].push_back((aaVrtVec[t[1]])[tind2]);
1604  }
1605  }
1606  else if(tind2 == -1){
1607  // the vertex already exists in t[0]
1608  tind2 = (int)aaVrtVec[t[1]].size();
1609  aaVrtVec[t[1]].push_back((aaVrtVec[t[0]])[tind1]);
1610  }
1611 
1612  // ind1 now contains the index into the vertex array of t[0], at
1613  // which a vertex with position ip[i] lies.
1614  inds1[i] = tind1;
1615  inds2[i] = tind2;
1616  }
1617  // we found the indices of both endpoints and can now add an edge
1618  // connecting both to the edgeDesc arrays of t[0] and t[1].
1619  if(inds1[0] != inds1[1])
1620  aaEdgeDescVec[t[0]].push_back(make_pair(inds1[0], inds1[1]));
1621  if(inds2[0] != inds2[1])
1622  aaEdgeDescVec[t[1]].push_back(make_pair(inds2[0], inds2[1]));
1623  }
1624  }
1625  }
1626 
1627 // all intersections have been resolved. Iterate over the triangles again and
1628 // create the new elements.
1629 // triangles that shall be deleted are pushed to vDelTris
1630  vector<Triangle*> vDelTris;
1631 // here we collect all vertices on which a merge has to be performed at the end
1632 // of the algorithm (vertices created through edge-edge intersections inside a triangle)
1633  vector<Vertex*> cutVertices;
1635  AInt aInt;
1636  AVertex aVrt;
1637  tgrid.attach_to_vertices(aPos);
1638  tgrid.attach_to_vertices(aInt);
1639  tgrid.attach_to_vertices_dv(aVrt, NULL);
1640  Grid::VertexAttachmentAccessor<TAPos> taaPos(tgrid, aPos);
1641  Grid::VertexAttachmentAccessor<AVertex> aaVrt(tgrid, aVrt);
1642 
1643 // holds vertices of tgrid, so that they are accessible by index.
1644  vector<Vertex*> tgridVrts;
1645 // we don't want the newly created faces to be selected
1646  sel.enable_selection_inheritance(false);
1647 
1648  std::vector<Vertex*> dblVrts;
1649  triCounter = 0;
1650  for(TriangleIterator triIter = sel.begin<Triangle>();
1651  triIter != sel.end<Triangle>(); ++triIter, ++triCounter)
1652  {
1653  Triangle* t = *triIter;
1654  // we only proceed if there are intersecion-edges at all
1655  if(aaVrtVec[t].size() > 3){
1656  tgrid.clear_geometry();
1657  tgridVrts.clear();
1658 
1659  // copy vertices associated with t1 to tgrid
1660  vector<Vertex*>& vrts = aaVrtVec[t];
1661  for(size_t i = 0; i < vrts.size(); ++i){
1662  Vertex* vrt = *tgrid.create<RegularVertex>();
1663  aaVrt[vrt] = vrts[i];
1664  taaPos[vrt] = aaPos[vrts[i]];
1665  tgridVrts.push_back(vrt);
1666  }
1667 
1668  // now create the edges. vertices are found by indexing tgridVrts
1669  vector<pair<int, int> >& edgeDescs = aaEdgeDescVec[t];
1670 
1671  // tri edges
1672  tgrid.create<RegularEdge>(EdgeDescriptor(tgridVrts[0], tgridVrts[1]));
1673  tgrid.create<RegularEdge>(EdgeDescriptor(tgridVrts[1], tgridVrts[2]));
1674  tgrid.create<RegularEdge>(EdgeDescriptor(tgridVrts[2], tgridVrts[0]));
1675 
1676  // new edges
1677  for(size_t i = 0; i < edgeDescs.size(); ++i){
1678  tgrid.create<RegularEdge>(EdgeDescriptor(tgridVrts[edgeDescs[i].first],
1679  tgridVrts[edgeDescs[i].second]));
1680  }
1681 
1682  // if(triCounter == 128){
1683  // grid_intersection_impl::DebugSave (tgrid, "tri-128", aPos);
1684  // }
1685 
1686  // due to construction there may be double-edges
1687  RemoveDuplicates(tgrid, tgrid.edges_begin(), tgrid.edges_end());
1688 
1689  // we now have to resolve intersections between the edges
1690  // first we'll try to snap vertices to edges
1692  aPos, snapThreshold);
1693 
1694  // remove doubles
1695  // typically we only have a few vertices here...
1696  //todo: use a special version of this algorithm which uses a kdtree if many
1697  // vertices are present
1698  // dblVrts.clear();
1699  // for(VertexIterator iter = tgrid.begin<Vertex>();
1700  // iter != tgrid.end<Vertex>(); ++iter)
1701  // {
1702  // dblVrts.push_back(*iter);
1703  // }
1704 
1705  // const size_t numVrts = dblVrts.size();
1706  // for(size_t i = 0; i < numVrts; ++i){
1707  // Vertex* v0 = dblVrts[i];
1708  // if(!v0) continue;
1709  // for(size_t j = i+1; j < numVrts; ++j){
1710  // Vertex* v1 = dblVrts[j];
1711  // if(!v1) continue;
1712  // if(VecDistanceSq(aaPos[v0], aaPos[v1]) <= snapThresholdSq){
1713  // MergeVertices(tgrid, v0, v1);
1714  // dblVrts[j] = NULL;
1715  // }
1716  // }
1717  // }
1718 
1719  // //DEBUGGING BEGIN
1720  // {
1721  // UG_LOG("STORING TEST GRID\n");
1722  // static int dbgCounter = 0;
1723  // std::stringstream name;
1724  // name << "/home/sreiter/Desktop/_grids/failure-"
1725  // << dbgCounter << ".ugx";
1726  // SaveGridToFile(tgrid, name.str().c_str(), aPos);
1727 
1728  // ++dbgCounter;
1729  // }
1730  // //DEBUGGING END
1731 
1732  // if there are only 3 vertices left, there's nothing to do...
1733  if(tgrid.num_vertices() <= 3)
1734  continue;
1735  // now resolve edge/edge intersections
1736  //IntersectCloseEdges(tgrid, tgrid, taaPos, SMALL);
1737  IntersectCloseEdges(tgrid, tgrid, taaPos, snapThreshold);
1738  // if(!IntersectCloseEdges(tgrid, tgrid, taaPos, snapThreshold)){
1739  // static int dbgCounter = 0;
1740  // std::stringstream name;
1741  // name << "/home/sreiter/Desktop/failed_sweeplines/failed_intersect_close_edges_"
1742  // << dbgCounter << ".ugx";
1743  // SaveGridToFile(tgrid, name.str().c_str(), aPos);
1744 
1745  // ++dbgCounter;
1746  // }
1747 
1748  // make sure that all vertices have an associated aaVrt
1749  for(VertexIterator viter = tgrid.vertices_begin();
1750  viter != tgrid.vertices_end(); ++viter)
1751  {
1752  if(!aaVrt[*viter]){
1753  // since the vertex does not have an associated vertex in grid,
1754  // it is clear that it has been created through an edge-edge cut.
1755  // Associates of such vertices have to be merged later on.
1756  aaVrt[*viter] = *grid.create<RegularVertex>();
1757  aaPos[aaVrt[*viter]] = taaPos[*viter];
1758  cutVertices.push_back(aaVrt[*viter]);
1759  }
1760  }
1761 
1762 
1763  // ok. Everything is prepared. We can now triangulate the grid.
1764  if(TriangleFill_SweepLine(tgrid, tgrid.edges_begin(), tgrid.edges_end(),
1765  aPos, aInt))
1766  {
1767  // mark the triangle for deletion
1768  vDelTris.push_back(*triIter);
1769 
1770  // add the triangles to the grid.
1771  for(TriangleIterator titer = tgrid.begin<Triangle>();
1772  titer != tgrid.end<Triangle>(); ++titer)
1773  {
1774  Triangle* ntri = *titer;
1775  FaceDescriptor fd(3);
1776  fd.set_vertex(0, aaVrt[ntri->vertex(0)]);
1777  fd.set_vertex(1, aaVrt[ntri->vertex(1)]);
1778  fd.set_vertex(2, aaVrt[ntri->vertex(2)]);
1779 
1780  if(!grid.get_element(fd)){
1781  grid.create<Triangle>(TriangleDescriptor(aaVrt[ntri->vertex(0)],
1782  aaVrt[ntri->vertex(1)],
1783  aaVrt[ntri->vertex(2)]),
1784  *triIter);
1785  }
1786  }
1787  }
1788  else{
1789  UG_LOG("TriangleFill_SweepLine failed for tri " << triCounter << "\n");
1790  UG_LOG("at:")
1791  size_t cnt = 0;
1792  for(VertexIterator iter = tgrid.begin<Vertex>();
1793  iter != tgrid.end<Vertex>(); ++iter, ++cnt)
1794  {
1795  if(cnt > 2)
1796  break;
1797  UG_LOG(" " << taaPos[*iter]);
1798  }
1799  UG_LOG(std::endl);
1800 
1801  grid_intersection_impl::DebugSave(tgrid, "failed_sweepline", aPos);
1802  grid_intersection_impl::DebugSave2d(tgrid, "failed_sweepline_2d", aPos);
1803 
1804  // UG_THROW("ResolveTriangleIntersections failed!");
1805  }
1806  }
1807  }
1808 
1809 // detach attachments (tgrid is deleted anyways)
1810  grid.detach_from_faces(aVrtVec);
1811  grid.detach_from_faces(aEdgeDescVec);
1812 
1814 // GRID POSTPROCESS
1815 // before we merge vertices in cutVertices, we'll select all faces
1816 // in order to make sure that only valid faces will be deleted.
1817  sel.clear();
1818  sel.select(vDelTris.begin(), vDelTris.end());
1819  sel.select(cutVertices.begin(), cutVertices.end());
1820 
1821 // perform the merge (this has to be done on a selector.
1822 // the current version of RemoveDoubles is a little restrictive
1823 // in this regard.)
1824  if(!sel.empty<Vertex>()){
1825  RemoveDoubles<3>(grid, sel.vertices_begin(), sel.vertices_end(),
1826  aPosition, snapThreshold);
1827  }
1828 
1829  sel.clear<Vertex>();
1830  sel.clear<Edge>();
1831 
1832 // finally delete all refined triangles and associated unused edges and vertices
1835 
1836  grid.erase(sel.begin<Face>(), sel.end<Face>());
1837  grid.erase(sel.begin<Edge>(), sel.end<Edge>());
1838  grid.erase(sel.begin<Vertex>(), sel.end<Vertex>());
1839 
1840  return true;
1841 }
1842 
1843 }// end of namespace
1844 
1845 #endif
parameterString p
parameterString s
A generic specialization of IAttachment.
Definition: attachment_pipe.h:263
virtual Vertex * vertex(size_t index) const
Definition: grid_objects_2d.h:120
Can be used to store information about an edge and to construct an edge.
Definition: grid_base_objects.h:464
Base-class for edges.
Definition: grid_base_objects.h:397
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
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:701
void set_vertex(uint index, Vertex *vrt)
Definition: grid_base_objects.h:706
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
virtual bool refine(std::vector< Face * > &vNewFacesOut, Vertex **newFaceVertexOut, Vertex **newEdgeVertices, Vertex *newFaceVertex=NULL, Vertex **pSubstituteVertices=NULL, int snapPointIndex=-1)
Definition: grid_base_objects.h:594
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
Definition: grid_base_objects.h:483
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:486
virtual size_t num_vertices() const
Definition: grid_base_objects.h:488
Definition: grid.h:221
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
uint get_attachment_data_index(TGeomObj *pObj) const
Definition: grid_impl.hpp:419
EdgeIterator edges_begin()
Definition: grid.h:515
void register_element(Vertex *v, GridObject *pParent=NULL)
Definition: grid.h:870
void attach_to_vertices_dv(TAttachment &attachment, const typename TAttachment::ValueType &defaultValue)
Definition: grid.h:754
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition: grid_impl.hpp:843
VertexIterator vertices_begin()
Definition: grid.h:513
VertexIterator vertices_end()
Definition: grid.h:514
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
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
virtual GridObjectCollection get_grid_objects()
returns the the GridObjectCollection of the grid:
Definition: grid.cpp:527
void erase(GridObject *geomObj)
Definition: grid.cpp:459
void begin_marking()
begin marking.
Definition: grid.cpp:1262
void clear_geometry()
clears the grids geometry. Registered attachments remain.
Definition: grid.cpp:226
size_t num_vertices() const
Definition: grid.h:551
geometry_traits< TGeomObj >::iterator begin()
Definition: grid_impl.hpp:164
Edge * get_element(const EdgeVertices &ev)
returns the element for the given vertices.
Definition: grid.h:614
void attach_to_faces(IAttachment &attachment, bool passOnValues)
Definition: grid.h:730
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
void attach_to_vertices(IAttachment &attachment, bool passOnValues)
Definition: grid.h:728
geometry_traits< TGeomObj >::iterator create(GridObject *pParent=NULL)
create a custom element.
Definition: grid_impl.hpp:69
geometry_traits< TGeomObj >::iterator end()
Definition: grid_impl.hpp:175
EdgeIterator edges_end()
Definition: grid.h:516
void detach_from_faces(IAttachment &attachment)
Definition: grid.h:789
a helper class that holds a collection of possibly unconnected geometric-objects.
Definition: grid_object_collection.h:96
geometry_traits< TGeomObj >::iterator begin(size_t level=0)
Definition: grid_object_collection_impl.hpp:95
geometry_traits< TGeomObj >::iterator end(size_t level=0)
Definition: grid_object_collection_impl.hpp:106
size_t num() const
Definition: grid_object_collection_impl.hpp:130
void select(GridObject *elem, byte status)
selects an element
Definition: selector_interface_impl.hpp:56
void enable_selection_inheritance(bool bEnable)
Definition: selector_interface.cpp:195
void enable_autoselection(bool bEnable)
Definition: selector_interface.cpp:190
A class for fixed size, dense matrices.
Definition: math_matrix.h:52
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
a face with four points.
Definition: grid_objects_2d.h:323
Edges connect two vertices.
Definition: grid_objects_1d.h:66
A basic vertex-type.
Definition: grid_objects_0d.h:62
specialization of ISelector for a grid of class Grid.
Definition: selector_grid.h:96
geometry_traits< TElem >::iterator end()
Definition: selector_grid_impl.hpp:134
bool empty() const
Definition: selector_grid_impl.hpp:91
VertexIterator vertices_end()
Definition: selector_grid.h:173
virtual void clear()
Definition: selector_grid.cpp:155
VertexIterator vertices_begin()
Definition: selector_grid.h:172
geometry_traits< TElem >::iterator begin()
Definition: selector_grid_impl.hpp:106
Definition: shapes.h:42
only used to initialize a triangle. for all other tasks you should use FaceDescriptor.
Definition: grid_objects_2d.h:78
the most simple form of a face
Definition: grid_objects_2d.h:174
Instances of this class or of derived classes are thrown if errors arise.
Definition: error.h:104
const std::string & get_msg() const
returns the initial message
Definition: error.h:137
Base-class for all vertex-types.
Definition: grid_base_objects.h:231
Definition: lg_ntree.h:338
bool EdgeContains(EdgeVertices *e, Vertex *vrt)
Definition: grid_util_impl.hpp:45
int NumAssociatedFaces(Grid &grid, Edge *e)
returns the number of associated faces of the given edge
Definition: edge_util.cpp:247
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 FaceContains(Face *f, EdgeVertices *ev)
returns true if the given face contains the two given vertices
Definition: grid_util.cpp:561
void Triangulate(Grid &grid, Quadrilateral *q, Grid::VertexAttachmentAccessor< APosition > *paaPos)
removes the quadrilateral and replaces it by two triangles.
Definition: face_util.cpp:273
UG_API size_t NumSharedVertices(Grid &grid, TElemPtr1 elem1, TElemPtr2 elem2)
returns the number of vertices that are shared by two objects
Definition: misc_util_impl.hpp:200
std::string ElementDebugInfo(const Grid &grid, GridObject *e)
Returns a string containing information on the given element.
Definition: debug_util.cpp:991
void CollectFaces(std::vector< Face * > &vFacesOut, Grid &grid, Vertex *vrt, bool clearContainer)
Collects all faces that exist in the given grid which contain the given vertex.
Definition: grid_util.cpp:458
void SelectInnerSelectionVertices(TSelector &sel)
selects all vertices that are only connected to selected elements.
Definition: selection_util.cpp:641
void SelectAssociatedVertices(TSelector &sel, TElemIterator elemsBegin, TElemIterator elemsEnd, ISelector::status_t status=ISelector::SELECTED)
selects all associated vertices of the elements between elemsBegin and elemsEnd
Definition: selection_util_impl.hpp:229
void SelectInnerSelectionEdges(TSelector &sel)
selects all edges that are only connected to selected elements.
Definition: selection_util.cpp:748
void MergeVertices(Grid &grid, Vertex *v1, Vertex *v2)
merges two vertices and restructures the adjacent elements.
Definition: vertex_util.cpp:395
Vertex * GetConnectedVertex(Edge *e, Vertex *v)
returns the vertex that is connected to v via e.
Definition: vertex_util.cpp:78
@ GRIDOPT_STANDARD_INTERCONNECTION
All elements store references to associated lower dimensional geometric objects.
Definition: grid_constants.h:107
#define UG_THROW(msg)
Definition: error.h:57
#define UG_LOG(msg)
Definition: log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
double number
Definition: types.h:124
void TransposedMatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
Transposed Matrix - Vector Muliplication.
Definition: math_matrix_vector_functions_common_impl.hpp:111
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
number ProjectPointToLine(vector_t &vOut, const vector_t &v, const vector_t &from, const vector_t &to)
finds the projection of v onto the line defined by from and to
Definition: math_util_impl.hpp:186
bool TransformPointSetTo2D(vector2 *pointSetOut, const vector3 *pointSet, size_t numPoints)
transforms points from 3d space to 2d space.
Definition: math_util.cpp:294
bool LineLineIntersection2d(vector_t &vOut, number &t0Out, number &t1Out, const vector_t &from0, const vector_t &to0, const vector_t &from1, const vector_t &to1, const number threshold=0)
calculates the intersection of a two lines in 2d
Definition: math_util_impl.hpp:443
bool LineLineProjection(number &t1Out, number &t2Out, const vector_t &a1, const vector_t &a2, const vector_t &b1, const vector_t &b2)
calculates the closest point between the rays through the given lines.
Definition: math_util_impl.hpp:488
bool ConstructOrthonormalSystem(matrix33 &matOut, const vector3 &v, size_t vColInd)
constructs a orthonormal matrix given a vector in 3d.
Definition: math_util.cpp:211
number DropAPerpendicular(vector_t &vOut, const vector_t &v, const vector_t &v0, const vector_t &v1)
finds the projection of v onto the line defined by v0 and v1
Definition: math_util_impl.hpp:123
bool PointIsInsideTriangle(const vector_t &v, const vector_t &v0, const vector_t &v1, const vector_t &v2)
Returns true if the point lies inside or on the boundary of a triangle.
Definition: math_util_impl.hpp:971
TNumber sq(TNumber val)
returns the square of a value (val*val)
Definition: math_util_impl.hpp:91
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
bool RayTriangleIntersection(vector_t &vOut, number &bc1Out, number &bc2Out, number &tOut, const vector_t &p0, const vector_t &p1, const vector_t &p2, const vector_t &vFrom, const vector_t &vDir, const number small=SMALL)
calculates the intersection of a ray with a triangle
Definition: math_util_impl.hpp:506
void ProjectPointToPlane(vector_t &vOut, const vector_t &v, const vector_t &p, const vector_t &n)
projects v onto the plane defined by the point p and the planes normal n.
Definition: math_util_impl.hpp:342
UG_API bool TriangleTriangleIntersection(const MathVector< 3 > &p0, const MathVector< 3 > &p1, const MathVector< 3 > &p2, const MathVector< 3 > &q0, const MathVector< 3 > &q1, const MathVector< 3 > &q2, MathVector< 3 > *ip1Out=NULL, MathVector< 3 > *ip2Out=NULL, number snapThreshold=SMALL)
checks whether two triangles intersect and returns the intervals, if they do.
Definition: tritri.cpp:390
number DistancePointToPlane(const vector_t &v, const vector_t &p, const vector_t &n)
Calculates the distance between the specified point and the plane.
Definition: math_util_impl.hpp:332
number ProjectPointToRay(vector_t &vOut, const vector_t &v, const vector_t &from, const vector_t &dir)
finds the projection of v onto the ray defined by from and dir
Definition: math_util_impl.hpp:160
vector_t::value_type VecLength(const vector_t &v)
returns the length of v. Slower than VecLengthSq.
Definition: math_vector_functions_common_impl.hpp:341
void VecCopy(vector_target_t &target, const vector_source_t &source, typename vector_target_t::value_type fill)
Copy contents between vectors of possibly different types.
Definition: math_vector_functions_common_impl.hpp:56
MathVector< 2, number > vector2
a 2d vector
Definition: ugmath_types.h:69
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 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 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
void CalculateTriangleNormal(vector_t &vOut, const vector_t &v1, const vector_t &v2, const vector_t &v3)
Calculates a triangle-normal in 3d (output has length 1).
Definition: math_vector_functions_common_impl.hpp:528
MathVector< 3, number > vector3
a 3d vector
Definition: ugmath_types.h:72
vector_t::value_type VecLengthSq(const vector_t &v)
returns the squared length of v. Faster than VecLength.
Definition: math_vector_functions_common_impl.hpp:324
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
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
std::pair< counting_iterator< size_t >, counting_iterator< size_t > > vertices(ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:60
int num_vertices(ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:70
Definition: smart_pointer.h:814
void DebugSave2d(Grid &grid, const char *filePrefix, TAPos aPos)
Definition: resolve_intersections_impl.hpp:95
void DebugSave(Grid &grid, const char *filePrefix, TAPos aPos)
Definition: resolve_intersections_impl.hpp:80
the ug namespace
ElementStorage< Vertex >::SectionContainer::iterator VertexIterator
This Iterator will be used as base-class for iterators of specialized geometric objects.
Definition: grid_base_object_traits.h:73
ElementStorage< Face >::SectionContainer::iterator FaceIterator
Definition: grid_base_object_traits.h:79
bool SaveGridToFile(Grid &grid, ISubsetHandler &sh, const char *filename, TAPos &aPos)
Saves a grid to a file. Position data is read from the specified attachment.
Definition: file_io.cpp:468
const number SMALL
Definition: math_constants.h:41
bool FindElementsInIntersectingNodes(std::vector< typename tree_t::elem_t > &elemsOut, const tree_t &tree, const typename tree_t::box_t &bbox)
Definition: ntree_traverser.h:274
ElementStorage< Edge >::SectionContainer::iterator EdgeIterator
Definition: grid_base_object_traits.h:76
void SpacialVertexSort(std::multimap< number, Vertex * > &vrtsOut, const TVrtIter vrtsBegin, const TVrtIter vrtsEnd, const typename TAAPos::ValueType &rayFrom, const typename TAAPos::ValueType &rayDir, TAAPos aaPos, bool clearContainer=true)
sorts vertices along the specified ray
Definition: resolve_intersections_impl.hpp:563
int FindClosestVertexInPointSet(const vector_t *pointSet, const Vertex *p, TAAPosVRT &aaPos, number snapThreshold, size_t numPoints)
returns the index of the closest vertex to p if closer than snapThreshold
Definition: resolve_intersections_impl.hpp:1039
bool ProjectVerticesToCloseEdges(Grid &grid, GridObjectCollection elems, TAAPosVRT &aaPos, number snapThreshold)
bool ResolveVertexFaceIntersection(Grid &grid, Vertex *v, Face *f, TAAPosVRT &aaPos, number snapThreshold, std::vector< Face * > *pNewFacesOut)
Definition: resolve_intersections_impl.hpp:188
bool IntersectCoplanarTriangles(std::vector< vector2 > &edgesOut, const vector2 &p00, const vector2 &p01, const vector2 &p02, const vector2 &p10, const vector2 &p11, const vector2 &p12)
Intersects Coplanar Triangles.
Definition: resolve_intersections_impl.hpp:1059
Vertex * ResolveEdgeEdgeIntersection(Grid &grid, Edge *e1, Edge *e2, TAAPosVRT &aaPos, number snapThreshold)
Definition: resolve_intersections_impl.hpp:417
geometry_traits< Triangle >::iterator TriangleIterator
Definition: grid_objects_2d.h:211
int FindCloseVertexInArray(const std::vector< Vertex * > &array, const typename TAAPosVRT::ValueType &p, TAAPosVRT &aaPos, number snapThreshold)
returns the index of the first vertex closer to p than snapThreshold.
int FindClosestVertexInArray(const std::vector< Vertex * > &array, const Vertex *p, TAAPosVRT &aaPos, number snapThreshold)
returns the index of the closest vertex to p if closer than snapThreshold.
Sphere< typename TAAPos::ValueType > CalculateBoundingSphere(FaceVertices *face, TAAPos aaPos)
Definition: resolve_intersections_impl.hpp:1337
APosition aPosition("position", true)
The standard 3d position type.
Definition: common_attachments.h:84
bool IntersectCloseEdges(Grid &grid, TObjectCollection &elems, TAAPosVRT &aaPos, number snapThreshold)
Definition: resolve_intersections_impl.hpp:932
bool ResolveEdgeFaceIntersection(Grid &grid, Edge *e, Face *f, TAAPosVRT &aaPos, number snapThreshold)
Definition: resolve_intersections_impl.hpp:477
Vertex * ResolveVertexEdgeIntersection(Grid &grid, Vertex *v, Edge *e, TAAPosVRT &aaPos, number snapThreshold)
Definition: resolve_intersections_impl.hpp:137
bool ResolveTriangleIntersections(Grid &grid, TriangleIterator trisBegin, TriangleIterator trisEnd, number snapThreshold, TAPos &aPos)
Definition: resolve_intersections_impl.hpp:1353
void RemoveDuplicates(Grid &grid, TElemIter elemsBegin, TElemIter elemsEnd)
Removes elements which share the same set of vertices with other elements in the given range.
Definition: remove_duplicates_util.h:44
bool ProjectVerticesToCloseFaces(Grid &grid, TObjectCollection &elems, TAPos &aPos, number snapThreshold)
Definition: resolve_intersections_impl.hpp:826
bool EdgeOrientationMatches(EdgeVertices *ev, Face *f)
checks if the edge-orientation of the edge and the face matches.
Definition: orientation_util.cpp:37
bool TriangleFill_SweepLine(vector< int > &facesOut, const vector< vector2 > &srcVrtsOrig, vector< int > &srcEdges)
Performs triangulation of a polygon and resoves additional inner edges.
Definition: triangle_fill_sweep_line.cpp:942
void MultiEdgeSplit(Grid &grid, Edge *edge, TVrtIter vrtsBegin, TVrtIter vrtsEnd, TAAPos aaPos)
Inserts the specified vertices on the given edge.
Definition: resolve_intersections_impl.hpp:588
#define mkstr(s)
Comfortable (but not necessarily efficient) string building.
Definition: stringify.h:100
Definition: resolve_intersections_impl.hpp:688
Record()
Definition: resolve_intersections_impl.hpp:689
number distanceSq
Definition: resolve_intersections_impl.hpp:691
int closestEdge
Definition: resolve_intersections_impl.hpp:690