surfaceSplitNonManifolds.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  surfaceSplitNonManifolds
26 
27 Description
28  Takes multiply connected surface and tries to split surface at
29  multiply connected edges by duplicating points. Introduces concept of
30  - borderEdge. Edge with 4 faces connected to it.
31  - borderPoint. Point connected to exactly 2 borderEdges.
32  - borderLine. Connected list of borderEdges.
33 
34  By duplicating borderPoints this will split 'borderLines'. As a
35  preprocessing step it can detect borderEdges without any borderPoints
36  and explicitly split these triangles.
37 
38  The problems in this algorithm are:
39  - determining which two (of the four) faces form a surface. Done by walking
40  face-edge-face while keeping and edge or point on the borderEdge
41  borderPoint.
42  - determining the outwards pointing normal to be used to slightly offset the
43  duplicated point.
44 
45  Uses sortedEdgeFaces quite a bit.
46 
47  Is tested on simple borderLines resulting from extracting a surface
48  from a hex mesh. Will quite possibly go wrong on more complicated border
49  lines (i.e. ones forming a loop).
50 
51  Dumps surface every so often since might take a long time to complete.
52 
53 \*---------------------------------------------------------------------------*/
54 
55 #include "argList.H"
56 #include "triSurface.H"
57 #include "OFstream.H"
58 #include "ListOps.H"
59 #include "triSurfaceTools.H"
60 
61 using namespace Foam;
62 
63 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
64 
65 void writeOBJ(Ostream& os, const pointField& pts)
66 {
67  forAll(pts, i)
68  {
69  const point& pt = pts[i];
70 
71  os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
72  }
73 }
74 
75 
76 void dumpPoints(const triSurface& surf, const labelList& borderPoint)
77 {
78  fileName fName("borderPoints.obj");
79 
80  Info<< "Dumping borderPoints as Lightwave .obj file to " << fName
81  << "\nThis can be visualised with e.g. javaview (www.javaview.de)\n\n";
82 
83  OFstream os(fName);
84 
85  forAll(borderPoint, pointi)
86  {
87  if (borderPoint[pointi] != -1)
88  {
89  const point& pt = surf.localPoints()[pointi];
90 
91  os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
92  }
93  }
94 }
95 
96 
97 void dumpEdges(const triSurface& surf, const boolList& borderEdge)
98 {
99  fileName fName("borderEdges.obj");
100 
101  Info<< "Dumping borderEdges as Lightwave .obj file to " << fName
102  << "\nThis can be visualised with e.g. javaview (www.javaview.de)\n\n";
103 
104  OFstream os(fName);
105 
106  writeOBJ(os, surf.localPoints());
107 
108  forAll(borderEdge, edgeI)
109  {
110  if (borderEdge[edgeI])
111  {
112  const edge& e = surf.edges()[edgeI];
113 
114  os << "l " << e.start()+1 << ' ' << e.end()+1 << endl;
115  }
116  }
117 }
118 
119 
120 void dumpFaces
121 (
122  const fileName& fName,
123  const triSurface& surf,
124  const Map<label>& connectedFaces
125 )
126 {
127  Info<< "Dumping connectedFaces as Lightwave .obj file to " << fName
128  << "\nThis can be visualised with e.g. javaview (www.javaview.de)\n\n";
129 
130  OFstream os(fName);
131 
132  forAllConstIter(Map<label>, connectedFaces, iter)
133  {
134  point ctr = surf.localFaces()[iter.key()].centre(surf.localPoints());
135 
136  os << "v " << ctr.x() << ' ' << ctr.y() << ' ' << ctr.z() << endl;
137  }
138 }
139 
140 
141 void testSortedEdgeFaces(const triSurface& surf)
142 {
143  const labelListList& edgeFaces = surf.edgeFaces();
144  const labelListList& sortedEdgeFaces = surf.sortedEdgeFaces();
145 
146  forAll(edgeFaces, edgeI)
147  {
148  const labelList& myFaces = edgeFaces[edgeI];
149  const labelList& sortMyFaces = sortedEdgeFaces[edgeI];
150 
151  forAll(myFaces, i)
152  {
153  if (findIndex(sortMyFaces, myFaces[i]) == -1)
154  {
156  }
157  }
158  forAll(sortMyFaces, i)
159  {
160  if (findIndex(myFaces, sortMyFaces[i]) == -1)
161  {
163  }
164  }
165  }
166 }
167 
168 
169 // Mark off all border edges. Return number of border edges.
170 label markBorderEdges
171 (
172  const bool debug,
173  const triSurface& surf,
174  boolList& borderEdge
175 )
176 {
177  label nBorderEdges = 0;
178 
179  const labelListList& edgeFaces = surf.edgeFaces();
180 
181  forAll(edgeFaces, edgeI)
182  {
183  if (edgeFaces[edgeI].size() == 4)
184  {
185  borderEdge[edgeI] = true;
186 
187  nBorderEdges++;
188  }
189  }
190 
191  if (debug)
192  {
193  dumpEdges(surf, borderEdge);
194  }
195 
196  return nBorderEdges;
197 }
198 
199 
200 // Mark off all border points. Return number of border points. Border points
201 // marked by setting value to newly introduced point.
202 label markBorderPoints
203 (
204  const bool debug,
205  const triSurface& surf,
206  const boolList& borderEdge,
207  labelList& borderPoint
208 )
209 {
210  label nPoints = surf.nPoints();
211 
212  const labelListList& pointEdges = surf.pointEdges();
213 
214  forAll(pointEdges, pointi)
215  {
216  const labelList& pEdges = pointEdges[pointi];
217 
218  label nBorderEdges = 0;
219 
220  forAll(pEdges, i)
221  {
222  if (borderEdge[pEdges[i]])
223  {
224  nBorderEdges++;
225  }
226  }
227 
228  if (nBorderEdges == 2 && borderPoint[pointi] == -1)
229  {
230  borderPoint[pointi] = nPoints++;
231  }
232  }
233 
234  label nBorderPoints = nPoints - surf.nPoints();
235 
236  if (debug)
237  {
238  dumpPoints(surf, borderPoint);
239  }
240 
241  return nBorderPoints;
242 }
243 
244 
245 // Get minimum length of edges connected to pointi
246 // Serves to get some local length scale.
247 scalar minEdgeLen(const triSurface& surf, const label pointi)
248 {
249  const pointField& points = surf.localPoints();
250 
251  const labelList& pEdges = surf.pointEdges()[pointi];
252 
253  scalar minLen = great;
254 
255  forAll(pEdges, i)
256  {
257  label edgeI = pEdges[i];
258 
259  scalar len = surf.edges()[edgeI].mag(points);
260 
261  if (len < minLen)
262  {
263  minLen = len;
264  }
265  }
266  return minLen;
267 }
268 
269 
270 // Find edge among edgeLabels with endpoints v0,v1
272 (
273  const triSurface& surf,
274  const labelList& edgeLabels,
275  const label v0,
276  const label v1
277 )
278 {
279  forAll(edgeLabels, i)
280  {
281  label edgeI = edgeLabels[i];
282 
283  const edge& e = surf.edges()[edgeI];
284 
285  if
286  (
287  (
288  e.start() == v0
289  && e.end() == v1
290  )
291  || (
292  e.start() == v1
293  && e.end() == v0
294  )
295  )
296  {
297  return edgeI;
298  }
299  }
300 
301 
303  << ' ' << v1 << " in candidates " << edgeLabels
304  << " with vertices:" << UIndirectList<edge>(surf.edges(), edgeLabels)()
305  << abort(FatalError);
306 
307  return -1;
308 }
309 
310 
311 // Get the other edge connected to pointi on facei.
313 (
314  const triSurface& surf,
315  const label facei,
316  const label otherEdgeI,
317  const label pointi
318 )
319 {
320  const labelList& fEdges = surf.faceEdges()[facei];
321 
322  forAll(fEdges, i)
323  {
324  label edgeI = fEdges[i];
325 
326  const edge& e = surf.edges()[edgeI];
327 
328  if
329  (
330  edgeI != otherEdgeI
331  && (
332  e.start() == pointi
333  || e.end() == pointi
334  )
335  )
336  {
337  return edgeI;
338  }
339  }
340 
342  << " verts:" << surf.localPoints()[facei]
343  << " connected to point " << pointi
344  << " faceEdges:" << UIndirectList<edge>(surf.edges(), fEdges)()
345  << abort(FatalError);
346 
347  return -1;
348 }
349 
350 
351 // Starting from startPoint on startEdge on startFace walk along border
352 // and insert faces along the way. Walk keeps always one point or one edge
353 // on the border line.
354 void walkSplitLine
355 (
356  const triSurface& surf,
357  const boolList& borderEdge,
358  const labelList& borderPoint,
359 
360  const label startFacei,
361  const label startEdgeI, // is border edge
362  const label startPointi, // is border point
363 
364  Map<label>& faceToEdge,
366 )
367 {
368  label facei = startFacei;
369  label edgeI = startEdgeI;
370  label pointi = startPointi;
371 
372  do
373  {
374  //
375  // Stick to pointi and walk face-edge-face until back on border edge.
376  //
377 
378  do
379  {
380  // Cross face to next edge.
381  edgeI = otherEdge(surf, facei, edgeI, pointi);
382 
383  if (borderEdge[edgeI])
384  {
385  if (!faceToEdge.insert(facei, edgeI))
386  {
387  // Was already visited.
388  return;
389  }
390  else
391  {
392  // First visit to this borderEdge. We're back on borderline.
393  break;
394  }
395  }
396  else if (!faceToPoint.insert(facei, pointi))
397  {
398  // Was already visited.
399  return;
400  }
401 
402  // Cross edge to other face
403  const labelList& eFaces = surf.edgeFaces()[edgeI];
404 
405  if (eFaces.size() != 2)
406  {
408  << "Can only handle edges with 2 or 4 edges for now."
409  << abort(FatalError);
410  }
411 
412  if (eFaces[0] == facei)
413  {
414  facei = eFaces[1];
415  }
416  else if (eFaces[1] == facei)
417  {
418  facei = eFaces[0];
419  }
420  else
421  {
423  }
424  }
425  while (true);
426 
427 
428  //
429  // Back on border edge. Cross to other point on edge.
430  //
431 
432  pointi = surf.edges()[edgeI].otherVertex(pointi);
433 
434  if (borderPoint[pointi] == -1)
435  {
436  return;
437  }
438 
439  }
440  while (true);
441 }
442 
443 
444 // Find second face which is from same surface i.e. has points on the
445 // shared edge in reverse order.
446 label sharedFace
447 (
448  const triSurface& surf,
449  const label firstFacei,
450  const label sharedEdgeI
451 )
452 {
453  // Find ordering of face points in edge.
454 
455  const edge& e = surf.edges()[sharedEdgeI];
456 
457  const triSurface::FaceType& f = surf.localFaces()[firstFacei];
458 
459  label startIndex = findIndex(f, e.start());
460 
461  // points in face in same order as edge
462  bool edgeOrder = (f[f.fcIndex(startIndex)] == e.end());
463 
464  // Get faces using edge in sorted order. (sorted such that walking
465  // around them in anti-clockwise order corresponds to edge vector
466  // acc. to right-hand rule)
467  const labelList& eFaces = surf.sortedEdgeFaces()[sharedEdgeI];
468 
469  // Get position of face in sorted edge faces
470  label faceIndex = findIndex(eFaces, firstFacei);
471 
472  if (edgeOrder)
473  {
474  // Get face before firstFacei
475  return eFaces[eFaces.rcIndex(faceIndex)];
476  }
477  else
478  {
479  // Get face after firstFacei
480  return eFaces[eFaces.fcIndex(faceIndex)];
481  }
482 }
483 
484 
485 // Calculate (inward pointing) normals on edges shared by faces in
486 // faceToEdge and averages them to pointNormals.
487 void calcPointVecs
488 (
489  const triSurface& surf,
490  const Map<label>& faceToEdge,
491  const Map<label>& faceToPoint,
492  vectorField& borderPointVec
493 )
494 {
495  const labelListList& sortedEdgeFaces = surf.sortedEdgeFaces();
496  const edgeList& edges = surf.edges();
497  const pointField& points = surf.localPoints();
498 
499  boolList edgeDone(surf.nEdges(), false);
500 
501  forAllConstIter(Map<label>, faceToEdge, iter)
502  {
503  const label edgeI = iter();
504 
505  if (!edgeDone[edgeI])
506  {
507  edgeDone[edgeI] = true;
508 
509  // Get the two connected faces in sorted order
510  // Note: should have stored this when walking ...
511 
512  label face0I = -1;
513  label face1I = -1;
514 
515  const labelList& eFaces = sortedEdgeFaces[edgeI];
516 
517  forAll(eFaces, i)
518  {
519  label facei = eFaces[i];
520 
521  if (faceToEdge.found(facei))
522  {
523  if (face0I == -1)
524  {
525  face0I = facei;
526  }
527  else if (face1I == -1)
528  {
529  face1I = facei;
530 
531  break;
532  }
533  }
534  }
535 
536  if (face0I == -1 && face1I == -1)
537  {
538  Info<< "Writing surface to errorSurf.obj" << endl;
539 
540  surf.write("errorSurf.obj");
541 
543  << "Cannot find two faces using border edge " << edgeI
544  << " verts:" << edges[edgeI]
545  << " eFaces:" << eFaces << endl
546  << "face0I:" << face0I
547  << " face1I:" << face1I << nl
548  << "faceToEdge:" << faceToEdge << nl
549  << "faceToPoint:" << faceToPoint
550  << "Written surface to errorSurf.obj"
551  << abort(FatalError);
552  }
553 
554  // Now we have edge and the two faces in counter-clockwise order
555  // as seen from edge vector. Calculate normal.
556  const edge& e = edges[edgeI];
557  vector eVec = e.vec(points);
558 
559  // Determine vector as average of the vectors in the two faces.
560  // If there is only one face available use only one vector.
561  vector midVec(Zero);
562 
563  if (face0I != -1)
564  {
565  label v0 = triSurfaceTools::oppositeVertex(surf, face0I, edgeI);
566  vector e0 = (points[v0] - points[e.start()]) ^ eVec;
567  e0 /= mag(e0);
568  midVec = e0;
569  }
570 
571  if (face1I != -1)
572  {
573  label v1 = triSurfaceTools::oppositeVertex(surf, face1I, edgeI);
574  vector e1 = (points[e.start()] - points[v1]) ^ eVec;
575  e1 /= mag(e1);
576  midVec += e1;
577  }
578 
579  scalar magMidVec = mag(midVec);
580 
581  if (magMidVec > small)
582  {
583  midVec /= magMidVec;
584 
585  // Average to pointVec
586  borderPointVec[e.start()] += midVec;
587  borderPointVec[e.end()] += midVec;
588  }
589  }
590  }
591 }
592 
593 
594 // Renumbers vertices (of triangles in faceToEdge) of which the pointMap is
595 // not -1.
596 void renumberFaces
597 (
598  const triSurface& surf,
599  const labelList& pointMap,
600  const Map<label>& faceToEdge,
602 )
603 {
604  forAllConstIter(Map<label>, faceToEdge, iter)
605  {
606  const label facei = iter.key();
607  const triSurface::FaceType& f = surf.localFaces()[facei];
608 
609  forAll(f, fp)
610  {
611  if (pointMap[f[fp]] != -1)
612  {
613  newTris[facei][fp] = pointMap[f[fp]];
614  }
615  }
616  }
617 }
618 
619 
620 // Split all borderEdges that don't have borderPoint. Return true if split
621 // anything.
622 bool splitBorderEdges
623 (
624  triSurface& surf,
625  const boolList& borderEdge,
626  const labelList& borderPoint
627 )
628 {
629  labelList edgesToBeSplit(surf.nEdges());
630  label nSplit = 0;
631 
632  forAll(borderEdge, edgeI)
633  {
634  if (borderEdge[edgeI])
635  {
636  const edge& e = surf.edges()[edgeI];
637 
638  if (borderPoint[e.start()] == -1 && borderPoint[e.end()] == -1)
639  {
640  // None of the points of the edge is borderPoint. Split edge
641  // to introduce border point.
642  edgesToBeSplit[nSplit++] = edgeI;
643  }
644  }
645  }
646  edgesToBeSplit.setSize(nSplit);
647 
648  if (nSplit > 0)
649  {
650  Info<< "Splitting surface along " << nSplit << " borderEdges that don't"
651  << " neighbour other borderEdges" << nl << endl;
652 
653  surf = triSurfaceTools::greenRefine(surf, edgesToBeSplit);
654 
655  return true;
656  }
657  else
658  {
659  Info<< "No edges to be split" <<nl << endl;
660 
661  return false;
662  }
663 }
664 
665 
666 
667 int main(int argc, char *argv[])
668 {
669  #include "removeCaseOptions.H"
670 
672  (
673  "split multiply connected surface edges by duplicating points"
674  );
675  argList::validArgs.append("surface file");
676  argList::validArgs.append("output surface file");
678  (
679  "debug",
680  "add debugging output"
681  );
682 
683  argList args(argc, argv);
684 
685  const fileName inSurfName = args[1];
686  const fileName outSurfName = args[2];
687  const bool debug = args.optionFound("debug");
688 
689  Info<< "Reading surface from " << inSurfName << endl;
690 
691  triSurface surf(inSurfName);
692 
693  // Make sure sortedEdgeFaces is calculated correctly
694  testSortedEdgeFaces(surf);
695 
696  // Get all quad connected edges. These are seen as borders when walking.
697  boolList borderEdge(surf.nEdges(), false);
698  markBorderEdges(debug, surf, borderEdge);
699 
700  // Points on two sides connected to borderEdges are called
701  // borderPoints and will be duplicated. borderPoint contains label
702  // of newly introduced vertex.
703  labelList borderPoint(surf.nPoints(), -1);
704  markBorderPoints(debug, surf, borderEdge, borderPoint);
705 
706  // Split edges where there would be no borderPoint to duplicate.
707  splitBorderEdges(surf, borderEdge, borderPoint);
708 
709 
710  Info<< "Writing split surface to " << outSurfName << nl << endl;
711  surf.write(outSurfName);
712  Info<< "Finished writing surface to " << outSurfName << nl << endl;
713 
714 
715  // Last iteration values.
716  label nOldBorderEdges = -1;
717  label nOldBorderPoints = -1;
718 
719  label iteration = 0;
720 
721  do
722  {
723  // Redo borderEdge/borderPoint calculation.
724  boolList borderEdge(surf.nEdges(), false);
725 
726  label nBorderEdges = markBorderEdges(debug, surf, borderEdge);
727 
728  if (nBorderEdges == 0)
729  {
730  Info<< "Found no border edges. Exiting." << nl << nl;
731 
732  break;
733  }
734 
735  // Label of newly introduced duplicate.
736  labelList borderPoint(surf.nPoints(), -1);
737 
738  label nBorderPoints =
739  markBorderPoints
740  (
741  debug,
742  surf,
743  borderEdge,
744  borderPoint
745  );
746 
747  if (nBorderPoints == 0)
748  {
749  Info<< "Found no border points. Exiting." << nl << nl;
750 
751  break;
752  }
753 
754  Info<< "Found:\n"
755  << " border edges :" << nBorderEdges << nl
756  << " border points:" << nBorderPoints << nl
757  << endl;
758 
759  if
760  (
761  nBorderPoints == nOldBorderPoints
762  && nBorderEdges == nOldBorderEdges
763  )
764  {
765  Info<< "Stopping since number of border edges and point is same"
766  << " as in previous iteration" << nl << endl;
767 
768  break;
769  }
770 
771  //
772  // Define splitLine as a series of connected borderEdges. Find start
773  // of one (as edge and point on edge)
774  //
775 
776  label startEdgeI = -1;
777  label startPointi = -1;
778 
779  forAll(borderEdge, edgeI)
780  {
781  if (borderEdge[edgeI])
782  {
783  const edge& e = surf.edges()[edgeI];
784 
785  if ((borderPoint[e[0]] != -1) && (borderPoint[e[1]] == -1))
786  {
787  startEdgeI = edgeI;
788  startPointi = e[0];
789 
790  break;
791  }
792  else if ((borderPoint[e[0]] == -1) && (borderPoint[e[1]] != -1))
793  {
794  startEdgeI = edgeI;
795  startPointi = e[1];
796 
797  break;
798  }
799  }
800  }
801 
802  if (startEdgeI == -1)
803  {
804  Info<< "Cannot find starting point of splitLine\n" << endl;
805 
806  break;
807  }
808 
809  // Pick any face using edge to start from.
810  const labelList& eFaces = surf.edgeFaces()[startEdgeI];
811 
812  label firstFacei = eFaces[0];
813 
814  // Find second face which is from same surface i.e. has outwards
815  // pointing normal as well (actually bit more complex than this)
816  label secondFacei = sharedFace(surf, firstFacei, startEdgeI);
817 
818  Info<< "Starting local walk from:" << endl
819  << " edge :" << startEdgeI << endl
820  << " point:" << startPointi << endl
821  << " face0:" << firstFacei << endl
822  << " face1:" << secondFacei << endl
823  << endl;
824 
825  // From face on border edge to edge.
826  Map<label> faceToEdge(2*nBorderEdges);
827  // From face connected to border point (but not border edge) to point.
828  Map<label> faceToPoint(2*nBorderPoints);
829 
830  faceToEdge.insert(firstFacei, startEdgeI);
831 
832  walkSplitLine
833  (
834  surf,
835  borderEdge,
836  borderPoint,
837 
838  firstFacei,
839  startEdgeI,
840  startPointi,
841 
842  faceToEdge,
844  );
845 
846  faceToEdge.insert(secondFacei, startEdgeI);
847 
848  walkSplitLine
849  (
850  surf,
851  borderEdge,
852  borderPoint,
853 
854  secondFacei,
855  startEdgeI,
856  startPointi,
857 
858  faceToEdge,
860  );
861 
862  Info<< "Finished local walk and visited" << nl
863  << " border edges :" << faceToEdge.size() << nl
864  << " border points(but not edges):" << faceToPoint.size() << nl
865  << endl;
866 
867  if (debug)
868  {
869  dumpFaces("faceToEdge.obj", surf, faceToEdge);
870  dumpFaces("faceToPoint.obj", surf, faceToPoint);
871  }
872 
873  //
874  // Create coordinates for borderPoints by duplicating the existing
875  // point and then slightly shifting it inwards. To determine the
876  // inwards direction get the average normal of both connectedFaces on
877  // the edge and then interpolate this to the (border)point.
878  //
879 
880  vectorField borderPointVec(surf.nPoints(), vector(great, great, great));
881 
882  calcPointVecs(surf, faceToEdge, faceToPoint, borderPointVec);
883 
884 
885  // New position. Start off from copy of old points.
886  pointField newPoints(surf.localPoints());
887  newPoints.setSize(newPoints.size() + nBorderPoints);
888 
889  forAll(borderPoint, pointi)
890  {
891  label newPointi = borderPoint[pointi];
892 
893  if (newPointi != -1)
894  {
895  scalar minLen = minEdgeLen(surf, pointi);
896 
897  vector n = borderPointVec[pointi];
898  n /= mag(n);
899 
900  newPoints[newPointi] = newPoints[pointi] + 0.1 * minLen * n;
901  }
902  }
903 
904 
905  //
906  // Renumber all faces in connectedFaces
907  //
908 
909  // Start off from copy of faces.
910  List<labelledTri> newTris(surf.size());
911 
912  forAll(surf, facei)
913  {
914  newTris[facei] = surf.localFaces()[facei];
915  newTris[facei].region() = surf[facei].region();
916  }
917 
918  // Renumber all faces in faceToEdge
919  renumberFaces(surf, borderPoint, faceToEdge, newTris);
920  // Renumber all faces in faceToPoint
921  renumberFaces(surf, borderPoint, faceToPoint, newTris);
922 
923 
924  // Check if faces use unmoved points.
925  forAll(newTris, facei)
926  {
927  const triSurface::FaceType& f = newTris[facei];
928 
929  forAll(f, fp)
930  {
931  const point& pt = newPoints[f[fp]];
932 
933  if (mag(pt) >= great/2)
934  {
935  Info<< "newTri:" << facei << " verts:" << f
936  << " vert:" << f[fp] << " point:" << pt << endl;
937  }
938  }
939  }
940 
941 
942  surf = triSurface(newTris, surf.patches(), newPoints);
943 
944  if (debug || (iteration != 0 && (iteration % 20) == 0))
945  {
946  Info<< "Writing surface to " << outSurfName << nl << endl;
947 
948  surf.write(outSurfName);
949 
950  Info<< "Finished writing surface to " << outSurfName << nl << endl;
951  }
952 
953  // Save prev iteration values.
954  nOldBorderEdges = nBorderEdges;
955  nOldBorderPoints = nBorderPoints;
956 
957  iteration++;
958  }
959  while (true);
960 
961  Info<< "Writing final surface to " << outSurfName << nl << endl;
962 
963  surf.write(outSurfName);
964 
965  Info<< "End\n" << endl;
966 
967  return 0;
968 }
969 
970 
971 // ************************************************************************* //
Various functions to operate on Lists.
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:113
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
Output to file stream.
Definition: OFstream.H:86
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
label nEdges() const
Return number of edges in patch.
label nPoints() const
Return number of points supporting patch faces.
const labelListList & pointEdges() const
Return point-edge addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
std::remove_reference< ::Foam::List< labelledTri > >::type::value_type FaceType
const labelListList & edgeFaces() const
Return edge-face addressing.
const labelListList & faceEdges() const
Return face-edge addressing.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
A List with indirect addressing.
Definition: UIndirectList.H:60
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:159
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
A topoSetSource to select points based on usage in faces.
Definition: faceToPoint.H:52
A class for handling file names.
Definition: fileName.H:82
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:69
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:322
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
Definition: triSurface.C:714
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
int main(int argc, char *argv[])
Definition: financialFoam.C:44
const pointField & points
label nPoints
label findEdge(const edgeList &edges, const labelList &candidates, const label v0, const label v1)
Return edge among candidates that uses the two vertices.
Definition: meshTools.C:337
label otherEdge(const primitiveMesh &, const labelList &edgeLabels, const label edgeI, const label vertI)
Return label of other edge (out of candidates edgeLabels)
Definition: meshTools.C:501
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
Namespace for OpenFOAM.
static const zero Zero
Definition: zero.H:97
const doubleScalar e
Definition: doubleScalar.H:105
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
static const char nl
Definition: Ostream.H:260
label newPointi
Definition: readKivaGrid.H:495
labelList f(nPoints)
Foam::argList args(argc, argv)