triSurface.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | foam-extend: Open Source CFD
4  \\ / O peration | Version: 3.2
5  \\ / A nd | Web: http://www.foam-extend.org
6  \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9  This file is part of foam-extend.
10 
11  foam-extend is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation, either version 3 of the License, or (at your
14  option) any later version.
15 
16  foam-extend is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triSurface.H"
27 #include "demandDrivenData.H"
28 #include "IFstream.H"
29 #include "OFstream.H"
30 #include "objectRegistry.H"
31 #include "foamTime.H"
32 #include "boundBox.H"
33 #include "SortableList.H"
34 #include "PackedBoolList.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
39 
40 
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 
44 {
45  fileName foamName(d.caseName() + ".ftr");
46 
47  // Search back through the time directories list to find the time
48  // closest to and lower than current time
49 
50  instantList ts = d.times();
51  label i;
52 
53  for (i = ts.size() - 1; i >= 0; i--)
54  {
55  if (ts[i].value() <= d.timeOutputValue())
56  {
57  break;
58  }
59  }
60 
61  // Noting that the current directory has already been searched
62  // for mesh data, start searching from the previously stored time directory
63 
64  if (i >= 0)
65  {
66  for (label j = i; j >= 0; j--)
67  {
68  if (isFile(d.path()/ts[j].name()/typeName/foamName))
69  {
70  if (debug)
71  {
72  Pout<< " triSurface::triSurfInstance(const Time& d)"
73  << "reading " << foamName
74  << " from " << ts[j].name()/typeName
75  << endl;
76  }
77 
78  return ts[j].name();
79  }
80  }
81  }
82 
83  if (debug)
84  {
85  Pout<< " triSurface::triSurfInstance(const Time& d)"
86  << "reading " << foamName
87  << " from constant/" << endl;
88  }
89 
90  return d.constant();
91 }
92 
93 
95 (
96  const faceList& faces,
97  const label defaultRegion
98 )
99 {
100  List<labelledTri> triFaces(faces.size());
101 
102  forAll (triFaces, faceI)
103  {
104  const face& f = faces[faceI];
105 
106  if (f.size() != 3)
107  {
109  (
110  "triSurface::convertToTri"
111  "(const faceList&, const label)"
112  ) << "Face at position " << faceI
113  << " does not have three vertices:" << f
114  << abort(FatalError);
115  }
116 
117  labelledTri& tri = triFaces[faceI];
118 
119  tri[0] = f[0];
120  tri[1] = f[1];
121  tri[2] = f[2];
122  tri.region() = defaultRegion;
123  }
124 
125  return triFaces;
126 }
127 
128 
130 (
131  const triFaceList& faces,
132  const label defaultRegion
133 )
134 {
135  List<labelledTri> triFaces(faces.size());
136 
137  forAll (triFaces, faceI)
138  {
139  const triFace& f = faces[faceI];
140 
141  labelledTri& tri = triFaces[faceI];
142 
143  tri[0] = f[0];
144  tri[1] = f[1];
145  tri[2] = f[2];
146  tri.region() = defaultRegion;
147  }
148 
149  return triFaces;
150 }
151 
152 
153 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
154 
156 (
157  Ostream& os,
158  const string& pre,
159  const labelledTri& f,
160  const pointField& points
161 )
162 {
163  os << pre.c_str() << "vertex numbers:"
164  << f[0] << ' ' << f[1] << ' ' << f[2] << endl
165  << pre.c_str() << "vertex coords :"
166  << points[f[0]] << ' ' << points[f[1]] << ' ' << points[f[2]]
167  << pre.c_str() << "region :" << f.region() << endl
168  << endl;
169 }
170 
171 
173 {
174  string line;
175  do
176  {
177  is.getLine(line);
178  }
179  while ((line.empty() || line[0] == '#') && is.good());
180 
181  return line;
182 }
183 
184 
185 // Remove non-triangles, double triangles.
186 void Foam::triSurface::checkTriangles(const bool verbose)
187 {
188  // Simple check on indices ok.
189  const label maxPointI = points().size() - 1;
190 
191  forAll (*this, faceI)
192  {
193  const labelledTri& f = (*this)[faceI];
194 
195  if
196  (
197  (f[0] < 0) || (f[0] > maxPointI)
198  || (f[1] < 0) || (f[1] > maxPointI)
199  || (f[2] < 0) || (f[2] > maxPointI)
200  )
201  {
202  FatalErrorIn("triSurface::checkTriangles(bool)")
203  << "triangle " << f
204  << " uses point indices outside point range 0.."
205  << maxPointI
206  << exit(FatalError);
207  }
208  }
209 
210  // Two phase process
211  // 1. mark invalid faces
212  // 2. pack
213  // Done to keep numbering constant in phase 1
214 
215  // List of valid triangles
216  boolList valid(size(), true);
217  bool hasInvalid = false;
218 
219  const labelListList& fFaces = faceFaces();
220 
221  forAll (*this, faceI)
222  {
223  const labelledTri& f = (*this)[faceI];
224 
225  if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
226  {
227  // 'degenerate' triangle check
228  valid[faceI] = false;
229  hasInvalid = true;
230 
231  if (verbose)
232  {
233  WarningIn
234  (
235  "triSurface::checkTriangles(bool verbose)"
236  ) << "triangle " << faceI
237  << " does not have three unique vertices:\n";
238  printTriangle(Warning, " ", f, points());
239  }
240  }
241  else
242  {
243  // Duplicate triangle check
244  const labelList& neighbours = fFaces[faceI];
245 
246  // Check if faceNeighbours use same points as this face.
247  // Note: discards normal information - sides of baffle are merged.
248  forAll (neighbours, neighbourI)
249  {
250  if (neighbours[neighbourI] <= faceI)
251  {
252  // lower numbered faces already checked
253  continue;
254  }
255 
256  const labelledTri& n = (*this)[neighbours[neighbourI]];
257 
258  if
259  (
260  ((f[0] == n[0]) || (f[0] == n[1]) || (f[0] == n[2]))
261  && ((f[1] == n[0]) || (f[1] == n[1]) || (f[1] == n[2]))
262  && ((f[2] == n[0]) || (f[2] == n[1]) || (f[2] == n[2]))
263  )
264  {
265  valid[faceI] = false;
266  hasInvalid = true;
267 
268  if (verbose)
269  {
270  WarningIn
271  (
272  "triSurface::checkTriangles(bool verbose)"
273  ) << "triangles share the same vertices:\n"
274  << " face 1 :" << faceI << endl;
275  printTriangle(Warning, " ", f, points());
276 
277  Warning
278  << endl
279  << " face 2 :"
280  << neighbours[neighbourI] << endl;
281  printTriangle(Warning, " ", n, points());
282  }
283 
284  break;
285  }
286  }
287  }
288  }
289 
290  if (hasInvalid)
291  {
292  // Pack
293  label newFaceI = 0;
294  forAll (*this, faceI)
295  {
296  if (valid[faceI])
297  {
298  const labelledTri& f = (*this)[faceI];
299  (*this)[newFaceI++] = f;
300  }
301  }
302 
303  if (verbose)
304  {
305  WarningIn
306  (
307  "triSurface::checkTriangles(bool verbose)"
308  ) << "Removing " << size() - newFaceI
309  << " illegal faces." << endl;
310  }
311  (*this).setSize(newFaceI);
312 
313  // Topology can change because of renumbering
314  clearOut();
315  }
316 }
317 
318 
319 // Check/fix edges with more than two triangles
320 void Foam::triSurface::checkEdges(const bool verbose)
321 {
322  const labelListList& eFaces = edgeFaces();
323 
324  forAll (eFaces, edgeI)
325  {
326  const labelList& myFaces = eFaces[edgeI];
327 
328  if (myFaces.empty())
329  {
330  FatalErrorIn("triSurface::checkEdges(bool verbose)")
331  << "Edge " << edgeI << " with vertices " << edges()[edgeI]
332  << " has no edgeFaces"
333  << exit(FatalError);
334  }
335  else if (myFaces.size() > 2)
336  {
337  WarningIn
338  (
339  "triSurface::checkEdges(bool verbose)"
340  ) << "Edge " << edgeI << " with vertices " << edges()[edgeI]
341  << " has more than 2 faces connected to it : " << myFaces
342  << endl;
343  }
344  }
345 }
346 
347 
348 // Read triangles, points from Istream
350 {
351  is >> patches_ >> storedPoints() >> storedFaces();
352 
353  return true;
354 }
355 
356 
357 // Read from file in given format
359 (
360  const fileName& name,
361  const word& ext,
362  const bool check
363 )
364 {
365  if (check && !exists(name))
366  {
368  (
369  "triSurface::read(const fileName&, const word&, const bool)"
370  ) << "Cannnot read " << name << exit(FatalError);
371  }
372 
373  if (ext == "gz")
374  {
375  fileName unzipName = name.lessExt();
376 
377  // Do not check for existence. Let IFstream do the unzipping.
378  return read(unzipName, unzipName.ext(), false);
379  }
380  else if (ext == "ftr")
381  {
382  return read(IFstream(name)());
383  }
384  else if (ext == "stl")
385  {
386  return readSTL(name);
387  }
388  else if (ext == "stlb")
389  {
390  return readSTL(name);
391  }
392  else if (ext == "gts")
393  {
394  return readGTS(name);
395  }
396  else if (ext == "obj")
397  {
398  return readOBJ(name);
399  }
400  else if (ext == "off")
401  {
402  return readOFF(name);
403  }
404  else if (ext == "tri")
405  {
406  return readTRI(name);
407  }
408  else if (ext == "ac")
409  {
410  return readAC(name);
411  }
412  else if (ext == "nas")
413  {
414  return readNAS(name);
415  }
416  else
417  {
419  (
420  "triSurface::read(const fileName&, const word&)"
421  ) << "unknown file extension " << ext
422  << ". Supported extensions are '.ftr', '.stl', '.stlb', '.gts'"
423  << ", '.obj', '.ac', '.off', '.nas' and '.tri'"
424  << exit(FatalError);
425 
426  return false;
427  }
428 }
429 
430 
431 // Write to file in given format
433 (
434  const fileName& name,
435  const word& ext,
436  const bool sort
437 ) const
438 {
439  if (ext == "ftr")
440  {
441  return write(OFstream(name)());
442  }
443  else if (ext == "stl")
444  {
445  return writeSTLASCII(OFstream(name)());
446  }
447  else if (ext == "stlb")
448  {
449  ofstream outFile(name.c_str(), std::ios::binary);
450 
451  writeSTLBINARY(outFile);
452  }
453  else if (ext == "gts")
454  {
455  return writeGTS(sort, OFstream(name)());
456  }
457  else if (ext == "obj")
458  {
459  writeOBJ(sort, OFstream(name)());
460  }
461  else if (ext == "off")
462  {
463  writeOFF(sort, OFstream(name)());
464  }
465  else if (ext == "vtk")
466  {
467  writeVTK(sort, OFstream(name)());
468  }
469  else if (ext == "tri")
470  {
471  writeTRI(sort, OFstream(name)());
472  }
473  else if (ext == "dx")
474  {
475  writeDX(sort, OFstream(name)());
476  }
477  else if (ext == "ac")
478  {
479  writeAC(OFstream(name)());
480  }
481  else if (ext == "smesh")
482  {
483  writeSMESH(sort, OFstream(name)());
484  }
485  else
486  {
488  (
489  "triSurface::write(const fileName&, const word&, const bool)"
490  ) << "unknown file extension " << ext
491  << ". Supported extensions are '.ftr', '.stl', '.stlb', "
492  << "'.gts', '.obj', '.vtk'"
493  << ", '.off', '.dx', '.smesh', '.ac' and '.tri'"
494  << exit(FatalError);
495  }
496 }
497 
498 
499 // Returns patch info. Sets faceMap to the indexing according to patch
500 // numbers. Patch numbers start at 0.
502 {
503  // Sort according to region numbers of labelledTri
504  SortableList<label> sortedRegion(size());
505 
506  forAll (sortedRegion, faceI)
507  {
508  sortedRegion[faceI] = operator[](faceI).region();
509  }
510  sortedRegion.sort();
511 
512  faceMap = sortedRegion.indices();
513 
514  // Extend regions
515  label maxRegion = patches_.size()-1; // for non-compacted regions
516 
517  if (faceMap.size())
518  {
519  maxRegion = max
520  (
521  maxRegion,
522  operator[](faceMap[faceMap.size() - 1]).region()
523  );
524  }
525 
526  // Get new region list
527  surfacePatchList newPatches(maxRegion + 1);
528 
529  // Fill patch sizes
530  forAll (*this, faceI)
531  {
532  label region = operator[](faceI).region();
533 
534  newPatches[region].size()++;
535  }
536 
537 
538  // Fill rest of patch info
539 
540  label startFaceI = 0;
541  forAll (newPatches, newPatchI)
542  {
543  surfacePatch& newPatch = newPatches[newPatchI];
544 
545  newPatch.index() = newPatchI;
546 
547  label oldPatchI = newPatchI;
548 
549  // start of patch
550  newPatch.start() = startFaceI;
551 
552 
553  // Take over any information from existing patches
554  if
555  (
556  (oldPatchI < patches_.size())
557  && (patches_[oldPatchI].name() != "")
558  )
559  {
560  newPatch.name() = patches_[oldPatchI].name();
561  }
562  else
563  {
564  newPatch.name() = word("patch") + name(newPatchI);
565  }
566 
567  if
568  (
569  (oldPatchI < patches_.size())
570  && (patches_[oldPatchI].geometricType() != "")
571  )
572  {
573  newPatch.geometricType() = patches_[oldPatchI].geometricType();
574  }
575  else
576  {
577  newPatch.geometricType() = "empty";
578  }
579 
580  startFaceI += newPatch.size();
581  }
582 
583  return newPatches;
584 }
585 
586 
588 {
590 
591  // Get names, types and sizes
592  surfacePatchList newPatches(calcPatches(faceMap));
593 
594  // Take over names and types (but not size)
595  patches_.setSize(newPatches.size());
596 
597  forAll (newPatches, patchI)
598  {
599  patches_[patchI].index() = patchI;
600  patches_[patchI].name() = newPatches[patchI].name();
601  patches_[patchI].geometricType() = newPatches[patchI].geometricType();
602  }
603 }
604 
605 
606 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
607 
609 :
611  patches_(0),
612  sortedEdgeFacesPtr_(NULL),
613  edgeOwnerPtr_(NULL)
614 {}
615 
616 
617 
619 (
620  const List<labelledTri>& triangles,
622  const pointField& points
623 )
624 :
625  ParentType(triangles, points),
626  patches_(patches),
627  sortedEdgeFacesPtr_(NULL),
628  edgeOwnerPtr_(NULL)
629 {}
630 
631 
633 (
634  List<labelledTri>& triangles,
637  const bool reUse
638 )
639 :
640  ParentType(triangles, points, reUse),
641  patches_(patches),
642  sortedEdgeFacesPtr_(NULL),
643  edgeOwnerPtr_(NULL)
644 {}
645 
646 
648 (
649  const List<labelledTri>& triangles,
650  const pointField& points
651 )
652 :
653  ParentType(triangles, points),
654  patches_(),
655  sortedEdgeFacesPtr_(NULL),
656  edgeOwnerPtr_(NULL)
657 {
658  setDefaultPatches();
659 }
660 
661 
663 (
664  const triFaceList& triangles,
665  const pointField& points
666 )
667 :
668  ParentType(convertToTri(triangles, 0), points),
669  patches_(),
670  sortedEdgeFacesPtr_(NULL),
671  edgeOwnerPtr_(NULL)
672 {
673  setDefaultPatches();
674 }
675 
676 
678 :
680  patches_(),
681  sortedEdgeFacesPtr_(NULL),
682  edgeOwnerPtr_(NULL)
683 {
684  word ext = name.ext();
685 
686  read(name, ext);
687 
689 }
690 
691 
693 :
695  patches_(),
696  sortedEdgeFacesPtr_(NULL),
697  edgeOwnerPtr_(NULL)
698 {
699  read(is);
700 
702 }
703 
704 
706 :
708  patches_(),
709  sortedEdgeFacesPtr_(NULL),
710  edgeOwnerPtr_(NULL)
711 {
712  fileName foamFile(d.caseName() + ".ftr");
713 
714  fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
715 
716  IFstream foamStream(foamPath);
717 
718  read(foamStream);
719 
721 }
722 
723 
725 :
726  ParentType(ts, ts.points()),
727  patches_(ts.patches()),
728  sortedEdgeFacesPtr_(NULL),
729  edgeOwnerPtr_(NULL)
730 {}
731 
732 
733 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
734 
736 {
737  clearOut();
738 }
739 
740 
741 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
742 
744 {
745  ParentType::clearTopology();
746  deleteDemandDrivenData(sortedEdgeFacesPtr_);
747  deleteDemandDrivenData(edgeOwnerPtr_);
748 }
749 
750 
752 {
753  ParentType::clearPatchMeshAddr();
754 }
755 
756 
758 {
759  ParentType::clearOut();
760 
761  clearTopology();
762  clearPatchMeshAddr();
763 }
764 
765 
767 {
768  if (!sortedEdgeFacesPtr_)
769  {
770  calcSortedEdgeFaces();
771  }
772 
773  return *sortedEdgeFacesPtr_;
774 }
775 
776 
778 {
779  if (!edgeOwnerPtr_)
780  {
781  calcEdgeOwner();
782  }
783 
784  return *edgeOwnerPtr_;
785 }
786 
787 
788 //- Move points
790 {
791  // Remove all geometry dependent data
792  deleteDemandDrivenData(sortedEdgeFacesPtr_);
793 
794  // Adapt for new point position
795  ParentType::movePoints(newPoints);
796 
797  // Copy new points
798  storedPoints() = newPoints;
799 }
800 
801 
802 // scale points
803 void Foam::triSurface::scalePoints(const scalar& scaleFactor)
804 {
805  // avoid bad scaling
806  if (scaleFactor > 0 && scaleFactor != 1.0)
807  {
808  // Remove all geometry dependent data
809  clearTopology();
810 
811  // Adapt for new point position
812  ParentType::movePoints(pointField());
813 
814  storedPoints() *= scaleFactor;
815  }
816 }
817 
818 
819 // Remove non-triangles, double triangles.
820 void Foam::triSurface::cleanup(const bool verbose)
821 {
822  // Merge points (already done for STL, TRI)
823  stitchTriangles(points(), SMALL, verbose);
824 
825  // Merging points might have changed geometric factors
826  clearOut();
827 
828  checkTriangles(verbose);
829 
830  checkEdges(verbose);
831 }
832 
833 
834 // Finds area, starting at faceI, delimited by borderEdge. Marks all visited
835 // faces (from face-edge-face walk) with currentZone.
837 (
838  const boolList& borderEdge,
839  const label faceI,
840  const label currentZone,
842 ) const
843 {
844  // List of faces whose faceZone has been set.
845  labelList changedFaces(1, faceI);
846 
847  while(true)
848  {
849  // Pick up neighbours of changedFaces
850  dynamicLabelList newChangedFaces(2*changedFaces.size());
851 
852  forAll (changedFaces, i)
853  {
854  label faceI = changedFaces[i];
855 
856  const labelList& fEdges = faceEdges()[faceI];
857 
858  forAll (fEdges, i)
859  {
860  label edgeI = fEdges[i];
861 
862  if (!borderEdge[edgeI])
863  {
864  const labelList& eFaces = edgeFaces()[edgeI];
865 
866  forAll (eFaces, j)
867  {
868  label nbrFaceI = eFaces[j];
869 
870  if (faceZone[nbrFaceI] == -1)
871  {
872  faceZone[nbrFaceI] = currentZone;
873  newChangedFaces.append(nbrFaceI);
874  }
875  else if (faceZone[nbrFaceI] != currentZone)
876  {
878  (
879  "triSurface::markZone(const boolList&,"
880  "const label, const label, labelList&) const"
881  )
882  << "Zones " << faceZone[nbrFaceI]
883  << " at face " << nbrFaceI
884  << " connects to zone " << currentZone
885  << " at face " << faceI
886  << abort(FatalError);
887  }
888  }
889  }
890  }
891  }
892 
893  if (newChangedFaces.empty())
894  {
895  break;
896  }
897 
898  changedFaces.transfer(newChangedFaces);
899  }
900 }
901 
902 
903 // Finds areas delimited by borderEdge (or 'real' edges).
904 // Fills faceZone accordingly
906 (
907  const boolList& borderEdge,
909 ) const
910 {
911  faceZone.setSize(size());
912  faceZone = -1;
913 
914  if (borderEdge.size() != nEdges())
915  {
917  (
918  "triSurface::markZones"
919  "(const boolList&, labelList&)"
920  )
921  << "borderEdge boolList not same size as number of edges" << endl
922  << "borderEdge:" << borderEdge.size() << endl
923  << "nEdges :" << nEdges()
924  << exit(FatalError);
925  }
926 
927  label zoneI = 0;
928 
929  for (label startFaceI = 0;; zoneI++)
930  {
931  // Find first non-coloured face
932  for (; startFaceI < size(); startFaceI++)
933  {
934  if (faceZone[startFaceI] == -1)
935  {
936  break;
937  }
938  }
939 
940  if (startFaceI >= size())
941  {
942  break;
943  }
944 
945  faceZone[startFaceI] = zoneI;
946 
947  markZone(borderEdge, startFaceI, zoneI, faceZone);
948  }
949 
950  return zoneI;
951 }
952 
953 
955 (
956  const boolList& include,
957  labelList& pointMap,
959 ) const
960 {
961  const List<labelledTri>& locFaces = localFaces();
962 
963  label faceI = 0;
964  label pointI = 0;
965 
966  faceMap.setSize(locFaces.size());
967 
968  pointMap.setSize(nPoints());
969 
970  boolList pointHad(nPoints(), false);
971 
972  forAll (include, oldFacei)
973  {
974  if (include[oldFacei])
975  {
976  // Store new faces compact
977  faceMap[faceI++] = oldFacei;
978 
979  // Renumber labels for triangle
980  const labelledTri& tri = locFaces[oldFacei];
981 
982  label a = tri[0];
983  if (!pointHad[a])
984  {
985  pointHad[a] = true;
986  pointMap[pointI++] = a;
987  }
988 
989  label b = tri[1];
990  if (!pointHad[b])
991  {
992  pointHad[b] = true;
993  pointMap[pointI++] = b;
994  }
995 
996  label c = tri[2];
997  if (!pointHad[c])
998  {
999  pointHad[c] = true;
1000  pointMap[pointI++] = c;
1001  }
1002  }
1003  }
1004 
1005  // Trim
1006  faceMap.setSize(faceI);
1007 
1008  pointMap.setSize(pointI);
1009 }
1010 
1011 
1014  const boolList& include,
1015  labelList& pointMap,
1017 ) const
1018 {
1019  const pointField& locPoints = localPoints();
1020  const List<labelledTri>& locFaces = localFaces();
1021 
1022  // Fill pointMap, faceMap
1023  subsetMeshMap(include, pointMap, faceMap);
1024 
1025 
1026  // Create compact coordinate list and forward mapping array
1027  pointField newPoints(pointMap.size());
1028  labelList oldToNew(locPoints.size());
1029  forAll (pointMap, pointi)
1030  {
1031  newPoints[pointi] = locPoints[pointMap[pointi]];
1032  oldToNew[pointMap[pointi]] = pointi;
1033  }
1034 
1035  // Renumber triangle node labels and compact
1036  List<labelledTri> newTriangles(faceMap.size());
1037 
1038  forAll (faceMap, facei)
1039  {
1040  // Get old vertex labels
1041  const labelledTri& tri = locFaces[faceMap[facei]];
1042 
1043  newTriangles[facei][0] = oldToNew[tri[0]];
1044  newTriangles[facei][1] = oldToNew[tri[1]];
1045  newTriangles[facei][2] = oldToNew[tri[2]];
1046  newTriangles[facei].region() = tri.region();
1047  }
1048 
1049  // Construct subsurface
1050  return triSurface(newTriangles, patches(), newPoints, true);
1051 }
1052 
1053 
1056  const fileName& name,
1057  const bool sortByRegion
1058 ) const
1059 {
1060  write(name, name.ext(), sortByRegion);
1061 }
1062 
1063 
1065 {
1066  os << patches() << endl;
1067 
1068  //Note: Write with global point numbering
1069  os << points() << nl
1070  << static_cast<const List<labelledTri>&>(*this) << endl;
1071 
1072  // Check state of Ostream
1073  os.check("triSurface::write(Ostream&)");
1074 }
1075 
1076 
1077 void Foam::triSurface::write(const Time& d) const
1078 {
1079  fileName foamFile(d.caseName() + ".ftr");
1080 
1081  fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
1082 
1083  OFstream foamStream(foamPath);
1084 
1085  write(foamStream);
1086 }
1087 
1088 
1090 {
1091  // Unfortunately nPoints constructs meshPoints() so do compact version
1092  // ourselves.
1093  PackedBoolList pointIsUsed(points().size());
1094 
1095  label nPoints = 0;
1097 
1098  forAll (*this, triI)
1099  {
1100  const labelledTri& f = operator[](triI);
1101 
1102  forAll (f, fp)
1103  {
1104  label pointI = f[fp];
1105  if (pointIsUsed.set(pointI, 1))
1106  {
1107  bb.min() = ::Foam::min(bb.min(), points()[pointI]);
1108  bb.max() = ::Foam::max(bb.max(), points()[pointI]);
1109  nPoints++;
1110  }
1111  }
1112  }
1113 
1114  os << "Triangles : " << size() << endl
1115  << "Vertices : " << nPoints << endl
1116  << "Bounding Box : " << bb << endl;
1117 }
1118 
1119 
1120 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1121 
1123 {
1125  clearOut();
1126  storedPoints() = ts.points();
1127  patches_ = ts.patches();
1128 }
1129 
1130 
1131 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1132 
1134 {
1135  sm.write(os);
1136  return os;
1137 }
1138 
1139 
1140 // ************************************************************************* //
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Foam::TimeState::timeOutputValue
scalar timeOutputValue() const
Return current time value.
Definition: TimeState.C:67
Foam::geometricSurfacePatch::index
label index() const
Return the index of this patch in the boundaryMesh.
Definition: geometricSurfacePatch.H:125
Foam::triSurface::convertToTri
static List< labelledTri > convertToTri(const faceList &, const label defaultRegion=0)
Convert faces to labelledTri. All get same region.
Definition: triSurface.C:95
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
Foam::triSurface::subsetMeshMap
void subsetMeshMap(const boolList &include, labelList &pointMap, labelList &faceMap) const
'Create' sub mesh, including only faces for which
Definition: triSurface.C:955
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:90
Foam::surfacePatch::size
label size() const
Return size of this patch in the polyMesh face list.
Definition: surfacePatch.H:114
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::triSurface::clearOut
void clearOut()
Clear all data.
Definition: triSurface.C:757
Foam::triSurface::writeStats
void writeStats(Ostream &) const
Write some statistics.
Definition: triSurface.C:1089
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::exists
bool exists(const fileName &, const bool checkGzip=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:608
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
Foam::triSurface::checkTriangles
void checkTriangles(const bool verbose=false)
Check/remove duplicate/degenerate triangles.
Definition: triSurface.C:186
Foam::SortableList::sort
void sort()
(stable) sort the list (if changed after construction time)
Definition: SortableList.C:95
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
foamTime.H
Foam::Time::caseName
const fileName & caseName() const
Return case name.
Definition: Time.H:275
Foam::IFstream
Input from file stream.
Definition: IFstream.H:81
Foam::triSurface::read
bool read(Istream &)
Read in Foam format.
Definition: triSurface.C:349
Foam::Time::times
instantList times() const
Search the case for valid time directories.
Definition: Time.C:758
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::read
bool read(const char *, int32_t &)
Definition: int32IO.C:87
Foam::boundBox::invertedBox
static const boundBox invertedBox
A very large inverted boundBox: min/max == +/- VGREAT.
Definition: boundBox.H:79
Foam::PackedBoolList::set
void set(const PackedList< 1 > &)
Set specified bits.
Definition: PackedBoolList.C:169
Foam::Warning
messageStream Warning
objectRegistry.H
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
defineTypeNameAndDebug
defineTypeNameAndDebug(Foam::triSurface, 0)
Foam::surfacePatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: surfacePatch.H:102
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:74
Foam::triSurface::clearPatchMeshAddr
void clearPatchMeshAddr()
Clear patch addressing.
Definition: triSurface.C:751
Foam::triSurface::patches
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:301
Foam::List::operator=
void operator=(const UList< T > &)
Assignment from UList operator. Takes linear time.
Foam::triSurface::~triSurface
~triSurface()
Definition: triSurface.C:735
Foam::writeVTK
void writeVTK(OFstream &os, const Type &value)
OFstream.H
Foam::triSurface::movePoints
virtual void movePoints(const pointField &)
Move points.
Definition: triSurface.C:789
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:40
n
label n
Definition: TABSMDCalcMethod2.H:31
SortableList.H
Foam::triSurface::cleanup
void cleanup(const bool verbose=false)
Remove non-valid triangles.
Definition: triSurface.C:820
Foam::triSurface::subsetMesh
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
Definition: triSurface.C:1013
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::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::geometricSurfacePatch::geometricType
const word & geometricType() const
Return the type of the patch.
Definition: geometricSurfacePatch.H:113
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:57
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:57
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::ISstream::getLine
ISstream & getLine(string &)
Raw, low-level getline into a string function.
Definition: ISstreamI.H:77
PackedBoolList.H
Foam::triSurface::markZone
void markZone(const boolList &borderEdge, const label faceI, const label currentZone, labelList &faceZone) const
Fill faceZone with currentZone for every face reachable.
Definition: triSurface.C:837
Foam::triSurface::operator=
void operator=(const triSurface &)
Definition: triSurface.C:1122
Foam::triSurface::triSurface
triSurface()
Construct null.
Definition: triSurface.C:608
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
IFstream.H
Foam::operator<<
Ostream & operator<<(Ostream &, const edgeMesh &)
Definition: edgeMeshIO.C:130
Foam::IOstream::check
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:92
Foam::FatalError
error FatalError
Foam::SortableList
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: List.H:65
Foam::triSurface::clearTopology
void clearTopology()
Clear topology.
Definition: triSurface.C:743
Foam::fileName::ext
word ext() const
Return file name extension (part after last .)
Definition: fileName.C:329
Foam::surfacePatch
'Patch' on surface as subset of triSurface.
Definition: surfacePatch.H:51
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::isFile
bool isFile(const fileName &, const bool checkGzip=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:622
Foam::triSurface::edgeOwner
const labelList & edgeOwner() const
If 2 face neighbours: label of face where ordering of edge.
Definition: triSurface.C:777
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::triSurface::calcPatches
surfacePatchList calcPatches(labelList &faceMap) const
Sort faces according to region. Returns patch list.
Definition: triSurface.C:501
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::triSurface::setDefaultPatches
void setDefaultPatches()
Sets default values for patches.
Definition: triSurface.C:587
boundBox.H
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::triSurface::markZones
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
Definition: triSurface.C:906
Foam::triSurface::checkEdges
void checkEdges(const bool verbose=false)
Check triply (or more) connected edges.
Definition: triSurface.C:320
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:281
Foam::triSurface::scalePoints
virtual void scalePoints(const scalar &)
Scale points. A non-positive factor is ignored.
Definition: triSurface.C:803
Foam::triFace
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:68
Foam::labelledTri::region
label region() const
Return region label.
Definition: labelledTriI.H:68
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
f
labelList f(nPoints)
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePaths.H:130
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::line
A line primitive.
Definition: line.H:56
Foam::SortableList::indices
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
Definition: SortableList.H:90
Foam::labelledTri
Triangle with additional region number.
Definition: labelledTri.H:49
Foam::boundBox
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:55
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
patches
patches[0]
Definition: createSingleCellMesh.H:36
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
WarningIn
#define WarningIn(functionName)
Report a warning using Foam::Warning.
Definition: messageStream.H:254
Foam::triSurface::sortedEdgeFaces
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
Definition: triSurface.C:766
Foam::sort
void sort(UList< T > &)
Definition: UList.C:107
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::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
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
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
triSurface.H
Foam::geometricSurfacePatch::name
const word & name() const
Return name.
Definition: geometricSurfacePatch.H:101
Foam::triSurface::getLineNoComment
static string getLineNoComment(IFstream &)
Read non-comment line.
Definition: triSurface.C:172
write
Tcoeff write()
Foam::triSurface::triSurfInstance
static fileName triSurfInstance(const Time &)
Name of triSurface directory to use.
Definition: triSurface.C:43
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::triSurface::printTriangle
static void printTriangle(Ostream &, const Foam::string &pre, const labelledTri &, const pointField &)
Helper function to print triangle info.
Definition: triSurface.C:156
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88