MeshedSurface.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "MeshedSurface.H"
30 #include "UnsortedMeshedSurface.H"
31 #include "MeshedSurfaceProxy.H"
32 #include "mergePoints.H"
33 #include "Time.H"
34 #include "ListOps.H"
35 #include "polyBoundaryMesh.H"
36 #include "polyMesh.H"
37 #include "surfMesh.H"
38 #include "primitivePatch.H"
39 #include "faceTraits.H"
41 
42 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
43 
44 template<class Face>
46 {
47  return wordHashSet(*fileExtensionConstructorTablePtr_);
48 }
49 
50 
51 template<class Face>
53 {
54  return wordHashSet(*writefileExtensionMemberFunctionTablePtr_);
55 }
56 
57 
58 template<class Face>
60 (
61  const word& fileType,
62  bool verbose
63 )
64 {
65  return fileFormats::surfaceFormatsCore::checkSupport
66  (
67  readTypes() | FriendType::readTypes(),
68  fileType,
69  verbose,
70  "reading"
71  );
72 }
73 
74 
75 template<class Face>
77 (
78  const word& fileType,
79  bool verbose
80 )
81 {
82  return fileFormats::surfaceFormatsCore::checkSupport
83  (
84  writeTypes() | ProxyType::writeTypes(),
85  fileType,
86  verbose,
87  "writing"
88  );
89 }
90 
91 
92 template<class Face>
94 (
95  const fileName& name,
96  bool verbose
97 )
98 {
99  word ext(name.ext());
100  if (ext == "gz")
101  {
102  ext = name.lessExt().ext();
103  }
104  return canReadType(ext, verbose);
105 }
106 
107 
108 template<class Face>
110 (
111  const fileName& name,
112  const MeshedSurface<Face>& surf,
113  IOstreamOption streamOpt,
114  const dictionary& options
115 )
116 {
117  write(name, name.ext(), surf, streamOpt, options);
118 }
119 
120 
121 template<class Face>
123 (
124  const fileName& name,
125  const word& fileType,
126  const MeshedSurface<Face>& surf,
127  IOstreamOption streamOpt,
128  const dictionary& options
129 )
130 {
131  if (fileType.empty())
132  {
133  // Handle empty/missing type
134 
135  const word ext(name.ext());
136 
137  if (ext.empty())
138  {
140  << "Cannot determine format from filename" << nl
141  << " " << name << nl
142  << exit(FatalError);
143  }
144 
145  write(name, ext, surf, streamOpt, options);
146  return;
147  }
148 
149 
150  DebugInFunction << "Writing to " << name << nl;
151 
152  auto* mfuncPtr = writefileExtensionMemberFunctionTable(fileType);
153 
154  if (!mfuncPtr)
155  {
156  // Delegate to proxy if possible
157  const wordHashSet delegate(ProxyType::writeTypes());
158 
159  if (!delegate.found(fileType))
160  {
162  << "Unknown write format " << fileType << nl << nl
163  << "Valid types:" << nl
164  << flatOutput((delegate | writeTypes()).sortedToc()) << nl
165  << exit(FatalError);
166  }
167 
169  (
170  name, fileType, streamOpt, options
171  );
172  }
173  else
174  {
175  mfuncPtr(name, surf, streamOpt, options);
176  }
177 }
178 
179 
180 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
181 
182 template<class Face>
184 :
185  MeshReference(List<Face>(), pointField()),
186  faceIds_(),
187  zones_()
188 {}
189 
190 
191 template<class Face>
193 (
194  const MeshedSurface<Face>& surf
195 )
196 :
197  MeshReference(surf.surfFaces(), surf.points()),
198  faceIds_(surf.faceIds_),
199  zones_(surf.zones_)
200 {}
201 
202 
203 template<class Face>
205 (
206  const UnsortedMeshedSurface<Face>& surf
207 )
208 :
209  MeshReference(List<Face>(), surf.points()), // Copy points only
210  faceIds_(),
211  zones_()
212 {
214  this->storedZones() = surf.sortedZones(faceMap);
215 
216  // Faces, in the sorted order
217  const List<Face>& origFaces = surf;
218  {
219  List<Face> newFaces(origFaces.size());
220 
221  forAll(newFaces, facei)
222  {
223  newFaces[faceMap[facei]] = origFaces[facei];
224  }
225 
226  this->storedFaces().transfer(newFaces);
227  }
228 
229  // FaceIds, in the sorted order
230  const labelList& origIds = surf.faceIds();
231 
232  if (origIds.size() == origFaces.size())
233  {
234  labelList newFaceIds(origIds.size());
235 
236  forAll(newFaceIds, facei)
237  {
238  newFaceIds[faceMap[facei]] = origIds[facei];
239  }
240 
241  this->storedFaceIds().transfer(newFaceIds);
242  }
243 }
244 
245 
246 template<class Face>
248 (
249  MeshedSurface<Face>&& surf
250 )
251 :
253 {
254  transfer(surf);
255 }
256 
257 
258 template<class Face>
260 (
262 )
263 :
265 {
266  transfer(surf);
267 }
268 
269 
270 template<class Face>
272 (
273  const pointField& pointLst,
274  const UList<Face>& faceLst,
275  const UList<surfZone>& zoneLst
276 )
277 :
278  MeshReference(faceLst, pointLst), // Copy construct
279  faceIds_(),
280  zones_(zoneLst)
281 {
282  this->checkZones(false); // Non-verbose fix zones
283 }
284 
285 
286 template<class Face>
288 (
289  pointField&& pointLst,
290  List<Face>&& faceLst,
291  const UList<surfZone>& zoneLst
292 )
293 :
294  MeshReference(faceLst, pointLst, true), // Move construct
295  faceIds_(),
296  zones_(zoneLst)
297 {
298  this->checkZones(false); // Non-verbose fix zones
299 }
300 
301 
302 template<class Face>
304 (
305  const pointField& pointLst,
306  const UList<Face>& faceLst,
307  const labelUList& zoneSizes,
308  const UList<word>& zoneNames
309 )
310 :
311  MeshReference(faceLst, pointLst), // Copy construct
312  faceIds_(),
313  zones_()
314 {
315  if (zoneSizes.size())
316  {
317  if (zoneNames.size())
318  {
319  addZones(zoneSizes, zoneNames);
320  }
321  else
322  {
323  addZones(zoneSizes);
324  }
325  }
326 }
327 
328 
329 template<class Face>
331 (
332  pointField&& pointLst,
333  List<Face>&& faceLst,
334  const labelUList& zoneSizes,
335  const UList<word>& zoneNames
336 )
337 :
338  MeshReference(faceLst, pointLst, true), // Move construct
339  faceIds_(),
340  zones_()
341 {
342  if (zoneSizes.size())
343  {
344  if (zoneNames.size())
345  {
346  addZones(zoneSizes, zoneNames);
347  }
348  else
349  {
350  addZones(zoneSizes);
351  }
352  }
353 }
354 
355 
356 template<class Face>
358 :
359  MeshedSurface<Face>()
360 {
361  // Need same face type as surfMesh
363  (
364  mesh.points(),
365  mesh.faces(),
366  mesh.surfZones()
367  );
368 
369  this->transcribe(surf);
370 }
371 
372 
373 template<class Face>
375 (
376  const polyBoundaryMesh& bMesh,
377  const bool useGlobalPoints
378 )
379 :
381 {
382  const polyMesh& mesh = bMesh.mesh();
383  const polyPatchList& bPatches = bMesh;
384 
385  // Get a single patch for all boundaries
386  primitivePatch allBoundary
387  (
389  (
390  mesh.faces(),
391  mesh.nBoundaryFaces(),
392  mesh.nInternalFaces()
393  ),
394  mesh.points()
395  );
396 
397  // use global/local points:
398  const pointField& bPoints =
399  (
400  useGlobalPoints ? mesh.points() : allBoundary.localPoints()
401  );
402 
403  // global/local face addressing:
404  const List<Face>& bFaces =
405  (
406  useGlobalPoints ? allBoundary : allBoundary.localFaces()
407  );
408 
409 
410  // create zone list
411  surfZoneList newZones(bPatches.size());
412 
413  label startFacei = 0;
414  label nZone = 0;
415  for (const polyPatch& p : bPatches)
416  {
417  if (p.size())
418  {
419  newZones[nZone] = surfZone
420  (
421  p.name(),
422  p.size(),
423  startFacei,
424  nZone
425  );
426 
427  ++nZone;
428  startFacei += p.size();
429  }
430  }
431 
432  newZones.setSize(nZone);
433 
434  // Face type as per polyBoundaryMesh
435  MeshedSurface<face> surf(bPoints, bFaces, newZones);
436 
437  this->transcribe(surf);
438 }
439 
440 
441 template<class Face>
443 (
444  const fileName& name,
445  const word& fileType
446 )
447 :
449 {
450  read(name, fileType);
451 }
452 
453 
454 template<class Face>
456 :
457  MeshedSurface<Face>()
458 {
459  read(name);
460 }
461 
462 
463 template<class Face>
465 :
466  MeshedSurface<Face>()
467 {
468  read(is);
469 }
470 
471 
472 template<class Face>
474 (
475  const Time& runTime
476 )
477 :
478  MeshedSurface<Face>(runTime, word::null)
479 {}
480 
481 
482 template<class Face>
484 (
485  const Time& runTime,
486  const word& surfName
487 )
488 :
490 {
491  surfMesh mesh
492  (
493  IOobject
494  (
495  "dummyName",
496  runTime.timeName(),
497  runTime,
498  IOobject::MUST_READ_IF_MODIFIED,
499  IOobject::NO_WRITE,
500  false
501  ),
502  surfName
503  );
504 
505  // The geometry components, returned via autoPtr
507  (
508  std::move(*(mesh.releaseGeom()))
509  );
510 
511  this->transcribe(surf);
512 }
513 
514 
515 template<class Face>
517 (
518  const IOobject& io,
519  const dictionary& dict,
520  const bool isGlobal
521 )
522 :
524 {
525  fileName fName
526  (
527  fileFormats::surfaceFormatsCore::checkFile(io, dict, isGlobal)
528  );
529 
530  this->read(fName, dict.getOrDefault<word>("fileType", word::null));
531 
532  this->scalePoints(dict.getOrDefault<scalar>("scale", 0));
533 }
534 
535 
536 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
537 
538 template<class Face>
540 {
541  clear();
542 }
543 
544 
545 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
546 
547 template<class Face>
549 (
550  const labelUList& faceMapNewToOld
551 )
552 {
553  if (faceMapNewToOld.empty())
554  {
555  return;
556  }
557 
558  surfZoneList& zones = storedZones();
559 
560  if (zones.size() == 1)
561  {
562  // Single zone case is trivial
563  zones[0].size() = faceMapNewToOld.size();
564  return;
565  }
566 
567  // Recalculate the zone start/size
568  label newFacei = 0;
569  label origEndi = 0;
570 
571  for (surfZone& zone : zones)
572  {
573  // Adjust zone start
574  zone.start() = newFacei;
575  origEndi += zone.size();
576 
577  for (label facei = newFacei; facei < faceMapNewToOld.size(); ++facei)
578  {
579  if (faceMapNewToOld[facei] < origEndi)
580  {
581  ++newFacei;
582  }
583  else
584  {
585  break;
586  }
587  }
588 
589  // Adjust zone size
590  zone.size() = newFacei - zone.start();
591  }
592 }
593 
594 
595 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
596 
597 template<class Face>
599 {
600  MeshReference::clearOut(); // Topology changes
601 
602  storedPoints().clear();
603  storedFaces().clear();
604  storedFaceIds().clear();
605  storedZones().clear();
606 }
607 
608 
609 template<class Face>
611 {
612  MeshReference::clearGeom(); // Changes areas, normals etc.
613 
614  // Adapt for new point positions
615  MeshReference::movePoints(newPoints);
616 
617  // Copy new points
618  storedPoints() = newPoints;
619 }
620 
621 
622 template<class Face>
623 void Foam::MeshedSurface<Face>::scalePoints(const scalar scaleFactor)
624 {
625  // Avoid bad or no scaling
626  if (scaleFactor > SMALL && !equal(scaleFactor, 1))
627  {
628  // Remove all geometry dependent data
629  this->clearTopology();
630 
631  // Adapt for new point positions
632  MeshReference::movePoints(pointField());
633 
634  this->storedPoints() *= scaleFactor;
635  }
636 }
637 
638 
639 // Remove badly degenerate faces, double faces.
640 template<class Face>
641 void Foam::MeshedSurface<Face>::cleanup(const bool verbose)
642 {
643  // Merge points (already done for STL, TRI)
644  stitchFaces(SMALL, verbose);
645 
646  checkFaces(verbose);
647  this->checkTopology(verbose);
648 }
649 
650 
651 template<class Face>
653 {
654  this->clearOut(); // Topology changes
655 
656  // Remove unused points while walking and renumbering faces
657  // in visit order - walk order as per localFaces()
658 
659  labelList oldToCompact(this->points().size(), -1);
660  DynamicList<label> compactPointMap(oldToCompact.size());
661 
662  for (auto& f : this->storedFaces())
663  {
664  for (label& pointi : f)
665  {
666  label compacti = oldToCompact[pointi];
667  if (compacti == -1)
668  {
669  compacti = compactPointMap.size();
670  oldToCompact[pointi] = compacti;
671  compactPointMap.append(pointi);
672  }
673  pointi = compacti;
674  }
675  }
676 
677  pointField newPoints
678  (
679  UIndirectList<point>(this->points(), compactPointMap)
680  );
681 
682  this->swapPoints(newPoints);
683 
684  if (notNull(pointMap))
685  {
686  pointMap.transfer(compactPointMap);
687  }
688 }
689 
690 
691 template<class Face>
693 (
694  const scalar tol,
695  const bool verbose
696 )
697 {
698  pointField& pointLst = this->storedPoints();
699 
700  // Merge points
701  labelList pointMap(pointLst.size());
702  pointField newPoints(pointLst.size());
703 
704  bool hasMerged = mergePoints(pointLst, tol, verbose, pointMap, newPoints);
705 
706  if (!hasMerged)
707  {
708  return false;
709  }
710 
711  if (verbose)
712  {
713  InfoInFunction<< "Renumbering all faces" << endl;
714  }
715 
716  // Set the coordinates to the merged ones
717  pointLst.transfer(newPoints);
718 
719  List<Face>& faceLst = this->storedFaces();
720 
721  labelList faceMap(faceLst.size(), -1);
722 
723  // Reset the point labels to the unique points array
724  label newFacei = 0;
725  forAll(faceLst, facei)
726  {
727  Face& f = faceLst[facei];
728  for (label& vert : f)
729  {
730  vert = pointMap[vert];
731  }
732 
733  // For extra safety: collapse face as well
734  if (f.collapse() >= 3)
735  {
736  if (newFacei != facei)
737  {
738  faceLst[newFacei] = f;
739  }
740  faceMap[newFacei] = facei;
741  ++newFacei;
742  }
743  else if (verbose)
744  {
745  Pout<< "MeshedSurface::stitchFaces : "
746  << "Removing collapsed face " << facei << endl
747  << " vertices :" << f << endl;
748  }
749  }
750  pointMap.clear();
751 
752  if (newFacei != faceLst.size())
753  {
754  if (verbose)
755  {
756  Pout<< "MeshedSurface::stitchFaces : "
757  << "Removed " << faceLst.size() - newFacei
758  << " faces" << endl;
759  }
760  faceMap.resize(newFacei);
761  faceLst.resize(newFacei);
762 
763  // The faceMap is a newToOld mapping and only removes elements
764  if (faceIds_.size())
765  {
766  forAll(faceMap, facei)
767  {
768  faceIds_[facei] = faceIds_[faceMap[facei]];
769  }
770 
771  faceIds_.resize(newFacei);
772  }
773 
774  remapFaces(faceMap);
775  }
776  faceMap.clear();
777 
778  // Topology can change when points are merged, etc
779  MeshReference::clearOut();
780 
781  return true;
782 }
783 
784 
785 // Remove badly degenerate faces and double faces.
786 template<class Face>
788 (
789  const bool verbose
790 )
791 {
792  bool changed = false;
793  List<Face>& faceLst = this->storedFaces();
794 
795  labelList faceMap(faceLst.size());
796 
797  label newFacei = 0;
798  const label maxPointi = this->points().size();
799 
800  // Detect badly labelled faces and mark degenerate faces
801  forAll(faceLst, facei)
802  {
803  Face& f = faceLst[facei];
804 
805  // Avoid degenerate faces
806  if (f.collapse() >= 3)
807  {
808  for (const label vert : f)
809  {
810  if (vert < 0 || vert >= maxPointi)
811  {
813  << "face " << f
814  << " uses point indices outside point range 0.."
815  << (maxPointi-1)
816  << exit(FatalError);
817  }
818  }
819 
820  faceMap[facei] = facei;
821  ++newFacei;
822  }
823  else
824  {
825  // Mark as bad face
826  faceMap[facei] = -1;
827 
828  changed = true;
829  if (verbose)
830  {
832  << "face[" << facei << "] = " << f
833  << " does not have three unique vertices" << endl;
834  }
835  }
836  }
837 
838  // Detect doubled faces
839  // do not touch the faces
840  const labelListList& fFaces = this->faceFaces();
841  newFacei = 0;
842  forAll(faceLst, facei)
843  {
844  // Skip already collapsed faces
845  if (faceMap[facei] < 0)
846  {
847  continue;
848  }
849 
850  const Face& f = faceLst[facei];
851 
852  // Duplicate face check
853  bool okay = true;
854  const labelList& neighbours = fFaces[facei];
855 
856  // Check if faceNeighbours use same points as this face.
857  // Note: discards normal information - sides of baffle are merged.
858  for (const label neiFacei : neighbours)
859  {
860  if (neiFacei <= facei || faceMap[neiFacei] < 0)
861  {
862  // lower numbered faces already checked
863  // skip neighbours that are themselves collapsed
864  continue;
865  }
866 
867  const Face& nei = faceLst[neiFacei];
868 
869  if (f == nei)
870  {
871  okay = false;
872 
873  if (verbose)
874  {
876  << "faces share the same vertices:" << nl
877  << " face[" << facei << "] : " << f << nl
878  << " face[" << neiFacei << "] : " << nei << endl;
879  // printFace(Warning, " ", f, points());
880  // printFace(Warning, " ", nei, points());
881  }
882 
883  break;
884  }
885  }
886 
887  if (okay)
888  {
889  faceMap[facei] = facei;
890  ++newFacei;
891  }
892  else
893  {
894  faceMap[facei] = -1;
895  }
896  }
897 
898 
899  // Until now, faceMap is an identity for good faces and -1 for bad faces
900 
901  // Phase 1: pack
902  // Done to keep numbering constant in phase 1
903 
904  if (changed || newFacei < faceLst.size())
905  {
906  changed = true;
907 
908  if (verbose)
909  {
911  << "Removed " << faceLst.size() - newFacei
912  << " illegal faces." << endl;
913  }
914 
915  // Compress the face list
916  newFacei = 0;
917  forAll(faceLst, facei)
918  {
919  if (faceMap[facei] >= 0)
920  {
921  if (newFacei != facei)
922  {
923  faceLst[newFacei] = std::move(faceLst[facei]);
924  }
925  faceMap[newFacei] = facei;
926  ++newFacei;
927  }
928  }
929 
930  faceMap.resize(newFacei);
931  faceLst.resize(newFacei);
932 
933  // The faceMap is a newToOld mapping and only removes elements
934  if (faceIds_.size())
935  {
936  forAll(faceMap, facei)
937  {
938  faceIds_[facei] = faceIds_[faceMap[facei]];
939  }
940 
941  faceIds_.resize(newFacei);
942  }
943 
944  remapFaces(faceMap);
945  }
946  faceMap.clear();
947 
948  // Topology can change because of renumbering
949  MeshReference::clearOut();
950  return changed;
951 }
952 
953 
954 template<class Face>
956 {
958  {
959  return MeshReference::size();
960  }
961 
962  return nTriangles
963  (
964  const_cast<labelList&>(labelList::null())
965  );
966 }
967 
968 
969 template<class Face>
971 (
973 ) const
974 {
975  label nTri = 0;
976  const List<Face>& faceLst = surfFaces();
977 
978  // Count triangles needed
979  for (const auto& f : faceLst)
980  {
981  nTri += f.nTriangles();
982  }
983 
984  // Nothing to do
985  if (nTri <= faceLst.size())
986  {
987  if (notNull(faceMap))
988  {
989  faceMap.clear();
990  }
991  }
992  else if (notNull(faceMap))
993  {
994  // Face map requested
995  faceMap.resize(nTri);
996 
997  nTri = 0;
998  forAll(faceLst, facei)
999  {
1000  label n = faceLst[facei].nTriangles();
1001  while (n-- > 0)
1002  {
1003  faceMap[nTri++] = facei;
1004  }
1005  }
1006 
1007  faceMap.resize(nTri);
1008  }
1009 
1010  return nTri;
1011 }
1012 
1013 
1014 template<class Face>
1016 {
1018  {
1019  // Inplace triangulation of triFace/labelledTri surface = no-op
1020  return 0;
1021  }
1022  else
1023  {
1024  return triangulate
1025  (
1026  const_cast<labelList&>(labelList::null())
1027  );
1028  }
1029 }
1030 
1031 
1032 template<class Face>
1035  labelList& faceMapOut
1036 )
1037 {
1038  labelList dummyFaceMap;
1039 
1040  labelList& faceMap =
1041  (
1042  notNull(faceMapOut)
1043  ? faceMapOut
1044  : dummyFaceMap
1045  );
1046 
1048  {
1049  // Inplace triangulation of triFace/labelledTri surface = no-op
1050  faceMap.clear();
1051  return 0;
1052  }
1053 
1054  label nTri = 0;
1055  label maxTri = 0; // the maximum number of triangles for any single face
1056  List<Face>& faceLst = this->storedFaces();
1057 
1058  // How many triangles will be needed
1059  for (const auto& f : faceLst)
1060  {
1061  const label n = f.nTriangles();
1062  if (maxTri < n)
1063  {
1064  maxTri = n;
1065  }
1066  nTri += n;
1067  }
1068 
1069  // Nothing to do
1070  if (nTri <= faceLst.size())
1071  {
1072  faceMap.clear();
1073  return 0;
1074  }
1075 
1076  this->storedFaceIds().clear(); // Invalid or misleading
1077 
1078  List<Face> newFaces(nTri);
1079  faceMap.resize(nTri);
1080 
1081  if (this->points().empty())
1082  {
1083  // triangulate without points
1084  // simple face triangulation around f[0]
1085  nTri = 0;
1086  forAll(faceLst, facei)
1087  {
1088  const Face& f = faceLst[facei];
1089 
1090  for (label fp = 1; fp < f.size() - 1; ++fp)
1091  {
1092  const label fp1 = f.fcIndex(fp);
1093 
1094  newFaces[nTri] = Face{f[0], f[fp], f[fp1]};
1095  faceMap[nTri] = facei;
1096  ++nTri;
1097  }
1098  }
1099  }
1100  else
1101  {
1102  // triangulate with points
1103  List<face> tmpTri(maxTri);
1104 
1105  nTri = 0;
1106  forAll(faceLst, facei)
1107  {
1108  // 'face' not '<Face>'
1109  const face& f = faceLst[facei];
1110 
1111  label nTmp = 0;
1112  f.triangles(this->points(), nTmp, tmpTri);
1113  for (label triI = 0; triI < nTmp; triI++)
1114  {
1115  newFaces[nTri] = Face
1116  (
1117  static_cast<labelUList&>(tmpTri[triI])
1118  );
1119  faceMap[nTri] = facei;
1120  ++nTri;
1121  }
1122  }
1123  }
1124 
1125  // The number of *additional* faces
1126  nTri -= faceLst.size();
1127 
1128  faceLst.transfer(newFaces);
1129  remapFaces(faceMap);
1130 
1131  // Topology can change because of renumbering
1132  MeshReference::clearOut();
1133 
1134  return nTri;
1135 }
1136 
1137 
1138 template<class Face>
1141 (
1142  const labelList& pointMap,
1143  const labelList& faceMap
1144 ) const
1145 {
1146  const pointField& locPoints = this->localPoints();
1147  const List<Face>& locFaces = this->localFaces();
1148 
1149  // Subset of points (compact)
1150  pointField newPoints(UIndirectList<point>(locPoints, pointMap));
1151 
1152  // Inverse point mapping - same as ListOps invert() without checks
1153  labelList oldToNew(locPoints.size(), -1);
1154  forAll(pointMap, pointi)
1155  {
1156  oldToNew[pointMap[pointi]] = pointi;
1157  }
1158 
1159  // Subset of faces
1160  List<Face> newFaces(UIndirectList<Face>(locFaces, faceMap));
1161 
1162  // Renumber face node labels
1163  for (auto& f : newFaces)
1164  {
1165  for (label& vert : f)
1166  {
1167  vert = oldToNew[vert];
1168  }
1169  }
1170  oldToNew.clear();
1171 
1172  // Deep copy of zones, leave start/size intact!!
1173  surfZoneList newZones(zones_);
1174 
1175  // Recalculate the zone start/size
1176  label newFacei = 0;
1177  label origEndi = 0;
1178 
1179  for (surfZone& zone : newZones)
1180  {
1181  // The old zone ending
1182  origEndi += zone.size();
1183 
1184  // The new zone start
1185  zone.start() = newFacei;
1186 
1187  for (label facei = newFacei; facei < faceMap.size(); ++facei)
1188  {
1189  if (faceMap[facei] < origEndi)
1190  {
1191  ++newFacei;
1192  }
1193  else
1194  {
1195  break;
1196  }
1197  }
1198 
1199  // The new zone size
1200  zone.size() = newFacei - zone.start();
1201  }
1202 
1203 
1204  // Subset of faceIds. Can be empty.
1205  labelList newFaceIds;
1206  if (faceIds_.size())
1207  {
1208  newFaceIds = labelUIndList(faceIds_, faceMap);
1209  }
1210 
1211  // Construct the sub-surface
1212  MeshedSurface<Face> newSurf;
1213  newSurf.storedFaces().transfer(newFaces);
1214  newSurf.storedPoints().transfer(newPoints);
1215  newSurf.storedZones().transfer(newZones);
1216  newSurf.storedFaceIds().transfer(newFaceIds);
1217 
1218  return newSurf;
1219 }
1220 
1221 
1222 template<class Face>
1226  const UList<bool>& include,
1227  labelList& pointMap,
1229 ) const
1230 {
1231  this->subsetMeshMap(include, pointMap, faceMap);
1232  return this->subsetMeshImpl(pointMap, faceMap);
1233 }
1234 
1235 
1236 template<class Face>
1240  const bitSet& include,
1241  labelList& pointMap,
1243 ) const
1244 {
1245  this->subsetMeshMap(include, pointMap, faceMap);
1246  return this->subsetMeshImpl(pointMap, faceMap);
1247 }
1248 
1249 
1250 template<class Face>
1254  const UList<bool>& include
1255 ) const
1256 {
1257  labelList pointMap, faceMap;
1258  return this->subsetMesh(include, pointMap, faceMap);
1259 }
1260 
1261 
1262 template<class Face>
1266  const bitSet& include
1267 ) const
1268 {
1269  labelList pointMap, faceMap;
1270  return this->subsetMesh(include, pointMap, faceMap);
1271 }
1272 
1273 
1274 template<class Face>
1277  const wordRes& includeNames,
1278  const wordRes& excludeNames
1279 ) const
1280 {
1281  bitSet include(this->size());
1282 
1283  for
1284  (
1285  const label zonei
1286  : fileFormats::surfaceFormatsCore::getSelectedPatches
1287  (
1288  zones_,
1289  includeNames,
1290  excludeNames
1291  )
1292  )
1293  {
1294  include.set(zones_[zonei].range());
1295  }
1296 
1297  return this->subsetMesh(include);
1298 }
1299 
1300 
1301 template<class Face>
1304  MeshedSurface<Face>& surf
1305 )
1306 {
1307  if (this == &surf)
1308  {
1309  return; // Self-swap is a no-op
1310  }
1311 
1312  MeshReference::clearOut(); // Topology changes
1313  surf.clearOut(); // Topology changes
1314 
1315  this->storedPoints().swap(surf.storedPoints());
1316  this->storedFaces().swap(surf.storedFaces());
1317  this->storedZones().swap(surf.storedZones());
1318  this->storedFaceIds().swap(surf.storedFaceIds());
1319 }
1320 
1321 
1322 template<class Face>
1325  pointField& pointLst,
1326  List<Face>& faceLst
1327 )
1328 {
1329  MeshReference::clearOut(); // Topology changes
1330 
1331  this->storedPoints().transfer(pointLst);
1332  this->storedFaces().transfer(faceLst);
1333  this->storedZones().clear();
1334  this->storedFaceIds().clear(); // Likely to be invalid
1335 }
1336 
1337 
1338 template<class Face>
1341  MeshedSurface<Face>& surf
1342 )
1343 {
1344  if (this == &surf)
1345  {
1346  return; // Self-assigment is a no-op
1347  }
1348 
1349  MeshReference::clearOut(); // Topology changes
1350 
1351  this->storedPoints().transfer(surf.storedPoints());
1352  this->storedFaces().transfer(surf.storedFaces());
1353  this->storedZones().transfer(surf.storedZones());
1354  this->storedFaceIds().transfer(surf.storedFaceIds());
1355 
1356  surf.clear();
1357 }
1358 
1359 
1360 template<class Face>
1364 )
1365 {
1366  // Clear everything
1367  this->clear();
1368 
1370  surfZoneList zoneLst = surf.sortedZones(faceMap);
1371 
1372  List<Face>& faceLst = surf.storedFaces();
1373 
1374  if (zoneLst.size() > 1)
1375  {
1376  // Unknown if we really need to sort the faces
1377  List<Face> sortedFaces(faceMap.size());
1378 
1379  forAll(faceMap, facei)
1380  {
1381  sortedFaces[faceMap[facei]].transfer(faceLst[facei]);
1382  }
1383 
1384  faceLst.swap(sortedFaces); // Replace with sorted faces
1385  }
1386 
1387  MeshedSurface<Face> newSurf
1388  (
1389  std::move(surf.storedPoints()),
1390  std::move(faceLst),
1391  zoneLst
1392  );
1393 
1394  surf.clear();
1395 
1396  this->swap(newSurf);
1397 }
1398 
1399 
1400 template<class Face>
1403 {
1404  return autoPtr<MeshedSurface<Face>>::New(std::move(*this));
1405 }
1406 
1407 
1408 template<class Face>
1410 {
1411  MeshReference::clearOut(); // Topology changes
1412 
1413  this->storedFaceIds().clear(); // Likely to be invalid
1414 
1415  this->storedFaces().swap(faces);
1416 
1417  this->checkZones(false); // Non-verbose fix zones
1418 }
1419 
1420 
1421 template<class Face>
1423 {
1424  // Adapt for new point positions
1425  MeshReference::movePoints(points);
1426 
1427  this->storedPoints().swap(points);
1428 }
1429 
1430 
1431 template<class Face>
1433 {
1434  this->clear();
1435  transfer(*New(name));
1436  return true;
1437 }
1438 
1439 
1440 template<class Face>
1443  const fileName& name,
1444  const word& fileType
1445 )
1446 {
1447  this->clear();
1448  transfer(*New(name, fileType));
1449  return true;
1450 }
1451 
1452 
1453 template<class Face>
1456  const Time& t,
1457  const word& surfName
1458 ) const
1459 {
1460  MeshedSurfaceProxy<Face>(*this).write(t, surfName);
1461 }
1462 
1463 
1464 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1465 
1466 template<class Face>
1468 {
1469  if (this == &surf)
1470  {
1471  return; // Self-assignment is a no-op
1472  }
1473 
1474  // Clear everything
1475  this->clear();
1476 
1477  this->storedPoints() = surf.points();
1478  this->storedFaces() = surf.surfFaces();
1479  this->storedFaceIds() = surf.faceIds();
1480  this->storedZones() = surf.surfZones();
1481 }
1482 
1483 
1484 template<class Face>
1486 {
1487  transfer(surf);
1488 }
1489 
1490 
1491 template<class Face>
1493 {
1495  (
1496  this->points(),
1497  this->surfFaces(),
1498  this->surfZones(),
1499  labelUList::null(), // faceMap = none
1500  this->faceIds()
1501  );
1502 }
1503 
1504 
1505 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1506 
1507 #include "MeshedSurfaceZones.C"
1508 #include "MeshedSurfaceIO.C"
1509 #include "MeshedSurfaceNew.C"
1510 
1511 // ************************************************************************* //
Foam::MeshedSurface::faceIds
const labelList & faceIds() const
Return const access to faces ids.
Definition: MeshedSurface.H:421
Foam::word::lessExt
word lessExt() const
Return word without extension (part before last .)
Definition: word.C:113
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:350
p
volScalarField & p
Definition: createFieldRefs.H:8
MeshedSurfaceProxy.H
Foam::MeshedSurface::surfZones
const surfZoneList & surfZones() const
Const access to the surface zones.
Definition: MeshedSurface.H:429
Foam::MeshedSurface::~MeshedSurface
virtual ~MeshedSurface()
Destructor.
Definition: MeshedSurface.C:539
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::MeshedSurface::storedFaces
List< Face > & storedFaces()
Non-const access to the faces.
Definition: MeshedSurface.H:173
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::MeshedSurface::storedFaceIds
labelList & storedFaceIds()
Non-const access to face ids.
Definition: MeshedSurface.H:179
Foam::MeshedSurface::canReadType
static bool canReadType(const word &fileType, bool verbose=false)
Can we read this file format? Also checks friend types.
Definition: MeshedSurface.C:60
Foam::MeshedSurface::triangulate
virtual label triangulate()
Triangulate in-place, returning the number of triangles added.
Definition: MeshedSurface.C:1015
Foam::DynamicList< label >
Foam::MeshedSurface::swap
void swap(MeshedSurface< Face > &surf)
Swap contents.
Definition: MeshedSurface.C:1303
Foam::MeshedSurface::storedPoints
pointField & storedPoints()
Non-const access to global points.
Definition: MeshedSurface.H:167
Foam::MeshedSurface::stitchFaces
virtual bool stitchFaces(const scalar tol=SMALL, const bool verbose=false)
Definition: MeshedSurface.C:693
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
Foam::MeshedSurface::operator=
void operator=(const MeshedSurface< Face > &surf)
Copy assignment.
Definition: MeshedSurface.C:1467
Foam::zone
Base class for mesh zones.
Definition: zone.H:63
Foam::MeshedSurface::surfFaces
const List< Face > & surfFaces() const
Return const access to the faces.
Definition: MeshedSurface.H:413
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::MeshedSurface::scalePoints
virtual void scalePoints(const scalar scaleFactor)
Scale points. A non-positive factor is ignored.
Definition: MeshedSurface.C:623
Foam::surfMesh
A surface mesh consisting of general polygon faces that has IO capabilities and a registry for storin...
Definition: surfMesh.H:63
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::word::ext
word ext() const
Return file name extension (part after last .)
Definition: word.C:126
Foam::MeshedSurface::clear
virtual void clear()
Clear all storage.
Definition: MeshedSurface.C:598
Foam::MeshedSurfaceProxy::write
static void write(const fileName &name, const MeshedSurfaceProxy &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &options=dictionary::null)
Write to file, select based on its extension.
Definition: MeshedSurfaceProxy.C:64
Foam::checkTopology
label checkTopology(const polyMesh &mesh, const bool allTopology, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, const autoPtr< writer< scalar >> &setWriter)
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::MeshedSurface::canWriteType
static bool canWriteType(const word &fileType, bool verbose=false)
Can we write this file format? Also checks proxy types.
Definition: MeshedSurface.C:77
polyMesh.H
Foam::MatrixTools::equal
bool equal(const Matrix< Form1, Type > &A, const Matrix< Form2, Type > &B, const bool verbose=false, const label maxDiffs=10, const scalar relTol=1e-5, const scalar absTol=1e-8)
Compare matrix elements for absolute or relative equality.
Definition: MatrixTools.C:34
Foam::HashSet< word, Hash< word > >
Foam::MeshedSurfaceProxy
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
Definition: MeshedSurface.H:82
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::MeshedSurface::checkFaces
virtual bool checkFaces(const bool verbose=false)
Definition: MeshedSurface.C:788
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::MeshedSurface::canRead
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
Definition: MeshedSurface.C:94
UnsortedMeshedSurface.H
Foam::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::MeshedSurface::storedZones
surfZoneList & storedZones()
Non-const access to the zones.
Definition: MeshedSurface.H:185
Foam::faceTraits
Traits class for faces.
Definition: faceTraits.H:50
Foam::MeshedSurface::transfer
void transfer(pointField &pointLst, List< Face > &faceLst)
Transfer the components.
Definition: MeshedSurface.C:1324
Foam::Field< vector >
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::UnsortedMeshedSurface
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
Definition: MeshedSurface.H:83
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:388
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::bMesh
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points)
Definition: bMesh.H:48
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::MeshedSurface::nTriangles
virtual label nTriangles() const
Count number of triangles.
Definition: MeshedSurface.C:955
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:59
MeshedSurfaceIO.C
Foam::MeshedSurface::swapPoints
void swapPoints(pointField &points)
Swap the stored points.
Definition: MeshedSurface.C:1422
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::UList::empty
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
Foam::notNull
bool notNull(const T *ptr)
True if ptr is not a pointer (of type T) to the nullObject.
Definition: nullObject.H:207
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
MeshedSurfaceZones.C
surfMesh.H
Foam::MeshedSurface::readTypes
static wordHashSet readTypes()
Known readable file-types, without friends or proxies.
Definition: MeshedSurface.C:45
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::MeshedSurface::movePoints
virtual void movePoints(const pointField &newPoints)
Move points.
Definition: MeshedSurface.C:610
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
range
scalar range
Definition: LISASMDCalcMethod1.H:12
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::UnsortedMeshedSurface::clear
virtual void clear()
Clear all storage.
Definition: UnsortedMeshedSurface.C:500
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:56
Foam::UList< Face >
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::wordRes
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:51
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
polyBoundaryMesh.H
Foam::MeshedSurface::MeshedSurface
MeshedSurface()
Default construct, an empty surface.
Definition: MeshedSurface.C:183
Foam::surfZoneList
List< surfZone > surfZoneList
Definition: surfZoneList.H:47
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
mergePoints.H
Merge points. See below.
Foam::wordHashSet
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:77
Foam::MeshedSurface::writeTypes
static wordHashSet writeTypes()
Known writable file-types, without friends or proxies.
Definition: MeshedSurface.C:52
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
MeshedSurfaceNew.C
ListOps.H
Various functions to operate on Lists.
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::MeshedSurface::swapFaces
void swapFaces(List< Face > &faces)
Swap the stored faces. Use with caution.
Definition: MeshedSurface.C:1409
Foam::MeshedSurface
A surface geometry mesh with zone information, not to be confused with the similarly named surfaceMes...
Definition: triSurfaceTools.H:80
faceTraits.H
primitivePatch.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::MeshedSurface::subsetMesh
MeshedSurface subsetMesh(const UList< bool > &include, labelList &pointMap, labelList &faceMap) const
Return a new surface subsetted on the selected faces.
Definition: MeshedSurface.C:1225
Foam::MeshedSurface::compactPoints
virtual void compactPoints(labelList &pointMap=const_cast< labelList & >(labelList::null()))
Remove unused points and renumber faces in local visit order.
Definition: MeshedSurface.C:652
Foam::MeshedSurface::remapFaces
virtual void remapFaces(const labelUList &faceMapNewToOld)
Set new zones from faceMap.
Definition: MeshedSurface.C:549
Foam::UnsortedMeshedSurface::sortedZones
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
Definition: UnsortedMeshedSurface.C:510
Foam::MeshedSurface::releaseGeom
autoPtr< MeshedSurface< Face > > releaseGeom()
Release (clear) geometry and return for reuse.
Definition: MeshedSurface.C:1402
Foam::MeshedSurface::cleanup
virtual void cleanup(const bool verbose)
Remove invalid faces.
Definition: MeshedSurface.C:641
MeshedSurface.H
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58