added: base class for texture based properties
This commit is contained in:
parent
914e3dfc19
commit
9606dea6db
128
src/Utility/TextureProperties.C
Normal file
128
src/Utility/TextureProperties.C
Normal file
@ -0,0 +1,128 @@
|
||||
// $Id$
|
||||
//==============================================================================
|
||||
//!
|
||||
//! \file TextureProperties.C
|
||||
//!
|
||||
//! \date Jan 3 2020
|
||||
//!
|
||||
//! \author Arne Morten Kvarving / SINTEF
|
||||
//!
|
||||
//! \brief Properties defined through a texture map.
|
||||
//!
|
||||
//==============================================================================
|
||||
|
||||
#include "TextureProperties.h"
|
||||
#include "IFEM.h"
|
||||
#include "HDF5Reader.h"
|
||||
#include "ProcessAdm.h"
|
||||
#include "Utilities.h"
|
||||
#include "Vec3.h"
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "StbImage.h"
|
||||
|
||||
|
||||
void TextureProperties::parse(const TiXmlElement* elem)
|
||||
{
|
||||
const TiXmlElement* child = elem->FirstChildElement("property");
|
||||
for (; child; child = child->NextSiblingElement()) {
|
||||
std::string prop;
|
||||
utl::getAttribute(child,"name",prop);
|
||||
if (prop.empty()) {
|
||||
std::cerr << "No name for property, skipping.." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string textureFile;
|
||||
utl::getAttribute(child, "file", textureFile);
|
||||
|
||||
if (textureFile.find(".h5") != std::string::npos ||
|
||||
textureFile.find(".hdf5") != std::string::npos) {
|
||||
properties[prop].prescaled = true;
|
||||
ProcessAdm adm;
|
||||
HDF5Reader reader(textureFile, adm);
|
||||
reader.read3DArray(prop, properties[prop].textureData);
|
||||
properties[prop].min = *std::min_element(properties[prop].textureData.begin(),
|
||||
properties[prop].textureData.end());
|
||||
properties[prop].max = *std::max_element(properties[prop].textureData.begin(),
|
||||
properties[prop].textureData.end());
|
||||
} else {
|
||||
int width, height, nrChannels;
|
||||
unsigned char* image = stb::loadImage(textureFile.c_str(),
|
||||
width, height, nrChannels);
|
||||
if (!image) {
|
||||
std::cerr << "File not found: " << textureFile << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
int nx, ny, nz;
|
||||
utl::getAttribute(child,"nx",nx);
|
||||
utl::getAttribute(child,"ny",ny);
|
||||
utl::getAttribute(child,"nz",nz);
|
||||
if (nx*ny*nz != width*height) {
|
||||
std::cerr << "Invalid dimensions specified " << nx << "x" << ny <<"x" << nz
|
||||
<< " image " << width << " " << height << std::endl;
|
||||
free(image);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nrChannels != 1) {
|
||||
std::cerr << "Expect a grayscale image" << std::endl;
|
||||
free(image);
|
||||
continue;
|
||||
}
|
||||
|
||||
properties[prop].textureData.resize(nx,ny,nz);
|
||||
const unsigned char* data = image;
|
||||
for (int i = 1; i <= nx; ++i)
|
||||
for (int j = 1; j <= ny; ++j)
|
||||
for (int k = 1; k <= nz; ++k)
|
||||
properties[prop].textureData(i,j,k) = double(*data++) / 255.0;
|
||||
|
||||
free(image);
|
||||
|
||||
utl::getAttribute(child,"min",properties[prop].min);
|
||||
utl::getAttribute(child,"max",properties[prop].max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureProperties::printLog() const
|
||||
{
|
||||
for (const auto& prop : properties)
|
||||
IFEM::cout << "\n\t\tProperty with name " << prop.first
|
||||
<< " (min = " << prop.second.min
|
||||
<< ", max = " << prop.second.max << ")";
|
||||
}
|
||||
|
||||
|
||||
bool TextureProperties::getProperty(const std::string& name,
|
||||
const Vec3& X, double& val) const
|
||||
{
|
||||
auto it = properties.find(name);
|
||||
if (it == properties.end())
|
||||
return false;
|
||||
|
||||
const Property& prop = it->second;
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TextureProperties::hasProperty(const std::string& name) const
|
||||
{
|
||||
return properties.find(name) != properties.end();
|
||||
}
|
85
src/Utility/TextureProperties.h
Normal file
85
src/Utility/TextureProperties.h
Normal file
@ -0,0 +1,85 @@
|
||||
// $Id$
|
||||
//==============================================================================
|
||||
//!
|
||||
//! \file TextureProperties.h
|
||||
//!
|
||||
//! \date Jan 3 2020
|
||||
//!
|
||||
//! \author Arne Morten Kvarving / SINTEF
|
||||
//!
|
||||
//! \brief Properties defined through a texture map.
|
||||
//!
|
||||
//==============================================================================
|
||||
|
||||
#ifndef TEXTURE_PROPERTIES_H_
|
||||
#define TEXTURE_PROPERTIES_H_
|
||||
|
||||
#include "Function.h"
|
||||
#include "MatVec.h"
|
||||
#include <map>
|
||||
|
||||
class TiXmlElement;
|
||||
class Vec3;
|
||||
|
||||
|
||||
//! \brief Class containing a set of properties defined through a texture map.
|
||||
class TextureProperties {
|
||||
public:
|
||||
//! \brief Parse an XML definition.
|
||||
//! param elem XML element to parse
|
||||
void parse (const TiXmlElement* elem);
|
||||
|
||||
//! \brief Print property information to log.
|
||||
void printLog() const;
|
||||
|
||||
//! \brief Get value for a 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, double& val) const;
|
||||
|
||||
//! \brief Check if a property is available.
|
||||
//! \param name Name of property
|
||||
bool hasProperty(const std::string& name) const;
|
||||
|
||||
protected:
|
||||
//! \brief Struct holding information about a property.
|
||||
struct Property {
|
||||
double min; //!< Minimum value
|
||||
double max; //!< Maximum value
|
||||
Matrix3D textureData; //!< Texture data
|
||||
bool prescaled = false; //!< True if data is already scaled
|
||||
};
|
||||
|
||||
std::map<std::string, Property> properties; //!< Map of available properties
|
||||
};
|
||||
|
||||
|
||||
//! \brief Class to use a property as a function.
|
||||
class PropertyFunc : public RealFunc {
|
||||
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)
|
||||
{}
|
||||
|
||||
//! \brief Empty destructor.
|
||||
virtual ~PropertyFunc() {}
|
||||
|
||||
//! \brief Evaluate function in a point.
|
||||
//! \param X Position to evaluate in
|
||||
double evaluate(const Vec3& X) const override
|
||||
{
|
||||
double val;
|
||||
m_props.getProperty(m_prop, X, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string m_prop; //!< Name of property
|
||||
const TextureProperties& m_props; //!< Texture properties container
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user