From 107ecfeb5e9172a57e8370e6c9da5403e1e316e0 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Fri, 12 Nov 2021 15:23:01 +0100 Subject: [PATCH] added: allow for defining a function for textureproperties this allows for a generic f(texture(X)) where f can be scalar or vector valued. ideally f would be a function of property name but as we do not have a base class for f: R -> R^3 we have to use the f: R^3 -> R^3 type for vector functions. for this reason, both scalar and vectorial functions have to refer to the texture value as 'x'. --- src/Utility/TextureProperties.C | 72 ++++++++++++++++++++++++++++----- src/Utility/TextureProperties.h | 35 +++++++++++----- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/Utility/TextureProperties.C b/src/Utility/TextureProperties.C index caf4de675..f35eee872 100644 --- a/src/Utility/TextureProperties.C +++ b/src/Utility/TextureProperties.C @@ -13,6 +13,7 @@ #include "TextureProperties.h" #include "IFEM.h" +#include "Functions.h" #include "HDF5Reader.h" #include "ProcessAdm.h" #include "Utilities.h" @@ -33,8 +34,11 @@ void TextureProperties::parse(const TiXmlElement* elem) continue; } - std::string textureFile; + std::string textureFile, function; utl::getAttribute(child, "file", textureFile); + utl::getAttribute(child, "function", function); + int comp = 1; + utl::getAttribute(child,"comp",comp); if (textureFile.find(".h5") != std::string::npos || textureFile.find(".hdf5") != std::string::npos) { @@ -73,6 +77,17 @@ void TextureProperties::parse(const TiXmlElement* elem) } properties[prop].textureData.resize(nx,ny,nz); + if (!function.empty()) { + properties[prop].func_definition = function; + FunctionBase* func; + if (comp == 1) + func = utl::parseRealFunc(function.c_str()); + else + func = utl::parseVecFunc(function.c_str()); + + properties[prop].function.reset(func); + } + const unsigned char* data = image; for (int i = 1; i <= nx; ++i) for (int j = 1; j <= ny; ++j) @@ -89,10 +104,13 @@ void TextureProperties::parse(const TiXmlElement* elem) void TextureProperties::printLog() const { - for (const auto& prop : properties) + for (const auto& prop : properties) { IFEM::cout << "\n\t\tProperty with name " << prop.first << " (min = " << prop.second.min << ", max = " << prop.second.max << ")"; + if (!prop.second.func_definition.empty()) + IFEM::cout << "\n\t\t\tfunction = " << prop.second.func_definition; + } } @@ -104,19 +122,33 @@ bool TextureProperties::getProperty(const std::string& name, return false; const Property& prop = it->second; + val = this->getValue(prop, X); - const Vec4* X4 = static_cast(&X); - if (!X4) + if (prop.function) { + Vec3 f; + f.x = val; + val = prop.function->getValue(f).front(); + } + + return true; +} + +bool TextureProperties::getProperty(const std::string& name, + const Vec3& X, Vec3& val) const +{ + auto it = properties.find(name); + if (it == properties.end()) return false; - int i = std::round(X4->u[0]*(prop.textureData.dim(1)-1)); - int j = std::round(X4->u[1]*(prop.textureData.dim(2)-1)); - int k = std::round(X4->u[2]*(prop.textureData.dim(3)-1)); + const Property& prop = it->second; + double value = this->getValue(prop, X); - if (prop.prescaled) - val = prop.textureData(i+1,j+1,k+1); - else - val = prop.min + (prop.max-prop.min) * prop.textureData(i+1,j+1,k+1); + if (prop.function) { + Vec3 f; + f.x = value; + val = prop.function->getValue(f); + } else + val = value; return true; } @@ -126,3 +158,21 @@ bool TextureProperties::hasProperty(const std::string& name) const { return properties.find(name) != properties.end(); } + + +double TextureProperties::getValue(const Property& prop, const Vec3& X) const +{ + const Vec4* X4 = static_cast(&X); + if (!X4) + return false; + + int i = std::round(X4->u[0]*(prop.textureData.dim(1)-1)); + int j = std::round(X4->u[1]*(prop.textureData.dim(2)-1)); + int k = std::round(X4->u[2]*(prop.textureData.dim(3)-1)); + + if (prop.prescaled) + return prop.textureData(i+1,j+1,k+1); + else + return prop.min + (prop.max-prop.min) * prop.textureData(i+1,j+1,k+1); + +} diff --git a/src/Utility/TextureProperties.h b/src/Utility/TextureProperties.h index 0809675ee..8076192fc 100644 --- a/src/Utility/TextureProperties.h +++ b/src/Utility/TextureProperties.h @@ -16,7 +16,9 @@ #include "Function.h" #include "MatVec.h" + #include +#include class TiXmlElement; class Vec3; @@ -38,6 +40,12 @@ class TextureProperties { //! \param[out] val Property value bool getProperty(const std::string& name, const Vec3& X, double& val) const; + //! \brief Get value for a vector property + //! \param[in] name Name of property + //! \param[in] X Position (including parameter values) to evaluate property for + //! \param[out] val Property value + bool getProperty(const std::string& name, const Vec3& X, Vec3& val) const; + //! \brief Check if a property is available. //! \param name Name of property bool hasProperty(const std::string& name) const; @@ -45,34 +53,39 @@ class TextureProperties { protected: //! \brief Struct holding information about a property. struct Property { - double min; //!< Minimum value - double max; //!< Maximum value + double min = 0.0; //!< Minimum value + double max = 1.0; //!< Maximum value Matrix3D textureData; //!< Texture data bool prescaled = false; //!< True if data is already scaled + std::string func_definition; //!< Non-empty if we have a function of the texture value + std::unique_ptr function; //!< Function definition for property (if any) }; + //! \brief Obtains texture value for a property. + double getValue(const Property& prop, const Vec3& X) const; + std::map properties; //!< Map of available properties }; //! \brief Class to use a property as a function. -class PropertyFunc : public RealFunc { +template +class PropertyFuncType : public Base { public: //! \brief Constructor initializes the members. //! \param prop Name of property //! \param props Texture property container - PropertyFunc(const std::string& prop, const TextureProperties& props) - : m_prop(prop), m_props(props) - {} + PropertyFuncType(const std::string& prop, const TextureProperties& props) : + m_prop(prop), m_props(props) {} //! \brief Empty destructor. - virtual ~PropertyFunc() {} + virtual ~PropertyFuncType() {} //! \brief Evaluate function in a point. //! \param X Position to evaluate in - double evaluate(const Vec3& X) const override + Value evaluate(const Vec3& X) const override { - double val; + Value val; m_props.getProperty(m_prop, X, val); return val; } @@ -82,4 +95,8 @@ class PropertyFunc : public RealFunc { const TextureProperties& m_props; //!< Texture properties container }; + +using PropertyFunc = PropertyFuncType; //!< Convenience type alias for scalars +using PropertyVecFunc = PropertyFuncType; //!< Convenience type alias for vector + #endif