VTKsurfaceFormat.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "VTKsurfaceFormat.H"
27 #include "vtkUnstructuredReader.H"
28 #include "scalarIOField.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 template<class Face>
34 (
35  Ostream& os,
36  const UList<Face>& faceLst
37 )
38 {
39  label nNodes = 0;
40 
41  forAll(faceLst, facei)
42  {
43  nNodes += faceLst[facei].size();
44  }
45 
46  os << nl
47  << "POLYGONS " << faceLst.size() << ' '
48  << faceLst.size() + nNodes << nl;
49 }
50 
51 
52 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
53 
54 template<class Face>
56 (
57  const fileName& filename
58 )
59 {
60  read(filename);
61 }
62 
63 
64 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
65 
66 template<class Face>
68 (
69  const fileName& filename
70 )
71 {
72  const bool mustTriangulate = this->isTri();
73  this->clear();
74 
75  IFstream is(filename);
76  if (!is.good())
77  {
79  << "Cannot read file " << filename
80  << exit(FatalError);
81  }
82 
83  // assume that the groups are not intermixed
84  bool sorted = true;
85 
86 
87  // Construct dummy time so we have something to create an objectRegistry
88  // from
89  Time dummyTime
90  (
91  "dummyRoot",
92  "dummyCase",
93  false // enableFunctionObjects
94  );
95 
96  // Make dummy object registry
97  objectRegistry obr
98  (
99  IOobject
100  (
101  "dummy",
102  dummyTime,
103  IOobject::NO_READ,
104  IOobject::NO_WRITE,
105  false
106  )
107  );
108 
109  // Read all
110  vtkUnstructuredReader reader(obr, is);
111  const faceList& faces = reader.faces();
112 
113  // Assume all faces in zone0 unless a region field is present
114  labelList zones(faces.size(), 0);
115  if (reader.cellData().foundObject<scalarIOField>("region"))
116  {
117  const scalarIOField& region =
119  (
120  "region"
121  );
122  forAll(region, i)
123  {
124  zones[i] = label(region[i]);
125  }
126  }
127  else if (reader.cellData().foundObject<scalarIOField>("STLSolidLabeling"))
128  {
129  const scalarIOField& region =
131  (
132  "STLSolidLabeling"
133  );
134  forAll(region, i)
135  {
136  zones[i] = label(region[i]);
137  }
138  }
139 
140  // Create zone names
141  const label nZones = max(zones)+1;
142  wordList zoneNames(nZones);
143  forAll(zoneNames, i)
144  {
145  zoneNames[i] = "zone" + Foam::name(i);
146  }
147 
148 
149  // See if needs triangulation
150  label nTri = 0;
151  if (mustTriangulate)
152  {
153  forAll(faces, facei)
154  {
155  nTri += faces[facei].size()-2;
156  }
157  }
158 
159  if (nTri > 0)
160  {
161  DynamicList<Face> dynFaces(nTri);
162  DynamicList<label> dynZones(nTri);
163  forAll(faces, facei)
164  {
165  const face& f = faces[facei];
166  for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
167  {
168  label fp2 = f.fcIndex(fp1);
169 
170  dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
171  dynZones.append(zones[facei]);
172  }
173  }
174 
175  // Count
176  labelList zoneSizes(nZones, 0);
177  forAll(dynZones, triI)
178  {
179  zoneSizes[dynZones[triI]]++;
180  }
181 
182  this->sortFacesAndStore(move(dynFaces), move(dynZones), sorted);
183 
184  // add zones, culling empty ones
185  this->addZones(zoneSizes, zoneNames, true);
186  }
187  else
188  {
189  DynamicList<Face> dynFaces(faces.size());
190  forAll(faces, facei)
191  {
192  const face& f = faces[facei];
193  dynFaces.append(Face(f));
194  }
195 
196  // Count
197  labelList zoneSizes(nZones, 0);
198  forAll(zones, facei)
199  {
200  zoneSizes[zones[facei]]++;
201  }
202 
203  this->sortFacesAndStore(move(dynFaces), move(zones), sorted);
204 
205  // add zones, culling empty ones
206  this->addZones(zoneSizes, zoneNames, true);
207  }
208 
209  // transfer to normal lists
210  this->storedPoints().transfer(reader.points());
211 
212  return true;
213 }
214 
215 
216 template<class Face>
218 (
219  const fileName& filename,
220  const MeshedSurfaceProxy<Face>& surf
221 )
222 {
223  const pointField& pointLst = surf.points();
224  const List<Face>& faceLst = surf.faces();
225  const List<label>& faceMap = surf.faceMap();
226 
227  const List<surfZone>& zones =
228  (
229  surf.surfZones().empty()
230  ? surfaceFormatsCore::oneZone(faceLst)
231  : surf.surfZones()
232  );
233 
234  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
235 
236  OFstream os(filename);
237  if (!os.good())
238  {
240  << "Cannot open file for writing " << filename
241  << exit(FatalError);
242  }
243 
244 
245  writeHeader(os, pointLst);
246  writeHeaderPolygons(os, faceLst);
247 
248  label faceIndex = 0;
249  forAll(zones, zoneI)
250  {
251  const surfZone& zone = zones[zoneI];
252 
253  if (useFaceMap)
254  {
255  forAll(zone, localFacei)
256  {
257  const Face& f = faceLst[faceMap[faceIndex++]];
258 
259  os << f.size();
260  forAll(f, fp)
261  {
262  os << ' ' << f[fp];
263  }
264  os << ' ' << nl;
265  }
266  }
267  else
268  {
269  forAll(zone, localFacei)
270  {
271  const Face& f = faceLst[faceIndex++];
272 
273  os << f.size();
274  forAll(f, fp)
275  {
276  os << ' ' << f[fp];
277  }
278  os << ' ' << nl;
279  }
280  }
281  }
282 
283  writeTail(os, zones);
284 }
285 
286 
287 template<class Face>
289 (
290  const fileName& filename,
291  const UnsortedMeshedSurface<Face>& surf
292 )
293 {
294  OFstream os(filename);
295  if (!os.good())
296  {
298  << "Cannot open file for writing " << filename
299  << exit(FatalError);
300  }
301 
302 
303  const List<Face>& faceLst = surf.faces();
304 
305  writeHeader(os, surf.points());
306  writeHeaderPolygons(os, faceLst);
307 
308  forAll(faceLst, facei)
309  {
310  const Face& f = faceLst[facei];
311 
312  os << f.size();
313  forAll(f, fp)
314  {
315  os << ' ' << f[fp];
316  }
317  os << ' ' << nl;
318  }
319 
320  writeTail(os, surf.zoneIds());
321 }
322 
323 
324 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
Input from file stream.
Definition: IFstream.H:85
A primitive field of type <Type> with automated input and output.
Definition: IOField.H:53
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const List< surfZone > & surfZones() const
Const access to the surface zones.
const List< Face > & faces() const
Return const access to the faces.
bool useFaceMap() const
Use faceMap?
const List< label > & faceMap() const
Const access to the faceMap, zero-sized when unused.
const pointField & points() const
Return const access to the points.
const List< Face > & faces() const
Return const access to the faces.
Output to file stream.
Definition: OFstream.H:86
const Field< PointType > & points() const
Return reference to global points.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
const List< label > & zoneIds() const
Return const access to the zone ids.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Provide a means of reading/writing VTK legacy format. The output is never sorted by zone.
static void write(const fileName &, const MeshedSurfaceProxy< Face > &)
Write surface mesh components by proxy.
virtual bool read(const fileName &)
Read from file.
VTKsurfaceFormat(const fileName &)
Construct from file name.
A class for handling file names.
Definition: fileName.H:82
Registry of regIOobjects.
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
bool foundObject(const word &name) const
Is the named Type in registry.
A surface zone on a MeshedSurface.
Definition: surfZone.H:65
Reader for vtk unstructured_grid legacy files. Supports single CELLS, POINTS etc. entry only.
const objectRegistry & cellData() const
Cell based fields.
const faceList & faces() const
2D cells (=faces)
const pointField & points() const
Points.
Base class for zones.
Definition: zone.H:60
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
tUEqn clear()
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
void writeHeader(std::ostream &, const bool isBinary, const std::string &title)
Write header.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
error FatalError
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static const char nl
Definition: Ostream.H:260
face triFace(3)
labelList f(nPoints)