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