x3dSurfaceWriter.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) 2019-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "x3dSurfaceWriter.H"
29#include "OFstream.H"
30#include "OSspecific.H"
31#include "MeshedSurfaceProxy.H"
34
35// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36
37namespace Foam
38{
39namespace surfaceWriters
40{
44}
45}
46
47
48// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
49
50namespace Foam
51{
52
53//- A (0-1) range for colouring
54inline scalar srange01(const scalarMinMax& range, scalar x)
55{
56 if (x >= range.max())
57 {
58 return 1;
59 }
60
61 x -= range.min();
62
63 if (x < VSMALL)
64 {
65 return 0;
66 }
67
68 return x / (range.max() - range.min());
69}
70
71
72//- A (0-1) range for colouring
73template<class Type>
74static inline scalar rangex(const scalarMinMax& range, const Type& val)
75{
76 return srange01(range, Foam::mag(val));
77}
78
79
80//- A (0-1) range for colouring
81template<>
82inline scalar rangex(const scalarMinMax& range, const scalar& val)
83{
84 return srange01(range, val);
85}
86
87
88//- A (0-1) range for colouring
89template<>
90inline scalar rangex(const scalarMinMax& range, const label& val)
91{
92 return srange01(range, val);
93}
94
95
96static inline void printColour(Ostream& os, const vector& rgb)
97{
98 os << rgb[0] << ' ' << rgb[1] << ' ' << rgb[2] << ',' << nl;
99}
100
101} // End namespace Foam
102
103
104// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105
107:
109 streamOpt_(),
110 range_(),
111 colourTablePtr_(nullptr)
112{}
113
114
116(
117 const dictionary& options
118)
119:
120 surfaceWriter(options),
121 streamOpt_
122 (
123 IOstreamOption::ASCII,
124 IOstreamOption::compressionEnum("compression", options)
125 ),
126 range_(),
127 colourTablePtr_(nullptr)
128{
129 verbose_ = true;
130
131 options.readIfPresent("range", range_);
132
133 word tableName;
134 if (options.readIfPresent("colourMap", tableName))
135 {
136 colourTablePtr_ = colourTable::ptr(tableName);
137 if (!colourTablePtr_)
138 {
140 << "No colourMap " << tableName << " using default" << nl;
141 }
142 }
143
144 if (!colourTablePtr_)
145 {
147 colourTablePtr_ = colourTable::ptr(colourTable::COOL_WARM);
148 }
149
150 if (verbose_)
151 {
152 Info<< "X3D with colourMap '" << tableName << "' and range ";
153
154 if (range_.valid())
155 {
156 Info<< range_;
157 }
158 else
159 {
160 Info<< "auto";
161 }
162 Info<< nl;
163 }
164}
165
166
168(
169 const meshedSurf& surf,
170 const fileName& outputPath,
171 bool parallel,
172 const dictionary& options
173)
174:
175 x3dWriter(options)
176{
177 open(surf, outputPath, parallel);
178}
179
180
182(
183 const pointField& points,
184 const faceList& faces,
185 const fileName& outputPath,
186 bool parallel,
187 const dictionary& options
188)
189:
190 x3dWriter(options)
191{
192 open(points, faces, outputPath, parallel);
193}
194
195
196// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
197
199{
200 checkOpen();
201
202 // Geometry: rootdir/<TIME>/surfaceName.x3d
203
204 fileName outputFile = outputPath_;
205 if (useTimeDir() && !timeName().empty())
206 {
207 // Splice in time-directory
208 outputFile = outputPath_.path() / timeName() / outputPath_.name();
209 }
210 outputFile.ext("x3d");
211
212 if (verbose_)
213 {
214 Info<< "Writing geometry to " << outputFile << endl;
215 }
216
217 // const meshedSurf& surf = surface();
218 const meshedSurfRef& surf = adjustSurface();
219
220 if (Pstream::master() || !parallel_)
221 {
222 if (!isDir(outputFile.path()))
223 {
224 mkDir(outputFile.path());
225 }
226
228 (
229 outputFile,
230 "x3d",
231 streamOpt_
232 );
233 }
234
235 wroteGeom_ = true;
236 return outputFile;
237}
238
239
240// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
241
242template<class Type>
243Foam::fileName Foam::surfaceWriters::x3dWriter::writeTemplate
244(
245 const word& fieldName,
246 const Field<Type>& localValues
247)
248{
249 if (!colourTablePtr_)
250 {
251 // Write geometry only if there are no colours to use
253 << "No output colours set" << endl;
254
255 return this->write();
256 }
257
258 checkOpen();
259
260 // Field: rootdir/<TIME>/<field>_surfaceName.x3d
261
262 fileName outputFile = outputPath_.path();
263 if (useTimeDir() && !timeName().empty())
264 {
265 // Splice in time-directory
266 outputFile /= timeName();
267 }
268
269 // Append <field>_surfaceName.x3d
270 outputFile /= fieldName + '_' + outputPath_.name();
271 outputFile.ext("x3d");
272
273 // Implicit geometry merge()
274 tmp<Field<Type>> tfield = adjustField(fieldName, mergeField(localValues));
275
276 if (verbose_)
277 {
278 Info<< " to " << outputFile << endl;
279 }
280
281
282 // const meshedSurf& surf = surface();
283 const meshedSurfRef& surf = adjustSurface();
284
285 if (Pstream::master() || !parallel_)
286 {
287 const auto& values = tfield();
288
289 scalarMinMax range(range_);
290
291 if (!range.valid())
292 {
293 range = minMaxMag(values);
294
295 if (equal(range.mag(), 0))
296 {
297 range.add(range.centre());
298 }
299 }
300
301 // Slight rounding
302 range.min() -= VSMALL;
303 range.max() += VSMALL;
304
305 if (!isDir(outputFile.path()))
306 {
307 mkDir(outputFile.path());
308 }
309
310 OFstream os(outputFile, streamOpt_);
311
313 beginGroup(os);
314 writeAppearance(os);
315
316 // For point field: "colorPerVetex=true"
317 os << " <IndexedFaceSet"
318 << " colorPerVertex='" << Switch(this->isPointData()) << "'"
319 << " coordIndex='" << nl;
320
321 for (const auto& f : surf.faces())
322 {
323 for (const label vrti : f)
324 {
325 os << vrti << ' ';
326 }
327 os << "-1\n";
328 }
329 os << "'";
330
331 // Colour indices for face fields
332 if (!this->isPointData())
333 {
334 const label nFaces = surf.faces().size();
335
336 os << " colorIndex='";
337
338 for (label i=0; i < nFaces; ++i)
339 {
340 os << i << ' ';
341 }
342 os << "'";
343 }
344
345 os << " >\n"; // IndexedFaceSet
346
347 writePoints(os, surf.points());
348
349 os << "<Color color='" << nl;
350
351 // writeColours(os, values, range, colorBar);
352
353 for (const Type& val : values)
354 {
355 const scalar x = rangex(range, val);
356 vector rgb = colourTablePtr_->value(x);
357 printColour(os, rgb);
358 }
359
360 os << "' />" << nl; // Color
361
362 os <<
363 " </IndexedFaceSet>\n";
364
365 endGroup(os);
366 writeFooter(os);
367 }
368
369 wroteGeom_ = true;
370 return outputFile;
371}
372
373
374// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
375
376// Field writing methods
378
379
380// ************************************************************************* //
scalar range
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
The IOstreamOption is a simple container for options an IOstream can normally have.
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
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.
bool valid() const
Range is valid if it is not inverted.
Definition: MinMaxI.H:164
Output to file stream, using an OSstream.
Definition: OFstream.H:57
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:78
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static const Enum< predefinedType > predefinedNames
Enumeration names for predefinedType.
Definition: colourTable.H:108
@ COOL_WARM
"coolToWarm"
Definition: colourTable.H:95
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
A class for handling file names.
Definition: fileName.H:76
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:218
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
Implements a meshed surface by referencing another meshed surface or faces/points components.
Definition: meshedSurfRef.H:56
virtual const pointField & points() const
The points used for the surface.
virtual const faceList & faces() const
The faces used for the surface.
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:50
splitCell * master() const
Definition: splitCell.H:113
Base class for surface writers.
virtual void open(const fileName &outputPath)
Open for output on specified path, using existing surface.
bool verbose_
Additional output verbosity.
A surfaceWriter for X3D files.
virtual fileName write()
Write surface geometry to file.
A class for managing temporary objects.
Definition: tmp.H:65
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeName(Type)
Define the typeName.
Definition: className.H:96
OBJstream os(runTime.globalPath()/outputName)
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
const pointField & points
word timeName
Definition: getTimeIndex.H:3
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:515
static void printColour(Ostream &os, const vector &rgb)
static void writeHeader(Ostream &os, const word &fieldName)
messageStream Info
Information stream (stdout output on master, null elsewhere)
static scalar rangex(const scalarMinMax &range, const Type &val)
A (0-1) range for colouring.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
bool equal(const T &s1, const T &s2)
Compare two values for equality.
Definition: doubleFloat.H:46
scalar srange01(const scalarMinMax &range, scalar x)
A (0-1) range for colouring.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
dimensioned< scalarMinMax > minMaxMag(const DimensionedField< Type, GeoMesh > &df)
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:651
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
runTime write()
labelList f(nPoints)
Convenience macros for instantiating surfaceWriter methods.
#define defineSurfaceWriterWriteFields(ThisClass)