42 namespace coordSetWriters
54 { fieldOption::UNIFORM,
"uniform" },
55 { fieldOption::FIELD,
"field" },
69 const scalar boundMin,
73 const label boundDelta = (boundMax - boundMin + ROOTVSMALL);
76 auto& result = tresult.ref();
80 const Type& val =
field[i];
90 result[i] = colours.
value((
f - boundMin)/boundDelta);
100 const dictionary&
dict,
101 const colourTable& colours,
102 const Field<Type>&
field 108 if (pTraits<Type>::nComponents == 1)
113 valLimits.min() = scalar(
component(scanned.min(), 0));
114 valLimits.max() = scalar(
component(scanned.max(), 0));
126 const scalar fraction =
128 (refValue - valLimits.min())
129 / (valLimits.max() - valLimits.min() + ROOTVSMALL)
133 return colours.value(fraction);
142 Foam::word Foam::coordSetWriters::gltfWriter::getColourMap
144 const dictionary&
dict 156 const dictionary&
dict 165 const word& fieldName
168 const dictionary fieldDict = fieldInfoDict_.subOrEmptyDict(fieldName);
172 fieldDict.readIfPresent(
"min", limits.min());
173 fieldDict.readIfPresent(
"max", limits.max());
180 Foam::coordSetWriters::gltfWriter::getAlphaField
182 const dictionary&
dict 186 scalar alphaValue(1);
194 else if (!eptr->stream().peek().isString())
198 ITstream& is = eptr->stream();
200 dict.checkITstream(is,
"alpha");
206 const auto option = fieldOptionNames_.get(
"alpha",
dict);
210 case fieldOption::NONE:
214 case fieldOption::UNIFORM:
216 dict.readEntry(
"alphaValue", alphaValue);
219 case fieldOption::FIELD:
222 <<
"Unsupported 'field' specification for alpha values" 233 void Foam::coordSetWriters::gltfWriter::setupAnimationColour()
235 const dictionary&
dict = animationDict_;
239 if (!eptr || !eptr->isStream())
242 <<
"Missing 'colour' entry" 245 else if (!eptr->stream().peek().isString())
249 ITstream& is = eptr->stream();
250 is >> animateColourValue_;
251 dict.checkITstream(is,
"colour");
254 animateColourOption_ = fieldOption::UNIFORM;
260 const auto option = fieldOptionNames_.get(
"colour",
dict);
264 case fieldOption::NONE:
267 <<
"Cannot select 'none' for colour entry!" <<
nl 268 <<
"... possible programming error" 272 case fieldOption::UNIFORM:
274 dict.readEntry(
"colourValue", animateColourValue_);
277 animateColourOption_ = fieldOption::UNIFORM;
280 case fieldOption::FIELD:
283 animateColourName_ =
dict.get<word>(
"colourField");
284 animateColourOption_ = fieldOption::FIELD;
300 animateColourOption_(fieldOption::NONE),
301 animateColourName_(),
302 animateColourValue_(
Zero),
312 animate_(options.getOrDefault(
"animate", false)),
313 colour_(options.getOrDefault(
"colour", false)),
314 animateColourOption_(fieldOption::NONE),
315 animateColourName_(),
316 animateColourValue_(
Zero),
317 fieldInfoDict_(options.subOrEmptyDict(
"fieldInfo")),
318 animationDict_(options.subOrEmptyDict(
"animationInfo"))
342 open(coords, outputPath);
355 open(tracks, outputPath);
374 return getExpectedPath(
"gltf");
380 writer_.reset(
nullptr);
387 writer_.reset(
nullptr);
394 writer_.reset(
nullptr);
401 writer_.reset(
nullptr);
411 const word& fieldName,
415 if (coords_.size() != fieldPtrs.size())
418 <<
"Attempted to write field: " << fieldName
419 <<
" (" << fieldPtrs.size() <<
" entries) for " 420 << coords_.size() <<
" sets" <<
nl 424 const auto& tracks = coords_;
438 auto& scene = writer_->getScene();
440 meshes_.resize(tracks.
size());
445 if (tracks.
size() == 1)
450 meshes_[tracki] = scene.addMesh(tracks[tracki], meshName);
455 auto& scene = writer_->getScene();
459 const label meshi = meshes_[tracki];
460 const auto&
field = fieldPtrs[tracki];
462 scene.addFieldToMesh(
field, fieldName, meshi);
466 const dictionary
dict = fieldInfoDict_.subOrEmptyDict(fieldName);
467 const auto& colours = getColourTable(
dict);
469 const auto talpha = getAlphaField(
dict);
472 const scalarMinMax valLimits = getFieldLimits(fieldName);
475 if (pTraits<Type>::nComponents == 1)
479 fldLimits.min() = scalar(
component(scanned.min(), 0));
480 fldLimits.max() = scalar(
component(scanned.max(), 0));
495 max(fldLimits.min(), valLimits.min()),
496 min(fldLimits.max(), valLimits.max())
500 scene.addColourToMesh
503 "Colour:" + fieldName,
510 return writer_().path();
515 Foam::fileName Foam::coordSetWriters::gltfWriter::writeTemplate_animate
517 const word& fieldName,
521 if (coords_.size() != fieldPtrs.size())
524 <<
"Attempted to write field: " << fieldName
525 <<
" (" << fieldPtrs.size() <<
" entries) for " 526 << coords_.size() <<
" sets" <<
nl 530 const auto& tracks = this->coords_;
531 const auto& times = this->trackTimes_;
543 auto& scene = writer_->getScene();
545 meshes_.resize(tracks.
size());
547 const label animationi = scene.createAnimation(
"animation");
551 const auto& track = tracks[tracki];
555 meshes_[tracki] = -1;
568 const label meshi = meshes_[tracki];
572 scene.addField(times[tracki],
"time:" +
Foam::name(tracki));
576 const label translationId =
577 scene.addField(translation,
"translation");
579 scene.addToAnimation(animationi, timeId, translationId, meshi);
584 auto& scene = writer_->getScene();
590 const auto& track = tracks[tracki];
591 const label meshi = meshes_[tracki];
592 const Field<Type>&
field = fieldPtrs[tracki];
594 if (track.empty() || meshi < 0)
600 scene.addFieldToMesh(Field<Type>(1,
field[0]), fieldName, meshi);
609 if (animateColourOption_ == fieldOption::NONE)
612 setupAnimationColour();
615 switch (animateColourOption_)
617 case fieldOption::NONE:
622 case fieldOption::UNIFORM:
629 const auto talpha = getAlphaField(animationDict_);
631 if (talpha && talpha().size())
633 alphaChannel[0] = talpha()[0];
638 const auto& track = tracks[tracki];
639 const label meshi = meshes_[tracki];
641 if (track.empty() || meshi < 0)
646 scene.addColourToMesh
656 animateColourName_.
clear();
657 animateColourOption_ = fieldOption::FIELD;
660 case fieldOption::FIELD:
664 !animateColourName_.empty()
665 && animateColourName_ == fieldName
670 const auto& colours = getColourTable(animationDict_);
675 const auto talpha = getAlphaField(animationDict_);
677 if (talpha && talpha().size())
679 alphaChannel[0] = talpha()[0];
684 const auto& track = tracks[tracki];
685 const label meshi = meshes_[tracki];
686 const Field<Type>&
field = fieldPtrs[tracki];
688 if (track.empty() || meshi < 0)
696 scene.addColourToMesh
706 animateColourName_.clear();
707 animateColourOption_ = fieldOption::FIELD;
714 return writer_().path();
721 const word& fieldName,
732 return writeTemplate(fieldName, fieldPtrs);
739 const word& fieldName,
751 if (animate_ && trackTimes_.size() >= coords_.size())
753 return writeTemplate_animate(fieldName, fieldPtrs);
756 return writeTemplate(fieldName, fieldPtrs);
Base class for generating a colour table from node points.
vector value(const scalar x) const
Return the colour at x. The input is clipped to 0-1 range.
A class for handling file names.
MinMax< scalar > scalarMinMax
A scalar min/max range.
static const Enum< predefinedType > predefinedNames
Enumeration names for predefinedType.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
constexpr char nl
The newline '\n' character (0x0a)
static const fileName null
An empty fileName.
static const Enum< fieldOption > fieldOptionNames_
Strings corresponding to the field options.
defineCoordSetWriterWriteFields(Foam::coordSetWriters::gltfWriter)
Ostream & endl(Ostream &os)
Add newline and flush stream.
A traits class, which is primarily used for primitives.
static tmp< vectorField > getBoundedColours(const colourTable &colours, const Field< Type > &field, const scalar boundMin, const scalar boundMax)
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
virtual void endTime()
End time step. Clears existing backend.
Macros for easy insertion into run-time selection tables.
gltfWriter()
Default construct.
virtual ~gltfWriter()
Destructor. Calls close()
static vector getAnimationColour(const dictionary &dict, const colourTable &colours, const Field< Type > &field)
MinMax< label > minMax(const labelHashSet &set)
Find the min/max values of labelHashSet.
#define forAll(list, i)
Loop across all elements in list.
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
virtual void beginTime(const Time &t)
Begin a time-step.
Convenience macros for instantiating coordSetWriter methods.
Holds list of sampling positions.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Generic templated field type.
A class for handling words, derived from Foam::string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
label size() const noexcept
The number of entries in the list.
defineTypeName(csvWriter)
Wrapper for glTF scene for file output.
Base class for writing coordSet(s) and tracks with fields.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
virtual void beginTime(const Time &t)
Begin time step. Clears existing backend.
const List< word > & names() const noexcept
The list of enum names, in construction order. Same as toc()
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
virtual fileName path() const
Expected (characteristic) output file name - information only.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
virtual void endTime()
End a time-step.
virtual void close(bool force=false)
Close and reset, clears backend.
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
addToRunTimeSelectionTable(coordSetWriter, csvWriter, word)
A coordSet(s) writer in glTF v2 format, which is particularly useful for writing track data...
static const colourTable & ref(const word &tableName)
Look up pointer to colourTable by name. Fatal on failure.
dimensioned< scalarMinMax > minMaxMag(const DimensionedField< Type, GeoMesh > &f1)
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Field< vector > vectorField
Specialisation of Field<T> for vector.
void clear()
Set list size to zero.
A class for managing temporary objects.
virtual void close(bool force=false)
Finish output, performing any necessary cleanup.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0)