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-2020 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 mfIter = writefileExtensionMemberFunctionTablePtr_->cfind(fileType);
153 
154  if (!mfIter.found())
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  mfIter()(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 
283 
284 template<class Face>
286 (
287  pointField&& pointLst,
288  List<Face>&& faceLst,
289  const UList<surfZone>& zoneLst
290 )
291 :
292  MeshReference(faceLst, pointLst, true), // Move construct
293  faceIds_(),
294  zones_(zoneLst)
295 {}
296 
297 
298 template<class Face>
300 (
301  const pointField& pointLst,
302  const UList<Face>& faceLst,
303  const labelUList& zoneSizes,
304  const UList<word>& zoneNames
305 )
306 :
307  MeshReference(faceLst, pointLst), // Copy construct
308  faceIds_(),
309  zones_()
310 {
311  if (zoneSizes.size())
312  {
313  if (zoneNames.size())
314  {
315  addZones(zoneSizes, zoneNames);
316  }
317  else
318  {
319  addZones(zoneSizes);
320  }
321  }
322 }
323 
324 
325 template<class Face>
327 (
328  pointField&& pointLst,
329  List<Face>&& faceLst,
330  const labelUList& zoneSizes,
331  const UList<word>& zoneNames
332 )
333 :
334  MeshReference(faceLst, pointLst, true), // Move construct
335  faceIds_(),
336  zones_()
337 {
338  if (zoneSizes.size())
339  {
340  if (zoneNames.size())
341  {
342  addZones(zoneSizes, zoneNames);
343  }
344  else
345  {
346  addZones(zoneSizes);
347  }
348  }
349 }
350 
351 
352 template<class Face>
354 :
355  MeshedSurface<Face>()
356 {
357  // Need same face type as surfMesh
359  (
360  mesh.points(),
361  mesh.faces(),
362  mesh.surfZones()
363  );
364 
365  this->transcribe(surf);
366 }
367 
368 
369 template<class Face>
371 (
372  const polyBoundaryMesh& bMesh,
373  const bool useGlobalPoints
374 )
375 :
377 {
378  const polyMesh& mesh = bMesh.mesh();
379  const polyPatchList& bPatches = bMesh;
380 
381  // Get a single patch for all boundaries
382  primitivePatch allBoundary
383  (
385  (
386  mesh.faces(),
387  mesh.nBoundaryFaces(),
388  mesh.nInternalFaces()
389  ),
390  mesh.points()
391  );
392 
393  // use global/local points:
394  const pointField& bPoints =
395  (
396  useGlobalPoints ? mesh.points() : allBoundary.localPoints()
397  );
398 
399  // global/local face addressing:
400  const List<Face>& bFaces =
401  (
402  useGlobalPoints ? allBoundary : allBoundary.localFaces()
403  );
404 
405 
406  // create zone list
407  surfZoneList newZones(bPatches.size());
408 
409  label startFacei = 0;
410  label nZone = 0;
411  for (const polyPatch& p : bPatches)
412  {
413  if (p.size())
414  {
415  newZones[nZone] = surfZone
416  (
417  p.name(),
418  p.size(),
419  startFacei,
420  nZone
421  );
422 
423  ++nZone;
424  startFacei += p.size();
425  }
426  }
427 
428  newZones.setSize(nZone);
429 
430  // Face type as per polyBoundaryMesh
431  MeshedSurface<face> surf(bPoints, bFaces, newZones);
432 
433  this->transcribe(surf);
434 }
435 
436 
437 template<class Face>
439 (
440  const fileName& name,
441  const word& fileType
442 )
443 :
445 {
446  read(name, fileType);
447 }
448 
449 
450 template<class Face>
452 :
453  MeshedSurface<Face>()
454 {
455  read(name);
456 }
457 
458 
459 template<class Face>
461 :
462  MeshedSurface<Face>()
463 {
464  read(is);
465 }
466 
467 
468 template<class Face>
470 (
471  const Time& runTime
472 )
473 :
474  MeshedSurface<Face>(runTime, word::null)
475 {}
476 
477 
478 template<class Face>
480 (
481  const Time& runTime,
482  const word& surfName
483 )
484 :
486 {
487  surfMesh mesh
488  (
489  IOobject
490  (
491  "dummyName",
492  runTime.timeName(),
493  runTime,
494  IOobject::MUST_READ_IF_MODIFIED,
495  IOobject::NO_WRITE,
496  false
497  ),
498  surfName
499  );
500 
501  // The geometry components, returned via autoPtr
503  (
504  std::move(*(mesh.releaseGeom()))
505  );
506 
507  this->transcribe(surf);
508 }
509 
510 
511 template<class Face>
513 (
514  const IOobject& io,
515  const dictionary& dict,
516  const bool isGlobal
517 )
518 :
520 {
521  fileName fName
522  (
523  fileFormats::surfaceFormatsCore::checkFile(io, dict, isGlobal)
524  );
525 
526  this->read(fName, dict.getOrDefault<word>("fileType", word::null));
527 
528  this->scalePoints(dict.getOrDefault<scalar>("scale", 0));
529 }
530 
531 
532 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
533 
534 template<class Face>
536 {
537  clear();
538 }
539 
540 
541 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
542 
543 template<class Face>
545 (
546  const labelUList& faceMapNewToOld
547 )
548 {
549  if (faceMapNewToOld.empty())
550  {
551  return;
552  }
553 
554  surfZoneList& zones = storedZones();
555 
556  if (zones.size() == 1)
557  {
558  // Single zone case is trivial
559  zones[0].size() = faceMapNewToOld.size();
560  return;
561  }
562 
563  // Recalculate the zone start/size
564  label newFacei = 0;
565  label origEndi = 0;
566 
567  for (surfZone& zone : zones)
568  {
569  // Adjust zone start
570  zone.start() = newFacei;
571  origEndi += zone.size();
572 
573  for (label facei = newFacei; facei < faceMapNewToOld.size(); ++facei)
574  {
575  if (faceMapNewToOld[facei] < origEndi)
576  {
577  ++newFacei;
578  }
579  else
580  {
581  break;
582  }
583  }
584 
585  // Adjust zone size
586  zone.size() = newFacei - zone.start();
587  }
588 }
589 
590 
591 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
592 
593 template<class Face>
595 {
596  MeshReference::clearOut(); // Topology changes
597 
598  storedPoints().clear();
599  storedFaces().clear();
600  storedFaceIds().clear();
601  storedZones().clear();
602 }
603 
604 
605 template<class Face>
607 {
608  MeshReference::clearGeom(); // Changes areas, normals etc.
609 
610  // Adapt for new point position
611  MeshReference::movePoints(newPoints);
612 
613  // Copy new points
614  storedPoints() = newPoints;
615 }
616 
617 
618 template<class Face>
619 void Foam::MeshedSurface<Face>::scalePoints(const scalar scaleFactor)
620 {
621  // Avoid bad scaling
622  if (scaleFactor > 0 && scaleFactor != 1.0)
623  {
624  MeshReference::clearGeom(); // Changes areas, normals etc.
625 
626  pointField newPoints(scaleFactor*this->points());
627 
628  // Adapt for new point position
629  MeshReference::movePoints(newPoints);
630 
631  storedPoints() = std::move(newPoints);
632  }
633 }
634 
635 
636 // Remove badly degenerate faces, double faces.
637 template<class Face>
638 void Foam::MeshedSurface<Face>::cleanup(const bool verbose)
639 {
640  // Merge points (already done for STL, TRI)
641  stitchFaces(SMALL, verbose);
642 
643  checkFaces(verbose);
644  this->checkTopology(verbose);
645 }
646 
647 
648 template<class Face>
650 (
651  const scalar tol,
652  const bool verbose
653 )
654 {
655  pointField& pointLst = this->storedPoints();
656 
657  // Merge points
658  labelList pointMap(pointLst.size());
659  pointField newPoints(pointLst.size());
660 
661  bool hasMerged = mergePoints(pointLst, tol, verbose, pointMap, newPoints);
662 
663  if (!hasMerged)
664  {
665  return false;
666  }
667 
668  if (verbose)
669  {
670  InfoInFunction<< "Renumbering all faces" << endl;
671  }
672 
673  // Set the coordinates to the merged ones
674  pointLst.transfer(newPoints);
675 
676  List<Face>& faceLst = this->storedFaces();
677 
678  labelList faceMap(faceLst.size(), -1);
679 
680  // Reset the point labels to the unique points array
681  label newFacei = 0;
682  forAll(faceLst, facei)
683  {
684  Face& f = faceLst[facei];
685  for (label& vert : f)
686  {
687  vert = pointMap[vert];
688  }
689 
690  // For extra safety: collapse face as well
691  if (f.collapse() >= 3)
692  {
693  if (newFacei != facei)
694  {
695  faceLst[newFacei] = f;
696  }
697  faceMap[newFacei] = facei;
698  ++newFacei;
699  }
700  else if (verbose)
701  {
702  Pout<< "MeshedSurface::stitchFaces : "
703  << "Removing collapsed face " << facei << endl
704  << " vertices :" << f << endl;
705  }
706  }
707  pointMap.clear();
708 
709  if (newFacei != faceLst.size())
710  {
711  if (verbose)
712  {
713  Pout<< "MeshedSurface::stitchFaces : "
714  << "Removed " << faceLst.size() - newFacei
715  << " faces" << endl;
716  }
717  faceMap.resize(newFacei);
718  faceLst.resize(newFacei);
719 
720  // The faceMap is a newToOld mapping and only removes elements
721  if (faceIds_.size())
722  {
723  forAll(faceMap, facei)
724  {
725  faceIds_[facei] = faceIds_[faceMap[facei]];
726  }
727 
728  faceIds_.resize(newFacei);
729  }
730 
731  remapFaces(faceMap);
732  }
733  faceMap.clear();
734 
735  // Topology can change when points are merged, etc
736  MeshReference::clearOut();
737 
738  return true;
739 }
740 
741 
742 // Remove badly degenerate faces and double faces.
743 template<class Face>
745 (
746  const bool verbose
747 )
748 {
749  bool changed = false;
750  List<Face>& faceLst = this->storedFaces();
751 
752  labelList faceMap(faceLst.size());
753 
754  label newFacei = 0;
755  const label maxPointi = this->points().size();
756 
757  // Detect badly labelled faces and mark degenerate faces
758  forAll(faceLst, facei)
759  {
760  Face& f = faceLst[facei];
761 
762  // Avoid degenerate faces
763  if (f.collapse() >= 3)
764  {
765  for (const label vert : f)
766  {
767  if (vert < 0 || vert >= maxPointi)
768  {
770  << "face " << f
771  << " uses point indices outside point range 0.."
772  << (maxPointi-1)
773  << exit(FatalError);
774  }
775  }
776 
777  faceMap[facei] = facei;
778  ++newFacei;
779  }
780  else
781  {
782  // Mark as bad face
783  faceMap[facei] = -1;
784 
785  changed = true;
786  if (verbose)
787  {
789  << "face[" << facei << "] = " << f
790  << " does not have three unique vertices" << endl;
791  }
792  }
793  }
794 
795  // Detect doubled faces
796  // do not touch the faces
797  const labelListList& fFaces = this->faceFaces();
798  newFacei = 0;
799  forAll(faceLst, facei)
800  {
801  // Skip already collapsed faces
802  if (faceMap[facei] < 0)
803  {
804  continue;
805  }
806 
807  const Face& f = faceLst[facei];
808 
809  // Duplicate face check
810  bool okay = true;
811  const labelList& neighbours = fFaces[facei];
812 
813  // Check if faceNeighbours use same points as this face.
814  // Note: discards normal information - sides of baffle are merged.
815  for (const label neiFacei : neighbours)
816  {
817  if (neiFacei <= facei || faceMap[neiFacei] < 0)
818  {
819  // lower numbered faces already checked
820  // skip neighbours that are themselves collapsed
821  continue;
822  }
823 
824  const Face& nei = faceLst[neiFacei];
825 
826  if (f == nei)
827  {
828  okay = false;
829 
830  if (verbose)
831  {
833  << "faces share the same vertices:" << nl
834  << " face[" << facei << "] : " << f << nl
835  << " face[" << neiFacei << "] : " << nei << endl;
836  // printFace(Warning, " ", f, points());
837  // printFace(Warning, " ", nei, points());
838  }
839 
840  break;
841  }
842  }
843 
844  if (okay)
845  {
846  faceMap[facei] = facei;
847  ++newFacei;
848  }
849  else
850  {
851  faceMap[facei] = -1;
852  }
853  }
854 
855 
856  // Until now, faceMap is an identity for good faces and -1 for bad faces
857 
858  // Phase 1: pack
859  // Done to keep numbering constant in phase 1
860 
861  if (changed || newFacei < faceLst.size())
862  {
863  changed = true;
864 
865  if (verbose)
866  {
868  << "Removed " << faceLst.size() - newFacei
869  << " illegal faces." << endl;
870  }
871 
872  // Compress the face list
873  newFacei = 0;
874  forAll(faceLst, facei)
875  {
876  if (faceMap[facei] >= 0)
877  {
878  if (newFacei != facei)
879  {
880  faceLst[newFacei] = std::move(faceLst[facei]);
881  }
882  faceMap[newFacei] = facei;
883  ++newFacei;
884  }
885  }
886 
887  faceMap.resize(newFacei);
888  faceLst.resize(newFacei);
889 
890  // The faceMap is a newToOld mapping and only removes elements
891  if (faceIds_.size())
892  {
893  forAll(faceMap, facei)
894  {
895  faceIds_[facei] = faceIds_[faceMap[facei]];
896  }
897 
898  faceIds_.resize(newFacei);
899  }
900 
901  remapFaces(faceMap);
902  }
903  faceMap.clear();
904 
905  // Topology can change because of renumbering
906  MeshReference::clearOut();
907  return changed;
908 }
909 
910 
911 template<class Face>
913 {
915  {
916  return MeshReference::size();
917  }
918 
919  return nTriangles
920  (
921  const_cast<labelList&>(labelList::null())
922  );
923 }
924 
925 
926 template<class Face>
928 (
930 ) const
931 {
932  label nTri = 0;
933  const List<Face>& faceLst = surfFaces();
934 
935  // Count triangles needed
936  for (const auto& f : faceLst)
937  {
938  nTri += f.nTriangles();
939  }
940 
941  // Nothing to do
942  if (nTri <= faceLst.size())
943  {
944  if (notNull(faceMap))
945  {
946  faceMap.clear();
947  }
948  }
949  else if (notNull(faceMap))
950  {
951  // Face map requested
952  faceMap.resize(nTri);
953 
954  nTri = 0;
955  forAll(faceLst, facei)
956  {
957  label n = faceLst[facei].nTriangles();
958  while (n-- > 0)
959  {
960  faceMap[nTri++] = facei;
961  }
962  }
963 
964  faceMap.resize(nTri);
965  }
966 
967  return nTri;
968 }
969 
970 
971 template<class Face>
973 {
975  {
976  // Inplace triangulation of triFace/labelledTri surface = no-op
977  return 0;
978  }
979  else
980  {
981  return triangulate
982  (
983  const_cast<labelList&>(labelList::null())
984  );
985  }
986 }
987 
988 
989 template<class Face>
991 (
992  labelList& faceMapOut
993 )
994 {
995  labelList dummyFaceMap;
996 
997  labelList& faceMap =
998  (
999  notNull(faceMapOut)
1000  ? faceMapOut
1001  : dummyFaceMap
1002  );
1003 
1005  {
1006  // Inplace triangulation of triFace/labelledTri surface = no-op
1007  faceMap.clear();
1008  return 0;
1009  }
1010 
1011  label nTri = 0;
1012  label maxTri = 0; // the maximum number of triangles for any single face
1013  List<Face>& faceLst = this->storedFaces();
1014 
1015  // How many triangles will be needed
1016  for (const auto& f : faceLst)
1017  {
1018  const label n = f.nTriangles();
1019  if (maxTri < n)
1020  {
1021  maxTri = n;
1022  }
1023  nTri += n;
1024  }
1025 
1026  // Nothing to do
1027  if (nTri <= faceLst.size())
1028  {
1029  faceMap.clear();
1030  return 0;
1031  }
1032 
1033  this->storedFaceIds().clear(); // Invalid or misleading
1034 
1035  List<Face> newFaces(nTri);
1036  faceMap.resize(nTri);
1037 
1038  if (this->points().empty())
1039  {
1040  // triangulate without points
1041  // simple face triangulation around f[0]
1042  nTri = 0;
1043  forAll(faceLst, facei)
1044  {
1045  const Face& f = faceLst[facei];
1046 
1047  for (label fp = 1; fp < f.size() - 1; ++fp)
1048  {
1049  const label fp1 = f.fcIndex(fp);
1050 
1051  newFaces[nTri] = Face{f[0], f[fp], f[fp1]};
1052  faceMap[nTri] = facei;
1053  ++nTri;
1054  }
1055  }
1056  }
1057  else
1058  {
1059  // triangulate with points
1060  List<face> tmpTri(maxTri);
1061 
1062  nTri = 0;
1063  forAll(faceLst, facei)
1064  {
1065  // 'face' not '<Face>'
1066  const face& f = faceLst[facei];
1067 
1068  label nTmp = 0;
1069  f.triangles(this->points(), nTmp, tmpTri);
1070  for (label triI = 0; triI < nTmp; triI++)
1071  {
1072  newFaces[nTri] = Face
1073  (
1074  static_cast<labelUList&>(tmpTri[triI])
1075  );
1076  faceMap[nTri] = facei;
1077  ++nTri;
1078  }
1079  }
1080  }
1081 
1082  // The number of *additional* faces
1083  nTri -= faceLst.size();
1084 
1085  faceLst.transfer(newFaces);
1086  remapFaces(faceMap);
1087 
1088  // Topology can change because of renumbering
1089  MeshReference::clearOut();
1090 
1091  return nTri;
1092 }
1093 
1094 
1095 template<class Face>
1098 (
1099  const labelList& pointMap,
1100  const labelList& faceMap
1101 ) const
1102 {
1103  const pointField& locPoints = this->localPoints();
1104  const List<Face>& locFaces = this->localFaces();
1105 
1106  // Subset of points (compact)
1107  pointField newPoints(UIndirectList<point>(locPoints, pointMap));
1108 
1109  // Inverse point mapping - same as ListOps invert() without checks
1110  labelList oldToNew(locPoints.size(), -1);
1111  forAll(pointMap, pointi)
1112  {
1113  oldToNew[pointMap[pointi]] = pointi;
1114  }
1115 
1116  // Subset of faces
1117  List<Face> newFaces(UIndirectList<Face>(locFaces, faceMap));
1118 
1119  // Renumber face node labels
1120  for (auto& f : newFaces)
1121  {
1122  for (label& vert : f)
1123  {
1124  vert = oldToNew[vert];
1125  }
1126  }
1127  oldToNew.clear();
1128 
1129  // Deep copy of zones, leave start/size intact!!
1130  surfZoneList newZones(zones_);
1131 
1132  // Recalculate the zone start/size
1133  label newFacei = 0;
1134  label origEndi = 0;
1135 
1136  for (surfZone& zone : newZones)
1137  {
1138  // The old zone ending
1139  origEndi += zone.size();
1140 
1141  // The new zone start
1142  zone.start() = newFacei;
1143 
1144  for (label facei = newFacei; facei < faceMap.size(); ++facei)
1145  {
1146  if (faceMap[facei] < origEndi)
1147  {
1148  ++newFacei;
1149  }
1150  else
1151  {
1152  break;
1153  }
1154  }
1155 
1156  // The new zone size
1157  zone.size() = newFacei - zone.start();
1158  }
1159 
1160 
1161  // Subset of faceIds. Can be empty.
1162  labelList newFaceIds;
1163  if (faceIds_.size())
1164  {
1165  newFaceIds = labelUIndList(faceIds_, faceMap);
1166  }
1167 
1168  // Construct the sub-surface
1169  MeshedSurface<Face> newSurf;
1170  newSurf.storedFaces().transfer(newFaces);
1171  newSurf.storedPoints().transfer(newPoints);
1172  newSurf.storedZones().transfer(newZones);
1173  newSurf.storedFaceIds().transfer(newFaceIds);
1174 
1175  return newSurf;
1176 }
1177 
1178 
1179 template<class Face>
1183  const UList<bool>& include,
1184  labelList& pointMap,
1186 ) const
1187 {
1188  this->subsetMeshMap(include, pointMap, faceMap);
1189  return this->subsetMeshImpl(pointMap, faceMap);
1190 }
1191 
1192 
1193 template<class Face>
1197  const bitSet& include,
1198  labelList& pointMap,
1200 ) const
1201 {
1202  this->subsetMeshMap(include, pointMap, faceMap);
1203  return this->subsetMeshImpl(pointMap, faceMap);
1204 }
1205 
1206 
1207 template<class Face>
1211  const UList<bool>& include
1212 ) const
1213 {
1214  labelList pointMap, faceMap;
1215  return this->subsetMesh(include, pointMap, faceMap);
1216 }
1217 
1218 
1219 template<class Face>
1223  const bitSet& include
1224 ) const
1225 {
1226  labelList pointMap, faceMap;
1227  return this->subsetMesh(include, pointMap, faceMap);
1228 }
1229 
1230 
1231 template<class Face>
1234  const wordRes& includeNames,
1235  const wordRes& excludeNames
1236 ) const
1237 {
1238  bitSet include(this->size());
1239 
1240  for
1241  (
1242  const label zonei
1243  : fileFormats::surfaceFormatsCore::getSelectedPatches
1244  (
1245  zones_,
1246  includeNames,
1247  excludeNames
1248  )
1249  )
1250  {
1251  include.set(zones_[zonei].range());
1252  }
1253 
1254  return this->subsetMesh(include);
1255 }
1256 
1257 
1258 template<class Face>
1261  MeshedSurface<Face>& surf
1262 )
1263 {
1264  if (this == &surf)
1265  {
1266  return; // Self-swap is a no-op
1267  }
1268 
1269  MeshReference::clearOut(); // Topology changes
1270  surf.clearOut(); // Topology changes
1271 
1272  this->storedPoints().swap(surf.storedPoints());
1273  this->storedFaces().swap(surf.storedFaces());
1274  this->storedZones().swap(surf.storedZones());
1275  this->storedFaceIds().swap(surf.storedFaceIds());
1276 }
1277 
1278 
1279 template<class Face>
1282  pointField& pointLst,
1283  List<Face>& faceLst
1284 )
1285 {
1286  MeshReference::clearOut(); // Topology changes
1287 
1288  this->storedPoints().transfer(pointLst);
1289  this->storedFaces().transfer(faceLst);
1290  this->storedZones().clear();
1291  this->storedFaceIds().clear(); // Likely to be invalid
1292 }
1293 
1294 
1295 template<class Face>
1298  MeshedSurface<Face>& surf
1299 )
1300 {
1301  if (this == &surf)
1302  {
1303  return; // Self-assigment is a no-op
1304  }
1305 
1306  MeshReference::clearOut(); // Topology changes
1307 
1308  this->storedPoints().transfer(surf.storedPoints());
1309  this->storedFaces().transfer(surf.storedFaces());
1310  this->storedZones().transfer(surf.storedZones());
1311  this->storedFaceIds().transfer(surf.storedFaceIds());
1312 
1313  surf.clear();
1314 }
1315 
1316 
1317 template<class Face>
1321 )
1322 {
1323  // Clear everything
1324  this->clear();
1325 
1327  surfZoneList zoneLst = surf.sortedZones(faceMap);
1328 
1329  List<Face>& faceLst = surf.storedFaces();
1330 
1331  if (zoneLst.size() > 1)
1332  {
1333  // Unknown if we really need to sort the faces
1334  List<Face> sortedFaces(faceMap.size());
1335 
1336  forAll(faceMap, facei)
1337  {
1338  sortedFaces[faceMap[facei]].transfer(faceLst[facei]);
1339  }
1340 
1341  faceLst.swap(sortedFaces); // Replace with sorted faces
1342  }
1343 
1344  MeshedSurface<Face> newSurf
1345  (
1346  std::move(surf.storedPoints()),
1347  std::move(faceLst),
1348  std::move(zoneLst)
1349  );
1350 
1351  surf.clear();
1352 
1353  this->swap(newSurf);
1354 }
1355 
1356 
1357 template<class Face>
1360 {
1361  return autoPtr<MeshedSurface<Face>>::New(std::move(*this));
1362 }
1363 
1364 
1365 template<class Face>
1367 {
1368  MeshReference::clearOut(); // Topology changes
1369 
1370  this->storedFaceIds().clear(); // Likely to be invalid
1371 
1372  this->storedFaces().swap(faces);
1373 }
1374 
1375 
1376 template<class Face>
1378 {
1379  MeshReference::clearOut(); // Topology changes
1380 
1381  this->storedPoints().swap(points);
1382 }
1383 
1384 
1385 template<class Face>
1387 {
1388  this->clear();
1389  transfer(*New(name));
1390  return true;
1391 }
1392 
1393 
1394 template<class Face>
1397  const fileName& name,
1398  const word& fileType
1399 )
1400 {
1401  this->clear();
1402  transfer(*New(name, fileType));
1403  return true;
1404 }
1405 
1406 
1407 template<class Face>
1410  const Time& t,
1411  const word& surfName
1412 ) const
1413 {
1414  MeshedSurfaceProxy<Face>(*this).write(t, surfName);
1415 }
1416 
1417 
1418 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1419 
1420 template<class Face>
1422 {
1423  if (this == &surf)
1424  {
1425  return; // Self-assignment is a no-op
1426  }
1427 
1428  // Clear everything
1429  this->clear();
1430 
1431  this->storedPoints() = surf.points();
1432  this->storedFaces() = surf.surfFaces();
1433  this->storedFaceIds() = surf.faceIds();
1434  this->storedZones() = surf.surfZones();
1435 }
1436 
1437 
1438 template<class Face>
1440 {
1441  transfer(surf);
1442 }
1443 
1444 
1445 template<class Face>
1447 {
1449  (
1450  this->points(),
1451  this->surfFaces(),
1452  this->surfZones(),
1453  labelUList::null(), // faceMap = none
1454  this->faceIds()
1455  );
1456 }
1457 
1458 
1459 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1460 
1461 #include "MeshedSurfaceZones.C"
1462 #include "MeshedSurfaceIO.C"
1463 #include "MeshedSurfaceNew.C"
1464 
1465 // ************************************************************************* //
Foam::MeshedSurface::faceIds
const labelList & faceIds() const
Return const access to faces ids.
Definition: MeshedSurface.H:419
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:71
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:104
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:325
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:427
Foam::MeshedSurface::~MeshedSurface
virtual ~MeshedSurface()
Destructor.
Definition: MeshedSurface.C:535
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:62
Foam::MeshedSurface::storedFaces
List< Face > & storedFaces()
Non-const access to the faces.
Definition: MeshedSurface.H:171
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::MeshedSurface::storedFaceIds
labelList & storedFaceIds()
Non-const access to face ids.
Definition: MeshedSurface.H:177
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:972
Foam::MeshedSurface::swap
void swap(MeshedSurface< Face > &surf)
Swap contents.
Definition: MeshedSurface.C:1260
Foam::MeshedSurface::storedPoints
pointField & storedPoints()
Non-const access to global points.
Definition: MeshedSurface.H:165
Foam::MeshedSurface::stitchFaces
virtual bool stitchFaces(const scalar tol=SMALL, const bool verbose=false)
Definition: MeshedSurface.C:650
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::MeshedSurface::operator=
void operator=(const MeshedSurface< Face > &surf)
Copy assignment.
Definition: MeshedSurface.C:1421
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:411
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:619
Foam::surfMesh
A surface mesh consisting of general polygon faces that has IO capabilities and a registry for storin...
Definition: surfMesh.H:63
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
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:594
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::HashSet< 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:745
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
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::MeshedSurface::storedZones
surfZoneList & storedZones()
Non-const access to the zones.
Definition: MeshedSurface.H:183
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:1281
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:365
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
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:459
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:912
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
MeshedSurfaceIO.C
Foam::List::resize
void resize(const label newSize)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
Foam::MeshedSurface::swapPoints
void swapPoints(pointField &points)
Swap the stored points.
Definition: MeshedSurface.C:1377
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:374
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:121
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:217
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:606
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
range
scalar range
Definition: LISASMDCalcMethod1.H:12
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:385
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:115
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:35
mergePoints.H
Merge points. See below.
Foam::wordHashSet
HashSet< word > wordHashSet
A HashSet with word keys.
Definition: HashSet.H:406
Foam::MeshedSurface::writeTypes
static wordHashSet writeTypes()
Known writable file-types, without friends or proxies.
Definition: MeshedSurface.C:52
Foam::UList::size
void size(const label n) noexcept
Override size to be inconsistent with allocated storage.
Definition: UListI.H:360
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::HashTable::found
bool found(const Key &key) const
Return true if hashed entry is found in table.
Definition: HashTableI.H:100
Foam::MeshedSurface::swapFaces
void swapFaces(List< Face > &faces)
Swap the stored faces. Use with caution.
Definition: MeshedSurface.C:1366
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:303
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:1182
Foam::MeshedSurface::remapFaces
virtual void remapFaces(const labelUList &faceMapNewToOld)
Set new zones from faceMap.
Definition: MeshedSurface.C:545
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:1359
Foam::MeshedSurface::cleanup
virtual void cleanup(const bool verbose)
Remove invalid faces.
Definition: MeshedSurface.C:638
MeshedSurface.H
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:85
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58