Commit f4abd44d authored by Ludovic Courtès's avatar Ludovic Courtès

core: 'load' is no longer a method of 'data'.

Instead, plugins must provide a 'load_data' function (with C linkage)
that 'plugins_manager::load_data' calls.
parent 486221c6
......@@ -24,11 +24,6 @@
#include "ptr.h"
//namespace alta {
// class data;
//}
//void load_data_from_binary(std::istream& in, const alta::arguments& header, alta::data& data);
namespace alta {
/*! \brief A data object. Allows to load data from files.
......@@ -53,10 +48,6 @@ class data
// Virtual destructor
virtual ~data() {}
// Load data from an input stream.
virtual void load(std::istream& input,
const arguments& args = arguments()) = 0;
// Save the data to a file
virtual void save(const std::string& filename) const;
......@@ -167,12 +158,6 @@ class data_params : public data
NOT_IMPLEMENTED();
}
virtual void load(std::istream&, const arguments&)
{
std::cerr << "<<ERROR>> this data type cannot load data" << std::endl;
throw;
}
// Acces to data
virtual vec get(int i) const
{
......
......@@ -470,8 +470,34 @@ ptr<data> plugins_manager::get_data(const std::string& n, const arguments& args)
ptr<data> plugins_manager::load_data(const std::string& type, std::istream& input,
const arguments& args)
{
ptr<data> result = get_data(type, args);
if (result) result->load(input, args);
ptr<data> result;
if (type.empty() || type == "vertical_segment")
{
auto header = arguments::parse_header(input);
auto vs = new vertical_segment();
if(!header.is_defined("FORMAT")) {
std::cerr << "<<DEBUG>> The file format is undefined, assuming TEXT"
<< std::endl;
}
if (header["FORMAT"] == "binary") {
load_data_from_binary(input, header, *vs);
} else {
// FIXME: ARGS is currently ignored.
load_data_from_text(input, header, *vs);
}
result = ptr<data>(vs);
}
else
{
LoadDataPrototype load;
load = open_library<LoadDataPrototype>(type, "load_data");
if (load != NULL) result = ptr<data>(load(input, args));
}
return result;
}
......
......@@ -90,5 +90,7 @@ class plugins_manager
typedef function* (*FunctionPrototype)(const parameters&);
typedef fitter* (*FitterPrototype)();
typedef data* (*DataPrototype)(const arguments&);
typedef data* (*LoadDataPrototype)(std::istream& input,
const arguments&);
};
}
......@@ -23,6 +23,12 @@ using namespace alta;
//#define RELATIVE_ERROR
vertical_segment::vertical_segment(const parameters& params,
std::vector<vec>&& input_data)
: data(params), _data(input_data), _is_absolute(true), _dt(0.1)
{
}
vertical_segment::vertical_segment(const parameters& params, unsigned int size):
data(params), _is_absolute(true), _dt(0.1)
{
......@@ -59,26 +65,6 @@ vertical_segment::initializeToZero( unsigned int number_of_data_elements )
}
}
void vertical_segment::load(std::istream& input, const arguments& args)
{
arguments header = arguments::parse_header(input);
// Default behaviour: parsing a file as TEXT file. Send a message error in case
// the user did not set it.
if(! header.is_defined("FORMAT")) {
std::cerr << "<<DEBUG>> The file format is undefined, assuming TEXT" << std::endl;
}
if (header["FORMAT"] == "binary") {
load_data_from_binary(input, header, *this);
} else {
// FIXME: ARGS is currently ignored.
load_data_from_text(input, header, *this);
}
}
void vertical_segment::get(int i, vec& x, vec& yl, vec& yu) const
{
#ifdef DEBUG
......
......@@ -80,6 +80,9 @@ class vertical_segment : public data
{
public: // methods
vertical_segment(const parameters& params,
std::vector<vec>&& data);
vertical_segment(const parameters& params, unsigned int size);
//! \brief Default constructor that does nothing at all.
......@@ -93,20 +96,6 @@ class vertical_segment : public data
params::output out_param,
unsigned int size );
//! \brief Load data from a stream using the command line arguments.
//!
//! \details
//! Specific arguments for the vertical segment data
//! --dt specify a value for the absolute/relative segment if not defined
//! in the data
//! --data-positive for the data to be positive
//! --dt-relative use a relative segment intervale. The dt is used
//! multipled by the data
virtual void load(std::istream& input,
const arguments& args = arguments()) ;
// Acces to data
virtual vec get(int i) const ;
......
......@@ -9,6 +9,7 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <core/data.h>
#include <core/data_storage.h>
#include <core/vertical_segment.h>
#include <cstdio>
......@@ -151,15 +152,15 @@ class BrdfGrid : public vertical_segment {
std::vector<int> _size;
BrdfGrid(const arguments& args) : vertical_segment()
BrdfGrid(const arguments& args)
: vertical_segment(alta::parameters(2, 3, params::STARK_2D,
params::RGB_COLOR),
0) // XXX: size
{
// Set the input and output parametrization
parameters p(2, 3, params::STARK_2D, params::RGB_COLOR);
setParametrization(p);
initialize(args);
}
// FIXME: Move this to constructor.
void initialize(const arguments& args, bool preallocate = true) {
// Allow to load a different parametrization depending on the
......@@ -268,16 +269,6 @@ class BrdfGrid : public vertical_segment {
}
}
// Load data from a file
virtual void load(std::istream& input, const arguments& args)
{
arguments header = arguments::parse_header(input);
initialize(header, false);
// FIXME: ARGS is ignored.
load_data_from_text(input, header, *this);
}
void save(const std::string& filename) const
{
std::ofstream file;
......@@ -378,3 +369,17 @@ ALTA_DLL_EXPORT data* provide_data(const arguments& args)
{
return new BrdfGrid(args);
}
ALTA_DLL_EXPORT data* load_data(std::istream& input,
const arguments& args)
{
arguments header = arguments::parse_header(input);
BrdfGrid* result = new BrdfGrid(args);
// XXX: Should be done in constructor.
result->initialize(header, false);
load_data_from_text(input, header, *result);
return result;
}
......@@ -86,6 +86,9 @@ class MatlabInterpolant : public data
engClose(ep);
}
// FIXME: The following method should be converted to a 'load_data'
// function.
#if 0
// Load data from a file
virtual void load(std::istream& input, const arguments& args)
{
......@@ -128,6 +131,7 @@ class MatlabInterpolant : public data
x = mxCreateDoubleMatrix(1, dimX(), mxREAL);
}
#endif
virtual void save(const std::string& filename) const
{
......
......@@ -12,6 +12,7 @@
#include <core/vertical_segment.h>
#include <core/common.h>
#include <core/args.h>
#include <core/plugins_manager.h>
//#define USE_DELAUNAY
#ifdef USE_DELAUNAY
......@@ -72,10 +73,40 @@ class rbf_interpolant : public data
public:
rbf_interpolant() : _data(new vertical_segment())
rbf_interpolant(ptr<data> proxied_data)
: data(proxied_data->parametrization()),
_data(proxied_data),
_knn(3)
{
_knn = 3;
}
_min = _data->min();
_max = _data->max();
#ifdef USE_DELAUNAY
dD = parametrization().dimX()+parametrization().dimY();
D = new Delaunay_d(dD);
for(int i=0; i<_data->size(); ++i)
{
vec x = _data->get(i);
Point pt(dD, &x[0], &x[dD]);
D->insert(pt);
}
std::cout << "<<DEBUG>> number of points in the Delaunay triangulation: " << D->all_points().size() << std::endl;
std::cout << "<<DEBUG>> number of points in input: " << _data->size() << std::endl;
#else
// Update the KDtreee by inserting all points
double* _d = new double[parametrization().dimX()*_data->size()];
flann::Matrix<double> pts(_d, _data->size(), parametrization().dimX());
for(int i=0; i<_data->size(); ++i)
{
vec x = _data->get(i);
memcpy(pts[i], &x[0], parametrization().dimX()*sizeof(double));
}
_kdtree = new flann::Index< flann::L2<double> >(pts, flann::KDTreeIndexParams(4));
_kdtree->buildIndex();
#endif
}
virtual ~rbf_interpolant()
{
......@@ -88,48 +119,6 @@ class rbf_interpolant : public data
#endif
}
// Load data from a file
virtual void load(std::istream& input, const arguments& args)
{
// Load the data
_data->load(input, args);
// Copy the informations
parameters p(_data->parametrization().dimX(),
_data->parametrization().dimY(),
_data->parametrization().input_parametrization(),
_data->parametrization().output_parametrization());
setParametrization(p);
setMin(_data->min());
setMax(_data->max());
#ifdef USE_DELAUNAY
dD = parametrization().dimX()+parametrization().dimY();
D = new Delaunay_d(dD);
for(int i=0; i<_data->size(); ++i)
{
vec x = _data->get(i);
Point pt(dD, &x[0], &x[dD]);
D->insert(pt);
}
std::cout << "<<DEBUG>> number of points in the Delaunay triangulation: " << D->all_points().size() << std::endl;
std::cout << "<<DEBUG>> number of points in input: " << _data->size() << std::endl;
#else
// Update the KDtreee by inserting all points
double* _d = new double[parametrization().dimX()*_data->size()];
flann::Matrix<double> pts(_d, _data->size(), parametrization().dimX());
for(int i=0; i<_data->size(); ++i)
{
vec x = _data->get(i);
memcpy(pts[i], &x[0], parametrization().dimX()*sizeof(double));
}
_kdtree = new flann::Index< flann::L2<double> >(pts, flann::KDTreeIndexParams(4));
_kdtree->buildIndex();
#endif
}
virtual void save(const std::string& filename) const
{
}
......@@ -236,7 +225,13 @@ class rbf_interpolant : public data
}
};
ALTA_DLL_EXPORT data* provide_data(const arguments&)
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args)
{
return new rbf_interpolant();
// Load the data
ptr<data> proxied = plugins_manager::load_data("vertical_segment",
input, args);
return new rbf_interpolant(proxied);
}
......@@ -20,6 +20,7 @@
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <utility>
using namespace alta;
......@@ -50,128 +51,126 @@ class ASTM : public vertical_segment
{
public: //methods
ASTM() : vertical_segment() {
ASTM(const parameters& params, std::vector<vec>&& input_data)
: vertical_segment(params, std::move(input_data))
{ }
}
ASTM(): vertical_segment() { }
};
// Parse ASTM header.
// An ASTM header is composed of a KEY in capital letters and a list
// of string/numeric values. An ASTM header finishes after the key VARS.
//
arguments parse_header(std::istream& in) const {
// Parse ASTM header.
// An ASTM header is composed of a KEY in capital letters and a list
// of string/numeric values. An ASTM header finishes after the key VARS.
//
static arguments parse_header(std::istream& in) {
arguments args;
std::string key, line;
arguments args;
std::string key, line;
while(in.good()) {
while(in.good()) {
// Get the current key
in >> key;
// Get the current key
in >> key;
// Extract the current line
std::getline(in, line);
// Extract the current line
std::getline(in, line);
// End of header
if(key == "VARS") {
// End of header
if(key == "VARS") {
args.update(key, std::string("[") + line + std::string("]"));
break;
} else {
} else {
args.update(key, line);
}
}
return args;
}
// Update the dimX, dimY and input and output dimension based on the
// values stored in the VARS list.
//
// The input parametrization can take the form:
// + theta_i, phi_i, theta_s, phi_s
// + theta_i, theta_s, phi_s
//
// The output parametrization can take the form:
// + Integrated ..
// + R, G, B
//
void update_params(const std::vector<std::string>& vars) {
unsigned int nX = 0, nY = 0;
for(auto it=vars.begin(); it!=vars.end(); it++) {
if(*it == "theta_i" || *it == "phi_i" ||
*it == "theta_s" || *it == "phi_s") {
}
}
return args;
}
const parameters
compute_parameters(const std::vector<std::string>& vars)
{
// Update the dimX, dimY and input and output dimension based on the
// values stored in the VARS list.
//
// The input parametrization can take the form:
// + theta_i, phi_i, theta_s, phi_s
// + theta_i, theta_s, phi_s
//
// The output parametrization can take the form:
// + Integrated ..
// + R, G, B
//
unsigned int nX = 0, nY = 0;
for(auto it=vars.begin(); it!=vars.end(); it++) {
if(*it == "theta_i" || *it == "phi_i" ||
*it == "theta_s" || *it == "phi_s") {
nX += 1;
} else {
} else {
nY += 1;
}
}
auto out_param = [&]() {
if(vars.back() == "B") {
return params::RGB_COLOR;
} else if(vars.back().compare(0, 10, "Integrated") == 0) {
return params::INV_STERADIAN;
} else {
std::cout << "<<ERROR>> Output format not handled in \'data_astm\'" << std::endl;
return params::UNKNOWN_OUTPUT;
}
};
parameters param(nX, nY,
nX == 4 ? params::SPHERICAL_TL_PL_TV_PV : params::UNKNOWN_INPUT,
out_param());
setParametrization(param);
}
// Load data from a file
virtual void load(std::istream& input, const arguments& args)
{
}
}
auto out_param = [&]() {
if(vars.back() == "B") {
return params::RGB_COLOR;
} else if(vars.back().compare(0, 10, "Integrated") == 0) {
return params::INV_STERADIAN;
} else {
std::cout << "<<ERROR>> Output format not handled in \'data_astm\'" << std::endl;
return params::UNKNOWN_OUTPUT;
}
};
return parameters(nX, nY,
nX == 4 ? params::SPHERICAL_TL_PL_TV_PV : params::UNKNOWN_INPUT,
out_param());
}
ALTA_DLL_EXPORT data* provide_data(const arguments&)
{
return new ASTM();
}
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args)
{
std::string line;
// Parse the header, get the output/input dimensions and params
arguments header = parse_header(input);
auto vars = header.get_vec<std::string>("VARS");
update_params(vars);
auto vars = header.get_vec<std::string>("VARS");
auto params = compute_parameters(vars);
// Check data size from header
assert(header.is_defined("NUM_POINTS"));
int size = header.get_int("NUM_POINTS", 0);
initializeToZero(size);
// Check data size from header
assert(header.is_defined("NUM_POINTS"));
int size = header.get_int("NUM_POINTS", 0);
// Size of the data
const int n = parametrization().dimX() + parametrization().dimY();
int i = 0;
// Size of the data
std::vector<vec> data(size);
const int n = params.dimX() + params.dimY();
int i = 0;
while(input.good())
{
std::getline(input, line);
std::getline(input, line);
if(line.size() == 0 || line.rfind(',') == std::string::npos)
if(line.size() == 0 || line.rfind(',') == std::string::npos)
continue;
std::replace(line.begin(), line.end(), ',', ' ');
std::replace(line.begin(), line.end(), ',', ' ');
// Create a stream from the line data and extract it as
// a vec of dim parametrization().dimX() + parametrization().dimY().
std::stringstream stream(line);
vec x(n);
for(int i=0; i<n; ++i) {
stream >> x[i];
}
// Create a stream from the line data and extract it as
// a vec of dim parametrization().dimX() + parametrization().dimY().
std::stringstream stream(line);
vec x(n);
for(int i=0; i<n; ++i) {
stream >> x[i];
}
set(i++, x);
data[i++] = x;
}
if(header.is_defined("NUM_POINTS")) {
assert(this->size() == header.get_int("NUM_POINTS"));
}
}
};
ALTA_DLL_EXPORT data* provide_data(const arguments&)
{
return new ASTM();
return new ASTM(params, std::move(data));
}
......@@ -70,6 +70,9 @@ using namespace alta;
* [merl]: http://people.csail.mit.edu/wojciech/BRDFDatabase/brdfs/
* [ngan]: http://people.csail.mit.edu/addy/research/brdf/
*/
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args);
class MERL : public data
{
private: // data
......@@ -99,16 +102,6 @@ public: // methods
}
// Load data from a file
void load(std::istream& input, const arguments& args)
{
if(!read_brdf(input, brdf))
{
std::cerr << "<<ERROR>> unable to load the data as a MERL file" << std::endl ;
throw;
}
}
void save(const std::string& filename) const
{
FILE *f = fopen(filename.c_str(), "wb");
......@@ -445,28 +438,42 @@ private: //methods
}
// Read BRDF data
bool read_brdf(std::istream& input, double* &brdf)
{
friend data* load_data(std::istream&, const arguments&);
};
static bool read_brdf(std::istream& input, double* &brdf)
{
int dims[3];
input.read((char *) &dims, sizeof dims);
int n = dims[0] * dims[1] * dims[2];
if (n != BRDF_SAMPLING_RES_THETA_H *
BRDF_SAMPLING_RES_THETA_D *
BRDF_SAMPLING_RES_PHI_D / 2)
BRDF_SAMPLING_RES_THETA_D *
BRDF_SAMPLING_RES_PHI_D / 2)
{
fprintf(stderr, "Dimensions don't match\n");
return false;
fprintf(stderr, "Dimensions don't match\n");
return false;
}
input.read((char *) brdf, 3 * n * sizeof(double));
return true;
}
};
}
ALTA_DLL_EXPORT data* provide_data(const arguments&)
{
return new MERL();
}
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args)
{
MERL* result = new MERL();
if(!read_brdf(input, result->brdf))
{
std::cerr << "<<ERROR>> unable to load the data as a MERL file" << std::endl ;
throw;
}
return result;
}
......@@ -49,6 +49,8 @@ brdf_slice_parameters(const arguments& args)
return result;
}
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args);
/*! \ingroup datas
* \class data_brdf_slice
* \brief Data interface for the BRDF slice file format.
......@@ -105,13 +107,6 @@ class BrdfSlice : public data {
delete[] _data;
}
// Load data from a file
void load(std::istream& input, const arguments& args)
{
delete[] _data;
t_EXR_IO<double>::LoadEXR(input, width, height, _data);
}
void save(const std::string& filename) const
{
if(!t_EXR_IO<double>::SaveEXR(filename.c_str(), width, slice*height, _data))
......@@ -281,6 +276,8 @@ class BrdfSlice : public data {
}
return res ;
}
friend data* load_data(std::istream&, const arguments&);
};
ALTA_DLL_EXPORT data* provide_data(const arguments& args)
......@@ -289,3 +286,13 @@ ALTA_DLL_EXPORT data* provide_data(const arguments& args)
}
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args)
{
BrdfSlice* result = new BrdfSlice(args);
delete[] result->_data;
t_EXR_IO<double>::LoadEXR(input, result->width, result->height,
result->_data);
return result;
}
......@@ -30,6 +30,8 @@
using namespace alta;
ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args);
/*! \ingroup datas
* \class data_utia
* \brief Data interface for the [UTIA][utia] file format.
......@@ -89,48 +91,6 @@ public:
delete[] this->Bd;
}
// Load data from a file
virtual void load(std::istream& input, const arguments& args) {
#if 0 // FIXME: backport this
/* If the file is an OpenEXR image */
if(filename.substr(filename.find_last_of(".") + 1) == "exr") {
double* temp;