function.cpp 3.93 KB
Newer Older
Laurent Belcour's avatar
Laurent Belcour committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include "function.h"

#include <string>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>

#include <core/common.h>

ALTA_DLL_EXPORT function* provide_function()
{
    return new diffuse_function();
}

// Overload the function operator
vec diffuse_function::operator()(const vec& x) const 
{
	return value(x);
}
vec diffuse_function::value(const vec& x) const 
{
    vec res(dimY());
    for(int i=0; i<dimY(); ++i)
    {
        res[i] = _kd[i];
    }

    return res;
}

//! Load function specific files
34
bool diffuse_function::load(std::istream &in)
Laurent Belcour's avatar
Laurent Belcour committed
35
{
36 37 38 39 40
    // Parse line until the next comment
    while(in.peek() != '#')
    {
        char line[256];
        in.getline(line, 256);
41 42 43 44 45 46

		  // If we cross the end of the file, or the badbit is
		  // set, the file cannot be loaded
		  if(!in.good())
			  return false;
	 }
47

Laurent Belcour's avatar
Laurent Belcour committed
48
    // Checking for the comment line #FUNC nonlinear_function_diffuse
49 50
    std::string token;
    in >> token;
51 52 53 54 55
    if(token != "#FUNC")
    {
        std::cerr << "<<ERROR>> parsing the stream. The #FUNC is not the next line defined." << std::endl;
        return false;
    }
56 57

    in >> token;
58 59 60 61 62
    if(token != "nonlinear_function_diffuse")
    {
        std::cerr << "<<ERROR>> parsing the stream. function name is not the next token." << std::endl;
        return false;
    }
63 64 65 66 67 68

    // kd [double]
    for(int i=0; i<dimY(); ++i)
    {
        in >> token >> _kd[i];
    }
69
    return true;
70

Laurent Belcour's avatar
Laurent Belcour committed
71
}
72 73

void diffuse_function::save_call(std::ostream& out, const arguments& args) const
Laurent Belcour's avatar
Laurent Belcour committed
74
{
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    bool is_alta   = !args.is_defined("export") || args["export"] == "alta";

    if(is_alta)
    {
        out << "#FUNC nonlinear_function_diffuse" << std::endl ;
        for(int i=0; i<dimY(); ++i)
        {
            out << "kd " << _kd[i] << std::endl;
        }
        out << std::endl;
    }
    else
    {
        out << "vec3(";
        for(int i=0; i<dimY(); ++i)
        {
            out << _kd[i]; if(i < dimY()-1) { out << ", "; }
        }
        out << ")";
    }

Laurent Belcour's avatar
Laurent Belcour committed
96
}
97
		
Laurent Belcour's avatar
Laurent Belcour committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
//! Number of parameters to this non-linear function
int diffuse_function::nbParameters() const 
{
#ifdef FIT_DIFFUSE
    return dimY();
#else
    return 0;
#endif
}

//! Get the vector of parameters for the function
vec diffuse_function::parameters() const 
{
#ifdef FIT_DIFFUSE
    vec res(dimY());
    for(int i=0; i<dimY(); ++i)
    {
        res[i*3 + 0] = _kd[i];
    }
#else
118
    vec res(1);
Laurent Belcour's avatar
Laurent Belcour committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
#endif
    return res;
}

//! Update the vector of parameters for the function
void diffuse_function::setParameters(const vec& p) 
{
#ifdef FIT_DIFFUSE
    for(int i=0; i<dimY(); ++i)
    {
        _kd[i] = p[i];
    }
#endif
}

//! Obtain the derivatives of the function with respect to the 
//! parameters. 
vec diffuse_function::parametersJacobian(const vec& x) const 
{
#ifdef FIT_DIFFUSE
	vec jac(dimY());
	for(int i=0; i<dimY(); ++i)
		for(int j=0; j<dimY(); ++j)
		{
			if(i == j)
			{
				// df / dk_d
				jac[i*dimY() + j] = 1.0;

			}
			else
			{
				jac[i*dimY() + j] = 0.0;
			}
		}
#else
155
	vec jac(1);
Laurent Belcour's avatar
Laurent Belcour committed
156 157 158 159 160 161 162 163 164
#endif

    return jac;
}


void diffuse_function::bootstrap(const data* d, const arguments& args)
{
	// Set the diffuse component
165 166 167 168 169 170 171 172 173 174 175 176
	if(params::is_cosine_weighted(d->output_parametrization()))
	{
		vec cart(6);

		for(int i=0; i<d->dimY(); ++i)
			_kd[i] = std::numeric_limits<double>::max();

		for(int i=1; i<d->size(); ++i)
		{
			vec x = d->get(i);
			params::convert(&x[0], d->input_parametrization(), params::CARTESIAN, &cart[0]);
			double cosine = (cart[2] > 0.0 ? cart[2] : 0.0) * (cart[5] > 0.0 ? cart[5] : 0.0);
Laurent Belcour's avatar
Laurent Belcour committed
177

178 179 180 181 182 183 184 185 186 187
			if(cosine > 0.0)
			{
				for(int j=0; j<d->dimY(); ++j)
				{
					_kd[j] = std::min(x[d->dimX() + j] / cosine, _kd[j]);
				}
			}
		}
	}
	else
Laurent Belcour's avatar
Laurent Belcour committed
188
	{
189 190 191 192 193 194 195 196 197 198
		vec x0 = d->get(0);
		for(int i=0; i<d->dimY(); ++i)
			_kd[i] = x0[d->dimX() + i];

		for(int i=1; i<d->size(); ++i)
		{
			vec xi = d->get(i);
			for(int j=0; j<d->dimY(); ++j)
				_kd[j] = std::min(xi[d->dimX() + j], _kd[j]);
		}
Laurent Belcour's avatar
Laurent Belcour committed
199 200 201 202 203
	}
	std::cout << "<<INFO>> found diffuse: " << _kd << std::endl;

}