Commit 60b9eb80 authored by pacanows's avatar pacanows
Browse files

Merge

parents 2f00f43a 27ebbb6d
/*!
\page format Format
\todo Describe here the file format
<h2>Common notations</h2>
<h2>Input file format</h2>
For a text data file with <em>n</em> data entries where the input domain has <em>N</em> dimensions and a <em>input_param</em> parametrization and the output domain has <em>P</em> dimensions and a <em>output_param</em> parametrization, our file format is the following:
\verbatim
#DIM N P
#PARAM_IN %input_param%
#PARAM_OUT %output_param%
#VS [0|1|2] (P times)
x_{1,1} ... x_{1,N} y_{1,1} ... y_{1,P}
...
x_{i,1} ... x_{i,N} y_{i,1} ... y_{i,P}
...
x_{n,1} ... x_{n,N} y_{n,1} ... y_{n,P}
\endverbatim
Vertical segments are not defined if VS is 0. For a VS of 1, each sample as a radius associated for the associated dimension. If VS is 2, each sample has a min and max segment value for the associated dimension.
Data and function files have the same format. They are text file very close to dump.
Each file starts with a header containing :
<h3> Parametrization format </h3>
New Tokens
<ul>
<li> \verbatim #PARAM_IN input_parametrization_name \endverbatim </li>
<li> \verbatim #PARAM_OUT output_parametrization_name \endverbatim </li>
</ul>
<h3>Input Parametrization</h3>
Param toujours de la forme NOMDUTYPE_PARAM1_PARAM2_..._PARAMN ou N est le nombre
......@@ -60,32 +42,97 @@ enum{
ENERGY ( as specified by the International Unit System i.e., Joule)
LUMINANCE
<h2>Input file format</h2>
For a text data file with <em>n</em> data entries where the input domain has <em>N</em> dimensions and a <em>input_param</em> parametrization and the output domain has <em>P</em> dimensions and a <em>output_param</em> parametrization, our file format is the following:
\verbatim
#DIM N P
#PARAM_IN %input_param%
#PARAM_OUT %output_param%
#VS [0|1|2] (P times)
x_{1,1} ... x_{1,N} y_{1,1} ... y_{1,P}
...
x_{i,1} ... x_{i,N} y_{i,1} ... y_{i,P}
...
x_{n,1} ... x_{n,N} y_{n,1} ... y_{n,P}
\endverbatim
Vertical segments are not defined if VS is 0. For a VS of 1, each sample as a radius associated for the associated dimension. If VS is 2, each sample has a min and max segment value for the associated dimension.
<h2>Rational function file format (.rational)</h2>
We advise to output all rational function into .rational file for consistency.
ALTA library assumes that all rational polynomials are exported using the
following convention:
<h2>Function file format (.function_name)</h2>
We advise to output function file into <em>.function</em> file for consistency.
ALTA library assumes that all functions are exported using the following convention:
<ul>
<li>The .rational file is outputed in plain text and not in binary.</li>
<li>The .rational file starts with a header. Each line of the header
<li>The .function file is outputed in plain text and not in binary.</li>
<li>The .function file starts with a header. Each line of the header
starts with the character '#'.</li>
<li>If there are multiple color channels to the rational function, they
<li>The header contains the command line used to create the function
in a <em>#CMD ...</em> line.
<li>If there are multiple color channels to the function, they
are enumerated in the file, one color channel by one.</li>
</ul>
Example of a .rational file:
Example of a .function file for a single Lafortune lobe without any diffuse:
\verbatim
#ALTA_HEADER_DATA
#CMD lafortune --nb_lobes 1 --isotrope
#DIM 2 1
#PARAM_IN ROMEIRO_TH_TD
#PARAM_OUT ENERGY
#ALTA_HEADER_END
#FUNC lafortune
Cx 1.0
Cz 1.0
N 10.0
\endverbatim
For multiple BRDFs lobes (when you want to add a diffuse for example), you need to
specify it into the command line. The different parameters are outputed sequentially
into the file:
\verbatim
#DIM N P
#NP (nombre de coeffs ou degré max au numerateur )
#NQ (nombre de coeffs ou degré min au denominateur )
#BASIS "chaine_caract_decrivant_le_type_de_fonction_de_base"
Coeff_numerateur deg_1_fct_base deg_2_fct_base ... coeff_associe
Coeff denominateur
#NP
#NQ
#ALTA_HEADER_FUNC
#CMD [diffuse, lafortune --nb_lobes 1 --isotrope, phong --fresnel schlick]
#DIM 2 3
#PARAM_IN ROMEIRO_TH_TD
#PARAM_OUT RGB_COLOR
#ALTA_HEADER_END
#FUNC diffuse
kd 1.0
kd 0.02
kd 0.1
#FUNC lafortune
Cx 1.0
Cz 1.0
N 10.0
Cx 1.0
Cz 1.0
N 10.0
Cx 1.0
Cz 1.0
N 10.0
#FUNC phong
ks 1.0
N 10.0
ks 1.0
N 10.0
ks 1.0
N 10.0
#FUNC schlick
R 1.0
R 1.0
R 1.0
\endverbatim
\todo Right now the different color channels have the same length !
......
......@@ -14,7 +14,7 @@
+ Format texte d'entrée et de sortie
+ Format en Entrée
<h2>Data file format</h2>
#DIM N P
# COMMENTAIRE
......@@ -24,7 +24,7 @@
x1 .... xN y1.....yP
+ Format en Sortie
<h2>Function file format</h2>
#DIM N P
#NP (nombre de coeffs ou degré max au numerateur )
......
#pragma once
#include <string>
#include <sstream>
#include <map>
#include <cstdlib>
#include <iostream>
......@@ -223,6 +224,62 @@ class arguments
return res;
}
//! \brief get the reconstructed command line arguments (without
//! the executable name
std::string get_cmd() const
{
std::string cmd;
std::map<std::string, std::string>::const_iterator it = _map.begin();
for(;it != _map.end(); it++)
{
if(!it->first.empty())
{
cmd.append(" --");
cmd.append(it->first);
cmd.append(" ");
cmd.append(it->second);
}
}
return cmd;
}
//! \brief Create an argument object from a string describing a command
//! line.
static arguments create_arguments(const std::string& n)
{
std::vector<std::string> cmd_vec;
std::stringstream stream(n);
#ifdef DEBUG_ARGS
std::cout << "<<DEBUG>> create argument vector: [";
#endif
while(stream.good())
{
std::string temp;
stream >> temp;
#ifdef DEBUG_ARGS
std::cout << temp << ", ";
#endif
cmd_vec.push_back(temp);
}
#ifdef DEBUG_ARGS
std::cout << "]" << std::endl;
#endif
int argc = cmd_vec.size();
char* argv[argc];
for(int i=0; i<argc; ++i)
{
argv[i] = &cmd_vec[i][0];
}
arguments current_args(argc, argv);
return current_args;
}
private: // data
std::map<std::string, std::string> _map ;
......
......@@ -7,6 +7,7 @@
#include <cstring>
#include <algorithm>
#ifdef OLD
/*! \brief A core implementation of a vector of double.
* \ingroup core
* \internal
......@@ -28,11 +29,8 @@ class vec : public std::vector<double>
{
assign(dim, 0.0) ;
}
virtual ~vec()
{
}
//! \brief get a subpart of the vector
//! \brief get a subpart of the vector
vec subvector(int start, int n) const
{
vec res(n);
......@@ -224,6 +222,18 @@ class vec : public std::vector<double>
} ;
#endif
#include <Eigen/Core>
typedef Eigen::VectorXd vec;
double norm(const vec& a);
vec normalize(const vec& a);
double dot(const vec& a, const vec& b);
vec product(const vec& a, const vec& b);
//! \brief locate the first index of value v in vector vec. Complexity in
//! O(n) is the worst case.
......@@ -245,7 +255,7 @@ template<typename T> T clamp(T x, T a, T b)
}
#define NOT_IMPLEMENTED() \
std::cerr << "<<ERROR>> not implemented " << __FILE__ \
std::cerr << "<<ERROR>> not implemented " << __PRETTY_FUNCTION__ << " in file " << __FILE__ \
<< ":" << __LINE__ << std::endl; \
throw
......
TEMPLATE = lib
CONFIG *= static \
console
console \
eigen
DESTDIR = ../build
unix{
QMAKE_CXXFLAGS += -std=c++0x -m64
QMAKE_CXXFLAGS += -std=c++0x -Wall -pedantic
}
HEADERS = args.h \
......@@ -19,7 +20,8 @@ HEADERS = args.h \
params.h \
clustering.h
SOURCES = plugins_manager.cpp \
SOURCES = common.cpp \
plugins_manager.cpp \
vertical_segment.cpp \
rational_function.cpp \
params.cpp \
......
......@@ -2,21 +2,104 @@
#include "common.h"
void function::save(const std::string& filename, const arguments& args) const
{
// Open the file
std::ofstream file(filename);
if(!file.is_open())
{
std::cerr << "<<ERROR>> unable to open output file for writing" << std::endl;
}
// Save common header
save_header(file, args);
// Save function definition
save_body(file, args);
// Save fit data
save_call(file, args);
}
//! \brief save the header of the output function file. The header should
//! store general information about the fit such as the command line used
//! the dimension of the fit. L2 and L_inf distance could be added here.
void function::save_header(std::ostream& out, const arguments& args) const
{
if(!args.is_defined("export"))
{
out << "#ALTA FUNC HEADER" << std::endl;
out << "#CMD " << args.get_cmd() << std::endl;
out << "#DIM " << _nX << " " << _nY << std::endl;
out << "#PARAM_IN " << params::get_name(input_parametrization()) << std::endl;
//out << "#PARAM_OUT " << params::get_name(output_parametrization()) << std::endl;
out << "#ALTA HEADER END" << std::endl;
out << std::endl;
}
}
//! \brief save function specific data. This has no use for ALTA export
//! but allows to factorize the code in the C++ or matlab export by
//! defining function calls that are common to all the plugins.
void function::save_body(std::ostream& out, const arguments& args) const
{
bool is_cpp = args["export"] == "C++";
bool is_shader = args["export"] == "shader";
bool is_matlab = args["export"] == "matlab";
if(is_cpp)
{
out << "vec brdf(const vec& in, const vec& out)" << std::endl;
out << "{" << std::endl;
out << "\tvec res(" << dimY() << ");" << std::endl;
}
else if(is_matlab)
{
out << "function res = brdf(in, out)" << std::endl;
out << "\tres = zeros(" << dimY() << ");" << std::endl;
}
else if(is_shader)
{
out << "vec3 brdf(vec3 in, vec3 out)" << std::endl;
out << "\tvec3 res = vec3(0.0f);" << std::endl;
}
}
//! \brief save object specific information. For an ALTA export the
//! coefficients will be exported. For a C++ or matlab export, the call
//! to the associated function will be done.
void function::save_call(std::ostream& out, const arguments& args) const
{
bool is_cpp = args["export"] == "C++";
bool is_shader = args["export"] == "shader";
bool is_matlab = args["export"] == "matlab";
if(is_cpp || is_shader)
{
out << "\treturn res;" << std::endl;
out << "}" << std::endl;
}
else if(is_matlab)
{
out << "endfunction" << std::endl;
}
}
//! \brief L2 norm to data.
double function::L2_distance(const data* d) const
{
double l2_dist = 0.0;
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec y(d->dimY());
for(int j=0; j<d->dimY(); ++j)
y[j] = dat[d->dimX()+j];
//linf_dist = std::max<double>(linf_dist, std::abs<double>(norm(y-rj->value(dat))));
l2_dist += std::pow(norm(y-value(dat)), 2);
}
l2_dist = std::sqrt(l2_dist / d->size());
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec y(d->dimY());
for(int j=0; j<d->dimY(); ++j)
y[j] = dat[d->dimX()+j];
//linf_dist = std::max<double>(linf_dist, std::abs<double>(norm(y-rj->value(dat))));
l2_dist += std::pow(norm(y-value(dat)), 2);
}
l2_dist = std::sqrt(l2_dist / d->size());
return l2_dist;
}
......@@ -25,15 +108,15 @@ double function::Linf_distance(const data* d) const
{
double linf_dist = 0.0;
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec y(d->dimY());
for(int j=0; j<d->dimY(); ++j)
y[j] = dat[d->dimX()+j];
linf_dist = std::max<double>(linf_dist, std::abs(norm(y-value(dat))));
}
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec y(d->dimY());
for(int j=0; j<d->dimY(); ++j)
y[j] = dat[d->dimX()+j];
linf_dist = std::max<double>(linf_dist, std::abs(norm(y-value(dat))));
}
return linf_dist;
}
......@@ -24,12 +24,14 @@ class function : public parametrized
{
public: // methods
/* INTERFACE */
// Overload the function operator
virtual vec operator()(const vec& x) const = 0 ;
virtual vec value(const vec& x) const = 0 ;
//! Load function specific files
virtual void load(const std::string& filename) = 0 ;
virtual void load(std::istream& in) = 0 ;
//! \brief Provide a first rough fit of the function.
//!
......@@ -38,41 +40,6 @@ class function : public parametrized
//! example.
virtual void bootstrap(const data* d, const arguments& args) {}
//! \brief Save the current function to a specific file type, args can
//! be used to differenciate the type of export.
//!
//! \see rational_function.cpp for an example
virtual void save(const std::string& filename, const arguments& args) const
{
std::cout << "<<DEBUG>> Exporting the function" << std::endl;
if(args.is_defined("export"))
{
if(args["export"].compare("c++") == 0)
{
std::cout << "<<INFO>> will export in C++ format" << std::endl;
save_cpp(filename, args);
}
else if(args["export"].compare("matlab") == 0)
{
std::cout << "<<INFO>> will export in matlab format" << std::endl;
save_matlab(filename, args);
}
else if(args["export"].compare("explorer") == 0)
{
std::cout << "<<INFO>> will export in BRDF explorer format" << std::endl;
save_brdfexplorer(filename, args);
}
else
{
std::cerr << "<<ERROR>> the export format is unknown" << std::endl ;
}
}
else
{
save(filename) ;
}
}
//! Provide the dimension of the input space of the function
virtual int dimX() const { return _nX ; }
//! Provide the dimension of the output space of the function
......@@ -101,62 +68,32 @@ class function : public parametrized
virtual vec getMin() const { return _min ; }
virtual vec getMax() const { return _max ; }
protected: // function
//! \brief Standard saving function.
virtual void save(const std::string& filename) const
{
NOT_IMPLEMENTED();
}
/* EXPORT FUNCTIONS */
//! \brief Output the function as a gnuplot file. It requires
//! the data object to output the function at the input location only.
virtual void save_gnuplot(const std::string& filename, const data* d,
const arguments& args) const
{
#ifndef OLD
std::ofstream file(filename.c_str(), std::ios_base::trunc);
for(int i=0; i<d->size(); ++i)
{
vec v = d->get(i) ;
// vec y1 ; y1.assign(d->dimY(), 0.0) ;
// for(int k=0; k<d->dimY(); ++k) { y1[k] = v[d->dimX() + k] ; }
vec y2 = value(v) ;
for(int u=0; u<d->dimX(); ++u)
file << v[u] << "\t" ;
for(int u=0; u<d->dimY(); ++u)
file << y2[u] << "\t" ;
file << std::endl ;
}
file.close();
#else
NOT_IMPLEMENTED();
#endif
}
//! \brief Save the current function to a specific file type, args can
//! be used to differenciate the type of export.
//!
//! \see rational_function.cpp for an example
virtual void save(const std::string& filename, const arguments& args) const;
//! \brief Output the function using a C++ function formating.
virtual void save_cpp(const std::string& filename, const arguments& args) const
//! \brief save the header of the output function file. The header should
//! store general information about the fit such as the command line used
//! the dimension of the fit. L2 and L_inf distance could be added here.
virtual void save_header(std::ostream& out, const arguments& args) const ;
{
NOT_IMPLEMENTED();
}
//! \brief save function specific data. This has no use for ALTA export
//! but allows to factorize the code in the C++ or matlab export by
//! defining function calls that are common to all the plugins.
virtual void save_body(std::ostream& out, const arguments& args) const ;
//! \brief Output the function using a C++ function formating.
virtual void save_matlab(const std::string& filename, const arguments& args) const
{
NOT_IMPLEMENTED();
}
//! \brief save object specific information. For an ALTA export the
//! coefficients will be exported. For a C++ or matlab export, the call
//! to the associated function will be done.
virtual void save_call(std::ostream& out, const arguments& args) const ;
//! \brief Output the function using a BRDF Explorer formating.
virtual void save_brdfexplorer(const std::string& filename, const arguments& args) const
{
NOT_IMPLEMENTED();
}
public: // methods
/* METRIC FUNCTIONS */
//! \brief L2 norm to data.
double L2_distance(const data* d) const ;
......@@ -164,6 +101,7 @@ class function : public parametrized
//! \brief Linf norm to data.
double Linf_distance(const data* d) const ;
protected: // data
// Dimension of the function & domain of definition.
......@@ -206,6 +144,314 @@ class nonlinear_function: public function
// The result vector should be orderer as res[i + dimY()*j], output
// dimension first, then parameters.
virtual vec parametersJacobian(const vec& x) const = 0;
//! \brief default non_linear import. Parse the parameters in order.
virtual void load(std::istream& in)
{
// Parse line until the next comment
while(in.peek() != '#')
{
char line[256];
in.getline(line, 256);
}
// Checking for the comment line #FUNC nonlinear_function_phong
std::string token;
in >> token;
if(token.compare("#FUNC") != 0)