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'.
This commit is contained in:
Arne Morten Kvarving 2021-11-12 15:23:01 +01:00
parent d8d4d40d8f
commit 107ecfeb5e
2 changed files with 87 additions and 20 deletions

View File

@ -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<const Vec4*>(&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<const Vec4*>(&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);
}

View File

@ -16,7 +16,9 @@
#include "Function.h"
#include "MatVec.h"
#include <map>
#include <memory>
class TiXmlElement;
class Vec3;
@ -38,6 +40,12 @@ public:
//! \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 @@ public:
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<FunctionBase> 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<std::string, Property> properties; //!< Map of available properties
};
//! \brief Class to use a property as a function.
class PropertyFunc : public RealFunc {
template<class Base, class Value>
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 @@ protected:
const TextureProperties& m_props; //!< Texture properties container
};
using PropertyFunc = PropertyFuncType<RealFunc,Real>; //!< Convenience type alias for scalars
using PropertyVecFunc = PropertyFuncType<VecFunc,Vec3>; //!< Convenience type alias for vector
#endif