triSurfaceChecks.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "triSurfaceChecks.H"
29 #include "triSurf.H"
30 #include "boundBox.H"
31 #include "meshOctree.H"
32 #include "meshOctreeCreator.H"
33 #include "helperFunctions.H"
34 
35 #ifdef USE_OMP
36 #include <omp.h>
37 # endif
38 
39 //#define DEBUGSurfaceChecks
40 
41 # ifdef DEBUGSurfaceChecks
42 #include "triSurfModifier.H"
43 # endif
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 namespace Foam
48 {
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 namespace triSurfaceChecks
53 {
54 
55 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
56 
58 (
59  const triSurf& surf,
60  labelLongList& badTriangles,
61  const scalar angleTol
62 )
63 {
64  badTriangles.clear();
65 
66  const scalar tol = Foam::cos(angleTol * M_PI / 180.0);
67 
68  const pointField& pts = surf.points();
69 
70  # ifdef USE_OMP
71  # pragma omp parallel for schedule(dynamic, 50)
72  # endif
73  forAll(surf, tI)
74  {
75  const labelledTri& tri = surf[tI];
76 
77  forAll(tri, pI)
78  {
79  vector vn = pts[tri[tri.fcIndex(pI)]] - pts[tri[pI]];
80  vn /= (mag(vn) + VSMALL);
81  vector vp = pts[tri[pI]] - pts[tri[tri.rcIndex(pI)]];
82  vp /= (mag(vp) + VSMALL);
83 
84  if( (vp & vn) >= tol )
85  {
86  # ifdef USE_OMP
87  # pragma omp critical
88  # endif
89  badTriangles.append(tI);
90 
91  break;
92  }
93  }
94  }
95 
96  return badTriangles.size();
97 }
98 
100 (
101  triSurf& surf,
102  const word subsetName,
103  const scalar angleTol
104 )
105 {
106  labelLongList badTriangles;
107 
108  if( checkAngles(surf, badTriangles, angleTol) )
109  {
110  label setId = surf.facetSubsetIndex(subsetName);
111  if( setId >= 0 )
112  surf.removeFacetSubset(setId);
113  setId = surf.addFacetSubset(subsetName);
114 
115  forAll(badTriangles, i)
116  surf.addFacetToSubset(setId, badTriangles[i]);
117  }
118 
119  return badTriangles.size();
120 }
121 
122 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
123 
124 namespace manifoldOps
125 {
126 
127 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
128 
130 {
131  // Private data
132  //- const reference to face-edges addressing
134 
135  //- const reference to edge-faces addressing
137 
138 public:
139 
140  // Constructors
141 
143  (
144  const VRWGraph& faceEdges,
145  const VRWGraph& edgeFaces
146  )
147  :
148  faceEdges_(faceEdges),
149  edgeFaces_(edgeFaces)
150  {}
151 
152  // Public member functions
153  label size() const
154  {
155  return faceEdges_.size();
156  }
157 
158  void operator()(const label tI, DynList<label>& neiTriangles) const
159  {
160  neiTriangles.clear();
161 
162  forAllRow(faceEdges_, tI, teI)
163  {
164  const label eI = faceEdges_(tI, teI);
165 
166  if( edgeFaces_.sizeOfRow(eI) != 2 )
167  continue;
168 
169  //- ind the neighbour triangle over the edge
170  label nei = edgeFaces_(eI, 0);
171 
172  if( nei == tI )
173  nei = edgeFaces_(eI, 1);
174 
175  neiTriangles.append(nei);
176  }
177  }
178 
179  template<class labelListType>
180  void collectGroups
181  (
182  std::map<label, DynList<label> >& /*neiGroups*/,
183  const labelListType& /*elementInGroup*/,
184  const DynList<label>& /*localGroupLabel*/
185  ) const
186  {
187  }
188 };
189 
190 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
191 
192 } // End namespace manifoldOps
193 
194 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
195 
196 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
197 
198 namespace selectorOps
199 {
200 
201 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
202 
203 class selectOp
204 {
205 
206 public:
207 
209  {}
210 
211  bool operator()(const label /*tI*/) const
212  {
213  return true;
214  }
215 };
216 
217 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
218 
219 } // End namespace selectorOps
220 
221 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
222 
223 
225 (
226  const triSurf& surf,
227  labelLongList& triangleInManifold
228 )
229 {
230  const VRWGraph& faceEdges = surf.facetEdges();
231  const VRWGraph& edgeFaces = surf.edgeFacets();
232 
233  const label nManifolds =
235  (
236  triangleInManifold,
237  manifoldOps::surfaceNeiOp(faceEdges, edgeFaces),
239  );
240 
241  return nManifolds;
242 }
243 
245 (
246  triSurf& surf,
247  const word subsetPrefix
248 )
249 {
250  labelLongList facetInManifold;
251 
252  const label nManifolds = checkSurfaceManifolds(surf, facetInManifold);
253 
254  if( nManifolds > 1 )
255  {
256  labelList groupIds(nManifolds);
257  forAll(groupIds, i)
258  {
259  const word sName = subsetPrefix+help::scalarToText(i);
260  label setId = surf.facetSubsetIndex(sName);
261  if( setId >= 0 )
262  surf.removeFacetSubset(setId);
263  groupIds[i] = surf.addFacetSubset(sName);
264  }
265 
266  forAll(facetInManifold, tI)
267  surf.addFacetToSubset(groupIds[facetInManifold[tI]], tI);
268  }
269 
270  return nManifolds;
271 }
272 
273 
274 label checkForHoles(const triSurf& surf, labelLongList& badTriangles)
275 {
276  badTriangles.clear();
277 
278  const VRWGraph& edgeFacets = surf.edgeFacets();
279 
280  # ifdef USE_OMP
281  # pragma omp parallel for schedule(dynamic, 100)
282  # endif
283  forAll(edgeFacets, eI)
284  {
285  if( edgeFacets.sizeOfRow(eI) == 1 )
286  {
287  # ifdef USE_OMP
288  # pragma omp critical
289  # endif
290  badTriangles.append(edgeFacets(eI, 0));
291  }
292  }
293 
294  return badTriangles.size();
295 }
296 
297 label checkForHoles(triSurf& surf, const word subsetName)
298 {
299  labelLongList trianglesNearHoles;
300 
301  if( checkForHoles(surf, trianglesNearHoles) )
302  {
303  label setId = surf.facetSubsetIndex(subsetName);
304  if( setId >= 0 )
305  surf.removeFacetSubset(setId);
306  setId = surf.addFacetSubset(subsetName);
307 
308  forAll(trianglesNearHoles, i)
309  surf.addFacetToSubset(setId, trianglesNearHoles[i]);
310  }
311 
312  return trianglesNearHoles.size();
313 }
314 
316 {
317  badTriangles.clear();
318 
319  const VRWGraph& edgeFacets = surf.edgeFacets();
320 
321  # ifdef USE_OMP
322  # pragma omp parallel for schedule(dynamic, 100)
323  # endif
324  forAll(edgeFacets, eI)
325  {
326  if( edgeFacets.sizeOfRow(eI) > 2 )
327  {
328  # ifdef USE_OMP
329  # pragma omp critical
330  # endif
331  {
332  forAllRow(edgeFacets, eI, efI)
333  badTriangles.append(edgeFacets(eI, efI));
334  }
335  }
336  }
337 
338  return badTriangles.size();
339 }
340 
342 (
343  triSurf& surf,
344  const word subsetPrefix
345 )
346 {
347  labelLongList trianglesNearHoles;
348 
349  if( checkForHoles(surf, trianglesNearHoles) )
350  {
351  label setId = surf.facetSubsetIndex(subsetPrefix);
352  if( setId >= 0 )
353  surf.removeFacetSubset(setId);
354  setId = surf.addFacetSubset(subsetPrefix);
355 
356  forAll(trianglesNearHoles, i)
357  surf.addFacetToSubset(setId, trianglesNearHoles[i]);
358  }
359 
360  return trianglesNearHoles.size();
361 }
362 
363 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
364 
365 namespace orientationOps
366 {
367 
368 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
369 
371 {
372  // Private data
373  //- const reference to face-edges addressing
375 
376  //- const reference to edge-faces addressing
378 
379  //- const reference to triangles
381 
382 public:
383 
384  // Constructors
385 
387  (
388  const VRWGraph& faceEdges,
389  const VRWGraph& edgeFaces,
390  const LongList<labelledTri>& triangles
391  )
392  :
393  faceEdges_(faceEdges),
394  edgeFaces_(edgeFaces),
395  triangles_(triangles)
396  {}
397 
398  // Public member functions
399  label size() const
400  {
401  return triangles_.size();
402  }
403 
404  void operator()(const label tI, DynList<label>& neiTriangles) const
405  {
406  neiTriangles.clear();
407 
408  const labelledTri& tri = triangles_[tI];
409 
410  forAllRow(faceEdges_, tI, teI)
411  {
412  const label eI = faceEdges_(tI, teI);
413 
414  if( edgeFaces_.sizeOfRow(eI) != 2 )
415  continue;
416 
417  //- ind the neighbour triangle over the edge
418  label nei = edgeFaces_(eI, 0);
419 
420  if( nei == tI )
421  nei = edgeFaces_(eI, 1);
422 
423  const labelledTri& neiTri = triangles_[nei];
424 
425  //- check the orientation
426  label pos(-1);
427  forAll(neiTri, i)
428  if( neiTri[i] == tri[teI] )
429  {
430  pos = i;
431  break;
432  }
433 
434  if( tri[tri.fcIndex(teI)] == neiTri[neiTri.rcIndex(pos)] )
435  {
436  //- triangles are of the same orientation
437  neiTriangles.append(nei);
438  }
439  }
440  }
441 
442  template<class labelListType>
443  void collectGroups
444  (
445  std::map<label, DynList<label> >& /*neiGroups*/,
446  const labelListType& /*elementInGroup*/,
447  const DynList<label>& /*localGroupLabel*/
448  ) const
449  {
450 
451  }
452 };
453 
454 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
455 
456 } // End namespace orientationOps
457 
458 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
459 
460 label checkOrientation(const triSurf& surf, labelLongList& triangleInGroup)
461 {
462  triangleInGroup.setSize(surf.size());
463  triangleInGroup = -1;
464  label nGroups(0);
465 
466  const VRWGraph& edgeFacets = surf.edgeFacets();
467  const VRWGraph& faceEdges = surf.facetEdges();
468  const LongList<labelledTri>& triangles = surf.facets();
469 
470  nGroups =
472  (
473  triangleInGroup,
474  orientationOps::surfaceNeiOp(faceEdges, edgeFacets, triangles),
476  );
477 
478  return nGroups;
479 }
480 
481 label checkOrientation(triSurf& surf, const word subsetPrefix)
482 {
483  labelLongList triangleInGroup;
484 
485  const label nGroups = checkOrientation(surf, triangleInGroup);
486 
487  if( nGroups > 1 )
488  {
489  labelList groupIds(nGroups);
490  forAll(groupIds, i)
491  {
492  const word sName = subsetPrefix+help::scalarToText(i);
493  label setId = surf.facetSubsetIndex(sName);
494  if( setId >= 0 )
495  surf.removeFacetSubset(setId);
496 
497  groupIds[i] = surf.addFacetSubset(sName);
498  }
499 
500  forAll(triangleInGroup, tI)
501  surf.addFacetToSubset(groupIds[triangleInGroup[tI]], tI);
502  }
503 
504  return nGroups;
505 }
506 
507 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
508 
509 namespace connectionOps
510 {
511 
512 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
513 
515 {
516  // Private data
517  //- const reference to face-edges addressing
519 
520  //- const reference to edge-faces addressing
522 
523 public:
524 
525  // Constructors
526 
528  (
529  const VRWGraph& faceEdges,
530  const VRWGraph& edgeFaces
531  )
532  :
533  faceEdges_(faceEdges),
534  edgeFaces_(edgeFaces)
535  {}
536 
537  // Public member functions
538  label size() const
539  {
540  return faceEdges_.size();
541  }
542 
543  void operator()(const label tI, DynList<label>& neiTriangles) const
544  {
545  neiTriangles.clear();
546 
547  forAllRow(faceEdges_, tI, teI)
548  {
549  const label eI = faceEdges_(tI, teI);
550 
551  forAllRow(edgeFaces_, eI, efI)
552  {
553  const label tJ = edgeFaces_(eI, efI);
554 
555  if( tJ == tI )
556  continue;
557 
558  neiTriangles.append(tJ);
559  }
560  }
561  }
562 
563  template<class labelListType>
564  void collectGroups
565  (
566  std::map<label, DynList<label> >& /*neiGroups*/,
567  const labelListType& /*elementInGroup*/,
568  const DynList<label>& /*localGroupLabel*/
569  ) const
570  {
571 
572  }
573 };
574 
575 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
576 
577 } // End namespace orientationOps
578 
579 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
580 
582 (
583  const triSurf& surf,
584  labelLongList& triangleInRegion
585 )
586 {
587  triangleInRegion.setSize(surf.size());
588  triangleInRegion = -1;
589  label nGroups(0);
590 
591  const VRWGraph& edgeFacets = surf.edgeFacets();
592  const VRWGraph& faceEdges = surf.facetEdges();
593 
594  nGroups =
596  (
597  triangleInRegion,
598  connectionOps::surfaceNeiOp(faceEdges, edgeFacets),
600  );
601 
602  return nGroups;
603 }
604 
605 label checkDisconnectedParts(triSurf& surf, const word subsetPrefix)
606 {
607  labelLongList triangleInRegion;
608 
609  const label nGroups = checkDisconnectedParts(surf, triangleInRegion);
610 
611  if( nGroups > 1 )
612  {
613  labelList groupIds(nGroups);
614  forAll(groupIds, i)
615  {
616  const word sName = subsetPrefix+help::scalarToText(i);
617  label setId = surf.facetSubsetIndex(sName);
618  if( setId >= 0 )
619  surf.removeFacetSubset(setId);
620 
621  groupIds[i] = surf.addFacetSubset(sName);
622  }
623 
624  forAll(triangleInRegion, tI)
625  surf.addFacetToSubset(groupIds[triangleInRegion[tI]], tI);
626  }
627 
628  return nGroups;
629 }
630 
631 void calculateBoundingBox(const triSurf& surf, boundBox& bb)
632 {
633  bb.min() = Foam::min(surf.points());
634  bb.max() = Foam::max(surf.points());
635 }
636 
638 (
639  const triSurf& surf,
640  labelLongList& collocatedPoints,
641  const scalar distTol
642 )
643 {
644  collocatedPoints.clear();
645 
646  meshOctree octree(surf);
648 
649  const pointField& pts = surf.points();
650 
651  boolList collocated(pts.size(), false);
652 
653  # ifdef USE_OMP
654  # pragma omp parallel for schedule(dynamic, 50)
655  # endif
656  forAll(collocated, pI)
657  {
658  const point& p = pts[pI];
659 
660  boundBox bb(p, p);
661 
662  bb.min() -= point(distTol, distTol, distTol);
663  bb.max() += point(distTol, distTol, distTol);
664 
665  DynList<label> leavesInBox;
666  octree.findLeavesContainedInBox(bb, leavesInBox);
667 
668  forAll(leavesInBox, i)
669  {
670  const label leafI = leavesInBox[i];
671 
672  DynList<label> trianglesInBox;
673 
674  octree.containedTriangles(leafI, trianglesInBox);
675 
676  forAll(trianglesInBox, j)
677  {
678  const label triJ = trianglesInBox[j];
679  const labelledTri& nt = surf[triJ];
680 
681  forAll(nt, tpI)
682  {
683  if( nt[tpI] == pI )
684  continue;
685 
686  if( magSqr(pts[nt[tpI]] - p) < sqr(distTol) )
687  {
688  collocated[pI] = true;
689  collocated[nt[tpI]] = true;
690  }
691  }
692  }
693  }
694  }
695 
696  forAll(collocated, pI)
697  if( collocated[pI] )
698  collocatedPoints.append(pI);
699 
700  return collocatedPoints.size();
701 }
702 
704 (
705  triSurf& surf,
706  const word subsetName,
707  const scalar distTol
708 )
709 {
710  labelLongList collocatedPoints;
711 
712  if( checkCollocatedPoints(surf, collocatedPoints, distTol) )
713  {
714  label setId = surf.pointSubsetIndex(subsetName);
715  if( setId >= 0 )
716  surf.removePointSubset(setId);
717  setId = surf.addPointSubset(subsetName);
718 
719  forAll(collocatedPoints, i)
720  surf.addPointToSubset(setId, collocatedPoints[i]);
721  }
722 
723  return collocatedPoints.size();
724 }
725 
727 (
728  const triSurf& surf,
729  labelLongList& badFaces,
730  const scalar tol
731 )
732 {
733  badFaces.clear();
734 
735  meshOctree octree(surf);
737 
738  const pointField& pts = surf.points();
739 
740  boolList intersected(surf.size(), false);
741 
742  # ifdef USE_OMP
743  # pragma omp parallel for schedule(dynamic, 50)
744  # endif
745  forAll(intersected, tI)
746  {
747  const labelledTri& tri = surf[tI];
748 
749  const triangle<point, point> currTri
750  (
751  pts[tri[0]],
752  pts[tri[1]],
753  pts[tri[2]]
754  );
755 
756  boundBox bb(pts[tri[0]], pts[tri[0]]);
757  for(label i=1;i<3;++i)
758  {
759  bb.min() = Foam::min(bb.min(), pts[tri[i]]);
760  bb.max() = Foam::max(bb.max(), pts[tri[i]]);
761  }
762 
763  bb.min() -= point(tol, tol, tol);
764  bb.max() += point(tol, tol, tol);
765 
766  DynList<label> leavesInBox;
767  octree.findLeavesContainedInBox(bb, leavesInBox);
768 
769  forAll(leavesInBox, i)
770  {
771  const label leafI = leavesInBox[i];
772 
773  DynList<label> trianglesInBox;
774 
775  octree.containedTriangles(leafI, trianglesInBox);
776 
777  forAll(trianglesInBox, j)
778  {
779  const label triJ = trianglesInBox[j];
780  const labelledTri& nt = surf[triJ];
781 
782  if( tI >= triJ )
783  continue;
784 
785  DynList<label, 3> sharedPoints;
786  forAll(nt, pJ)
787  {
788  forAll(tri, pI)
789  if( tri[pI] == nt[pJ] )
790  sharedPoints.append(pJ);
791  }
792 
793  if( sharedPoints.size() >= 2 )
794  {
795  //- triangles share an edge and cannot self-intersect
796  continue;
797  }
798  else if( sharedPoints.size() == 1 )
799  {
800  //- check if the opposite edge intersects the triangle
801  const point& s = pts[nt[(sharedPoints[0]+1)%3]];
802  const point& e = pts[nt[(sharedPoints[0]+2)%3]];
803 
805  const bool lineIntersection =
807 
808  if( lineIntersection )
809  {
810  intersected[tI] = true;
811  intersected[triJ] = true;
812  }
813  }
814  else
815  {
816  //- triangles do not share any vertices
817  const triangle<point, point> neiTri
818  (
819  pts[nt[0]],
820  pts[nt[1]],
821  pts[nt[2]]
822  );
823 
824  const bool intersect =
826  (
827  currTri,
828  neiTri,
829  tol
830  );
831 
832  if( intersect )
833  {
834  intersected[tI] = true;
835  intersected[triJ] = true;
836 
837  # ifdef DEBUGSurfaceChecks
838  const label sId =
839  const_cast<triSurf&>(surf).addFacetSubset
840  (
841  "noCommonIntersect_"+help::scalarToText(tI)+
842  "_"+help::scalarToText(triJ)
843  );
844  const_cast<triSurf&>(surf).addFacetToSubset(sId, tI);
845  const_cast<triSurf&>(surf).addFacetToSubset(sId, triJ);
846  # endif
847  }
848  }
849  }
850  }
851  }
852 
853  forAll(intersected, tI)
854  {
855  if( intersected[tI] )
856  badFaces.append(tI);
857  }
858 
859  return badFaces.size();
860 }
861 
863 (
864  triSurf& surf,
865  const word subsetName,
866  const scalar tol
867 )
868 {
869  labelLongList badFacets;
870 
871  if( checkSelfIntersections(surf, badFacets, tol) )
872  {
873  label setId = surf.facetSubsetIndex(subsetName);
874  if( setId >= 0 )
875  surf.removeFacetSubset(setId);
876  setId = surf.addFacetSubset(subsetName);
877 
878  forAll(badFacets, i)
879  surf.addFacetToSubset(setId, badFacets[i]);
880  }
881 
882  return badFacets.size();
883 }
884 
886 (
887  const triSurf& surf,
888  labelLongList& badFaces,
889  const scalar tol,
890  const scalar angleTol
891 )
892 {
893  badFaces.clear();
894 
895  meshOctree octree(surf);
897 
898  const scalar cosVal = Foam::cos(angleTol * M_PI / 180.0);
899 
900  const pointField& pts = surf.points();
901 
902  boolList intersected(surf.size(), false);
903 
904  # ifdef USE_OMP
905  # pragma omp parallel for schedule(dynamic, 50)
906  # endif
907  forAll(intersected, tI)
908  {
909  const labelledTri& tri = surf[tI];
910 
911  const triangle<point, point> currTri
912  (
913  pts[tri[0]],
914  pts[tri[1]],
915  pts[tri[2]]
916  );
917 
918  boundBox bb(pts[tri[0]], pts[tri[0]]);
919  for(label i=1;i<3;++i)
920  {
921  bb.min() = Foam::min(bb.min(), pts[tri[i]]);
922  bb.max() = Foam::max(bb.max(), pts[tri[i]]);
923  }
924 
925  bb.min() -= point(tol, tol, tol);
926  bb.max() += point(tol, tol, tol);
927 
928  DynList<label> leavesInBox;
929  octree.findLeavesContainedInBox(bb, leavesInBox);
930 
931  forAll(leavesInBox, i)
932  {
933  const label leafI = leavesInBox[i];
934 
935  DynList<label> trianglesInBox;
936 
937  octree.containedTriangles(leafI, trianglesInBox);
938 
939  forAll(trianglesInBox, j)
940  {
941  const label triJ = trianglesInBox[j];
942  const labelledTri& nt = surf[triJ];
943 
944  if( tI >= triJ )
945  continue;
946 
947  const triangle<point, point> neiTri
948  (
949  pts[nt[0]],
950  pts[nt[1]],
951  pts[nt[2]]
952  );
953 
954  DynList<point> commonPolygon;
955 
956  const bool intersect =
958  (
959  currTri,
960  neiTri,
961  commonPolygon,
962  tol,
963  cosVal
964  );
965 
966  if( intersect )
967  {
968  intersected[tI] = true;
969  intersected[triJ] = true;
970 
971  # ifdef DEBUGSurfaceChecks
972  const label sId =
973  const_cast<triSurf&>(surf).addFacetSubset
974  (
975  "noCommonOverlap_"+help::scalarToText(tI)+
976  "_"+help::scalarToText(triJ)
977  );
978  const_cast<triSurf&>(surf).addFacetToSubset(sId, tI);
979  const_cast<triSurf&>(surf).addFacetToSubset(sId, triJ);
980 
981  triSurf newSurf;
983  triSurfModifier(newSurf).patchesAccess();
984  patches.setSize(1);
985  patches[0].name() = "patch0";
986  forAll(commonPolygon, i)
987  newSurf.appendVertex(commonPolygon[i]);
988  for(label i=0;i<commonPolygon.size()-2;++i)
989  newSurf.appendTriangle(labelledTri(0, i+1, i+2, 0));
990  newSurf.writeSurface
991  (
992  "overlap_"+help::scalarToText(tI)+
993  "_"+help::scalarToText(triJ)+".fms"
994  );
995  # endif
996  }
997  }
998  }
999  }
1000 
1001  forAll(intersected, tI)
1002  {
1003  if( intersected[tI] )
1004  badFaces.append(tI);
1005  }
1006 
1007  return badFaces.size();
1008 }
1009 
1012  triSurf& surf,
1013  const word subsetName,
1014  const scalar tol,
1015  const scalar angleTol
1016 )
1017 {
1018  labelLongList badFaces;
1019 
1020  if( checkOverlaps(surf, badFaces, tol, angleTol) )
1021  {
1022  label setId = surf.facetSubsetIndex(subsetName);
1023  if( setId >= 0 )
1024  surf.removeFacetSubset(setId);
1025  setId = surf.addFacetSubset(subsetName);
1026 
1027  forAll(badFaces, i)
1028  surf.addFacetToSubset(setId, badFaces[i]);
1029  }
1030 
1031  return badFaces.size();
1032 }
1033 
1034 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1035 
1036 } // End namespace triSurfaceChecks
1037 
1038 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1039 
1040 } // End namespace Foam
1041 
1042 // ************************************************************************* //
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::collectGroups
void collectGroups(std::map< label, DynList< label > > &, const labelListType &, const DynList< label > &) const
Definition: triSurfaceChecks.C:565
triSurfaceChecks.H
Foam::LongList::append
void append(const T &e)
Append an element at the end of the list.
Definition: LongListI.H:265
triSurf.H
Foam::help::doTrianglesIntersect
bool doTrianglesIntersect(const triangle< point, point > &tri0, const triangle< point, point > &tri1, const scalar distTol=-1.0)
check the existence of intersection between the two triangles
Definition: helperFunctionsGeometryQueriesI.H:1149
p
p
Definition: pEqn.H:62
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::surfaceNeiOp
surfaceNeiOp(const VRWGraph &faceEdges, const VRWGraph &edgeFaces, const LongList< labelledTri > &triangles)
Definition: triSurfaceChecks.C:387
Foam::meshOctreeCreator
Definition: meshOctreeCreator.H:57
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::operator()
void operator()(const label tI, DynList< label > &neiTriangles) const
Definition: triSurfaceChecks.C:404
Foam::triSurfPoints::points
const pointField & points() const
access to points
Definition: triSurfPointsI.H:44
Foam::triSurfFacets::appendTriangle
void appendTriangle(const labelledTri &tria)
append a triangle to the end of the list
Definition: triSurfFacetsI.H:54
Foam::help::scalarToText
word scalarToText(const scalar s)
convert the scalar value into text
Definition: helperFunctionsStringConversion.C:61
Foam::LongList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: LongListI.H:230
Foam::meshOctree::containedTriangles
void containedTriangles(const label, DynList< label > &) const
Definition: meshOctreeI.H:81
Foam::triSurfaceChecks::checkOrientation
label checkOrientation(const triSurf &surf, labelLongList &triangleInGroup)
check orientation of triangles
Definition: triSurfaceChecks.C:460
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::collectGroups
void collectGroups(std::map< label, DynList< label > > &, const labelListType &, const DynList< label > &) const
Definition: triSurfaceChecks.C:444
triSurfModifier.H
Foam::triSurfModifier
Definition: triSurfModifier.H:48
Foam::LongList::size
label size() const
Size of the active part of the list.
Definition: LongListI.H:203
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::meshOctree::findLeavesContainedInBox
void findLeavesContainedInBox(const boundBox &, DynList< const meshOctreeCube *, 256 > &) const
find leaves contained in the box
Definition: meshOctreeInsideCalculations.C:131
Foam::triSurfaceChecks::calculateBoundingBox
void calculateBoundingBox(const triSurf &surf, boundBox &bb)
calculate bounding box of the surface mesh
Definition: triSurfaceChecks.C:631
Foam::triSurfPoints::addPointSubset
label addPointSubset(const word &)
point subsets
Definition: triSurfPoints.C:54
Foam::triSurfModifier::patchesAccess
geometricSurfacePatchList & patchesAccess()
access to patches
Definition: triSurfModifierI.H:52
Foam::FixedList::fcIndex
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: FixedListI.H:115
meshOctree.H
Foam::triSurfaceChecks::selectorOps::selectOp
Definition: triSurfaceChecks.C:203
Foam::triSurfPoints::appendVertex
void appendVertex(const point &p)
append a vertex to the end of the list
Definition: triSurfPointsI.H:49
Foam::LongList::setSize
void setSize(const label)
Reset size of List.
Definition: LongListI.H:223
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::collectGroups
void collectGroups(std::map< label, DynList< label > > &, const labelListType &, const DynList< label > &) const
Definition: triSurfaceChecks.C:181
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp
Definition: triSurfaceChecks.C:129
Foam::LongList< label >
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:59
Foam::triSurfFacets::removeFacetSubset
void removeFacetSubset(const label)
Definition: triSurfFacets.C:127
Foam::triSurfaceChecks::checkForHoles
label checkForHoles(const triSurf &surf, labelLongList &badTriangles)
check for existence of holes in the surface mesh
Definition: triSurfaceChecks.C:274
Foam::triSurfFacets::addFacetToSubset
void addFacetToSubset(const label, const label)
Definition: triSurfFacetsI.H:60
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::edgeFaces_
const VRWGraph & edgeFaces_
const reference to edge-faces addressing
Definition: triSurfaceChecks.C:521
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::help::groupMarking
label groupMarking(labelListType &elementInGroup, const neiOp &neighbourCalculator, const filterOp &selector)
Definition: helperFunctionsFrontalMarking.C:155
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::triSurfPoints::addPointToSubset
void addPointToSubset(const label, const label)
Definition: triSurfPointsI.H:57
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::faceEdges_
const VRWGraph & faceEdges_
const reference to face-edges addressing
Definition: triSurfaceChecks.C:518
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp
Definition: triSurfaceChecks.C:370
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::operator()
void operator()(const label tI, DynList< label > &neiTriangles) const
Definition: triSurfaceChecks.C:158
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::size
label size() const
Definition: triSurfaceChecks.C:153
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::surfaceNeiOp
surfaceNeiOp(const VRWGraph &faceEdges, const VRWGraph &edgeFaces)
Definition: triSurfaceChecks.C:528
Foam::VRWGraph::size
label size() const
Returns the number of rows.
Definition: VRWGraphI.H:122
Foam::meshOctreeCreator::createOctreeWithRefinedBoundary
void createOctreeWithRefinedBoundary(const direction maxLevel, const label nTrianglesInLeaf=15)
Definition: meshOctreeCreatorCreateOctreeBoxes.C:498
Foam::triSurfaceChecks::checkCollocatedPoints
label checkCollocatedPoints(const triSurf &surf, labelLongList &collocatedPoints, const scalar distTol)
check existence of collocated points
Definition: triSurfaceChecks.C:638
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::faceEdges_
const VRWGraph & faceEdges_
const reference to face-edges addressing
Definition: triSurfaceChecks.C:374
Foam::triSurfaceChecks::checkSelfIntersections
label checkSelfIntersections(const triSurf &surf, labelLongList &badFaces, const scalar tol)
check if there exist any self-intersections
Definition: triSurfaceChecks.C:727
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
Foam::triSurfFacets::addFacetSubset
label addFacetSubset(const word &)
point subsets
Definition: triSurfFacets.C:105
intersect
Raster intersect(const Raster &rast1, const Raster &rast2)
Definition: Raster.C:666
Foam::VRWGraph::sizeOfRow
label sizeOfRow(const label rowI) const
Returns the number of elements in the given row.
Definition: VRWGraphI.H:127
Foam::triSurfPoints::removePointSubset
void removePointSubset(const label)
Definition: triSurfPoints.C:76
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp
Definition: triSurfaceChecks.C:514
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::faceEdges_
const VRWGraph & faceEdges_
const reference to face-edges addressing
Definition: triSurfaceChecks.C:133
Foam::help::triLineIntersection
bool triLineIntersection(const triangle< point, point > &tria, const point &lineStart, const point &lineEnd, point &intersection)
check if a line intersects the triangle, and return the intersection
Definition: helperFunctionsGeometryQueriesI.H:653
Foam::triSurfaceChecks::checkSurfaceManifolds
label checkSurfaceManifolds(const triSurf &surf, labelLongList &triangleInManifold)
check for existence of boudary and non-manifold edges
Definition: triSurfaceChecks.C:225
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::edgeFaces_
const VRWGraph & edgeFaces_
const reference to edge-faces addressing
Definition: triSurfaceChecks.C:136
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::DynList< label >
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::operator()
void operator()(const label tI, DynList< label > &neiTriangles) const
Definition: triSurfaceChecks.C:543
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::size
label size() const
Definition: triSurfaceChecks.C:399
Foam::triSurfaceChecks::selectorOps::selectOp::selectOp
selectOp()
Definition: triSurfaceChecks.C:208
Foam::triSurfaceChecks::checkDisconnectedParts
label checkDisconnectedParts(const triSurf &surf, labelLongList &triangleInRegion)
check for disconnected surface parts
Definition: triSurfaceChecks.C:582
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
boundBox.H
Foam::triSurfaceChecks::connectionOps::surfaceNeiOp::size
label size() const
Definition: triSurfaceChecks.C:538
Foam::help::doTrianglesOverlap
bool doTrianglesOverlap(const triangle< point, point > &tri0, const triangle< point, point > &tri1, DynList< point > &overlappingPolygon, const scalar distTol=-1.0, const scalar cosTol=Foam::cos(5.0 *(M_PI/180.0)))
check the existence of overlap between the two triangles
Definition: helperFunctionsGeometryQueriesI.H:957
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::edgeFaces_
const VRWGraph & edgeFaces_
const reference to edge-faces addressing
Definition: triSurfaceChecks.C:377
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
helperFunctions.H
Foam::triSurfFacets::size
label size() const
return the number of triangles
Definition: triSurfFacetsI.H:39
Foam::triSurfPoints::pointSubsetIndex
label pointSubsetIndex(const word &) const
Definition: triSurfPoints.C:96
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::meshOctree
Definition: meshOctree.H:55
Foam::triSurfAddressing::facetEdges
const VRWGraph & facetEdges() const
return facet-edges addressing
Definition: triSurfAddressingI.H:79
Foam::intersection
Foam::intersection.
Definition: intersection.H:49
Foam::labelledTri
Triangle with additional region number.
Definition: labelledTri.H:49
Foam::triSurf::writeSurface
void writeSurface(const fileName &) const
Definition: triSurf.C:430
Foam::boundBox
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:55
Foam::triSurfaceChecks::checkAngles
label checkAngles(const triSurf &surf, labelLongList &badTriangles, const scalar angleTol)
Definition: triSurfaceChecks.C:58
Foam::triSurfFacets::facets
const LongList< labelledTri > & facets() const
access to facets
Definition: triSurfFacetsI.H:44
Foam::triSurfaceChecks::orientationOps::surfaceNeiOp::triangles_
const LongList< labelledTri > & triangles_
const reference to triangles
Definition: triSurfaceChecks.C:380
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::triSurfaceChecks::selectorOps::selectOp::operator()
bool operator()(const label) const
Definition: triSurfaceChecks.C:211
Foam::DynList::size
label size() const
Definition: DynListI.H:235
Foam::triSurfFacets::facetSubsetIndex
label facetSubsetIndex(const word &) const
Definition: triSurfFacets.C:147
meshOctreeCreator.H
Foam::triSurfaceChecks::checkOverlaps
label checkOverlaps(const triSurf &surf, labelLongList &badFaces, const scalar tol, const scalar angleTol)
check if there exist any overlaps
Definition: triSurfaceChecks.C:886
Foam::point
vector point
Point is a vector.
Definition: point.H:41
Foam::triSurfaceChecks::checkForNonManifoldEdges
label checkForNonManifoldEdges(const triSurf &surf, labelLongList &badTriangles)
check for existence of non-manifold edges
Definition: triSurfaceChecks.C:315
Foam::VRWGraph
Definition: VRWGraph.H:101
Foam::FixedList::rcIndex
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: FixedListI.H:122
Foam::triSurf
Definition: triSurf.H:59
Foam::triSurfaceChecks::manifoldOps::surfaceNeiOp::surfaceNeiOp
surfaceNeiOp(const VRWGraph &faceEdges, const VRWGraph &edgeFaces)
Definition: triSurfaceChecks.C:143
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::triSurfAddressing::edgeFacets
const VRWGraph & edgeFacets() const
return edge-facets addressing
Definition: triSurfAddressingI.H:97
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::DynList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: DynListI.H:279
Foam::DynList::append
void append(const T &e)
Append an element at the end of the list.
Definition: DynListI.H:304
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190