Loading...
Searching...
No Matches
collapseBase.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "collapseBase.H"
30#include "triSurfaceTools.H"
31#include "argList.H"
32#include "OFstream.H"
33#include "SubList.H"
34#include "labelPair.H"
35#include "meshTools.H"
36#include "OSspecific.H"
37
38using namespace Foam;
39
40// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41
43//static void writeRegionOBJ
44//(
45// const triSurface& surf,
46// const label regionI,
47// const labelList& collapseRegion,
48// const labelList& outsideVerts
49//)
50//{
51// fileName dir("regions");
52//
53// mkDir(dir);
54// fileName regionName(dir / "region_" + name(regionI) + ".obj");
55//
56// Pout<< "Dumping region " << regionI << " to file " << regionName << endl;
57//
58// boolList include(surf.size(), false);
59//
60// forAll(collapseRegion, facei)
61// {
62// if (collapseRegion[facei] == regionI)
63// {
64// include[facei] = true;
65// }
66// }
67//
68// triSurface regionSurf(surf.subsetMesh(include));
69//
70// Pout<< "Region " << regionI << " surface:" << nl;
71// regionSurf.writeStats(Pout);
72//
73// regionSurf.write(regionName);
74//
75//
76// // Dump corresponding outside vertices.
77// fileName pointsName(dir / "regionPoints_" + name(regionI) + ".obj");
78//
79// Pout<< "Dumping region " << regionI << " points to file " << pointsName
80// << endl;
81//
82// OFstream str(pointsName);
83//
84// forAll(outsideVerts, i)
85// {
86// meshTools::writeOBJ(str, surf.localPoints()[outsideVerts[i]]);
87// }
88//}
89
90
91// Split triangle into multiple triangles because edge e being split
92// into multiple edges.
93static void splitTri
94(
95 const labelledTri& f,
96 const edge& e,
97 const labelList& splitPoints,
99)
100{
101 //label oldNTris = tris.size();
102
103 label fp = f.find(e[0]);
104 label fp1 = f.fcIndex(fp);
105 label fp2 = f.fcIndex(fp1);
106
107 if (f[fp1] == e[1])
108 {
109 // Split triangle along fp to fp1
110 tris.append(labelledTri(f[fp2], f[fp], splitPoints[0], f.region()));
111
112 for (label i = 1; i < splitPoints.size(); i++)
113 {
114 tris.append
115 (
117 (
118 f[fp2],
119 splitPoints[i-1],
120 splitPoints[i],
121 f.region()
122 )
123 );
124 }
125
126 tris.append
127 (
129 (
130 f[fp2],
131 splitPoints.last(),
132 f[fp1],
133 f.region()
134 )
135 );
136 }
137 else if (f[fp2] == e[1])
138 {
139 // Split triangle along fp2 to fp. (Reverse order of splitPoints)
140
141 tris.append
142 (
144 (
145 f[fp1],
146 f[fp2],
147 splitPoints.last(),
148 f.region()
149 )
150 );
151
152 for (label i = splitPoints.size()-1; i > 0; --i)
153 {
154 tris.append
155 (
157 (
158 f[fp1],
159 splitPoints[i],
160 splitPoints[i-1],
161 f.region()
162 )
163 );
164 }
165
166 tris.append
167 (
169 (
170 f[fp1],
171 splitPoints[0],
172 f[fp],
173 f.region()
174 )
175 );
176 }
177 else
178 {
180 << "Edge " << e << " not part of triangle " << f
181 << " fp:" << fp
182 << " fp1:" << fp1
183 << " fp2:" << fp2
184 << abort(FatalError);
185 }
186
187 //Pout<< "Split face " << f << " along edge " << e
188 // << " into triangles:" << endl;
189 //
190 //for (label i = oldNTris; i < tris.size(); i++)
191 //{
192 // Pout<< " " << tris[i] << nl;
193 //}
194}
195
196
197// Insert scalar into sortedVerts/sortedWeights so the weights are in
198// incrementing order.
199static bool insertSorted
200(
201 const label vertI,
202 const scalar weight,
203
204 labelList& sortedVerts,
205 scalarField& sortedWeights
206)
207{
208 if (sortedVerts.found(vertI))
209 {
211 << " which is already in list of sorted vertices "
212 << sortedVerts << abort(FatalError);
213 }
214
215 if (weight <= 0 || weight >= 1)
216 {
218 << " with illegal weight " << weight
219 << " into list of sorted vertices "
220 << sortedVerts << abort(FatalError);
221 }
222
223
224 label insertI = sortedVerts.size();
225
226 forAll(sortedVerts, sortedI)
227 {
228 scalar w = sortedWeights[sortedI];
229
230 if (mag(w - weight) < SMALL)
231 {
233 << "Trying to insert weight " << weight << " which is close to"
234 << " existing weight " << w << " in " << sortedWeights
235 << endl;
236 }
237
238 if (w > weight)
239 {
240 // Start inserting before sortedI.
241 insertI = sortedI;
242 break;
243 }
244 }
245
246
247 label sz = sortedWeights.size();
248
249 sortedWeights.setSize(sz + 1);
250 sortedVerts.setSize(sz + 1);
251
252 // Leave everything up to (not including) insertI intact.
253
254 // Make space by copying from insertI up.
255 for (label i = sz-1; i >= insertI; --i)
256 {
257 sortedWeights[i+1] = sortedWeights[i];
258 sortedVerts[i+1] = sortedVerts[i];
259 }
260 sortedWeights[insertI] = weight;
261 sortedVerts[insertI] = vertI;
262
263 return true;
264}
265
266
267// Is triangle candidate for collapse? Small height or small quality
268bool isSliver
269(
270 const triSurface& surf,
271 const scalar minLen,
272 const scalar minQuality,
273 const label facei,
274 const label edgeI
275)
276{
277 const pointField& localPoints = surf.localPoints();
278
279 // Check
280 // - opposite vertex projects onto base edge
281 // - normal distance is small
282 // - or triangle quality is small
283
284 label opposite0 =
286 (
287 surf,
288 facei,
289 edgeI
290 );
291
292 const edge& e = surf.edges()[edgeI];
293 const labelledTri& f = surf[facei];
294
295 pointHit pHit =
296 e.line(localPoints).nearestDist
297 (
298 localPoints[opposite0]
299 );
300
301 if
302 (
303 pHit.hit()
304 && (
305 pHit.distance() < minLen
306 || f.tri(surf.points()).quality() < minQuality
307 )
308 )
309 {
310 // Remove facei and split all other faces using this
311 // edge. This is done by 'replacing' the edgeI with the
312 // opposite0 vertex
313 //Pout<< "Splitting face " << facei << " since distance "
314 // << pHit.distance()
315 // << " from vertex " << opposite0
316 // << " to edge " << edgeI
317 // << " points "
318 // << localPoints[e[0]]
319 // << localPoints[e[1]]
320 // << " is too small or triangle quality "
321 // << f.tri(surf.points()).quality()
322 // << " too small." << endl;
323
324 return true;
325 }
326
327 return false;
328}
329
330
331// Mark all faces that are going to be collapsed.
332// faceToEdge: per face -1 or the base edge of the face.
333static void markCollapsedFaces
334(
335 const triSurface& surf,
336 const scalar minLen,
337 const scalar minQuality,
338 labelList& faceToEdge
339)
340{
341 faceToEdge.setSize(surf.size());
342 faceToEdge = -1;
343
344 const labelListList& edgeFaces = surf.edgeFaces();
345
346 forAll(edgeFaces, edgeI)
347 {
348 const labelList& eFaces = surf.edgeFaces()[edgeI];
349
350 forAll(eFaces, i)
351 {
352 label facei = eFaces[i];
353
354 bool isCandidate = isSliver(surf, minLen, minQuality, facei, edgeI);
355
356 if (isCandidate)
357 {
358 // Mark face as being collapsed
359 if (faceToEdge[facei] != -1)
360 {
362 << "Cannot collapse face " << facei << " since "
363 << " is marked to be collapsed both to edge "
364 << faceToEdge[facei] << " and " << edgeI
365 << abort(FatalError);
366 }
367
368 faceToEdge[facei] = edgeI;
369 }
370 }
371 }
372}
373
374
375// Recurse through collapsed faces marking all of them with regionI (in
376// collapseRegion)
377static void markRegion
378(
379 const triSurface& surf,
380 const labelList& faceToEdge,
381 const label regionI,
382 const label facei,
383 labelList& collapseRegion
384)
385{
386 if (faceToEdge[facei] == -1 || collapseRegion[facei] != -1)
387 {
389 << "Problem : crossed into uncollapsed/regionized face"
390 << abort(FatalError);
391 }
392
393 collapseRegion[facei] = regionI;
394
395 // Recurse across edges to collapsed neighbours
396
397 const labelList& fEdges = surf.faceEdges()[facei];
398
399 forAll(fEdges, fEdgeI)
400 {
401 label edgeI = fEdges[fEdgeI];
402
403 const labelList& eFaces = surf.edgeFaces()[edgeI];
404
405 forAll(eFaces, i)
406 {
407 label nbrFacei = eFaces[i];
408
409 if (faceToEdge[nbrFacei] != -1)
410 {
411 if (collapseRegion[nbrFacei] == -1)
412 {
413 markRegion
414 (
415 surf,
416 faceToEdge,
417 regionI,
418 nbrFacei,
419 collapseRegion
420 );
421 }
422 else if (collapseRegion[nbrFacei] != regionI)
423 {
425 << "Edge:" << edgeI << " between face " << facei
426 << " with region " << regionI
427 << " and face " << nbrFacei
428 << " with region " << collapseRegion[nbrFacei]
429 << endl;
430 }
431 }
432 }
433 }
434}
435
436
437// Mark every face with region (in collapseRegion) (or -1).
438// Return number of regions.
439static label markRegions
440(
441 const triSurface& surf,
442 const labelList& faceToEdge,
443 labelList& collapseRegion
444)
445{
446 label regionI = 0;
447
448 forAll(faceToEdge, facei)
449 {
450 if (collapseRegion[facei] == -1 && faceToEdge[facei] != -1)
451 {
452 //Pout<< "markRegions : Marking region:" << regionI
453 // << " starting from face " << facei << endl;
454
455 // Collapsed face. Mark connected region with current region number
456 markRegion(surf, faceToEdge, regionI++, facei, collapseRegion);
457 }
458 }
459 return regionI;
460}
461
462
463// Type of region.
464// -1 : edge inbetween uncollapsed faces.
465// -2 : edge inbetween collapsed faces
466// >=0 : edge inbetween uncollapsed and collapsed region. Returns region.
467static label edgeType
468(
469 const triSurface& surf,
470 const labelList& collapseRegion,
471 const label edgeI
472)
473{
474 const labelList& eFaces = surf.edgeFaces()[edgeI];
475
476 // Detect if edge is inbetween collapseRegion and non-collapse face
477 bool usesUncollapsed = false;
478 label usesRegion = -1;
479
480 forAll(eFaces, i)
481 {
482 label facei = eFaces[i];
483
484 label region = collapseRegion[facei];
485
486 if (region == -1)
487 {
488 usesUncollapsed = true;
489 }
490 else if (usesRegion == -1)
491 {
492 usesRegion = region;
493 }
494 else if (usesRegion != region)
495 {
497 }
498 else
499 {
500 // Equal regions.
501 }
502 }
503
504 if (usesUncollapsed)
505 {
506 if (usesRegion == -1)
507 {
508 // uncollapsed faces only.
509 return -1;
510 }
511 else
512 {
513 // between uncollapsed and collapsed.
514 return usesRegion;
515 }
516 }
517 else
518 {
519 if (usesRegion == -1)
520 {
522 return -2;
523 }
524 else
525 {
526 return -2;
527 }
528 }
529}
530
531
532// Get points on outside edge of region (= outside points)
533static labelListList getOutsideVerts
534(
535 const triSurface& surf,
536 const labelList& collapseRegion,
537 const label nRegions
538)
539{
540 const labelListList& edgeFaces = surf.edgeFaces();
541
542 // Per region all the outside vertices.
543 labelListList outsideVerts(nRegions);
544
545 forAll(edgeFaces, edgeI)
546 {
547 // Detect if edge is inbetween collapseRegion and non-collapse face
548 label regionI = edgeType(surf, collapseRegion, edgeI);
549
550 if (regionI >= 0)
551 {
552 // Edge borders both uncollapsed face and collapsed face on region
553 // usesRegion.
554
555 const edge& e = surf.edges()[edgeI];
556
557 labelList& regionVerts = outsideVerts[regionI];
558
559 // Add both edge points to regionVerts.
560 forAll(e, eI)
561 {
562 label v = e[eI];
563
564 if (!regionVerts.found(v))
565 {
566 label sz = regionVerts.size();
567 regionVerts.setSize(sz+1);
568 regionVerts[sz] = v;
569 }
570 }
571 }
572 }
573
574 return outsideVerts;
575}
576
577
578// n^2 search for furthest removed point pair.
579static labelPair getSpanPoints
580(
581 const triSurface& surf,
582 const labelList& outsideVerts
583)
584{
585 const pointField& localPoints = surf.localPoints();
586
587 scalar maxDist = -GREAT;
588 labelPair maxPair;
589
590 forAll(outsideVerts, i)
591 {
592 label v0 = outsideVerts[i];
593
594 for (label j = i+1; j < outsideVerts.size(); j++)
595 {
596 label v1 = outsideVerts[j];
597
598 scalar d = mag(localPoints[v0] - localPoints[v1]);
599
600 if (d > maxDist)
601 {
602 maxDist = d;
603 maxPair[0] = v0;
604 maxPair[1] = v1;
605 }
606 }
607 }
608
609 return maxPair;
610}
611
612
613// Project all non-span points onto the span edge.
614static void projectNonSpanPoints
615(
616 const triSurface& surf,
617 const labelList& outsideVerts,
618 const labelPair& spanPair,
619 labelList& sortedVertices,
620 scalarField& sortedWeights
621)
622{
623 const point& p0 = surf.localPoints()[spanPair[0]];
624 const point& p1 = surf.localPoints()[spanPair[1]];
625
626 forAll(outsideVerts, i)
627 {
628 label v = outsideVerts[i];
629
630 if (v != spanPair[0] && v != spanPair[1])
631 {
632 // Is a non-span point. Project onto spanning edge.
633
634 pointHit pHit =
635 linePointRef(p0, p1).nearestDist
636 (
637 surf.localPoints()[v]
638 );
639
640 if (!pHit.hit())
641 {
643 << abort(FatalError);
644 }
645
646 scalar w = pHit.point().dist(p0) / p1.dist(p0);
647
648 insertSorted(v, w, sortedVertices, sortedWeights);
649 }
650 }
651}
652
653
654// Slice part of the orderVertices (and optionally reverse) for this edge.
655static void getSplitVerts
656(
657 const triSurface& surf,
658 const label regionI,
659 const labelPair& spanPoints,
660 const labelList& orderedVerts,
661 const scalarField& orderedWeights,
662 const label edgeI,
663
664 labelList& splitVerts,
665 scalarField& splitWeights
666)
667{
668 const edge& e = surf.edges()[edgeI];
669 const label sz = orderedVerts.size();
670
671 if (e[0] == spanPoints[0])
672 {
673 // Edge in same order as spanPoints&orderedVerts. Keep order.
674
675 if (e[1] == spanPoints[1])
676 {
677 // Copy all.
678 splitVerts = orderedVerts;
679 splitWeights = orderedWeights;
680 }
681 else
682 {
683 // Copy upto (but not including) e[1]
684 label i1 = orderedVerts.find(e[1]);
685 splitVerts = SubList<label>(orderedVerts, i1, 0);
686 splitWeights = SubList<scalar>(orderedWeights, i1, 0);
687 }
688 }
689 else if (e[0] == spanPoints[1])
690 {
691 // Reverse.
692
693 if (e[1] == spanPoints[0])
694 {
695 // Copy all.
696 splitVerts = orderedVerts;
697 reverse(splitVerts);
698 splitWeights = orderedWeights;
699 reverse(splitWeights);
700 }
701 else
702 {
703 // Copy downto (but not including) e[1]
704
705 label i1 = orderedVerts.find(e[1]);
706 splitVerts = SubList<label>(orderedVerts, sz-(i1+1), i1+1);
707 reverse(splitVerts);
708 splitWeights = SubList<scalar>(orderedWeights, sz-(i1+1), i1+1);
709 reverse(splitWeights);
710 }
711 }
712 else if (e[1] == spanPoints[0])
713 {
714 // Reverse.
715
716 // Copy upto (but not including) e[0]
717
718 label i0 = orderedVerts.find(e[0]);
719 splitVerts = SubList<label>(orderedVerts, i0, 0);
720 reverse(splitVerts);
721 splitWeights = SubList<scalar>(orderedWeights, i0, 0);
722 reverse(splitWeights);
723 }
724 else if (e[1] == spanPoints[1])
725 {
726 // Copy from (but not including) e[0] to end
727
728 label i0 = orderedVerts.find(e[0]);
729 splitVerts = SubList<label>(orderedVerts, sz-(i0+1), i0+1);
730 splitWeights = SubList<scalar>(orderedWeights, sz-(i0+1), i0+1);
731 }
732 else
733 {
734 label i0 = orderedVerts.find(e[0]);
735 label i1 = orderedVerts.find(e[1]);
736
737 if (i0 == -1 || i1 == -1)
738 {
740 << "Did not find edge in projected vertices." << nl
741 << "region:" << regionI << nl
742 << "spanPoints:" << spanPoints
743 << " coords:" << surf.localPoints()[spanPoints[0]]
744 << surf.localPoints()[spanPoints[1]] << nl
745 << "edge:" << edgeI
746 << " verts:" << e
747 << " coords:" << surf.localPoints()[e[0]]
748 << surf.localPoints()[e[1]] << nl
749 << "orderedVerts:" << orderedVerts << nl
750 << abort(FatalError);
751 }
752
753 if (i0 < i1)
754 {
755 splitVerts = SubList<label>(orderedVerts, i1-i0-1, i0+1);
756 splitWeights = SubList<scalar>(orderedWeights, i1-i0-1, i0+1);
757 }
758 else
759 {
760 splitVerts = SubList<label>(orderedVerts, i0-i1-1, i1+1);
761 reverse(splitVerts);
762 splitWeights = SubList<scalar>(orderedWeights, i0-i1-1, i1+1);
763 reverse(splitWeights);
764 }
765 }
766}
767
768
769label collapseBase
770(
771 triSurface& surf,
772 const scalar minLen,
773 const scalar minQuality
774)
775{
776 label nTotalSplit = 0;
777
778 // label iter = 0;
779
780 while (true)
781 {
782 // Detect faces to collapse
783 // ~~~~~~~~~~~~~~~~~~~~~~~~
784
785 // -1 or edge the face is collapsed onto.
786 labelList faceToEdge(surf.size(), -1);
787
788 // Calculate faceToEdge (face collapses)
789 markCollapsedFaces(surf, minLen, minQuality, faceToEdge);
790
791
792 // Find regions of connected collapsed faces
793 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
794
795 // per face -1 or region
796 labelList collapseRegion(surf.size(), -1);
797
798 label nRegions = markRegions(surf, faceToEdge, collapseRegion);
799
800 //Pout<< "Detected " << nRegions << " regions of faces to be collapsed"
801 // << nl << endl;
802
803 // Pick up all vertices on outside of region
804 labelListList outsideVerts
805 (
806 getOutsideVerts(surf, collapseRegion, nRegions)
807 );
808
809 // For all regions determine maximum distance between points
810 List<labelPair> spanPoints(nRegions);
811 labelListList orderedVertices(nRegions);
812 List<scalarField> orderedWeights(nRegions);
813
814 forAll(spanPoints, regionI)
815 {
816 spanPoints[regionI] = getSpanPoints(surf, outsideVerts[regionI]);
817
818 //Pout<< "For region " << regionI << " found extrema at points "
819 // << surf.localPoints()[spanPoints[regionI][0]]
820 // << surf.localPoints()[spanPoints[regionI][1]]
821 // << endl;
822
823 // Project all non-span points onto the span edge.
824 projectNonSpanPoints
825 (
826 surf,
827 outsideVerts[regionI],
828 spanPoints[regionI],
829 orderedVertices[regionI],
830 orderedWeights[regionI]
831 );
832
833 //Pout<< "For region:" << regionI
834 // << " span:" << spanPoints[regionI]
835 // << " orderedVerts:" << orderedVertices[regionI]
836 // << " orderedWeights:" << orderedWeights[regionI]
837 // << endl;
838
839 //writeRegionOBJ
840 //(
841 // surf,
842 // regionI,
843 // collapseRegion,
844 // outsideVerts[regionI]
845 //);
846
847 //Pout<< endl;
848 }
849
850
851
852 // Actually split the edges
853 // ~~~~~~~~~~~~~~~~~~~~~~~~
854
855
856 const List<labelledTri>& localFaces = surf.localFaces();
857 const edgeList& edges = surf.edges();
858
859 label nSplit = 0;
860
861 // Storage for new triangles.
862 DynamicList<labelledTri> newTris(surf.size());
863
864 // Whether face has been dealt with (either copied/split or deleted)
865 boolList faceHandled(surf.size(), false);
866
867
868 forAll(edges, edgeI)
869 {
870 const edge& e = edges[edgeI];
871
872 // Detect if edge is inbetween collapseRegion and non-collapse face
873 label regionI = edgeType(surf, collapseRegion, edgeI);
874
875 if (regionI == -2)
876 {
877 // inbetween collapsed faces. nothing needs to be done.
878 }
879 else if (regionI == -1)
880 {
881 // edge inbetween uncollapsed faces. Handle these later on.
882 }
883 else
884 {
885 // some faces around edge are collapsed.
886
887 // Find additional set of points on edge to be used to split
888 // the remaining faces.
889
890 labelList splitVerts;
891 scalarField splitWeights;
892 getSplitVerts
893 (
894 surf,
895 regionI,
896 spanPoints[regionI],
897 orderedVertices[regionI],
898 orderedWeights[regionI],
899 edgeI,
900
901 splitVerts,
902 splitWeights
903 );
904
905 if (splitVerts.size())
906 {
907 // Split edge using splitVerts. All non-collapsed triangles
908 // using edge will get split.
909
910 //{
911 // const pointField& localPoints = surf.localPoints();
912 // Pout<< "edge " << edgeI << ' ' << e
913 // << " points "
914 // << localPoints[e[0]] << ' ' << localPoints[e[1]]
915 // << " split into edges with extra points:"
916 // << endl;
917 // forAll(splitVerts, i)
918 // {
919 // Pout<< " " << splitVerts[i] << " weight "
920 // << splitWeights[i] << nl;
921 // }
922 //}
923
924 const labelList& eFaces = surf.edgeFaces()[edgeI];
925
926 forAll(eFaces, i)
927 {
928 label facei = eFaces[i];
929
930 if (!faceHandled[facei] && faceToEdge[facei] == -1)
931 {
932 // Split face to use vertices.
933 splitTri
934 (
935 localFaces[facei],
936 e,
937 splitVerts,
938 newTris
939 );
940
941 faceHandled[facei] = true;
942
943 nSplit++;
944 }
945 }
946 }
947 }
948 }
949
950 // Copy all unsplit faces
951 forAll(faceHandled, facei)
952 {
953 if (!faceHandled[facei] && faceToEdge[facei] == -1)
954 {
955 newTris.append(localFaces[facei]);
956 }
957 }
958
959 Info<< "collapseBase : collapsing " << nSplit
960 << " triangles by splitting their base edge."
961 << endl;
962
963 nTotalSplit += nSplit;
964
965 if (nSplit == 0)
966 {
967 break;
968 }
969
970 // Pack the triangles
971 newTris.shrink();
972
973 //Pout<< "Resetting surface from " << surf.size() << " to "
974 // << newTris.size() << " triangles" << endl;
975 surf = triSurface(newTris, surf.patches(), surf.localPoints());
976
977 //{
978 // fileName fName("bla" + name(iter) + ".obj");
979 // Pout<< "Writing surf to " << fName << endl;
980 // surf.write(fName);
981 //}
982
983 // ++iter;
984 }
985
986 // Remove any unused vertices
987 surf = triSurface(surf.localFaces(), surf.patches(), surf.localPoints());
988
989 return nTotalSplit;
990}
991
992
993// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
void setSize(label n)
Alias for resize().
Definition List.H:536
scalar distance() const noexcept
Return distance to hit.
Definition pointHit.H:169
bool hit() const noexcept
Is there a hit.
Definition pointHit.H:145
const point_type & point() const noexcept
Return the point, no checks.
Definition pointHit.H:161
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
const Field< point_type > & points() const noexcept
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
const labelListList & faceEdges() const
Return face-edge addressing.
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
bool found(const T &val, label pos=0) const
Same as contains().
Definition UList.H:983
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
T & last()
Access last element of the list, position [size()-1].
Definition UList.H:971
label find(const T &val) const
Find index of the first occurrence of the value.
Definition UList.C:160
scalar dist(const Vector< Cmpt > &v2) const
The L2-norm distance from another vector. The mag() of the difference.
Definition VectorI.H:107
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Definition edge.H:62
A triFace with additional (region) index.
Definition labelledTri.H:56
static label oppositeVertex(const triSurface &surf, const label facei, const label edgeI)
Get vertex (local numbering) opposite edge.
Triangulated surface description with patch information.
Definition triSurface.H:74
const geometricSurfacePatchList & patches() const noexcept
Definition triSurface.H:509
Routines collapse sliver triangles by splitting the base edge.
label collapseBase(triSurface &surf, const scalar minLen, const scalar minQuality)
Keep collapsing all triangles whose height is < minLen or quality < minQ.
const volScalarField & p0
Definition EEqn.H:36
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
List< edge > edgeList
List of edge.
Definition edgeList.H:32
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
PointHit< point > pointHit
A PointHit with a 3D point.
Definition pointHit.H:51
List< label > labelList
A List of labels.
Definition List.H:62
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
Definition UListI.H:539
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
line< point, const point & > linePointRef
A line using referred points.
Definition line.H:66
errorManip< error > abort(error &err)
Definition errorManip.H:139
vector point
Point is a vector.
Definition point.H:37
List< bool > boolList
A List of bools.
Definition List.H:60
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
volScalarField & e
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299