surfaceSplitNonManifolds.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 | Copyright (C) 2011-2016 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 visualized 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 visualized 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 visualized 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 minumum 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,
365  Map<label>& faceToPoint
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 {
670  (
671  "split multiply connected surface edges by duplicating points"
672  );
674  argList::validArgs.append("surfaceFile");
675  argList::validArgs.append("output surfaceFile");
677  (
678  "debug",
679  "add debugging output"
680  );
681 
682  argList args(argc, argv);
683 
684  const fileName inSurfName = args[1];
685  const fileName outSurfName = args[2];
686  const bool debug = args.optionFound("debug");
687 
688  Info<< "Reading surface from " << inSurfName << endl;
689 
690  triSurface surf(inSurfName);
691 
692  // Make sure sortedEdgeFaces is calculated correctly
693  testSortedEdgeFaces(surf);
694 
695  // Get all quad connected edges. These are seen as borders when walking.
696  boolList borderEdge(surf.nEdges(), false);
697  markBorderEdges(debug, surf, borderEdge);
698 
699  // Points on two sides connected to borderEdges are called
700  // borderPoints and will be duplicated. borderPoint contains label
701  // of newly introduced vertex.
702  labelList borderPoint(surf.nPoints(), -1);
703  markBorderPoints(debug, surf, borderEdge, borderPoint);
704 
705  // Split edges where there would be no borderPoint to duplicate.
706  splitBorderEdges(surf, borderEdge, borderPoint);
707 
708 
709  Info<< "Writing split surface to " << outSurfName << nl << endl;
710  surf.write(outSurfName);
711  Info<< "Finished writing surface to " << outSurfName << nl << endl;
712 
713 
714  // Last iteration values.
715  label nOldBorderEdges = -1;
716  label nOldBorderPoints = -1;
717 
718  label iteration = 0;
719 
720  do
721  {
722  // Redo borderEdge/borderPoint calculation.
723  boolList borderEdge(surf.nEdges(), false);
724 
725  label nBorderEdges = markBorderEdges(debug, surf, borderEdge);
726 
727  if (nBorderEdges == 0)
728  {
729  Info<< "Found no border edges. Exiting." << nl << nl;
730 
731  break;
732  }
733 
734  // Label of newly introduced duplicate.
735  labelList borderPoint(surf.nPoints(), -1);
736 
737  label nBorderPoints =
738  markBorderPoints
739  (
740  debug,
741  surf,
742  borderEdge,
743  borderPoint
744  );
745 
746  if (nBorderPoints == 0)
747  {
748  Info<< "Found no border points. Exiting." << nl << nl;
749 
750  break;
751  }
752 
753  Info<< "Found:\n"
754  << " border edges :" << nBorderEdges << nl
755  << " border points:" << nBorderPoints << nl
756  << endl;
757 
758  if
759  (
760  nBorderPoints == nOldBorderPoints
761  && nBorderEdges == nOldBorderEdges
762  )
763  {
764  Info<< "Stopping since number of border edges and point is same"
765  << " as in previous iteration" << nl << endl;
766 
767  break;
768  }
769 
770  //
771  // Define splitLine as a series of connected borderEdges. Find start
772  // of one (as edge and point on edge)
773  //
774 
775  label startEdgeI = -1;
776  label startPointi = -1;
777 
778  forAll(borderEdge, edgeI)
779  {
780  if (borderEdge[edgeI])
781  {
782  const edge& e = surf.edges()[edgeI];
783 
784  if ((borderPoint[e[0]] != -1) && (borderPoint[e[1]] == -1))
785  {
786  startEdgeI = edgeI;
787  startPointi = e[0];
788 
789  break;
790  }
791  else if ((borderPoint[e[0]] == -1) && (borderPoint[e[1]] != -1))
792  {
793  startEdgeI = edgeI;
794  startPointi = e[1];
795 
796  break;
797  }
798  }
799  }
800 
801  if (startEdgeI == -1)
802  {
803  Info<< "Cannot find starting point of splitLine\n" << endl;
804 
805  break;
806  }
807 
808  // Pick any face using edge to start from.
809  const labelList& eFaces = surf.edgeFaces()[startEdgeI];
810 
811  label firstFacei = eFaces[0];
812 
813  // Find second face which is from same surface i.e. has outwards
814  // pointing normal as well (actually bit more complex than this)
815  label secondFacei = sharedFace(surf, firstFacei, startEdgeI);
816 
817  Info<< "Starting local walk from:" << endl
818  << " edge :" << startEdgeI << endl
819  << " point:" << startPointi << endl
820  << " face0:" << firstFacei << endl
821  << " face1:" << secondFacei << endl
822  << endl;
823 
824  // From face on border edge to edge.
825  Map<label> faceToEdge(2*nBorderEdges);
826  // From face connected to border point (but not border edge) to point.
827  Map<label> faceToPoint(2*nBorderPoints);
828 
829  faceToEdge.insert(firstFacei, startEdgeI);
830 
831  walkSplitLine
832  (
833  surf,
834  borderEdge,
835  borderPoint,
836 
837  firstFacei,
838  startEdgeI,
839  startPointi,
840 
841  faceToEdge,
842  faceToPoint
843  );
844 
845  faceToEdge.insert(secondFacei, startEdgeI);
846 
847  walkSplitLine
848  (
849  surf,
850  borderEdge,
851  borderPoint,
852 
853  secondFacei,
854  startEdgeI,
855  startPointi,
856 
857  faceToEdge,
858  faceToPoint
859  );
860 
861  Info<< "Finished local walk and visited" << nl
862  << " border edges :" << faceToEdge.size() << nl
863  << " border points(but not edges):" << faceToPoint.size() << nl
864  << endl;
865 
866  if (debug)
867  {
868  dumpFaces("faceToEdge.obj", surf, faceToEdge);
869  dumpFaces("faceToPoint.obj", surf, faceToPoint);
870  }
871 
872  //
873  // Create coordinates for borderPoints by duplicating the existing
874  // point and then slightly shifting it inwards. To determine the
875  // inwards direction get the average normal of both connectedFaces on
876  // the edge and then interpolate this to the (border)point.
877  //
878 
879  vectorField borderPointVec(surf.nPoints(), vector(GREAT, GREAT, GREAT));
880 
881  calcPointVecs(surf, faceToEdge, faceToPoint, borderPointVec);
882 
883 
884  // New position. Start off from copy of old points.
885  pointField newPoints(surf.localPoints());
886  newPoints.setSize(newPoints.size() + nBorderPoints);
887 
888  forAll(borderPoint, pointi)
889  {
890  label newPointi = borderPoint[pointi];
891 
892  if (newPointi != -1)
893  {
894  scalar minLen = minEdgeLen(surf, pointi);
895 
896  vector n = borderPointVec[pointi];
897  n /= mag(n);
898 
899  newPoints[newPointi] = newPoints[pointi] + 0.1 * minLen * n;
900  }
901  }
902 
903 
904  //
905  // Renumber all faces in connectedFaces
906  //
907 
908  // Start off from copy of faces.
909  List<labelledTri> newTris(surf.size());
910 
911  forAll(surf, facei)
912  {
913  newTris[facei] = surf.localFaces()[facei];
914  newTris[facei].region() = surf[facei].region();
915  }
916 
917  // Renumber all faces in faceToEdge
918  renumberFaces(surf, borderPoint, faceToEdge, newTris);
919  // Renumber all faces in faceToPoint
920  renumberFaces(surf, borderPoint, faceToPoint, newTris);
921 
922 
923  // Check if faces use unmoved points.
924  forAll(newTris, facei)
925  {
926  const triSurface::FaceType& f = newTris[facei];
927 
928  forAll(f, fp)
929  {
930  const point& pt = newPoints[f[fp]];
931 
932  if (mag(pt) >= GREAT/2)
933  {
934  Info<< "newTri:" << facei << " verts:" << f
935  << " vert:" << f[fp] << " point:" << pt << endl;
936  }
937  }
938  }
939 
940 
941  surf = triSurface(newTris, surf.patches(), newPoints);
942 
943  if (debug || (iteration != 0 && (iteration % 20) == 0))
944  {
945  Info<< "Writing surface to " << outSurfName << nl << endl;
946 
947  surf.write(outSurfName);
948 
949  Info<< "Finished writing surface to " << outSurfName << nl << endl;
950  }
951 
952  // Save prev iteration values.
953  nOldBorderEdges = nBorderEdges;
954  nOldBorderPoints = nBorderPoints;
955 
956  iteration++;
957  }
958  while (true);
959 
960  Info<< "Writing final surface to " << outSurfName << nl << endl;
961 
962  surf.write(outSurfName);
963 
964  Info<< "End\n" << endl;
965 
966  return 0;
967 }
968 
969 
970 // ************************************************************************* //
label end() const
Return end vertex label.
Definition: edgeI.H:92
label nPoints() const
Return number of points supporting patch faces.
const Cmpt & z() const
Definition: VectorI.H:87
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
A class for handling file names.
Definition: fileName.H:69
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
const Cmpt & x() const
Definition: VectorI.H:75
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Output to file stream.
Definition: OFstream.H:81
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static void noParallel()
Remove the parallel options.
Definition: argList.C:146
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:154
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
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
Definition: triSurface.C:766
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
const labelListList & pointEdges() const
Return point-edge addressing.
Various functions to operate on Lists.
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
static label oppositeVertex(const triSurface &surf, const label facei, const label edgeI)
Get vertex (local numbering) opposite edge.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:314
const labelListList & faceEdges() const
Return face-edge addressing.
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:102
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Cmpt & y() const
Definition: VectorI.H:81
static const zero Zero
Definition: zero.H:91
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
errorManip< error > abort(error &err)
Definition: errorManip.H:131
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
label start() const
Return start vertex label.
Definition: edgeI.H:81
static const char nl
Definition: Ostream.H:262
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label nEdges() const
Return number of edges in patch.
void setSize(const label)
Reset size of List.
Definition: List.C:295
label newPointi
Definition: readKivaGrid.H:501
A List with indirect addressing.
Definition: fvMatrix.H:106
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:157
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
label n
const labelListList & edgeFaces() const
Return edge-face addressing.
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:83
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:124
Triangulated surface description with patch information.
Definition: triSurface.H:65
Foam::argList args(argc, argv)
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Namespace for OpenFOAM.