VTKsurfaceFormat.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-------------------------------------------------------------------------------
11License
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 "VTKsurfaceFormat.H"
31#include "labelIOField.H"
32#include "scalarIOField.H"
33#include "faceTraits.H"
34#include <fstream>
35
36// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37
38template<class Face>
40(
41 vtk::formatter& format,
42 const UList<Face>& faces
43)
44{
45 // connectivity count without additional storage (done internally)
46 label nConnectivity = 0;
47 for (const Face& f : faces)
48 {
49 nConnectivity += f.size();
50 }
51
52 vtk::legacy::beginPolys
53 (
54 format.os(),
55 faces.size(),
56 nConnectivity
57 );
58
59
60 // legacy: size + connectivity together
61 // [nPts, id1, id2, ..., nPts, id1, id2, ...]
62
63 for (const Face& f : faces)
64 {
65 format.write(f.size()); // The size prefix
66 vtk::writeList(format, f);
67 }
68
69 format.flush();
70}
71
72
73// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
74
75template<class Face>
77(
78 const fileName& filename
79)
80{
81 read(filename);
82}
83
84
85// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
86
87template<class Face>
89(
90 const fileName& filename
91)
92{
93 // Clear everything
94 this->clear();
95
96 IFstream is(filename);
97 if (!is.good())
98 {
100 << "Cannot read file " << filename << nl
101 << exit(FatalError);
102 }
103
104 // Assume groups are not intermixed
105 bool sorted = true;
106
107
108 // Use dummy Time for objectRegistry
109 autoPtr<Time> dummyTimePtr(Time::New());
110
112 (
114 (
115 "vtk::surfaceFormat",
116 *dummyTimePtr,
117 IOobject::NO_READ,
118 IOobject::NO_WRITE,
119 false
120 )
121 );
122
123 // Read all
124 vtkUnstructuredReader reader(obr, is);
125 const faceList& faces = reader.faces();
126
127 // Assume all faces in zone0 unless a region field is present
128 labelList zones(faces.size(), Zero);
129
130 for (auto fieldName : { "region", "STLSolidLabeling" })
131 {
132 const labelIOField* lptr =
133 reader.cellData().findObject<labelIOField>(fieldName);
134
135 if (lptr)
136 {
137 label i = 0;
138 for (const auto& region : *lptr)
139 {
140 zones[i++] = label(region);
141 }
142 break;
143 }
144
145 const scalarIOField* sptr =
146 reader.cellData().findObject<scalarIOField>(fieldName);
147
148 if (sptr)
149 {
150 label i = 0;
151 for (const auto& region : *sptr)
152 {
153 zones[i++] = label(region);
154 }
155 break;
156 }
157 }
158
159
160 // Create zone names
161 const label nZones = max(zones)+1;
162 wordList zoneNames(nZones);
163 forAll(zoneNames, i)
164 {
165 zoneNames[i] = surfZone::defaultName(i);
166 }
167
168
169 // Check if it needs triangulation
170 label nTri = 0;
172 {
173 for (const face& f : faces)
174 {
175 nTri += f.nTriangles();
176 }
177 }
178
179 DynamicList<label> dynElemId; // unused
180
181 if (nTri > faces.size())
182 {
183 // We are here if the target surface needs triangles and
184 // the source surface has non-triangles
185
186 DynamicList<Face> dynFaces(nTri);
187 DynamicList<label> dynZones(nTri);
188
189 forAll(faces, facei)
190 {
191 const face& f = faces[facei];
192 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
193 {
194 const label fp2 = f.fcIndex(fp1);
195
196 dynFaces.append(Face{f[0], f[fp1], f[fp2]});
197 dynZones.append(zones[facei]);
198 }
199 }
200 zones.clear();
201
202 // Count
203 labelList zoneSizes(nZones, Zero);
204 for (const label zonei : dynZones)
205 {
206 zoneSizes[zonei]++;
207 }
208
209 this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted);
210
211 // Add zones (retaining empty ones)
212 this->addZones(zoneSizes, zoneNames);
213 }
214 else
215 {
216 DynamicList<Face> dynFaces(faces.size());
217 DynamicList<label> dynZones(std::move(zones));
218
219 for (const face& f : faces)
220 {
221 dynFaces.append(Face(f));
222 }
223
224 // Count
225 labelList zoneSizes(nZones, Zero);
226 for (const label zonei : dynZones)
227 {
228 zoneSizes[zonei]++;
229 }
230
231 this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted);
232
233 // Add zones (retaining empty ones)
234 this->addZones(zoneSizes, zoneNames);
235 }
236 this->addZonesToFaces(); // for labelledTri
237
238 // transfer to normal lists
239 this->storedPoints().transfer(reader.points());
240
241 return true;
242}
243
244
245template<class Face>
247(
248 const fileName& filename,
249 const MeshedSurfaceProxy<Face>& surf,
251 const dictionary& options
252)
253{
254 const UList<point>& pointLst = surf.points();
255 const UList<Face>& faceLst = surf.surfFaces();
256 const UList<label>& faceMap = surf.faceMap();
257
258 const surfZoneList zones =
259 (
260 surf.surfZones().empty()
261 ? surfaceFormatsCore::oneZone(faceLst)
262 : surf.surfZones()
263 );
264
265 const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
266
267 vtk::outputOptions opts = formatOptions(options);
268
269 std::ofstream os(filename, std::ios::binary);
270
272
273 writeHeader(format(), pointLst);
274
275 if (useFaceMap)
276 {
277 // connectivity count without additional storage (done internally)
278 label nConnectivity = 0;
279 for (const Face& f : faceLst)
280 {
281 nConnectivity += f.size();
282 }
283
284 vtk::legacy::beginPolys
285 (
286 format().os(),
287 faceLst.size(),
288 nConnectivity
289 );
290
291 label faceIndex = 0;
292 for (const surfZone& zone : zones)
293 {
294 forAll(zone, i)
295 {
296 const Face& f = faceLst[faceMap[faceIndex++]];
297
298 format().write(f.size()); // The size prefix
299 vtk::writeList(format(), f);
300 }
301 }
302
303 format().flush();
304 }
305 else
306 {
307 // Easy to write polys without a faceMap
308 writePolys(format(), faceLst);
309 }
310
311 // Write regions (zones) as CellData
312 if (zones.size() > 1)
313 {
314 writeCellData(format(), zones);
315 }
316}
317
318
319template<class Face>
321(
322 const fileName& filename,
323 const UnsortedMeshedSurface<Face>& surf,
325 const dictionary& options
326)
327{
328 vtk::outputOptions opts = formatOptions(options);
329
330 std::ofstream os(filename, std::ios::binary);
331
333
334 writeHeader(format(), surf.points());
335
336 // Easy to write polys without a faceMap
337 writePolys(format(), surf.surfFaces());
338
339 // Write regions (zones) as CellData
340 writeCellData(format(), surf.zoneIds());
341}
342
343
344// ************************************************************************* //
Y[inertIndex] max(0.0)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
Input from file stream, using an ISstream.
Definition: IFstream.H:57
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
The IOstreamOption is a simple container for options an IOstream can normally have.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const UList< surfZone > & surfZones() const
Const access to the surface zones.
const UList< Face > & surfFaces() const
Return const access to the faces.
bool useFaceMap() const
Can/should use faceMap?
const pointField & points() const
Return const access to the points.
const labelUList & faceMap() const
Const access to the faceMap, zero-sized when unused.
const List< Face > & surfFaces() const
Return const access to the faces.
const Field< point_type > & points() const noexcept
Return reference to global points.
virtual bool read()
Re-read model coefficients if they have changed.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
virtual const labelList & zoneIds() const
Return const access to the zone ids.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Traits class for faces.
Definition: faceTraits.H:51
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Read/write VTK legacy format (ASCII) for surfaces.
A class for handling file names.
Definition: fileName.H:76
virtual bool write()
Write the output fields.
Registry of regIOobjects.
const Type * findObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
A surface zone on a MeshedSurface.
Definition: surfZone.H:59
Reader for vtk UNSTRUCTURED_GRID legacy files. Supports single CELLS, POINTS etc. entry only.
const faceList & faces() const noexcept
2D cells (=faces)
const objectRegistry & cellData() const noexcept
Cell based fields.
const pointField & points() const noexcept
Points.
Encapsulated combinations of output format options. This is primarily useful when defining the output...
autoPtr< formatter > newFormatter(std::ostream &os) const
Return new formatter based on the selected output options.
Base class for mesh zones.
Definition: zone.H:67
patchWriters clear()
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
label nZones
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
const dictionary formatOptions(propsDict.subOrEmptyDict("formatOptions", keyType::LITERAL))