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:
parent
d8d4d40d8f
commit
107ecfeb5e
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user