/* ImLib3D
 * Copyright (c) 2001, ULP-IPB Strasbourg.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*! \file PiecewiseLinearFct.hpp */

#ifndef _PiecewiseLinearFct_hpp
#define _PiecewiseLinearFct_hpp

//! a function composed by a set of segments,  defined by an arbitrairy set of it's values
template<class ValueType>
class PiecewiseLinearFct
{
	map<float,ValueType> points;
public:
	ValueType Value(float x) const
	{
		float x0,x1;
		ValueType v0,v1;
		typename map<float,ValueType>::const_iterator lb=points.lower_bound(x);
		if(lb==points.end()  )
		{
			lb--;
			x1=(*lb).first;
			v1=(*lb).second;
			lb--;
			x0=(*lb).first;
			v0=(*lb).second;
		}
		else
		if(lb==points.begin())
		{
			x0=(*lb).first;
			v0=(*lb).second;
			lb++;
			x1=(*lb).first;
			v1=(*lb).second;
		}
		else
		{
			x1=(*lb).first;
			v1=(*lb).second;
			lb--;
			x0=(*lb).first;
			v0=(*lb).second;
		}
		return ((x-x0)/(x1-x0))*(v1-v0)+v0;
	}
	void Plot() const
	{
		vector<double> x,y;

		float x0=(*points.begin()).first;
		float x1=(*--points.end()).first;
		for(float xx=x0-.5*(x1-x0);xx<=x1+.5*(x1-x0);xx+=(x1-x0)/100.0)
		{
			x.push_back(xx);
			y.push_back((*this)(xx));
		}
		GnuPlot(x,y);
	}
	inline ValueType operator()(float x) const {return Value(x);}
	void AddValue(float x,const ValueType &y){points[x]=y;}
	PiecewiseLinearFct(){;}
	//! ctr only for real valued ValueType
	PiecewiseLinearFct(const ValueType *init,int n)
	{
		for(int i=0;i<n;i++)
		{
			AddValue((float)init[2*i],init[2*i+1]);
		}
	}
};

typedef  PiecewiseLinearFct<float> PiecewiseLinearFctf;

#endif // _PiecewiseLinearFct_hpp
