rational_function.h 7.59 KB
Newer Older
1 2
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions

3
   Copyright (C) 2013, 2014, 2016 Inria
4 5 6 7 8 9 10

   This file is part of ALTA.

   This Source Code Form is subject to the terms of the Mozilla Public
   License, v. 2.0.  If a copy of the MPL was not distributed with this
   file, You can obtain one at http://mozilla.org/MPL/2.0/.  */

11 12 13 14 15
#pragma once

// Include STL
#include <vector>
#include <string>
16
#include <sstream>
17 18 19 20 21 22 23 24

// Interface
#include "function.h"
#include "data.h"
#include "fitter.h"
#include "args.h"
#include "common.h"

25

26 27 28 29 30 31 32 33 34 35 36
namespace alta {
   class rational_function_1d;
   class rational_function;
}
// STL stream ouput
std::ostream& operator<< (std::ostream&, const alta::rational_function_1d&);
std::ostream& operator<< (std::ostream&, const alta::rational_function&);


namespace alta {

37 38 39
/*! \brief A one dimensional rational function class. A rational function has
 *  the form \f$r(x) = \dfrac{\sum_{i} a_i p_i(x)}{b_i q_i(x)}$\f.
 */
40 41 42 43
class rational_function_1d : public function
{
	public: // methods

44 45 46 47 48
		rational_function_1d(const parameters& params,
                         unsigned int np = 0, unsigned int nq = 0,
                         bool separable = false);

    rational_function_1d() ALTA_DEPRECATED;
49
		rational_function_1d(int nX, unsigned int np, unsigned int nq, 
50
									bool separable = false) ALTA_DEPRECATED;
51
		virtual ~rational_function_1d() {}
52

53

54
		/* FUNCTION INHERITANCE */
55

56
		//! Overload the function operator
57 58
		virtual vec value(const vec& x) const ;
		virtual vec operator()(const vec& x) const { return value(x) ; }
59

60 61
		//! IO function to text files
		virtual bool load(std::istream& in);
62

63 64 65 66 67
		//! \brief Save the rational function expansion. It should
		//! not be store in any variable (e.g. "y = rf(x);") as the
		//! nD rational function can append factor to the 1D rational
		//! function.
		virtual void save_body(std::ostream&, const arguments&) const;
68 69


70
      /* RATIONAL FUNCTION SPECIFIC */
71

72 73 74 75 76
		//! Evaluate the numerator \f$p(\mathbf{x})\f$ of the rational
		//! function. This function is provided to allow fast 
		//! implementation. For example one can use the Clenshaw 
		//! algorithm to efficiently evaluate recursively defined
		//! polynomials. 
77
		virtual vec p(const vec& x) const ;
78

79 80 81 82 83
		//! Evaluate the denominator \f$q(\mathbf{x})\f$ of the rational
		//! function. This function is provided to allow fast 
		//! implementation. For example one can use the Clenshaw 
		//! algorithm to efficiently evaluate recursively defined
		//! polynomials. 
84 85
		virtual vec q(const vec& x) const ;

86 87
		//! Evaluate the basis function \f$p_i(\mathbf{x})\f$ for the
		//! numerator of the rational function.
88
		virtual double p(const vec& x, int i) const ;
89 90
		//! Evaluate the basis function \f$q_i(\mathbf{x})\f$ for the
		//! denominator of the rational function.
91 92
		virtual double q(const vec& x, int j) const ;

93 94 95 96

		//! Update the coefficient vectors with new values. The new values
		//! are normalized by the first element of the denominator 
		//! coefficients.
97 98
		virtual void update(const vec& in_a, 
		                    const vec& in_b) ;
99 100 101 102 103
		
		//! Update the 1D rational function with another one. Note that
		//! this function can change the dimensions of the coefficients
		//! vectors.
		virtual void update(const rational_function_1d* r) ;
104

105 106 107
		//! Resize the polynomial.
		virtual void resize(unsigned int np, unsigned int nq);

108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
		//! Get the i-th coefficient of the numerator.
		virtual double getP(int i) const { return _p_coeffs[i].a; }

		//! Get the i-th coefficient of the denominator.
		virtual double getQ(int i) const { return _q_coeffs[i].a; }

		//! Get the vector of coefficient for the numerator.
		virtual vec getP() const 
		{
			const int np = _p_coeffs.size();
			vec t(np);
			for(int i=0; i<np; ++i) {t[i] = _p_coeffs[i].a; }
			return t; 
		}
		
