ug4
Loading...
Searching...
No Matches
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>
47
48namespace ug{
49
50namespace 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
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
136template <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
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
416template <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
476template <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
562template <class TVrtIter, class TAAPos>
563void 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
587template <class TVrtIter, class TAAPos>
588void 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
686namespace impl{
687namespace ProjectVerticesToCloseEdges{
688 struct Record{
689 Record() : closestEdge(-1), distanceSq(std::numeric_limits<number>::max()) {}
692 };
693}}
694
695template <class TAPos>
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
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
825template <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
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
931template <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
999template <class TAAPosVRT>
1000int 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
1017template <class TAAPosVRT>
1018int 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
1038template <class TAAPosVRT, class vector_t>
1039int 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
1059inline 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
1248inline 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
1310template <class TAAPos>
1311bool 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
1335template <class TAAPos>
1336Sphere<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
1352template <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
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...
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
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 size_t num_vertices() const
Definition grid_base_objects.h:488
virtual Vertex * vertex(size_t index) const
Definition grid_base_objects.h:486
Manages the elements of a grid and their interconnection.
Definition grid.h:132
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
Edge * get_element(const EdgeVertices &ev)
returns the element for the given vertices.
Definition grid.h:614
geometry_traits< TGeomObj >::iterator begin()
Definition grid_impl.hpp:164
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:63
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
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
Sphere< typename TAAPos::ValueType > CalculateBoundingSphere(FaceVertices *face, TAAPos aaPos)
Definition resolve_intersections_impl.hpp:1337
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.
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
PointerConstArray< Edge * > secure_container
Definition grid.h:146
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