		//! Get the vector of coefficient for the denominator.
		virtual vec getQ() const 
		{ 
			const int nq = _q_coeffs.size();
			vec t(nq);
			for(int i=0; i<nq; ++i) {t[i] = _q_coeffs[i].a; }
			return t; 
		}
132

133

134 135 136 137
		//! Convert a 1D index into a vector of degree for a
		//! multinomial coeffcient. The resulting vector v should
		//! be used as prod_k x[k]^v[k] for the monomial basis
		std::vector<int> index2degree(int i) const ;
138

139
	protected: // functions
140

141
		static int estimate_dk(int k, int d);
142

143 144
		static void populate(std::vector<int>& vec, int N, int M, int j);

145 146 147

	protected: // data

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
		// Structure to store a multi-dimensional coefficient. The
		// coeffcient, a, is associated with the vector of degree
		// for each dimension.
		struct coeff
		{
			coeff() {}
			coeff(double a, std::vector<int> deg) :
				a(a), deg(deg) { }

			double a;
			std::vector<int> deg;
		};

		// Table of coefficients and indices, sorted with respect
		// to the indices.
		std::vector<coeff> _p_coeffs;
		std::vector<coeff> _q_coeffs;

		//! Is the function separable with respect to its input dimensions?
		//! \todo Make possible to have only part of the dimensions
		//! separable.
		bool _separable;
170 171
} ;

172 173 174 175 176 177
/*! \brief Rational function define a BRDF model using a ratio of polynomials
 *  \ingroup core
 *
 *  \details
 *  A rational function define a BRDF model using a ratio of polynomials.
 */
178
class rational_function : public function
179
{
180

181 182
	public: // methods

183 184 185 186 187 188
		rational_function() ALTA_DEPRECATED;
		rational_function(int np, int nq) ALTA_DEPRECATED;

    rational_function(const parameters& params,
                      int np = 0, int nq = 0);

189
		virtual ~rational_function() ;
190 191 192 193

		// Overload the function operator
		virtual vec value(const vec& x) const ;
		virtual vec operator()(const vec& x) const { return value(x) ; }
194

195
		// IO function to text files
196
		virtual bool load(std::istream& in) ;
197

198
		// Update the function
199 200
		virtual void update(const ptr<rational_function>& r) 
		{
201 202
      assert(r->parametrization().dimX() == _parameters.dimX());
      assert(r->parametrization().dimY() == _parameters.dimY());
203

204
			for(int k=0; k < _parameters.dimY(); ++k)
205 206 207 208
			{
				get(k)->update(r->get(k));
			}
		}
209
		virtual void update(int i, rational_function_1d* r) ;
210

211 212
		//! Get the 1D function associated with color channel i. If no one exist, 
		//! this function allocates a new element. If i > nY, it returns NULL.
213
		virtual rational_function_1d* get(int i) ;
214
		virtual rational_function_1d* get(int i) const ALTA_DEPRECATED;
215

216 217
		//! Set the dimension of the output space of the function. This function 
		//! will update the size of the rs vector size.
218 219 220 221 222 223 224
		virtual void setDimY(int nY)
		{
      parameters new_params(_parameters.dimX(), nY,
                            _parameters.input_parametrization(),
                            _parameters.output_parametrization());
      _parameters = new_params;
      rs.resize(nY);
225 226
		}

227 228
		//! \brief Set the size of the rational function. Any newly created 1D 
		//! function will have np and nq fixed as defined.
229 230 231 232 233 234
		virtual void setSize(int np, int nq)
		{
			this->np = np;
			this->nq = nq;
			clear();
		}
235
		
236 237 238 239
		//! \brief Clear the vector of 1D rational functions.
		virtual void clear()
		{
			rs.clear();
240
			rs.resize(_parameters.dimY());
241 242
		}

243 244 245 246
		virtual void setMin(const vec& min)
		{
			function::setMin(min);
		}
247

248 249 250 251 252
		virtual void setMax(const vec& max)
		{
			function::setMax(max);
		}

253 254
		//! \brief Save the rational function to the rational format (see 
		//! \ref formating).
255 256
		virtual void save_call(std::ostream& out, const arguments& args) const ;

257 258
	protected: // data

259 260
		//! Store the y \in R rational functions. Each channel is a distinct 
		//! polynomial and should be fitted separately.
261
		std::vector<rational_function_1d*> rs ;
262

263 264 265
		//! Size of the polynomials
		//! \todo Change it by a more adaptive scheme, with different np, nq per 
		//! color channel?
266
		int np, nq;
267 268
};
}